21
21
EmptyResult ,
22
22
ErrorData ,
23
23
InitializeResult ,
24
+ ReadResourceResult ,
24
25
TextContent ,
25
26
TextResourceContents ,
26
27
Tool ,
@@ -50,7 +51,11 @@ def __init__(self):
50
51
async def handle_read_resource (uri : AnyUrl ) -> str | bytes :
51
52
if uri .scheme == "foobar" :
52
53
return f"Read { uri .host } "
53
- # TODO: make this an error
54
+ elif uri .scheme == "slow" :
55
+ # Simulate a slow resource
56
+ await anyio .sleep (2.0 )
57
+ return f"Slow response from { uri .host } "
58
+
54
59
raise McpError (
55
60
error = ErrorData (
56
61
code = 404 , message = "OOPS! no resource with that URI was found"
@@ -200,12 +205,13 @@ async def test_sse_client_basic_connection(server: None, server_url: str) -> Non
200
205
async def initialized_sse_client_session (
201
206
server , server_url : str
202
207
) -> AsyncGenerator [ClientSession , None ]:
203
- async with sse_client (server_url + "/sse" ) as streams :
208
+ async with sse_client (server_url + "/sse" , sse_read_timeout = 0.5 ) as streams :
204
209
async with ClientSession (* streams ) as session :
205
210
await session .initialize ()
206
211
yield session
207
212
208
213
214
+
209
215
@pytest .mark .anyio
210
216
async def test_sse_client_happy_request_and_response (
211
217
initialized_sse_client_session : ClientSession ,
@@ -226,4 +232,23 @@ async def test_sse_client_exception_handling(
226
232
await session .read_resource (uri = AnyUrl ("xxx://will-not-work" ))
227
233
228
234
229
- # TODO: test that timeouts are respected and that the error comes back
235
+ @pytest .mark .anyio
236
+ @pytest .mark .skip (
237
+ "this test highlights a possible bug in SSE read timeout exception handling"
238
+ )
239
+ async def test_sse_client_timeout (
240
+ initialized_sse_client_session : ClientSession ,
241
+ ) -> None :
242
+ session = initialized_sse_client_session
243
+
244
+ # sanity check that normal, fast responses are working
245
+ response = await session .read_resource (uri = AnyUrl ("foobar://1" ))
246
+ assert isinstance (response , ReadResourceResult )
247
+
248
+ with anyio .move_on_after (3 ):
249
+ with pytest .raises (McpError , match = "Read timed out" ):
250
+ response = await session .read_resource (uri = AnyUrl ("slow://2" ))
251
+ # we should receive an error here
252
+ return
253
+
254
+ pytest .fail ("the client should have timed out and returned an error already" )
0 commit comments