Skip to content

Fix MCPServerStreamableHTTP closing user-provided HTTP clients with MCP SDK 1.25+ - #3854

Closed
eekstunt wants to merge 9 commits into
pydantic:mainfrom
eekstunt:fix-3745-Fix-MCPServerStreamableHTTP-closing-user-provided-HTTP-clients-with-MCP-SDK-1.25+
Closed

Fix MCPServerStreamableHTTP closing user-provided HTTP clients with MCP SDK 1.25+#3854
eekstunt wants to merge 9 commits into
pydantic:mainfrom
eekstunt:fix-3745-Fix-MCPServerStreamableHTTP-closing-user-provided-HTTP-clients-with-MCP-SDK-1.25+

Conversation

@eekstunt

@eekstunt eekstunt commented Dec 26, 2025

Copy link
Copy Markdown
Contributor

Summary

Fix AttributeError: '_AsyncGeneratorContextManager' object has no attribute 'stream' when using custom http_client with MCPServerStreamableHTTP after MCP SDK update.

Problem

After MCP SDK PR modelcontextprotocol/python-sdk#1177 (which FastMCP 2.14.1 depends on), the streamable_http_client function changed its signature. The new function accepts http_client: httpx.AsyncClient directly, while the deprecated streamablehttp_client wrapper expects a factory function (httpx_client_factory).

When pydantic-ai passed a custom http_client, the deprecated wrapper's internal async with client: block would close the user's HTTP client prematurely, breaking reusability.

Solution

Added conditional logic to use the new streamable_http_client API directly when:

  1. A custom http_client is provided
  2. The new API is available (MCP SDK >= 1.25.0)

For older MCP SDK versions or SSE transport, falls back to the factory approach.

Changes

  • Added conditional import for streamable_http_client with graceful fallback
  • Modified client_streams() in MCPServerStreamableHTTP to use new API when available
  • Added unit tests for both code paths

@dsfaccini

Copy link
Copy Markdown
Contributor

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.

@dsfaccini

Copy link
Copy Markdown
Contributor

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?

@dsfaccini dsfaccini self-assigned this Dec 31, 2025
@dsfaccini dsfaccini changed the title Fix MCPServerStreamableHTTP closing user-provided HTTP clients with MCP SDK 1.25+ Fix MCPServerStreamableHTTP closing user-provided HTTP clients with MCP SDK 1.25+ Dec 31, 2025

@dsfaccini dsfaccini left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my last comment

@eekstunt

eekstunt commented Jan 2, 2026

Copy link
Copy Markdown
Contributor Author

@dsfaccini

See my last comment

I will do it. Thank you!

@DouweM DouweM added the bug Report that something isn't working, or PR implementing a fix label Jan 6, 2026
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 (

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This still need to use _transport_client

@property
def _transport_client(self):
return streamablehttp_client
return self.http_client

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be reverted

assert self.http_client is not None
yield self.http_client

async with transport_client_partial(httpx_client_factory=httpx_client_factory) as (

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the transport_client_partial method can now be deleted

read_stream,
write_stream,
*_,
_,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm unsure if this is right

@DouweM DouweM assigned DouweM and unassigned dsfaccini Jan 6, 2026
@DouweM DouweM added the size: S Small PR (≤100 weighted lines) label Jan 7, 2026
@github-actions

Copy link
Copy Markdown
Contributor

This PR is stale, and will be closed in 7 days if no reply is received.

@github-actions github-actions Bot added the Stale label Jan 21, 2026
@dsfaccini

Copy link
Copy Markdown
Contributor

@DouweM lets close this in favor of #4047

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

awaiting author revision bug Report that something isn't working, or PR implementing a fix MCP package upgrades size: S Small PR (≤100 weighted lines) Stale

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MCPServerStreamableHTTP breaks with latest mcp version due to changes to streamble_http client

3 participants