On July 28, 2026, the Model Context Protocol shipped the largest revision since Anthropic open-sourced it in late 2024 — and deleted the single thing that made remote MCP servers annoying to operate. Sessions are gone. The initialize handshake is gone. The Mcp-Session-Id header is gone. In their place: a stateless request/response core where a client's first message can be the actual tool call, and any server instance behind a plain round-robin load balancer can answer it.
If you self-host agent tool servers on machines you own, this is the rare protocol change that directly deletes infrastructure. Here is the one-paragraph version, then the full before/after.
The one-paragraph answer
Under the old 2025-11-25 revision, every client opened with an initialize request, the server issued a session, and every later request had to carry the same Mcp-Session-Id back to the same server instance. Horizontally scaled deployments needed sticky routing at the load balancer plus a shared session store across instances — the exact machinery the AWS Architecture Blog's migration guide now tells you to delete. The new 2026-07-28 core makes each request self-describing instead: protocol version, client identity, and capabilities travel in a _meta field on every call, mirrored into HTTP headers. The operational delta for a self-hosted fleet:
| 2025-era sessionful MCP | 2026-07-28 stateless MCP |
|---|---|
| ALB stickiness so each session reaches the same instance | Plain round-robin — delete the stickiness rules |
| Session state in Redis/DynamoDB just to keep the protocol happy | Delete the protocol session store (your app datastore stays) |
| Gateways parsing JSON-RPC bodies to route and meter | Route and throttle on Mcp-Method / Mcp-Name headers |
| Handshake workarounds to squeeze MCP onto Lambda | Serverless as a first-class pattern: request in, response out |
tools/list re-fetched on every connect | Cacheable lists via ttlMs + cacheScope |
Nothing breaks on day one: adoption is opt-in, new clients fall back to the old handshake against older servers, and the spec ships a backward-compatible lane for 2025-era clients. The people with homework are custom MCP server authors, not tool users.
What actually shipped on July 28
The fifth spec revision, 2026-07-28, was frozen as a release candidate on May 21, giving SDK maintainers a ten-week validation window before it went final. The maintainers call it the largest change since launch, and the direction is not new: as VentureBeat reported, co-creator Justin Spahr-Summers opened a public design discussion back in December 2024 — weeks after launch — flagging that long-lived stateful connections were a poor fit for serverless deployments, and the maintainers formally committed to the stateless direction at a December 2025 meeting on the future of MCP transports.
The concrete changes, each with the exact name you will see in SDK changelogs:
- No
initialize/notifications/initializedhandshake, noMcp-Session-Id. Every request carries its protocol version, client capabilities, and optional client identity in_meta, with the version mirrored in theMCP-Protocol-Versionheader. The GET SSE stream tied to the session model goes with it. - Optional
server/discoverRPC. Clients that want upfront capability discovery call one method and get protocol versions, capabilities, and server identity in a single response. Servers must implement it; clients are not required to call it. - Required
Mcp-MethodandMcp-Nameheaders on Streamable HTTP POSTs, so gateways, WAFs, and meters can route on the operation type without parsing JSON bodies. - Multi Round-Trip Requests (MRTR) replace server-initiated elicitation, sampling, and roots calls. A server that needs input returns
resultType: "input_required"with aninputRequestsmap and an opaquerequestStatetoken; the client fulfills the requests and re-sends the original call withinputResponsesplus the echoed token. No stream is held open. - Cacheable list responses.
tools/list,prompts/list, andresources/listcarryttlMsandcacheScope, so clients and gateways can cache listings with protocol-declared freshness instead of guessing at staleness. - A deprecation clock. Roots, Sampling, Logging, and OAuth Dynamic Client Registration are deprecated under a new twelve-month policy, eligible for removal in the first revision on or after July 28, 2027. DCR's replacement is Client ID Metadata Documents: the client hosts its identity at an HTTPS URL and uses that URL as its
client_id.
Two details operators will feel immediately: every request now carries W3C Trace Context keys (traceparent, tracestate, baggage) in _meta, so MCP traffic traces end to end through any OpenTelemetry backend; and every response carries a required resultType (complete or input_required), giving gateways an unambiguous per-operation signal for metrics and alarms. Proprietary protocol logging is deprecated in favor of stderr plus OpenTelemetry — one less bespoke telemetry pipe to maintain.
What you can delete from your self-hosted stack
This is the section that pays for the migration. Audit your MCP deployment for everything that exists only to preserve protocol sessions, and put it on the removal list:
- Sticky-routing rules. Session affinity at the load balancer existed so each
Mcp-Session-Idkept reaching the instance that issued it. Stateless requests have no affinity requirement, so the stickiness configuration goes — and with it the uneven load distribution sticky routing imposes, which wastes capacity on a fleet whose sessions happened to pile onto a few instances. - The protocol session store. If you run Redis or ElastiCache purely so any instance can look up any session, that cluster's reason for existing is gone. AWS's guide prices a two-node
cache.t4g.microElastiCache session store at roughly $23/month — small in absolute terms, but the real saving is deleting an entire stateful component and its failover, backup, and upgrade burden. One boundary to keep straight: the protocol session store is deleted, but your application datastore stays — the coat-check handles in the next section still need somewhere to live. - Session-replication logic. Any code that syncs session maps between replicas, drains sessions on scale-in, or pins instances warm because they hold sessions can go. Instance loss becomes a non-event: retries need no affinity, and scale-in never drains anything.
- Custom observability plumbing. Body-parsing middleware that extracted the JSON-RPC method for metrics is replaced by header-based routing on
Mcp-Method/Mcp-Name, and bespoke log shipping for protocol events gives way tostderrplus the OpenTelemetry pipeline you already run for everything else.
One behavioral change to plan for alongside the deletions: stream resumability was removed, so a broken response stream loses the in-flight payload and the client must re-issue the call. The mitigation is idempotent tools — make re-issued requests produce no duplicate side effects, the same discipline REST APIs adopted years ago. The spec also allocates standardized error-code ranges (-32000 to -32019 implementation-defined, -32020 to -32099 reserved), so gateways can finally implement retry, backoff, and circuit-breaking on canonical signals.
What replaces sessions for stateful work
Settle this up front, because it drives everything else: stateless describes the protocol, not your application. Stateful use cases still work — they just move from hidden connection state to explicit, request-carried references.
AWS's guide uses a coat-check analogy: under the old protocol the server was a valet who remembered your face, so you had to keep dealing with that same valet. Now you get a numbered ticket, and any attendant can serve you because the ticket carries the reference. Concretely: when a server needs continuity across calls, a tool returns an identifier for the stored state, and the model includes that identifier on the calls that follow. The state stays in your datastore; the model carries only the key. This has a genuine advantage over the old model — the identifier sits in the model's context rather than hidden in a header, so the model can reason about it and thread it across tools.
For mid-call interaction, MRTR turns the old held-open-stream pattern into a retry:
# Before: server holds the stream open and asks the client mid-call
POST /mcp (Mcp-Session-Id: 1868a90c-...) → stream stays open for elicitation
# After: server returns input_required; any instance resumes the retry
POST /mcp (MCP-Protocol-Version: 2026-07-28)
→ { "resultType": "input_required", "inputRequests": {...}, "requestState": "opaque-token" }
POST /mcp (same request + inputResponses + requestState)
→ { "resultType": "complete", ... }Because requestState carries all the context the server needs to resume, any instance can pick up the retry — no shared session store required, and the pattern works on Lambda, where holding a connection open never fit. Compare that with the sessionful shape one request earlier: the difference between "any instance serves any request" and "this request must find its valet" is the entire migration.
The migration path frameworks already paved
You do not have to hand-roll the transition. The two ends of the framework spectrum have both landed it, in opposite defaults:
- Mastra went opt-in.
@mastra/mcpPR #20929 added support for the stateless revision behind a date-basedprotocolVersionflag on bothMCPServerand the MCP client. Omitting the flag keeps the legacy 2025-era handshake unchanged; settingprotocolVersion: '2026-07-28'serves the stateless revision through a dual-era handler that serves new clients natively and legacy clients through a built-in fallback on the same endpoint. The client side offers'auto', which probes at connect time and uses stateless when the server supports it.
const server = new MCPServer({
name: "deploy-tools",
protocolVersion: "2026-07-28", // stateless core; omit for legacy handshake
});- Turul went stateless-by-default. The Rust
turul-mcp-frameworkserves2026-07-28as the default connection shape — no session id, per-request_meta-carried capabilities, aserver/discoverhandler — with2025-11-25available as the opt-in connection for legacy clients that still send the old version header and expect a session id back.
Whichever default your stack picks, heed the one warning every migration guide repeats: do not delete session infrastructure while you still serve 2025-era clients. The spec's backward-compatible lane preserves session semantics for older clients, which means your stickiness rules and session store must remain in place until legacy traffic reaches zero. The practical sequence is to instrument your gateway to log protocol version per request, set a sunset date for the legacy lane, communicate it to client teams, and only then decommission. Deletion day is a traffic milestone, not a deploy.
The tradeoff it sharpens
Here is the honest part. Statelessness makes self-hosting cheaper — horizontal scale on owned boxes with no affinity, no warm-instance pinning, no session-store failover drills — and simultaneously makes serverless the path of least resistance. Lambda has no sticky routing and no persistent connections; under the sessionful protocol, running MCP there meant externalizing state to a shared store and still paying for a mandatory handshake. With the stateless core, request-in/response-out is exactly what Lambda does natively. As one cookbook puts it: do not add sticky sessions to new MCP infrastructure unless your application itself genuinely needs them.
So a self-hosted control plane can no longer argue protocol fit. It has to argue the three things that were always the real reasons to own the box:
- Latency. A deploy-from-chat loop that round-trips through a tool server on every agent step pays cold-start and network-hop tax on serverless that a warm process on your own machine does not. When the agent is driving deployments interactively, per-call latency is user-facing.
- Cost at sustained scale. Consumption pricing wins for bursty, idle-mostly traffic. A tool server fielding steady agent traffic all day prices differently — owned capacity you already run for the PaaS itself absorbs it at marginal cost near zero.
- Data gravity. Tool servers that deploy apps touch credentials, source code, and production state. Keeping that traffic on infrastructure you control, under the same audit and network boundary as the workloads it manages, is a posture argument serverless cannot match at any price.
The spec's history supports reading it this way. The stateless core was designed so MCP runs on ordinary HTTP infrastructure — every load balancer, gateway, cache, and autoscaler you already operate. Whether that infrastructure is a hyperscaler's or your own Hetzner fleet was deliberately left as your decision. The protocol just stopped taxing either answer.
What to do this week
The 2027-07-28 removal horizon for Roots, Sampling, Logging, and Dynamic Client Registration sounds far away, but the deprecations that bite are the operational ones, not the calendar ones: every month you run sticky routing and a session store for a protocol that no longer needs them is a month of paying for deleted complexity. Audit what in your stack exists only for sessions, flip the stateless flag in staging, log protocol versions at the gateway, and set the legacy sunset date. The valet has retired; hand out coat-check tickets.
Bex.co is the open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on machines you own. Star the repo on GitHub or deploy your first app today.


