Calling MCP Tools over HTTP
AdvancedCalling MCP Tools over HTTP
Metapad's MCP server is just an HTTP endpoint that speaks JSON-RPC 2.0. Interactive clients like Claude Desktop and Claude Code wrap this transport for you, but you can also call it directly from any script, curl command, or CI pipeline — useful when no interactive OAuth login is possible.
The endpoint
POST /mcp/{model_id}
Authorization: Bearer mpt_your_token_here
Content-Type: application/json
A single URL handles every MCP tool. Which tool runs is determined by the JSON-RPC body, not the path.
The request envelope
Every request follows JSON-RPC 2.0:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "<tool_name>",
"arguments": { /* tool-specific */ }
}
}
methodis almost alwaystools/callfor actual work.params.namepicks one of the MCP tools — the same names you see in this reference (get_metamodel,search_nodes,create_nodes, etc.).params.argumentsis the tool's input schema — see the APITool node for each tool's parameters.
Other JSON-RPC methods
| Method | Purpose |
|---|---|
initialize | Handshake — returns protocol version + server info. |
ping | Health check. |
tools/list | Returns the full list of available tools with their JSON schemas. |
tools/call | Run a tool. |
notifications/initialized | One-way notification — no response expected. |
Worked example: search for nodes
curl -X POST https://app.metapad.ai/mcp/your-model-id \
-H "Authorization: Bearer mpt_your_token_here" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "search_nodes",
"arguments": { "node_type": "Feature", "limit": 10 }
}
}'
Response:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [
{
"type": "text",
"text": "{\"total_count\": 3, \"returned_count\": 3, \"nodes\": [...]}"
}
]
}
}
The tool's structured output is JSON-encoded inside result.content[0].text — parse it on the client side.
Worked example: create a node
curl -X POST https://app.metapad.ai/mcp/your-model-id \
-H "Authorization: Bearer mpt_your_token_here" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "create_nodes",
"arguments": {
"nodes": [{"node_type": "Feature", "label": "OAuth integration"}]
}
}
}'
Mutations broadcast through the collaboration system — browser users see the new node appear in real time.
Error handling
Errors come back in the JSON-RPC error envelope:
{"jsonrpc": "2.0", "id": 1, "error": {"code": -32602, "message": "..."}}
| Code | Meaning |
|---|---|
-32700 | Parse error — request body wasn't valid JSON. |
-32600 | Invalid request — wrong JSON-RPC version, missing method. |
-32601 | Method not found — unknown JSON-RPC method. |
-32602 | Invalid params — tool arguments don't match the schema. |
-32603 | Internal error. |
HTTP-level failures (401, 403, 429) are returned as plain HTTP errors before the JSON-RPC layer. A 401 will include a WWW-Authenticate header pointing to the OAuth discovery URL.
REST API v1 vs MCP HTTP API
Both use the same mpt_... tokens. Use whichever fits your script:
| REST API v1 | MCP HTTP API | |
|---|---|---|
| URL shape | /api/v1/models/{id}/nodes, /folders, /assets | /mcp/{id} (single endpoint) |
| Read shape | Conventional REST resources | JSON-RPC tool calls |
| Writes | Asset upload/delete only | Full read + write (create/update/delete nodes, relationships, types) |
| Best for | Browsing a model from a dashboard, polling for changes | Automation scripts, CI pipelines, anything needing mutations |
Security
- Treat
mpt_...tokens like passwords — never commit them to repos or share in chats. - Tokens are scoped to a single model.
- Revoke and rotate tokens from the API Tokens Tab when no longer needed.