Some months, the AI news is just a trickle of point releases. But this past month was like a firehose. The protocol that connects agents to your tools got its biggest rewrite since inception, and Anthropic, OpenAI, Google, Meta, Moonshot, and a brand-new lab founded by a former OpenAI CTO all shipped new models in a single month.
Besides the models, the rest of the Python ecosystem was equally active. The major scientific libraries dropped support for 3.13t and settled on 3.14t as their free-threaded target. Python 3.15 shipped its final beta, the JIT team responded to the Steering Council’s ultimatum, the PSF opened nominations for its board and the first-ever Packaging Council, and Astral shipped breaking minors of uv and Ruff. The MCP rewrite comes first.
Join Now: Click here to join the Real Python Newsletter and you’ll never miss another Python tutorial, course, or news update.
MCP Drops Sessions and Goes Stateless
Two things landed on July 28, and together they make this the most disruptive month MCP has had since it launched. The 2026-07-28 specification was finalized with a revision that changes how servers are deployed, and the Python SDK shipped a 2.0 the same day, renaming the class most Python servers are built on.
What the New Spec Changes
The main change is that the protocol is now stateless. A client used to open with a handshake and then carry a session ID through the rest of the conversation. Both are 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. If you only call MCP servers, then the stateless switch is what affects you the most.
If you ship an MCP server, then your migration list looks like this:
- Remove the session machinery: The handshake and the session header are both gone, so anything you built to track a client between requests goes with them.
- Validate the
Mcp-MethodandMcp-Nameheaders: Clients now send them so gateways can route without cracking open the request body, and your server has to check that they match the request. - Change your missing-resource error: Use the standard JSON-RPC invalid-params code,
-32602, instead of MCP’s own-32002. - Rework your server-initiated requests: Roots, Sampling, and Elicitation no longer call back to the client. Instead, your server returns a result that the client uses to make a follow-up request, which is the biggest rewrite on this list.
- Move off the experimental Tasks API: Tasks have graduated from the core spec to an extension and have gained a new lifecycle along the way.
Roots, Sampling, and Logging all entered formal deprecation, and all three keep working for now. The spec also adopted a deprecation policy promising at least a year’s notice before anything is removed, with a 90-day floor reserved for active security risks. That’s more warning than this ecosystem has offered before.
Authorization also hardened, picking up issuer validation and issuer-bound credentials on top of its OAuth 2.0 foundation.
Extensions, which existed before without any process around them, finally got one: namespaced identities and independent release cycles. That’s what let Tasks move out of the core without dragging the whole protocol along, and MCP Apps now arrives as an official extension under that process. A server can send interactive HTML that the host renders in a sandboxed iframe, so a tool call returns a real interface instead of a wall of text.
Treat third-party MCP servers with the same scrutiny you’d give any dependency. The official registry verifies who published a server through GitHub or DNS ownership, but there’s still no code-signing requirement and no review of what a server actually does, and a server you install gets to describe its own tools to your agent.
The Python SDK Renames FastMCP
The spec is only part of the story if you write Python. The MCP Python SDK reached 2.0.0 alongside it, and pip install mcp now provides the 2.x line.
The first change you’ll notice is a rename. FastMCP is now MCPServer, with no alias and no deprecation shim:
# Before, on mcp 1.x
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("Demo")
# After, on mcp 2.x
from mcp.server.mcpserver import MCPServer
mcp = MCPServer("Demo")
The rest of 2.0 is broader than the rename suggests:
- Wire types are snake_case now:
result.isErroris nowresult.is_error, andtool.inputSchemais nowtool.input_schema. These types have also moved into a separatemcp-typespackage, althoughmcp.typesstays as a permanent alias. - One
Clientreplaces three layers: The old arrangement of a transport, aClientSession, and aninitialize()call now collapses into a single object that connects to a URL, a stdio subprocess, or an in-memory server object for tests. httpxis nowhttpx2: The SDK moved to the next-generation HTTP client, which is worth knowing if you pinhttpxelsewhere in your dependency tree.- Synchronous handlers run on worker threads: They no longer block the event loop. Your handler code doesn’t change, but
asyncio.get_running_loop()now raises inside them. McpErroris nowMCPError: It’s the same acronym capitalization asMCPServer, so anyexcept McpErrorclause needs the new spelling.
One MCPServer serves both protocol eras, so 2025-era clients keep working against a migrated server with nothing to configure. The 1.x line moves to maintenance mode with security fixes only, so if you’re not ready this month, then pin mcp>=1.28,<2 and come back to it.