
SYS.BLOG
MCP Goes Stateless: The 2026 Spec Explained
The MCP 2026-07-28 spec deletes the handshake, sessions, and SSE resumability. What breaks, what got better, and how to migrate your MCP server.
The MCP spec that shipped today (July 28, 2026) deletes the initialization handshake, deletes protocol-level sessions, and deletes SSE resumability. That is not a feature release, that is a rewrite of how the protocol works at the transport layer, and the maintainers themselves call it the biggest change since authorization landed. I have built a couple of MCP servers, so I read the full 2026-07-28 specification and the changelog. Here is what actually changed, what breaks, and whether you should care.
The Handshake Is Gone: MCP Is Now Stateless
MCP no longer has an initialize handshake or an Mcp-Session-Id header. Every request is now self-contained: the protocol version, client capabilities, and client identity travel in a _meta object on each request, and the server identifies itself in each result the same way. If the versions do not match, you get an UnsupportedProtocolVersionError back instead of a broken session.
This is the change everything else falls out of. The old model was a stateful, bidirectional connection, which meant horizontally scaled HTTP servers needed sticky routing or a shared session store just to answer tools/list. Serverless deployments fought the protocol constantly. Now a plain request/response server on Lambda, Cloudflare Workers, or any edge runtime speaks MCP without ceremony. Servers that genuinely need cross-call state mint their own handles and pass them as ordinary tool arguments, which is how every other stateless protocol on the internet already does it.
There is one new obligation: servers MUST implement a server/discover RPC that advertises supported versions and capabilities. Clients can call it up front to pick a version, or use it as a compatibility probe on stdio.
What Actually Breaks If You Run a Server Today
The honest answer: a 2026-07-28 server and an older client will not understand each other, and vice versa. The specific removals that bite are ping, logging/setLevel, the HTTP GET notification endpoint, resources/subscribe, and SSE stream resumability. If a response stream drops mid-request, the request is just gone and the client re-issues it with a new ID. There is no Last-Event-ID replay anymore, so long-running tool calls need to be idempotent or use the tasks extension.
Two smaller ones that will still trip up SDK code: every result now carries a required resultType field, and the resource-not-found error code moved from -32002 to the standard JSON-RPC -32602. Log level is now set per-request via _meta, and a server is not allowed to emit log notifications for requests that did not ask for them. That last one is a real fix: chatty servers spamming every client was a genuine problem.
Multi Round-Trip Requests Replace Server-Initiated Calls
Servers can no longer call the client. The old server-initiated requests (sampling/createMessage, elicitation/create, roots/list) are replaced by a pattern called Multi Round-Trip Requests: when a server needs something from the user mid-tool-call, it returns an interim result with resultType: "input_required" listing what it needs, and the client retries the original request with the answers attached. The server correlates retries through an opaque requestState blob it hands back.
This is clunkier to write than a callback, but it is the price of statelessness, and it means elicitation now works on serverless infrastructure where a reverse channel never existed in the first place. If you built interactive flows on elicitation/create, this is your biggest migration item.
One Stream for Subscriptions Instead of Three Mechanisms
Change notifications now flow through a single long-lived subscriptions/listen stream that the client opts into, picking exactly which notification types it wants (tool list changes, resource updates, and so on). This replaces the HTTP GET endpoint and the subscribe/unsubscribe dance. Progress and log notifications still ride on the response stream of the request they belong to, which keeps them scoped and cancellable.
Tasks, Apps, and Skills Are Extensions Now
The core protocol got smaller, and everything ambitious moved into versioned, opt-in extensions negotiated via a new extensions capability field. Tasks (long-running async operations) left the core, dropped the blocking tasks/result call for polling via tasks/get, and gained tasks/update for feeding input to a running task. MCP Apps (interactive UI rendered inline in conversations) and Skills over MCP are the other two headline extensions.
I think this is the right call. The 2025 specs were accumulating features that most servers never implemented, and every client had to at least know about them. A small mandatory core with negotiated extensions is how protocols survive their own success.
Roots, Sampling, and Logging Are on Death Row
All three features are deprecated with a minimum twelve-month window under the new feature lifecycle policy. They still work, but new implementations should skip them. The suggested migrations are blunt: pass directories as tool parameters instead of Roots, call your LLM provider directly instead of Sampling, and log to stderr or OpenTelemetry instead of the Logging feature.
Nobody I know shipped real Sampling support anyway, so this mostly formalizes reality. Dynamic Client Registration is also deprecated in favor of Client ID Metadata Documents, which matters if you do OAuth against enterprise identity providers.
Caching Finally Exists, and It Helps Your Prompt Cache Too
List results now carry required ttlMs and cacheScope fields, so clients can stop hammering tools/list on every turn. The spec also tells servers to return tools in deterministic order specifically to improve LLM prompt cache hit rates. That is a small line in the changelog with real money attached: shuffled tool lists were silently invalidating prompt caches, and anyone running agents at scale was paying for it. I wrote about where those tokens actually go in my post on Claude Code session files.
What Claude Is Doing With the New Spec
Anthropic announced same-day support rolling out across Claude products: MCP Apps rendering interactive UI inside conversations, enterprise-managed connectors provisioned through Entra and Okta, observability dashboards for connector usage, and MCP tunnels (a research preview) that connect Claude to servers on private networks without exposing them publicly. Figma, Intuit, Netlify, PostHog, Xero, and Zoom built against the spec during the beta. The SDKs are at 400 million monthly downloads, four times what they were a year ago, so this is no longer a protocol you can wait out.
Should You Migrate Your MCP Server Now?
If your server is stdio-based, relax: the wire format changes are modest for you, and server/discover doubles as the compatibility probe. Both of mine, the Gemini image generation server and the YouTube analysis server, are stdio servers that mostly need the resultType field and the discover endpoint once the SDKs land stable releases. If you run a remote HTTP server, migrate sooner: you get to delete your session store, your sticky routing config, and your resumability code, and what is left deploys anywhere.
The practical path: update to the new SDK betas, run your server, and poke at what it actually exposes with my free browser-based MCP inspector before wiring it into a client. And if you are new to MCP entirely, the Claude Code complete guide covers how servers plug into a real agent workflow. The interesting open question is whether the tasks extension becomes the default way agents do long-running work, because polling durable handles looks a lot more like a job queue than a chat protocol, and that is probably where agent infrastructure was heading anyway.
FREQUENTLY ASKED QUESTIONS
What changed in the MCP 2026-07-28 specification?
The 2026-07-28 spec makes MCP stateless: the initialize handshake and Mcp-Session-Id header are gone, protocol version and capabilities travel in _meta on every request, and a new server/discover RPC advertises what a server supports. Tasks moved to an extension, and Roots, Sampling, and Logging are deprecated.
Is the new MCP spec backwards compatible?
No, not automatically. A 2026-07-28 server and an older client will not understand each other because the handshake, session header, and several methods were removed. Clients can call server/discover as a compatibility probe, and deprecated features keep working for at least twelve months under the new lifecycle policy.
What does stateless mean for MCP servers?
Every MCP request is now self-contained, so servers no longer track sessions between calls. That removes the need for sticky routing or shared session stores and lets MCP servers run on serverless and edge platforms like Lambda or Cloudflare Workers. Servers that need cross-call state pass explicit handles as tool arguments.
Are Roots, Sampling, and Logging removed from MCP?
They are deprecated, not removed yet. All three keep working during a minimum twelve-month deprecation window, but new implementations should not adopt them. The suggested replacements are tool parameters instead of Roots, direct LLM provider APIs instead of Sampling, and stderr or OpenTelemetry instead of Logging.


