MCP Went Stateless: What the 2026-07-28 Spec Actually Breaks

The MCP 2026-07-28 spec drops the initialize handshake, kills session IDs, and renames FastMCP. Here is what breaks, what survives, and how to sequence your migration.

Cover art for MCP Went Stateless: What the 2026-07-28 Spec Actually Breaks

Your MCP server boots on Monday morning and immediately dies with ModuleNotFoundError: No module named 'mcp.server.fastmcp'. A dependency declared mcp>=1.28.1 with no upper bound, the index returned mcp 2.0.0 published on July 28, and the process dies at import because mcp.server.fastmcp is a module 2.0.0 removed. Nothing else in your stack changed. That is the MCP 2026-07-28 spec migration landing in the worst possible way - silently, through an unbounded dependency range.

MCP v2 (protocol revision 2026-07-28) is final. The release candidate was locked on May 21, 2026, SDK maintainers validated it against real workloads during a ten-week window, and the spec was published on July 28, 2026. This is not a point release. The maintainers themselves called it the largest revision since launch, and for once that framing is accurate. Here is what is genuinely new, what is incremental, and where the hype outruns the change.

What the MCP stateless spec actually changes at the wire level

The 2026-07-28 specification converts MCP from a bidirectional stateful protocol into a request/response stateless one. The practical difference: in v1, every session began with an initialize/initialized handshake, and the server issued an Mcp-Session-Id that the client sent back on every subsequent request. That session ID pinned a client to a specific server instance.

That pin is gone. Protocol version and client capabilities now ride along on every request, and a new server/discover call fetches what a server can do. Under the new specification, any request can land on any instance, and a plain round-robin load balancer is enough.

A remote MCP server that previously needed sticky sessions, a shared session store, and deep packet inspection at the gateway can now run behind a plain round-robin load balancer, route traffic on an Mcp-Method header, and let clients cache tools/list responses for as long as the server's ttlMs permits.

That is the concrete infrastructure win. The observability story also improves: W3C Trace Context propagation in _meta is now documented (SEP-414), locking down the traceparent, tracestate, and baggage key names so distributed traces correlate across SDKs and gateways. A trace that starts in a host application can follow a tool call through the client SDK, the MCP server, and whatever the server calls downstream, and show up as a single span tree in an OpenTelemetry-compatible backend.

July 28, 2026spec finalizedafter a ten-week validation window from the May 21 RC
4 SDKson day onePython, TypeScript, Go, and C# shipped v2 on the same date
12 monthsdeprecation runwayRoots, Sampling, and Logging eligible for removal no earlier than July 28, 2027

The SDK changes that will actually break your server

The protocol change is clean. The SDK story has sharp edges.

Python: MCP Python SDK 2.0.0, published 2026-07-28, moved every submodule under mcp.server.fastmcp.* to mcp.server.mcpserver.* and renamed the FastMCP class to MCPServer.

The decorator API carries over

  • so a @mcp.tool() server still looks nearly identical once you update the import. The footwork is small; the import path change is not optional.

TypeScript: v2 does not ship as a new version of @modelcontextprotocol/sdk. On npm it ships as two brand-new packages - @modelcontextprotocol/server and @modelcontextprotocol/client - both at 2.0.0-beta.1, while the old package stays on v1. If your upgrade plan is "bump the version number," you will miss the migration entirely. This is a package-name change, not a version bump. Dependency scanners that only watch @modelcontextprotocol/sdk will report you as up to date while you are, in fact, a full major version behind.

Java: Budget for a lag - it is officially a Tier 2 SDK with up to six months to catch up.

Backward compatibility is real, not aspirational. The Python, TypeScript, and C# v2 SDKs serve both the 2025-11-25 and 2026-07-28 wire formats from the same running server, so existing deployments keep working.

Clients that speak 2026-07-28 fall back to the initialize handshake when they reach a server on 2025-11-25 or earlier, so old servers and new clients keep interoperating.

Running a remote MCP server pre- and post-2026-07-28
Without Beagle
server needs sticky routing, a shared session store, and gateway-level session affinity; each request is tied to an instance via Mcp-Session-Id
With Beagle
any request lands on any instance; a plain round-robin load balancer is enough; clients cache tools/list responses via ttlMs

What is deprecated, and how much time you actually have

Three first-class MCP primitives are deprecated in the 2026-07-28 spec: Roots - the capability for servers to declare filesystem or resource roots; Sampling - the LLM sampling request primitive (servers requesting the client to run inference); Logging - structured log emission from servers to clients.

Roots, Sampling, and Logging are deprecated. They still work, and they will keep working for at least twelve months. New implementations should not adopt them.

