22
33from __future__ import annotations
44
5- from collections .abc import Iterator
5+ from collections .abc import Iterator , Mapping
66from contextlib import contextmanager
7- from typing import Any
7+ from typing import Any , cast
88
99from opentelemetry .context import Context
1010from 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
0 commit comments