C.W.K.
Stream
Lesson 03 of 05 · published

Session IDs and Statefulness

~20 min · session, mcp-session-id, stateful, stateless

Level 0Curious Reader
0 XP0/48 lessons0/14 achievements
0/100 XP to next level100 XP to go0% complete

Streamable HTTP supports both stateful and stateless servers. The protocol does not pick for you; you choose at design time and signal it with the Mcp-Session-Id header.

A stateful server issues a session id during initialize (Mcp-Session-Id in the response). Subsequent requests carry the same id back in the request header. The server uses the id to look up per-session state — open subscriptions, paginated cursor positions, in-flight long-running tasks. Tear-down is explicit: the client sends an HTTP DELETE to the endpoint with the session id when it is done, and the server reaps the state.

A stateless server does not issue a session id. Every request is independent; per-call work is done in-process and discarded. Stateless servers scale horizontally with no coordination — any node behind a load balancer can serve any request — but they cannot offer subscriptions, cursored pagination across calls, or any feature that needs to remember "what did I last say to this client?"

The choice is operational. Stateful servers are easier to write but harder to scale (you need sticky routing or shared session storage). Stateless servers are easier to scale but force you to push state into the request payload (e.g. cursors as opaque tokens). Most production deployments end up stateless behind a CDN-like edge with state shared via Redis or similar — that gives the simplicity of stateless plumbing and the capability of stateful semantics.

Code

Stateful — session id in headers·text
POST /mcp  →  HTTP/1.1 200 OK
                 Mcp-Session-Id: sess_abc123

POST /mcp  Mcp-Session-Id: sess_abc123  →  ...
DELETE /mcp Mcp-Session-Id: sess_abc123  →  HTTP/1.1 204 No Content
Stateless — every call is fresh·text
POST /mcp  →  HTTP/1.1 200 OK
                 (no Mcp-Session-Id header issued)

# Each request carries enough state to be served independently.
# Cursors / opaque tokens go in params, never in server memory.

External links

Exercise

Take a server you have written and ask: which tools, if any, actually need session-scoped state? If the answer is 'none', delete the session-id machinery and ship stateless. Most servers I have written needed less state than I first thought.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.