You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
MCP server silently ignores unknown tool arguments - an agent's misspelled parameter returns a confidently wrong answer #3870
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:
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.
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.
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.
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.
Activity
erikdarlingdata commentedon Sep 22, 2026
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.
erikdarlingdata commentedon Sep 22, 2026
Second live instance, different tool, same session:
get_alert_historycalled withhours: 4andmetric_filter: "Retention"— both silently dropped. The response reportedhours_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.
The collection log can be asked for the failures: a status filter on …
An argument the tool does not declare is refused instead of dropped (#…
erikdarlingdata commentedon Sep 22, 2026
Closed by the watcher: delivered in PR #3873, merged to dev.