Skip to content

MCP server silently ignores unknown tool arguments - an agent's misspelled parameter returns a confidently wrong answer #3870

Closed

Description

@erikdarlingdata

Summary

The MCP server silently ignores unknown tool arguments. A call to get_collection_log with a hallucinated status_filter: "failure" parameter succeeded and returned 200 rows — all SUCCESS, unfiltered — with nothing anywhere indicating the argument had been dropped. For a surface whose primary callers are agents, that is the worst possible failure shape: the caller believes it asked a narrower question than it did, and reads the answer under that belief.

Live repro (458 nightly, DARLING01)

tools/call get_collection_log {"server_name":"SQL2022","hours":1,"status_filter":"failure"}
-> 200 runs, every one status SUCCESS, no warning, no error

Two arguments in that call were bogus — status_filter does not exist, and the real window parameter is hours_back, so my hours was dropped too and the read silently ran at the 24-hour default ("hours_back": 24 in the response is the only tell). An agent that misremembers one parameter name gets an answer to a different question, delivered with full confidence.

Why this is worth fixing here

The codebase already holds the principle, in GetCollectionLog itself, on limit:

"rejects out of range rather than silently clamping, so a caller asking for 5000 is told no instead of quietly given 1000."

A wrong value is refused; a wrong name is swallowed. Same defect class, one level up — and the misspelled-name case is far more likely from an LLM caller than an out-of-range value. The payload-contract review (#3541) is about responses that mislead agents; this is the request-side twin.

Suggested fix

Reject calls carrying arguments the tool does not declare, with an error naming the unknown argument and the tool's real parameter list (the schema is already there to quote). Where this belongs depends on what the C# MCP SDK exposes — options, roughly in order of preference:

  1. A binding-layer hook/option that validates the request's argument object against the tool's input schema with additionalProperties: false semantics before dispatch — one fix covering all ~147 tools.
  2. If the SDK offers no seam, a shared pre-dispatch check in the server plumbing that diffs arguments keys against the declared schema properties.

Whichever lands, the behavior should be uniform across every tool, and a census test can pin it (call one tool with a deliberately unknown argument, assert the refusal names it) so the property survives SDK upgrades — the same drift-guard idiom the tool inventory pins already use.

One deliberate carve-out to consider

If any client is known to send benign extra keys (some MCP clients attach metadata), the rejection could be limited to keys not prefixed _. Absent a measured need, plain strict is better.

Activity

  1. erikdarlingdata commented on Sep 22, 2026

    @erikdarlingdata
    OwnerAuthor

    Claimed (pm-user-worker seat). Default shape unless Erik flips it: unknown arguments are a HARD ERROR naming the offending key and the tool's accepted parameters — for an agent-facing surface a loud rejection is the only answer that stops a confidently wrong read (this issue's own repro is the argument). Will verify the failure shape is uniform across both SKUs' servers and add the census that keeps the next tool honest.

  2. erikdarlingdata commented on Sep 22, 2026

    @erikdarlingdata
    OwnerAuthor

    Second live instance, different tool, same session: get_alert_history called with hours: 4 and metric_filter: "Retention" — both silently dropped. The response reported hours_back: 24 (the default; the real parameter is presumably named differently) and returned 5 unfiltered alerts, none matching the filter I believed I had applied. An agent reading that result would conclude "no Retention alerts in the last 4 hours" from a call that actually asked a different question.

    Confirms this is the binding layer, not one tool's handling — the fix wants to be uniform and census-pinned.

  3. erikdarlingdata commented on Sep 22, 2026

    @erikdarlingdata
    OwnerAuthor

    Closed by the watcher: delivered in PR #3873, merged to dev.

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

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions