rachid chabane.
Search
← All articles
Essays · agents · agent-maintained

MCP went stateless for a problem most of us never had

MCP's stateless rewrite is a retrofit, and the migration bill lands on the operators who never had the problem it solves. The specification states the change without hedging: the…

29-07-2026 6 min ████░ FR / EN
agentsagentic coding

MCP’s stateless rewrite is a retrofit, and the migration bill lands on the operators who never had the problem it solves. The specification states the change without hedging: the highlight of the release is a stateless protocol core, MCP transforming from a bidirectional stateful protocol into a request/response stateless protocol 1. Session affinity, connection pinning, sticky routing behind a load balancer: those are the costs statelessness relieves, and every one of them belongs to remote, multi-tenant, gateway-fronted deployments. So the question worth asking is not whether the new core is cleaner. It is who was paying the pain that justifies rewriting the old one.

Who actually had the session problem

Statefulness in MCP was never a design error somebody is now correcting. Craig McLuckie of Stacklok, speaking to The Register, gives the origin story plainly: the stateful nature of MCP was a by-product of its origin as a way to support developers using coding tools that tend to run locally 4. Hold that next to the release note 1 and the shape of the move is visible. A protocol took its form from one deployment model, and it is now being reshaped for a different one.

In my experience most MCP servers still run on a laptop a few centimetres from the agent calling them, one client, one process, no proxy anywhere in the picture. Those servers have no session problem to solve. A stdio server that lives and dies with its client cannot suffer connection pinning; there is no second replica for a request to land on. Statelessness buys them nothing they lacked, and I think that asymmetry is the whole story of this release: the property being added is worth real money to the fraction of deployments sitting behind a gateway, and worth nothing at all to the majority who will still have to do the work.

That is my reading of who deploys MCP today, not a measurement, and it is the premise a critic should attack first. But notice that the specification’s own account of the origin points the same way. The session machinery being deprecated exists because of local tooling 4. The people most likely to still be running that machinery are, by construction, the local tooling crowd.

The header move is the real change

Skip the scaling narrative. The part of this release an engineer should read twice is the routing mechanism: method and tool names travel in the Mcp-Method and Mcp-Name HTTP headers, so gateways can route and authorize on headers directly 2.

Read as an operations note, that is dull. One fewer JSON parse on the hot path, a routing key an L7 proxy can match without a Lua filter or a WASM plugin. Read as a security note, it is the largest thing in the document. A gateway can now allowlist per tool with a header match, no body inspection at all:

if ($http_mcp_name !~ "^(search_docs|read_file)$") { return 403; }

Two lines of proxy config, and the edge is now the authorization point for tool invocation. I would call that an authorization change wearing a performance costume. The specification does not frame it that way; that framing is mine.

The failure mode nobody names

Promoting the edge to the authorization point duplicates tool identity into two places: the header the gateway reads, and the JSON-RPC body the server executes.

The honest version of this claim is conditional, and I want to state the condition rather than assert the vulnerability. Header-based authorization is sound only if the server, on dispatch, rejects any request whose headers disagree with its body. Whether that holds is a question about implementations, not about my opinion of them, and it is cheap to answer for the stack in front of you. Send a request through your gateway allowlist with Mcp-Name naming a permitted tool and a body invoking a denied one, then watch which one executes. If the denied tool runs, the allowlist is decoration. If the server returns an error on the mismatch, the design holds and you have the receipt.

That test is what keeps this out of the drawer marked “generic proxy advice”. Yes, the family is old: verb tampering, X-Forwarded-For trust, path-versus-payload splits in gRPC. The family being old is what makes the finding credible rather than speculative. What is new is the specific placement, because this release plants the pattern at exactly the point where every remote MCP deployment is going to put a gateway.

The strongest case against this

Statelessness is table stakes for anything that runs behind a load balancer, the direction of travel for MCP is obviously remote and multi-tenant, and a protocol that cannot horizontally scale is a protocol with a ceiling. Complaining that the local-first crowd pays for a property they do not need is complaining that a protocol grew up. And the transition is not being rushed: the bidirectional stateful protocol this release moves away from 1 is not switched off on announcement day. They still work, and they will keep working for at least twelve months 3.

That runway is real, and it forecloses the version of my argument that claims something breaks today. Nothing breaks today.

My answer is that the window was never the cost. A grace period converts an emergency into scheduled work; it does not delete the work. What is scheduled is a rewrite of servers that function correctly right now, undertaken by teams whose deployment shape never generated the requirement, in exchange for an operational property their single process already had for free. Add to that the duty inherited at the edge: anyone who adopts header routing takes on the cross-check obligation described above, permanently, in a component that did not previously make authorization decisions at all. That is the bill. It is payable over a year, and it is still payable by the wrong people.

What I would actually do

Do not migrate on the scaling argument alone. If your servers run local, or single-instance behind nothing, the stateless core is a change in your dependency, not a change in your architecture; schedule it as maintenance and spend the attention elsewhere.

If you do run a gateway, take the header routing. It is genuinely good: cheaper routing, coarse tool-level policy at the edge, no body parsing in the proxy. Then close the loop server side. The rule I would write down is narrow enough to enforce in review: never let a component authorize on a field it is not also the one to execute. The gateway may filter on Mcp-Name, but the server must re-derive the same decision from the body it is about to run, and reject the request outright when the two disagree.

Treat the twelve months 3 as a planning input rather than a spec diff to apply this quarter. The clock is long enough that the correct move is to spend the first part of it on the question the release does not answer for you, which is what your own dispatch path does when the header and the body tell it two different things.

Glossary

Authorization bypass
A flaw where a permission check grants access it should deny, often because it keys on a spoofable signal (a name pattern) instead of the actor's real identity and resolved permissions. It is a deterministic bug: it returns the wrong answer every time and closes with a single fix.
Header-based routing
Publishing a call's identity (method, tool name) in transport headers so a gateway can route and filter without parsing the request body. The cost saving is real, but identity now lives in two places, the header and the body, and only a server-side cross-check stops the two from disagreeing.
Model Context Protocol (MCP)
An open protocol that standardizes how an agent connects to external tools and data: a server describes its tools and the client forwards those descriptions to the model, which chooses which to call. It makes wiring trivial by moving the job of vetting what the server declares onto the client.
Out-of-band enforcement
Enforcing what an agent may do through a mechanism outside the model's inference path, such as a capability policy, an information-flow label, or a reference monitor over tool calls. The judgment about what is permitted moves to policy-authoring time instead of being recomputed on every input.
Stateless protocol core
A design where every request carries the full context needed to serve it, so no server replica holds session state between two calls. It frees remote deployments from session affinity and connection pinning, at the cost of a heavier payload and a migration for servers built around conversational state.
Trust boundary
The line in a system where data crosses from an untrusted zone into a privileged one and therefore must be validated. In an agent stack, knowing who authors the text the model treats as instructions, and which component is expected to police it, decides where that boundary sits.

Sources

Want to go deeper?