Skip to content

fix(mcp): use model_dump(by_alias=True) to preserve _meta field in instrumentation#2062

Open
Zelys-DFKH wants to merge 1 commit intostrands-agents:mainfrom
Zelys-DFKH:fix/mcp-instrumentation-meta-alias
Open

fix(mcp): use model_dump(by_alias=True) to preserve _meta field in instrumentation#2062
Zelys-DFKH wants to merge 1 commit intostrands-agents:mainfrom
Zelys-DFKH:fix/mcp-instrumentation-meta-alias

Conversation

@Zelys-DFKH
Copy link
Copy Markdown

Description

CallToolRequestParams defines its tracing field with the Python name `meta`
and the wire alias `_meta`. Calling model_dump() without by_alias=True
serialises the field as `meta`, so the subsequent setdefault("_meta", ...)
call always creates a second, unrelated key. The OpenTelemetry context is
injected into that orphaned key and never reaches the MCP server.

There is a second part to the bug: `_meta` is None by default, and setdefault
does not replace an existing key even when its value is None. So even after
switching to by_alias=True the inject() call would receive None as its carrier.
The fix explicitly replaces None with an empty dict before injecting.

Changes:

  • `model_dump(by_alias=True)` on line 93 of `mcp_instrumentation.py` so the key
    is `_meta` throughout, matching the MCP wire format
  • Replace `setdefault("_meta", {})` with an explicit isinstance check that
    initialises `_meta` to `{}` when the value is absent or None

Related Issues

Fixes #1916

Documentation PR

N/A

Type of Change

Bug fix

Testing

  • Added `test_patch_mcp_client_injects_context_into_real_mcp_params` using
    the actual `CallToolRequestParams` type to verify `inject()` receives a dict
    carrier (not None) and that `_meta` is a dict after `model_validate`
  • Updated two mock `model_dump` methods to accept `**kwargs` so they remain
    compatible with the `by_alias=True` call
  • All 135 existing MCP tests pass

Checklist

  • I have read the CONTRIBUTING document
  • I have added any necessary tests that prove my fix is effective or my feature works
  • I have updated the documentation accordingly
  • My changes generate no new warnings
  • Any dependent changes have been merged and published

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

…e _meta field

CallToolRequestParams defines its tracing field as `meta` with alias `_meta`.
model_dump() serialises it under the Python field name `meta`, so the subsequent
setdefault("_meta", ...) always created a second, disconnected key and the
OpenTelemetry context was never forwarded to the MCP server.

Switching to model_dump(by_alias=True) ensures the key is `_meta` throughout,
matching the MCP wire format.

Adds a regression test using the real CallToolRequestParams to verify the alias
is preserved end-to-end.

Fixes strands-agents#1916
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.

[BUG] Strands MCPClient does not forward _meta to MCP tool calls + instrumentation corrupts _meta

1 participant