FastMCP tool argument models silently ignore unknown/misspelled arguments (extra=ignore default)

Open Beginner friendly
#3,067 1 comment 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
76/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Quiet
Tech stack
python

Research direction

Start at src/mcp/server/mcpserver/utilities/func_metadata.py and inspect ArgModelBase.model_config and the generated arg_model validation path. Add a regression test using the read_doc-style unknown-argument case, then run the relevant FastMCP tests; done means unknown tool arguments raise validation errors and the published schema rejects additional properties.

Written by the indexing model from the issue text.

Description

enhancement needs decision P2 v1 v2

Description

mcp.server.fastmcp.utilities.func_metadata.ArgModelBase does not set extra in its
model_config, so it inherits Pydantic v2's default, extra="ignore":

class ArgModelBase(BaseModel):
    """A model representing the arguments to a function."""
    ...
    model_config = ConfigDict(
        arbitrary_types_allowed=True,
    )

Every per-tool *Arguments model that FastMCP generates via create_model(..., __base__=ArgModelBase, ...)
inherits this. As a result, when a client calls a tool with an argument name that doesn't
exist on the function (a typo, or a hallucinated parameter name from an LLM), Pydantic
silently drops it instead of raising a validation error. The tool then runs with that
parameter at its default value, and returns a "successful" but semantically wrong result —
with no signal anywhere that anything was off.

Reproduction

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("repro")

@mcp.tool()
def read_doc(topic: str = "") -> str:
    return f"topic={topic!r}"

# Simulate what happens when a client calls with the wrong argument name:
tool = mcp._tool_manager.get_tool("read_doc")
result = tool.fn_metadata.arg_model.model_validate({"path": "something"})
print(result.model_dump_one_level())
# {'topic': ''}  <- no error, no signal that "path" was bogus

Expected behavior

An unknown argument in a tools/call request should fail validation immediately with a
clear error (e.g. Pydantic's own "Extra inputs are not permitted"), the same way a missing
required argument already does. This is especially important for MCP given the primary
caller is frequently an LLM: a wrong parameter name is a common, plausible failure mode, and
a loud, immediate error is far more useful (and self-correcting for the model) than a
silently-wrong "successful" response.

Suggested fix

Set extra="forbid" on ArgModelBase.model_config:

model_config = ConfigDict(
    arbitrary_types_allowed=True,
    extra="forbid",
)

This should be safe: the fields validated by ArgModelBase subclasses are exactly the
arguments dict of a tools/call request (i.e. exactly what's declared in the tool's
inputSchema). Protocol-level fields (_meta, progressToken, etc.) live on the
surrounding params object, not inside arguments, and Context is injected separately
via arguments_to_pass_directly — neither passes through ArgModelBase. The side effect is
that model_json_schema() will now emit "additionalProperties": false on the published
inputSchema, which seems like a feature, not a regression (it lets clients that validate
against the schema catch this class of error before the round-trip).

Scope checked

  • Confirmed present in mcp 1.27.2 and 1.28.1 (latest on PyPI as of 2026-07).
  • Confirmed still present on main (the in-progress v2, where fastmcp is being renamed to
    mcpserver): src/mcp/server/mcpserver/utilities/func_metadata.py has the same
    ArgModelBase without extra set.
  • I didn't find an existing issue about this specific behavior (searched for "extra fields",
    "forbid", "unknown argument", "additionalProperties", "silently ignored").
  • For context: the TypeScript SDK has an equivalent gap for a different underlying reason
    (Zod's default strip behavior on unknown object keys) — see
    https://github.com/modelcontextprotocol/typescript-sdk/issues/147

Happy to open a PR with the one-line change plus a regression test if that's useful.

Dominant language
Python
Stars
24.3k
Forks
4k
Avg merge
1d 19m
Merged PRs (30d)
29

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from modelcontextprotocol/python-sdk

All issues in modelcontextprotocol/python-sdk

Similar issues

More Python issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.