Skip to content

Commit d0e7d14

Browse files
fix(integrations): properly distinguish between network.transport and mcp.transport (#5063)
### Description Fixes the wrong handling of `mcp.transport`, it should be one of "http", "sse", or "stdio", not "pipe" or "tcp". These values are for the [`network.transport`](https://opentelemetry.io/docs/specs/semconv/registry/attributes/network/#network-transport) attribute which was also introduced. #### Issues * closes https://linear.app/getsentry/issue/TET-1354/mcp-transport-vs-network-transport
1 parent e910302 commit d0e7d14

File tree

3 files changed

+174
-45
lines changed

3 files changed

+174
-45
lines changed

sentry_sdk/consts.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -706,6 +706,12 @@ class SPANDATA:
706706
Example: 6379
707707
"""
708708

709+
NETWORK_TRANSPORT = "network.transport"
710+
"""
711+
The transport protocol used for the network connection.
712+
Example: "tcp", "udp", "unix"
713+
"""
714+
709715
PROFILER_ID = "profiler_id"
710716
"""
711717
Label identifying the profiler id that the span occurred in. This should be a string.
@@ -824,7 +830,7 @@ class SPANDATA:
824830
MCP_TRANSPORT = "mcp.transport"
825831
"""
826832
The transport method used for MCP communication.
827-
Example: "pipe" (stdio), "tcp" (HTTP/WebSocket/SSE)
833+
Example: "http", "sse", "stdio"
828834
"""
829835

830836
MCP_SESSION_ID = "mcp.session.id"

sentry_sdk/integrations/mcp.py

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -56,34 +56,44 @@ def setup_once():
5656
def _get_request_context_data():
5757
# type: () -> tuple[Optional[str], Optional[str], str]
5858
"""
59-
Extract request ID, session ID, and transport type from the MCP request context.
59+
Extract request ID, session ID, and MCP transport type from the request context.
6060
6161
Returns:
62-
Tuple of (request_id, session_id, transport).
62+
Tuple of (request_id, session_id, mcp_transport).
6363
- request_id: May be None if not available
6464
- session_id: May be None if not available
65-
- transport: "tcp" for HTTP-based, "pipe" for stdio
65+
- mcp_transport: "http", "sse", "stdio"
6666
"""
6767
request_id = None # type: Optional[str]
6868
session_id = None # type: Optional[str]
69-
transport = "pipe" # type: str
69+
mcp_transport = "stdio" # type: str
7070

7171
try:
7272
ctx = request_ctx.get()
7373

7474
if ctx is not None:
7575
request_id = ctx.request_id
7676
if hasattr(ctx, "request") and ctx.request is not None:
77-
transport = "tcp"
7877
request = ctx.request
79-
if hasattr(request, "headers"):
78+
# Detect transport type by checking request characteristics
79+
if hasattr(request, "query_params") and request.query_params.get(
80+
"session_id"
81+
):
82+
# SSE transport uses query parameter
83+
mcp_transport = "sse"
84+
session_id = request.query_params.get("session_id")
85+
elif hasattr(request, "headers") and request.headers.get(
86+
"mcp-session-id"
87+
):
88+
# StreamableHTTP transport uses header
89+
mcp_transport = "http"
8090
session_id = request.headers.get("mcp-session-id")
8191

8292
except LookupError:
83-
# No request context available - default to pipe
93+
# No request context available - default to stdio
8494
pass
8595

86-
return request_id, session_id, transport
96+
return request_id, session_id, mcp_transport
8797

8898

8999
def _get_span_config(handler_type, item_name):
@@ -120,16 +130,20 @@ def _set_span_input_data(
120130
arguments,
121131
request_id,
122132
session_id,
123-
transport,
133+
mcp_transport,
124134
):
125135
# type: (Any, str, str, str, dict[str, Any], Optional[str], Optional[str], str) -> None
126136
"""Set input span data for MCP handlers."""
137+
127138
# Set handler identifier
128139
span.set_data(span_data_key, handler_name)
129140
span.set_data(SPANDATA.MCP_METHOD_NAME, mcp_method_name)
130141

131-
# Set transport type
132-
span.set_data(SPANDATA.MCP_TRANSPORT, transport)
142+
# Set transport/MCP transport type
143+
span.set_data(
144+
SPANDATA.NETWORK_TRANSPORT, "pipe" if mcp_transport == "stdio" else "tcp"
145+
)
146+
span.set_data(SPANDATA.MCP_TRANSPORT, mcp_transport)
133147

134148
# Set request_id if provided
135149
if request_id:
@@ -331,7 +345,7 @@ async def _async_handler_wrapper(handler_type, func, original_args):
331345
origin=MCPIntegration.origin,
332346
) as span:
333347
# Get request ID, session ID, and transport from context
334-
request_id, session_id, transport = _get_request_context_data()
348+
request_id, session_id, mcp_transport = _get_request_context_data()
335349

336350
# Set input span data
337351
_set_span_input_data(
@@ -342,7 +356,7 @@ async def _async_handler_wrapper(handler_type, func, original_args):
342356
arguments,
343357
request_id,
344358
session_id,
345-
transport,
359+
mcp_transport,
346360
)
347361

348362
# For resources, extract and set protocol
@@ -396,7 +410,7 @@ def _sync_handler_wrapper(handler_type, func, original_args):
396410
origin=MCPIntegration.origin,
397411
) as span:
398412
# Get request ID, session ID, and transport from context
399-
request_id, session_id, transport = _get_request_context_data()
413+
request_id, session_id, mcp_transport = _get_request_context_data()
400414

401415
# Set input span data
402416
_set_span_input_data(
@@ -407,7 +421,7 @@ def _sync_handler_wrapper(handler_type, func, original_args):
407421
arguments,
408422
request_id,
409423
session_id,
410-
transport,
424+
mcp_transport,
411425
)
412426

413427
# For resources, extract and set protocol

0 commit comments

Comments
 (0)