@@ -169,6 +169,8 @@ def __init__(
169169 ] = {}
170170 self ._sse_stream_writers : dict [RequestId , MemoryObjectSendStream [dict [str , str ]]] = {}
171171 self ._terminated = False
172+ # Idle timeout cancel scope; managed by the session manager.
173+ self .idle_scope : anyio .CancelScope | None = None
172174
173175 @property
174176 def is_terminated (self ) -> bool :
@@ -298,12 +300,12 @@ def _create_error_response(
298300 # Return a properly formatted JSON error response
299301 error_response = JSONRPCError (
300302 jsonrpc = "2.0" ,
301- id = "server-error" , # We don't have a request ID for general errors
303+ id = None ,
302304 error = ErrorData (code = error_code , message = error_message ),
303305 )
304306
305307 return Response (
306- error_response .model_dump_json (by_alias = True , exclude_none = True ),
308+ error_response .model_dump_json (by_alias = True , exclude_unset = True ),
307309 status_code = status_code ,
308310 headers = response_headers ,
309311 )
@@ -323,7 +325,7 @@ def _create_json_response(
323325 response_headers [MCP_SESSION_ID_HEADER ] = self .mcp_session_id
324326
325327 return Response (
326- response_message .model_dump_json (by_alias = True , exclude_none = True ) if response_message else None ,
328+ response_message .model_dump_json (by_alias = True , exclude_unset = True ) if response_message else None ,
327329 status_code = status_code ,
328330 headers = response_headers ,
329331 )
@@ -336,7 +338,7 @@ def _create_event_data(self, event_message: EventMessage) -> dict[str, str]:
336338 """Create event data dictionary from an EventMessage."""
337339 event_data = {
338340 "event" : "message" ,
339- "data" : event_message .message .model_dump_json (by_alias = True , exclude_none = True ),
341+ "data" : event_message .message .model_dump_json (by_alias = True , exclude_unset = True ),
340342 }
341343
342344 # If an event ID was provided, include it
@@ -975,12 +977,11 @@ async def message_router():
975977 # Determine which request stream(s) should receive this message
976978 message = session_message .message
977979 target_request_id = None
978- # Check if this is a response
979- if isinstance (message , JSONRPCResponse | JSONRPCError ):
980- response_id = str (message .id )
981- # If this response is for an existing request stream,
982- # send it there
983- target_request_id = response_id
980+ # Check if this is a response with a known request id.
981+ # Null-id errors (e.g., parse errors) fall through to
982+ # the GET stream since they can't be correlated.
983+ if isinstance (message , JSONRPCResponse | JSONRPCError ) and message .id is not None :
984+ target_request_id = str (message .id )
984985 # Extract related_request_id from meta if it exists
985986 elif ( # pragma: no cover
986987 session_message .metadata is not None
0 commit comments