88from opentelemetry import trace
99from opentelemetry .instrumentation .instrumentor import BaseInstrumentor
1010from opentelemetry .instrumentation .utils import unwrap
11-
11+ from . semconv import MCPAttributes , MCPSpanNames , MCPOperations , MCPTraceContext , MCPEnvironmentVariables
1212_instruments = ("mcp >= 1.6.0" ,)
1313
1414class MCPInstrumentor (BaseInstrumentor ):
@@ -27,9 +27,9 @@ def instrumentation_dependencies() -> Collection[str]:
2727 def _instrument (self , ** kwargs : Any ) -> None :
2828 tracer_provider = kwargs .get ("tracer_provider" )
2929 if tracer_provider :
30- self .tracer = tracer_provider .get_tracer ("mcp" )
30+ self .tracer = tracer_provider .get_tracer ("instrumentation. mcp" )
3131 else :
32- self .tracer = trace .get_tracer ("mcp" )
32+ self .tracer = trace .get_tracer ("instrumentation. mcp" )
3333 register_post_import_hook (
3434 lambda _ : wrap_function_wrapper (
3535 "mcp.shared.session" ,
@@ -65,7 +65,7 @@ def _wrap_send_request(
6565 """
6666
6767 async def async_wrapper ():
68- with self .tracer .start_as_current_span ("client.send_request" , kind = trace .SpanKind .CLIENT ) as span :
68+ with self .tracer .start_as_current_span (MCPSpanNames . CLIENT_SEND_REQUEST , kind = trace .SpanKind .CLIENT ) as span :
6969 span_ctx = span .get_span_context ()
7070 request = args [0 ] if len (args ) > 0 else kwargs .get ("request" )
7171 if request :
@@ -107,7 +107,7 @@ async def _wrap_handle_request(
107107 traceparent = None
108108
109109 if req and hasattr (req , "params" ) and req .params and hasattr (req .params , "meta" ) and req .params .meta :
110- traceparent = getattr (req .params .meta , "traceparent" , None )
110+ traceparent = getattr (req .params .meta , MCPTraceContext . TRACEPARENT_HEADER , None )
111111 span_context = self ._extract_span_context_from_traceparent (traceparent ) if traceparent else None
112112 if span_context :
113113 span_name = self ._get_mcp_operation (req )
@@ -125,16 +125,24 @@ async def _wrap_handle_request(
125125 def _generate_mcp_attributes (self , span : trace .Span , request : ClientRequest , is_client : bool ) -> None :
126126 import mcp .types as types # pylint: disable=import-outside-toplevel,consider-using-from-import
127127
128- operation = "UnknownOperation"
128+ operation = MCPOperations .UNKNOWN_OPERATION
129+
129130 if isinstance (request , types .ListToolsRequest ):
130- operation = "ListTool"
131- span .set_attribute ("mcp.list_tools" , True )
131+ operation = MCPOperations .LIST_TOOL
132+ span .set_attribute (MCPAttributes .MCP_LIST_TOOLS , True )
133+ if is_client :
134+ span .update_name (MCPSpanNames .CLIENT_LIST_TOOLS )
132135 elif isinstance (request , types .CallToolRequest ):
133136 operation = request .params .name
134- span .set_attribute ("mcp.call_tool" , True )
137+ span .set_attribute (MCPAttributes .MCP_CALL_TOOL , True )
138+ if is_client :
139+ span .update_name (MCPSpanNames .client_call_tool (request .params .name ))
135140 elif isinstance (request , types .InitializeRequest ):
136- operation = "Initialize"
137- span .set_attribute ("mcp.initialize" , True )
141+ operation = MCPOperations .INITIALIZE
142+ span .set_attribute (MCPAttributes .MCP_INITIALIZE , True )
143+ if is_client :
144+ span .update_name (MCPSpanNames .CLIENT_INITIALIZE )
145+
138146 if is_client :
139147 self ._add_client_attributes (span , operation , request )
140148 else :
@@ -148,9 +156,9 @@ def _inject_trace_context(request_data: Dict[str, Any], span_ctx) -> None:
148156 request_data ["params" ]["_meta" ] = {}
149157 trace_id_hex = f"{ span_ctx .trace_id :032x} "
150158 span_id_hex = f"{ span_ctx .span_id :016x} "
151- trace_flags = "01"
152- traceparent = f"00 -{ trace_id_hex } -{ span_id_hex } -{ trace_flags } "
153- request_data ["params" ]["_meta" ]["traceparent" ] = traceparent
159+ trace_flags = MCPTraceContext . TRACE_FLAGS_SAMPLED
160+ traceparent = f"{ MCPTraceContext . TRACEPARENT_VERSION } -{ trace_id_hex } -{ span_id_hex } -{ trace_flags } "
161+ request_data ["params" ]["_meta" ][MCPTraceContext . TRACEPARENT_HEADER ] = traceparent
154162
155163 @staticmethod
156164 def _extract_span_context_from_traceparent (traceparent : str ):
@@ -177,24 +185,24 @@ def _get_mcp_operation(req: ClientRequest) -> str:
177185 span_name = "unknown"
178186
179187 if isinstance (req , types .ListToolsRequest ):
180- span_name = "tools/list"
188+ span_name = MCPSpanNames . TOOLS_LIST
181189 elif isinstance (req , types .CallToolRequest ):
182- span_name = f"tools/ { req .params .name } "
190+ span_name = MCPSpanNames . tools_call ( req .params .name )
183191 elif isinstance (req , types .InitializeRequest ):
184- span_name = "tools/initialize"
192+ span_name = MCPSpanNames . TOOLS_INITIALIZE
185193 return span_name
186194
187195 @staticmethod
188196 def _add_client_attributes (span : trace .Span , operation : str , request : ClientRequest ) -> None :
189197 import os # pylint: disable=import-outside-toplevel
190198
191- service_name = os .environ .get ("MCP_INSTRUMENTATION_SERVER_NAME" , "mcp server" )
192- span .set_attribute ("aws.remote.service" , service_name )
193- span .set_attribute ("aws.remote.operation" , operation )
199+ service_name = os .environ .get (MCPEnvironmentVariables . SERVER_NAME , "mcp server" )
200+ span .set_attribute (MCPAttributes . AWS_REMOTE_SERVICE , service_name )
201+ span .set_attribute (MCPAttributes . AWS_REMOTE_OPERATION , operation )
194202 if hasattr (request , "params" ) and request .params and hasattr (request .params , "name" ):
195- span .set_attribute ("tool.name" , request .params .name )
203+ span .set_attribute (MCPAttributes . MCP_TOOL_NAME , request .params .name )
196204
197205 @staticmethod
198206 def _add_server_attributes (span : trace .Span , operation : str , request : ClientRequest ) -> None :
199207 if hasattr (request , "params" ) and request .params and hasattr (request .params , "name" ):
200- span .set_attribute ("tool.name" , request .params .name )
208+ span .set_attribute (MCPAttributes . MCP_TOOL_NAME , request .params .name )
0 commit comments