MCP-client adapter doesn't surface a strict-mode signal; constrained decoding unreachable for MCP tools

Resolved 💬 3 comments Opened May 1, 2026 by yazzaoui Closed May 1, 2026

Summary

Claude Code's MCP-client adapter doesn't read any strict-mode signal from external MCP tools, so the existing API-strict-forwarding path never fires for them. MCP-served tools can't benefit from Anthropic's structured-outputs / constrained-decoding feature, even when the MCP server is willing to advertise the capability. This is a feature gap, not a transport bug.

Current behavior (verified against claude 2.1.119, Mach-O arm64)

The internal tool → API conversion (function gK6, ~offset 83942500) already supports forwarding strict:

if ($ && H.strict === true && _.model && zJH(_.model))
  O.strict = true;

…gated on the tengu_tool_pear Statsig flag and a model-supports-strict check. So the API layer is wired.

The MCP-client adapter (~offset 81492734) maps each external MCP tool to the internal form, reading only:

  • name, description, inputSchema
  • annotations.{readOnlyHint, destructiveHint, openWorldHint}
  • _meta["anthropic/{alwaysLoad, maxResultSizeChars, permissionDisplay, searchHint}"]

No strict is read — not from O.strict, not from O.annotations, not from O._meta. Confirmed by exhaustive enumeration of anthropic/* _meta-key string literals in the binary:

"anthropic/alwaysLoad"
"anthropic/maxResultSizeChars"
"anthropic/permissionDisplay"
"anthropic/searchHint"

So H.strict is always undefined for MCP-sourced tools, and gK6 omits strict from the API request. Schema bytes still flow through verbatim as input_schema (the model sees additionalProperties: false, enums, etc.) — but constrained decoding is not engaged.

Proposal

Have the MCP adapter recognize a strict-mode signal — e.g. _meta[\"anthropic/strict\"] === true — and set it on the internal tool, so gK6's existing branch fires:

// in the MCP-client adapter
strict: O._meta?.[\"anthropic/strict\"] === true ? true : undefined,

Conceptually one line. Design calls are yours:

  • Key name: _meta[\"anthropic/strict\"] matches the existing namespace; alternative naming welcome.
  • Gating: keep tengu_tool_pear + zJH(_.model)? add a server-trust gate?
  • Validation: should the adapter reject an MCP server that asserts strict but ships an open schema (missing additionalProperties: false, etc.)?
  • Fallback semantics: if the model rejects strict at the API layer, retry without it, or surface the error?

Why this matters

Frameworks shipping typed runtime contracts through MCP — multi-agent runtimes, schema-driven agent platforms, anything generating a tool catalog from a contract — currently can't get constrained decoding on the model side, even when their schemas are tight by construction. The only available mitigation is runtime fail-closed validation, which catches errors the model could have been prevented from making in the first place.

Related

#10858 covers the inverse direction: Claude Code's MCP server emits the API-specific strict field, which spec-compliant MCP clients reject. This proposal is for the client direction and is opt-in via a namespaced _meta key, so it doesn't change behavior for any existing MCP server.

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