Skip to content

Commit ee35583

Browse files
committed
Merge remote-tracking branch 'upstream/rename-streamable-http' into feature/streamable_http_extensions
# Conflicts: # src/mcp/client/streamable_http.py # tests/shared/test_streamable_http.py
2 parents 3326974 + a14eeb2 commit ee35583

File tree

13 files changed

+403
-198
lines changed

13 files changed

+403
-198
lines changed

.github/workflows/shared.yml

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,53 +13,59 @@ jobs:
1313
pre-commit:
1414
runs-on: ubuntu-latest
1515
steps:
16-
- uses: actions/checkout@v4
16+
- uses: actions/checkout@v5
1717

18-
- uses: astral-sh/setup-uv@v5
18+
- uses: astral-sh/setup-uv@v7
1919
with:
2020
enable-cache: true
2121
version: 0.9.5
22-
2322
- name: Install dependencies
2423
run: uv sync --frozen --all-extras --python 3.10
2524

26-
- uses: pre-commit/action@v3.0.0
25+
- uses: pre-commit/action@v3.0.1
2726
with:
2827
extra_args: --all-files --verbose
2928
env:
3029
SKIP: no-commit-to-branch
3130

3231
test:
32+
name: test (${{ matrix.python-version }}, ${{ matrix.dep-resolution.name }}, ${{ matrix.os }})
3333
runs-on: ${{ matrix.os }}
3434
timeout-minutes: 10
3535
continue-on-error: true
3636
strategy:
3737
matrix:
3838
python-version: ["3.10", "3.11", "3.12", "3.13"]
39-
dep-resolution: ["lowest-direct", "highest"]
39+
dep-resolution:
40+
- name: lowest-direct
41+
install-flags: "--resolution lowest-direct"
42+
- name: highest
43+
install-flags: "--frozen"
4044
os: [ubuntu-latest, windows-latest]
4145

4246
steps:
43-
- uses: actions/checkout@v4
47+
- uses: actions/checkout@v5
4448

4549
- name: Install uv
46-
uses: astral-sh/setup-uv@v3
50+
uses: astral-sh/setup-uv@v7
4751
with:
4852
enable-cache: true
4953
version: 0.9.5
5054

5155
- name: Install the project
52-
run: uv sync --frozen --all-extras --python ${{ matrix.python-version }} --resolution ${{ matrix.dep-resolution }}
56+
run: uv sync ${{ matrix.dep-resolution.install-flags }} --all-extras --python ${{ matrix.python-version }}
5357

5458
- name: Run pytest
55-
run: uv run --frozen --no-sync pytest
59+
run: uv run ${{ matrix.dep-resolution.install-flags }} --no-sync pytest
60+
env:
61+
UV_RESOLUTION: ${{ matrix.dep-resolution.name == 'lowest-direct' && 'lowest-direct' || 'highest' }}
5662

5763
readme-snippets:
5864
runs-on: ubuntu-latest
5965
steps:
60-
- uses: actions/checkout@v4
66+
- uses: actions/checkout@v5
6167

62-
- uses: astral-sh/setup-uv@v5
68+
- uses: astral-sh/setup-uv@v7
6369
with:
6470
enable-cache: true
6571
version: 0.9.5

README.md

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2127,12 +2127,12 @@ Run from the repository root:
21272127
import asyncio
21282128

21292129
from mcp import ClientSession
2130-
from mcp.client.streamable_http import streamablehttp_client
2130+
from mcp.client.streamable_http import streamable_http_client
21312131

21322132

