The Model Context Protocol just deleted its own session layer. Not deprecated it, not made it optional. The Mcp-Session-Id header is gone from the Streamable HTTP transport, and if your server relied on it to remember anything between calls, that server is now broken against the current spec.
This is the 2026-07-28 revision, the largest rewrite since MCP launched in 2024. I have spent the last week reading the changelog against a server I actually run, and the honest summary is that the migration is small if your tools were already pure functions, and quite a lot of work if they were not.
Table of contents
- What actually changed
- Why sessions had to go
- The replacement is a server-minted handle
- Multi Round-Trip Requests
- Cacheable tool lists
- Which SDKs are ready
- A migration order that works
- Who this hurts
- FAQ
- Sources
What actually changed
Five things landed together, and only the first one breaks code.
| Change | Effect on your server |
|---|---|
| Sessions removed | Breaking. Mcp-Session-Id no longer exists in Streamable HTTP |
| Multi Round-Trip Requests | New. Interactive tools work without a long-lived connection |
| Cacheable list results | tools/list and friends no longer vary per connection |
| Header-based routing | Ordinary HTTP infrastructure can route MCP traffic |
| Extensions framework | Non-standard features get a formal home |
The spec also gained a real feature lifecycle and a deprecation policy. The 2026-07-28 deprecations were the first ones processed under it, which matters more than it sounds: it means the next removal will arrive with notice instead of arriving as a surprise in a changelog.
Why sessions had to go
A session ties a client to one server process. That is fine on a laptop and miserable in production. Every MCP deployment behind a load balancer had to solve sticky routing, and sticky routing means a dead node takes live conversations with it.
Google's developer blog framed the payoff plainly when the release candidate went out: removing transport-level session management gives you a stateless core that scales on ordinary HTTP load balanced infrastructure. Cloudflare put it more bluntly, describing MCP as now fully stateless, with the specification, interaction model, and SDKs all rewritten around that.
The cost is real and worth stating. Every server call now carries its own complete context. Nothing is implied by the connection. If your tool needed to know what happened three calls ago, you have to say so explicitly in the arguments.
The replacement is a server-minted handle
This is the part people get wrong on the first read. The spec kept the ability to hold state and removed the transport that used to hold it for you.
The mechanism, introduced as SEP-2567, is a server-minted handle passed as an ordinary tool argument. Your server creates an opaque string, hands it back in a result, and the client passes it into the next call like any other parameter.
{
"name": "query_dataset",
"arguments": {
"cursor_handle": "ds_7f21a9c4",
"limit": 100
}
}Three properties make this better than a session:
The handle is visible to the model, so the client can reason about it and log it. It is scoped to one workflow rather than one connection, so a client reconnect does not invalidate it. And it is yours to expire, which means you set the TTL rather than inheriting whatever the transport decided.
If you are hand-editing config or debugging a handle payload that came back mangled, a strict parser helps more than a text editor does. I keep the JSON Formatter open in a tab for exactly this, because a trailing comma in a tool result is a twenty minute mystery otherwise.
Multi Round-Trip Requests
The awkward case for a stateless protocol is a tool that needs to ask the user something halfway through. Elicitation used to depend on the connection staying open, which is precisely what the rewrite removed.
Multi Round-Trip Requests, or MRT, handle this by turning a mid-call question into a retryable round rather than a paused connection. The server responds with what it needs, the client gathers it, and the client calls again with the answer included.
LangChain shipped support for this in early September and their framing is the clearest one I have seen: the mid-call elicitation becomes a LangGraph interrupt. That is the right mental model. It is a resumable pause in your orchestration layer, not a held socket.
Microsoft made the same point when the C# SDK hit v2.0, describing MRT as the reason interactive tools no longer require a long-lived session. If you maintain a tool with a confirmation step, an OAuth handoff, or a "which of these 12 rows did you mean" branch, this is the API you migrate to.
Cacheable tool lists
tools/list, resources/list, and prompts/list no longer vary per connection. That single sentence in the changelog has a bigger cost impact than anything else in the release.
Under the old model, a client had to assume the catalog might differ per connection, so it re-fetched on every run. Now the catalog is cacheable. LangChain called this out specifically: a tool catalog no longer has to be re-fetched on every run.
For a local server that is a rounding error. For an agent doing hundreds of runs a day against a remote server with 60 tools, you are removing a large block of tokens from every single run, because the tool schemas were being pushed into the model's context each time. If you want to see what that actually saves in currency rather than tokens, the API Cost Calculator does the per-million math against current provider rates.
Which SDKs are ready
The Tier 1 SDKs shipped alongside the spec rather than trailing it, which is a change from earlier revisions.
| SDK | Status at release |
|---|---|
| TypeScript | Updated with the 2026-07-28 spec |
| Python | Updated with the 2026-07-28 spec |
| Go | Updated with the 2026-07-28 spec |
| C# | v2.0, released July 29, 2026 |
| Ruby | First stable release of the mcp gem, public API frozen |
The Ruby one is worth a note if you are on Rails. It is the first stable release, and the maintainers committed to breaking changes only in major versions under a documented versioning policy.
A migration order that works
Ordered by how likely each step is to bite you, which is not the same as the order the changelog lists them:
- Grep your server for
Mcp-Session-Id. Every hit is a break. - Find any state your tools read that did not arrive in the arguments. That is your handle list.
- Mint handles for those, return them in results, and accept them as parameters.
- Convert anything that blocks on user input to MRT.
- Bump the SDK last, after you know what your own code assumes.
Step two is the one that takes real time. In-memory maps keyed by session ID are the common pattern, and they look harmless until you try to run two replicas.
The client side is easier. If you are configuring an MCP client rather than writing a server, the config file shape did not change in this revision. Our LM Studio mcp.json guide still applies as written.
Who this hurts
Ad tech, apparently. Trade coverage at the end of July described the removal forcing a rebuild of agent servers across that sector, because every call now has to carry its own context instead of leaning on a persistent connection. That is not a niche complaint. Any server that streamed state into a connection and read it back out is in the same position.
Local single-user servers barely notice. Remote multi-tenant servers with per-connection auth caches have the most work.
I am mildly annoyed at the timing. A rewrite this size, six weeks after the previous revision, is a lot to absorb. But the sticky-session problem was not going to fix itself, and a protocol that cannot sit behind a normal load balancer was going to hit a wall somewhere.
FAQ
What is the latest MCP specification version?
2026-07-28. It removed protocol-level sessions, added Multi Round-Trip Requests, made list results cacheable, standardized header-based routing, and introduced a formal extensions framework.
Is MCP fully stateless now?
The transport is. The protocol no longer carries session state, and the Mcp-Session-Id header was removed from Streamable HTTP. Servers can still hold state, but they do it with explicit server-minted handles passed as tool arguments under SEP-2567.
Does this break my existing MCP server?
Only if it used the session header or relied on per-connection state. A server whose tools are pure functions of their arguments needs an SDK bump and nothing else.
What replaces elicitation on a stateless connection?
Multi Round-Trip Requests. A mid-call request for input becomes a retryable round: the server asks, the client gathers the answer, and the call is repeated with the answer in the arguments.
Do I need to change my mcp.json?
No. This revision changed the transport and the server interaction model, not the client configuration format.
Why did tool list caching matter so much?
Because tool schemas get pushed into the model context on every run. Once a catalog is cacheable, an agent that runs hundreds of times a day stops paying for the same 60 schemas over and over.
Conclusion
Read the session removal first and the rest second. It is the only breaking change, and the work it implies, auditing every place your tools read state that did not arrive as an argument, is the work that will actually consume your week.
MRT is the piece I would learn properly rather than skim. Interactive tools were the weakest part of MCP, and a retryable round is a much sturdier design than a paused connection ever was.
Sources
- MCP 2026-07-28 specification changelog
- The next generation of MCP, Cloudflare
- Scaling AI agent infrastructure with the MCP stateless updates, Google Developers Blog
- Announcing v2.0 of the official MCP C# SDK, Microsoft
- MCP in LangChain: stateless protocol, elicitation and more
- MCP roadmap and governance update
