Python: feature: Inject OpenTelemetry trace context into MCP requests and update…#3780
Conversation
Python Test Coverage Report •
Python Unit Test Overview
|
||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Pull request overview
Adds OpenTelemetry trace-context propagation across the MCP transport boundary by injecting the active trace context into MCP tools/call requests via params._meta, enabling end-to-end distributed tracing from Agent Framework → MCP servers.
Changes:
- Add
_inject_otel_into_mcp_meta()helper to inject the current OTel context into an MCP_metacarrier. - Wire OTel meta injection into
MCPTool.call_tool()so all MCP transports benefit. - Add a unit test and a documentation note describing MCP trace propagation.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| python/packages/core/agent_framework/_mcp.py | Injects OTel propagation fields into MCP tool calls via the request meta field. |
| python/packages/core/tests/core/test_mcp.py | Adds a test validating meta injection behavior for active vs inactive span contexts. |
| python/samples/getting_started/observability/README.md | Documents that trace context is propagated to MCP servers using params._meta. |
|
@copilot open a new pull request to apply changes based on the comments in this thread |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
OpenTelemetry is a hard dependency of agent-framework-core (per pyproject.toml), so the try/except ImportError guard was dead code. Move the import to the top of the file to fail fast on missing dependencies instead of silently hiding installation issues.
…-context-meta # Conflicts: # python/packages/core/agent_framework/_mcp.py
Head branch was pushed to by a user without write access
1f67f5a to
ccc34d2
Compare
|
@rogerbarreto and @markwallace-microsoft, are any additional changes needed to get this merged? Happy to make any edits needed. There are a few projects in flight that this update would really help with. I am not able to rerun the markdown-lint-check for some reason. Perhaps permissions? |
yes -- we are too awaiting this for active work as well. @rogerbarreto @markwallace-microsoft |
Motivation and Context
When an Agent Framework application calls tools on remote MCP servers, the OpenTelemetry trace context is lost at the MCP transport boundary. The agent's span tree stops at
call_tool()and the MCP server starts a new, unrelated trace — breaking distributed tracing and preventing end-to-end latency visibility across agent → MCP server calls.The MCP specification (2025-11-25) reserves
params._metafor exactly this kind of client/server metadata: "The_metaproperty/parameter is reserved by MCP to allow clients and servers to attach additional metadata to their interactions."Fixes #3778
Description
Adds a
_inject_otel_into_mcp_meta()helper that usesopentelemetry.propagate.inject()to write the current trace context into a carrier dict, then merges it into the MCP request_meta. This is wired intoMCPTool.call_tool()— the single chokepoint for all transports (stdio, SSE, streamable HTTP).Key design decisions:
traceparent/tracestate, B3, etc.) rather than hardcoding specific headerstry/except ImportErrorso the framework works unchanged when OTel is not installed_metakeysOBSERVABILITY_SETTINGS: propagation happens whenever a valid span context exists, independent of the framework's observability configurationFiles changed:
packages/core/agent_framework/_mcp.py— added_inject_otel_into_mcp_meta()helper, wired intoMCPTool.call_tool()packages/core/tests/core/test_mcp.py— added parametrized test covering span/no-span casessamples/getting_started/observability/README.md— added MCP trace propagation documentation noteContribution Checklist