1515from mcp .shared .message import MessageMetadata , ServerMessageMetadata , SessionMessage
1616from mcp .types import (
1717 CancelledNotification ,
18+ CancelledNotificationParams ,
1819 ClientNotification ,
1920 ClientRequest ,
2021 ClientResult ,
3334SendRequestT = TypeVar ("SendRequestT" , ClientRequest , ServerRequest )
3435SendResultT = TypeVar ("SendResultT" , ClientResult , ServerResult )
3536SendNotificationT = TypeVar ("SendNotificationT" , ClientNotification , ServerNotification )
37+ SendNotificationInternalT = TypeVar ("SendNotificationInternalT" , CancelledNotification , ClientNotification , ServerNotification )
3638ReceiveRequestT = TypeVar ("ReceiveRequestT" , ClientRequest , ServerRequest )
3739ReceiveResultT = TypeVar ("ReceiveResultT" , bound = BaseModel )
3840ReceiveNotificationT = TypeVar (
@@ -254,6 +256,8 @@ async def send_request(
254256 elif self ._session_read_timeout_seconds is not None :
255257 timeout = self ._session_read_timeout_seconds .total_seconds ()
256258
259+ response_or_error = None
260+
257261 try :
258262 with anyio .fail_after (timeout ):
259263 response_or_error = await response_stream_reader .receive ()
@@ -268,7 +272,21 @@ async def send_request(
268272 ),
269273 )
270274 )
275+ except anyio .get_cancelled_exc_class ():
276+ with anyio .CancelScope (shield = True ):
277+ notification = CancelledNotification (
278+ method = "notifications/cancelled" ,
279+ params = CancelledNotificationParams (
280+ requestId = request_id ,
281+ reason = "cancelled"
282+ )
283+ )
284+ await self ._send_notification_internal (notification , request_id , )
271285
286+ if response_or_error is None :
287+ raise McpError (
288+ ErrorData (code = 32601 , message = "request cancelled" )
289+ )
272290 if isinstance (response_or_error , JSONRPCError ):
273291 raise McpError (response_or_error .error )
274292 else :
@@ -283,6 +301,13 @@ async def send_notification(
283301 self ,
284302 notification : SendNotificationT ,
285303 related_request_id : RequestId | None = None ,
304+ ) -> None :
305+ await self ._send_notification_internal (notification , related_request_id )
306+
307+ async def _send_notification_internal (
308+ self ,
309+ notification : SendNotificationInternalT ,
310+ related_request_id : RequestId | None = None ,
286311 ) -> None :
287312 """
288313 Emits a notification, which is a one-way message that does not expect
0 commit comments