fix(mcplocal): stop upstream required params from blocking a drill-down #129

Merged
michal merged 1 commits from fix/drilldown-required-params into main 2026-09-05 16:59:47 +00:00
Owner

A paginated tool result instructs the model to call the same tool again with only _resultId/_section. The advertised schema still carried the upstream's own required list, so a validating client rejected that exact call ("Received tool input did not match expected schema") and the model concluded pagination was broken.

Verified live: websearch_fetch_content advertised required: ["url"] alongside the drill-down params.

required is ANDed with the rest of the schema, so declaring properties could not fix it. It is now an alternation — the upstream's requirements (fresh call) OR _resultId (a re-read, answered from cache, never forwarded upstream). Validators that understand anyOf enforce it; naive ones see no top-level required and accept both. Existing combinators are preserved (alternation appended to allOf); schemas without required are untouched.

Tests: 4 new unit tests (required-bearing schema, drill-down without required params, no-required schema untouched, combinator composition) + a smoke assertion that no advertised tool keeps a drill-down-blocking required. Full mcplocal suite green (850 tests).

🤖 Generated with Claude Code

https://claude.ai/code/session_01JQr5Z9gYrqBQXTGBBuemZ2

A paginated tool result instructs the model to call the same tool again with only `_resultId`/`_section`. The advertised schema still carried the upstream's own `required` list, so a validating client rejected that exact call ("Received tool input did not match expected schema") and the model concluded pagination was broken. Verified live: `websearch_fetch_content` advertised `required: ["url"]` alongside the drill-down params. `required` is ANDed with the rest of the schema, so declaring properties could not fix it. It is now an alternation — the upstream's requirements (fresh call) OR `_resultId` (a re-read, answered from cache, never forwarded upstream). Validators that understand `anyOf` enforce it; naive ones see no top-level `required` and accept both. Existing combinators are preserved (alternation appended to `allOf`); schemas without `required` are untouched. Tests: 4 new unit tests (required-bearing schema, drill-down without required params, no-required schema untouched, combinator composition) + a smoke assertion that no advertised tool keeps a drill-down-blocking `required`. Full mcplocal suite green (850 tests). 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01JQr5Z9gYrqBQXTGBBuemZ2
michal added 1 commit 2026-09-05 16:59:05 +00:00
fix(mcplocal): stop upstream required params from blocking a drill-down
Some checks failed
CI/CD / typecheck (pull_request) Successful in 1m27s
CI/CD / lint (pull_request) Successful in 2m22s
CI/CD / test (pull_request) Successful in 1m31s
CI/CD / smoke (pull_request) Failing after 2m41s
CI/CD / build (pull_request) Successful in 2m21s
CI/CD / publish (pull_request) Has been skipped
0e12637271
A paginated tool result tells the model to call the same tool again with
only _resultId/_section. The advertised schema still carried the upstream's
own `required` list, so a client that validates arguments rejected exactly
that call — "Received tool input did not match expected schema" — and the
model concluded pagination was broken and gave up
(websearch/fetch_content requires `url`; verified live on llm-model-tester).

`required` is ANDed with everything else in a schema, so no property
declaration could rescue it. It now becomes an alternation: either the
upstream's requirements (a fresh call) or `_resultId` (a re-read, which is
answered from cache and never reaches the upstream). Validators that
understand anyOf enforce that; naive ones that only read top-level
`required` now find none and accept both. Schemas that already carry a
combinator get the alternation appended to `allOf`, and a schema with no
required params is left untouched.

Covered by unit tests on a required-bearing upstream schema plus a smoke
assertion that no advertised tool keeps a drill-down-blocking `required`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JQr5Z9gYrqBQXTGBBuemZ2
michal merged commit b5d0234d0b into main 2026-09-05 16:59:47 +00:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: michal/mcpctl#129