Skip to content

Commit 6930f92

Browse files
committed
Fix pyright type errors and coverage gaps in OTel span attributes
1 parent 811b7ab commit 6930f92

2 files changed

Lines changed: 16 additions & 19 deletions

File tree

src/mcp/shared/_otel.py

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
from __future__ import annotations
44

5-
from collections.abc import Iterator
5+
from collections.abc import Iterator, Mapping
66
from contextlib import contextmanager
7-
from typing import Any
7+
from typing import Any, cast
88

99
from opentelemetry.context import Context
1010
from opentelemetry.propagate import extract, inject
@@ -29,15 +29,12 @@ def build_span_attributes(
2929
method: str,
3030
request_id: Any,
3131
*,
32-
params: dict[str, Any] | None = None,
33-
server_name: str | None = None,
34-
session_id: str | None = None,
32+
params: Mapping[str, Any] | None = None,
3533
) -> dict[str, Any]:
3634
"""Build OTel span attributes for an MCP request.
3735
3836
Produces the base set of semantic convention attributes shared by both
3937
client (`SpanKind.CLIENT`) and server (`SpanKind.SERVER`) spans.
40-
Pass `server_name` and `session_id` for server-side spans.
4138
"""
4239
attrs: dict[str, Any] = {
4340
"rpc.system": "mcp",
@@ -49,27 +46,21 @@ def build_span_attributes(
4946
if operation is not None:
5047
attrs["gen_ai.operation.name"] = operation
5148

52-
if server_name is not None:
53-
attrs["rpc.service"] = server_name
54-
5549
if params is not None:
5650
# gen_ai.tool.name — present on tools/call, prompts/get
5751
name = params.get("name")
5852
if isinstance(name, str):
5953
attrs["gen_ai.tool.name"] = name
6054

6155
# mcp.resource.uri — present on resources/read; also on completion/complete via ref.uri
62-
uri = params.get("uri")
56+
uri: Any = params.get("uri")
6357
if uri is None:
6458
ref = params.get("ref")
6559
if isinstance(ref, dict):
66-
uri = ref.get("uri")
60+
uri = cast(dict[str, Any], ref).get("uri")
6761
if uri is not None:
6862
attrs["mcp.resource.uri"] = str(uri)
6963

70-
if session_id is not None:
71-
attrs["mcp.session.id"] = session_id
72-
7364
return attrs
7465

7566

tests/shared/test_otel.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,21 @@
66
from mcp import types
77
from mcp.client.client import Client
88
from mcp.server.mcpserver import MCPServer
9+
from mcp.shared._otel import build_span_attributes
910

1011
pytestmark = pytest.mark.anyio
1112

1213

14+
def test_build_span_attributes_ref_uri() -> None:
15+
"""build_span_attributes extracts mcp.resource.uri from nested ref.uri."""
16+
attrs = build_span_attributes(
17+
"completion/complete",
18+
"1",
19+
params={"ref": {"uri": "test://doc"}},
20+
)
21+
assert attrs["mcp.resource.uri"] == "test://doc"
22+
23+
1324
async def test_client_and_server_spans(capfire: CaptureLogfire):
1425
"""Verify that calling a tool produces client and server spans with correct attributes."""
1526
server = MCPServer("test")
@@ -55,11 +66,6 @@ async def test_list_tools_spans(capfire: CaptureLogfire):
5566
"""Verify that listing tools produces spans with list_tools operation."""
5667
server = MCPServer("test")
5768

58-
@server.tool()
59-
def greet(name: str) -> str:
60-
"""Greet someone."""
61-
return f"Hello, {name}!"
62-
6369
async with Client(server) as client:
6470
await client.list_tools()
6571

0 commit comments

Comments
 (0)