Skip to content

Commit 79e5779

Browse files
committed
cleanup
1 parent 66c192c commit 79e5779

File tree

1 file changed

+53
-79
lines changed

1 file changed

+53
-79
lines changed

sentry_sdk/integrations/mcp.py

Lines changed: 53 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -290,26 +290,51 @@ def _set_span_output_data(span, result, result_data_key, handler_type):
290290
# Handler data preparation and wrapping
291291

292292

293-
def _prepare_handler_data(handler_type, original_args):
294-
# type: (str, tuple[Any, ...]) -> tuple[str, dict[str, Any], str, str, str, Optional[str]]
293+
def _prepare_handler_data(handler_type, original_args, original_kwargs=None):
294+
# type: (str, tuple[Any, ...], Optional[dict[str, Any]]) -> tuple[str, dict[str, Any], str, str, str, Optional[str]]
295295
"""
296296
Prepare common handler data for both async and sync wrappers.
297297
298298
Returns:
299299
Tuple of (handler_name, arguments, span_data_key, span_name, mcp_method_name, result_data_key)
300300
"""
301+
original_kwargs = original_kwargs or {}
302+
301303
# Extract handler-specific data based on handler type
302304
if handler_type == "tool":
303-
handler_name = original_args[0] # tool_name
304-
arguments = original_args[1] if len(original_args) > 1 else {}
305+
if original_args:
306+
handler_name = original_args[0]
307+
elif original_kwargs.get("tool_name"):
308+
handler_name = original_kwargs["tool_name"]
309+
310+
arguments = {}
311+
if len(original_args) > 1:
312+
arguments = original_args[1]
313+
elif original_kwargs.get("arguments"):
314+
arguments = original_kwargs["arguments"]
315+
305316
elif handler_type == "prompt":
306-
handler_name = original_args[0] # name
307-
arguments = original_args[1] if len(original_args) > 1 else {}
317+
if original_args:
318+
handler_name = original_args[0]
319+
elif original_kwargs.get("tool_name"):
320+
handler_name = original_kwargs["tool_name"]
321+
322+
arguments = {}
323+
if len(original_args) > 1:
324+
arguments = original_args[1]
325+
elif original_kwargs.get("arguments"):
326+
arguments = original_kwargs["arguments"]
327+
308328
# Include name in arguments dict for span data
309329
arguments = {"name": handler_name, **(arguments or {})}
330+
310331
else: # resource
311-
uri = original_args[0]
312-
handler_name = str(uri) if uri else "unknown"
332+
handler_name = "unknown"
333+
if original_args:
334+
handler_name = str(original_args[0])
335+
elif original_kwargs.get("uri"):
336+
handler_name = str(original_kwargs["uri"])
337+
313338
arguments = {}
314339

315340
# Get span configuration
@@ -327,8 +352,10 @@ def _prepare_handler_data(handler_type, original_args):
327352
)
328353

329354

330-
async def _async_handler_wrapper(handler_type, func, original_args):
331-
# type: (str, Callable[..., Any], tuple[Any, ...]) -> Any
355+
async def _async_handler_wrapper(
356+
handler_type, func, original_args, original_kwargs=None
357+
):
358+
# type: (str, Callable[..., Any], tuple[Any, ...], Optional[dict[Any, Any]]) -> Any
332359
"""
333360
Async wrapper for MCP handlers.
334361
@@ -337,14 +364,17 @@ async def _async_handler_wrapper(handler_type, func, original_args):
337364
func: The async handler function to wrap
338365
original_args: Original arguments passed to the handler
339366
"""
367+
if original_kwargs is None:
368+
original_kwargs = {}
369+
340370
(
341371
handler_name,
342372
arguments,
343373
span_data_key,
344374
span_name,
345375
mcp_method_name,
346376
result_data_key,
347-
) = _prepare_handler_data(handler_type, original_args)
377+
) = _prepare_handler_data(handler_type, original_args, original_kwargs)
348378

