MCP Python SDK v2.0.0a2

v2.0.0a2Pre-release
Added 3
  • Add generated per-version protocol types for 2025-11-25 and 2026-07-28 schemas alongside the hand-maintained superset monolith in mcp.types
  • Implement version-gated wire validation that selects the negotiated protocol version's type set at runtime for validating inbound requests, notifications, and results
  • Add dispatcher keyword-only constructor argument to ClientSession to support passing a pre-built dispatcher instead of read/write stream pair
Changed 3
  • Rewrite ClientSession to run on JSONRPCDispatcher receive path instead of inline, allowing server-initiated requests to run concurrently
  • Make validation stricter by returning INTERNAL_ERROR for spec-invalid handler output and rejecting spec-invalid server output at clients
  • Strip fields that only exist in newer spec versions from outbound results before they reach older peers
Fixed 4
  • Fix server-initiated request callbacks blocking the whole session when slow or deadlocking when sending requests themselves
  • Contain raising notification or request callbacks at the dispatcher to prevent them from taking down the connection
  • Implement timed-out or caller-cancelled request handling by sending notifications/cancelled to the peer
  • Fix server-to-client cancellation to actually interrupt the running client callback
Removed 1
  • Remove BaseSession class

Second v2 alpha. Pre-releases are opt-in only; pip install mcp still resolves to the stable 1.x line.

pip install mcp==2.0.0a2
# or
uv add "mcp==2.0.0a2"

See the migration guide for the full list of breaking changes.

Highlights
Full 2026-07-28 types added along with per-version protocol types and version-gated wire validation (#2849)

The SDK now ships three type sets:

  • mcp.types - the hand-maintained superset monolith. This remains the public API you import from; it covers every field from every supported spec version.
  • mcp.types.v2025_11_25 - generated verbatim from the 2025-11-25 schema (also serves earlier versions).
  • mcp.types.v2026_07_28 - generated verbatim from the 2026-07-28 schema.

The generated per-version packages are wired into both ServerRunner and ClientSession via mcp.types.methods, which maps each (method, version) pair to its request/result/notification types. At runtime, the negotiated protocol version selects which generated set is used to validate traffic on the wire:

  • Inbound requests and notifications are validated against the negotiated version's types. A spec method that does not exist at that version returns METHOD_NOT_FOUND; a malformed payload returns INVALID_PARAMS.
  • Inbound results (in both directions) are validated against the negotiated version's result type before being parsed into the monolith type.
  • Outbound results are serialized through the negotiated version's type, so fields that only exist in a newer spec version are stripped before they reach an older peer.

User code keeps working with the monolith mcp.types; the per-version packages are an internal validation layer. 2026-07-28 is modeled but not yet negotiable - SUPPORTED_PROTOCOL_VERSIONS is unchanged in this alpha.

This makes validation stricter than a1: handlers that returned spec-invalid output (for example Tool(inputSchema={}) without "type": "object") now fail with INTERNAL_ERROR, and clients now reject spec-invalid server output that was previously tolerated.

ClientSession now runs on the dispatcher (#2838)

ClientSession has been rewritten to sit on the same JSONRPCDispatcher receive path that ServerRunner adopted in a1, and BaseSession is removed. The public surface (constructor, typed request methods, initialize(), context-manager lifecycle) is unchanged, but the internals fix several long-standing v1 issues:

  • Server-initiated requests (sampling, elicitation, roots) now run concurrently instead of inline in the receive loop, so a slow callback no longer blocks the whole session and a callback that itself sends a request no longer deadlocks.
  • A raising notification or request callback is contained at the dispatcher and no longer takes down the connection.
  • Timed-out or caller-cancelled requests now send notifications/cancelled to the peer.
  • Server-to-client cancellation now actually interrupts the running client callback.

A new keyword-only dispatcher= constructor argument lets you pass a pre-built dispatcher (for example DirectDispatcher for in-process embedding) instead of the read/write stream pair.

What's Changed

Full Changelog: https://github.com/modelcontextprotocol/python-sdk/compare/v2.0.0a1...v2.0.0a2

View original

Upgraded? How did it go?

Discussion