MCP tool `strict` field not forwarded to Anthropic API

Resolved 💬 3 comments Opened Apr 1, 2026 by limsaehyun Closed Jun 7, 2026

Description

When an MCP server sets strict: true on a tool definition (via mcp.types.Tool's ConfigDict(extra="allow")), the field is present in the list_tools response but is not forwarded to the Anthropic API request body. This means grammar-constrained sampling is never applied to MCP tools, even when the server explicitly opts in.

Reproduction

  1. Create an MCP server that sets strict: true on tools:
from fastmcp import FastMCP
from mcp.types import Tool as MCPTool

app = FastMCP("test")

@app.tool()
async def my_tool(name: str, value: int) -> str:
    return "ok"

# Inject strict: true via list_tools handler
original = app.list_tools
@app._mcp_server.list_tools()
async def patched() -> list[MCPTool]:
    tools = await original()
    mcp_tools = []
    for t in tools:
        mt = t.to_mcp_tool()
        mt.strict = True
        mcp_tools.append(mt)
    return mcp_tools
  1. Verify the MCP server returns strict: true in its tool definitions (confirmed via direct list_tools call)
  1. Connect Claude Code (v2.1.89) to this server and intercept the outgoing Anthropic API request using a local reverse proxy on ANTHROPIC_BASE_URL
  1. Observe that strict is null/missing for all tools in the API request body — both MCP and built-in

Observed behavior

Proxy capture of the Anthropic API request:

[CAPTURE] /v1/messages — 33 tools
  Agent: strict=None, additionalProperties=False
  Bash: strict=None, additionalProperties=False
  Read: strict=None, additionalProperties=False
  Edit: strict=None, additionalProperties=False
  mcp__test__get_historical_crypto_prices: strict=None, additionalProperties=False
  mcp__test__get_available_crypto_tickers: strict=None, additionalProperties=False
  ... (all 33 tools)

[SUMMARY] strict=true: 0, strict missing/false: 33
[HEADER] anthropic-beta: oauth-2025-04-20,interleaved-thinking-2025-05-14,...
[HEADER] ✗ structured-outputs beta header not included

Consequence: Without strict mode, the model occasionally generates tool calls with incorrect parameter names. For example, calling get_historical_crypto_prices with from/to/multiplier/timespan instead of the schema-defined start_date/end_date/interval/interval_multiplier, resulting in Pydantic validation errors on the server side.

Expected behavior

  1. If an MCP server returns strict: true on a tool, that field should be preserved and forwarded to the Anthropic API
  2. The structured-outputs beta header should be included when strict tools are present
  3. Built-in tools that define strict: true in their source should also have it forwarded

Impact

For agent systems that use MCP tools for critical operations (trading, database writes, etc.), incorrect parameter generation can cause silent failures or require retry loops. Grammar-constrained sampling via strict: true would prevent this class of errors at generation time.

Workaround attempted

We tried using a local proxy to inject strict: true into the API request body, but hit the "compiled grammar is too large" error when applying it to multiple tools. Selectively applying to fewer tools still triggered the size limit with 33 total tools in the request. There doesn't appear to be a viable workaround from the user side.

Environment

  • Claude Code: v2.1.89
  • Agent SDK: 0.1.48
  • Platform: macOS Darwin 23.2.0
  • MCP SDK: fastmcp 3.2.0

View original on GitHub ↗

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