MCP Went Stateless on July 28 - What Changes for Your Servers

The MCP 2026-07-28 specification removes the session handshake and Mcp-Session-Id that pinned clients to one server instance. Here is what actually changed, what breaks, and what the hype is missing.

Cover art for MCP Went Stateless on July 28 - What Changes for Your Servers

Before July 28, every MCP deployment that wanted to scale horizontally had the same problem: the initialize handshake minted an Mcp-Session-Id that pinned each client to whichever server instance handled the first request. Round-robin a second request to a different pod and the SDK returned 404. Two ASP.NET Core MCP pods behind a round-robin load balancer hit this exactly: pod A handled initialize and minted a session ID; the follow-up SSE request hashed to pod B, which had never seen that client, and returned 404. Thirty seconds later the client threw TaskCanceledException. The usual fix was LB stickiness on Mcp-Session-Id - it works, but it is infrastructure duct tape over a protocol problem.

The 2026-07-28 spec removes the duct tape requirement entirely. On May 21, 2026, the MCP team locked the release candidate - the largest revision since the protocol launched - and the final specification shipped on July 28, 2026, after a ten-week validation window for SDK maintainers. The two lead maintainers, David Soria Parra and Den Delimarsky, called it "the last revision that breaks compatibility."

What the stateless core actually means for production

The headline change is a stateless protocol core: MCP transforms from a bidirectional stateful protocol into a request/response stateless protocol. The concrete infrastructure consequence is direct. A remote MCP server that previously needed sticky sessions, a shared session store, and deep packet inspection at the gateway can now run behind a plain round-robin load balancer, route traffic on an Mcp-Method header, and let clients cache tools/list responses for as long as the server's ttlMs permits.

Two specification enhancement proposals define the change. SEP-2575 removes the initialize handshake, and SEP-2567 removes the Mcp-Session-Id header along with the protocol-level session.

Protocol version, client info, and capabilities now travel inline in a _meta field on each request

  • making every call self-describing rather than relying on accumulated handshake context.

One thing worth being precise about: stateless transport does not mean stateless application. Removing the protocol-level session does not mean your application has to be stateless. Servers that need to carry state across calls can mint an explicit handle - a basket_id, a browser_id - from a tool and have the model pass it back as an ordinary argument on later calls. State that was previously hidden in the transport now has to be visible in the tool call. That is a meaningful design constraint, and it makes agent behavior easier to trace and debug.

How server-to-client requests work without a persistent connection

The hardest part of going stateless is what to do when a server needs to ask the client something mid-call - an "are you sure you want to delete these three files?" prompt. The old answer was: hold an SSE stream open. Server-initiated requests like elicitations or sampling callbacks used to depend on holding a Server-Sent Events stream open. The new spec introduces InputRequiredResult: the server returns a result with resultType: input_required, a map of questions in inputRequests, and an opaque requestState token. The client collects the answers and re-issues the original call with inputResponses plus the echoed requestState. Because requestState carries everything needed to resume, the retry can land on a completely different server instance.

One InputRequiredResult can batch an elicitation and a sampling request together in a single round-trip. And crucially, server-initiated requests may now only be issued while the server is actively processing a client request. Earlier spec versions recommended this; it is now required. A user is never prompted out of nowhere, and every elicitation traces back to something they or their agent started.

Beagle in action#engineering, Tuesday 10:42am
The ask
agent calls a file-management tool that needs a confirmation before deleting three docs
Beagle drafts
receives InputRequiredResult from the MCP server, surfaces the "Delete 3 files?" prompt inline in Slack for a human nod
You approve
you approve; Beagle re-issues the tool call with inputResponses and requestState - the retry hits a different pod and completes cleanly
Do this in your workspace

The migration picture: what breaks, what does not, and the one real cliff

The honest scope of the work is: two changes are immediate for anyone who wants the new behaviour - removing the handshake dependency and removing Mcp-Session-Id - and the rest can be scheduled against a minimum 12-month deprecation window. Nothing switched off on July 28.

Three features enter formal deprecation on this release.

Three features enter deprecation: Roots (replaced by tool parameters or config), Sampling (call the LLM provider API directly), and Logging (use stderr or OpenTelemetry). A formal deprecation policy guarantees a minimum twelve-month window between deprecation and removal, so none of these break on July 28.

The one genuine cliff is version mixing with elicitations. If your gateway fronts an MCP server target that upgrades to 2026-07-28 before your clients do, it translates between versions, so a 2025-era client can call ordinary tools on a 2026-07-28 target and receive results in the format it expects. However, this translation does not currently support elicitations and sampling calls from servers to clients. If a 2025-era client calls a tool on a 2026-07-28 server that requires elicitation or sampling, it receives an error.

That means: if you run tools that prompt the user for confirmation and you upgrade the server before the clients, those flows break silently for old clients. Audit that before you deploy.

What Before 2026-07-28 After 2026-07-28
Session handshake Required; mints Mcp-Session-Id Removed (SEP-2575 + SEP-2567)
Load balancer Sticky sessions or shared session store Plain round-robin, route on Mcp-Method header
Mid-call user prompts Held SSE stream InputRequiredResult + requestState retry
Long-running tasks Experimental Tasks API Stateless tasks/get / tasks/cancel lifecycle
SSE stream resumability Last-Event-ID, event redelivery Removed; client re-issues with new request ID
App state Hidden in transport session Explicit tool handles passed as arguments
22,311MCP servers in the ecosystemas of July 16, 2026 (PulseMCP)
400M+monthly SDK downloadscited by Anthropic at launch
12 monthsminimum deprecation windowfor Roots, Sampling, and Logging
4Tier 1 SDKs shipping new specTypeScript, Python, Go, C# - all live on release day

The extensions framework and what ships alongside it

The stateless core is the structural change; the release also ships: an Extensions framework, Tasks, MCP Apps, authorization hardening, and a formal deprecation policy.

Extensions are now identified by reverse-DNS IDs, negotiated through an extensions map on client and server capabilities, live in their own ext-* repositories with delegated maintainers, and version independently of the specification. A new Extensions Track in the SEP process gives them a path from experimental to official.

Authorization hardening is worth understanding carefully because it is being misreported. The authorization rework is the part most likely to be misreported. MCP did not invent new security primitives in this release. It made two existing ones mandatory and reordered how clients register.

RFC 9207, "OAuth 2.0 Authorization Server Issuer Identification," was published by the IETF in March 2022 as a countermeasure to mix-up attacks. What is new in 2026 is the requirement, not the mechanism.

The Tasks extension is worth flagging separately. The Tasks extension reshapes the lifecycle around the stateless model: a server can answer tools/call with a task handle, and the client drives it with tasks/get, tasks/update, and tasks/cancel. If you were using the experimental Tasks API from 2025, this is a migration, not a drop-in - budget time for it.

Running an MCP server at scale
Without Beagle
sticky sessions on the load balancer, shared Redis for session state, reconnect logic for when a pod restarts, and bespoke gateway config to route by session ID
With Beagle
plain round-robin load balancer, stateless pod pool, Mcp-Method header routing - and app state carried as explicit tool handles the model passes back

MCP 2026-07-28 stateless spec: common questions

What is the MCP 2026-07-28 specification?

It is the largest revision to the Model Context Protocol since its November 2024 launch. The headline change is that the protocol becomes stateless: the initialize handshake and Mcp-Session-Id header are removed, so any request can land on any server instance behind a plain round-robin load balancer. It also ships an Extensions framework, the Tasks extension, MCP Apps, and a formal deprecation policy.

Do I have to rewrite my existing MCP server?

No full rewrite. The two immediate changes are removing the handshake dependency and the session ID. Everything else - Roots, Sampling, Logging - enters a minimum 12-month deprecation window. Nothing stopped working on July 28. The new @modelcontextprotocol/server v2 SDK can serve both old and new clients from a single handler.

What replaces server-initiated elicitations over SSE?

The new Multi Round-Trip Request (MRTR) pattern. The server returns an InputRequiredResult with the questions it needs answered and an opaque requestState token. The client collects answers from the user and re-issues the original call with inputResponses and the echoed requestState. Because all state travels in the payload, the retry can hit a different server instance.

Will old 2025-era clients break against a 2026-07-28 server?

For ordinary tool calls: no, gateways translate between versions. The exception is elicitation and sampling: if a 2025-era client calls a tool that triggers an InputRequiredResult, it receives an error because the old client does not know the new result type. Audit any tools that prompt for confirmation before upgrading your server ahead of your clients.

What gets deprecated in this release?

Three features: Roots (use tool parameters or config instead), Sampling (call your LLM provider API directly), and Logging (use stderr or an OpenTelemetry exporter). All three carry a minimum twelve-month window before they can be removed - the earliest possible removal date is July 2027.

Or just watch me work

Point me at your website.

I will read up on your business and come back with what I would run for you. No account, no card, about a minute.

I only read what is public. Nothing is saved to your name until you say so.

Keep reading

Beagle does this work for you, in your Slack.1,000 free credits. No card.Hire Beagle