Skip to content

fix: support mcp 2.x result shapes in MCP instrumentation - #42

Merged
PabloPardoGarcia merged 1 commit into
mainfrom
pablo/gla2-300-mcp-v2-compat
Aug 4, 2026
Merged

fix: support mcp 2.x result shapes in MCP instrumentation#42
PabloPardoGarcia merged 1 commit into
mainfrom
pablo/gla2-300-mcp-v2-compat

Conversation

@PabloPardoGarcia

Copy link
Copy Markdown
Member

Closes GLA2-300 (items 1–3; item 4, the SEP-414 trace-propagation docs, follows separately once this is released).

mcp 2.0.0 shipped with spec 2026-07-28 and pip install mcp now installs 2.x, while our extra is mcp>=1.0.0 unbounded — so fresh installs already resolve a version where the instrumentation silently misreads results.

What was broken on mcp 2.x

  • CallToolResult.isError/structuredContent no longer exist (renamed to snake_case, camelCase dropped — verified against the real package). Our defensive getattr(..., False) reads returned the fallback, so failed tool calls produced healthy-looking spans and structured output silently degraded to text blocks.
  • tools/call can now return an interim InputRequiredResult (MRTR): the retry loop produces one span per round, and the interim payload (input_requests, i.e. elicitation/sampling content) was recorded as output.value.

Changes

  • Result reads try both spellings, extracted into _result_is_error / _record_result so they're unit-testable.
  • Interim input_required rounds record only an mcp.result_type marker (new semconv key, following the mcp SDK's own mcp.* namespace) and never record the interim payload as output.
  • Test module now runs on both majors: import/session shims (FastMCP vs MCPServer + in-memory Client), version-agnostic error-flag assertion, plus fakes pinning each major's exact attribute surface (RED-first; the six new tests failed before the fix).
  • New mcp-v2 CI job overlays mcp>=2,<3 on the locked env and re-runs the MCP tests, so the next upstream rename fails a build instead of un-flagging error results in production.

Verification

  • Full suite green on the locked mcp 1.28 (171 passed).
  • uv run --with "mcp>=2,<3" pytest tests/test_mcp_instrumentation.py green (12 passed) — real 2.x, not fakes only.
  • Pin stays mcp>=1.0.0 (unbounded) by design: the wrapper is now correct on both majors simultaneously.

mcp 2.0 (spec 2026-07-28) renamed CallToolResult's fields to snake_case
and dropped the camelCase attributes, so the isError read silently
returned False (failed tool calls looked healthy) and structuredContent
was never found. Reads now try both spellings.

tools/call can also return an interim InputRequiredResult (MRTR): its
input_requests carry elicitation/sampling content, so interim rounds now
get only an mcp.result_type marker instead of recording that payload as
output.value.

Tests run against both majors: the shims pick the right server fixture
(FastMCP vs MCPServer, in-memory Client), fakes pin each major's exact
attribute surface, and a new ci job overlays mcp>=2 onto the locked env.

GLA2-300 items 1-3; item 4 (SEP-414 trace-propagation docs) follows
separately.
@PabloPardoGarcia
PabloPardoGarcia merged commit 65aff4b into main Aug 4, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant