15
15
from contextlib import AsyncExitStack
16
16
import functools
17
17
import sys
18
+ from datetime import timedelta
18
19
from typing import Any , TextIO
19
20
import anyio
20
21
from pydantic import BaseModel
23
24
from mcp import ClientSession , StdioServerParameters
24
25
from mcp .client .sse import sse_client
25
26
from mcp .client .stdio import stdio_client
27
+ from mcp .client .streamable_http import streamablehttp_client
26
28
except ImportError as e :
27
29
import sys
28
30
@@ -48,6 +50,19 @@ class SseServerParams(BaseModel):
48
50
sse_read_timeout : float = 60 * 5
49
51
50
52
53
+ class StreamableHTTPServerParams (BaseModel ):
54
+ """Parameters for the MCP SSE connection.
55
+
56
+ See MCP SSE Client documentation for more details.
57
+ https://github.com/modelcontextprotocol/python-sdk/blob/main/src/mcp/client/streamable_http.py
58
+ """
59
+ url : str
60
+ headers : dict [str , Any ] | None = None
61
+ timeout : float = 5
62
+ sse_read_timeout : float = 60 * 5
63
+ terminate_on_close : bool = True
64
+
65
+
51
66
def retry_on_closed_resource (async_reinit_func_name : str ):
52
67
"""Decorator to automatically reinitialize session and retry action.
53
68
@@ -117,7 +132,7 @@ class MCPSessionManager:
117
132
118
133
def __init__ (
119
134
self ,
120
- connection_params : StdioServerParameters | SseServerParams ,
135
+ connection_params : StdioServerParameters | SseServerParams | StreamableHTTPServerParams ,
121
136
exit_stack : AsyncExitStack ,
122
137
errlog : TextIO = sys .stderr ,
123
138
) -> ClientSession :
@@ -153,7 +168,7 @@ async def create_session(self) -> ClientSession:
153
168
async def initialize_session (
154
169
cls ,
155
170
* ,
156
- connection_params : StdioServerParameters | SseServerParams ,
171
+ connection_params : StdioServerParameters | SseServerParams | StreamableHTTPServerParams ,
157
172
exit_stack : AsyncExitStack ,
158
173
errlog : TextIO = sys .stderr ,
159
174
) -> ClientSession :
@@ -177,6 +192,14 @@ async def initialize_session(
177
192
timeout = connection_params .timeout ,
178
193
sse_read_timeout = connection_params .sse_read_timeout ,
179
194
)
195
+ elif isinstance (connection_params , StreamableHTTPServerParams ):
196
+ client = streamablehttp_client (
197
+ url = connection_params .url ,
198
+ headers = connection_params .headers ,
199
+ timeout = timedelta (seconds = connection_params .timeout ),
200
+ sse_read_timeout = timedelta (seconds = connection_params .sse_read_timeout ),
201
+ terminate_on_close = connection_params .terminate_on_close ,
202
+ )
180
203
else :
181
204
raise ValueError (
182
205
'Unable to initialize connection. Connection should be'
@@ -185,6 +208,6 @@ async def initialize_session(
185
208
)
186
209
187
210
transports = await exit_stack .enter_async_context (client )
188
- session = await exit_stack .enter_async_context (ClientSession (* transports ))
211
+ session = await exit_stack .enter_async_context (ClientSession (* transports [: 2 ] ))
189
212
await session .initialize ()
190
213
return session
0 commit comments