The July 28 MCP revision breaks both eras: what to fix in your server
If you run an MCP server, tomorrow's specification revision touches you. That is true whether you are still on the 2024 HTTP+SSE transport or you migrated to Streamable HTTP last year and assumed you were done. The second group is the one being caught out. Some of the better coverage has already said so; what still dominates the summaries is that the old transport is finally dying, and that is not what happens on July 28.
I went through the draft specification, which is public now and becomes the 2026-07-28 revision tomorrow, and pulled out the parts that change what your server has to return. Where this article quotes the specification, it quotes the draft; if the final text differs tomorrow I will update this page in place rather than leave it wrong.
Quick answer: The 2026-07-28 revision removes protocol-level sessions, theinitializehandshake, the standalone GET stream andLast-Event-IDresumability from Streamable HTTP. Legacy HTTP+SSE is deprecated, not removed, and no client has announced a cutoff. So the servers with real work to do are the 2025-era Streamable HTTP ones.
What actually changes on July 28?
The specification says it plainly in its own note on the Streamable HTTP page:
"Revision 2026-07-28 changed the behavior of Streamable HTTP. Clients must ensure they handle backwards compatibility correctly. Changes included: Removal of the GET stream endpoint. Removal of protocol-level sessions."
Four mechanisms that existed in revisions 2025-03-26 through 2025-11-25 are gone. The spec lists them together: servers could assign a session via the Mcp-Session-Id header, clients could open a standalone SSE stream with HTTP GET, servers could send JSON-RPC requests on SSE streams, and streams were resumable via Last-Event-ID. On the new revision, "None of these mechanisms are part of this revision."
The initialize handshake goes with them. Protocol metadata now rides on every request instead, in _meta.io.modelcontextprotocol/* fields that the transport mirrors into HTTP headers. The spec's own backward-compatibility section describes the old world in the past tense: "Earlier protocol revisions established a connection-scoped session with an initialize handshake and allowed servers to initiate JSON-RPC requests."
That last clause is the deepest change. Under the new message-pattern rules, "servers do not initiate JSON-RPC requests and clients do not send JSON-RPC responses." Sampling, elicitation and roots do not disappear, but they stop being server-initiated requests and become embedded input requests under Multi Round-Trip Requests (MRTR): the server returns an InputRequiredResult containing inputRequests, and the client retries the original call with matching inputResponses.
Does this kill SSE?
No, and the headlines saying otherwise will cost someone a weekend.
SSE is still how a streaming response is delivered. The spec describes the modern transport as: each message is an HTTP POST to a single MCP endpoint, and "replies arrive as a JSON object or a request-scoped SSE stream." What was removed is the standalone GET stream and the ability for a server to push independent requests down it. Request-scoped streaming is core.
The 2024-11-05 HTTP+SSE transport is a separate question, and it is also not removed. It has been deprecated since 2025-03-26, and the deprecated-features registry gives its earliest removal as "Three months after SEP-2596 reaches Final." The same registry ends with a line worth pinning above your desk:
"No features have been removed under this policy yet."
Deprecated features carry a twelve-month floor before they are even eligible for removal. No client vendor has published a date for dropping the legacy transport: Anthropic's connector docs say "Claude supports both Streamable HTTP and the legacy HTTP+SSE transport," and OpenAI's Responses API accepts servers on "either the Streamable HTTP or the HTTP/SSE transport protocols." If you read anywhere that legacy servers stop working tomorrow, that claim has no source behind it.
There is a clock, though, and it is nearer than "no date" suggests. The policy governing all of this, SEP-2596, has already reached Final status, and its transition table sets the HTTP+SSE transport's earliest removal as "Three months after this SEP is Final." The twelve-month floor does not apply to it, because the two grandfathered features "were publicly deprecated well over twelve months before this SEP, so the minimum deprecation window has in practice already been served." Three months from a SEP that went Final in mid-2026 lands in late summer, which is weeks away rather than someday.
Eligibility is not removal, and the SEP is unusually clear about the difference. Removal is "a Core Maintainer decision at release preparation, not an automatic event when the grace period ends," and features "may remain Deprecated, without removal, for much longer than the minimum deprecation window." So nothing breaks on a date you can circle. But if you are still serving the 2024 transport, you are now inside the window where someone could decide, rather than outside it.
What do I actually change in my server?
This is the part the explainers skip. If your server implements only the new revision and an older client turns up, the spec tells you exactly what to return:
- HTTP GET or DELETE to the MCP endpoint: respond with
405 Method Not Allowed. - An
Mcp-Session-Idheader on a request: "ignore it, and do not mint or echo session IDs." - A
Last-Event-IDheader: "ignore it; streams are not resumable."
Three request headers are now required rather than advisory. MCP-Protocol-Version on every POST, Mcp-Method on all requests, and Mcp-Name on tools/call, resources/read and prompts/get. The spec's wording is "These headers are REQUIRED for compliance." A minimal compliant call looks like this:
POST /mcp HTTP/1.1
Content-Type: application/json
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: get_weather
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "get_weather",
"arguments": { "location": "Seattle, WA" },
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientInfo": { "name": "ExampleClient", "version": "1.0.0" }
}
}
}
The header values are not decoration. The MCP-Protocol-Version header must match the io.modelcontextprotocol/protocolVersion field in the body, and if they disagree the server must reject the request with 400 Bad Request and JSON-RPC error -32020, named HeaderMismatch. The reason is a real deployment failure mode: a load balancer routing on the header while the server executes on the body is a security bug waiting to happen.
Four more return codes worth wiring correctly:
- A JSON-RPC notification the server accepts returns
202 Acceptedwith no body. - An unimplemented method returns
404 Not Foundwith JSON-RPC code-32601, which is what distinguishes a modern server from a legacy one that simply has nothing at that path. - An unsupported protocol version returns
400with anUnsupportedProtocolVersionErrorlisting the versions you do support. - An invalid
Originheader returns403 Forbidden. That requirement is not new, but DNS rebinding against local servers is still the most under-defended hole in MCP deployments, which I covered in the MCP security risks AI assistants don't mention.
Two operational details that will save you a support ticket. When you open an SSE stream, send X-Accel-Buffering: no, or nginx will buffer your events and your streaming will look broken. And for long-lived streams, emit a periodic SSE comment line as a keep-alive so intermediaries do not close the connection during quiet periods.
Finally, if you relied on the GET stream for change notifications, the replacement is a request: the client POSTs subscriptions/listen and the response stream stays open carrying the notification types it opted into, such as notifications/tools/list_changed.
What is the second shoe?
Transport is not the only thing deprecated on July 28. The deprecated-features registry adds four entries dated 2026-07-28, each with an earliest removal on or after 2027-07-28:
- Roots, migrating to directories or files passed via tool parameters, resource URIs, or server configuration.
- Sampling, migrating to integrating directly with LLM provider APIs.
- Logging, migrating to
stderron stdio and OpenTelemetry for observability. - Dynamic Client Registration, migrating to Client ID Metadata Documents.
One more migration that is not a deprecation but will break code: Tasks leaves the core specification. It shipped as an experimental core feature in 2025-11-25, and per the release-candidate announcement, "Production use surfaced enough redesign that the right home for it is an extension rather than the specification." If you built against Tasks, that is a move, not a rename.
That last one is the one to put on a roadmap now, because DCR is how a large share of remote MCP servers currently onboard OAuth clients. It is not hypothetical: Capacities, the notes app, documents its hosted MCP server as using "OAuth 2.1 (including PKCE, Dynamic Client Registration, and refresh tokens)." That is a shipping, documented third-party server built on a mechanism that starts its deprecation clock tomorrow. Plenty of others are in the same position, including mine, which I will come back to.
How do clients tell the two eras apart?
If you write a client, the detection order is now specified rather than folklore. Try a modern request first. On 400 Bad Request, inspect the body before concluding anything, because modern servers also return 400 for unsupported versions, missing capabilities and header-validation failures.
- If the body contains a recognized modern JSON-RPC error, the server is modern. Retry with an advertised supported version or fix the request. Do not fall back.
- If the body is empty or unrecognized, fall back to
initializeand continue on the legacy version.
For the 2024-11-05 transport specifically, a 400, 404 or 405 whose body is not a recognized modern error is your cue to issue a GET and expect an endpoint event as the first SSE event.
Where does my own server stand?
Disclosure: Calmara is my product, and running its MCP server through this checklist is the fastest way to show that the migration is real work rather than a press release.
What already holds up. The cloud endpoint is a single POST /mcp that is stateless per request, so there are no sessions to remove. GET and DELETE against it return 405 today, which is what the new revision asks for. You can check both yourself:
curl -s -o /dev/null -w "%{http_code}\n" -X GET https://api.calmara.app/mcp # 405
curl -s -o /dev/null -w "%{http_code}\n" -X POST https://api.calmara.app/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' # 200
What does not, and is now on my list. The OAuth flow still uses RFC 7591 Dynamic Client Registration, so it inherits the migration to Client ID Metadata Documents. The required Mcp-Method and Mcp-Name header validation is not implemented. MRTR is not implemented, which is fine only because the server initiates nothing today. And the legacy /mcp/sse alias is still served for existing connectors, which is allowed and will stay until clients stop needing it.
That is four items on a server that was already on the modern transport, which is the whole point of this article. If you are on the Claude Desktop connector path as a user rather than an operator, none of this requires anything from you; the work sits with whoever runs the server.
FAQ
Does the July 28 revision break my existing MCP server?
Not on July 28. Nothing is removed that day. But a server built for 2025-03-26 through 2025-11-25 does not speak the new revision, because sessions, the initialize handshake, the GET stream and resumability are gone from it. You keep working with clients that negotiate an older version, and you need real changes to serve the new one.
Is SSE removed from MCP?
No. Streaming responses are still delivered as a request-scoped SSE stream. What was removed is the standalone GET stream and the ability for servers to send independent requests on it. The separate 2024-11-05 HTTP+SSE transport is deprecated, not removed.
Do I have to migrate off HTTP+SSE by July 28?
No. It has been deprecated since March 2025, its earliest removal is three months after SEP-2596 reaches Final, and the registry states that no features have been removed under the policy yet. No client vendor has announced a cutoff date. Migrate because it is the right direction, not because of a deadline that does not exist.
What replaces the standalone GET stream?
A subscriptions/listen request. The response to it is an SSE stream that stays open and delivers the change notifications the client subscribed to, such as notifications/tools/list_changed.
What is MRTR?
Multi Round-Trip Requests. Because servers can no longer initiate JSON-RPC requests, sampling, elicitation and roots are returned inside an InputRequiredResult as inputRequests, and the client retries the original call with matching inputResponses.
Is Dynamic Client Registration going away?
It is deprecated as of 2026-07-28, with Client ID Metadata Documents as the documented migration path and an earliest removal in the first revision released on or after 2027-07-28. You have a year, and you should use it rather than discover this in 2027.
What protocol version should my client send?
Whatever version you actually implement, in both the MCP-Protocol-Version header and the body's _meta, and they must match or the server must reject the request with -32020. As of today the current published version is still 2025-11-25; 2026-07-28 becomes current tomorrow.
---
The fastest way to know where you stand is to point three curl calls at your own endpoint: a GET that should return 405, a POST with a mismatched MCP-Protocol-Version header and body value that should return 400 with -32020, and a call to a method you do not implement that should return 404 with -32601. Whatever those three return today is your migration list.
Written by Dan Hagen