Skip to content

Would opt-in rejection of unknown tool arguments be useful in 2.x? #3646

Description

@starsstreaming

Related: #3067 and the closed PR #3068. I would like to ask whether maintainers want an opt-in, per-tool policy for this behavior, while preserving the existing 2.x default. If this is better discussed in #3067, I am happy to consolidate it there.

On current main (91941ed4d3985d59def99e090baa3f880c626cc8), I reproduced a misspelled argument being silently ignored through an in-memory Client call:

import anyio
from mcp import Client
from mcp.server import MCPServer

mcp = MCPServer("repro")

@mcp.tool()
def list_records(limit: int = 10) -> int:
    """Return at most limit records."""
    return limit

async def main() -> None:
    async with Client(mcp) as client:
        result = await client.call_tool("list_records", {"limti": 1})
        print(result.is_error, result.structured_content)

anyio.run(main)

Observed: False {'result': 10}. The tool runs with its default, so the caller receives no indication that the supplied parameter was not applied.

Would a configuration along these lines be useful?

@mcp.tool(extra_arguments="forbid")  # proposed API, not implemented
def list_records(limit: int = 10) -> int:
    return limit
  • Default remains extra_arguments="ignore" for compatibility.
  • Opted-in tools publish root additionalProperties: false and reject unknown top-level argument names before executing the handler.
  • Rejection uses the existing is_error=True tool-result path, allowing the model to correct its call.
  • Existing type coercion and nested model/dictionary behavior remain unchanged.
  • Programmatic add_tool registration would expose the same option.

I am not proposing a global default change or automatic spelling correction. Would maintainers consider this worth supporting in 2.x, and is a per-tool option the right scope? No implementation has been started.

Prepared with AI assistance; the reported behavior was reproduced locally.

Activity

  1. maxisbey commented on Oct 6, 2026

    @maxisbey
    Contributor

    Thanks for asking before building anything, that's exactly how we'd like new API to start.

    I'm going to close this as not planned, along with #3067. A per-tool option would be new public API on tool() and add_tool(), and so far nobody has told us they need it. None of the other SDKs I checked have a dedicated setting for this either. Where you can be strict, it comes from the schema or type you already write. You can also do the check yourself today from the raw arguments, which I've described on #3067.

    The thing that would help most is a real use case. If you run a server where a dropped argument has caused trouble, tell us what happened and why it mattered, here or on #3067. That's what we use to decide what to prioritise (CONTRIBUTING.md has more on this), and we're happy to reopen with that in hand.

    AI Disclaimer


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions