Add streamable_http_client which accepts httpx.AsyncClient instead of httpx_client_factory (#1177)

Co-authored-by: Felix Weinberger <fweinberger@anthropic.com>
This commit is contained in:
Marcelo Trylesinski 2025-12-10 17:39:00 +01:00 • committed by GitHub
commit a3a4b8d11a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 488 additions and 221 deletions

View file

@ -12,7 +12,7 @@ from collections.abc import Generator
import pytest
from mcp.client.session import ClientSession
from mcp.client.streamable_http import streamablehttp_client
from mcp.client.streamable_http import streamable_http_client
from tests.test_helpers import wait_for_server
# Test constants with various Unicode characters
@ -178,7 +178,7 @@ async def test_streamable_http_client_unicode_tool_call(running_unicode_server:
base_url = running_unicode_server
endpoint_url = f"{base_url}/mcp"
async with streamablehttp_client(endpoint_url) as (read_stream, write_stream, _get_session_id):
async with streamable_http_client(endpoint_url) as (read_stream, write_stream, _get_session_id):
async with ClientSession(read_stream, write_stream) as session:
await session.initialize()
@ -210,7 +210,7 @@ async def test_streamable_http_client_unicode_prompts(running_unicode_server: st
base_url = running_unicode_server
endpoint_url = f"{base_url}/mcp"
async with streamablehttp_client(endpoint_url) as (read_stream, write_stream, _get_session_id):
async with streamable_http_client(endpoint_url) as (read_stream, write_stream, _get_session_id):
async with ClientSession(read_stream, write_stream) as session:
await session.initialize()

View file

@ -18,7 +18,7 @@ from starlette.responses import JSONResponse, Response
from starlette.routing import Route
from mcp import ClientSession, types
from mcp.client.streamable_http import streamablehttp_client
from mcp.client.streamable_http import streamable_http_client
from mcp.shared.session import RequestResponder
from mcp.types import ClientNotification, RootsListChangedNotification
from tests.test_helpers import wait_for_server
@ -127,7 +127,7 @@ async def test_non_compliant_notification_response(non_sdk_server: None, non_sdk
if isinstance(message, Exception):
returned_exception = message
async with streamablehttp_client(server_url) as (read_stream, write_stream, _):
async with streamable_http_client(server_url) as (read_stream, write_stream, _):
async with ClientSession(
read_stream,
write_stream,

View file

@ -280,7 +280,7 @@ class TestClientSessionGroup:
(
StreamableHttpParameters(url="http://test.com/stream", terminate_on_close=False),
"streamablehttp",
"mcp.client.session_group.streamablehttp_client",
"mcp.client.session_group.streamable_http_client",
), # url, headers, timeout, sse_read_timeout, terminate_on_close
],
)
@ -296,7 +296,7 @@ class TestClientSessionGroup:
mock_read_stream = mock.AsyncMock(name=f"{client_type_name}Read")
mock_write_stream = mock.AsyncMock(name=f"{client_type_name}Write")
# streamablehttp_client's __aenter__ returns three values
# streamable_http_client's __aenter__ returns three values
if client_type_name == "streamablehttp":
mock_extra_stream_val = mock.AsyncMock(name="StreamableExtra")
mock_client_cm_instance.__aenter__.return_value = (
@ -354,13 +354,14 @@ class TestClientSessionGroup:
)
elif client_type_name == "streamablehttp": # pragma: no branch
assert isinstance(server_params_instance, StreamableHttpParameters)
mock_specific_client_func.assert_called_once_with(
url=server_params_instance.url,
headers=server_params_instance.headers,
timeout=server_params_instance.timeout,
sse_read_timeout=server_params_instance.sse_read_timeout,
terminate_on_close=server_params_instance.terminate_on_close,
)
# Verify streamable_http_client was called with url, httpx_client, and terminate_on_close
# The http_client is created by the real create_mcp_http_client
import httpx
call_args = mock_specific_client_func.call_args
assert call_args.kwargs["url"] == server_params_instance.url
assert call_args.kwargs["terminate_on_close"] == server_params_instance.terminate_on_close
assert isinstance(call_args.kwargs["http_client"], httpx.AsyncClient)
mock_client_cm_instance.__aenter__.assert_awaited_once()