Table of Contents
MCP 2026-07-28 Spec Goes Stateless: The Migration Guide for n8n, Cursor, and Cline Builders
If you run a remote MCP server today, here is the one sentence that matters: the initialize handshake and the Mcp-Session-Id header are gone in the next spec, so any code that pins a client to a single server instance through a session will stop working when the 2026-07-28 version lands. The release candidate dropped May 21, 2026. The final ships July 28. That gives you a ten-week window to migrate, and the payoff is real: a server that needed sticky sessions, a shared session store, and deep packet inspection at the gateway can now sit behind a plain round-robin load balancer (per the RC announcement).
We pulled the before-and-after HTTP from the spec, mapped every deprecation to its replacement, and wrote the migration checklist for the three tools most Pondero readers run MCP through: self-hosted n8n, Cursor, and Cline. The verdict up front: if you ship MCP servers to clients, start the migration now, because the breaking changes are concrete and the deadline is fixed. If you only consume MCP servers through a managed client, you mostly wait for your tool to update, with one exception we flag below.
The stateless shift, in HTTP
The headline change is that MCP is stateless at the protocol layer. Six Specification Enhancement Proposals (SEPs) work together to get there, completing the transport plan the working group laid out in December 2025 (RC announcement).
Walk through what a single tool call looks like before and after. In the current 2025-11-25 spec, calling a tool over Streamable HTTP means you establish a session first:
POST /mcp HTTP/1.1
Content-Type: application/json
{"jsonrpc":"2.0","id":1,"method":"initialize",
"params":{"protocolVersion":"2025-11-25","capabilities":{},
"clientInfo":{"name":"my-app","version":"1.0"}}}
The server hands back an Mcp-Session-Id, and every request after that has to carry it. That header is what pins the client to whichever instance issued it:
POST /mcp HTTP/1.1
Mcp-Session-Id: 1868a90c-3a3f-4f5b
Content-Type: application/json
{"jsonrpc":"2.0","id":2,"method":"tools/call",
"params":{"name":"search","arguments":{"q":"otters"}}}
In 2026-07-28, that same call collapses into one self-contained request that any server instance can answer:
POST /mcp HTTP/1.1
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: search
Content-Type: application/json
{"jsonrpc":"2.0","id":1,"method":"tools/call",
"params":{"name":"search","arguments":{"q":"otters"},
"_meta":{"io.modelcontextprotocol/clientInfo":{"name":"my-app","version":"1.0"}}}}
Two things changed structurally. The initialize/initialized handshake is removed (SEP-2575). Protocol version, client info, and client capabilities now ride in _meta on every request, and a new server/discover method lets a client pull server capabilities up front when it actually needs them. And the Mcp-Session-Id header, plus the protocol-level session that came with it, is removed too (SEP-2567). With both gone, any MCP request can land on any instance. The sticky routing and shared session stores that horizontal deployments needed at the protocol layer are no longer required.
The HTTP examples above are reproduced from the official
2026-07-28release candidate. The spec is still an RC until July 28; the changelog against2025-11-25lives in the draft specification.
Stateless protocol does not mean stateless app
This is the part that trips people up. Dropping the protocol session does not mean your application can't carry state. It means state moves into the open, where the model can see it.
The replacement is the explicit-handle pattern, which is how HTTP APIs have always done this. A tool mints an identifier (a basket_id, a browser_id) and returns it, and the model passes that handle back as an ordinary argument on the next call:
// create_basket returns a handle
{ "basket_id": "bskt_91af20" }
// the model threads it back into the next tool call
{"jsonrpc":"2.0","id":2,"method":"tools/call",
"params":{"name":"add_item",
"arguments":{"basket_id":"bskt_91af20","sku":"A-1138"}}}
The MCP maintainers argue this is more than a workaround. Because the handle is visible to the model rather than hidden in transport metadata, the model can compose handles across tools and hand them off between steps in ways that an externally managed session never allowed (RC announcement).
What happens to server-to-client requests
A stateless protocol still needs a way for a server to ask the client something mid-call, like an elicitation prompt. Holding an SSE stream open was the old answer. The new one is Multi Round-Trip Requests (SEP-2322): the server returns an InputRequiredResult instead of blocking on a stream.
{
"resultType": "inputRequired",
"inputRequests": {
"confirm": {
"type": "elicitation",
"message": "Delete 3 files?",
"schema": { "type": "boolean" }
}
},
"requestState": "eyJzdGVwIjoxLCJmaWxlcyI6WyJhIiwiYiIsImMiXX0="
}
The client gathers the answers and re-issues the original call with inputResponses plus the echoed requestState. Because everything the server needs is in that payload, any instance can pick up the retry. One related tightening: server-initiated requests may now only fire while the server is actively processing a client request (SEP-2260). A user never gets prompted out of nowhere.
Deprecations to remove now
Three core features are deprecated under the new feature lifecycle policy (SEP-2577). These are annotation-only deprecations, so the methods keep working in this release and in every spec version published within a year of it. But the replacement is clear in each case, and new servers should not build on them.
| Deprecated feature | What to use instead |
|---|---|
| Roots | Tool parameters, resource URIs, or server configuration |
| Sampling | Direct integration with your LLM provider's API |
| Logging | stderr for stdio transports; OpenTelemetry for structured observability |
If your server exposed filesystem boundaries through Roots, fold those into a tool parameter or a resource URI scheme instead. If you called back to the host's model through Sampling, wire your server straight to the provider API you actually use. And if you leaned on the MCP Logging capability, route stdio logs to stderr and emit structured telemetry through OpenTelemetry, which the spec now documents as the supported observability path.
One error code also changed, and it bites silently. The code for a missing resource moves from MCP's custom -32002 to the JSON-RPC standard -32602 Invalid Params (SEP-2164). If your client matches on the literal -32002 integer anywhere, update that branch or it will fall through.
MCP Apps and Tasks: the two extensions that ship with the RC
Extensions existed in 2025-11-25 but had no formal process behind them. The RC fixes that (SEP-2133): extensions get reverse-DNS IDs, negotiate through an extensions map on capabilities, live in their own ext-* repositories with delegated maintainers, and version independently of the spec. Two official extensions ship alongside the release.
MCP Apps (SEP-1865) lets a server ship an interactive HTML interface that the host renders in a sandboxed iframe. Tools declare their UI templates ahead of time, so a host can prefetch, cache, and security-review them before anything runs. The rendered UI talks back over the same JSON-RPC base protocol, which means every action a user takes inside that UI goes through the same audit and consent path as a direct tool call. In practice this is how an MCP server returns a confirmation card or a small form instead of dumping text at the model.
The Tasks extension is the migration most builders will trip on. Tasks shipped as an experimental core feature in 2025-11-25. Production use surfaced enough redesign that it now lives in an extension, reshaped around the stateless model. A server can answer a tools/call with a task handle, and the client drives the work with tasks/get, tasks/update, and tasks/cancel. Task creation is server-directed: the client advertises the extension, and the server decides when a call runs as a task. The tasks/list method is gone, because it can't be scoped safely without sessions. Anyone who shipped against the 2025-11-25 experimental Tasks API has to migrate to this new lifecycle (RC announcement).
The "change X to Y" cheat sheet
Here is every breaking change mapped to its fix in one place.
| If you use this today | Change it to this |
|---|---|
initialize / initialized session handshake | A single self-contained request; client info and capabilities ride in _meta; use server/discover to fetch capabilities up front |
Mcp-Session-Id header for sticky routing | No session header; mint an explicit handle (basket_id, etc.) from a tool and pass it back as an argument |
Tasks experimental API with tasks/list | The Tasks extension lifecycle: tasks/get, tasks/update, tasks/cancel (no tasks/list) |
Matching on error code -32002 for a missing resource | Match on -32602 Invalid Params |
| Roots / Sampling / Logging core features | Tool params or resource URIs / direct LLM provider API / stderr plus OpenTelemetry |
Migration checklist by tool
Self-hosted n8n
The stateless spec directly solves the pain n8n users hit when they scale an MCP server behind more than one worker. Sticky sessions meant you either ran a single instance or stood up a shared session store. With 2026-07-28, neither is required at the protocol layer.
What to do before July 28:
# 1. Audit your MCP server nodes for session assumptions.
# Search your workflow exports for the old session header.
grep -rni "mcp-session-id" ./n8n-workflows/
# 2. If you front your MCP server with nginx/HAProxy, drop the
# sticky-session config once your server speaks 2026-07-28.
# Round-robin is enough. Verify the upstream block looks like:
# upstream mcp { server mcp-a:3000; server mcp-b:3000; }
# with NO `ip_hash;` or session-affinity directive.
# 3. Move any cross-call state into explicit handles returned by
# your tool, not into a session the transport tracked for you.
If you run MCP servers as containers, the stateless model is also where a managed host earns its keep, because you can finally scale horizontally without a session store bolted on the side. Cloudways is a reasonable pick for a self-hosted MCP server, since you get a managed VPS with autoscaling-friendly load balancing already in front of it, which is exactly the round-robin setup the new spec assumes.
Builders wiring MCP into a low-code automation layer rather than self-hosting can also reach MCP through Make, whose modules can call an MCP server as part of a workflow. The same stateless server you build for July 28 works there without per-platform special-casing, because there is no session to keep alive.
Cursor
Cursor consumes MCP servers as a client; you configure them in its MCP settings rather than running the transport yourself. The practical move here is to wait for Cursor to ship 2026-07-28 support and then re-test any custom MCP server you point it at. The one thing to do now: if you maintain a server that Cursor connects to, make sure it can speak both spec versions during the transition, because clients will upgrade on their own schedule. Cursor's own MCP documentation is the place to track when its client lands the new version.
Cline
Cline is an open-source coding agent that acts as an MCP client and iterates quickly. If you run MCP servers that Cline connects to, the same dual-version rule applies during the window: keep the server answering 2025-11-25 requests until Cline ships the new client, then drop the old path. Watch the Cline releases page for the version that adds 2026-07-28 client support, and re-test your server against it before you remove session handling.
Timeline, and what to do if you ship to clients before July 28
The dates are fixed. The RC locked May 21, 2026. The final spec publishes July 28, 2026. The ten-week window exists so SDK maintainers and client implementers can validate the changes against real workloads, and under the MCP SDK tier system, Tier 1 SDKs (the official Python and TypeScript SDKs among them) are expected to ship support inside that window (RC announcement).
If you are delivering an MCP server to a client before July 28, the safe play is to build it dual-version. Keep the 2025-11-25 session path working for any client that hasn't upgraded, and add the stateless 2026-07-28 path behind a version check on the incoming MCP-Protocol-Version header. Concretely:
# Pseudocode for a dual-version request router.
# Verify the exact API against the official SDK once it ships
# 2026-07-28 support inside the ten-week window.
def route(request):
version = request.headers.get("MCP-Protocol-Version", "2025-11-25")
if version == "2026-07-28":
# Stateless path: no session lookup. Read client info
# from request._meta, route on the Mcp-Method header.
return handle_stateless(request)
else:
# Legacy path: validate Mcp-Session-Id, look up session.
return handle_session(request)
Do not remove the session path on day one. The annotation-only deprecations mean the old features keep working for at least a year, and the feature lifecycle policy guarantees at least twelve months between a deprecation and the earliest possible removal (per the RC). You have room to migrate clients deliberately rather than in a panic.
Which tools are confirmed updating, and where to track it
The protocol's own SDKs are the signal that matters most. The official Tier 1 SDKs are expected to ship 2026-07-28 support before the final date, and a Standards Track change can no longer reach Final status until a matching scenario lands in the MCP conformance suite, so the spec and the SDKs move together rather than drifting apart (RC announcement).
For client-side adoption, the active MCP clients are the ones to watch: Cline on the open-source side, Cursor through its MCP docs, and the automation platforms like Make and self-hosted n8n that expose MCP as a workflow building block. The broader builder community noticed the shift fast. Ben's Bites flagged it on May 26 under the line "MCP comeback in works," tying it to the case that API, CLI, and SDK-first tools are in a strong spot right now (Ben's Bites).
The single best place to track the real state is the draft specification and its changelog, which lists every change against 2025-11-25. Bookmark it, check it the week of July 28, and run your dual-version server against the first SDK release that claims 2026-07-28 support before you delete a line of session code.
Where we land: this is the cleanest break MCP has shipped, and it makes remote servers genuinely cheaper to operate. Start the server migration now if you build them, write everything dual-version through the transition, and let your managed clients pull you the rest of the way after July 28.