Fix MCPServerStreamableHTTP closing user-provided HTTP clients with MCP SDK 1.25+ - #3854
Conversation
…-user-provided-HTTP-clients-with-MCP-SDK-1.25+
|
hey @eekstunt thank you for your contribution! please note that we currently have a couple PRs reviewing and updating dependencies, see here https://github.com/pydantic/pydantic-ai/pull/3778/files#r2648478356 If the problem were to be solved by that then we would avoid the extra logic and tests from this PR, otherwise we'll revisit this. |
|
hey @eekstunt we've closed the PR I referenced, so we can continue with this one. I would prefer though if we just require the higher version of the mcp package so we don't have to maintain both branches of this logic, do you think you could course-correct your PR? |
MCPServerStreamableHTTP closing user-provided HTTP clients with MCP SDK 1.25+
I will do it. Thank you! |
| yield self.http_client | ||
|
|
||
| async with transport_client_partial(httpx_client_factory=httpx_client_factory) as ( | ||
| async with streamable_http_client(self.url, http_client=self.http_client) as ( |
There was a problem hiding this comment.
This still need to use _transport_client
| @property | ||
| def _transport_client(self): | ||
| return streamablehttp_client | ||
| return self.http_client |
| assert self.http_client is not None | ||
| yield self.http_client | ||
|
|
||
| async with transport_client_partial(httpx_client_factory=httpx_client_factory) as ( |
There was a problem hiding this comment.
I think the transport_client_partial method can now be deleted
| read_stream, | ||
| write_stream, | ||
| *_, | ||
| _, |
|
This PR is stale, and will be closed in 7 days if no reply is received. |
Summary
Fix
AttributeError: '_AsyncGeneratorContextManager' object has no attribute 'stream'when using customhttp_clientwithMCPServerStreamableHTTPafter MCP SDK update.Problem
After MCP SDK PR modelcontextprotocol/python-sdk#1177 (which FastMCP 2.14.1 depends on), the
streamable_http_clientfunction changed its signature. The new function acceptshttp_client: httpx.AsyncClientdirectly, while the deprecatedstreamablehttp_clientwrapper expects a factory function (httpx_client_factory).When
pydantic-aipassed a customhttp_client, the deprecated wrapper's internalasync with client:block would close the user's HTTP client prematurely, breaking reusability.Solution
Added conditional logic to use the new
streamable_http_clientAPI directly when:http_clientis providedFor older MCP SDK versions or SSE transport, falls back to the factory approach.
Changes
streamable_http_clientwith graceful fallbackclient_streams()inMCPServerStreamableHTTPto use new API when available