diff --git a/src/mcp/client/sse.py b/src/mcp/client/sse.py index 7ca8d19af..ac13ad76d 100644 --- a/src/mcp/client/sse.py +++ b/src/mcp/client/sse.py @@ -28,6 +28,7 @@ async def sse_client( sse_read_timeout: float = 60 * 5, httpx_client_factory: McpHttpClientFactory = create_mcp_http_client, auth: httpx.Auth | None = None, + verify: bool | None = None, ): """ Client transport for SSE. @@ -55,7 +56,10 @@ async def sse_client( try: logger.debug(f"Connecting to SSE endpoint: {remove_request_params(url)}") async with httpx_client_factory( - headers=headers, auth=auth, timeout=httpx.Timeout(timeout, read=sse_read_timeout) + headers=headers, + timeout=httpx.Timeout(timeout, read=sse_read_timeout), + auth=auth, + verify=verify, ) as client: async with aconnect_sse( client, diff --git a/src/mcp/client/streamable_http.py b/src/mcp/client/streamable_http.py index b1ab2c079..58d96afeb 100644 --- a/src/mcp/client/streamable_http.py +++ b/src/mcp/client/streamable_http.py @@ -448,6 +448,7 @@ async def streamablehttp_client( terminate_on_close: bool = True, httpx_client_factory: McpHttpClientFactory = create_mcp_http_client, auth: httpx.Auth | None = None, + verify: bool | None = None, ) -> AsyncGenerator[ tuple[ MemoryObjectReceiveStream[SessionMessage | Exception], @@ -481,6 +482,7 @@ async def streamablehttp_client( headers=transport.request_headers, timeout=httpx.Timeout(transport.timeout, read=transport.sse_read_timeout), auth=transport.auth, + verify=verify, ) as client: # Define callbacks that need access to tg def start_get_stream() -> None: diff --git a/src/mcp/shared/_httpx_utils.py b/src/mcp/shared/_httpx_utils.py index e0611ce73..1f01e5a4a 100644 --- a/src/mcp/shared/_httpx_utils.py +++ b/src/mcp/shared/_httpx_utils.py @@ -13,6 +13,7 @@ def __call__( headers: dict[str, str] | None = None, timeout: httpx.Timeout | None = None, auth: httpx.Auth | None = None, + verify: bool | None = None, ) -> httpx.AsyncClient: ... @@ -20,6 +21,7 @@ def create_mcp_http_client( headers: dict[str, str] | None = None, timeout: httpx.Timeout | None = None, auth: httpx.Auth | None = None, + verify: bool | None = None, ) -> httpx.AsyncClient: """Create a standardized httpx AsyncClient with MCP defaults. @@ -32,6 +34,8 @@ def create_mcp_http_client( timeout: Request timeout as httpx.Timeout object. Defaults to 30 seconds if not specified. auth: Optional authentication handler. + verify: Either True to use default CA bundle, False to disable verification, or an instance of ssl.SSLContext. + Returns: Configured httpx.AsyncClient instance with MCP defaults. @@ -60,6 +64,10 @@ def create_mcp_http_client( auth = BasicAuth(username="user", password="pass") async with create_mcp_http_client(headers, timeout, auth) as client: response = await client.get("/protected-endpoint") + + # With SSL verification disabled + async with create_mcp_http_client(verify=False) as client: + response = await client.get("/insecure-endpoint") """ # Set MCP defaults kwargs: dict[str, Any] = { @@ -80,4 +88,8 @@ def create_mcp_http_client( if auth is not None: kwargs["auth"] = auth + # Handle SSL verification + if verify is not None: + kwargs["verify"] = verify + return httpx.AsyncClient(**kwargs)