Skip to content

Conversation

@mpfaffenberger
Copy link
Contributor

@mpfaffenberger mpfaffenberger commented Jun 5, 2025

Hey everyone! Thanks for considering this P/R. The extra_http_client_args will allow us to send in extra config for the underlying httpx.AsyncClients that get spun up in the MCP connection pool. I personally need this to use Pydantic AI's MCP client tools in my corporate environment where I am required to use a self signed cert.

@johnjdonna
Copy link

We've been using a hacky solution for this, this would be absolutely huge for my team.

@mpfaffenberger
Copy link
Contributor Author

We've been using a hacky solution for this, this would be absolutely huge for my team.

Yeah, it's feasible to monkey patch the underlying MCP httpx_client_factory or whatnot.

@DouweM
Copy link
Collaborator

DouweM commented Jun 10, 2025

@mpfaffenberger Thank you!

What do you think of letting the user directly pass their own http_client instead of just the args, like we support on AnthropicProvider and some other providers? That would mean raising an error if timeout, headers, or auth are passed, but I like the simplicity and consistency.

@mpfaffenberger
Copy link
Contributor Author

@mpfaffenberger Thank you!

What do you think of letting the user directly pass their own http_client instead of just the args, like we support on AnthropicProvider and some other providers? That would mean raising an error if timeout, headers, or auth are passed, but I like the simplicity and consistency.

I'm happy to make that change if you want!! Let me cook it up really quick.

Copy link
Contributor

@dmontagu dmontagu left a comment

Choose a reason for hiding this comment

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

Looks good to me but I defer to @Kludex

@mpfaffenberger
Copy link
Contributor Author

@DouweM Is this what you were hoping for?

Comment on lines 381 to 404
if self.http_client and self.headers:
raise ValueError(f'In {self.__name__}, only one of `headers` or `http_client` can be provided.')

sse_client_partial = functools.partial(
sse_client,
url=self.url,
headers=self.headers,
timeout=self.timeout,
sse_read_timeout=self.sse_read_timeout,
) as (read_stream, write_stream):
yield read_stream, write_stream
)

if self.http_client is not None:

def httpx_client_factory(
headers: dict[str, str] | None = None,
timeout: httpx.Timeout | None = None,
auth: httpx.Auth | None = None,
) -> httpx.AsyncClient:
return self.http_client # pyright: ignore

async with sse_client_partial(httpx_client_factory=httpx_client_factory) as (read_stream, write_stream):
yield read_stream, write_stream
else:
async with sse_client_partial(headers=self.headers) as (read_stream, write_stream):
yield read_stream, write_stream
Copy link
Member

Choose a reason for hiding this comment

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

I don't think this is what we want. We either want:

  1. Only allow http_client or headers/timeout/auth. It would be nice to add an typing.overload.
  2. Allow all parameters, and replace them on the factory we are creating.

Copy link
Contributor Author

@mpfaffenberger mpfaffenberger Jun 11, 2025

Choose a reason for hiding this comment

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

So for 2) let's say I run this code as a dev:

custom_client = httpx.AsyncClient(headers={"X-Api-Key": "12345"}, timeout=300)

headers = {
    "X-Api-Key": "54321",
}

server = MCPServerHTTP(
    http_client=custom_client,
    timeout=5,
    headers=headers
)

How do we decide which parameters ultimately get passed to MCP's sse_client?
I think it's fine to pick one or the other as long as users get a warnings.warn or something.

I had discussed this briefly on Slack with @dmontagu

More than happy to continue iterating on this P/R btw. :)

edit: I realize this example is silly + contrived, but I expect users to do silly things :D

Copy link
Member

@Kludex Kludex left a comment

Choose a reason for hiding this comment

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

Let's start without the overload. It's fine.

@Kludex Kludex enabled auto-merge (squash) June 11, 2025 14:46
@Kludex Kludex force-pushed the feature/mcp-http-server-extra-http-args branch from 55a4736 to a993102 Compare June 11, 2025 14:50
@Kludex Kludex merged commit a1259fe into pydantic:main Jun 11, 2025
16 checks passed
@mpfaffenberger mpfaffenberger deleted the feature/mcp-http-server-extra-http-args branch June 11, 2025 15:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants