11import json
22from collections .abc import Coroutine
3+ from datetime import datetime
34from typing import Any
45from unittest .mock import AsyncMock , Mock , patch
56
1011from mcp .server .lowlevel .server import NotificationOptions , Server
1112from mcp .server .minimcp .exceptions import (
1213 ContextError ,
14+ InternalMCPError ,
15+ InvalidArgumentsError ,
1316 InvalidJSONError ,
1417 InvalidJSONRPCMessageError ,
1518 InvalidMessageError ,
19+ MCPRuntimeError ,
20+ PrimitiveError ,
1621 RequestHandlerNotFoundError ,
22+ ResourceNotFoundError ,
1723 UnsupportedMessageTypeError ,
1824)
1925from mcp .server .minimcp .managers .context_manager import Context , ContextManager
@@ -711,13 +717,10 @@ async def test_error_metadata_in_response(self):
711717 assert "isoTimestamp" in error_data
712718
713719 # Verify timestamp is valid ISO format
714- from datetime import datetime
715-
716720 datetime .fromisoformat (error_data ["isoTimestamp" ])
717721
718722 async def test_process_error_with_internal_mcp_error (self ):
719723 """Test _process_error method with InternalMCPError that has data."""
720- from mcp .server .minimcp .exceptions import ResourceNotFoundError
721724
722725 server : MiniMCP [Any ] = MiniMCP (name = "process-error-test" )
723726
@@ -736,11 +739,6 @@ async def test_process_error_with_internal_mcp_error(self):
736739
737740 async def test_handle_with_different_error_types (self ):
738741 """Test handling different types of MiniMCP errors."""
739- from mcp .server .minimcp .exceptions import (
740- InvalidArgumentsError ,
741- MCPRuntimeError ,
742- PrimitiveError ,
743- )
744742
745743 server : MiniMCP [Any ] = MiniMCP (name = "error-types-test" )
746744
@@ -838,3 +836,91 @@ async def test_limiter_integration_with_errors(self):
838836 for i , response in enumerate (results ):
839837 assert response ["id" ] == i
840838 assert "error" in response
839+
840+ async def test_unsupported_message_type_error (self ):
841+ """Test handling of UnsupportedMessageTypeError."""
842+ server : MiniMCP [Any ] = MiniMCP (name = "test-server" )
843+
844+ # Create a message that will trigger UnsupportedMessageTypeError
845+ # This happens when the message is valid JSON-RPC but not a request or notification
846+ with patch ("mcp.server.minimcp.minimcp.MiniMCP._handle_rpc_msg" ) as mock_handle :
847+ from mcp .server .minimcp .exceptions import UnsupportedMessageTypeError
848+
849+ mock_handle .side_effect = UnsupportedMessageTypeError ("Unsupported message type" )
850+
851+ message = json .dumps ({"jsonrpc" : "2.0" , "id" : 1 , "method" : "test" , "params" : {}})
852+ result = await server .handle (message )
853+
854+ # Should return an error response
855+ response = json .loads (result ) # type: ignore
856+ assert "error" in response
857+ assert response ["id" ] == 1
858+
859+ async def test_request_handler_not_found_error (self ):
860+ """Test handling of RequestHandlerNotFoundError."""
861+ server : MiniMCP [Any ] = MiniMCP (name = "test-server" )
862+
863+ # Create a message with a method that doesn't exist in MiniMCP
864+ message = json .dumps (
865+ {"jsonrpc" : "2.0" , "id" : 1 , "method" : "resources/subscribe" , "params" : {"uri" : "file:///config.json" }}
866+ )
867+ result = await server .handle (message )
868+
869+ # Should return a METHOD_NOT_FOUND error
870+ response = json .loads (result ) # type: ignore
871+ assert "error" in response
872+ assert response ["error" ]["code" ] == types .METHOD_NOT_FOUND
873+ assert response ["id" ] == 1
874+
875+ async def test_resource_not_found_error (self ):
876+ """Test handling of ResourceNotFoundError."""
877+ server : MiniMCP [Any ] = MiniMCP (name = "test-server" )
878+
879+ # Try to read a resource that doesn't exist
880+ message = json .dumps (
881+ {"jsonrpc" : "2.0" , "id" : 1 , "method" : "resources/read" , "params" : {"uri" : "nonexistent://resource" }}
882+ )
883+ result = await server .handle (message )
884+
885+ # Should return a RESOURCE_NOT_FOUND error
886+ response = json .loads (result ) # type: ignore
887+ assert "error" in response
888+ assert response ["error" ]["code" ] == types .RESOURCE_NOT_FOUND
889+ assert response ["id" ] == 1
890+
891+ async def test_internal_mcp_error (self ):
892+ """Test handling of InternalMCPError."""
893+
894+ server : MiniMCP [Any ] = MiniMCP (name = "test-server" )
895+
896+ # Mock _handle_rpc_msg to raise InternalMCPError
897+ with patch ("mcp.server.minimcp.minimcp.MiniMCP._handle_rpc_msg" ) as mock_handle :
898+ mock_handle .side_effect = InternalMCPError ("Internal error" )
899+
900+ message = json .dumps ({"jsonrpc" : "2.0" , "id" : 1 , "method" : "test" , "params" : {}})
901+ result = await server .handle (message )
902+
903+ # Should return an INTERNAL_ERROR response
904+ response = json .loads (result ) # type: ignore
905+ assert "error" in response
906+ assert response ["error" ]["code" ] == types .INTERNAL_ERROR
907+ assert response ["id" ] == 1
908+
909+ async def test_error_type_checking_branches (self ):
910+ """Test the error type checking branches in _parse_message."""
911+ server : MiniMCP [Any ] = MiniMCP (name = "test-server" )
912+
913+ # Test with invalid JSON that triggers json_invalid error
914+ invalid_json = "{invalid json"
915+ with pytest .raises (InvalidMessageError ):
916+ await server .handle (invalid_json )
917+
918+ # Test with valid JSON but invalid JSON-RPC (missing jsonrpc field)
919+ invalid_jsonrpc = json .dumps ({"id" : 1 , "method" : "test" })
920+ with pytest .raises (InvalidMessageError ):
921+ await server .handle (invalid_jsonrpc )
922+
923+ # Test with wrong jsonrpc version
924+ wrong_version = json .dumps ({"jsonrpc" : "1.0" , "id" : 1 , "method" : "test" , "params" : {}})
925+ with pytest .raises (InvalidMessageError ):
926+ await server .handle (wrong_version )
0 commit comments