11import logging
2- from typing import Any , AsyncGenerator , Callable , Collection , Tuple , cast
2+ from typing import Any , Collection
33
44from openinference .instrumentation .mcp .package import _instruments
5- from wrapt import ObjectProxy , register_post_import_hook , wrap_function_wrapper
5+ from wrapt import register_post_import_hook , wrap_function_wrapper
66
7- from opentelemetry import context , propagate , trace
7+ from opentelemetry import trace
88from opentelemetry .instrumentation .instrumentor import BaseInstrumentor
99from opentelemetry .instrumentation .utils import unwrap
10- from opentelemetry .sdk .resources import Resource
1110
1211
1312def setup_loggertwo ():
@@ -69,15 +68,13 @@ def handle_attributes(self, span, request, is_client=True):
6968 span .set_attribute ("mcp.list_tools" , True )
7069 elif isinstance (request , types .CallToolRequest ):
7170 if hasattr (request , "params" ) and hasattr (request .params , "name" ):
72- operation = request .params .name
71+ operation = request .params .name
7372 span .set_attribute ("mcp.call_tool" , True )
7473 if is_client :
7574 self ._add_client_attributes (span , operation , request )
7675 else :
7776 self ._add_server_attributes (span , operation , request )
7877
79-
80-
8178 def _add_client_attributes (self , span , operation , request ):
8279 span .set_attribute ("span.kind" , "CLIENT" )
8380 span .set_attribute ("aws.remote.service" , "Appsignals MCP Server" )
@@ -103,23 +100,22 @@ def _send_request_wrapper(self, wrapped, instance, args, kwargs):
103100 """
104101 Changes made:
105102 The wrapper intercepts the request before sending, injects distributed tracing context into the
106- request's params._meta field and creates OpenTelemetry spans. The wrapper does not change anything else from the original function's
107- behavior because it reconstructs the request object with the same type and calling the original function with identical parameters.
103+ request's params._meta field and creates OpenTelemetry spans. The wrapper does not change anything
104+ else from the original function's behavior because it reconstructs the request object with the same
105+ type and calling the original function with identical parameters.
108106 """
109107
110108 async def async_wrapper ():
111109 if self .tracer_provider is None :
112110 tracer = trace .get_tracer ("mcp.client" )
113111 else :
114112 tracer = self .tracer_provider .get_tracer ("mcp.client" )
115- with tracer .start_as_current_span (
116- "client.send_request" , kind = trace .SpanKind .CLIENT
117- ) as span :
113+ with tracer .start_as_current_span ("client.send_request" , kind = trace .SpanKind .CLIENT ) as span :
118114 span_ctx = span .get_span_context ()
119115 request = args [0 ] if len (args ) > 0 else kwargs .get ("request" )
120116 if request :
121117 req_root = request .root if hasattr (request , "root" ) else request
122-
118+
123119 self .handle_attributes (span , req_root , True )
124120 request_data = request .model_dump (by_alias = True , mode = "json" , exclude_none = True )
125121 self ._inject_trace_context (request_data , span_ctx )
@@ -155,24 +151,30 @@ async def _server_handle_request_wrapper(self, wrapped, instance, args, kwargs):
155151 """
156152 Changes made:
157153 This wrapper intercepts requests before processing, extracts distributed tracing context from
158- the request's params._meta field, and creates server-side OpenTelemetry spans linked to the client spans. The wrapper
159- also does not change the original function's behavior by calling it with identical parameters
154+ the request's params._meta field, and creates server-side OpenTelemetry spans linked to the client spans.
155+ The wrapper also does not change the original function's behavior by calling it with identical parameters
160156 ensuring no breaking changes to the MCP server functionality.
161157 """
162158 req = args [1 ] if len (args ) > 1 else None
163159 trace_context = None
164-
160+
165161 if req and hasattr (req , "params" ) and req .params and hasattr (req .params , "meta" ) and req .params .meta :
166162 trace_context = req .params .meta .trace_context
167163 if trace_context :
168-
164+
169165 if self .tracer_provider is None :
170166 tracer = trace .get_tracer ("mcp.server" )
171167 else :
172168 tracer = self .tracer_provider .get_tracer ("mcp.server" )
173169 trace_id = trace_context .get ("trace_id" )
174170 span_id = trace_context .get ("span_id" )
175- span_context = trace .SpanContext (trace_id = trace_id , span_id = span_id , is_remote = True ,trace_flags = trace .TraceFlags (trace .TraceFlags .SAMPLED ),trace_state = trace .TraceState ())
171+ span_context = trace .SpanContext (
172+ trace_id = trace_id ,
173+ span_id = span_id ,
174+ is_remote = True ,
175+ trace_flags = trace .TraceFlags (trace .TraceFlags .SAMPLED ),
176+ trace_state = trace .TraceState (),
177+ )
176178 span_name = self .getname (req )
177179 with tracer .start_as_current_span (
178180 span_name ,
@@ -183,5 +185,7 @@ async def _server_handle_request_wrapper(self, wrapped, instance, args, kwargs):
183185 result = await wrapped (* args , ** kwargs )
184186 return result
185187 else :
186- return await wrapped (* args , ** kwargs ,)
187-
188+ return await wrapped (
189+ * args ,
190+ ** kwargs ,
191+ )
0 commit comments