Skip to content

Conversation

tonybaloney
Copy link

The way the MCP HTTP streamable class is written, the headers are set at instantiation, which encourages folks to set headers once outside of the workflow.

For OTEL's tracing to work between AF and the MCP servers, we want to propagate the trace and span ID to the MCP servers in the calls.

This PR adds another header to MCP HTTP calls (disabled by default) with the standard OTEL headers. I've tested this on FastMCP with the starlette instrumentation and the traces to the MCPs are propagated correctly.

Screenshot 2025-10-18 195309

@github-actions github-actions bot changed the title Add OTEL trace headers on requests to MCP HTTP Streamable Tools Python: Add OTEL trace headers on requests to MCP HTTP Streamable Tools Oct 20, 2025
@markwallace-microsoft
Copy link
Member

markwallace-microsoft commented Oct 20, 2025

Python Test Coverage

Python Test Coverage Report •
FileStmtsMissCoverMissing
packages/core/agent_framework
   _mcp.py32711564%133, 143–144, 165, 190, 205, 211, 215, 217, 299, 317–322, 325–326, 336–338, 341–343, 345–351, 353–355, 358–359, 381–382, 386–391, 397–398, 402–403, 407, 409, 413–414, 418, 436, 456–466, 477, 490, 493–494, 498, 522, 525–526, 530, 561, 580, 582, 589–590, 609, 611, 617–620, 637–641, 760, 765–769, 877, 880–892, 894, 984, 987–989
TOTAL11123178583% 

Python Unit Test Overview

Tests Skipped Failures Errors Time
1352 98 💤 0 ❌ 0 🔥 28.121s ⏱️

@tonybaloney
Copy link
Author

@moonbox3 please could you take a look at this idea

args["terminate_on_close"] = self.terminate_on_close
if self._client_kwargs:
args.update(self._client_kwargs)
if self._include_traceparent:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it’s better to build this around per-request dynamic headers, not mutate the tool's static dict. Capture the static headers once in MCPStreamableHTTPTool, then pass an optional dynamic_headers callable down into streamablehttp_client / StreamableHTTPTransport. The callable can pull the current span, make sure the context is valid, derive the sampled flag, and return {"traceparent": ...} only when it should be sent. We can then have _prepare_request_headers merge that callable's output on every POST so each RPC carries the active span while the static headers stay untouched. That then handles a possible KeyError when no headers were supplied and keeps the trace flag accurate instead of hardcoding 01.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants