Skip to content

Commit c97c8df

Browse files
committed
Fix MCP instrumentation for distributed tracing
1 parent 064c71c commit c97c8df

File tree

2 files changed

+10
-19
lines changed

2 files changed

+10
-19
lines changed

aws-opentelemetry-distro/pyproject.toml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,9 @@ dependencies = [
8989
# If a new patch is added into the list, it must also be added into tox.ini, dev-requirements.txt and _instrumentation_patch
9090
patch = [
9191
"botocore ~= 1.0",
92-
"mcp >= 0.1.6",
93-
]
94-
instruments = [
95-
"mcp >= 0.1.6",
92+
"mcp >= 1.6.0",
9693
]
94+
9795
test = []
9896

9997
[project.entry-points.opentelemetry_configurator]

aws-opentelemetry-distro/src/amazon/opentelemetry/distro/instrumentation/mcp/instrumentation.py

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,10 @@ def __init__(self, **kwargs):
3434
self.tracer = trace.get_tracer(__name__, __version__, tracer_provider=kwargs.get("tracer_provider", None))
3535

3636
def instrumentation_dependencies(self) -> Collection[str]:
37-
return "mcp >= 1.6.0"
37+
return ("mcp >= 1.6.0",)
3838

3939
def _instrument(self, **kwargs: Any) -> None:
40-
40+
4141
register_post_import_hook(
4242
lambda _: wrap_function_wrapper(
4343
"mcp.shared.session",
@@ -63,6 +63,7 @@ def _wrap_send_request(
6363
self, wrapped: Callable, instance: Any, args: Tuple[Any, ...], kwargs: Dict[str, Any]
6464
) -> Callable:
6565
import mcp.types as types
66+
6667

6768
"""
6869
Patches BaseSession.send_request which is responsible for sending requests from the client to the MCP server.
@@ -103,23 +104,16 @@ async def async_wrapper():
103104
new_args = (modified_request,) + args[1:]
104105

105106
return await wrapped(*new_args, **kwargs)
107+
return async_wrapper()
106108

107-
return async_wrapper
108-
109-
# Handle Request Wrapper
110109
async def _wrap_handle_request(
111110
self, wrapped: Callable, instance: Any, args: Tuple[Any, ...], kwargs: Dict[str, Any]
112111
) -> Any:
113-
"""
114-
Patches Server._handle_request which is responsible for processing requests on the MCP server.
115-
This patched MCP server intercepts incoming requests to extract tracing context from
116-
the request's params._meta field and creates server-side spans linked to the client spans.
117-
"""
118112
req = args[1] if len(args) > 1 else None
119113
carrier = {}
120114

121115
if req and hasattr(req, "params") and req.params and hasattr(req.params, "meta") and req.params.meta:
122-
carrier = req.params.meta.__dict__
116+
carrier = req.params.meta.model_dump()
123117

124118
parent_ctx = self.propagators.extract(carrier=carrier)
125119

@@ -128,8 +122,7 @@ async def _wrap_handle_request(
128122
MCPSpanNames.SPAN_MCP_SERVER, kind=trace.SpanKind.SERVER, context=parent_ctx
129123
) as mcp_server_span:
130124
self._set_mcp_server_attributes(mcp_server_span, req)
131-
132-
return await wrapped(*args, **kwargs)
125+
return await wrapped(*args, **kwargs)
133126

134127
@staticmethod
135128
def _set_mcp_client_attributes(span: trace.Span, request: Any) -> None:
@@ -149,9 +142,9 @@ def _set_mcp_client_attributes(span: trace.Span, request: Any) -> None:
149142
def _set_mcp_server_attributes(span: trace.Span, request: Any) -> None:
150143
import mcp.types as types # pylint: disable=import-outside-toplevel,consider-using-from-import
151144

152-
if isinstance(span, types.ListToolsRequest):
145+
if isinstance(request, types.ListToolsRequest):
153146
span.set_attribute(MCP_METHOD_NAME, TOOLS_LIST)
154-
if isinstance(span, types.CallToolRequest):
147+
if isinstance(request, types.CallToolRequest):
155148
tool_name = request.params.name
156149
span.update_name(f"{TOOLS_CALL} {tool_name}")
157150
span.set_attribute(MCP_METHOD_NAME, TOOLS_CALL)

0 commit comments

Comments
 (0)