Skip to content

Commit b5b5389

Browse files
committed
Inline OTel span attributes
1 parent 67ca7fe commit b5b5389

File tree

3 files changed

+24
-62
lines changed

3 files changed

+24
-62
lines changed

src/mcp/server/lowlevel/server.py

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ async def main():
6666
from mcp.server.streamable_http import EventStore
6767
from mcp.server.streamable_http_manager import StreamableHTTPASGIApp, StreamableHTTPSessionManager
6868
from mcp.server.transport_security import TransportSecuritySettings
69-
from mcp.shared._otel import build_server_span_attributes, extract_trace_context, otel_span
69+
from mcp.shared._otel import extract_trace_context, otel_span
7070
from mcp.shared._stream_protocols import ReadStream, WriteStream
7171
from mcp.shared.exceptions import MCPError
7272
from mcp.shared.message import ServerMessageMetadata, SessionMessage
@@ -464,17 +464,23 @@ async def _handle_request(
464464
close_standalone_sse_stream_cb = message.message_metadata.close_standalone_sse_stream
465465
request_headers = getattr(request_data, "headers", None)
466466
session_id = request_headers.get(MCP_SESSION_ID_HEADER) if request_headers is not None else None
467+
span_attributes: dict[str, Any] = {
468+
"rpc.system": "mcp",
469+
"rpc.service": self.name,
470+
"rpc.method": req.method,
471+
"mcp.method.name": req.method,
472+
"jsonrpc.request.id": message.request_id,
473+
}
474+
resource_uri = getattr(req.params, "uri", None)
475+
if resource_uri is not None:
476+
span_attributes["mcp.resource.uri"] = str(resource_uri)
477+
if session_id is not None:
478+
span_attributes["mcp.session.id"] = session_id
467479

468480
with otel_span(
469481
span_name,
470482
kind=SpanKind.SERVER,
471-
attributes=build_server_span_attributes(
472-
service_name=self.name,
473-
method=req.method,
474-
request_id=message.request_id,
475-
params=req.params,
476-
session_id=session_id,
477-
),
483+
attributes=span_attributes,
478484
context=parent_context,
479485
) as span:
480486
if handler := self._request_handlers.get(req.method):

src/mcp/shared/_otel.py

Lines changed: 0 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
from opentelemetry.trace import SpanKind, get_tracer
1212

1313
_tracer = get_tracer("mcp-python-sdk")
14-
MCP_RPC_SYSTEM = "mcp"
1514

1615

1716
@contextmanager
@@ -35,50 +34,3 @@ def inject_trace_context(meta: dict[str, Any]) -> None:
3534
def extract_trace_context(meta: dict[str, Any]) -> Context:
3635
"""Extract W3C trace context from a `_meta` dict."""
3736
return extract(meta)
38-
39-
40-
def build_client_span_attributes(
41-
*,
42-
method: str,
43-
request_id: str | int,
44-
params: dict[str, Any] | None = None,
45-
) -> dict[str, Any]:
46-
"""Build OTel attributes for an MCP client request span."""
47-
attributes: dict[str, Any] = {
48-
"rpc.system": MCP_RPC_SYSTEM,
49-
"rpc.method": method,
50-
"mcp.method.name": method,
51-
"jsonrpc.request.id": request_id,
52-
}
53-
54-
if params is not None and (resource_uri := params.get("uri")) is not None:
55-
attributes["mcp.resource.uri"] = resource_uri
56-
57-
return attributes
58-
59-
60-
def build_server_span_attributes(
61-
*,
62-
service_name: str,
63-
method: str,
64-
request_id: str | int,
65-
params: Any = None,
66-
session_id: str | None = None,
67-
) -> dict[str, Any]:
68-
"""Build OTel attributes for an MCP server request span."""
69-
attributes: dict[str, Any] = {
70-
"rpc.system": MCP_RPC_SYSTEM,
71-
"rpc.service": service_name,
72-
"rpc.method": method,
73-
"mcp.method.name": method,
74-
"jsonrpc.request.id": request_id,
75-
}
76-
77-
resource_uri = getattr(params, "uri", None)
78-
if resource_uri is not None:
79-
attributes["mcp.resource.uri"] = str(resource_uri)
80-
81-
if session_id is not None:
82-
attributes["mcp.session.id"] = session_id
83-
84-
return attributes

src/mcp/shared/session.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from pydantic import BaseModel, TypeAdapter
1414
from typing_extensions import Self
1515

16-
from mcp.shared._otel import build_client_span_attributes, inject_trace_context, otel_span
16+
from mcp.shared._otel import inject_trace_context, otel_span
1717
from mcp.shared._stream_protocols import ReadStream, WriteStream
1818
from mcp.shared.exceptions import MCPError
1919
from mcp.shared.message import MessageMetadata, ServerMessageMetadata, SessionMessage
@@ -272,15 +272,19 @@ async def send_request(
272272
try:
273273
target = request_data.get("params", {}).get("name")
274274
span_name = f"MCP send {request.method} {target}" if target else f"MCP send {request.method}"
275+
span_attributes: dict[str, Any] = {
276+
"rpc.system": "mcp",
277+
"rpc.method": request.method,
278+
"mcp.method.name": request.method,
279+
"jsonrpc.request.id": request_id,
280+
}
281+
if (resource_uri := request_data.get("params", {}).get("uri")) is not None:
282+
span_attributes["mcp.resource.uri"] = resource_uri
275283

276284
with otel_span(
277285
span_name,
278286
kind=SpanKind.CLIENT,
279-
attributes=build_client_span_attributes(
280-
method=request.method,
281-
request_id=request_id,
282-
params=request_data.get("params"),
283-
),
287+
attributes=span_attributes,
284288
):
285289
# Inject W3C trace context into _meta (SEP-414).
286290
meta: dict[str, Any] = request_data.setdefault("params", {}).setdefault("_meta", {})

0 commit comments

Comments
 (0)