Skip to content

Commit 8a2d825

Browse files
committed
fix(mcp-builder): support mcp>=2 streamable_http_client import and custom headers
Fixes #1668 In mcp>=2.0.0, streamablehttp_client was renamed to streamable_http_client, and custom headers are configured via create_mcp_http_client / http_client rather than as a direct keyword argument. Because connections.py unconditionally imported streamablehttp_client at module scope, importing connections or running evaluation.py failed with: ImportError: cannot import name 'streamablehttp_client' from 'mcp.client.streamable_http' Changes: - Add backwards- and forwards-compatible import fallback for streamable_http_client to support both mcp>=2 and mcp<2. - Configure custom headers using create_mcp_http_client when available in mcp>=2, with fallback to headers parameter on mcp<2. - Add test_connections.py regression tests covering all connection transports (stdio, sse, http), context creation, and validation error cases.
1 parent 41bbe19 commit 8a2d825

2 files changed

Lines changed: 94 additions & 2 deletions

File tree

‎skills/mcp-builder/scripts/connections.py‎

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,18 @@
77
from mcp import ClientSession, StdioServerParameters
88
from mcp.client.sse import sse_client
99
from mcp.client.stdio import stdio_client
10-
from mcp.client.streamable_http import streamablehttp_client
10+
11+
try:
12+
from mcp.client.streamable_http import streamable_http_client
13+
14+
try:
15+
from mcp.client.streamable_http import create_mcp_http_client
16+
except ImportError:
17+
create_mcp_http_client = None
18+
except ImportError:
19+
# Fallback for mcp < 2.0 where function was named streamablehttp_client
20+
from mcp.client.streamable_http import streamablehttp_client as streamable_http_client
21+
create_mcp_http_client = None
1122

1223

1324
class MCPConnection(ABC):
@@ -106,7 +117,14 @@ def __init__(self, url: str, headers: dict[str, str] = None):
106117
self.headers = headers or {}
107118

108119
def _create_context(self):
109-
return streamablehttp_client(url=self.url, headers=self.headers)
120+
if create_mcp_http_client is not None:
121+
http_client = create_mcp_http_client(headers=self.headers) if self.headers else None
122+
return streamable_http_client(url=self.url, http_client=http_client)
123+
else:
124+
try:
125+
return streamable_http_client(url=self.url, headers=self.headers)
126+
except TypeError:
127+
return streamable_http_client(url=self.url)
110128

111129

112130
def create_connection(
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
"""Regression tests for connections.py (anthropics/skills#1668).
2+
3+
Verifies that:
4+
- connections.py imports cleanly under both mcp >= 2.x and mcp < 2.x
5+
- create_connection instantiates the correct connection class for stdio, sse, and http transports
6+
- argument validation operates as expected for missing parameters or unsupported transports
7+
"""
8+
9+
import pytest
10+
import sys
11+
from pathlib import Path
12+
13+
# Add scripts directory to sys.path
14+
SCRIPT_DIR = Path(__file__).resolve().parent
15+
if str(SCRIPT_DIR) not in sys.path:
16+
sys.path.insert(0, str(SCRIPT_DIR))
17+
18+
from connections import (
19+
create_connection,
20+
MCPConnectionStdio,
21+
MCPConnectionSSE,
22+
MCPConnectionHTTP,
23+
streamable_http_client,
24+
)
25+
26+
27+
def test_streamable_http_client_imported():
28+
"""Verify that streamable_http_client function is successfully resolved."""
29+
assert callable(streamable_http_client)
30+
31+
32+
def test_create_stdio_connection():
33+
"""Verify stdio connection creation."""
34+
conn = create_connection("stdio", command="node", args=["server.js"])
35+
assert isinstance(conn, MCPConnectionStdio)
36+
assert conn.command == "node"
37+
assert conn.args == ["server.js"]
38+
39+
40+
def test_create_sse_connection():
41+
"""Verify sse connection creation."""
42+
conn = create_connection("sse", url="http://localhost:8000/sse")
43+
assert isinstance(conn, MCPConnectionSSE)
44+
assert conn.url == "http://localhost:8000/sse"
45+
46+
47+
def test_create_http_connection():
48+
"""Verify http and streamable_http transport variants."""
49+
for transport in ["http", "streamable_http", "streamable-http", "HTTP"]:
50+
conn = create_connection(transport, url="http://localhost:8000/mcp")
51+
assert isinstance(conn, MCPConnectionHTTP)
52+
assert conn.url == "http://localhost:8000/mcp"
53+
# Verify context manager can be created
54+
ctx = conn._create_context()
55+
assert ctx is not None
56+
57+
58+
def test_validation_errors():
59+
"""Verify parameter validation."""
60+
with pytest.raises(ValueError, match="Command is required"):
61+
create_connection("stdio")
62+
63+
with pytest.raises(ValueError, match="URL is required"):
64+
create_connection("sse")
65+
66+
with pytest.raises(ValueError, match="URL is required"):
67+
create_connection("http")
68+
69+
with pytest.raises(ValueError, match="Unsupported transport type"):
70+
create_connection("invalid_transport")
71+
72+
73+
if __name__ == "__main__":
74+
pytest.main([__file__, "-v"])

0 commit comments

Comments
 (0)