v2.0.0a3
Pre-releaseThird v2 alpha. Pre-releases are opt-in only; pip install mcp still resolves to the stable 1.x line.
pip install mcp==2.0.0a3
# or
uv add "mcp==2.0.0a3"See the migration guide for the full list of breaking changes.
Warning
The public API is likely to change between alpha releases, and ideally less-so between beta releases.
Highlights
2026-07-28 stateless protocol is now negotiable end to end (#2928, #2950)
The 2026-07-28 spec revision drops the initialize handshake on streamable HTTP: each POST is self-describing (protocol version, client info, and capabilities ride in params._meta) and the server replies with a single JSON-RPC response. Both sides of that path are now wired up.
Server side: ServerRunner is now a pure handler kernel composed by three drivers (serve_one, serve_connection, serve_loop). A new Connection object owns per-peer state with two factories - from_envelope for the per-request stateless path and for_loop for handshake-driven connections - so protocol_version is always set and the old stateless: bool flag is gone from ServerRunner, ServerSession, and Server.run(). The streamable-HTTP session manager routes by header: known handshake versions go to the legacy transport; everything else hits a new per-POST entry that classifies, builds a Connection.from_envelope, and drives serve_one. server/discover is auto-derived from registered handlers, and lifespan is entered once at manager startup in both modes.
Client side: ClientSession gains .discover() and .adopt() alongside .initialize(), each of which installs an outbound stamp closure at connect time so the send path has no era branch. Client gains mode='legacy'|'auto'|<version> and prior_discover=; mode='auto' probes server/discover and falls back to initialize on -32601 or timeout. The streamable-HTTP transport is now version-agnostic (per-message headers arrive via CallOptions), and an in-process modern_on_request driver lets Client(server, mode='auto') run the stateless path against an in-memory server.
LATEST_PROTOCOL_VERSION is now "2026-07-28". SUPPORTED_PROTOCOL_VERSIONS is deprecated in favour of HANDSHAKE_PROTOCOL_VERSIONS and MODERN_PROTOCOL_VERSIONS.
Protocol types split into a standalone mcp-types package (#2973)
The wire types now ship as a separate mcp-types distribution (imported as mcp_types) that depends only on pydantic and typing-extensions. Tooling and lightweight clients can serialize and validate MCP traffic without pulling in httpx, starlette, uvicorn, or the rest of the transport stack.
mcp.types and mcp.shared.version are removed; import from mcp_types and mcp_types.version instead. The top-level from mcp import Tool re-exports are unchanged. The two packages are version-locked and published together from the same tag.
Multi-round tool calls: InputRequiredResult plumbed through both sides (#2967, #2968, #2974)
The lowlevel Server on_* return types are widened to admit InputRequiredResult, and a subscriptions/listen handler slot is added. On the client, ClientSession.call_tool gains input_responses= and request_state= retry kwargs and returns CallToolResult | InputRequiredResult; Client.call_tool and ClientSessionGroup.call_tool are overloaded on a new allow_input_required flag so existing callers keep their CallToolResult return type. ClientSession.send_request now accepts a TypeAdapter for union result parsing.
ServerMiddleware reshaped to (ctx, call_next) and OpenTelemetryMiddleware added (#2941, #2970)
ServerMiddleware.__call__ goes from (ctx, method, params, call_next) to (ctx, call_next); method and raw params now live on ServerRequestContext, and call_next(ctx) lets middleware rewrite the inbound message via replace(ctx, params=...) before the handler runs. A new context-tier OpenTelemetryMiddleware spans both requests and notifications and sets the OpenTelemetry GenAI semantic-convention attributes.
OAuth client conformance: RFC 9207, SEP-837, SEP-2350, SEP-2352 (#2921, #2930, #2931, #2933)
The OAuth client now validates the iss authorization-response parameter (RFC 9207), sends application_type during Dynamic Client Registration (SEP-837), unions previously requested scopes on step-up re-authorization (SEP-2350), and binds client credentials to the authorization server that issued them (SEP-2352). #2936 and #2946 harden the edge cases (refresh-token retention on non-rotating refresh, same-origin issuer binding).
Roots, sampling, and logging methods deprecated per SEP-2577 (#2926)
The user-facing methods for roots, sampling, and logging/setLevel are now marked with typing_extensions.deprecated. The deprecation is advisory only - capability negotiation and wire behaviour are unchanged, and everything keeps working for sessions negotiating 2025-11-25 or earlier.
What's Changed
- Pass a list to parametrize in test_docs_examples (pytest 9.1.0 compat) by @maxisbey in #2890
- docs: add AI-assisted contribution policy to CONTRIBUTING.md by @maxisbey in #2887
- Resolve protocol version per request and expose it as ctx.protocol_version by @maxisbey in #2886
- tests/interaction: era-axis machinery for the requirements manifest by @maxisbey in #2909
- ci(conformance): add 2026-07-28 carried-forward leg + bump harness to 0.2.0-alpha.4 by @maxisbey in #2911
- Re-vendor 2026-07-28 schema and absorb spec #2907 error-code renumber by @maxisbey in #2912
- Relax monolith ElicitRequestURLParams.elicitation_id for 2026-07-28 by @maxisbey in #2913
- First end-to-end 2026-07-28 stateless tools/call (experimental entry + ClientSession pin) by @maxisbey in #2917
- Add uv ecosystem to dependabot and drop weekly lockfile workflow by @Kludex in #2919
- Return -32602 for resource not found (SEP-2164) by @Kludex in #2920
- fix: correct MCPServer call_tool result type by @fengjikui in #2816
- Ignore pre-2026 protocol_version pins at the StreamableHTTP transport by @maxisbey in #2923
- Preserve empty URL paths on OAuth metadata models by @Kludex in #2925
- Validate the
issauthorization-response parameter (RFC 9207 / SEP-2468) by @Kludex in #2921 - ci(conformance): bump harness to 0.2.0-alpha.5 preview by @maxisbey in #2927
- Document
redirect_uriwire-format change in OAuth migration note by @Kludex in #2929 - Send
application_typeduring Dynamic Client Registration (SEP-837) by @Kludex in #2930 - Pass json-schema-ref-no-deref conformance scenario (SEP-2106) by @Kludex in #2924
- Deprecate roots, sampling, and logging methods per SEP-2577 by @Kludex in #2926
- Union previously requested scopes on step-up re-authorization (SEP-2350) by @Kludex in #2931
- Move scope step-up test to top-level function by @Kludex in #2932
- Bind client credentials to their authorization server (SEP-2352) by @Kludex in #2933
- Server-side 2026-07-28 stateless support: classifier, driver split, server/discover by @maxisbey in #2928
- OAuth client: harden SEP-2352/SEP-2350 edge cases; fix conformance comment by @maxisbey in #2936
- Slim ServerMiddleware to
(ctx, call_next)and addOpenTelemetryMiddlewareby @Kludex in #2941 - OAuth client: keep refresh_token on non-rotating refresh; restore same-origin issuer binding by @maxisbey in #2946
- Buffer per-request StreamableHTTP streams to avoid serial-router head-of-line block by @maxisbey in #2934
- lowlevel Server: widen on_* return types for InputRequiredResult; add subscriptions/listen slot by @maxisbey in #2967
- Client-side 2026-07-28 support: .discover()/.adopt() + Client(mode=); request-metadata green by @maxisbey in #2950
- Add GenAI semantic-convention attributes to OpenTelemetryMiddleware by @Kludex in #2970
- Stop flagging snake_case is_error results as tool errors in OTel span by @Kludex in #2971
- Client call_tool: input_responses/request_state retry params; InputRequiredResult via allow_input_required by @maxisbey in #2968
- Split protocol types into a standalone
mcp-typespackage by @Kludex in #2973 - Set Development Status classifier to Production/Stable by @maxisbey in #2975
- Conformance burn-down: server-side InputRequiredResult, Mcp-Method/Name validation, x-mcp-header filter (14 scenarios → green) by @maxisbey in #2974
New Contributors
- @fengjikui made their first contribution in #2816
Full Changelog: v2.0.0a2...v2.0.0a3