Back to BlogWeb APIs

MCP Drops the Handshake: What the 2026-07-28 Spec Means for Your Servers

The MCP 2026-07-28 release candidate removes the initialize handshake and Mcp-Session-Id entirely, making the protocol stateless-first. Here is what that breaks in your server implementations, why it matters for scaling, and what the migration actually looks like.

mcpmodel-context-protocolstatelessapi-designdeveloper-tooling
MCP Drops the Handshake: What the 2026-07-28 Spec Means for Your Servers

The Model Context Protocol just published its release candidate for the 2026-07-28 spec revision — and the maintainers aren't underselling it when they call it the largest revision since launch. Two things are gone that you've been building around: the initialize handshake and Mcp-Session-Id. These aren't minor cleanups — they restructure how clients and servers establish shared context.

If you're building MCP servers, MCP clients, or wrapping any of the official SDKs, here's what actually changed and what you need to do about it.

The Old Flow: A Connection That Remembered You

Before 2026-07-28, every MCP session started with a two-step negotiation. The client sent initialize with its protocol version, client info, and capabilities. The server responded with its own capabilities, then waited for the client to fire notifications/initialized to confirm the handshake was complete.

After that, the server tracked you by session. Every request carried an Mcp-Session-Id header, and the server looked up the right context for each one. It's a familiar pattern — SMTP, WebSockets, and a dozen other protocols do exactly this. The downside is it makes your server stateful at the protocol layer, which is fine until you need to scale.

When you run multiple server instances behind a load balancer, sticky routing or a shared session store becomes mandatory. Any request that lands on the wrong instance gets context from a different session — or no session at all. In practice this means either configuring your load balancer for IP affinity (which limits your scaling options) or standing up a Redis cluster just to hold session metadata. Both are workarounds for a protocol constraint, not application requirements.

What the RC Changes

SEP-2575 removes initialize and initialized entirely. SEP-2567 removes Mcp-Session-Id. Both together eliminate the protocol's session concept at the transport layer.

The data that used to travel once in the handshake now travels on every request, in _meta:

// Before: server reads client capabilities from session state
const caps = sessions.get(req.headers['mcp-session-id']).clientCapabilities;

// After: capabilities arrive in _meta on every request
const caps = req.params._meta?.capabilities;

Capability exchange is replaced by server/discover, a new method the client calls when it needs to know what the server supports. Instead of forcing the exchange at connection open, the client pulls it on demand.

Every request is now self-contained. The server can process it without knowing anything about prior requests from the same client. That's the whole model: every hop is stateless, every request self-describes, and any server instance can answer.

Why This Matters for Scaling

Once Mcp-Session-Id is gone, MCP servers behave like stateless HTTP APIs. Any request can land on any instance. You don't need sticky sessions. You don't need to replicate session state across a shared store.

For serverless deployments — Cloudflare Workers, Lambda, Deno Deploy — this is especially significant. A function invocation processing an MCP request doesn't need to reconstruct session context from a store or fail because it doesn't have one. The request arrives with everything the server needs.

Multi-region deployments also get simpler. Before, you either routed users to the region holding their session or replicated session state across regions. Now you route to the nearest instance and call it done.

What Actually Breaks

**Session-keyed state** is the biggest one. Any server-side map from Mcp-Session-Id to client context is now orphaned — the header won't arrive. If you're storing per-client state (tool preferences, conversation context, cached auth) at the protocol layer, move it to your own storage with your own key: a user ID, an API key, a custom header your client controls.

**Connection lifecycle code** in clients needs updating too. If you have a connection manager that blocks real requests until initialized is received, remove that gate entirely. The notification no longer exists, and your client will hang waiting for it.

**SDK version assumptions** are worth auditing now. The official TypeScript, Python, and Go SDKs will ship breaking changes before July 28. The API surface for capability handling will change — watch for new method signatures around _meta injection on the client side and capability extraction on the server side. If you auto-update, don't let the SDK update land without a review.

**_meta passthrough** applies to anyone building proxies or middleware. If your layer strips or ignores _meta, stop. It's now load-bearing: the server reads client capabilities from _meta on every request, and a proxy that drops it blinds the server.

The Timeline

The RC is available now at blog.modelcontextprotocol.io. The final spec publishes July 28. Tier 1 SDKs — the official TypeScript, Python, and Go implementations — are expected to ship support within the 10-week window that follows.

The other additions in this RC — the ext-* extension framework and the Tasks primitive — are additive and don't break anything existing. But the stateless core change requires active migration, especially if session management is deep in your server's logic.

If you're starting a new MCP server today, write to the new spec. If you're maintaining an existing one, start the audit now so the SDK update isn't a surprise.