fix(mcp): say why a tool was skipped on import - #849
Conversation
"has no usable parameter schema" is true and unactionable: it does not separate a malformed schema from an oversized one from a well-formed one this import deliberately refuses. The report now names the reason, and for the common case the keyword whose removal would widen what the tool accepts. Concretely: DeepWiki's ask_question declares repoName as string-or-list via anyOf, so the whole tool is refused while its two siblings import. The operator saw only that something was unusable. The rejection rules are unchanged. rejectionReason() mirrors normalise() step for step and walks the FILTERED schema, so a keyword sitting in a key that is dropped anyway is never reported as the cause. Assisted-by: claude-code:claude-fable-5 Agent-Session: https://claude.ai/code/session_0144iD1P22LotW8rxmxrNGro Agent-Host: 0493f0 Signed-off-by: Sebastian Mendel <sebastian.mendel@netresearch.de>
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Scanned FilesNone |
There was a problem hiding this comment.
Automated approval for maintainer PR
All automated quality gates passed. See SECURITY_CONTROLS.md for compensating controls.
|
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #849 +/- ##
============================================
- Coverage 86.75% 86.74% -0.02%
- Complexity 9880 9899 +19
============================================
Files 573 573
Lines 31949 31991 +42
============================================
+ Hits 27717 27749 +32
- Misses 4232 4242 +10
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
|
Self-review: 6c84fdc The review this pull request demands is unsatisfiable (Copilot quota wall or repeated bot failures on this head). Per the documented fallback, the diff on this head was reviewed by the PR author; this comment is the on-the-record attestation the merge gate reads back. It stops matching on the next push. |



Reported from the demo instance: the MCP module's last import error read
That sentence is true and gives the operator nothing. It does not separate a malformed schema from an oversized one from a well-formed one this import deliberately refuses, and there is no way to tell which of the three happened without reading the normaliser.
What it says now: the reason, and for the common case the keyword whose removal would widen what the tool accepts:
Verified against the real server.
https://mcp.deepwiki.com/mcpdeclaresask_question'srepoNameasanyOf[string, array<string>]; its two sibling tools import fine, which is exactly the "two imported DeepWiki tools" the demo seeds. The new unit test carries that schema verbatim rather than a constructed one.The rejection rules are unchanged.
rejectionReason()mirrorsnormalise()step for step, in the same order, on the same data — including that the keyword walk runs over the FILTERED schema. A keyword sitting in a key that gets dropped anyway (anexamplesblock, say) is therefore never reported as the cause; there is a test for that, because a plausible-but-wrong reason would be worse than the vague one it replaces.Whether the union should be refused at all is a separate question, filed as #848 rather than decided here.
Tests: three new unit tests (real schema refused with the keyword named, a passing sibling schema reports no reason, a keyword in a dropped key is not blamed). Gates run locally: cgl, PHPStan level 10, the normaliser unit suite, and the functional
McpImportsuite on sqlite — all green; CI covers the eight-cell matrix.Assisted by claude-code:claude-fable-5 — Session