Strict MCP arguments (#2709) + zero-Systems bootstrap ask (#2683) #113

Merged
bvandeusen merged 2 commits from dev into main 2026-08-17 16:26:32 -04:00
Owner

Two fixes from the open-issue list:

  • #2709 — reject undeclared tool arguments instead of silently dropping them. FastMCP's pydantic validation ignored extra fields, so create_note(content=...) reported success and stored an empty body — invisible to embedding/search. StrictArgsFastMCP now rejects any tool call carrying undeclared arguments before dispatch, with a did-you-mean hint, on every tool.
  • #2683 — evidence-carrying bootstrap ask for mature zero-Systems projects. A project with ≥20 records and no Systems gets a concrete, self-retiring ask (record count + recent titles → propose 3–6 Systems, confirm, create) at both the write moment (systems_hint escalation) and arrival (enter_project.systems_bootstrap). Young projects keep the mild question; the first create_system retires the ask everywhere.

CI green on both commits (runs 3869, 3889).

🤖 Generated with Claude Code

Two fixes from the open-issue list: - **#2709 — reject undeclared tool arguments instead of silently dropping them.** FastMCP's pydantic validation ignored extra fields, so `create_note(content=...)` reported success and stored an empty body — invisible to embedding/search. `StrictArgsFastMCP` now rejects any tool call carrying undeclared arguments before dispatch, with a did-you-mean hint, on every tool. - **#2683 — evidence-carrying bootstrap ask for mature zero-Systems projects.** A project with ≥20 records and no Systems gets a concrete, self-retiring ask (record count + recent titles → propose 3–6 Systems, confirm, create) at both the write moment (`systems_hint` escalation) and arrival (`enter_project.systems_bootstrap`). Young projects keep the mild question; the first `create_system` retires the ask everywhere. CI green on both commits (runs 3869, 3889). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
bvandeusen added 2 commits 2026-08-17 16:26:24 -04:00
fix(mcp): reject undeclared tool arguments instead of silently dropping them (#2709)
CI & Build / Plugin hooks (push) Successful in 10s
CI & Build / integration (push) Successful in 23s
CI & Build / TypeScript typecheck (push) Successful in 33s
CI & Build / Python lint (push) Successful in 4s
CI & Build / Python tests (push) Successful in 1m4s
CI & Build / Build & push image (push) Successful in 37s
d6c9f08a59
FastMCP validates tool arguments with a pydantic model whose extra-field
policy is 'ignore', so create_note(content=...) — a plausible near-miss
for body=, primed by add_task_log's content — ran successfully, stored
body: '', and left a record embedding/search cannot see. Two real notes
were persisted body-less before the pattern was noticed; create_task
only 'worked' because those calls happened to use the right name.

StrictArgsFastMCP rejects any tool call carrying arguments the tool does
not declare, before dispatch, with a did-you-mean hint when one is close
and the declared list when none is. Applied at the dispatch seam so
every tool gets the guarantee — an error the caller sees once beats data
half-written forever.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
feat(systems): evidence-carrying bootstrap ask for mature zero-Systems projects (#2683)
CI & Build / Build & push image (push) Successful in 39s
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 10s
CI & Build / integration (push) Successful in 24s
CI & Build / TypeScript typecheck (push) Successful in 33s
CI & Build / Python tests (push) Successful in 1m4s
7a5e2b18d9
The generic zero-state systems_hint never converts: identical on every
record, maximal in scope, asked at wrap-up time — Minstrel reached 282
records with zero Systems while vocabularied projects grew organically.
What converts is the project's own evidence at the moment of action.

bootstrap_systems_ask (mcp/tools/systems.py) fires only in a project
with >=20 records and no Systems: it names the record count and recent
titles, and asks for a concrete deliverable — propose 3-6 Systems,
confirm with the operator, create_system the set. Self-retiring: the
first System ends it everywhere. Wired at both moments the task named:
untagged_systems_hint escalates to it at write time, and enter_project
carries it as systems_bootstrap at arrival (attached only when it
applies). Young projects keep the mild question; populated vocabularies
never pay the count query.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
bvandeusen merged commit 5c14c2621c into main 2026-08-17 16:26:32 -04:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: bvandeusen/FabledScribe#113