The MCP 2026-07-28 specification is the largest revision of the Model Context Protocol since it launched in late 2024. It removes the initialize/initialized handshake and the Mcp-Session-Id header entirely, making every request fully self-contained. Any server instance behind a plain round-robin load balancer can now handle any request, without sticky routing, shared session storage, or persistent connections.
Last verified: 2026-08-08
initializehandshake andMcp-Session-Idheader are gone (SEP-2575 + SEP-2567)- Every request now carries protocol version and client capabilities in
_meta - New
Mcp-MethodandMcp-NameHTTP headers let gateways route without parsing JSON - Multi Round-Trip Requests (MRTR) replace server-initiated callbacks for user input
- Tasks graduated from experimental to an official extension; Roots, Sampling, and Logging are deprecated with a 12-month minimum removal window
- All four Tier 1 SDKs (TypeScript, Python, Go, C#) shipped support by launch day; TypeScript v2 replaces the monolithic package with modular libraries plus a codemod
Why Did Stateful MCP Cause So Much Pain?
Stateful MCP caused pain because the session ID pinned the client to one server instance. If you placed an MCP server behind a load balancer with three instances, the instance that received the initialize call held the session state. Every subsequent request had to reach that same instance carrying the Mcp-Session-Id header. If a load balancer routed a request to a different instance, that instance had never heard of the session and returned a 400 "Session not found" error. The same failure happened if that pod crashed or was restarted — the session state was lost and every following request failed.
Workarounds existed but added cost and complexity:
- Sticky sessions (session affinity): the load balancer pins each client to one instance. This works but defeats the purpose of horizontal scaling — you can never rebalance traffic across instances without breaking active sessions.
- Shared session store: an external Redis (or similar) holds session state so any instance can look it up. This added latency, operational overhead, and a single point of failure to what should have been a stateless API call.
The deeper problem was that sessions had no consistent meaning across MCP clients. As the SEP-2567 proposal noted, some clients scoped sessions per tool call, some per application launch, some per page load, and almost none resumed them. A server author could not predict what scope or lifetime a session would have with an arbitrary client, making the session abstraction unreliable as a container for application state.
What Is the 2026-07-28 MCP Specification?
The 2026-07-28 specification is the version of the Model Context Protocol published on July 28, 2026. MCP uses dated version strings instead of semantic versioning — the previous stable spec was 2025-11-25. The release candidate was locked on May 21, 2026, followed by a ten-week validation window for Tier 1 SDK maintainers before the final release.
Two proposals do the heavy lifting:
- SEP-2575 ("Make MCP Stateless"): removes the
initialize/initializedhandshake. Protocol version, client info, and client capabilities that were previously exchanged once at connection time now travel in_metaon every request. A new optionalserver/discovermethod lets clients fetch server capabilities when they need them. - SEP-2567 ("Sessionless MCP via Explicit State Handles"): removes the
Mcp-Session-Idheader and the protocol-level session concept entirely. Together with SEP-2575, these make MCP stateless at every layer.
How Does a Stateless Tool Call Look Now?
A tool call that previously required an initialize handshake plus session headers on every request is now a single self-contained HTTP POST. Here is the before and after:
Before (2025-11-25):
POST /mcp HTTP/1.1
Mcp-Session-Id: 1868a90c-3a3f-4f5b
Content-Type: application/json
{"jsonrpc":"2.0","id":2,"method":"tools/call",
"params":{"name":"search","arguments":{"q":"otters"}}}
After (2026-07-28):
POST /mcp HTTP/1.1
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: search
Content-Type: application/json
{"jsonrpc":"2.0","id":1,"method":"tools/call",
"params":{"name":"search","arguments":{"q":"otters"},
"_meta":{"io.modelcontextprotocol/clientInfo":{"name":"my-app","version":"1.0"}}}}
No session header. No prior handshake. Any server instance can process this request because everything it needs to understand the client is embedded in the request itself.
What Are the New HTTP Headers for MCP?
Two new required headers on Streamable HTTP POST requests — Mcp-Method and Mcp-Name — were added via SEP-2243. They let a load balancer, API gateway, rate limiter, or firewall route and authorize requests by inspecting headers alone, without parsing the JSON-RPC body.
Mcp-Method: the JSON-RPC method being called (e.g.,tools/call)Mcp-Name: the specific tool or resource name (e.g.,search)
Servers reject requests where the headers and body disagree, closing off mismatches between routing and operation. This also reduces latency at the gateway layer since inspectors do not need to buffer and parse the full request body to make routing decisions.
How Does User Input Work Without a Persistent Connection?
User input requests (elicitation, sampling) now use Multi Round-Trip Requests (MRTR), introduced in this spec via SEP-2322. Instead of the server pushing a follow-up question down an open stream to the client — which could prompt the user out of nowhere — the server returns an InputRequiredResult with resultType: "input_required".
The flow works like this:
- Client sends a tool call (e.g., "delete this file").
- Server determines it needs confirmation and returns
input_requiredwith arequestStatepayload (all the context needed to resume) and aninputRequestsmap describing what it needs (e.g., an elicitation asking "Are you sure?" as a boolean). - The client prompts the user, gathers the response, then retries the original call with
inputResponsesattached and therequestStateechoed back. - Any server instance can pick up the retry — the
requestStatecarries everything needed to resume. No instance affinity required.
This replaces the old pattern where servers sent elicitation/create or sampling/createMessage as server-initiated JSON-RPC requests over a persistent stream. MRTR makes every interaction explicit and fully auditable.
How Do Long-Running Tasks Work in Stateless MCP?
Long-running tasks are handled by the Tasks extension, which graduated from experimental status to an official extension (io.modelcontextprotocol/tasks) via SEP-2663. The pattern is asynchronous polling:
- A tool writes task state to a database (status: "working") and kicks off an async job.
- The tool call immediately returns a task handle to the agent and user.
- The client polls progress via
tasks/getor subscribes withsubscriptions/listen. - When the job completes, the client retrieves the final result.
This removes the need to hold a connection open while a long operation runs, and any server instance can answer a tasks/get poll since the state lives in a database, not in server memory.
What Happened to State? Can Tools Still Store Information?
State did not disappear — it moved from the protocol layer to your application layer. When a tool needs cross-call state (a shopping basket, a browser session, a workflow context), the server mints an explicit handle such as a basket_id or browser_id and the model passes it back as an ordinary tool argument on later calls.
This is more flexible than protocol-level sessions because:
- The model decides scope: state can be shared across conversations, handed off to a different agent, or isolated per call — the developer controls this, not the protocol.
- List endpoints are cacheable:
tools/list,prompts/list, andresources/listresults no longer vary per-connection. Responses now carryttlMsandcacheScopefields (SEP-2549), modeled on HTTP'sCache-Control, so a client knows exactly how long a tool list is fresh and whether it is safe to share across users. - State is addressable: an explicit
basket_idcan be passed to any tool, any agent, or resumed in a new conversation. A session ID could never refer to state outside the session that created it.
What Does Stateless MCP Mean for Deployment?
Stateless MCP is built on normal HTTP infrastructure, so every deployment simplification that applies to HTTP APIs now applies to MCP servers. The biggest wins:
- Standard round-robin routing: any container can handle any request. No sticky sessions, no shared Redis instance holding session state.
- Scale to zero: on serverless platforms like Cloudflare Workers or Google Cloud Run, the server does not need to be up 24/7 since there are no connections to hold open. It can scale down to zero when idle and spin up on demand. Cloudflare confirmed that MCP servers no longer require Durable Objects to speak the protocol — each request runs on a fresh stateless Worker.
- Auto-scaling: traffic can be distributed across any number of instances without coordination. If one instance crashes, the load balancer sends the next request to a healthy instance and the client never notices.
- Simpler infrastructure: no session store, no sticky routing configuration, no SSE stream management. A remote MCP server is now just a stateless HTTP service.
What Is Deprecated in the 2026-07-28 Spec?
Three protocol features are deprecated (not removed yet) via SEP-2577, with a minimum 12-month window before any could be removed (SEP-2596):
| Feature | What It Did | Replacement |
|---|---|---|
| Roots | Let servers read filesystem locations from the client | Pass paths as tool parameters or config |
| Sampling | Let servers request LLM completions from the client model | Call the LLM provider API directly from the server |
| Logging | Let servers send log messages to the client via notifications/message |
Use stderr or OpenTelemetry trace context (now propagated in _meta via SEP-414) |
The deprecated features still work during the deprecation window — these are annotation-only deprecations with no wire-level changes. The earliest anything deprecated on 2026-07-28 could be removed is July 2027, and removal requires a separate SEP.
Additionally, ping and logging/setLevel were removed outright (log level is now set per-request via io.modelcontextprotocol/logLevel in _meta), and SSE stream resumability / message redelivery (the Last-Event-ID header and SSE event IDs) were removed from the Streamable HTTP transport.
A notable error code change: "resource not found" errors moved from the custom -32002 code to the standard JSON-RPC -32602 ("Invalid Params"). If your server or client hardcodes -32002, this is a required update.
How Do You Migrate an MCP Server to the New Spec?
Migrating is not a simple package bump — it involves architectural changes to how your server handles state, routing, and user interactions. Here is a practical checklist:
Step 1: Upgrade Your SDK
All four Tier 1 SDKs ship support for the 2026-07-28 protocol:
- TypeScript: the monolithic
@modelcontextprotocol/sdk(v1) is replaced by two modular packages —@modelcontextprotocol/clientand@modelcontextprotocol/server, both at version 2.0. A codemod (npx @modelcontextprotocol/codemod@latest v1-to-v2 .) handles the standard API renames. Run it at the package root, not just./src, because real projects import the SDK fromtest/andscripts/too. - Python, Go, C#: each shipped a major version bump with support for the new protocol revision.
The codemod handles the v1-to-v2 SDK surface upgrade only. Adopting the 2026-07-28 protocol revision itself (createMcpHandler, multi-round-trip requests, versionNegotiation) is architectural and not codemod-automatable.
Step 2: Remove Session Assumptions
- Stop relying on
Mcp-Session-Id. Move any per-session state into explicit handles (likebasket_id) passed as tool arguments. - Remove any
initializehandshake logic. Protocol version and capabilities now arrive in_metaon every request.
Step 3: Emit the New HTTP Headers
Ensure Mcp-Method and Mcp-Name are set on all Streamable HTTP POST requests. Servers must reject requests where the headers and body disagree.
Step 4: Implement MRTR for User Input
Replace any server-initiated elicitation/create, sampling/createMessage, or roots/list calls with the MRTR pattern. Return InputRequiredResult when you need input; the client will retry the original call with responses attached.
Step 5: Add Caching Metadata
Add ttlMs and cacheScope to your tools/list, prompts/list, resources/list, and resources/read responses so clients can cache correctly and reduce unnecessary re-fetching.
Step 6: Migrate Tasks
If you used the experimental Tasks API, switch to the extension lifecycle: tasks/get for polling, tasks/update for client-to-server input, and tasks/cancel for cancellation.
Step 7: Update Error Codes
Change "resource not found" errors from -32002 to -32602 if your code references the custom code.
Step 8: Plan Deprecation Moves
Schedule the migration off Roots, Sampling, and Logging within the 12-month window. Replace Sampling with direct LLM API calls, Roots with tool parameters, and Logging with OpenTelemetry or stderr.
What This Means for You
If you build AI agents that call remote MCP servers, the good news is that most SDKs handle the protocol upgrade for you. Your agent code likely does not change much — the SDK abstracts the _meta envelope, MRTR retry loop, and header emission. The main risk is if you relied on server-initiated sampling (the server asking your client for LLM completions); that pattern is deprecated and you should be prepared to provide your own model access.
If you operate remote MCP servers, this is the biggest operational shift the protocol has seen. Without session state to manage, a remote MCP server is now a stateless HTTP service. You get round-robin load balancing, auto-scaling, scale-to-zero on serverless platforms, and standard gateway routing without instance coordination. But you must audit every dependency on Mcp-Session-Id and initialize, move state into explicit handles or shared storage, implement MRTR for interactive flows, and update your SDK. The 12-month deprecation window gives runway, but the breaking changes at the transport layer mean a client upgrade will break against an un-upgraded server.
If you are planning new MCP infrastructure, start from the 2026-07-28 spec directly. There is no reason to build against the old stateful model. The new spec is simpler, more scalable, and aligns with how HTTP services already work.
Building AI agents that talk to tools is part of a broader shift toward agentic operating systems that orchestrate multiple capabilities. For teams looking to build a personal AI agent OS, MCP's stateless model means your agent can now connect to tool servers that scale like any other web service. If you are running agents locally, the local agentic OS guide covers the same pattern without cloud dependencies.
FAQ
Q: Is the 2026-07-28 MCP spec backward compatible?
A: No, it introduces breaking changes at the transport layer. The initialize handshake and Mcp-Session-Id are removed. However, the SDKs support both eras — a modern client that sends a 2026-07-28 request to an older server will fall back to the initialize flow if the server rejects it. This means migration can be gradual.
Q: What replaces Mcp-Session-Id in the new spec?
A: Nothing at the protocol level. If your tool needs cross-call state, you mint an explicit identifier (like basket_id) as a tool argument. The model carries and threads it through subsequent calls. This is a tool-design pattern, not a new protocol construct.
Q: Do I have to rewrite my entire MCP server?
A: Not a full rewrite, but significant updates are needed. Upgrade the SDK, remove session tracking, emit the new Mcp-Method and Mcp-Name headers, implement MRTR for interactive flows, add ttlMs to list responses, migrate experimental Tasks to the extension lifecycle, and update error codes from -32002 to -32602.
Q: Can I still use Cloudflare Durable Objects with the new spec? A: Yes, but they are no longer required to speak the protocol. The stateless spec runs on a plain Cloudflare Worker. Use Durable Objects when your application genuinely needs coordinated state, not for protocol-level session management.
Q: What is the minimum time before deprecated features are removed? A: The specification's Feature Lifecycle Policy (SEP-2596) guarantees a minimum 12-month window between deprecation and removal. Features deprecated on 2026-07-28 cannot be removed before July 2027 at the earliest, and removal requires a separate SEP.
Q: What happens if a client uses the old initialize handshake?
A: Servers can implement both eras side by side. A server that wishes to support both old and new clients can continue implementing the old initialize RPC for legacy clients while also exposing the new stateless RPCs. SDKs handle automatic version negotiation between client and server.
Every claim here is traced to a primary source, dated, and listed under Sources. Research and drafting are AI-assisted; editing, verification and publication are human decisions, and a person is accountable for what appears on this page. How we work →

Discussion
0 comments