2525 JSONRPCRequest ,
2626 JSONRPCResponse ,
2727 RequestId ,
28+ jsonrpc_message_adapter ,
2829)
2930
3031logger = logging .getLogger (__name__ )
@@ -95,11 +96,11 @@ def _prepare_headers(self) -> dict[str, str]:
9596
9697 def _is_initialization_request (self , message : JSONRPCMessage ) -> bool :
9798 """Check if the message is an initialization request."""
98- return isinstance (message . root , JSONRPCRequest ) and message . root .method == "initialize"
99+ return isinstance (message , JSONRPCRequest ) and message .method == "initialize"
99100
100101 def _is_initialized_notification (self , message : JSONRPCMessage ) -> bool :
101102 """Check if the message is an initialized notification."""
102- return isinstance (message . root , JSONRPCNotification ) and message . root .method == "notifications/initialized"
103+ return isinstance (message , JSONRPCNotification ) and message .method == "notifications/initialized"
103104
104105 def _maybe_extract_session_id_from_response (self , response : httpx .Response ) -> None :
105106 """Extract and store session ID from response headers."""
@@ -110,15 +111,15 @@ def _maybe_extract_session_id_from_response(self, response: httpx.Response) -> N
110111
111112 def _maybe_extract_protocol_version_from_message (self , message : JSONRPCMessage ) -> None :
112113 """Extract protocol version from initialization response message."""
113- if isinstance (message . root , JSONRPCResponse ) and message . root .result : # pragma: no branch
114+ if isinstance (message , JSONRPCResponse ) and message .result : # pragma: no branch
114115 try :
115116 # Parse the result as InitializeResult for type safety
116- init_result = InitializeResult .model_validate (message .root . result , by_name = False )
117+ init_result = InitializeResult .model_validate (message .result , by_name = False )
117118 self .protocol_version = str (init_result .protocol_version )
118119 logger .info (f"Negotiated protocol version: { self .protocol_version } " )
119120 except Exception : # pragma: no cover
120121 logger .warning ("Failed to parse initialization response as InitializeResult" , exc_info = True )
121- logger .warning (f"Raw result: { message .root . result } " )
122+ logger .warning (f"Raw result: { message .result } " )
122123
123124 async def _handle_sse_event (
124125 self ,
@@ -137,16 +138,16 @@ async def _handle_sse_event(
137138 await resumption_callback (sse .id )
138139 return False
139140 try :
140- message = JSONRPCMessage . model_validate_json (sse .data , by_name = False )
141+ message = jsonrpc_message_adapter . validate_json (sse .data , by_name = False )
141142 logger .debug (f"SSE message: { message } " )
142143
143144 # Extract protocol version from initialization response
144145 if is_initialization :
145146 self ._maybe_extract_protocol_version_from_message (message )
146147
147148 # If this is a response and we have original_request_id, replace it
148- if original_request_id is not None and isinstance (message . root , JSONRPCResponse | JSONRPCError ):
149- message .root . id = original_request_id
149+ if original_request_id is not None and isinstance (message , JSONRPCResponse | JSONRPCError ):
150+ message .id = original_request_id
150151
151152 session_message = SessionMessage (message )
152153 await read_stream_writer .send (session_message )
@@ -157,7 +158,7 @@ async def _handle_sse_event(
157158
158159 # If this is a response or error return True indicating completion
159160 # Otherwise, return False to continue listening
160- return isinstance (message . root , JSONRPCResponse | JSONRPCError )
161+ return isinstance (message , JSONRPCResponse | JSONRPCError )
161162
162163 except Exception as exc : # pragma: no cover
163164 logger .exception ("Error parsing SSE message" )
@@ -222,8 +223,8 @@ async def _handle_resumption_request(self, ctx: RequestContext) -> None:
222223
223224 # Extract original request ID to map responses
224225 original_request_id = None
225- if isinstance (ctx .session_message .message . root , JSONRPCRequest ): # pragma: no branch
226- original_request_id = ctx .session_message .message .root . id
226+ if isinstance (ctx .session_message .message , JSONRPCRequest ): # pragma: no branch
227+ original_request_id = ctx .session_message .message .id
227228
228229 async with aconnect_sse (ctx .client , "GET" , self .url , headers = headers ) as event_source :
229230 event_source .response .raise_for_status ()
@@ -257,20 +258,17 @@ async def _handle_post_request(self, ctx: RequestContext) -> None:
257258 return
258259
259260 if response .status_code == 404 : # pragma: no branch
260- if isinstance (message .root , JSONRPCRequest ):
261- await self ._send_session_terminated_error ( # pragma: no cover
262- ctx .read_stream_writer , # pragma: no cover
263- message .root .id , # pragma: no cover
264- ) # pragma: no cover
265- return # pragma: no cover
261+ if isinstance (message , JSONRPCRequest ): # pragma: no branch
262+ await self ._send_session_terminated_error (ctx .read_stream_writer , message .id )
263+ return
266264
267265 response .raise_for_status ()
268266 if is_initialization :
269267 self ._maybe_extract_session_id_from_response (response )
270268
271269 # Per https://modelcontextprotocol.io/specification/2025-06-18/basic#notifications:
272270 # The server MUST NOT send a response to notifications.
273- if isinstance (message . root , JSONRPCRequest ):
271+ if isinstance (message , JSONRPCRequest ):
274272 content_type = response .headers .get ("content-type" , "" ).lower ()
275273 if content_type .startswith ("application/json" ):
276274 await self ._handle_json_response (response , ctx .read_stream_writer , is_initialization )
@@ -291,7 +289,7 @@ async def _handle_json_response(
291289 """Handle JSON response from the server."""
292290 try :
293291 content = await response .aread ()
294- message = JSONRPCMessage . model_validate_json (content , by_name = False )
292+ message = jsonrpc_message_adapter . validate_json (content , by_name = False )
295293
296294 # Extract protocol version from initialization response
297295 if is_initialization :
@@ -365,8 +363,8 @@ async def _handle_reconnection(
365363
366364 # Extract original request ID to map responses
367365 original_request_id = None
368- if isinstance (ctx .session_message .message . root , JSONRPCRequest ): # pragma: no branch
369- original_request_id = ctx .session_message .message .root . id
366+ if isinstance (ctx .session_message .message , JSONRPCRequest ): # pragma: no branch
367+ original_request_id = ctx .session_message .message .id
370368
371369 try :
372370 async with aconnect_sse (ctx .client , "GET" , self .url , headers = headers ) as event_source :
@@ -463,7 +461,7 @@ async def handle_request_async():
463461 await self ._handle_post_request (ctx )
464462
465463 # If this is a request, start a new task to handle it
466- if isinstance (message . root , JSONRPCRequest ):
464+ if isinstance (message , JSONRPCRequest ):
467465 tg .start_soon (handle_request_async )
468466 else :
469467 await handle_request_async ()
0 commit comments