From 6f43fc08f72dfc5fa11d71266b2fc66d7325eaf4 Mon Sep 17 00:00:00 2001 From: Lukas Innig Date: Thu, 13 Nov 2025 08:41:58 +0000 Subject: [PATCH] adding alias streamable_http_client for streamablehttp_client --- README.md | 8 +-- .../mcp_simple_auth_client/main.py | 4 +- examples/snippets/clients/oauth_client.py | 4 +- examples/snippets/clients/streamable_basic.py | 4 +- src/mcp/client/session_group.py | 6 +- src/mcp/client/streamable_http.py | 3 + tests/client/test_http_unicode.py | 6 +- tests/client/test_notification_response.py | 4 +- tests/client/test_session_group.py | 4 +- tests/server/fastmcp/test_integration.py | 4 +- tests/shared/test_streamable_http.py | 60 +++++++++---------- 11 files changed, 55 insertions(+), 52 deletions(-) diff --git a/README.md b/README.md index 5dbc4bd9dd..066d4dee74 100644 --- a/README.md +++ b/README.md @@ -2127,12 +2127,12 @@ Run from the repository root: import asyncio from mcp import ClientSession -from mcp.client.streamable_http import streamablehttp_client +from mcp.client.streamable_http import streamable_http_client async def main(): # Connect to a streamable HTTP server - async with streamablehttp_client("http://localhost:8000/mcp") as ( + async with streamable_http_client("http://localhost:8000/mcp") as ( read_stream, write_stream, _, @@ -2260,7 +2260,7 @@ from pydantic import AnyUrl from mcp import ClientSession from mcp.client.auth import OAuthClientProvider, TokenStorage -from mcp.client.streamable_http import streamablehttp_client +from mcp.client.streamable_http import streamable_http_client from mcp.shared.auth import OAuthClientInformationFull, OAuthClientMetadata, OAuthToken @@ -2314,7 +2314,7 @@ async def main(): callback_handler=handle_callback, ) - async with streamablehttp_client("http://localhost:8001/mcp", auth=oauth_auth) as (read, write, _): + async with streamable_http_client("http://localhost:8001/mcp", auth=oauth_auth) as (read, write, _): async with ClientSession(read, write) as session: await session.initialize() diff --git a/examples/clients/simple-auth-client/mcp_simple_auth_client/main.py b/examples/clients/simple-auth-client/mcp_simple_auth_client/main.py index 5987a878ef..fb555f592b 100644 --- a/examples/clients/simple-auth-client/mcp_simple_auth_client/main.py +++ b/examples/clients/simple-auth-client/mcp_simple_auth_client/main.py @@ -19,7 +19,7 @@ from mcp.client.auth import OAuthClientProvider, TokenStorage from mcp.client.session import ClientSession from mcp.client.sse import sse_client -from mcp.client.streamable_http import streamablehttp_client +from mcp.client.streamable_http import streamable_http_client from mcp.shared.auth import OAuthClientInformationFull, OAuthClientMetadata, OAuthToken @@ -205,7 +205,7 @@ async def _default_redirect_handler(authorization_url: str) -> None: await self._run_session(read_stream, write_stream, None) else: print("📡 Opening StreamableHTTP transport connection with auth...") - async with streamablehttp_client( + async with streamable_http_client( url=self.server_url, auth=oauth_auth, timeout=timedelta(seconds=60), diff --git a/examples/snippets/clients/oauth_client.py b/examples/snippets/clients/oauth_client.py index 45026590a5..38bf7f95f3 100644 --- a/examples/snippets/clients/oauth_client.py +++ b/examples/snippets/clients/oauth_client.py @@ -14,7 +14,7 @@ from mcp import ClientSession from mcp.client.auth import OAuthClientProvider, TokenStorage -from mcp.client.streamable_http import streamablehttp_client +from mcp.client.streamable_http import streamable_http_client from mcp.shared.auth import OAuthClientInformationFull, OAuthClientMetadata, OAuthToken @@ -68,7 +68,7 @@ async def main(): callback_handler=handle_callback, ) - async with streamablehttp_client("http://localhost:8001/mcp", auth=oauth_auth) as (read, write, _): + async with streamable_http_client("http://localhost:8001/mcp", auth=oauth_auth) as (read, write, _): async with ClientSession(read, write) as session: await session.initialize() diff --git a/examples/snippets/clients/streamable_basic.py b/examples/snippets/clients/streamable_basic.py index 108439613e..071ea81553 100644 --- a/examples/snippets/clients/streamable_basic.py +++ b/examples/snippets/clients/streamable_basic.py @@ -6,12 +6,12 @@ import asyncio from mcp import ClientSession -from mcp.client.streamable_http import streamablehttp_client +from mcp.client.streamable_http import streamable_http_client async def main(): # Connect to a streamable HTTP server - async with streamablehttp_client("http://localhost:8000/mcp") as ( + async with streamable_http_client("http://localhost:8000/mcp") as ( read_stream, write_stream, _, diff --git a/src/mcp/client/session_group.py b/src/mcp/client/session_group.py index 2c55bb7752..4b821d037d 100644 --- a/src/mcp/client/session_group.py +++ b/src/mcp/client/session_group.py @@ -23,7 +23,7 @@ from mcp import types from mcp.client.sse import sse_client from mcp.client.stdio import StdioServerParameters -from mcp.client.streamable_http import streamablehttp_client +from mcp.client.streamable_http import streamable_http_client from mcp.shared.exceptions import McpError @@ -44,7 +44,7 @@ class SseServerParameters(BaseModel): class StreamableHttpParameters(BaseModel): - """Parameters for intializing a streamablehttp_client.""" + """Parameters for intializing a streamable_http_client.""" # The endpoint URL. url: str @@ -250,7 +250,7 @@ async def _establish_session( ) read, write = await session_stack.enter_async_context(client) else: - client = streamablehttp_client( + client = streamable_http_client( url=server_params.url, headers=server_params.headers, timeout=server_params.timeout, diff --git a/src/mcp/client/streamable_http.py b/src/mcp/client/streamable_http.py index 03b65b0a57..4575a17570 100644 --- a/src/mcp/client/streamable_http.py +++ b/src/mcp/client/streamable_http.py @@ -513,3 +513,6 @@ def start_get_stream() -> None: finally: await read_stream_writer.aclose() await write_stream.aclose() + + +streamable_http_client = streamablehttp_client diff --git a/tests/client/test_http_unicode.py b/tests/client/test_http_unicode.py index 95e01ce577..ec38f35838 100644 --- a/tests/client/test_http_unicode.py +++ b/tests/client/test_http_unicode.py @@ -12,7 +12,7 @@ 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() diff --git a/tests/client/test_notification_response.py b/tests/client/test_notification_response.py index 19d5374007..7500abee73 100644 --- a/tests/client/test_notification_response.py +++ b/tests/client/test_notification_response.py @@ -18,7 +18,7 @@ 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 message_handler( # pragma: no cover 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, diff --git a/tests/client/test_session_group.py b/tests/client/test_session_group.py index 3a19cff68b..19335e4737 100644 --- a/tests/client/test_session_group.py +++ b/tests/client/test_session_group.py @@ -272,7 +272,7 @@ async def test_disconnect_non_existent_server(self): ( 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 ], ) @@ -288,7 +288,7 @@ async def test_establish_session_parameterized( 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 = ( diff --git a/tests/server/fastmcp/test_integration.py b/tests/server/fastmcp/test_integration.py index b1cefca29c..70948bd7e2 100644 --- a/tests/server/fastmcp/test_integration.py +++ b/tests/server/fastmcp/test_integration.py @@ -34,7 +34,7 @@ ) from mcp.client.session import ClientSession from mcp.client.sse import sse_client -from mcp.client.streamable_http import GetSessionIdCallback, streamablehttp_client +from mcp.client.streamable_http import GetSessionIdCallback, streamable_http_client from mcp.shared.context import RequestContext from mcp.shared.message import SessionMessage from mcp.shared.session import RequestResponder @@ -179,7 +179,7 @@ def create_client_for_transport(transport: str, server_url: str): return sse_client(endpoint) elif transport == "streamable-http": endpoint = f"{server_url}/mcp" - return streamablehttp_client(endpoint) + return streamable_http_client(endpoint) else: # pragma: no cover raise ValueError(f"Invalid transport: {transport}") diff --git a/tests/shared/test_streamable_http.py b/tests/shared/test_streamable_http.py index 43b321d96e..3627a01e46 100644 --- a/tests/shared/test_streamable_http.py +++ b/tests/shared/test_streamable_http.py @@ -22,7 +22,7 @@ import mcp.types as types from mcp.client.session import ClientSession -from mcp.client.streamable_http import streamablehttp_client +from mcp.client.streamable_http import streamable_http_client from mcp.server import Server from mcp.server.streamable_http import ( MCP_PROTOCOL_VERSION_HEADER, @@ -833,7 +833,7 @@ async def http_client(basic_server: None, basic_server_url: str): # pragma: no @pytest.fixture async def initialized_client_session(basic_server: None, basic_server_url: str): """Create initialized StreamableHTTP client session.""" - async with streamablehttp_client(f"{basic_server_url}/mcp") as ( + async with streamable_http_client(f"{basic_server_url}/mcp") as ( read_stream, write_stream, _, @@ -847,9 +847,9 @@ async def initialized_client_session(basic_server: None, basic_server_url: str): @pytest.mark.anyio -async def test_streamablehttp_client_basic_connection(basic_server: None, basic_server_url: str): +async def test_streamable_http_client_basic_connection(basic_server: None, basic_server_url: str): """Test basic client connection with initialization.""" - async with streamablehttp_client(f"{basic_server_url}/mcp") as ( + async with streamable_http_client(f"{basic_server_url}/mcp") as ( read_stream, write_stream, _, @@ -865,7 +865,7 @@ async def test_streamablehttp_client_basic_connection(basic_server: None, basic_ @pytest.mark.anyio -async def test_streamablehttp_client_resource_read(initialized_client_session: ClientSession): +async def test_streamable_http_client_resource_read(initialized_client_session: ClientSession): """Test client resource read functionality.""" response = await initialized_client_session.read_resource(uri=AnyUrl("foobar://test-resource")) assert len(response.contents) == 1 @@ -875,7 +875,7 @@ async def test_streamablehttp_client_resource_read(initialized_client_session: C @pytest.mark.anyio -async def test_streamablehttp_client_tool_invocation(initialized_client_session: ClientSession): +async def test_streamable_http_client_tool_invocation(initialized_client_session: ClientSession): """Test client tool invocation.""" # First list tools tools = await initialized_client_session.list_tools() @@ -890,7 +890,7 @@ async def test_streamablehttp_client_tool_invocation(initialized_client_session: @pytest.mark.anyio -async def test_streamablehttp_client_error_handling(initialized_client_session: ClientSession): +async def test_streamable_http_client_error_handling(initialized_client_session: ClientSession): """Test error handling in client.""" with pytest.raises(McpError) as exc_info: await initialized_client_session.read_resource(uri=AnyUrl("unknown://test-error")) @@ -899,9 +899,9 @@ async def test_streamablehttp_client_error_handling(initialized_client_session: @pytest.mark.anyio -async def test_streamablehttp_client_session_persistence(basic_server: None, basic_server_url: str): +async def test_streamable_http_client_session_persistence(basic_server: None, basic_server_url: str): """Test that session ID persists across requests.""" - async with streamablehttp_client(f"{basic_server_url}/mcp") as ( + async with streamable_http_client(f"{basic_server_url}/mcp") as ( read_stream, write_stream, _, @@ -927,9 +927,9 @@ async def test_streamablehttp_client_session_persistence(basic_server: None, bas @pytest.mark.anyio -async def test_streamablehttp_client_json_response(json_response_server: None, json_server_url: str): +async def test_streamable_http_client_json_response(json_response_server: None, json_server_url: str): """Test client with JSON response mode.""" - async with streamablehttp_client(f"{json_server_url}/mcp") as ( + async with streamable_http_client(f"{json_server_url}/mcp") as ( read_stream, write_stream, _, @@ -955,7 +955,7 @@ async def test_streamablehttp_client_json_response(json_response_server: None, j @pytest.mark.anyio -async def test_streamablehttp_client_get_stream(basic_server: None, basic_server_url: str): +async def test_streamable_http_client_get_stream(basic_server: None, basic_server_url: str): """Test GET stream functionality for server-initiated messages.""" import mcp.types as types from mcp.shared.session import RequestResponder @@ -969,7 +969,7 @@ async def message_handler( # pragma: no branch if isinstance(message, types.ServerNotification): # pragma: no branch notifications_received.append(message) - async with streamablehttp_client(f"{basic_server_url}/mcp") as ( + async with streamable_http_client(f"{basic_server_url}/mcp") as ( read_stream, write_stream, _, @@ -996,13 +996,13 @@ async def message_handler( # pragma: no branch @pytest.mark.anyio -async def test_streamablehttp_client_session_termination(basic_server: None, basic_server_url: str): +async def test_streamable_http_client_session_termination(basic_server: None, basic_server_url: str): """Test client session termination functionality.""" captured_session_id = None - # Create the streamablehttp_client with a custom httpx client to capture headers - async with streamablehttp_client(f"{basic_server_url}/mcp") as ( + # Create the streamable_http_client with a custom httpx client to capture headers + async with streamable_http_client(f"{basic_server_url}/mcp") as ( read_stream, write_stream, get_session_id, @@ -1022,7 +1022,7 @@ async def test_streamablehttp_client_session_termination(basic_server: None, bas if captured_session_id: # pragma: no cover headers[MCP_SESSION_ID_HEADER] = captured_session_id - async with streamablehttp_client(f"{basic_server_url}/mcp", headers=headers) as ( + async with streamable_http_client(f"{basic_server_url}/mcp", headers=headers) as ( read_stream, write_stream, _, @@ -1037,7 +1037,7 @@ async def test_streamablehttp_client_session_termination(basic_server: None, bas @pytest.mark.anyio -async def test_streamablehttp_client_session_termination_204( +async def test_streamable_http_client_session_termination_204( basic_server: None, basic_server_url: str, monkeypatch: pytest.MonkeyPatch ): """Test client session termination functionality with a 204 response. @@ -1067,8 +1067,8 @@ async def mock_delete(self: httpx.AsyncClient, *args: Any, **kwargs: Any) -> htt captured_session_id = None - # Create the streamablehttp_client with a custom httpx client to capture headers - async with streamablehttp_client(f"{basic_server_url}/mcp") as ( + # Create the streamable_http_client with a custom httpx client to capture headers + async with streamable_http_client(f"{basic_server_url}/mcp") as ( read_stream, write_stream, get_session_id, @@ -1088,7 +1088,7 @@ async def mock_delete(self: httpx.AsyncClient, *args: Any, **kwargs: Any) -> htt if captured_session_id: # pragma: no cover headers[MCP_SESSION_ID_HEADER] = captured_session_id - async with streamablehttp_client(f"{basic_server_url}/mcp", headers=headers) as ( + async with streamable_http_client(f"{basic_server_url}/mcp", headers=headers) as ( read_stream, write_stream, _, @@ -1103,7 +1103,7 @@ async def mock_delete(self: httpx.AsyncClient, *args: Any, **kwargs: Any) -> htt @pytest.mark.anyio -async def test_streamablehttp_client_resumption(event_server: tuple[SimpleEventStore, str]): +async def test_streamable_http_client_resumption(event_server: tuple[SimpleEventStore, str]): """Test client session resumption using sync primitives for reliable coordination.""" _, server_url = event_server @@ -1130,7 +1130,7 @@ async def on_resumption_token_update(token: str) -> None: captured_resumption_token = token # First, start the client session and begin the tool that waits on lock - async with streamablehttp_client(f"{server_url}/mcp", terminate_on_close=False) as ( + async with streamable_http_client(f"{server_url}/mcp", terminate_on_close=False) as ( read_stream, write_stream, get_session_id, @@ -1186,7 +1186,7 @@ async def run_tool(): headers[MCP_SESSION_ID_HEADER] = captured_session_id if captured_protocol_version: # pragma: no cover headers[MCP_PROTOCOL_VERSION_HEADER] = captured_protocol_version - async with streamablehttp_client(f"{server_url}/mcp", headers=headers) as ( + async with streamable_http_client(f"{server_url}/mcp", headers=headers) as ( read_stream, write_stream, _, @@ -1252,7 +1252,7 @@ async def sampling_callback( ) # Create client with sampling callback - async with streamablehttp_client(f"{basic_server_url}/mcp") as ( + async with streamable_http_client(f"{basic_server_url}/mcp") as ( read_stream, write_stream, _, @@ -1397,7 +1397,7 @@ async def test_streamablehttp_request_context_propagation(context_aware_server: "X-Trace-Id": "trace-123", } - async with streamablehttp_client(f"{basic_server_url}/mcp", headers=custom_headers) as ( + async with streamable_http_client(f"{basic_server_url}/mcp", headers=custom_headers) as ( read_stream, write_stream, _, @@ -1434,7 +1434,7 @@ async def test_streamablehttp_request_context_isolation(context_aware_server: No "Authorization": f"Bearer token-{i}", } - async with streamablehttp_client(f"{basic_server_url}/mcp", headers=headers) as (read_stream, write_stream, _): + async with streamable_http_client(f"{basic_server_url}/mcp", headers=headers) as (read_stream, write_stream, _): async with ClientSession(read_stream, write_stream) as session: await session.initialize() @@ -1458,7 +1458,7 @@ async def test_streamablehttp_request_context_isolation(context_aware_server: No @pytest.mark.anyio async def test_client_includes_protocol_version_header_after_init(context_aware_server: None, basic_server_url: str): """Test that client includes mcp-protocol-version header after initialization.""" - async with streamablehttp_client(f"{basic_server_url}/mcp") as ( + async with streamable_http_client(f"{basic_server_url}/mcp") as ( read_stream, write_stream, _, @@ -1574,7 +1574,7 @@ async def test_client_crash_handled(basic_server: None, basic_server_url: str): # Simulate bad client that crashes after init async def bad_client(): """Client that triggers ClosedResourceError""" - async with streamablehttp_client(f"{basic_server_url}/mcp") as ( + async with streamable_http_client(f"{basic_server_url}/mcp") as ( read_stream, write_stream, _, @@ -1592,7 +1592,7 @@ async def bad_client(): await anyio.sleep(0.1) # Try a good client, it should still be able to connect and list tools - async with streamablehttp_client(f"{basic_server_url}/mcp") as ( + async with streamable_http_client(f"{basic_server_url}/mcp") as ( read_stream, write_stream, _,