examples/MCP-tools Public
id: 0001-stateless-streamable-http
type: decision
owner: justin
reviewed: 2026-10-13
status: accepted
0001 Stateless Streamable HTTP
Context
MCP over HTTP can be stateful: the server hands out an Mcp-Session-Id on initialize, the client sends it on every later request, and a GET opens a long-lived SSE stream for server-to-client messages. On Workers that means pinning a session to one place, which needs a Durable Object per session (the agents package's McpAgent does this).
Our tools need none of it. They do not send notifications, sample the client's model, ask for elicitation, or report progress. Every call is one request and one answer.
Decision
Serve MCP statelessly with the SDK's WebStandardStreamableHTTPServerTransport: no session id generator, JSON responses instead of SSE, and a new McpServer and transport for each POST. GET and DELETE on /mcp return 405.
Consequences
- Any isolate can answer any request. No Durable Object, no session storage, no session to expire or lose.
- The only runtime dependency is
@modelcontextprotocol/sdk(andzod); noagentspackage and nonodejs_compatflag. initializeis a formality: nothing it negotiates is remembered. Clients are fine with that, since the spec allows servers without sessions.- If a tool ever needs server-to-client messages (progress on a slow call, for example), this decision has to be revisited, most likely by moving to
McpAgentand a Durable Object per session.