MCP gateway
Your MCP servers behind one RouterPlus key.
The MCP gateway puts your MCP servers behind one RouterPlus endpoint. Your agents call the servers with their RouterPlus inference key. The gateway adds the server's credentials, applies your tool policy and logs each tool call.
The gateway uses the MCP Streamable HTTP transport (JSON-RPC 2.0). It accepts JSON and text/event-stream responses from the server. In the console, open Build > MCP servers.
Register a server
Send POST /v1/mcp/servers with a management key (Authorization: Bearer tm_mk_...):
{
"slug": "github",
"url": "https://mcp.example.com/mcp",
"auth_header": "Authorization",
"auth_value": "Bearer ghp_...",
"allowed_tools": ["search_*", "get_issue"],
"blocked_tools": ["search_admin*"],
"workspace_ids": []
}| Field | Rule |
|---|---|
slug | Required. 1 to 40 of a-z, 0-9 and -, starting with a letter or digit. Unique in your org. servers and calls are reserved. |
url | Required. An https URL. http works only for localhost. No user name or password in the URL. |
auth_header | Optional. The header name that the server expects, for example Authorization or X-Api-Key. |
auth_value | Required with auth_header. Up to 3,000 bytes. RouterPlus stores it encrypted and never returns it. |
allowed_tools | Optional. Tool names or globs. Empty (the default) allows every tool. |
blocked_tools | Optional. Tool names or globs. A blocked tool stays blocked even when allowed_tools matches it. |
workspace_ids | Optional. The workspaces whose keys can use the server. Empty (the default) means every workspace. |
enabled | Optional. Default true. A disabled server returns 404. |
In a glob, * matches any run of characters. Every other character matches itself. Names are case-sensitive.
The response is 201, with the server. It shows auth_header and has_auth_value. It never shows the value.
Manage servers
| Route | What it does |
|---|---|
GET /v1/mcp/servers | Lists your servers. |
GET /v1/mcp/servers/{id} | Reads one server. |
PATCH /v1/mcp/servers/{id} | Changes the fields you send. To rotate the secret, send auth_value alone. To remove the auth header and its value, send "auth_header": null. |
DELETE /v1/mcp/servers/{id} | Deletes the server. Its call log stays. |
GET /v1/mcp/calls | Reads the tool call log. |
Every route also works under /api/v1. Each change writes a row to the audit log (GET /v1/audit).
Call a server
Point your MCP client at https://<gateway>/v1/mcp/{slug} and send your inference key:
Authorization: Bearer tm_vk_...| Method | Use |
|---|---|
POST | Sends a JSON-RPC message or batch. The response is JSON or an SSE stream, in the form that the server sends. |
GET | Opens the server's SSE stream. |
DELETE | Ends the session. |
- The gateway passes
mcp-session-id,mcp-protocol-versionandlast-event-idto the server. It returns the server'smcp-session-idto you. - It sends the server's
auth_headerwith the stored value. It never sends your RouterPlus key to the server.
Tool policy
tools/list: the gateway removes the tools that your policy does not allow, in JSON and in SSE.tools/callfor a tool that your policy does not allow: the gateway returns this error and does not call the server:
{ "jsonrpc": "2.0", "id": 3, "error": { "code": -32601, "message": "tool not allowed by RouterPlus policy" } }- The gateway checks a batch one message at a time. Allowed messages go to the server. Refused calls get the error above, in the same response.
- Other methods (
initialize,resources/*,prompts/*, notifications) pass through.
Tool call log
The gateway records each tools/call: the tool name, the key, the server, the status and the duration. It does not store arguments or results.
| Status | Meaning |
|---|---|
ok | The server returned a result. |
error | The server returned a JSON-RPC error or a result with isError: true. |
blocked | Your policy refused the call. The gateway did not call the server. |
upstream_error | The server was unreachable or returned an HTTP error. |
timeout | The server did not answer in time. |
no_answer | The server ended its response without an answer to the call. |
GET /v1/mcp/calls takes these query parameters: server_id, key_id, tool, status, from and to (ISO 8601 times), and limit (1 to 500, default 100). The newest calls come first.
Limits and errors
| Limit | Value |
|---|---|
| Request body | 4 MiB. A larger body gets 413. |
| Server timeout | 120 s until the server starts its response, and 120 s between parts of a stream. When the server does not start in time, the response is 504. |
| JSON response from the server | 16 MiB. |
| Status | Cause |
|---|---|
401 | The inference key is missing or not valid. |
404 | No enabled server has this slug in your org, or the server is not open to your key's workspace. |
400 with JSON-RPC code -32700 | The body is not valid JSON. |
400 upstream_refused | The server URL resolves to a private, loopback or link-local address. The gateway does not call it. |
502 upstream_auth_failed | The server refused the stored credentials (HTTP 401 or 403). |
502 upstream_error | The server was unreachable, or sent a redirect or invalid JSON. |
Other HTTP errors from the server (for example 404 for an expired session) reach you unchanged.
For agents: /docs/mcp-gateway.md and /llms.txt