fix(ai): Support distributed tracing for MCP tool calls#5271
fix(ai): Support distributed tracing for MCP tool calls#5271maxclaus wants to merge 1 commit intogetsentry:masterfrom
Conversation
MCP tool calls now properly continue distributed traces from parent services instead of creating new transactions with new trace IDs. The issue occurred because when get_start_span_function() executes during MCP tool handler wrapping, the HTTP transaction isn't accessible due to async context isolation. The function only checked the current scope, which often contained unrelated spans with different trace IDs. This fix adds checking for sentry-trace headers in the MCP request context and uses continue_trace() to create transactions that inherit the trace_id and parent_span_id from incoming requests. Benefits: - MCP tools join distributed traces correctly - Transactions still appear in MCP Insights dashboard - Fully backward compatible - No new dependencies
| ) | ||
|
|
||
| # Start transaction on scope so it becomes active | ||
| return sentry_sdk.start_transaction(transaction=transaction) |
There was a problem hiding this comment.
kwargs ignored in MCP headers success path
The **kwargs parameter is passed to start_transaction() in the fallback path (line 181) but completely ignored when the MCP headers path succeeds (line 176). This causes inconsistent behavior where additional keyword arguments are applied only when the primary code path fails, leading to silent differences in transaction configuration depending on whether MCP headers are present.
Additional Locations (1)
| sentry_trace = request.headers.get("sentry-trace") | ||
| if sentry_trace: | ||
| return _create_transaction_from_mcp_headers | ||
| except (ImportError, LookupError): |
There was a problem hiding this comment.
AttributeError uncaught when headers attribute is None
In get_start_span_function(), the code uses hasattr(request, "headers") to check if the attribute exists, then immediately calls request.headers.get("sentry-trace"). If headers exists but is None, this raises an AttributeError that isn't caught by the except (ImportError, LookupError) handler. The similar code in _create_transaction_from_mcp_headers() catches all Exception, but this function would fail and propagate the error.
|
I am closing this PR and will open an issue next to discuss about it first. |
Description
MCP tool calls now properly continue distributed traces from parent services instead of creating new transactions with new trace IDs.
Problem: When
get_start_span_function()executes during MCP tool handler wrapping, the HTTP transaction isn't accessible due to async context isolation. The function only checks the current scope, which often contains unrelated spans with different trace IDs.Solution: Enhanced
get_start_span_function()to check for sentry-trace headers in MCP request context. Added_create_transaction_from_mcp_headers()that extracts headers and usescontinue_trace()to create transactions inheriting trace_id and parent_span_id.Benefits:
Issues
N/A (External contribution)