MCP's First Breaking Change: Sessions Are Gone, Statelessness Wins
The 2026-07-28 MCP spec drops sessions and the handshake for good. Here's what breaks, what's deprecated, and what the reference SDK already shipped.

The protocol that never broke anything just broke something
Since Anthropic introduced the Model Context Protocol, MCP has moved through several spec revisions without ever removing something a running server depended on. That streak ended on July 28, when the 2026-07-28 revision shipped: the largest single set of protocol changes since MCP launched, and the first that genuinely breaks the wire contract client and server used to share.
The headline: MCP is no longer a session protocol. It's stateless, request by request. If you've deployed MCP servers assuming a live connection carries identity across calls, that assumption stops being safe under the new spec — on a minimum twelve-month deprecation clock, not an emergency, but a real one.
What actually changed: no more sessions, no more handshake
Three removals do the real work. First, protocol-level sessions are gone — the Mcp-Session-Id header disappears from Streamable HTTP, and tools/list/resources/list/prompts/list no longer vary per connection. A server that needs cross-call state now mints its own handle and passes it back as an ordinary tool argument, the same way any stateless HTTP API would. That inverts where state lives:
// before: state rode the connection
initialize → Mcp-Session-Id: abc123 → tools/call (session implied)
// after: state is an explicit, server-minted argument
tools/call { cursor: "srv_7f3a…" } → tools/call { cursor: "srv_9b1c…" }
Second, the initialize/notifications/initialized handshake is gone too. Every request now carries its own protocol version and capabilities in _meta (io.modelcontextprotocol/protocolVersion, io.modelcontextprotocol/clientCapabilities), and a new server/discover RPC — which servers must implement — lets a client learn a server's supported versions and identity up front, or use it as a backward-compatibility probe. A version mismatch now returns an explicit UnsupportedProtocolVersionError instead of a silently failed handshake. There's no more "connect, then talk"; every request is self-describing.
Third, SSE stream resumability is gone. Drop a response stream mid-request under the new spec and you don't recover it with a Last-Event-ID — you re-issue the whole request with a new ID. Combined with statelessness, this is a genuine simplification for anyone running MCP servers behind a load balancer: no session affinity, no sticky routing, no "which pod holds this connection's state" problem. Stateless-by-default fits serverless and edge deployment far better than the connection-oriented design MCP shipped with.
The deprecations: Sampling, Roots, and Logging are on the clock
The quieter change matters more for anyone with production servers today: Roots, Sampling, and Logging are now formally deprecated, replaced by a "Multi Round-Trip Requests" (MRTR) pattern for anything that used to be a server-initiated request.
It's worth seeing what MRTR actually replaces the reverse channel with, because "multi round-trip" sounds vaguer than it is. Instead of the server calling back into the client mid-request, the server returns an InputRequiredResult whose inputRequests field lists exactly what it needs; the client retries the original request with inputResponses attached. One request shape, no server-to-client callbacks, no half-open state to reason about. Everything that used to be roots/list, sampling/createMessage, or elicitation/create now flows through that single retry loop.
The deprecated features still work during the window, but new implementations shouldn't build on them — and the spec is explicit about where to land instead: pass directories through tool parameters instead of Roots, call your own LLM provider API directly instead of Sampling, and log to stderr or OpenTelemetry instead of the Logging feature.
Sampling is the one worth pausing on. It let an MCP server ask the client's connected LLM to do a piece of reasoning on the server's behalf — no separate API key, no separate bill, borrowed intelligence from whoever's driving the client. That convenience is going away. Every server that leaned on it now owns its own model calls, its own provider keys, and its own cost line. It's a less elegant trust model, but a more honest one: the server doing the reasoning is the one paying for it and choosing which model runs it.
The reference SDK already shipped v2 — same day
This isn't a paper spec waiting for adoption. The @modelcontextprotocol TypeScript SDK published a full v2.0.0 package family — core, server, client, plus framework adapters for Express, Fastify, Hono, and Node — on July 27, hours ahead of the spec going final. There's also a codemod package that rewrites a v1 codebase's imports automatically, and a server-legacy package for teams that need to keep serving pre-2026-07-28 clients while they migrate.
The early interop pain is already documented and already fixed: the SDK's v2.0.0 release notes describe a beta build that hard-rejected a conforming server's DiscoverResult — a mismatch against the final spec text that caused real connect failures against other early implementations, including a pre-release Go SDK. That's the normal cost of a spec landing across multiple official SDKs at once, and it's a good sign the ecosystem is actually testing interop rather than each language shipping in isolation.
For anyone running MCP servers in TypeScript, the migration story is unusually complete for a spec that's one week old: read docs/migration/upgrade-to-v2.md, run the codemod, keep server-legacy in front of clients you can't force to upgrade yet.
What to actually check this week
You don't need to migrate today — the deprecation window is at least twelve months, and most hosted MCP clients will keep negotiating the old handshake for a while yet. But three checks are cheap and worth doing now, before this becomes a fire drill:
- Grep your MCP servers for
Samplingusage. If a server calls back into the client's LLM instead of its own, that's the piece with a real cost implication once the feature goes away — you'll need a provider key and a budget line that don't exist today. - Check whether anything in your infrastructure relies on session affinity for MCP traffic. If a load balancer routes by
Mcp-Session-Idtoday, that routing rule becomes dead weight once servers move to the stateless model — worth flagging before someone spends a sprint debugging a "connection" that no longer exists. - If you're on the TypeScript SDK, run the codemod against a branch now, even if you don't merge it. The interop bugs the SDK team already caught (the
DiscoverResultmismatch against early Go implementations) are exactly the kind of thing you want to hit in a branch, not in production three months from now when the deprecation clock is louder.
What we're betting on next week
We're watching two things. First, whether the Python and Go SDKs land equivalent v2 support at the same pace the TypeScript SDK did — a single fast reference implementation doesn't tell you whether the spec itself works cleanly across runtimes. Second, whether any of the mid-size hosted MCP platforms publish their own migration timeline; a twelve-month deprecation window is generous, but "generous" is also how migrations quietly slip to month eleven.
If you're running MCP servers that lean on Sampling for cost-free reasoning, start pricing what a direct LLM API call costs you instead — that number will matter more than the deprecation deadline.
Running MCP servers in production and unsure what the stateless spec actually touches in your fleet? Get in touch.
Work with Ikki
Running MCP servers in production?
We audit your MCP server fleet against the 2026-07-28 spec: session assumptions, Sampling/Roots usage, and a concrete v1-to-v2 migration plan.
More articles
Claude Opus 5 Ships at Opus 4.8's Price. Speed Becomes the Upsell.
Opus 5 launches at $5/$25 per million tokens, unchanged from Opus 4.8, while the Agent SDK ships the code-level controls for its new fast mode.
PlatformsNuxt 3's Clock Runs Out July 31, Right As Nuxt 4.5 Ships
Nuxt 3 reaches end-of-life July 31 — eleven days after Nuxt 4.5 shipped Vite 8, Rspack 2, and an experimental SSR streaming mode worth testing now.