Skip to content
Open
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
99 changes: 32 additions & 67 deletions sentry_sdk/integrations/mcp.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,57 +259,6 @@
return " ".join(texts) if texts else content_blocks


def _extract_handler_data_from_args(
handler_type: str,
original_args: "tuple[Any, ...]",
original_kwargs: "Optional[dict[str, Any]]" = None,
) -> "tuple[str, dict[str, Any]]":
"""
Extract handler name and arguments from v1 positional args.

In MCP SDK v1, handlers receive positional args:
- Tool: (tool_name, arguments)
- Prompt: (name, arguments)
- Resource: (uri,)
"""
original_kwargs = original_kwargs or {}

if handler_type == "tool":
if original_args:
handler_name = original_args[0]
elif original_kwargs.get("name"):
handler_name = original_kwargs["name"]

arguments = {}
if len(original_args) > 1:
arguments = original_args[1]
elif original_kwargs.get("arguments"):
arguments = original_kwargs["arguments"]

elif handler_type == "prompt":
if original_args:
handler_name = original_args[0]
elif original_kwargs.get("name"):
handler_name = original_kwargs["name"]

arguments = {}
if len(original_args) > 1:
arguments = original_args[1]
elif original_kwargs.get("arguments"):
arguments = original_kwargs["arguments"]

else: # resource
handler_name = "unknown"
if original_args:
handler_name = str(original_args[0])
elif original_kwargs.get("uri"):
handler_name = str(original_kwargs["uri"])

arguments = {}

return handler_name, arguments


async def _tool_handler_wrapper(
func: "Callable[..., Awaitable[Union[CallToolResult, InputRequiredResult]]]",
original_args: "tuple[Any, ...]",
Expand All @@ -329,12 +278,18 @@
"""
client = sentry_sdk.get_client()

if original_kwargs is None:
original_kwargs = {}
original_kwargs = original_kwargs or {}

handler_name, arguments = _extract_handler_data_from_args(
"tool", original_args, original_kwargs
)
if original_args:
handler_name = original_args[0]
elif original_kwargs.get("name"):
handler_name = original_kwargs["name"]

arguments = {}
if len(original_args) > 1:
arguments = original_args[1]
elif original_kwargs.get("arguments"):
arguments = original_kwargs["arguments"]

if has_data_collection_enabled(client.options):
if not client.options["data_collection"]["gen_ai"]["inputs"]:
Expand Down Expand Up @@ -549,13 +504,20 @@
original_kwargs: Original keyword arguments passed to the handler
self: Optional instance for bound methods
"""
if original_kwargs is None:
original_kwargs = {}

client = sentry_sdk.get_client()
handler_name, arguments = _extract_handler_data_from_args(
"prompt", original_args, original_kwargs
)

original_kwargs = original_kwargs or {}

if original_args:
handler_name = original_args[0]
elif original_kwargs.get("name"):
handler_name = original_kwargs["name"]

arguments = {}
if len(original_args) > 1:
arguments = original_args[1]
elif original_kwargs.get("arguments"):
arguments = original_kwargs["arguments"]

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

View check run for this annotation

@sentry/warden / warden: find-bugs

Prompt wrapper crashes when positional arguments is None

Normalize `original_args[1]` with `or {}` (as v2 does) so a missing prompt `arguments` value cannot make `_set_span_input_data()` call `.items()` on None and fail the request.
Comment thread
alexander-alderman-webb marked this conversation as resolved.

if has_data_collection_enabled(client.options):
if not client.options["data_collection"]["gen_ai"]["inputs"]:
Expand Down Expand Up @@ -847,12 +809,15 @@
original_kwargs: Original keyword arguments passed to the handler
self: Optional instance for bound methods
"""
if original_kwargs is None:
original_kwargs = {}
original_kwargs = original_kwargs or {}

handler_name, arguments = _extract_handler_data_from_args(
"resource", original_args, original_kwargs
)
handler_name = "unknown"
if original_args:
handler_name = str(original_args[0])
elif original_kwargs.get("uri"):
handler_name = str(original_kwargs["uri"])

arguments: "dict[str, Any]" = {}

ctx = None
try:
Expand Down
Loading