MCP Goes Stateless: What the 2026-07-28 RC Means for Servers
The Model Context Protocol 2026-07-28 release candidate is the first MCP revision that should make remote servers feel like ordinary HTTP infrastructure instead of sticky-session infrastructure with JSON-RPC inside it.
That is the useful mental model for developers. Previous Streamable HTTP deployments could still depend on an initialization handshake, an Mcp-Session-Id, and connection-scoped assumptions. The 2026-07-28 RC removes the protocol-level session and moves protocol metadata onto each request. It also formalizes request headers such as Mcp-Method, adds cache hints such as ttlMs and cacheScope, moves Tasks into an official extension, and hardens OAuth behavior around issuer validation.
Effloow Lab ran a stdlib-only local sandbox PoC for this article. The PoC did not use an official MCP SDK and does not claim conformance. It validated the migration shape: a request reached any simulated worker without a session, header/body mismatch returned a structured error, tools/list returned cache metadata, and a task created by worker B was polled by worker A through an explicit task handle. Evidence is saved at data/lab-runs/mcp-stateless-http-2026-07-28-rc-production-guide.md.
Why This RC Matters
The official MCP blog says the release candidate became available on May 21, 2026, with the final specification planned for July 28, 2026. It describes the RC as a stateless protocol core with first-class extensions, Tasks, MCP Apps, authorization hardening, and a formal deprecation policy.
That is more than cleanup. MCP servers are increasingly deployed as remote services behind gateways, reverse proxies, load balancers, and observability systems. If an MCP server requires request two to land on the same process that handled request one, operators need sticky routing or a shared protocol session store. Those are solvable problems, but they are unnecessary for many tool servers.
The RC changes the default architecture. Every request can carry the protocol version, client identity, and client capabilities in _meta. Streamable HTTP can mirror routing-relevant fields into headers. Application state still exists, but it moves into explicit handles: a workspace_id, basket_id, task_id, browser_id, or other server-minted identifier that the model passes back as a normal tool argument.
That is the important distinction: MCP is becoming stateless at the protocol layer, not pretending that real applications have no state.
What Effloow Lab Verified
The local sandbox used Python's standard library to start a temporary HTTP endpoint on 127.0.0.1. Each client request included:
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/list
Accept: application/json, text/event-stream
The JSON-RPC body carried matching _meta values:
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list",
"params": {
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientInfo": {
"name": "effloow-lab",
"version": "0.1"
},
"io.modelcontextprotocol/clientCapabilities": {
"extensions": {
"io.modelcontextprotocol/tasks": {
"version": "draft"
}
}
}
}
}
}
The useful output was not the toy server itself. It was the behavior:
discover_status= 200
tools_cache= {'ttlMs': 30000, 'cacheScope': 'public'}
mismatch_status= 400
mismatch_error= HeaderMismatch
task_create_status= 202
task_created_by= B
task_get_status_value= completed
task_polled_by= A
task_result_text= sandbox result
That output proves only a local design point. It does not prove final spec compatibility, OAuth security, SSE behavior, SDK support, or client interoperability. It does show why the RC is operationally attractive: protocol-level session state is no longer required for the simple case where every request is self-describing and task state is stored behind an explicit handle.
The Main Breaking Change: No Protocol Session
The draft changelog lists two related major changes: remove protocol-level sessions and remove the initialize / notifications/initialized handshake. The older request shape established a protocol session first, then sent subsequent requests with Mcp-Session-Id. In the RC shape, a tools/call request can stand on its own.
For a production server, that affects four areas.
First, load balancers no longer need to keep the same client pinned to the same worker for protocol reasons. You may still choose sticky routing for application performance, but the protocol itself should not force it.
Second, horizontal scaling becomes easier to reason about. If worker A dies, worker B can still process the next request as long as any required application state is in a database, cache, object store, workflow engine, or ordinary explicit handle.
Third, compatibility logic becomes more important. A serious server may need to reject unsupported protocol versions with clear errors, accept only versions it actually implements, and keep migration tests for old and new request shapes.
Fourth, hidden state becomes a design smell. If a tool depends on a client having previously called another method, the dependency should be visible in the schema or arguments. Models are better at using visible identifiers than invisible transport sessions.
Headers Become Infrastructure Signals
The draft Streamable HTTP transport says each JSON-RPC message is sent as its own HTTP POST to a single MCP endpoint. It also says request metadata can be mirrored into HTTP headers so intermediaries can route and inspect requests without parsing the body.
The important headers are:
MCP-Protocol-Version: the requested protocol version.Mcp-Method: the JSON-RPC method, such astools/call.Mcp-Name: the tool name, resource URI, or prompt name for selected methods.
The server still treats the body as the source of truth. If the header says tools/list and the JSON-RPC body says tools/call, the server should reject the mismatch. Effloow Lab's sandbox reproduced that pattern with a HeaderMismatch response.
This matters for platform teams because gateways, WAFs, rate limiters, and tracing systems can make decisions earlier. A gateway can route expensive tools differently from cheap list calls. An observability pipeline can label spans by MCP method without parsing arbitrary JSON. A server can fail fast when a buggy client sends inconsistent metadata.
Cache Hints Make tools/list Less Noisy
The RC adds ttlMs and cacheScope to list and read responses through a cacheable result interface. The point is not to turn every MCP response into CDN content. The point is to stop clients from asking the same stable questions on every interaction.
For example, a server whose tool list rarely changes can return:
{
"tools": [
{
"name": "summarize",
"description": "Summarize text",
"inputSchema": { "type": "object" }
}
],
"ttlMs": 30000,
"cacheScope": "public"
}
That tells clients the response is fresh for 30 seconds and can be shared under the declared cache scope. For hosted agent systems, this can reduce repeated capability-discovery traffic and improve prompt-cache stability because the same ordered tool list can be reused instead of regenerated.
Do not overread this. A dynamic server still has to be conservative. If available tools vary by user, tenant, entitlement, project, or request context, cacheScope should reflect that. A wrong cache hint can leak capabilities or confuse a model into calling a tool the user cannot access.
Tasks Move To An Extension
The release candidate moves experimental Tasks out of core protocol and into the official io.modelcontextprotocol/tasks extension. The RC blog says the extension reshapes task lifecycle around the stateless model: a server can answer tools/call with a task handle, then the client drives progress with methods such as tasks/get, tasks/update, and tasks/cancel.
This is a healthier model for long-running work. Without a task primitive, developers often invent tool triplets:
start_reportpoll_reportget_report_result
That works, but it pushes lifecycle conventions into prompt text. With a task extension, the lifecycle becomes a negotiated protocol capability. The agent host can own polling, cancellation, progress display, and retry behavior instead of hoping the model remembers the right sequence.
Effloow Lab's sandbox implemented only a minimal version: tools/call returned a task ID, tasks/get returned completed status after a short delay, and tasks/result returned text. That is intentionally smaller than the RC extension and does not test cancellation or client input. The design lesson still holds: long-running work should return a handle, not hide state inside a worker process.
Authorization Hardening Is Not Optional In Practice
The draft authorization page says MCP authorization is optional for implementations, but if an HTTP-based implementation supports authorization, it should conform to the MCP authorization specification. The draft also references OAuth 2.1, protected resource metadata, dynamic client registration, resource indicators, and RFC 9207 issuer identification.
The practical security change developers should notice is iss validation. RFC 9207 defines an authorization response issuer parameter. The draft MCP authorization spec says clients must compare a present iss value against the recorded issuer before sending an authorization code to any token endpoint, and should reject responses when metadata says iss is supported but the response omits it.
That matters because MCP clients may connect to many servers. A generic client that talks to a dozen MCP servers has a bigger mix-up surface than a single-purpose app talking to one API. Issuer validation helps ensure an authorization response belongs to the authorization server the client actually selected.
For server authors, the migration point is straightforward: do not treat auth as an add-on after the transport works. Protected resource metadata, token audience validation, issuer handling, scope challenges, and per-request authorization checks need to be part of the same design pass as stateless transport.
Migration Checklist For Server Authors
Start by inventorying session assumptions. Search your server for state keyed by connection, session ID, worker memory, or initialization order. Decide which state should disappear, which should become an explicit tool argument, and which should move into a durable store.
Next, add strict protocol metadata validation. A request should have a protocol version in _meta, a matching MCP-Protocol-Version header on HTTP, and deterministic behavior when the version is unsupported. Reject mismatches early.
Then make tool and resource lists deterministic. Stable ordering and accurate cache hints reduce repeated discovery overhead. Use private cache scope when output depends on user, tenant, permission, or project state.
After that, separate fast tools from task-backed tools. Fast deterministic calls can still return directly. Slow, cancellable, retryable, expensive, or externally queued work should return a task handle and store task state outside the request handler.
Finally, test behind boring infrastructure. Put the server behind a local reverse proxy or load balancer, disable sticky sessions, and send repeated calls from a client harness. Verify that request one and request two can land on different workers without breaking protocol behavior.
Common Mistakes
The first mistake is saying "stateless" and deleting application state. A browser automation task, report generator, checkout flow, or code execution job still needs state. The RC is about removing hidden protocol session state, not pretending workflows are single-request functions.
The second mistake is caching capability lists too aggressively. A stable public tool list is a good cache candidate. A user-specific permission-filtered tool list is not public cache material.
The third mistake is ignoring backward compatibility. The draft transport page explicitly calls out behavior changes from earlier Streamable HTTP revisions. If your server supports multiple protocol versions, write tests for each era instead of branching casually.
The fourth mistake is treating Tasks as a queue name. A task lifecycle needs status, cancellation, expiry, retention, authorization checks, and result access rules. A task ID is a public handle from the agent's perspective; handle it like one.
FAQ
Q: Is the 2026-07-28 MCP specification final now?
No. The official blog describes it as a release candidate available on May 21, 2026, with the final specification planned for July 28, 2026. Build migration prototypes now, but label RC support clearly until the final spec lands.
Q: Does stateless MCP mean I no longer need Redis, Postgres, or a workflow engine?
No. You may need them more clearly. Stateless protocol design moves hidden connection state into explicit application state. If a job outlives one request, store it somewhere durable enough for your reliability target.
Q: Should every tool call become a task?
No. Use tasks for work that is slow, cancellable, retryable, expensive, or likely to outlive one HTTP response. A simple deterministic lookup should still return directly.
Q: Can I claim my server supports the RC if headers work?
Not safely. Headers are only one part of the RC. You also need protocol metadata handling, version negotiation behavior, discovery, compatibility decisions, task extension negotiation where relevant, authorization behavior where applicable, and tests against current SDKs or conformance tools when available.
Key Takeaways
The MCP 2026-07-28 release candidate is a production-infrastructure release. It changes how servers should scale, how clients should discover capabilities, how gateways can route traffic, and how long-running work should be represented.
Effloow Lab's local sandbox verified the most important design shape: no session handshake, self-contained request metadata, header/body mismatch rejection, cache hints on list responses, and explicit task handles that survive worker changes. That is enough to guide architecture, not enough to claim conformance.
If you maintain an MCP server, the safest next step is a migration branch with three tests: one request per HTTP POST, no sticky session dependency, and task state stored outside the worker. Once that is true, the RC's bigger changes become a manageable protocol migration instead of a production rewrite.
Treat the 2026-07-28 RC as a forcing function: remove hidden protocol sessions, make state explicit, and test your server behind ordinary HTTP infrastructure before the final spec date.
Sources
- Official MCP release candidate blog:
https://blog.modelcontextprotocol.io/posts/2026-07-28-release-candidate/ - Official MCP roadmap:
https://modelcontextprotocol.io/development/roadmap - Draft changelog:
https://modelcontextprotocol.io/specification/draft/changelog - Draft Streamable HTTP transport:
https://modelcontextprotocol.io/specification/draft/basic/transports/streamable-http - Draft authorization specification:
https://modelcontextprotocol.io/specification/draft/basic/authorization - RFC 9207:
https://www.rfc-editor.org/rfc/rfc9207.html - Related Effloow article:
/articles/mcp-roadmap-2026-stateless-http-tasks-server-cards
Need content like this
for your blog?
We run AI-powered technical blogs. Start with a free 3-article pilot.