@@ -564,15 +564,16 @@ async def mock_client():
564564 assert resp1 .message .root .error .code == types .METHOD_NOT_FOUND
565565 assert resp1 .message .root .error .message == "Method not found"
566566
567- # 2. Send malformed known method request (initialize with invalid params shape )
567+ # 2. Send malformed known method request (initialize missing required capabilities/clientInfo )
568568 await client_to_server_send .send (
569569 SessionMessage (
570570 types .JSONRPCMessage (
571571 types .JSONRPCRequest (
572572 jsonrpc = "2.0" ,
573573 id = 2 ,
574574 method = "initialize" ,
575- params = {"protocolVersion" : 12345 }, # invalid type for protocolVersion
575+ # protocolVersion is valid; capabilities/clientInfo are missing
576+ params = {"protocolVersion" : "2025-06-18" },
576577 )
577578 )
578579 )
@@ -593,3 +594,66 @@ async def mock_client():
593594 ):
594595 tg .start_soon (run_server )
595596 tg .start_soon (mock_client )
597+
598+
599+ @pytest .mark .anyio
600+ async def test_unknown_notification_receives_no_response ():
601+ """Test that unknown notifications go unanswered, per JSON-RPC (notifications must not be responded to)."""
602+ server_to_client_send , server_to_client_receive = anyio .create_memory_object_stream [SessionMessage ](1 )
603+ client_to_server_send , client_to_server_receive = anyio .create_memory_object_stream [SessionMessage | Exception ](1 )
604+
605+ async def run_server ():
606+ async with ServerSession (
607+ client_to_server_receive ,
608+ server_to_client_send ,
609+ InitializationOptions (
610+ server_name = "mcp" ,
611+ server_version = "0.1.0" ,
612+ capabilities = ServerCapabilities (),
613+ ),
614+ ):
615+ await anyio .sleep (0.2 )
616+
617+ async def mock_client ():
618+ # 1. Send an unknown notification
619+ await client_to_server_send .send (
620+ SessionMessage (
621+ types .JSONRPCMessage (
622+ types .JSONRPCNotification (
623+ jsonrpc = "2.0" ,
624+ method = "totally/bogus" ,
625+ params = {},
626+ )
627+ )
628+ )
629+ )
630+
631+ # 2. Send a request afterwards; the first response received must be for the
632+ # request, proving the notification produced no response
633+ await client_to_server_send .send (
634+ SessionMessage (
635+ types .JSONRPCMessage (
636+ types .JSONRPCRequest (
637+ jsonrpc = "2.0" ,
638+ id = 1 ,
639+ method = "totally/bogus" ,
640+ params = {},
641+ )
642+ )
643+ )
644+ )
645+
646+ resp = await server_to_client_receive .receive ()
647+ assert isinstance (resp .message .root , types .JSONRPCError )
648+ assert resp .message .root .id == 1
649+ assert resp .message .root .error .code == types .METHOD_NOT_FOUND
650+
651+ async with (
652+ client_to_server_send ,
653+ client_to_server_receive ,
654+ server_to_client_send ,
655+ server_to_client_receive ,
656+ anyio .create_task_group () as tg ,
657+ ):
658+ tg .start_soon (run_server )
659+ tg .start_soon (mock_client )
0 commit comments