The replacements are not mysterious. Roots gives way to plain tool parameters and resource URIs. Sampling - the idea that a server could borrow the client's model - gives way to calling your LLM provider directly; client support was always patchy. Logging gives way to stderr for stdio servers and OpenTelemetry for everything else, and the spec now documents W3C Trace Context propagating through _meta.

Multi Round-Trip Requests (SEP-2322) replaces server-initiated calls like sampling and elicitation. A server returns an InputRequiredResult carrying inputRequests plus an opaque requestState; the client gathers answers and re-issues the original call with inputResponses.

The honest assessment: sampling was a clever idea that almost nobody shipped against. Client support was always inconsistent, and the spec's own blog describes it as a feature that never fully landed in practice. Its deprecation is less of a breaking change and more of a formal acknowledgment that the ecosystem voted with its feet.

The specification includes a feature lifecycle policy: twelve-month deprecation windows before removal. This is the MCP team's commitment that future breaking changes will not be sprung on developers the way this one was.

That last clause is the non-obvious part: the stateless migration is itself the thing that did not get a twelve-month runway. The new deprecation policy applies going forward. Teams that built on Roots or Sampling at least get a year; teams that built session-pinned infrastructure had weeks.

What is genuinely new versus incremental

Not everything in the 2026-07-28 release is a breaking change. Two additions are net-new capability:

Feature What it does Status
MCP Apps Tools return sandboxed HTML via ui:// scheme; server-rendered interactive UI inside the host Formalized extension, ships now
Tasks extension Long-running work via poll-based tasks/get and tasks/update; moved out of experimental core Breaking change for anyone on the 2025-11-25 experimental API
W3C Trace Context in _meta Distributed traces across client, SDK, server, and downstream in one OpenTelemetry span tree New in this release
Extensions framework Reverse-DNS IDs, independently versioned ext-* repos, formal negotiation via capabilities map Formalized; replaces ad-hoc extension mechanism

Tasks' move to the extension is breaking - the experimental 2025-11-25 API does not carry forward, and internal servers built against it need auditing now.

A teammate like Beagle, whose tool calls traverse MCP servers to pull context from Notion or Linear, benefits directly from the tracing change: a failed tool call that previously produced only a timeout now shows up as a named span you can inspect.

Beagle in action#eng-ops, 10:42am
The ask
'Beagle timed out fetching the Linear sprint - can we see what happened?'
Beagle drafts
reads the OpenTelemetry trace, locates the failing server/discover call, drafts a reply with the span ID and the specific tool call that stalled
You approve
you approve; the message posts with a linked trace rather than a guess
Do this in your workspace

MCP stateless migration: common questions

Does upgrading the Python SDK automatically break my server?

Not immediately if you are on an official SDK, but plan the migration deliberately rather than assuming nothing changes. Python, TypeScript, and C# all shipped v2 releases that serve both protocol eras from the same running server, and on the TypeScript SDK the new wire format is opt-in: nothing changes until you configure version negotiation or move to the new HTTP entry point. Upgrading the SDK alone does not silently flip your server's wire format. What does change immediately is any import of mcp.server.fastmcp - that module is gone in 2.0.0.

Are Roots, Sampling, and Logging being removed from MCP?

They are deprecated as of the 2026-07-28 specification (SEP-2577), not removed. Under the new lifecycle policy (SEP-2596), a feature must stay deprecated for at least twelve months from its deprecating revision before it is eligible for removal, so these features remain in the spec through at least July 2027. New servers should avoid adopting them; existing servers have time to plan.

What replaces the FastMCP class in the Python SDK?

FastMCP is renamed to MCPServer. The full list of changes is in the migration guide, which is currently the most complete documentation for v2. The decorator API - @mcp.tool(), @mcp.resource() - carries over unchanged. If you use the standalone fastmcp package from PrefectHQ rather than the official SDK, none of this touches you. That is a separate project on its own 3.x line, and the rename is partly there to stop the two from being mistaken for each other.

Can old clients still talk to a v2 server?

Yes. A v2 server answers the legacy initialize handshake alongside server/discover, so clients on 2025-11-25 keep connecting. The dual-format support is built into the Tier 1 SDKs from day one. The one exception: test against the exact SDK version you ship, since third-party servers that have not updated will not negotiate the new wire format on their own.

Is the Java SDK ready?

Not yet at parity. Java is officially a Tier 2 SDK with up to six months to catch up. If your agent infrastructure is Java-heavy, plan for a lag and pin against a tested v1 version until the Java SDK catches up.

Or just watch me work

Point me at your website.

I will read up on your business and come back with what I would run for you. No account, no card, about a minute.

I only read what is public. Nothing is saved to your name until you say so.

Keep reading

Beagle does this work for you, in your Slack.1,000 free credits. No card.Hire Beagle