MCP’s Stateless Era: A Production Migration Guide
The MCP 2026-07-28 specification removes protocol-level sessions and the initialize handshake. A remote tool call can now arrive as one self-contained HTTP request at any healthy server instance. That simplifies horizontal scaling, routing, caching, and recovery, but it is a breaking change for clients, servers, gateways, and test suites built around Mcp-Session-Id.
This guide explains what changed, what remains stateful, and how to migrate a production MCP deployment without turning a protocol upgrade into an outage.
What changed in MCP 2026-07-28
The official MCP release announcement calls this the largest protocol revision since launch. Its central change is a stateless protocol core designed to run on ordinary HTTP infrastructure.
Before: 2025-11-25 |
After: 2026-07-28 |
Production effect |
|---|---|---|
Client sends initialize, then notifications/initialized |
Initialization handshake is removed | No connection bootstrap path to maintain |
Server can issue Mcp-Session-Id |
Protocol-level sessions are removed | No sticky routing or shared session store required by MCP itself |
| Version and capabilities are negotiated once | Protocol version, client information, and capabilities travel with requests in _meta |
Each request contains the context needed to process it |
| Gateways inspect JSON-RPC bodies to identify operations | Streamable HTTP requires Mcp-Method and Mcp-Name headers |
Routing and rate limits can operate without parsing request bodies |
| Long-lived connections communicate list changes | List and resource reads include ttlMs and cacheScope |
Clients can cache results with explicit freshness and sharing rules |
| Experimental Tasks sit in the core specification | Tasks use a first-class extension lifecycle | Long-running work has an explicit, stateless handle-based flow |
The 2026-07-28 changelog is the source of truth for every breaking and minor change. Do not treat this as an SDK-only upgrade. The new lifecycle changes what crosses your network boundary and what your application must persist.
Stateless protocol does not mean stateless application
The easiest migration mistake is deleting all state because MCP is now “stateless.” The specification removes hidden transport state, not business state.
A shopping tool may still need a basket_id. A browser automation tool may still need a browser_id. A coding agent may still need a durable task record, credentials, artifacts, and an audit trail. The difference is that the server returns an explicit handle and the model passes it back as a normal tool argument on later calls.
That changes ownership:
- The protocol no longer owns continuity. Do not depend on an implicit session established during initialization.
- Your tool contract owns continuity. Make required handles visible in input and output schemas.
- Your application owns durability. Store handles and their backing records in a database when they must survive process restarts or span multiple replicas.
- Your authorization layer owns access. A valid handle must not become a bearer credential. Bind it to the authenticated principal and validate access on every call.
This is why persistent storage for MCP applications still matters. You may no longer need Redis just to route an Mcp-Session-Id, but you still need durable storage for workflows, user data, tool results, and long-running operations.
A six-step production migration
1. Inventory every session assumption
Search the client, server, reverse proxy, observability pipeline, and tests for initialize, notifications/initialized, and Mcp-Session-Id. Then classify each use:
- Protocol negotiation that can be deleted.
- Routing logic that can become ordinary round-robin load balancing.
- Application state that needs an explicit handle.
- Authentication or tenancy logic that must move to request-level validation.
- Metrics and traces that need a new correlation key.
Do not remove the old path until this inventory is complete. A session map sometimes hides application state that should have been modeled explicitly from the start.
2. Make each request self-contained
Update the SDKs first where supported, then verify the wire format rather than trusting the version number alone. A 2026-07-28 request should carry the protocol version and relevant client metadata on the request. Streamable HTTP POST requests also need Mcp-Method and Mcp-Name headers that agree with the JSON-RPC body.
At the gateway, route and rate-limit on those headers. Reject mismatches instead of trusting one representation over the other. Keep body-size, authentication, and schema validation controls in place because routable headers are operational metadata, not a security boundary.
If clients need server capabilities before making a call, use server/discover. Do not rebuild the removed initialization handshake under a different name.
3. Replace implicit sessions with explicit handles
For every multi-call workflow, define the smallest durable resource the tool needs. Return an opaque identifier when the resource is created and require that identifier on later operations.
{
"name": "create_deployment",
"arguments": {
"repository": "org/service"
}
}
{
"deployment_id": "dep_8f31",
"status": "queued"
}
Later tools receive deployment_id explicitly. The identifier should be opaque, hard to guess, scoped to the correct tenant, and safe to log. Put the actual state in PostgreSQL, Valkey, or another durable store according to its consistency and retention needs.
This model also makes retries easier to reason about. Creation tools should accept an idempotency key or implement equivalent deduplication so a network retry does not create two deployments, payments, or destructive operations.
4. Migrate long-running work to the Tasks extension
Tasks moved from an experimental core feature to the official Tasks extension and changed shape. A server can return a task handle from tools/call; the client then uses tasks/get, tasks/update, or tasks/cancel. Task creation is server-directed, and tasks/list is removed because it cannot be scoped safely without sessions.
If you used the 2025-11-25 Tasks API, treat the migration as a data-model change:
- Negotiate the Tasks extension rather than assuming the capability exists.
- Let the server decide when work becomes a task.
- Persist task ownership, status, progress, result, and cancellation state.
- Replace broad task listing with application-specific, authorized discovery if users genuinely need it.
- Test duplicate polling, cancellation races, expired handles, and worker restarts.
The handle is protocol-visible; the job queue and worker remain your application’s responsibility.
5. Harden authorization during the same rollout
The new authorization specification aligns more closely with real OAuth 2.0 and OpenID Connect deployments. Clients validate the authorization response iss value, declare an OpenID Connect application_type during Dynamic Client Registration, and bind registered credentials to the authorization server that issued them. The release also clarifies refresh-token requests, step-up scope accumulation, and .well-known discovery paths.
Before enabling the new protocol version:
- Confirm your authorization server supplies a correct
issparameter. - Test native and CLI clients with localhost redirect URIs.
- Re-register credentials when a resource moves to a different issuer.
- Validate audience, issuer, scopes, tenant, and handle ownership on every request.
- Keep tokens out of tool arguments, model context, logs, and task payloads.
These checks complement the broader MCP security controls around tool metadata, least privilege, consent, and auditability. The protocol can standardize the exchange, but it cannot decide whether a particular agent should be allowed to delete a production database.
6. Roll out with versioned compatibility
Run old and new clients against a compatibility environment before production. If your traffic mix requires both protocol versions, keep the compatibility boundary explicit: separate endpoints, adapters, or deployments are easier to reason about than conditionals scattered across every tool handler.
A safe rollout sequence is:
- Add request-level traces, metrics, and structured error reporting.
- Deploy server support for the new version behind a dedicated endpoint or traffic rule.
- Run conformance, contract, authorization, retry, and failure-injection tests.
- Upgrade a small client cohort and compare error rate, latency, cache behavior, and task completion.
- Increase traffic gradually while keeping the old path available for rollback.
- Remove session infrastructure only after old-version traffic reaches zero.
The specification now documents W3C Trace Context fields in _meta, so carry traceparent, tracestate, and baggage through the client, MCP server, workers, and downstream services. Stateless requests are easier to move between replicas, which makes end-to-end correlation more important, not less.
Other breaking changes to test
The transport rewrite is the largest change, but it is not the only one that can break production code.
- Tool schemas:
inputSchemaandoutputSchemanow support full JSON Schema 2020-12. Inputs still require an object at the root, while output schemas andstructuredContentcan represent any JSON value. Bound schema depth and validation time, and do not automatically dereference external$refURLs. - Resource errors: A missing resource now returns JSON-RPC
-32602Invalid Params instead of MCP-specific-32002. Update clients and alerts that match the literal code. - Server-to-client requests: A server may initiate a request only while processing a client request. Multi-round-trip flows return
InputRequiredResult; the client gathers input and repeats the original call withinputResponsesandrequestState. - Extensions: Capabilities use reverse-DNS extension identifiers and version independently from the core specification. Unknown or unsupported extensions must degrade cleanly.
- Deprecations: Roots, Sampling, and Logging are deprecated, but not removed. New implementations should use tool parameters or resource URIs instead of Roots, direct model-provider integrations instead of Sampling, and stderr or OpenTelemetry instead of protocol Logging.
The formal feature lifecycle provides at least a twelve-month window between deprecation and possible removal. Use that time to migrate deliberately, but do not build new dependencies on items in the deprecated features registry.
Production readiness checklist
Before declaring the migration complete, verify all of the following:
- No request requires
initialize,notifications/initialized, orMcp-Session-Id. - Any replica can process any request from the supported client cohort.
Mcp-MethodandMcp-Namematch the JSON-RPC body and drive gateway policy.- Cross-call state uses explicit, authorized handles backed by appropriate storage.
- Mutating tools are idempotent or safely deduplicated.
- Cached list and resource responses respect
ttlMsandcacheScope. - Long-running calls use the negotiated Tasks extension and survive worker restarts.
- OAuth issuer, audience, scopes, redirect behavior, refresh flow, and re-registration are tested.
- Trace context reaches downstream services without exposing sensitive baggage.
- Deprecated features have an owner and removal plan.
- Rollback works without corrupting handles, tasks, or user data.
If you need a refresher on the moving parts, start with MCP server architecture, then compare MCP hosting options against the state your application still needs.
Where CreateOS fits
The stateless specification makes MCP easier to distribute across standard HTTP infrastructure. Production applications still need a place to run tool handlers, persist explicit state, manage secrets, observe requests, and recover long-running work.
CreateOS provides one execution layer for deploying MCP servers and the services behind them. You can run the server, attach managed storage for application state, configure environment variables, inspect logs, and scale the workload without rebuilding protocol-level session routing. The platform does not make a stateful workflow stateless; it gives that state an explicit, durable home while the MCP transport remains horizontally scalable.
Deploy an MCP server on CreateOS when you are ready to test the 2026-07-28 model against real infrastructure. Start with a compatibility environment, prove the request and task lifecycle, then move production traffic deliberately.
Frequently asked questions
Is MCP completely stateless now?
The 2026-07-28 protocol core is stateless: it removes the initialization handshake, Mcp-Session-Id, and protocol-managed session continuity. Applications can still persist workflows, tasks, user data, and other state. They expose explicit handles in tool inputs and outputs instead of hiding continuity in transport metadata.
Do stateless MCP servers still need a database?
Not always. A pure lookup or transformation tool may not need storage. A server that manages deployments, browser sessions, carts, user records, long-running jobs, or audit history still needs durable application storage even though MCP no longer requires a protocol session store.
Can I remove sticky sessions from my load balancer?
Yes, once every production request is self-contained and no application code relies on replica-local state. Migrate application state to explicit handles and durable storage first, verify that any replica can serve any request, then remove sticky routing.
What happens to existing MCP clients?
Clients built for older protocol versions do not automatically speak 2026-07-28. Upgrade supported SDKs, test the actual wire behavior, and keep an explicit compatibility path while old clients remain in use. The July release contains breaking changes, so plan a staged rollout rather than a flag-day switch.
Are Roots, Sampling, and Logging already removed?
No. They are deprecated under the new feature lifecycle and continue to work in this specification. New implementations should avoid adopting them, and existing users should plan migrations to the documented replacements before a future removal.

