The MCP server over Streamable HTTP (revisions 2025-03-26 to 2025-06-18), as a Plug.
SuperPi.Gateway.Router forwards /mcp here, so the gateway's bearer-token authentication,
telemetry span, error handling, TLS and listener apply to MCP too. This module adds the MCP
transport rules on top of the pure engine SuperPi.MCP.Server.handle_mcp_line/2.
| Request | Answer |
|---|---|
POST with a request | 200 with the JSON-RPC reply as application/json, or as a one-event text/event-stream when the client accepts text/event-stream and not application/json |
POST with only notifications or responses | 202, no body |
POST with initialize | as above, plus an Mcp-Session-Id header |
GET | 405: the server does not push messages, so it opens no stream |
DELETE | 200, and the session ends |
Sessions
initialize starts a session (SuperPi.MCP.Sessions). Every other request must carry its id in
Mcp-Session-Id: a missing header is 400, an unknown or expired session is 404, and a client
then starts a new one. A session belongs to the principal that opened it. Requests of one session
that run at the same time each see the state the session had when they began, and the last
to finish stores its state.
initialize?harness=<id> selects the harness of the session's direct tool calls (see
SuperPi.MCP.Server). An unknown id is 400.
Checks
An MCP-Protocol-Version header that names a version the server does not speak is 400. A
draining node answers 503 with Retry-After, so the client reaches another node. When no
token is configured (SuperPi.Auth.required?/0 is false), a request with an Origin header must
come from a loopback host or one in config :super_pi, :mcp_allowed_origins ("*" allows all),
which stops a web page from calling a local server (DNS rebinding).
A JSON-RPC batch (an array) is accepted, as 2025-03-26 allows. It must not contain initialize.