1
1
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
2
# SPDX-License-Identifier: Apache-2.0
3
+ from dataclasses import dataclass
4
+ import json
3
5
from typing import Any , AsyncGenerator , Callable , Collection , Dict , Optional , Tuple , cast
4
6
5
- from wrapt import register_post_import_hook , wrap_function_wrapper
7
+ from wrapt import ObjectProxy , register_post_import_hook , wrap_function_wrapper
6
8
7
- from opentelemetry import trace
9
+ from opentelemetry import context , trace
8
10
from opentelemetry .instrumentation .instrumentor import BaseInstrumentor
9
11
from opentelemetry .instrumentation .utils import unwrap
10
12
from opentelemetry .semconv .trace import SpanAttributes
15
17
from .semconv import (
16
18
CLIENT_INITIALIZED ,
17
19
MCP_METHOD_NAME ,
20
+ MCP_REQUEST_ARGUMENT ,
18
21
TOOLS_CALL ,
19
22
TOOLS_LIST ,
20
23
MCPAttributes ,
@@ -34,7 +37,7 @@ def __init__(self, **kwargs):
34
37
self .tracer = trace .get_tracer (__name__ , __version__ , tracer_provider = kwargs .get ("tracer_provider" , None ))
35
38
36
39
def instrumentation_dependencies (self ) -> Collection [str ]:
37
- return ("mcp >= 1.6.0 " ,)
40
+ return ("mcp >= 1.8.1 " ,)
38
41
39
42
def _instrument (self , ** kwargs : Any ) -> None :
40
43
@@ -88,14 +91,14 @@ async def async_wrapper():
88
91
89
92
with self .tracer .start_as_current_span (
90
93
MCPSpanNames .SPAN_MCP_CLIENT , kind = trace .SpanKind .CLIENT
91
- ) as mcp_client_span :
94
+ ) as client_span :
92
95
93
96
if request :
94
- span_ctx = trace .set_span_in_context (mcp_client_span )
97
+ span_ctx = trace .set_span_in_context (client_span )
95
98
parent_span = {}
96
99
self .propagators .inject (carrier = parent_span , context = span_ctx )
97
100
98
- McpInstrumentor ._set_mcp_client_attributes (mcp_client_span , request )
101
+ McpInstrumentor ._set_mcp_client_attributes (client_span , request )
99
102
100
103
request_as_json ["params" ]["_meta" ].update (parent_span )
101
104
@@ -132,6 +135,10 @@ def _set_mcp_client_attributes(span: trace.Span, request: Any) -> None:
132
135
span .set_attribute (MCP_METHOD_NAME , TOOLS_LIST )
133
136
if isinstance (request , types .CallToolRequest ):
134
137
tool_name = request .params .name
138
+ tool_arguments = request .params .arguments
139
+ if tool_arguments :
140
+ for arg_name , arg_val in tool_arguments .items ():
141
+ span .set_attribute (f"{ MCP_REQUEST_ARGUMENT } .{ arg_name } " , McpInstrumentor .serialize (arg_val ))
135
142
span .update_name (f"{ TOOLS_CALL } { tool_name } " )
136
143
span .set_attribute (MCP_METHOD_NAME , TOOLS_CALL )
137
144
span .set_attribute (MCPAttributes .MCP_TOOL_NAME , tool_name )
@@ -149,3 +156,13 @@ def _set_mcp_server_attributes(span: trace.Span, request: Any) -> None:
149
156
span .update_name (f"{ TOOLS_CALL } { tool_name } " )
150
157
span .set_attribute (MCP_METHOD_NAME , TOOLS_CALL )
151
158
span .set_attribute (MCPAttributes .MCP_TOOL_NAME , tool_name )
159
+
160
+
161
+ @staticmethod
162
+ def serialize (args ):
163
+ try :
164
+ return json .dumps (args )
165
+ except Exception :
166
+ return str (args )
167
+
168
+
0 commit comments