5555if TYPE_CHECKING :
5656 from typing import Any , Awaitable , Callable , ContextManager , Optional , Tuple , Union
5757
58+ from mcp .server .context import CallNext , HandlerResult
5859 from mcp_types import (
5960 CallToolResult ,
6061 GetPromptResult ,
@@ -943,6 +944,21 @@ async def wrapper(*args: "Any") -> "Any":
943944 Server .read_resource = patched_read_resource # type: ignore[attr-defined]
944945
945946
947+ async def _sentry_middleware (
948+ ctx : "ServerRequestContext[Any, Any]" , call_next : "CallNext"
949+ ) -> "HandlerResult" :
950+ if ctx .method == "tools/call" :
951+ return await _tool_handler_wrapper (call_next , ctx )
952+
953+ if ctx .method == "prompts/get" :
954+ return await _prompt_handler_wrapper (call_next , ctx )
955+
956+ if ctx .method == "resources/read" :
957+ return await _resource_handler_wrapper (call_next , ctx )
958+
959+ return await call_next (ctx )
960+
961+
946962def _patch_lowlevel_server_v2 () -> None :
947963 """Patches the v2 Server to wrap tool/prompt/resource handlers.
948964
@@ -955,113 +971,11 @@ def _patch_lowlevel_server_v2() -> None:
955971
956972 @wraps (original_init )
957973 def patched_init (self : "Server" , * args : "Any" , ** kwargs : "Any" ) -> None :
958- on_tool_call = kwargs .get ("on_call_tool" )
959- if on_tool_call is not None and not getattr (
960- on_tool_call , "__sentry_mcp_wrapped__" , False
961- ):
962-
963- @wraps (on_tool_call )
964- async def wrapper (* args : "Any" , ** kwargs : "Any" ) -> "Any" :
965- return await _tool_handler_wrapper (
966- on_tool_call , args , kwargs , force_await = False
967- )
968-
969- wrapper .__sentry_mcp_wrapped__ = True # type: ignore[attr-defined]
970- kwargs ["on_call_tool" ] = wrapper
971-
972- on_get_prompt = kwargs .get ("on_get_prompt" )
973- if on_get_prompt is not None and not getattr (
974- on_get_prompt , "__sentry_mcp_wrapped__" , False
975- ):
976-
977- @wraps (on_get_prompt )
978- async def wrapper (* args : "Any" , ** kwargs : "Any" ) -> "Any" :
979- return await _prompt_handler_wrapper (
980- on_get_prompt , args , kwargs , force_await = False
981- )
982-
983- wrapper .__sentry_mcp_wrapped__ = True # type: ignore[attr-defined]
984- kwargs ["on_get_prompt" ] = wrapper
985-
986- on_read_resource = kwargs .get ("on_read_resource" )
987- if on_read_resource is not None and not getattr (
988- on_read_resource , "__sentry_mcp_wrapped__" , False
989- ):
990-
991- @wraps (on_read_resource )
992- async def wrapper (* args : "Any" , ** kwargs : "Any" ) -> "Any" :
993- return await _resource_handler_wrapper (
994- on_read_resource , args , kwargs , force_await = False
995- )
996-
997- wrapper .__sentry_mcp_wrapped__ = True # type: ignore[attr-defined]
998- kwargs ["on_read_resource" ] = wrapper
999-
1000974 original_init (self , * args , ** kwargs )
975+ self .middleware .append (_sentry_middleware )
1001976
1002977 Server .__init__ = patched_init # type: ignore[method-assign]
1003978
1004- original_add_request_handler = Server .add_request_handler
1005-
1006- def patched_add_request_handler (
1007- self : "Server" ,
1008- method : str ,
1009- params_type : "Any" ,
1010- handler : "Callable[..., Any]" ,
1011- * args : "Any" ,
1012- ** kwargs : "Any" ,
1013- ) -> None :
1014- if getattr (handler , "__sentry_mcp_wrapped__" , False ):
1015- return original_add_request_handler (
1016- self , method , params_type , handler , * args , ** kwargs
1017- )
1018-
1019- if method == "tools/call" :
1020-
1021- @wraps (handler )
1022- async def wrapper (* args : "Any" , ** kwargs : "Any" ) -> "Any" :
1023- return await _tool_handler_wrapper (
1024- handler , args , kwargs , force_await = False
1025- )
1026-
1027- wrapper .__sentry_mcp_wrapped__ = True # type: ignore[attr-defined]
1028-
1029- return original_add_request_handler (
1030- self , method , params_type , wrapper , * args , ** kwargs
1031- )
1032- if method == "prompts/get" :
1033-
1034- @wraps (handler )
1035- async def wrapper (* args : "Any" , ** kwargs : "Any" ) -> "Any" :
1036- return await _prompt_handler_wrapper (
1037- handler , args , kwargs , force_await = False
1038- )
1039-
1040- wrapper .__sentry_mcp_wrapped__ = True # type: ignore[attr-defined]
1041-
1042- return original_add_request_handler (
1043- self , method , params_type , wrapper , * args , ** kwargs
1044- )
1045- if method == "resources/read" :
1046-
1047- @wraps (handler )
1048- async def wrapper (* args : "Any" , ** kwargs : "Any" ) -> "Any" :
1049- return await _resource_handler_wrapper (
1050- handler , args , kwargs , force_await = False
1051- )
1052-
1053- wrapper .__sentry_mcp_wrapped__ = True # type: ignore[attr-defined]
1054-
1055- return original_add_request_handler (
1056- self , method , params_type , wrapper , * args , ** kwargs
1057- )
1058-
1059- original_add_request_handler (
1060- self , method , params_type , handler , * args , ** kwargs
1061- )
1062-
1063- Server .add_request_handler = patched_add_request_handler # type: ignore[method-assign]
1064-
1065979
1066980def _patch_handle_request () -> None :
1067981 original_handle_request = StreamableHTTPServerTransport .handle_request
0 commit comments