349379
# Start span and execute
350380
with get_start_span_function()(
@@ -380,7 +410,7 @@ async def _async_handler_wrapper(handler_type, func, original_args):
380410

381411
try:
382412
# Execute the async handler
383-
result = await func(*original_args)
413+
result = await func(*original_args, **original_kwargs)
384414
except Exception as e:
385415
# Set error flag for tools
386416
if handler_type == "tool":
@@ -588,84 +618,28 @@ def _patch_fastmcp():
588618
original_get_prompt_mcp = FastMCP._get_prompt_mcp
589619

590620
@wraps(original_get_prompt_mcp)
591-
async def patched_get_prompt_mcp(self, name, arguments=None):
592-
# type: (Any, str, Optional[dict[str, Any]]) -> Any
593-
return await _async_fastmcp_handler_wrapper(
621+
async def patched_get_prompt_mcp(self, *args, **kwargs):
622+
# type: (Any, Any) -> Any
623+
return await _async_handler_wrapper(
594624
"prompt",
595-
lambda n, a: original_get_prompt_mcp(self, n, a),
596-
(name, arguments),
625+
original_get_prompt_mcp,
626+
args,
627+
kwargs,
597628
)
598629

599630
FastMCP._get_prompt_mcp = patched_get_prompt_mcp
600631

601-
# Patch _read_resource_mcp
602632
if hasattr(FastMCP, "_read_resource_mcp"):
603633
original_read_resource_mcp = FastMCP._read_resource_mcp
604634

605635
@wraps(original_read_resource_mcp)
606-
async def patched_read_resource_mcp(self, uri):
636+
async def patched_read_resource_mcp(self, *args, **kwargs):
607637
# type: (Any, Any) -> Any
608-
return await _async_fastmcp_handler_wrapper(
638+
return await _async_handler_wrapper(
609639
"resource",
610-
lambda u: original_read_resource_mcp(self, u),
611-
(uri,),
640+
original_read_resource_mcp,
641+
args,
642+
kwargs,
612643
)
613644

614645
FastMCP._read_resource_mcp = patched_read_resource_mcp
615-
616-
617-
async def _async_fastmcp_handler_wrapper(handler_type, func, original_args):
618-
# type: (str, Callable[..., Any], tuple[Any, ...]) -> Any
619-
"""
620-
Async wrapper for standalone FastMCP handlers.
621-
622-
Similar to _async_handler_wrapper but the original function is already
623-
a coroutine function that we call directly.
624-
"""
625-
(
626-
handler_name,
627-
arguments,
628-
span_data_key,
629-
span_name,
630-
mcp_method_name,
631-
result_data_key,
632-
) = _prepare_handler_data(handler_type, original_args)
633-
634-
with get_start_span_function()(
635-
op=OP.MCP_SERVER,
636-
name=span_name,
637-
origin=MCPIntegration.origin,
638-
) as span:
639-
request_id, session_id, mcp_transport = _get_request_context_data()
640-
641-
_set_span_input_data(
642-
span,
643-
handler_name,
644-
span_data_key,
645-
mcp_method_name,
646-
arguments,
647-
request_id,
648-
session_id,
649-
mcp_transport,
650-
)
651-
652-
if handler_type == "resource":
653-
uri = original_args[0]
654-
protocol = None
655-
if hasattr(uri, "scheme"):
656-
protocol = uri.scheme
657-
elif handler_name and "://" in handler_name:
658-
protocol = handler_name.split("://")[0]
659-
if protocol:
660-
span.set_data(SPANDATA.MCP_RESOURCE_PROTOCOL, protocol)
661-
662-
try:
663-
result = await func(*original_args)
664-
except Exception as e:
665-
if handler_type == "tool":
666-
span.set_data(SPANDATA.MCP_TOOL_RESULT_IS_ERROR, True)
667-
sentry_sdk.capture_exception(e)
668-
raise
669-
670-
_set_span_output_data(span, result, result_data_key, handler_type)
671-
return result

0 commit comments

Comments
 (0)