Second v2 beta. Pre-releases are opt-in only; pip install mcp still resolves to the stable 1.x line.
pip install mcp==2.0.0b2
# or
uv add "mcp==2.0.0b2"The documentation has the full tutorial and API reference, and the migration guide covers coming from v1. Stable v2 is still targeted for 2026-07-28 alongside the spec release - keep pinning an exact version.
Highlights
httpx is replaced by httpx2 (#2972)
The SDK's HTTP stack now runs on httpx2 (>=2.5.0), the next-generation httpx fork with SSE support built in, replacing httpx + httpx-sse. Most code needs no changes; if you pass your own http_client into a transport, change the import to httpx2. Runtime behavior that changes:
- TLS verification uses the operating system trust store (via
truststore) instead of certifi's bundle.SSL_CERT_FILE/SSL_CERT_DIRare honored first. - Loggers are renamed:
httpx->httpx2,httpcore.*->httpcore2.*- update logging filters that match on those names. - SSE GET streams send
Accept: application/json, text/event-stream(previously exactlytext/event-stream).
Client-side subscriptions/listen (#3047)
The client half of subscriptions/listen (SEP-2575), promised in the b1 notes: one context manager, async for consumption, typed events.
async with client.listen(tools_list_changed=True, resource_subscriptions=["note://todo"]) as sub:
print(sub.honored) # the subset the server agreed to deliver
async for event in sub:
match event:
case ToolsListChanged():
tools = await client.list_tools()
case ResourceUpdated(uri=uri):
body = await client.read_resource(uri)Entering waits for the server's acknowledgment, so sub.honored is always populated and pre-ack failures raise instead of degrading silently.
Request cancellation works on the 2026 transports (#3046)
Cancelling or timing out a client request now actually stops it: over streamable HTTP the request's own POST/SSE stream is closed (the spec's cancellation signal), and over stdio the client sends notifications/cancelled. Callers can also supply the request id for a call - the seam the listen driver builds on.
Resolvers can sample and list roots (#3049)
Resolver dependency injection now covers all three multi-round-trip request kinds (SEP-2322): a dependency can return Sample(...) or ListRoots() in addition to Elicit(...), so a tool can ask the client's LLM or fetch its roots mid-call, on both protocol eras.
Notes
- Tool-name validation now rejects names with a trailing newline (#3076).
- The tasks extension is still in review and will ship in a later pre-release.
- If you install under uv's
exclude-newercooldown:mcppinsmcp-typesto the exact same version, so exempt both packages -exclude-newer-package = { mcp = false, mcp-types = false }.
What's Changed
- De-flake conformance CI: solo re-verification, spawn-storm reduction, result artifacts by @maxisbey in #3043
- Harden the dual-era stream loop's era-lock and rejection semantics by @maxisbey in #3040
- docs: restructure into topical sections and add the four most-asked-for pages by @maxisbey in #3044
- docs: add a "What's new in v2" page by @maxisbey in #3054
- docs: modernize the site theme by @maxisbey in #3057
- docs: restructure the migration guide around topical groups with a navigation layer by @maxisbey in #3058
- Make client-side cancellation work over the 2026 transports by @maxisbey in #3046
- Extend resolver DI to sampling and roots requests by @maxisbey in #3049
- Share one event loop per test module to stop Windows socketpair churn by @maxisbey in #3070
- docs: pin mkdocs<2 and silence the mkdocs-material advisory banner in CI by @maxisbey in #3072
- Add the client-side subscriptions/listen driver by @maxisbey in #3047
- Gate the test matrix and retry setup-uv's flaky manifest fetch by @maxisbey in #3080
- ci: pick the docs-preview toolchain from the PR checkout by @maxisbey in #3081
- docs: replace MkDocs with Zensical by @Kludex in #3073
- fix: reject trailing newline in tool-name validation by @Otis0408 in #3076
- Replace httpx and httpx-sse with httpx2 by @Kludex in #2972
New Contributors
Full Changelog: v2.0.0b1...v2.0.0b2