@@ -187,7 +187,6 @@ def __init__(
187
187
self ._receive_notification_type = receive_notification_type
188
188
self ._session_read_timeout_seconds = read_timeout_seconds
189
189
self ._in_flight = {}
190
-
191
190
self ._exit_stack = AsyncExitStack ()
192
191
193
192
async def __aenter__ (self ) -> Self :
@@ -232,45 +231,48 @@ async def send_request(
232
231
](1 )
233
232
self ._response_streams [request_id ] = response_stream
234
233
235
- self ._exit_stack .push_async_callback (lambda : response_stream .aclose ())
236
- self ._exit_stack .push_async_callback (lambda : response_stream_reader .aclose ())
237
-
238
- jsonrpc_request = JSONRPCRequest (
239
- jsonrpc = "2.0" ,
240
- id = request_id ,
241
- ** request .model_dump (by_alias = True , mode = "json" , exclude_none = True ),
242
- )
243
-
244
- # TODO: Support progress callbacks
245
-
246
- await self ._write_stream .send (JSONRPCMessage (jsonrpc_request ))
247
-
248
- # request read timeout takes precedence over session read timeout
249
- timeout = None
250
- if request_read_timeout_seconds is not None :
251
- timeout = request_read_timeout_seconds .total_seconds ()
252
- elif self ._session_read_timeout_seconds is not None :
253
- timeout = self ._session_read_timeout_seconds .total_seconds ()
254
-
255
234
try :
256
- with anyio .fail_after (timeout ):
257
- response_or_error = await response_stream_reader .receive ()
258
- except TimeoutError :
259
- raise McpError (
260
- ErrorData (
261
- code = httpx .codes .REQUEST_TIMEOUT ,
262
- message = (
263
- f"Timed out while waiting for response to "
264
- f"{ request .__class__ .__name__ } . Waited "
265
- f"{ timeout } seconds."
266
- ),
267
- )
235
+ jsonrpc_request = JSONRPCRequest (
236
+ jsonrpc = "2.0" ,
237
+ id = request_id ,
238
+ ** request .model_dump (by_alias = True , mode = "json" , exclude_none = True ),
268
239
)
269
240
270
- if isinstance (response_or_error , JSONRPCError ):
271
- raise McpError (response_or_error .error )
272
- else :
273
- return result_type .model_validate (response_or_error .result )
241
+ # TODO: Support progress callbacks
242
+
243
+ await self ._write_stream .send (JSONRPCMessage (jsonrpc_request ))
244
+
245
+ # request read timeout takes precedence over session read timeout
246
+ timeout = None
247
+ if request_read_timeout_seconds is not None :
248
+ timeout = request_read_timeout_seconds .total_seconds ()
249
+ elif self ._session_read_timeout_seconds is not None :
250
+ timeout = self ._session_read_timeout_seconds .total_seconds ()
251
+
252
+ try :
253
+ with anyio .fail_after (timeout ):
254
+ response_or_error = await response_stream_reader .receive ()
255
+ except TimeoutError :
256
+ raise McpError (
257
+ ErrorData (
258
+ code = httpx .codes .REQUEST_TIMEOUT ,
259
+ message = (
260
+ f"Timed out while waiting for response to "
261
+ f"{ request .__class__ .__name__ } . Waited "
262
+ f"{ timeout } seconds."
263
+ ),
264
+ )
265
+ )
266
+
267
+ if isinstance (response_or_error , JSONRPCError ):
268
+ raise McpError (response_or_error .error )
269
+ else :
270
+ return result_type .model_validate (response_or_error .result )
271
+
272
+ finally :
273
+ self ._response_streams .pop (request_id , None )
274
+ await response_stream .aclose ()
275
+ await response_stream_reader .aclose ()
274
276
275
277
async def send_notification (self , notification : SendNotificationT ) -> None :
276
278
"""
0 commit comments