Skip to content

fix(api): reject undeclared and off-enum tool arguments (policy R4) - #255

Open
Levalicious wants to merge 2 commits into
developfrom
feature/validate-tool-args
Open

Levalicious wants to merge 2 commits into
developfrom
feature/validate-tool-args

Conversation

@Levalicious

Copy link
Copy Markdown
Owner

Problem

The server never validated call arguments against the advertised inputSchemas, so undeclared keys were silently dropped. Concretely: open_nodes called with cursor (the get_neighbors page key) instead of relationCursor re-served page 1 with an identical nextCursor — every relation past page 1 was unreachable, and it looked like open_nodes ignored cursors. An off-enum direction: "both" also ran without complaint.

Fix

  • The tool list is bound to toolDefinitions; ListTools returns it and dispatch validates every call against the same schemas (validateToolArgs).
  • Undeclared keys and off-enum values → VALIDATION_FAILED, every offender listed in details (argument, message, allowed), tool does not run (R2 validate-first).
  • A misnamed cursor key names the cursor parameter(s) the tool actually takes.
  • docs/api-error-policy.md: R4 now explicitly covers arguments.

Existing per-field checks (LIMIT_EXCEEDED etc.) are untouched.

Tests

tests/arg-validation.test.ts (6): 5 fail on develop, all pass here; the 6th drains a 120-edge backward list via relationCursor (guards the correct path). Full suite 202/202, fuzz protoErr = 0.

🤖 Generated with Claude Code

https://claude.ai/code/session_01B7UQfn7Vue83jAPFaWfmAZ

Levalicious and others added 2 commits November 3, 2026 16:35
The server never validated call arguments against the advertised
inputSchemas, so anything undeclared was silently dropped. In practice:
open_nodes called with `cursor` (get_neighbors' page key) instead of
`relationCursor` re-served page 1 with an identical nextCursor, making
every relation past page 1 unreachable; an off-enum `direction` ("both")
ran without complaint.

dispatch now validates every call against the same tool definitions that
ListTools advertises. Undeclared keys and off-enum values fail with
VALIDATION_FAILED, listing every offender, and the tool does not run. A
misnamed cursor key names the cursor parameter(s) the tool does take.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01B7UQfn7Vue83jAPFaWfmAZ
@github-actions

github-actions Bot commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

Per-op benchmark — p50 cycles (base vs head)

base runs: 5, head runs: 5 (median of mins) · freq-correction ×1.0038 · threshold head−base > max(40 cyc, 5%)

op base head* Δ Δ%
lookup 75.2 73 -2.2 -2.9%
read_entity 36.5 37 +0.5 +1.4%
neighbors_d1 584.4 587 +2.6 +0.4%
neighbors_d2 2025.1 1999 -26.1 -1.3%
find_path_d6 163514 159914 -3600.0 -2.2%
search 969670 1002076 +32406.0 +3.3%
entities_by_type 14404 14485 +81.0 +0.6%
random_walk_d5 1207.1 1193 -14.1 -1.2%
inc_walker_visit 15.6 16 +0.4 +2.6%
structural_sample 2315430 2329747 +14317.0 +0.6%
compute_merw_psi 686088 709367 +23279.0 +3.4%
create_entity 884 887 +3.0 +0.3%
create_relation 780 783 +3.0 +0.4%

* head frequency-corrected to base via the reference op.

No regressions beyond threshold.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant