Skip to content

Python: Propagate user-supplied _meta from function_invocation_kwargs to MCP …#5159

Open
Serjbory wants to merge 2 commits intomicrosoft:mainfrom
Serjbory:feature/mcp-meta-support
Open

Python: Propagate user-supplied _meta from function_invocation_kwargs to MCP …#5159
Serjbory wants to merge 2 commits intomicrosoft:mainfrom
Serjbory:feature/mcp-meta-support

Conversation

@Serjbory
Copy link
Copy Markdown

@Serjbory Serjbory commented Apr 8, 2026

…call_tool requests (#5158)

Motivation and Context

MCP servers can accept a _meta field alongside tool arguments in call_tool requests, enabling clients to pass request-level metadata such as correlation IDs, user locale, session info, and other context that servers may use for debugging, distributed tracing, or request-specific behavior.

Both OpenAI Agents SDK (PR #2375) and LangChain MCP Adapters (PR #468) have recently added _meta support, making this an expected capability across MCP client frameworks.

Description

Propagate user-supplied _meta from function_invocation_kwargs to MCP call_tool requests. The change is minimal (~4 lines in MCPTool.call_tool()):

  1. Extract _meta from incoming **kwargs via kwargs.pop("_meta", None) before filtering
  2. Add "_meta" to the existing filtered-kwargs exclusion set so it never leaks into tool arguments
  3. Pass the extracted dict to _inject_otel_into_mcp_meta(user_meta) instead of _inject_otel_into_mcp_meta() — user keys take precedence, OTel keys fill in non-conflicting slots

This uses the established function_invocation_kwargs mechanism — the same per-request injection pattern already used across 6+ samples for API keys, user IDs, and session metadata:

response = await agent.run(
    "Search for Python repos",
    function_invocation_kwargs={
        "_meta": {
            "correlation_id": "req-456",
            "session_id": "abc-123",
            "locale": "fr-FR",
        },
    },
)

No new public types, parameters, or constructor changes. Fully backward compatible — when _meta is not provided, behavior is identical to before.

Files changed:

  • python/packages/core/agent_framework/_mcp.py — extract and forward _meta in call_tool()
  • python/packages/core/tests/core/test_mcp.py — 9 new tests covering all edge cases
  • docs/specs/002-mcp-meta-support.md — feature spec

Test coverage:

  • _meta forwarded as protocol-level meta, excluded from tool arguments
  • User meta merged with OTel trace context; user keys win on conflicts
  • Backward compatibility when _meta is absent
  • Caller's dict not mutated by OTel injection
  • Empty _meta={} treated as no user meta
  • End-to-end flow through FunctionTool wrapper (as created by load_tools())
  • MCPStreamableHTTPTool override forwards _meta to super().call_tool()
  • Combined with header_provider without interference

Contribution Checklist

  • The code builds clean without any errors or warnings
  • The PR follows the Contribution Guidelines
  • All unit tests pass, and I have added new tests where possible
  • Is this a breaking change? If yes, add "[BREAKING]" prefix to the title of the PR.

@moonbox3 moonbox3 added the python label Apr 8, 2026
@github-actions github-actions bot changed the title Propagate user-supplied _meta from function_invocation_kwargs to MCP … Python: Propagate user-supplied _meta from function_invocation_kwargs to MCP … Apr 8, 2026
@moonbox3
Copy link
Copy Markdown
Contributor

moonbox3 commented Apr 8, 2026

Python Test Coverage

Python Test Coverage Report •
FileStmtsMissCoverMissing
packages/core/agent_framework
   _mcp.py6123095%153, 294, 354–355, 484, 546, 559, 561–564, 583–584, 597–600, 602–603, 607, 670–672, 1031, 1151, 1203–1204, 1207, 1225, 1678
TOTAL27035318588% 

Python Unit Test Overview

Tests Skipped Failures Errors Time
5398 20 💤 0 ❌ 0 🔥 1m 27s ⏱️

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