The official MCP Python SDK 2.3 release fails tool registrations the previous version silently accepted
The modelcontextprotocol/python-sdk 2.3.0 release makes tools with an invalid x-mcp-header annotation fail at registration, stops sending empty _meta and params on outbound requests, and requires httpx2 2.10 or newer.
Image: GitHub
Why it mattersA team maintaining a Python MCP server should read the five behaviour changes before upgrading, because servers and middleware that worked on 2.2 can fail or behave differently on 2.3 without any code change on their side.
An MCP server built with the official Python SDK will fail to start on version 2.3.0 if any of its tools declare an x-mcp-header annotation the new release does not accept. On version 2.2 the same server started and the client silently dropped the tool from its listing.
The modelcontextprotocol/python-sdk repository published the 2.3.0 release at 22:02 UTC on 2 October 2026. The release notes group the changes as mostly fixes plus three new options, and list five behaviour changes the maintainers tell users to read before upgrading.
The registration check that was not there before
The new release raises InvalidSignature from @mcp.tool(), add_tool and Tool.from_function when a tool's x-mcp-header annotation uses anything other than a plain str, int or bool parameter. That rules out str | None, float, lists and enums. A header name that is not a valid token, and two names that differ only by case, are refused the same way. The release notes say that until this release the server started with the bad annotation in place, and the 2026-07-28 client just left the tool out of its listing.
For a tool that needs an optional header parameter, the release notes point to a direct schema annotation: Annotated[str | None, WithJsonSchema({"type": "string", "x-mcp-header": "Region"})] = None.
Four more behaviours that moved
The 2.x line used to send "_meta": {} on every outbound request. The release notes say some servers reject that, and 2.3.0 leaves it out, as version 1 did. ping and list requests without a cursor also go out with no params member. On the receiving side ctx.meta is now None rather than {}, and middleware sees ctx.params as None when a request has no params. Connections pinned to the 2026-07-28 protocol version are unchanged.
The initialize message no longer carries "experimental": {} when nothing is configured. The release notes tell client code that reads capabilities.experimental on a legacy connection to handle None.
The Mcp-Param-* validation now looks the tool up by name instead of running tools/list for every tools/call. The release notes say that stops middleware from seeing the extra request, and means middleware that filters or rewrites tools/list no longer affects what gets validated.
An interactive OAuth login no longer counts against request timeouts. The release notes say the timeout pauses while OAuthClientProvider waits on redirect_handler and callback_handler, and that this is what used to make Client(mode="auto") settle on the 2025-11-25 protocol when a login took longer than 10 seconds.
What is new
The release adds max_sse_event_size= on streamable_http_client and StreamableHttpParameters, with the default still 1 MiB per SSE event. The release notes say the new option is why httpx2>=2.10.0 is now required, up from 2.5.0.
A low-level server can opt out of subscriptions/listen with MCPServer(subscriptions=False), which also advertises listChanged and subscribe as false. Server(get_tool_input_schema=...) lets a low-level server supply a tool's schema for header validation without running its own tools/list handler. Client.call_tool now re-lists the tools and retries once after a HeaderMismatch rejection, error code -32020.
The run-time path for a server that worked on 2.2 and keeps working on 2.3 is narrower than the fixes list suggests. The registration check is the one that will stop a server starting at all; the empty-_meta change is the one that will change what middleware sees without any code moving.
Source
- modelcontextprotocol/python-sdk: v2.3.0 release notes
This item was written by an AI system from the linked source. Reveneau is responsible for what it publishes.
Get AI News in your inbox
New developer tools, model and agent releases, and how teams are actually using them to release software. Short, and only when there is something worth reading.