21332133
async def main():
21342134
# Connect to a streamable HTTP server
2135-
async with streamablehttp_client("http://localhost:8000/mcp") as (
2135+
async with streamable_http_client("http://localhost:8000/mcp") as (
21362136
read_stream,
21372137
write_stream,
21382138
_,
@@ -2256,11 +2256,12 @@ cd to the `examples/snippets` directory and run:
22562256
import asyncio
22572257
from urllib.parse import parse_qs, urlparse
22582258

2259+
import httpx
22592260
from pydantic import AnyUrl
22602261

22612262
from mcp import ClientSession
22622263
from mcp.client.auth import OAuthClientProvider, TokenStorage
2263-
from mcp.client.streamable_http import streamablehttp_client
2264+
from mcp.client.streamable_http import streamable_http_client
22642265
from mcp.shared.auth import OAuthClientInformationFull, OAuthClientMetadata, OAuthToken
22652266

22662267

@@ -2314,15 +2315,16 @@ async def main():
23142315
callback_handler=handle_callback,
23152316
)
23162317

2317-
async with streamablehttp_client("http://localhost:8001/mcp", auth=oauth_auth) as (read, write, _):
2318-
async with ClientSession(read, write) as session:
2319-
await session.initialize()
2318+
async with httpx.AsyncClient(auth=oauth_auth, follow_redirects=True) as custom_client:
2319+
async with streamable_http_client("http://localhost:8001/mcp", http_client=custom_client) as (read, write, _):
2320+
async with ClientSession(read, write) as session:
2321+
await session.initialize()
23202322

2321-
tools = await session.list_tools()
2322-
print(f"Available tools: {[tool.name for tool in tools.tools]}")
2323+
tools = await session.list_tools()
2324+
print(f"Available tools: {[tool.name for tool in tools.tools]}")
23232325

2324-
resources = await session.list_resources()
2325-
print(f"Available resources: {[r.uri for r in resources.resources]}")
2326+
resources = await session.list_resources()
2327+
print(f"Available resources: {[r.uri for r in resources.resources]}")
23262328

23272329

23282330
def run():

examples/clients/simple-auth-client/mcp_simple_auth_client/main.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@
1111
import threading
1212
import time
1313
import webbrowser
14-
from datetime import timedelta
1514
from http.server import BaseHTTPRequestHandler, HTTPServer
1615
from typing import Any
1716
from urllib.parse import parse_qs, urlparse
1817

18+
import httpx
1919
from mcp.client.auth import OAuthClientProvider, TokenStorage
2020
from mcp.client.session import ClientSession
2121
from mcp.client.sse import sse_client
22-
from mcp.client.streamable_http import streamablehttp_client
22+
from mcp.client.streamable_http import streamable_http_client
2323
from mcp.shared.auth import OAuthClientInformationFull, OAuthClientMetadata, OAuthToken
2424

2525

@@ -205,12 +205,12 @@ async def _default_redirect_handler(authorization_url: str) -> None:
205205
await self._run_session(read_stream, write_stream, None)
206206
else:
207207
print("📡 Opening StreamableHTTP transport connection with auth...")
208-
async with streamablehttp_client(
209-
url=self.server_url,
210-
auth=oauth_auth,
211-
timeout=timedelta(seconds=60),
212-
) as (read_stream, write_stream, get_session_id):
213-
await self._run_session(read_stream, write_stream, get_session_id)
208+
async with httpx.AsyncClient(auth=oauth_auth, follow_redirects=True) as custom_client:
209+
async with streamable_http_client(
210+
url=self.server_url,
211+
http_client=custom_client,
212+
) as (read_stream, write_stream, get_session_id):
213+
await self._run_session(read_stream, write_stream, get_session_id)
214214

215215
except Exception as e:
216216
print(f"❌ Failed to connect: {e}")

examples/snippets/clients/oauth_client.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,12 @@
1010
import asyncio
1111
from urllib.parse import parse_qs, urlparse
1212

13+
import httpx
1314
from pydantic import AnyUrl
1415

1516
from mcp import ClientSession
1617
from mcp.client.auth import OAuthClientProvider, TokenStorage
17-
from mcp.client.streamable_http import streamablehttp_client
18+
from mcp.client.streamable_http import streamable_http_client
1819
from mcp.shared.auth import OAuthClientInformationFull, OAuthClientMetadata, OAuthToken
1920

2021

@@ -68,15 +69,16 @@ async def main():
6869
callback_handler=handle_callback,
6970
)
7071

71-
async with streamablehttp_client("http://localhost:8001/mcp", auth=oauth_auth) as (read, write, _):
72-
async with ClientSession(read, write) as session:
73-
await session.initialize()
72+
async with httpx.AsyncClient(auth=oauth_auth, follow_redirects=True) as custom_client:
73+
async with streamable_http_client("http://localhost:8001/mcp", http_client=custom_client) as (read, write, _):
74+
async with ClientSession(read, write) as session:
75+
await session.initialize()
7476

75-
tools = await session.list_tools()
76-
print(f"Available tools: {[tool.name for tool in tools.tools]}")
77+
tools = await session.list_tools()
78+
print(f"Available tools: {[tool.name for tool in tools.tools]}")
7779

78-
resources = await session.list_resources()
79-
print(f"Available resources: {[r.uri for r in resources.resources]}")
80+
resources = await session.list_resources()
81+
print(f"Available resources: {[r.uri for r in resources.resources]}")
8082

8183

8284
def run():

examples/snippets/clients/streamable_basic.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@
66
import asyncio
77

88
from mcp import ClientSession
9-
from mcp.client.streamable_http import streamablehttp_client
9+
from mcp.client.streamable_http import streamable_http_client
1010

1111

1212
async def main():
1313
# Connect to a streamable HTTP server
14-
async with streamablehttp_client("http://localhost:8000/mcp") as (
14+
async with streamable_http_client("http://localhost:8000/mcp") as (
1515
read_stream,
1616
write_stream,
1717
_,

src/mcp/client/session_group.py

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,16 @@
1616
from typing import Any, TypeAlias
1717

1818
import anyio
19+
import httpx
1920
from pydantic import BaseModel
2021
from typing_extensions import Self
2122

2223
import mcp
2324
from mcp import types
2425
from mcp.client.sse import sse_client
2526
from mcp.client.stdio import StdioServerParameters
26-
from mcp.client.streamable_http import streamablehttp_client
27+
from mcp.client.streamable_http import streamable_http_client
28+
from mcp.shared._httpx_utils import create_mcp_http_client
2729
from mcp.shared.exceptions import McpError
2830

2931

@@ -44,7 +46,7 @@ class SseServerParameters(BaseModel):
4446

4547

4648
class StreamableHttpParameters(BaseModel):
47-
"""Parameters for intializing a streamablehttp_client."""
49+
"""Parameters for intializing a streamable_http_client."""
4850

4951
# The endpoint URL.
5052
url: str
@@ -250,11 +252,18 @@ async def _establish_session(
250252
)
251253
read, write = await session_stack.enter_async_context(client)
252254
else:
253-
client = streamablehttp_client(
254-
url=server_params.url,
255+
httpx_client = create_mcp_http_client(
255256
headers=server_params.headers,
256-
timeout=server_params.timeout,
257-
sse_read_timeout=server_params.sse_read_timeout,
257+
timeout=httpx.Timeout(
258+
server_params.timeout.total_seconds(),
259+
read=server_params.sse_read_timeout.total_seconds(),
260+
),
261+
)
262+
await session_stack.enter_async_context(httpx_client)
263+
264+
client = streamable_http_client(
265+
url=server_params.url,
266+
http_client=httpx_client,
258267
terminate_on_close=server_params.terminate_on_close,
259268
)
260269
read, write, _ = await session_stack.enter_async_context(client)

0 commit comments

Comments
 (0)