MCP-client adapter doesn't surface a strict-mode signal; constrained decoding unreachable for MCP tools
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,inputSchemaannotations.{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.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