Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 43 additions & 73 deletions sentry_sdk/integrations/mcp.py
Original file line number Diff line number Diff line change
Expand Up @@ -457,50 +457,6 @@
return handler_name, arguments


def _prepare_handler_data(
handler_type: str,
original_args: "tuple[Any, ...]",
original_kwargs: "Optional[dict[str, Any]]" = None,
params: "Optional[Any]" = None,
) -> "tuple[str, dict[str, Any], str, str, str, Optional[str]]":
"""
Prepare common handler data for both v1 and v2 MCP SDK.

Args:
handler_type: "tool", "prompt", or "resource"
original_args: Original positional args (v1 path)
original_kwargs: Original keyword args (v1 path)
params: Typed params object from v2 ServerRequestContext path

Returns:
Tuple of (handler_name, arguments, span_data_key, span_name, mcp_method_name, result_data_key)
"""
if params is not None:
handler_name, arguments = _extract_handler_data_from_params(
handler_type, params
)
elif _is_v2_context(original_args):
handler_name = "unknown"
arguments = {}
else:
handler_name, arguments = _extract_handler_data_from_args(
handler_type, original_args, original_kwargs
)

span_data_key, span_name, mcp_method_name, result_data_key = _get_span_config(
handler_type, handler_name
)

return (
handler_name,
arguments,
span_data_key,
span_name,
mcp_method_name,
result_data_key,
)


async def _tool_handler_wrapper(
func: "Callable[..., Awaitable[Union[CallToolResult, InputRequiredResult]]]",
original_args: "tuple[Any, ...]",
Expand Down Expand Up @@ -530,16 +486,20 @@
and isinstance(original_args[0], ServerRequestContext)
):
ctx = original_args[0]
params = original_args[1] if len(original_args) > 1 else None
if len(original_args) > 1:
params = original_args[1]
handler_name, arguments = _extract_handler_data_from_params("tool", params)
else:
handler_name = "unknown"
arguments = {}
else:
handler_name, arguments = _extract_handler_data_from_args(
"tool", original_args, original_kwargs
)

(
handler_name,
arguments,
span_data_key,
span_name,
mcp_method_name,
result_data_key,
) = _prepare_handler_data("tool", original_args, original_kwargs, params=params)
span_data_key, span_name, mcp_method_name, result_data_key = _get_span_config(
"tool", handler_name
)

scopes = _get_active_http_scopes(ctx=ctx)

Expand Down Expand Up @@ -641,23 +601,27 @@

# Detect v1 vs v2: MCP SDK v2 passes (ServerRequestContext, params) to handlers
ctx: "Optional[Any]" = None
params: "Optional[Any]" = None
if (
ServerRequestContext is not None
and original_args
and isinstance(original_args[0], ServerRequestContext)
):
ctx = original_args[0]
params = original_args[1] if len(original_args) > 1 else None
if len(original_args) > 1:
handler_name, arguments = _extract_handler_data_from_params(
"prompt", original_args[1]
)
else:
handler_name = "unknown"
arguments = {}
else:
handler_name, arguments = _extract_handler_data_from_args(
"prompt", original_args, original_kwargs

Check warning on line 619 in sentry_sdk/integrations/mcp.py

View check run for this annotation

@sentry/warden / warden: find-bugs

`handler_name` used before assignment in `_extract_handler_data_from_args` for prompt type

If `original_args` is empty and `original_kwargs` has no `"name"` key, `handler_name` is never assigned but is referenced in `arguments = {"name": handler_name, ...}`, raising `UnboundLocalError` at runtime.
Comment thread
alexander-alderman-webb marked this conversation as resolved.
)

(
handler_name,
arguments,
span_data_key,
span_name,
mcp_method_name,
result_data_key,
) = _prepare_handler_data("prompt", original_args, original_kwargs, params=params)
span_data_key, span_name, mcp_method_name, result_data_key = _get_span_config(
"prompt", handler_name
)

scopes = _get_active_http_scopes(ctx=ctx)

Expand Down Expand Up @@ -764,16 +728,22 @@
and isinstance(original_args[0], ServerRequestContext)
):
ctx = original_args[0]
params = original_args[1] if len(original_args) > 1 else None

(
handler_name,
arguments,
span_data_key,
span_name,
mcp_method_name,
result_data_key,
) = _prepare_handler_data("resource", original_args, original_kwargs, params=params)
if len(original_args) > 1:
params = original_args[1]
handler_name, arguments = _extract_handler_data_from_params(
"resource", params
)
else:
handler_name = "unknown"
arguments = {}
else:
handler_name, arguments = _extract_handler_data_from_args(
"resource", original_args, original_kwargs
)

span_data_key, span_name, mcp_method_name, result_data_key = _get_span_config(
"resource", handler_name
)

scopes = _get_active_http_scopes(ctx=ctx)

Expand Down
Loading