DocsMCP gateway
Start here
Build and run
DocsReference
MCP gateway reference
One endpoint, four protocol revisions, five methods. Everything a workspace has installed is reachable through it, and nothing is reachable without a credential.
Endpoint
The gateway is a Streamable HTTP MCP server. Every request is a JSON-RPC 2.0 document sent by POST, and every request carries its own bearer token, so the server holds no session between them.
POST /mcpGET returns 405. The 2026-07-28 revision removed the GET stream from the transport, and a scanner that receives a 200 from an unauthenticated GET reads the whole endpoint as open, which is the one thing a tool gateway must never look like. The facts a GET used to return live in server/discover instead.
OPTIONS answers the browser preflight. The allowed origin is a wildcard, which is correct rather than loose here: the caller is another origin by definition and its credential is a bearer token it already holds, never a cookie, so there is no ambient authority for a hostile page to borrow. www-authenticate is on the exposed header list, because a browser client with no token cannot otherwise read the challenge that tells it where to sign in.
Protocol revisions
Four revisions are answered on the same endpoint, newest first. Each one is listed because the gateway genuinely serves it: initialize, tools/list and tools/call are unchanged across all of them, and the server holds no session for any of them to differ about.
| Revision | Notes |
|---|---|
2026-07-28 | Latest. No initialize handshake and no session header: version, identity and capabilities travel in per-request _meta. Requires server/discover, and mirrors the method and tool name into request headers. |
2025-11-25 | What Claude's connector opens with. |
2025-06-18 | The version echoed back to a client that asks for something outside this list on initialize. |
2025-03-26 | Oldest revision served. |
A request naming a revision that is not on this list is refused with 400 and JSON-RPC code -32022, and the error data carries the supported list so the client can retry in a language the server speaks. Under 2026-07-28, a request whose mcp-method or mcp-name header disagrees with its body is refused with -32020. A missing header is never refused, only a contradictory one.
Methods
| Method | Authenticated | Answer |
|---|---|---|
server/discover | No | Supported versions, capabilities, and one line saying how to begin. Answered before the token is looked at, because behind a 401 a client cannot tell a server it must sign into from one it cannot speak to at all. It returns the same thing for every caller. |
initialize | Yes | Echoes the agreed revision, the server capabilities, and instructions naming the projects this credential reaches. |
notifications/initialized | Yes | 202 with no body. |
tools/list | Yes | The bridge tools. read_guide appears only when a toolkit this caller can reach actually has a guide. |
tools/call | Yes | Runs a bridge tool, or a real slug__action name directly. |
Authentication
There are two credentials the gateway accepts, and it tries them in that order.
An agent key is one indexed lookup against a SHA-256 hash, and it covers every config-file client. The lookup joins team membership, which is the authorization check and not decoration: a key outlives the person who created it, so someone removed from the workspace stops reaching its projects even while their token is still syntactically valid.
An OAuth access token is a JWT the application signs from its own key set and verifies against its own JWKS. It costs a signature check rather than a lookup, and it is the path a client that signed in takes. The audience is the deployment origin and the issuer is the auth provider mounted beneath it, so a token minted for one deployment is only ever accepted by that deployment.
The 401 challenge
A request with no credential, or with one that resolves to nothing, is answered with 401 and an RFC 9728 challenge naming the document that describes this resource's authorization server. It is how a client gets from a bare URL to a sign-in page without being configured.
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://toolspoke.com/.well-known/oauth-protected-resource"
{ "jsonrpc": "2.0", "id": null, "error": { "code": -32001, "message": "Missing bearer token" } }The status matters as much as the header. A WWW-Authenticate header means nothing on a 200: a client that probes the endpoint reads 200 as “this server needs no credential” and offers no sign-in at all.
What comes back from a call
tools/call returns MCP content blocks. A refusal is a result with isError set and a sentence saying why, rather than a transport error, because the agent is the party that can act on it. A tool name the agent invented comes back with the nearest real names attached, which is the one failure it can fix by itself.
Every call that reaches a provider is recorded under the underlying tool's real name rather than under the runner it came through, so the activity feed and the bill both read the way you would expect. See Bridge tools for what the advertised tools do, and Billing and credits for what each kind of call costs.