Skip to content

api: advertised tool schemas drift from the pydantic models and unknown keys are silently ignored (C-10, M-02) #236

Open

Description

@ViperJuice

From the 2026-09-01 codebase review (plans/codebase-review-2026-09-01.md), C-10 (MEDIUM, reproduced) with M-02.

The tool input schemas advertised over MCP are maintained by hand, separately from the pydantic models that actually validate the arguments. Two failure modes follow:

  • Drift: the advertised schema and the enforced model disagree, so an agent that obeys the published contract can still be rejected — and worse, a schema can keep advertising a parameter the model no longer honours.
  • Silent acceptance: the models do not set extra="forbid", so a misspelled or hallucinated key is accepted and ignored rather than refused. For an agent-facing API this is the wrong default: the caller gets success and different behaviour than it asked for, with nothing to notice.

Fix (review's estimate: M): generate the advertised schemas from the pydantic models, and set extra="forbid". Generation removes the drift by construction rather than by discipline.

Worth pinning with a test in the drift direction specifically — a test that asserts "the advertised schema equals the model's schema" for every registered tool will fail the moment someone hand-edits one, which is the regression that matters. Note that extra="forbid" is a behaviour change for existing callers that currently send extra keys and get away with it; that deserves a CHANGELOG note and possibly a release-note callout.

Activity

  1. 1 remaining item

  2. ViperJuice commented on Sep 26, 2026

    @ViperJuice
    CollaboratorAuthor

    Status: the plan merged as #291 and piece A merged as #300 (cdaf3c6). Advertised gateway tool schemas are now derived from their models, and unregistered names fail closed.

    Remaining for this issue:

  3. ViperJuice commented on Sep 27, 2026

    @ViperJuice
    CollaboratorAuthor

    #296 (record tools/call gate rejections in the scoped audit) is merged as #306, so piece B (extra="forbid") is no longer blocked by it. #301 (the pre-release host tools/list smoke test for piece A) is still open.

    🤖 Generated with Claude Code

  4. JDeun commented on Oct 2, 2026

    @JDeun

    SchemaRouter overlap / possible benchmark question:

    PMCP already solves progressive disclosure and schema-on-demand at the gateway layer. SchemaRouter is a typed capability retrieval layer that indexes provider/endpoint/field semantics while leaving execution authority with the host.

    Rather than proposing a competing gateway, I'd be interested in a reproducible comparison on the same downstream catalog: PMCP native discovery vs typed field-aware preselection feeding PMCP, measuring required-tool recall, unsupported/no-route rejection, revealed schema bytes, shortlist size, and routing latency.

    This also seems adjacent to #236: SchemaRouter can consume generated schemas, but PMCP should remain authoritative for schema generation/validation and execution. The useful question is only whether field-level retrieval improves discovery once that schema contract is trustworthy.

    If this boundary is useful, I can prepare an optional benchmark/example and report negative results as-is. SchemaRouter: https://github.com/JDeun/SchemaRouter

  5. added a commit that references this issue on Oct 4, 2026
  6. ViperJuice commented on Oct 5, 2026

    @ViperJuice
    CollaboratorAuthor

    Thanks for the thoughtful note, and for offering to report negative results as they come. We're going to pass on a joint or co-run comparison: pmcp isn't taking part in or endorsing outside benchmarks. We do agree discovery quality is worth measuring, and we plan to publish our own reproducible discovery benchmark for pmcp. Anyone, including SchemaRouter, will be welcome to run it independently. Best of luck with the project.

  7. added a commit that references this issue on Oct 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions