- The July 28 MCP spec removes protocol sessions and the initialize handshake, so any request can hit any server instance without sticky routing.
- State didn’t disappear; anything previously stored per session must be externalized into opaque handles that tools mint and clients pass back on each call.
- This shift is a code change, not a configuration tweak, and it forces servers to treat every request as self-contained and verifiable.
- New required headers (Mcp-Method, Mcp-Name) enable simple load balancer routing without parsing JSON-RPC bodies.
- Caching becomes standardized via ttlMs and cacheScope, while Roots, Sampling, and Logging are deprecated with a 12-month runway (effectively until mid-2027).

The July 28 MCP spec removes the protocol session. No more Mcp-Session-Id header, no initialize handshake. Any request can hit any server instance, so a remote MCP server can finally sit behind a plain round-robin load balancer.
The state you used to keep in the session does not vanish. You externalize it into opaque handles your tools mint and the client passes back on every call. That is a code change, not a config flag.
Roots, Sampling, and Logging are now deprecated with a twelve-month runway. If your server leans on them, you have until mid-2027, not forever.
For most of MCP's life, running a remote server in production meant fighting your own infrastructure. The protocol opened with an initialize handshake, handed back an Mcp-Session-Id, and expected every following request from that client to carry it. That one header quietly dictated your whole deployment. You needed sticky sessions so a client always landed on the same instance. You needed a shared session store if you wanted more than one instance. Your gateway had to crack open the JSON-RPC body to route anything intelligently. None of that is what you signed up for when you wrote a tool that looks up an order or queries a database.
The 2026-07-28 release candidate, which locks on July 28, takes the header out. SEP-2567 removes the protocol session. SEP-2575 removes the initialize and initialized handshake. Client info and capabilities now ride in _meta on every request, and a new server/discover method lets a client ask what a server can do without opening a stateful conversation first. The headline version of this is simple: any MCP request can now land on any server instance.
That sentence will end up in every writeup about this release. It also hides the actual work.
What you actually get
Start with the win, because it is real. A remote MCP server that used to need sticky routing, a shared session store, and deep packet inspection at the edge can now run behind a plain HTTP load balancer. Two new required headers, Mcp-Method and Mcp-Name (SEP-2243), let the load balancer route on the envelope instead of parsing the body. Your gateway stops being an MCP-aware component and goes back to being a load balancer.
Caching gets a real contract too. List and resource-read responses now carry ttlMs and cacheScope (SEP-2549), modeled on HTTP Cache-Control. The server says how long a tools/list response stays fresh and whether it can be shared across users. The client honors it. Before this, every client invented its own caching guesswork. Now there is a defined way to cache and a defined way to invalidate.
If you have ever tried to autoscale a remote MCP server and watched it fall over because instance B had no idea who the client talking to instance A was, this is the fix you wanted.
Where the state went
One line in the spec matters more than the load balancer story. Removing the session does not remove the state. It moves it to you.
Anything you used to hang off the session has to become an opaque handle. A basket id, a browser id, a workflow handle, a cursor into a long job. Your tool mints it, returns it, and the client passes it back on the next call. The server treats each request as complete on its own because it has to. The handle is the only thread connecting two calls, and you are the one who has to design it, sign it, and validate it.
This is not a config flag. If your server kept per-client state in memory and assumed the next request would find it there, you are rewriting that path. The upside is that the rewrite forces a cleaner design. Stateless tools are easier to test, easier to scale, and easier to reason about when something breaks at two in the morning. The cost is that "stateless at the protocol layer" reads like free scaling, and it is not free. You pay for it once, in code.
Tasks make the tradeoff concrete. Long-running async work moved out of the core and into an extension, redesigned around the stateless model. A tools/call comes back with a task handle, and the client drives it with tasks/get, tasks/update, and tasks/cancel. Notice what is gone: tasks/list was removed because listing tasks is unsafe without a session to scope them to. The handle is the scope now. If you used the experimental Tasks from the 2025-11-25 spec, this is a migration, not an upgrade.
The rest of the package
A few other changes are worth putting on your radar now rather than in July.
Authorization grew up. MCP servers are now formally OAuth 2.1 resource servers, with six SEPs aligning the spec to OAuth 2.0 and OpenID Connect. Clients have to validate the iss parameter to block mix-up attacks (SEP-2468), declare an application_type during dynamic client registration (SEP-837), and rebind credentials when an authorization server's issuer changes. If you have been hand-waving auth on an internal MCP server, the standard just got opinionated, and that helps anyone trying to get this through a security review.
MCP Apps (SEP-1865) let a server ship an interactive HTML interface that renders in a sandboxed iframe in the client, talking back over the same JSON-RPC path as any tool call, with the same consent and audit trail. Tool input and output schemas move up to full JSON Schema 2020-12 (SEP-2106), so oneOf, anyOf, conditionals, and $ref finally work.
And three features entered deprecation under a new policy (SEP-2577): Roots, Sampling, and Logging. The policy guarantees at least twelve months between the deprecation annotation and any removal, so nothing breaks on July 28. But if your server depends on Sampling to call back into the client's model, the replacement is a direct LLM provider integration, and the clock started. Logging moves to stderr for stdio servers and OpenTelemetry for structured observability. Roots get replaced by tool parameters or resource URIs.
What to do before July
You have a ten-week validation window, which is the entire point of a release candidate. Spend it on the one thing that will hurt later if you skip it.
Find every remote MCP server you operate that holds per-client state in memory. For each one, decide what that state actually is and design the opaque handle that will carry it. Then rebuild against the RC SDKs and deploy a stateless variant behind a plain load balancer. The test is one question: does it autoscale without a sticky-session config. If it does, you are ready for July 28. If it does not, you found the work early, which is the best outcome a release candidate can give you.
The session id was a small header. It was also load-bearing. Pulling it out is the most consequential thing MCP has done since it shipped, and the servers that handle it well will be the ones whose authors treated "stateless" as a design problem instead of a deployment setting.
If you run or build an MCP server, plan a refactor away from in-memory per-client session state: design opaque, signed, and validated handles (for cursors, workflows, baskets, job IDs) that make each request complete on its own. Update your edge and deployment assumptions to use plain round-robin load balancing and route using the new headers, and implement the new caching contract so clients can cache safely. Finally, audit any dependence on Roots/Sampling/Logging and schedule migration work before the deprecation window closes.