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

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