---
name: Python SDK
slug: mcp-python-sdk
type: github
source_url: https://github.com/modelcontextprotocol/python-sdk
organization: Model Context Protocol
organization_slug: modelcontextprotocol
total_releases: 65
latest_version: v2.3.0
latest_date: 2026-10-02
last_updated: 2026-10-24
tracking_since: 2024-11-20
canonical: https://releases.sh/modelcontextprotocol/mcp-python-sdk
organization_url: https://releases.sh/modelcontextprotocol
---

<Release version="v2.3.0" date="October 2, 2026" published="2026-10-02T22:02:27.000Z" url="https://github.com/modelcontextprotocol/python-sdk/releases/tag/v2.3.0">
`pip install -U mcp`. Docs: https://py.sdk.modelcontextprotocol.io/

Mostly fixes, plus three new options. A few things behave differently, so skim these first:

## Behaviour changes

**`httpx2>=2.10.0` is now required** (#3600)
- It was `>=2.5.0`. The new `max_sse_event_size` option needs it.
- Nothing to do unless you pin `httpx2` below 2.10.

**A tool with an invalid `x-mcp-header` annotation fails at registration** (#3620)
- `@mcp.tool()`, `add_tool` and `Tool.from_function` raise `InvalidSignature`, naming the tool and the problem.
- Until now the server started, and 2026-07-28 clients silently dropped the tool from their listing.
- Refused: anything other than a plain `str`, `int` or `bool` parameter (so also `str | None`, `float`, lists and enums), a header name that isn't a valid token, and two names that differ only by case.
- For an optional header parameter, give the schema directly: `Annotated[str | None, WithJsonSchema({"type": "string", "x-mcp-header": "Region"})] = None`.

**Empty `_meta` and `params` are no longer sent** (#3628)
- On 2025-11-25 and earlier connections, 2.x sent `"_meta": {}` on every request. Some servers reject that. It is now left out, as in v1.
- `ping` and list requests without a cursor go out with no `params` member.
- On the receiving side `ctx.meta` is `None` rather than `{}`, and middleware sees `ctx.params` as `None` for a request without params.
- 2026-07-28 connections are unchanged.

**`initialize` leaves out `experimental` when none is configured** (#3614)
- It used to send `"experimental": {}`. `server/discover` already left it out.
- Client code reading `capabilities.experimental` on a legacy connection should handle `None`.

**`Mcp-Param-*` validation looks the tool up by name** (#3630)
- `MCPServer` no longer runs `tools/list` for every `tools/call`, so middleware no longer sees that extra request.
- The registered schema is what gets checked. Middleware that filters or rewrites `tools/list` no longer affects it.

**An interactive OAuth login no longer counts against request timeouts** (#3635)
- The timeout pauses while `OAuthClientProvider` waits on `redirect_handler` and `callback_handler`.
- This fixes `Client(mode="auto")` settling on `2025-11-25` when the login took longer than 10 seconds.
- A request timeout no longer ends a login nobody finishes. Put a limit inside `callback_handler` if you need one.

## New

- `max_sse_event_size=` on `streamable_http_client` and `StreamableHttpParameters`. The default stays 1 MiB per SSE event; raise it, or pass `None`, for larger tool results (#3600).
- `MCPServer(subscriptions=False)` stops serving `subscriptions/listen` and advertises `listChanged` and `subscribe` as false (#3626).
- `Server(get_tool_input_schema=...)` lets a low-level server supply a tool's schema for header validation without running its `tools/list` handler (#3630).
- `Client.call_tool` re-lists the tools and retries once after a `HeaderMismatch` (`-32020`) rejection (#3627).

## Fixes

- `ctx: Context[AppState]` works on prompts and resource templates, not only on tools (#3624).
- An explicit `"structuredContent": null` is checked against the output schema instead of being treated as missing (#3621).
- A `progress_callback` that raises no longer fails the call on an in-process `Client(server)` (#3623).
- Client OpenTelemetry spans record JSON-RPC error responses. With `mode="auto"`, connecting to a server without `server/discover` now shows one `ERROR` span for the probe (#3629).
- `stdio_client` resolves the executable off the event loop on Windows (#3510).

## Docs

- New pages: [Cancellation](https://py.sdk.modelcontextprotocol.io/handlers/cancellation/) and [Header parameters](https://py.sdk.modelcontextprotocol.io/advanced/header-parameters/), plus a middleware tutorial.
- All twelve translations are refreshed (#3636).

## What's Changed
* Detect event-loop blocking in tests by @Kludex in https://github.com/modelcontextprotocol/python-sdk/pull/3510
* Bump httpcore2 from 2.5.0 to 2.10.0 by @dependabot[bot] in https://github.com/modelcontextprotocol/python-sdk/pull/3482
* Ask cubic for a review when the intake gate lets a PR back in by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3489
* docs: remove v2 notice from top of README by @claude[bot] in https://github.com/modelcontextprotocol/python-sdk/pull/3604
* Bump anyio from 4.10.0 to 4.14.2 by @dependabot[bot] in https://github.com/modelcontextprotocol/python-sdk/pull/3547
* Make the deeply nested body test independent of stack size by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3610
* Fall back to an NTFS junction when the symlink escape test can't create a symlink by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3609
* Group Dependabot security updates for uv dependencies by @Kludex in https://github.com/modelcontextprotocol/python-sdk/pull/3611
* Expose an SSE event size limit in Streamable HTTP clients by @Kludex in https://github.com/modelcontextprotocol/python-sdk/pull/3600
* Bump the github-actions group with 5 updates by @dependabot[bot] in https://github.com/modelcontextprotocol/python-sdk/pull/3612
* docs: add a middleware tutorial that refuses tool calls by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3613
* Omit an unset experimental capability from the initialize result by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3614
* Document when a caller-supplied request id can be minted again by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3619
* Document the timeout a hand-built httpx2 client needs by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3618
* Reject a tool with an invalid x-mcp-header annotation at registration by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3620
* Validate an explicit null structuredContent against the output schema by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3621
* Contain a raising progress callback on the in-process dispatcher by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3623
* Keep the live Context when a prompt or template annotates Context[T] by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3624
* Describe the ID-JAG confidential-client rule as SDK policy, not a SEP-990 requirement by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3622
* Let MCPServer opt out of serving subscriptions/listen by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3626
* Document how a handler deals with cancellation by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3625
* Omit an empty _meta and empty params from outbound requests by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3628
* Record JSON-RPC error responses on the client OpenTelemetry span by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3629
* Retry a tool call once after a HeaderMismatch rejection by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3627
* Look the tool schema up by name for Mcp-Param-* validation instead of running tools/list by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3630
* Bump urllib3 from 2.7.0 to 2.8.0 by @dependabot[bot] in https://github.com/modelcontextprotocol/python-sdk/pull/3607
* Let a newer Deploy Docs run cancel the one in progress by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3633
* Link What's new to the Header parameters page by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3632
* Keep inline-snapshot disabled when pytest runs in a terminal by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3634
* Stop counting an interactive OAuth login against request timeouts by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3635
* docs: refresh translations for recent English changes by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3636


**Full Changelog**: https://github.com/modelcontextprotocol/python-sdk/compare/v2.2.0...v2.3.0
</Release>

<Release version="v2.2.0" date="September 7, 2026" published="2026-09-07T15:53:57.000Z" url="https://github.com/modelcontextprotocol/python-sdk/releases/tag/v2.2.0">
`pip install -U mcp`. Docs: https://py.sdk.modelcontextprotocol.io/

A few defaults changed in this release. If you run a server or client on 2.x, skim these first:

## Behaviour changes

**HTTP client redirects are only followed within the endpoint's origin** (#3397)
- `Client("https://...")`, `streamable_http_client` and `sse_client` follow a redirect only if it stays on the same scheme, host and port (or upgrades `http` to `https` on the same host).
- A redirect anywhere else is not followed: the call fails with `MCPError` and the session stays usable (an SSE connect fails with `httpx2.HTTPStatusError`). If that other URL is the server you meant, use it as the endpoint URL.
- The `follow_redirects` setting on an `httpx2.AsyncClient` you pass in is no longer used for MCP requests, so you don't need it for the trailing-slash redirect any more.
- The OAuth providers apply the same rule to their own requests.

**Idle Streamable HTTP sessions now expire (legacy <=2025-11-25 spec(** (#3395)
- A stateful session with nothing in flight for 30 minutes is closed. The client's next request gets a 404 and it has to initialize again.
- Clients that keep the GET stream open (the SDK's `Client` does) are not affected. Neither are stateless servers or 2026-07-28 connections.
- A server also holds at most 10 000 sessions at once; beyond that, new sessions get a 503.
- To turn either off: `mcp.run(transport="streamable-http", session_idle_timeout=None, max_sessions=None)` (also on `streamable_http_app()` and `run_streamable_http_async()`).

**The OAuth client checks the authorization server's `issuer` on the legacy path too** (#3398)
- For servers without protected resource metadata, authorization server metadata whose `issuer` isn't the server's own origin is now rejected with `OAuthFlowError: Authorization server metadata issuer mismatch`. The protected-resource-metadata path has done this since 2.0.
- A 403 that isn't an `insufficient_scope` challenge is returned to the caller instead of retried.
- If protected resource metadata can't be fetched because of a 5xx/429, the flow now stops instead of falling back to the legacy endpoints.

**Two new `MCPDeprecationWarning`s** (#3435, #3447)
- `ClientCredentialsOAuthProvider` / `PrivateKeyJWTOAuthProvider` without `issuer=`. Pass your authorization server's issuer URL; 3.0 will require it.
- `AuthSettings` with `resource_server_url` set but `validate_token_resource` unset. Set it to `True` or `False`; 3.0 defaults it to `True`.
- Both keep working as before in 2.x; this mostly matters if your tests turn warnings into errors.

## New

- `AuthSettings.validate_token_resource`: only accept tokens your `TokenVerifier` reports as issued for this server (#3447).
- `issuer=` on `ClientCredentialsOAuthProvider` and `PrivateKeyJWTOAuthProvider` (#3398).
- `session_idle_timeout=` and `max_sessions=` on the Streamable HTTP server entry points (#3395).

## Fixes

- A client `DELETE` frees its session immediately, and a refused opening request no longer leaves a session behind (#2455, #3228, #3300).
- `$ref`s in a tool's `outputSchema` resolve within that schema only; an unresolvable one surfaces as `RuntimeError: Invalid schema for tool ...` (#3394).

## Known gaps

The tasks extension (SEP-2663), DPoP (SEP-1932) and the `jwt-bearer` grant are not implemented yet; https://github.com/modelcontextprotocol/python-sdk/blob/main/ROADMAP.md tracks them.


## What's Changed
* Gate draft PRs too and rewrite the auto-close comment by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3378
* Resolve tool output-schema references within the schema document only by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3394
* Expire idle Streamable HTTP sessions by default and cap concurrent sessions by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3395
* Validate the authorization server metadata issuer on every discovery path by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3398
* Deprecate constructing the pre-provisioned OAuth clients without an issuer by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3435
* Exercise the SEP-2575 stateless probes and SEP-2243 resource/prompt headers in the conformance fixtures by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3442
* Bump the github-actions group with 6 updates by @dependabot[bot] in https://github.com/modelcontextprotocol/python-sdk/pull/3424
* Move the docs-preview workflow scripts out of the YAML into .github/scripts by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3446
* Skip automatic docs previews for fork PRs and drop the setup-uv retry steps by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3445
* Follow redirects only within the MCP endpoint's origin by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3397
* Bump pymdown-extensions from 11.0 to 11.0.1 by @dependabot[bot] in https://github.com/modelcontextprotocol/python-sdk/pull/3285
* Bump the locked versions of eight dev and test dependencies by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3449
* Keep following a relative redirect when the endpoint URL carries userinfo by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3450
* Add AuthSettings.validate_token_resource to check a bearer token's resource by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3447
* docs: stop presenting the in-memory client as the way to connect by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3443
* docs: ask for AI disclosure on comments too by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3459
* docs: refresh translations, and translate pages in parallel by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3458
* Replace RootModel wrappers with type aliases and TypeAdapter validation by @Kludex in https://github.com/modelcontextprotocol/python-sdk/pull/3470


**Full Changelog**: https://github.com/modelcontextprotocol/python-sdk/compare/v2.1.1...v2.2.0
</Release>

<Release version="v1.30.0" date="September 7, 2026" published="2026-09-07T14:03:59.000Z" url="https://github.com/modelcontextprotocol/python-sdk/releases/tag/v1.30.0">
Maintenance release of the 1.x line. 2.x is the current line; 1.x docs are at https://py.sdk.modelcontextprotocol.io/v1/.

A few defaults changed in this release. If you run a server or client on 1.x, skim these first:

## Behaviour changes

**HTTP client redirects are only followed within the endpoint's origin** (#3448)
- `streamable_http_client` and `sse_client` follow a redirect only if it stays on the same scheme, host and port (or upgrades `http` to `https` on the same host).
- A redirect anywhere else now fails the request with `httpx.HTTPStatusError`. If that other URL is the server you meant, use it as the endpoint URL.
- The `follow_redirects` setting on an `httpx.AsyncClient` you pass in is no longer used for MCP requests, so you don't need it for the trailing-slash redirect any more.
- `OAuthClientProvider` applies the same rule to its own requests.

**Idle Streamable HTTP sessions now expire** (#3426)
- A stateful session with nothing in flight for 30 minutes is closed. The client's next request gets a 404 and it has to initialize again.
- Clients that keep the GET stream open (the SDK's client does) are not affected.
- A server also holds at most 10 000 sessions at once; beyond that, new sessions get a 503.
- To turn either off: `FastMCP(..., session_idle_timeout=None, max_sessions=None)`.

**The OAuth client checks the authorization server's `issuer`** (#3431)
- Authorization server metadata whose `issuer` doesn't match the server it was fetched for is now rejected with `OAuthFlowError: Authorization server metadata issuer mismatch`.
- Client registrations are now remembered per issuer; if the server later points at a different authorization server, the client registers again.
- If protected resource metadata can't be fetched because of a 5xx/429, the flow now stops instead of falling back to the legacy endpoints.

**Two new `DeprecationWarning`s** (#3431, #3451)
- `ClientCredentialsOAuthProvider` / `PrivateKeyJWTOAuthProvider` without `issuer=`. Pass your authorization server's issuer URL.
- `AuthSettings` with `resource_server_url` set but `validate_token_resource` unset. Set it to `True` or `False`.
- Both keep working as before in 1.x; this mostly matters if your tests turn warnings into errors.

## New

- `AuthSettings.validate_token_resource`: only accept tokens your `TokenVerifier` reports as issued for this server (#3451).
- `issuer=` on `ClientCredentialsOAuthProvider` and `PrivateKeyJWTOAuthProvider` (#3431).
- `session_idle_timeout=` and `max_sessions=` on `FastMCP` (#3426).


## What's Changed
* [v1.x] Resolve tool output-schema references within the schema document only by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3396
* [v1.x] Expire idle Streamable HTTP sessions by default and cap concurrent sessions by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3426
* [v1.x] Validate the authorization server metadata issuer on every discovery path by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3431
* [v1.x] Follow redirects only within the MCP endpoint's origin by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3448
* [v1.x] Add AuthSettings.validate_token_resource to check a bearer token's resource by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3451


**Full Changelog**: https://github.com/modelcontextprotocol/python-sdk/compare/v1.29.1...v1.30.0
</Release>

<Release version="v2.0.1" date="August 26, 2026" published="2026-08-26T10:42:44.000Z" url="https://github.com/modelcontextprotocol/python-sdk/releases/tag/v2.0.1">
One off backport of the FastMCP import warning for `2.0.x`, this is due to a lot of people running into this error and making issues on other repos about it. Ideally either pin `mcp<2` or upgrade to 2.

## What's Changed
* [v2.0.x] Point imports of mcp.server.fastmcp at the migration guide by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3393


**Full Changelog**: https://github.com/modelcontextprotocol/python-sdk/compare/v2.0.0...v2.0.1
</Release>

<Release version="v2.1.1" date="August 25, 2026" published="2026-08-25T15:58:21.000Z" url="https://github.com/modelcontextprotocol/python-sdk/releases/tag/v2.1.1">
## What's Changed
* Point imports of mcp.server.fastmcp at the migration guide by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3388


**Full Changelog**: https://github.com/modelcontextprotocol/python-sdk/compare/v2.1.0...v2.1.1
</Release>

<Release version="v2.1.0" date="August 24, 2026" published="2026-08-24T19:00:24.000Z" url="https://github.com/modelcontextprotocol/python-sdk/releases/tag/v2.1.0">
## Highlights

- `Client` accepts `StdioServerParameters` directly: `Client(StdioServerParameters(command="uv", args=["run", "server.py"]))` (#3321).
- Prompt messages accept `Image` and `Audio`, prompt functions may return bare content blocks, and `Message` / `UserMessage` / `AssistantMessage` are exported from `mcp.server.mcpserver` (#3320).
- The 4 MiB request body limit now also covers the SSE transport and the OAuth endpoints; `SseServerTransport` and `MCPServer.sse_app()` take `max_request_body_size`, and the SSE message endpoint answers 405 to non-POST requests (#3336).

## Behaviour changes to be aware of

- Handler exceptions (#3314): an unexpected exception from a tool, resource or prompt handler is logged once at ERROR with its traceback, and the client now sees only `Error executing tool <name>` (or the resource/prompt equivalent) rather than the exception text. Raise `ToolError` / `ResourceError` when the message is meant for the model; those still reach the client and are logged at INFO without a traceback.
- Content-block return annotations (#3320): a tool annotated to return `TextContent`, `EmbeddedResource`, `Image`, `Audio`, or lists/unions of them no longer advertises `outputSchema` or returns `structuredContent`; its `content` is unchanged. Pass `structured_output=True` to keep the previous shape.

## Fixes

- TypedDict tool results: `NotRequired` keys are omitted instead of serialized as `null`, and registration no longer fails on Python 3.10 (#3224, #3227); recursive return types get an object-rooted `outputSchema` that pre-2026 clients accept (#3337).
- 2026-07-28 over HTTP: a POSTed notification such as `notifications/cancelled` is acknowledged with 202 instead of rejected with 400 (#3324).
- Pre-2026 sessions ignore cache-hint fields from later revisions instead of failing `list_tools()` (#3223), and accept boolean sub-schemas in tool schema `properties` (#3353).
- `mcp install` reads and preserves a Claude Desktop config containing non-ASCII text on any Windows code page (#3296).

## What's Changed
* Retire wording tied to pre-2.0 milestones by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3211
* Describe the maintenance line without hardcoding 1.28 by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3212
* Ask which release line a bug report is on by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3213
* Link the released 2026-07-28 spec and point migrators at /v1/ by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3214
* Bump conformance harness to 0.2.0-alpha.11 by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3282
* Read UTF-8 test fixtures with explicit encoding by @ShuQingDollarVoyager in https://github.com/modelcontextprotocol/python-sdk/pull/3245
* Pin each conformance leg to a spec-revision wire by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3304
* docs: publish translated docs in twelve languages and the tool that maintains them by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3280
* Pin text I/O to UTF-8 and fail CI on locale-dependent reads/writes by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3296
* docs: lead the README client example with a URL, not the server object by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3315
* Publish versioning, roadmap, and dependency policies for v2 by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3215
* Drop later-revision cache-hint fields on pre-2026 sessions by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3223
* Stop framing breaking changes as a workflow in AGENTS.md by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3286
* MCPServer: content-block returns are unstructured, prompt messages take Image/Audio by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3320
* Let Client take StdioServerParameters directly by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3321
* Gate external PRs on an assigned, linked issue by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3291
* docs: cover the remaining Tier 1 audit items by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3325
* Acknowledge notification POSTs with 202 on the 2026-07-28 HTTP entry by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3326
* Shorten stdio test comments by @Kludex in https://github.com/modelcontextprotocol/python-sdk/pull/3329
* Hand TypedDict tool results to pydantic natively by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3331
* Apply the request body limit to the SSE and OAuth endpoints by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3336
* Accept boolean sub-schemas in 2025-11-25 tool schema properties by @pja-ant in https://github.com/modelcontextprotocol/python-sdk/pull/3354
* Log MCPServer handler exceptions by kind and keep crash details off the wire by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3314
* Give recursive tool return types an object-rooted output schema by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3376
* docs: refresh translations for recent English changes by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3379
* Build releases with the pinned hatchling and a publish action that accepts Metadata 2.5 by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3380

## New Contributors
* @ShuQingDollarVoyager made their first contribution in https://github.com/modelcontextprotocol/python-sdk/pull/3245

**Full Changelog**: https://github.com/modelcontextprotocol/python-sdk/compare/v2.0.0...v2.1.0
</Release>

<Release version="v1.29.1" date="August 24, 2026" published="2026-08-24T18:24:41.000Z" url="https://github.com/modelcontextprotocol/python-sdk/releases/tag/v1.29.1">
## What's Changed
* [v1.x] Complete the FastMCP Settings model at import time by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3352
* [v1.x] Apply the request body limit to the SSE and OAuth endpoints by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3344
* [v1.x] Give recursive tool return types an object-rooted output schema by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3377


**Full Changelog**: https://github.com/modelcontextprotocol/python-sdk/compare/v1.29.0...v1.29.1
</Release>

<Release version="v2.0.0" date="July 28, 2026" published="2026-07-28T13:41:36.000Z" url="https://github.com/modelcontextprotocol/python-sdk/releases/tag/v2.0.0">
# MCP Python SDK v2 Stable Release

This is v2.0.0, the stable v2 release of the MCP Python SDK. It supports the 2026-07-28 revision of the Model Context Protocol and serves every earlier revision from the same server. `pip install mcp` now installs 2.x.

```bash
pip install "mcp[cli]"
# or
uv add "mcp[cli]"
```

### Documentation Rewrite

The [documentation](https://py.sdk.modelcontextprotocol.io/) has the full tutorial and API reference. Coming from v1? [What's new in v2](https://py.sdk.modelcontextprotocol.io/whats-new/) is the tour of what changed and why, and the [migration guide](https://py.sdk.modelcontextprotocol.io/migration/) lists every breaking change with before-and-after code.

### V1 Maintenance mode

**v1.x is in maintenance mode and will only receive security fixes from now on** The 1.x line lives on the [`v1.x` branch](https://github.com/modelcontextprotocol/python-sdk/tree/v1.x), continues to receive critical bug fixes and security patches, and is documented at https://py.sdk.modelcontextprotocol.io/v1/. If your project is not ready to migrate, keep a `<2` upper bound on your requirement (for example `mcp>=1.28,<2`).

## Highlights

### One SDK, both protocol eras

v2 speaks the 2026-07-28 revision (stateless requests with no handshake, `server/discover`, `subscriptions/listen`, multi-round-trip requests) and still serves every 2025-era client from the same `MCPServer`, over Streamable HTTP and stdio, with nothing to configure. `Client(target)` negotiates the version automatically.

### `FastMCP` is now `MCPServer`, and there is a first-class `Client`

The decorator API is unchanged; the low-level `Server` is rebuilt around a shared dispatcher engine, and one `Client` object replaces v1's transport-plus-`ClientSession`-plus-`initialize()` layering. It connects to a URL, a stdio subprocess, a custom transport, or straight to a server object in memory for tests.

### Multi-round-trip requests and resolver dependency injection

At 2026-07-28 the server can no longer call the client, so tools return the question instead. A `Resolve(fn)` parameter is filled by your function invisibly to the model and can put a question to the user; one tool body serves both eras.

### Extension APIs, OpenTelemetry, and a standalone types package

Servers and clients compose protocol extensions through pluggable extension APIs (MCP Apps built in); OpenTelemetry tracing ships on by default; every protocol type is its own package, `mcp-types` (imported as `mcp_types`), published in lock-step with `mcp`.

### Hardened stdio and auth

stdio servers keep handler subprocesses and stray prints off the wire, and stdout is diverted to stderr while serving. OAuth adds RFC 9207 issuer validation, the SEP-990 identity-assertion flow, and the client-credentials extension.

## Coming from a v2 pre-release

Since the last release candidate: the per-version wire packages are private (`mcp_types._v*`), `mcp.types` is a permanent alias for `mcp_types`, the auth registration request model is split from the registered-client record, cancelled requests are no longer answered, and log notifications are gated on the per-request log-level opt-in at 2026-07-28. Since the betas: `Client(cache=False)` is now `cache=None` with `CacheConfig()` the default; `Context.client_id`, `RFC7523OAuthClientProvider`, and `OAuthClientProvider(timeout=)` are removed; the client-credentials providers take `scope=`; `message_handler` receives notifications and exceptions only; `FileResource(is_binary=)` becomes `encoding`; `MCP_*` env vars are gone with `pydantic-settings`; Streamable HTTP servers reject bodies over 4 MiB with HTTP 413. The migration guide covers all of it.

## Known gaps

The tasks extension (SEP-2663) is not part of this release. On the client, the DPoP proof binding (SEP-1932) and the workload-identity `jwt-bearer` grant are not implemented; both are additive and can land in 2.x.

## Feedback

Something rough, confusing, or broken? [Open an issue](https://github.com/modelcontextprotocol/python-sdk/issues/new/choose) or find us in [#python-sdk-dev on the MCP Contributors Discord](https://discord.gg/6CSzBmMkjX).

**Full Changelog**: https://github.com/modelcontextprotocol/python-sdk/compare/v2.0.0rc1...v2.0.0
</Release>

<Release version="v1.29.0" date="July 28, 2026" published="2026-07-28T13:37:06.000Z" url="https://github.com/modelcontextprotocol/python-sdk/releases/tag/v1.29.0">
## What's Changed
* [v1.x] Route Context.report_progress() to the originating request stream by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/2994
* [v1.x] docs: publish llms.txt and markdown renditions of the docs by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3029
* [v1.x] docs: pin mkdocs<2 by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3074
* [v1.x] Add Streamable HTTP request body limits by @Kludex in https://github.com/modelcontextprotocol/python-sdk/pull/3101
* [v1.x] fix: reject trailing newline in tool-name validation by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3086
* [v1.x] ci: pick the docs toolchain per worktree in build-docs.sh by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3082
* [v1.x] Move the v1.x docs to /v1/ and mark v1.x as the maintenance line by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/3177


**Full Changelog**: https://github.com/modelcontextprotocol/python-sdk/compare/v1.28.1...v1.29.0
</Release>

<Release version="v1.28.1" date="June 26, 2026" published="2026-06-26T12:32:57.000Z" url="https://github.com/modelcontextprotocol/python-sdk/releases/tag/v1.28.1">
## What's Changed
* [v1.x] Buffer per-request StreamableHTTP streams; store priming event before dispatch by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/2948
* [v1.x] Set Development Status classifier to Production/Stable by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/2976
* [v1.x] Support TransportSecuritySettings in the WebSocket server transport by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/2992


**Full Changelog**: https://github.com/modelcontextprotocol/python-sdk/compare/v1.28.0...v1.28.1
</Release>

<Release version="v1.28.0" date="June 16, 2026" published="2026-06-16T21:30:35.000Z" url="https://github.com/modelcontextprotocol/python-sdk/releases/tag/v1.28.0">
## Deprecations

Two API surfaces now emit `DeprecationWarning` ahead of their removal in v2. Nothing is removed in 1.x, and the warnings fire only when the deprecated API is *called* - importing the modules stays silent.

- **WebSocket transport** - `mcp.client.websocket.websocket_client` and `mcp.server.websocket.websocket_server`. WebSocket was never part of the MCP specification; use the streamable HTTP transport instead. The TypeScript SDK has likewise removed its WebSocket client for v2 (modelcontextprotocol/typescript-sdk#1783).
- **Experimental tasks API** - `ClientSession.experimental`, `Server.experimental`, `ServerSession.experimental`, and the `experimental_task_handlers=` kwarg on `ClientSession`. Tasks (SEP-1686) were removed from the MCP specification and are expected to return as a separate MCP extension.

If your test suite runs with `filterwarnings = ["error"]` and exercises these paths, add a scoped ignore such as `ignore:The experimental tasks API is deprecated:DeprecationWarning` or `ignore:The WebSocket .* transport is deprecated:DeprecationWarning`.

See #2828 for full details.

## What's Changed

* [v1.x] Support Python 3.14 by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/2769
* fix: omit null optional fields from task result payloads by @liuzemei in https://github.com/modelcontextprotocol/python-sdk/pull/2809
* [v1.x] Deprecate the WebSocket transport and the experimental tasks entry points by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/2828
* [v1.x] Add a v2 status banner to the README by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/2835
* [v1.x] Deflake the child process cleanup tests by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/2839

## New Contributors

* @liuzemei made their first contribution in https://github.com/modelcontextprotocol/python-sdk/pull/2809

**Full Changelog**: https://github.com/modelcontextprotocol/python-sdk/compare/v1.27.2...v1.28.0

</Release>

<Release version="v1.27.2" date="May 29, 2026" published="2026-05-29T17:10:26.000Z" url="https://github.com/modelcontextprotocol/python-sdk/releases/tag/v1.27.2">
## What's Changed
* [v1.x] ci: deploy docs to py.sdk.modelcontextprotocol.io via Pages artifact by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/2635
* [v1.x] Add subject and claims to AccessToken by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/2690
* [v1.x] Bind transport sessions to the authenticated principal by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/2719
* [v1.x] Scope experimental tasks to the session that created them by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/2720


**Full Changelog**: https://github.com/modelcontextprotocol/python-sdk/compare/v1.27.1...v1.27.2
</Release>

<Release version="v1.27.1" date="May 8, 2026" published="2026-05-08T16:44:58.000Z" url="https://github.com/modelcontextprotocol/python-sdk/releases/tag/v1.27.1">
## What's Changed
* [v1.x] fix: catch PydanticUserError when generating output schema (pydantic 2.13 compat) by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/2435
* [v1.x] fix(auth): coerce empty-string optional URL fields to None in OAuthClientMetadata by @felixweinberger in https://github.com/modelcontextprotocol/python-sdk/pull/2405
* [v1.x] build: restrict httpx to <1.0.0 by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/2559
* [v1.x] refactor: import SSEError from httpx_sse public API by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/2561


**Full Changelog**: https://github.com/modelcontextprotocol/python-sdk/compare/v1.27.0...v1.27.1
</Release>

<Release version="v1.27.0" date="April 2, 2026" published="2026-04-02T14:36:40.000Z" url="https://github.com/modelcontextprotocol/python-sdk/releases/tag/v1.27.0">
## What's Changed
* fix: remove unused `requests` dependency from simple-chatbot example by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/1959
* ci: backport conformance tests from main to v1.x by @felixweinberger in https://github.com/modelcontextprotocol/python-sdk/pull/2068
* fix: add RFC 8707 resource validation to OAuth client by @felixweinberger in https://github.com/modelcontextprotocol/python-sdk/pull/2069
* feat: add idle timeout for StreamableHTTP sessions by @felixweinberger in https://github.com/modelcontextprotocol/python-sdk/pull/1994
* [v1.x] fix: prevent command injection in example URL opening by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/2085
* Add VERSIONING.md, ROADMAP.md, and DEPENDENCY_POLICY.md by @felixweinberger in https://github.com/modelcontextprotocol/python-sdk/pull/2084
* docs: restructure README into docs/ pages by @felixweinberger in https://github.com/modelcontextprotocol/python-sdk/pull/2091
* docs: comprehensive feature documentation for SEP-1730 Tier 1 by @felixweinberger in https://github.com/modelcontextprotocol/python-sdk/pull/2090
* docs: fix stub pages and improve docs structure by @felixweinberger in https://github.com/modelcontextprotocol/python-sdk/pull/2101
* docs: fix GitHub links to point to v1.x branch by @felixweinberger in https://github.com/modelcontextprotocol/python-sdk/pull/2102
* docs: add snippet verification for docs/ pages by @felixweinberger in https://github.com/modelcontextprotocol/python-sdk/pull/2115
* docs: add server-side tool error handling documentation by @felixweinberger in https://github.com/modelcontextprotocol/python-sdk/pull/2129
* Backport: Add missing TasksCallCapability to v1.x by @BabyChrist666 in https://github.com/modelcontextprotocol/python-sdk/pull/2137
* [v1.x] fix: handle non-UTF-8 bytes in stdio server stdin by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/2303
* [v1.x] fix: handle ClosedResourceError when transport closes mid-request by @owendevereaux in https://github.com/modelcontextprotocol/python-sdk/pull/2334

## New Contributors
* @owendevereaux made their first contribution in https://github.com/modelcontextprotocol/python-sdk/pull/2334

**Full Changelog**: https://github.com/modelcontextprotocol/python-sdk/compare/v1.26.0...v1.27.0
</Release>

<Release version="v1.26.0" date="January 24, 2026" published="2026-01-24T19:26:20.000Z" url="https://github.com/modelcontextprotocol/python-sdk/releases/tag/v1.26.0">
## What's Changed
* ci: add all-green job to pull-request-checks workflow by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/1929
* Backport: Support for Resource and ResourceTemplate metadata by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/1928
* [v1.x] fix: return HTTP 404 for unknown session IDs instead of 400 by @LucaButBoring in https://github.com/modelcontextprotocol/python-sdk/pull/1945


**Full Changelog**: https://github.com/modelcontextprotocol/python-sdk/compare/v1.25.0...v1.26.0
</Release>

<Release version="v1.25.0" date="December 18, 2025" published="2025-12-18T17:15:31.000Z" url="https://github.com/modelcontextprotocol/python-sdk/releases/tag/v1.25.0">
 ## Branching Update

Starting with this release, the repository has adopted a new branching strategy for v2 development:

- **`main`** — v2 development (breaking changes)
- **`v1.x`** — v1 maintenance (security and critical bug fixes only, with very rare feature additions ported from `main`)

Users who need to stay on v1.x should pin to `mcp>=1.25,<2`.
  
The current plan is to work through v2 and have it released some time in Q1. This also relies on the next upcoming spec release which will heavily change how the transport layer works, which in turn will guide a lot of how we architect v2.

  ---

## What's Changed
* Fix for Url Elicitation issue 1768 by @gopitk in https://github.com/modelcontextprotocol/python-sdk/pull/1780
* ci: add v1.x branch to main-checks workflow by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/1802

## New Contributors
* @gopitk made their first contribution in https://github.com/modelcontextprotocol/python-sdk/pull/1780

**Full Changelog**: https://github.com/modelcontextprotocol/python-sdk/compare/v1.24.0...v1.25.0
</Release>

<Release version="v1.24.0" date="December 12, 2025" published="2025-12-12T14:11:16.000Z" url="https://github.com/modelcontextprotocol/python-sdk/releases/tag/v1.24.0">
## What's Changed
* feat: client-side support for SEP-1577 sampling with tools by @jlowin in https://github.com/modelcontextprotocol/python-sdk/pull/1722
* Fix JSON-RPC error response ID matching by @crondinini-ant in https://github.com/modelcontextprotocol/python-sdk/pull/1720
* Add `streamable_http_client` which accepts `httpx.AsyncClient` instead of `httpx_client_factory` by @Kludex in https://github.com/modelcontextprotocol/python-sdk/pull/1177
* fix: use correct python command name in test_stdio.py by @WOnder93 in https://github.com/modelcontextprotocol/python-sdk/pull/1782

## New Contributors
* @WOnder93 made their first contribution in https://github.com/modelcontextprotocol/python-sdk/pull/1782

**Full Changelog**: https://github.com/modelcontextprotocol/python-sdk/compare/v1.23.3...v1.24.0
</Release>

<Release version="v1.23.3" date="December 9, 2025" published="2025-12-09T15:46:18.000Z" url="https://github.com/modelcontextprotocol/python-sdk/releases/tag/v1.23.3">
## What's Changed
* refactor(auth): remove unused _register_client method by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/1748
* feat: add workflow to comment on PRs when released by @felixweinberger in https://github.com/modelcontextprotocol/python-sdk/pull/1750
* fix: allow MIME type parameters in resource validation (RFC 2045) by @antonpk1 in https://github.com/modelcontextprotocol/python-sdk/pull/1755
* Skip empty SSE data to avoid parsing errors by @injusticescorpio in https://github.com/modelcontextprotocol/python-sdk/pull/1753
* chore: remove release-comment workflow by @maxisbey in https://github.com/modelcontextprotocol/python-sdk/pull/1758

## New Contributors
* @antonpk1 made their first contribution in https://github.com/modelcontextprotocol/python-sdk/pull/1755
* @injusticescorpio made their first contribution in https://github.com/modelcontextprotocol/python-sdk/pull/1753

**Full Changelog**: https://github.com/modelcontextprotocol/python-sdk/compare/v1.23.2...v1.23.3
</Release>

<Release version="v1.23.2" date="December 4, 2025" published="2025-12-04T14:46:34.000Z" url="https://github.com/modelcontextprotocol/python-sdk/releases/tag/v1.23.2">
## What's Changed
* fix: add lifespan context manager to StreamableHTTP mounting examples by @TheMailmans in https://github.com/modelcontextprotocol/python-sdk/pull/1669
* fix: handle ClosedResourceError in StreamableHTTP message router by @Edison-A-N in https://github.com/modelcontextprotocol/python-sdk/pull/1384
* fix: skip priming events and close_sse_stream for old protocol versions by @felixweinberger in https://github.com/modelcontextprotocol/python-sdk/pull/1719

## New Contributors
* @TheMailmans made their first contribution in https://github.com/modelcontextprotocol/python-sdk/pull/1669
* @Edison-A-N made their first contribution in https://github.com/modelcontextprotocol/python-sdk/pull/1384

**Full Changelog**: https://github.com/modelcontextprotocol/python-sdk/compare/v1.23.1...v1.23.2
</Release>

<Release version="v1.23.1" date="December 2, 2025" published="2025-12-02T18:29:00.000Z" url="https://github.com/modelcontextprotocol/python-sdk/releases/tag/v1.23.1">
## What's Changed
* chore: update LATEST_PROTOCOL_VERSION to 2025-11-25 by @felixweinberger in https://github.com/modelcontextprotocol/python-sdk/pull/1715


**Full Changelog**: https://github.com/modelcontextprotocol/python-sdk/compare/v1.23.0...v1.23.1
</Release>

<Pagination cursor="2025-12-02T18:29:00.000Z|2026-10-23T22:54:19.505Z|rel_B4vY2KCSRKk_juc1MJYQl" next="https://releases.sh/modelcontextprotocol/mcp-python-sdk.md?cursor=2025-12-02T18%3A29%3A00.000Z%7C2026-10-23T22%3A54%3A19.505Z%7Crel_B4vY2KCSRKk_juc1MJYQl&limit=20" />
