Quick answer
The Model Context Protocol release candidate dated 2026-07-28 replaces the protocol-level session with self-contained requests. The initialize / initialized handshake and Mcp-Session-Id are removed. Protocol version, client identity, and capabilities now travel with requests, while server/discover provides server capabilities on demand.
As of July 24, this is a release candidate; the final specification is scheduled for July 28. GitHub announced on July 23 that its MCP Server already supports the new specification. If you maintain a custom MCP client, server, gateway, or SDK integration, use the remaining window to:
- Separate protocol session state from real application state.
- Add version-aware request handling without removing legacy support.
- Test routing, metadata, discovery, authorization, and multi-round-trip flows.
- Run the official MCP conformance suite before shifting traffic.
Do not delete a Redis store merely because the protocol became stateless. First prove that the store contains only transport-session data and not browser sessions, job progress, user consent, rate limits, or another application-owned state.
Who this guide is for
This guide is for developers who operate remote MCP servers, write clients, terminate MCP traffic at a gateway, or embed MCP in an AI agent product. It is not a guide for simply enabling an existing hosted connector whose vendor owns the protocol implementation.
The migration changes transport and lifecycle assumptions. Tool permissions still need a product-level boundary. Use the WebMCP security checklist for user-visible browser actions and the AI coding-agent sandbox checklist for untrusted repositories.
What changed
Under the 2025-11-25 lifecycle, a client first called initialize, received an Mcp-Session-Id, and sent that ID with later requests. A horizontally scaled server often needed sticky routing or a shared session store.
In the 2026-07-28 candidate, each request carries enough protocol context to land on any compatible instance:
| Concern | Previous lifecycle | 2026-07-28 candidate |
|---|---|---|
| Startup |
initialize then initialized
|
No initialization handshake |
| Protocol state | Session established once | Self-contained per request |
| Client context | Exchanged during initialization | Client info and capabilities in request _meta
|
| Routing | Often sticky by session ID | Any instance can handle a request |
| Server capabilities | Initialization response |
server/discover on demand |
| Request routing hints | Gateway inspects JSON-RPC body |
Mcp-Method and Mcp-Name headers |
The protocol can be stateless while the application remains stateful. A browser tool may still need a browser_id; a durable job may need a job_id. The server should return that explicit handle, and the model or host should pass it as an ordinary argument on later calls.
GitHub reports that its MCP Server removed Redis-backed protocol sessions and per-call session reads. It also moved logging and secret-scanning routing data to guaranteed HTTP headers instead of deeply inspecting every request body. That is an implementation example, not evidence that every MCP deployment can remove the same infrastructure.
Build a state-ownership inventory first
Trace every value currently keyed by Mcp-Session-Id or created during initialize.
| State | Owner after migration | Keep or remove |
|---|---|---|
| Protocol version | Request header | Remove session copy |
| Client name and capabilities | Per-request _meta
|
Remove session copy |
| Discovered server capabilities | Client cache with expiry | Remove server session copy |
| OAuth subject and scopes | Authorization layer | Keep and revalidate |
| Browser, cart, or workspace state | Application handle | Keep explicitly |
| Long-running task progress | Tasks extension or application job | Keep durably |
| Consent and approval evidence | Product audit store | Keep durably |
| Rate-limit counters | Identity, token, or tenant | Keep independently |
This table is the migration's most important artifact. If a value has no clear owner, do not remove it.
Add a dual-version boundary
Keep old and candidate behavior isolated behind protocol-version dispatch:
request
-> authenticate and authorize
-> read MCP-Protocol-Version
-> 2025-11-25: legacy initialize/session adapter
-> 2026-07-28: stateless request adapter
-> shared tool/resource/prompt implementation
-> version-specific response envelope
Do not fork the business logic. Fork only lifecycle and envelope handling. Record the protocol version, method, tool name, instance ID, authorization subject, latency, and result class in traces. Never log secrets or unrestricted tool arguments.
For application state, make the handle contract explicit:
{
"tool": "add_item",
"arguments": {
"basket_id": "opaque-handle-from-create-basket",
"sku": "SKU-42"
}
}
Treat handles as authorization-sensitive references. Validate that the caller may use the handle on every request; a stateless transport must not turn an opaque ID into an authorization bypass.
Run the official conformance suite
The official framework can test clients and servers against dated and draft behavior. Start with an isolated test instance and pin the package or action version in CI.
For a server:
npx @modelcontextprotocol/conformance server \
--url http://127.0.0.1:3000/mcp \
--suite draft
For a client:
npx @modelcontextprotocol/conformance client \
--command "node ./tests/everything-client.mjs" \
--suite draft \
--spec-version 2026-07-28
The framework records checks and exits non-zero for unexpected regressions. It supports an expected-failures baseline, but use check-level entries where possible. A whole-scenario exception can hide many unrelated failures; a stale baseline should also fail once the implementation starts passing.
Conformance proves protocol behavior, not product safety. Keep authorization, tenant isolation, consent, tool side-effect, and data-retention tests in the same release gate.
Run a seven-case canary
| Case | Test | Pass condition |
|---|---|---|
| Handshake-free | Send a valid 2026 request without initialize
|
Request succeeds without creating session state |
| Cross-instance | Send consecutive calls to different instances | Both succeed without sticky routing |
| Client context | Vary per-request client metadata | Policy sees the current request, not stale context |
| Discovery and cache | Refresh server/discover after capability change |
Cache respects the advertised expiry and refreshes |
| Application state | Create a handle, then use it on another instance | Authorized state continues; another user is rejected |
| Multi-round trip | Complete URL elicitation over separate HTTP requests | Flow resumes without a protocol session |
| Backward compatibility | Run one legacy client and one candidate client | Both pass through isolated adapters |
Canary production traffic gradually. Roll back the candidate adapter if conformance regresses, authorization decisions diverge, cross-instance calls lose application state, discovery becomes stale, or error rates exceed the recorded baseline.
Common mistakes
- Calling the candidate a final specification before July 28.
- Removing all server state instead of separating protocol and application ownership.
- Trusting client-provided metadata without authentication and authorization.
- Caching capabilities forever because initialization no longer returns them.
- Assuming round-robin routing proves state correctness without forcing cross-instance calls.
- Dropping legacy support before the clients you depend on have upgraded.
- Baselining an entire conformance scenario to hide one known failure.
- Treating protocol conformance as approval to run high-impact tools.
FAQ
Must every MCP server become stateless?
The candidate removes protocol-level sessions. Applications may still keep durable state, but it should be represented by explicit handles or extension semantics rather than an implicit transport session.
Can I remove Redis after upgrading?
Only if an inventory proves Redis holds no application, authorization, consent, rate-limit, or task state. GitHub removed its protocol-session dependency; that does not generalize automatically to your deployment.
Do official SDKs preserve older clients?
GitHub says Tier 1 SDKs have preserved backward compatibility and shipped beta support. Verify the exact SDK version you deploy and run both protocol paths in your own conformance and product tests.
Top comments (0)