ADR 0049 — Stateless MCP HTTP is the default
- Status: Accepted — changes the HTTP transport default; builds on immutable surface preparation from ADR 0047
- Date: 2026-08-07
Context
The HTTP handler defaulted to an in-memory MCP session store. That couples a
client to one process: replacement, restart or unpinned scale-out can turn a
valid Mcp-Session-Id into 404 Session not found. Most stitchkit MCP tools are
synchronous request/response operations and receive no benefit from retained
transport state.
A boolean stateless also makes the exceptional mode hard to read: omission
means stateful and false means the same thing.
Decision
Replace the boolean with:
sessionMode: 'stateless' | 'stateful' // default: 'stateless'
Stateless mode creates a fresh SDK server, transport, resolved auth/context and
runner for each HTTP request over one immutable prepared schema surface. It has
no session map, event store, sweep timer or Mcp-Session-Id lifecycle.
Stateful mode is explicit. It retains the existing server-issued session id, bounded session/event stores, resumable SSE stream and idle cleanup for clients that need cross-request progress or server-initiated messages.
No current stitchkit configuration field independently requests a stateful-only
capability, so there is no contradictory combination to reject. Adding such a
field later must fail at handler construction unless sessionMode: 'stateful'
is also explicit.
Consequences
- Normal synchronous servers survive process replacement and distribute across instances without shared session infrastructure.
- Stateful consumers must opt in during the 0.37.0 migration.
statelessis removed without an alias or overload.- Deterministic schema work remains once per static handler, while all mutable request/server state stays fresh.