RouterMCP
API Reference

MCP Protocol API

JSON-RPC 2.0 endpoints for interacting with aggregated MCP tools.

MCP Protocol API

The MCP Protocol API provides JSON-RPC 2.0 endpoints for MCP clients to interact with aggregated tools.

Endpoints

POST /v1/mcp/:projectSlug/request

JSON-RPC 2.0 endpoint for MCP protocol requests.

Path Parameters:

  • projectSlug (string) - Project identifier

Headers:

  • Content-Type: application/json
  • Authorization: Bearer <api-key> (if project requires auth)

GET/POST /v1/mcp/:projectSlug/sse

SSE (Server-Sent Events) bridge for streaming tool calls.

Headers:

  • Accept: text/event-stream
  • Authorization: Bearer <api-key> (if project requires auth)

MCP Methods

initialize

Establishes a session and negotiates protocol version/capabilities.

Request:

{
  "jsonrpc": "2.0",
  "id": "0",
  "method": "initialize",
  "params": {
    "protocolVersion": "2025-03-26",
    "capabilities": {},
    "clientInfo": { "name": "client", "version": "1.0.0" }
  }
}

Response:

{
  "jsonrpc": "2.0",
  "id": "0",
  "result": {
    "protocolVersion": "2025-03-26",
    "capabilities": {},
    "serverInfo": { "name": "RouterMCP", "version": "1.0.0" }
  }
}

tools/list

List all enabled tools from all configured servers.

Request:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/list"
}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "tools": [
      {
        "name": "github__create_issue",
        "description": "Create a new issue",
        "inputSchema": {
          "type": "object",
          "properties": {
            "title": { "type": "string" },
            "body": { "type": "string" }
          },
          "required": ["title"]
        }
      }
    ]
  }
}

Tools are namespaced as {serverAlias}__{toolName} to prevent conflicts.

tools/call

Execute a tool on the appropriate upstream server.

Request:

{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "github__create_issue",
    "arguments": {
      "title": "Bug report",
      "body": "Issue description"
    }
  }
}

Response:

{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "Issue created: #123"
      }
    ]
  }
}

routermcp_searchMcpForTask

This tool has two mutually exclusive modes. Use task for a non-empty natural-language task (maximum 2,048 Unicode characters and 8,192 UTF-8 bytes), or query for literal terms and supported qualifiers such as server:github. Do not pass both. Query syntax is described in the search guide.

Legacy task mode accepts an optional exact server alias, a limit from 1 to 20 (default 5), an offset from 0 to 10,000 (default 0), and includeSchema (default false). The response keeps total, nextOffset, topTool, and candidates; total and topTool cover all positive ranked matches, not only the current page. Pages shorten near offset 10,000 so nextOffset stays within the accepted range. At offset 10,000, nextOffset is null; truncated is true if more matches remain after that page.

Explicit query mode accepts limit from 1 to 50 (default 20), an optional opaque cursor, and includeSchema (default false). It cannot be combined with server or offset; put server constraints in the query and use the returned nextCursor to continue. Its JSON text envelope contains results, the page count, nextCursor, warnings, and coverage. Results use the callable name alias__tool; schemas are returned only for this page when requested and rechecked against the current project policy. Invalid arguments return JSON-RPC error -32602.

Request:

{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "routermcp_searchMcpForTask",
    "arguments": {
      "task": "create GitHub issue",
      "server": "github",
      "limit": 5,
      "offset": 0,
      "includeSchema": false
    }
  }
}

Legacy task response:

{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{\n  \"total\": 2,\n  \"nextOffset\": null,\n  \"truncated\": false,\n  \"topTool\": \"github__create_issue\",\n  \"candidates\": [\n    { \"name\": \"github__create_issue\", \"score\": 3.5 },\n    { \"name\": \"github__update_issue\", \"score\": 2 }\n  ]\n}"
      }
    ]
  }
}

The text value contains JSON with total, nextOffset, truncated, topTool, and the requested page of candidates. Each candidate has an executable namespaced name and score; inputSchema is included only when includeSchema is true. truncated is true only on the final page at offset 10,000 when additional ranked matches cannot be reached within the offset limit.

Explicit query request:

{
  "jsonrpc": "2.0",
  "id": 4,
  "method": "tools/call",
  "params": {
    "name": "routermcp_searchMcpForTask",
    "arguments": {
      "query": "server:github create issue",
      "limit": 20,
      "includeSchema": true
    }
  }
}

The query response text contains the shared search envelope. Each result's name remains an executable alias__tool callable name; pass that exact name to routermcp_executeTool. If nextCursor is non-null, send another request with the same query and that cursor.

Invalid queries and search execution failures return the JSON-RPC error.message together with error.data.code. Parser diagnostics may include a span with Unicode code-point offsets; all search diagnostics include a boolean restart field. When code is CURSOR_STALE, restart is true; repeat the search without the cursor to get a fresh page.

routermcp_listTools query mode

When Code Mode is enabled, routermcp_listTools still returns the existing full TypeScript declaration string when called with no query (or with the legacy filter). Its additive query mode accepts limit from 1 to 50 and an optional cursor; query cannot be combined with filter. The JSON text response contains the current page's TypeScript declarations, count, nextCursor, warnings, and coverage. Continue with the same query and returned cursor to load further declarations. Each page's schemas are rechecked against current Code Mode policy. Use the exact namespace identifier shown in declarations when writing code. Safe aliases keep their names; reserved or invalid aliases use stable encoded identifiers. Adding another alias does not change an existing alias's identifier. Query-page identifiers are allocated against the full authorized alias catalog.

SSE Streaming

The SSE endpoint returns events in this format:

Content-Type: text/event-stream

data: {"type":"progress","message":"Starting..."}

data: {"type":"result","result":{"success":true}}

data: [DONE]

Code Examples

JavaScript

async function callTool(projectSlug, apiKey, toolName, args) {
  const response = await fetch(
    `https://gateway.routermcp.com/v1/mcp/${projectSlug}/request`,
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${apiKey}`
      },
      body: JSON.stringify({
        jsonrpc: '2.0',
        id: Date.now(),
        method: 'tools/call',
        params: { name: toolName, arguments: args }
      })
    }
  );
  
  const data = await response.json();
  if (data.error) throw new Error(data.error.message);
  return data.result;
}

Python

import requests

def call_tool(project_slug, api_key, tool_name, args):
    response = requests.post(
        f'https://gateway.routermcp.com/v1/mcp/{project_slug}/request',
        headers={
            'Content-Type': 'application/json',
            'Authorization': f'Bearer {api_key}'
        },
        json={
            'jsonrpc': '2.0',
            'id': 1,
            'method': 'tools/call',
            'params': {'name': tool_name, 'arguments': args}
        }
    )
    data = response.json()
    if 'error' in data:
        raise Exception(data['error']['message'])
    return data['result']

cURL

curl -X POST 'https://gateway.routermcp.com/v1/mcp/my-project/request' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer rmc_your_api_key' \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/list"
  }'

On this page