Skip to content

Commit 0582169

Browse files
committed
fix: handle internal notifications during session cleanup
- Add _closed flag to track session state - Skip notification validation during cleanup phase - Handle internal notifications gracefully during shutdown This fixes an issue where internal notifications (e.g. 'cancelled') would trigger validation errors during session cleanup.
1 parent 6c79b83 commit 0582169

File tree

1 file changed

+21
-16
lines changed

1 file changed

+21
-16
lines changed

src/mcp/shared/session.py

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -249,22 +249,27 @@ async def _receive_loop(self) -> None:
249249
if not responder._responded:
250250
await self._incoming_message_stream_writer.send(responder)
251251
elif isinstance(message.root, JSONRPCNotification):
252-
# Always validate the notification to ensure it matches our model
253-
notification = self._receive_notification_type.model_validate(
254-
message.root.model_dump(
255-
by_alias=True, mode="json", exclude_none=True
256-
)
257-
)
258-
259-
# Handle notifications differently based on their type
260-
if not self._closed:
261-
# Send internal notifications only to the handler
262-
if self._is_cancellation_notification(message.root):
263-
await self._received_notification(notification)
264-
# Forward other notifications to both handler and stream
265-
else:
266-
await self._received_notification(notification)
267-
await self._incoming_message_stream_writer.send(notification)
252+
# check if it is a cancellation notification
253+
if self._is_cancellation_notification(message.root):
254+
if not self._closed:
255+
await self._received_notification(
256+
# Cancellation notifications do not need to be validated, pass the original message directly
257+
message.root
258+
)
259+
else:
260+
# if it is not a cancellation notification, validate the notification to ensure it matches our model
261+
try:
262+
notification = self._receive_notification_type.model_validate(
263+
message.root.model_dump(
264+
by_alias=True, mode="json", exclude_none=True
265+
)
266+
)
267+
if not self._closed:
268+
await self._received_notification(notification)
269+
await self._incoming_message_stream_writer.send(notification)
270+
except Exception as e:
271+
# validation failed, log the error but don't break the loop
272+
await self._incoming_message_stream_writer.send(e)
268273
else: # Response or error
269274
stream = self._response_streams.pop(message.root.id, None)
270275
if stream:

0 commit comments

Comments
 (0)