MCP's Twelve-Month Deprecation Window Doesn't Cover This Revision
The 2026-07-28 spec adopted a minimum twelve-month deprecation policy and deleted the protocol's session layer in the same release. The policy governs what happens next, not what just happened.
MCP specification revision 2026-07-28 supersedes 2025-11-25, and its
headline is that the protocol became stateless. The initialize and
notifications/initialized handshake is gone. The Mcp-Session-Id header is
gone from the Streamable HTTP transport. Every request now carries its own
protocol version and client capabilities in _meta, under the keys
io.modelcontextprotocol/protocolVersion and
io.modelcontextprotocol/clientCapabilities, and servers must implement a new
server/discover RPC that advertises the versions and capabilities they
support.
The revision is ten days old. What makes it this week's problem rather than
last week's reading is that implementations have started landing behind it:
Cloudflare published its SDK v2 migration path on 6 August, naming
@modelcontextprotocol/server@2.0.0 for stateless servers and
@modelcontextprotocol/client@2.0.0 for clients.
The list everyone is reading is the wrong list
The changelog has a section headed Deprecated. It newly deprecates Roots,
Sampling, Logging, and OAuth Dynamic Client Registration, and reclassifies two
features that were already described as deprecated — the HTTP+SSE transport and
two includeContext values — under a regime that did not exist before. A few
lines below, under governance updates, the revision adopts a feature lifecycle
policy defining three states — Active, Deprecated, Removed — with a minimum
twelve-month window between the middle two.
Read only that and you would conclude you have a year. You do not, because the work is in a different section.
Removed outright in this revision, with no Deprecated state in between: the
initialize/initialized handshake, the Mcp-Session-Id header, ping,
logging/setLevel, notifications/roots/list_changed, the HTTP GET endpoint,
and resources/subscribe with resources/unsubscribe — the last three
replaced by a single subscriptions/listen stream. Also removed: SSE stream
resumability and message redelivery, meaning the Last-Event-ID header and SSE
event IDs. A broken response stream now loses the in-flight request, and the
client must re-issue it as a new request with a new request ID.
The lifecycle policy measures its twelve months from the revision in which a feature is first marked Deprecated. None of those items were ever marked Deprecated. The policy was adopted in the same revision that removed them, so it could not have applied to them — it governs what happens next, not what just happened. The practical shape of that is worth saying plainly: your first migration under this policy is the unbuffered one, and every migration after it has a floor.
That claim is checkable. The deprecated registry lists exactly six features. If
Mcp-Session-Id or the initialize handshake turns up in it, I have misread
the revision and the window does cover this migration.
What the registry says about your actual deadline
Read at changelog level, every one of these deprecations looks like a 2027 problem. The registry is more precise than that, and in one row more urgent.
Four rows — Roots, Sampling, Logging, DCR — list earliest removal as the first revision released on or after 2027-07-28. The column wording matters: earliest removal marks when a feature becomes eligible, and the policy states that the actual removal is a Core Maintainer decision taken during release preparation, that it may happen later, and that features may stay Deprecated for much longer than the minimum window. That is a floor on your notice period, not a date on your calendar.
The row to act on is the oldest one. The HTTP+SSE transport, deprecated since
2025-03-26, carries an earliest removal of three months after SEP-2596 reaches
Final — not July 2027. The feature that has been deprecated longest has the
nearest removal eligibility in the registry. It has also carried a deprecation
notice since March 2025 without being removed, which is the pattern most likely
to have quietly moved it off a migration backlog.
One more number to hold: the twelve-month floor is not absolute. Expedited removal can shorten it for a feature presenting an active security risk with a published advisory and no in-place mitigation, subject to Core Maintainer approval, down to ninety days.
The migration cost, concretely
Cloudflare's guide keeps @modelcontextprotocol/sdk@1.30.0 around for a
temporary legacy lane, routed alongside the stateless one with an
isLegacyRequest() check. Old clients keep working through a default legacy
compatibility path that covers ordinary tools, resources, and prompts, but each
POST gets a fresh server and transport, HTTP GET and DELETE return 405, and no
session state persists. Sessionful behavior — pushed requests, standalone
streams, event replay — needs the explicit legacy handler.
The spec does extend one courtesy across revisions: results now carry a required
resultType, and clients must treat a result from an earlier-protocol server
that omits the field as complete.
The revision's new caching fields deserve more than a performance reading.
tools/list, prompts/list, resources/list, resources/read and
resources/templates/list now require ttlMs and cacheScope on their
results. If your server builds a tool list per user, cacheScope set to
private is the field that stops a shared intermediary serving one tenant's
tools to another. It is a caching hint doing access-control work, and it is
required, not optional.
This is the shape of cost that our argument about the last mile from proof of concept to production keeps landing on: the model did not change, and the integration layer under it was rewritten. A protocol that deletes its session concept is a change-management event with a version number on it.
Verdict
Adopt on a schedule you set. This week, in order:
- Grep your servers and clients for
Mcp-Session-Id,Last-Event-ID,resources/subscribe,logging/setLevel,ping, androots/list_changed. Every hit is unbuffered work with no window behind it. - Grep for Roots, Sampling, Logging, and DCR usage. That goes on the 2027 list, not this quarter's.
- If anything you run still speaks HTTP+SSE, move it first. It has the nearest removal eligibility of anything in the registry.
- The threshold that decides upgrade versus rewrite: if your server holds any state across calls that is not a server-minted handle passed as an ordinary tool argument, you are rewriting, not upgrading.
Turn this into a plan for your team.
One week, fixed fee: a working session with your team, a prioritized use-case backlog, and an ROI model for the opportunities worth chasing.