Tools
List, inspect, and run Melious-hosted tools — web search, URL scraping, document conversion — over REST
Tools are server-side capabilities you call over REST — web search, URL scraping, document conversion, and a handful of MCP-backed documentation lookups. You run them directly, or hand their definitions to a chat model and let it decide when to call them.
Base path: /v1/tools
Auth: Bearer token or x-api-key. Requires scope kit.tools. (Document conversion is its own endpoint with its own scope — see Document conversion.)
Two ways to use a tool
Call it yourself. Hit POST /v1/tools/{slug}/execute with the parameters and read the result. This is the path when your own code decides what to run.
Let a model call it. Fetch the tool definitions in OpenAI function format from GET /v1/tools/openai, pass them to Chat completions, and run whichever ones the model asks for. The model picks; you execute.
The second path is the usual one for agents. It's the standard function-calling loop from Tool calling, with the function bodies living on our side instead of yours.
Endpoints
| Method | Path | What it does |
|---|---|---|
GET | /v1/tools | List available tools |
GET | /v1/tools/openai | The same tools as OpenAI function definitions |
GET | /v1/tools/{slug} | One tool's metadata |
GET | /v1/tools/{slug}/schema | One tool's parameter JSON Schema |
POST | /v1/tools/{slug}/execute | Run a tool |
GET | /v1/tools/{slug}/rate-limit | Current rate-limit state for a tool |
List tools
GET /v1/toolsReturns the tools your key can run, paginated.
| Query param | Type | Default | Description |
|---|---|---|---|
page | integer | 1 | Page number. |
page_size | integer | 50 | Items per page, max 100. |
source | string | all | Filter by native, managed, or remote. |
tool_type | string | all | Filter by handler, mcp, or api. |
category | string | all | Filter by category (e.g. search). |
search | string | none | Free-text match against name and description. |
{
"items": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Web Search",
"slug": "web-search",
"source": "native",
"tool_type": "handler",
"description": "Search the web for current information",
"category": "search",
"parameters_schema": {
"type": "object",
"properties": {
"query": { "type": "string", "description": "Search query" },
"max_results": { "type": "integer", "default": 10 }
},
"required": ["query"]
},
"supports_streaming": false,
"cost_per_call": "0.01"
}
],
"total": 25,
"page": 1,
"page_size": 50,
"total_pages": 1
}source tells you where a tool comes from: native is built into Melious, managed is an integration we operate, remote is one you configured. tool_type tells you how it runs: handler is native code, mcp is a Model Context Protocol backend, api is an external HTTP call.
Get a tool's details and schema
GET /v1/tools/{slug}
GET /v1/tools/{slug}/schemaThe first returns the full metadata object (same shape as a list entry). The second returns just the parameters_schema — the JSON Schema your execute call has to satisfy. Fetch the schema before executing if you're building the request dynamically.
curl https://api.melious.ai/v1/tools/web-search/schema \
-H "Authorization: Bearer sk-mel-<YOUR_API_KEY>"Execute a tool
POST /v1/tools/{slug}/executeRun the tool. Pass arguments under parameters (a bare top-level object works too):
import httpx
response = httpx.post(
"https://api.melious.ai/v1/tools/web-search/execute",
headers={"Authorization": "Bearer sk-mel-<YOUR_API_KEY>"},
json={"parameters": {"query": "Hanseatic League history", "max_results": 5}},
).json()
print(response["result"])const response = await fetch(
"https://api.melious.ai/v1/tools/web-search/execute",
{
method: "POST",
headers: {
"Authorization": "Bearer sk-mel-<YOUR_API_KEY>",
"Content-Type": "application/json",
},
body: JSON.stringify({
parameters: { query: "Hanseatic League history", max_results: 5 },
}),
},
).then((r) => r.json());
console.log(response.result);curl https://api.melious.ai/v1/tools/web-search/execute \
-H "Authorization: Bearer sk-mel-<YOUR_API_KEY>" \
-H "Content-Type: application/json" \
-d '{"parameters": {"query": "Hanseatic League history", "max_results": 5}}'The response wraps the result with execution metadata:
{
"success": true,
"status": "completed",
"result": {
"results": [
{ "title": "The Hanseatic League", "url": "https://...", "snippet": "..." }
]
},
"error": null,
"execution_time_ms": 1250
}| Field | Type | Description |
|---|---|---|
success | boolean | Whether the run succeeded. Check this before reading result. |
status | string | completed, failed, or timeout. |
result | object | Tool-specific output. Shape varies per tool — see its schema. |
error | string | Human-readable message when success is false, otherwise null. |
execution_time_ms | integer | Wall-clock time the tool took. |
Use tools with chat completions
To let a model call these tools, fetch their OpenAI function definitions and pass them straight into Chat completions:
GET /v1/tools/openai{
"object": "list",
"data": [
{
"slug": "web-search",
"type": "function",
"function": {
"name": "web_search",
"description": "Search the web for current information",
"parameters": {
"type": "object",
"properties": { "query": { "type": "string" } },
"required": ["query"]
}
}
}
]
}Each entry carries both the function definition (what the model reads) and the slug (what you execute). The loop:
- Pass the
functionobjects in thetoolsarray of a chat request. - When the model returns a
tool_callsentry, map itsfunction.nameback to the matchingslug. - Run
POST /v1/tools/{slug}/executewith the model's arguments. - Feed the result back as a
toolmessage and continue.
The full loop, with code, is in Tool calling. The only Melious-specific step is mapping the function name to a slug and calling execute — everything else is the standard OpenAI flow.
Available tools
What we run today. The live list — with current per-call costs and parameter schemas — is GET /v1/tools.
| Tool | Slug | Category | What it does |
|---|---|---|---|
| Web search | web-search | search | Search the web for current information. |
| URL scraper | scrape-url | data | Fetch a URL and return its content as Markdown. |
| Context7 | context7-mcp | docs | Look up library documentation via Context7. |
| Microsoft Learn | microsoft-learn-mcp | docs | Search Microsoft Learn documentation. |
| Svelte | svelte-mcp | docs | Access Svelte framework documentation. |
Document conversion (POST /v1/documents/convert) is documented separately — it takes file uploads rather than JSON arguments, so it doesn't share the execute shape.
The three documentation tools are MCP backends surfaced through the same REST interface. If you'd rather talk MCP directly — connecting an agent that speaks the protocol — see MCP.
Rate limits
GET /v1/tools/{slug}/rate-limitTools are rate-limited per tool, separately from the inference rate limit. Check the current state before a heavy run:
{
"tool_slug": "web-search",
"limit_per_minute": 60,
"remaining_per_minute": 45,
"limit_per_day": 1000,
"remaining_per_day": 850,
"reset_at": "2026-05-22T15:00:00Z"
}Exceeding a limit returns KIT_6053 (execution rate-limited). Back off and retry.
Errors
A failed run returns success: false with the message in error — it's a 200 with a failure body, not an HTTP error, so check the field:
{
"success": false,
"status": "failed",
"result": null,
"error": "max_results must be between 1 and 50",
"execution_time_ms": 5
}Endpoint-level failures use the standard {"error": {"code", "message"}} shape:
KIT_6001— tool slug doesn't exist.KIT_6054— a parameter failed schema validation.KIT_6051— the tool ran but failed internally.KIT_6053— per-tool rate limit hit.BILLING_2001— insufficient balance for a paid tool.AUTH_1015— key is missing thekit.toolsscope.
Related
Tool calling for the model-driven loop • Document conversion for file-to-Markdown • MCP for connecting protocol-native agents.