Require the signed envelope and document where to get one - #1
Merged
Merged
Conversation
The MCP canary reached tool discovery and then failed on the only tool call with
HTTP 400. Root cause: the free route POST /v1/demo/verify accepts bare claims and
works, so the landing page, the playground and the published Postman example all
teach that shape, while the paid POST /v1/verify requires the signed envelope
returned by POST /v1/mandates.
The tool schema was z.record(z.string(), z.unknown()), which accepted the bare
shape and forwarded a request that could not succeed. The developer saw
"mandate.mandate" must be the claims object — an internal field path with no
route to a signed mandate.
The schema now requires {mandate, signature}, so the tool refuses locally with a
message naming the real cause. The tool description says the argument is the
envelope returned by POST /v1/mandates and that bare claims belong to the keyless
demo route. The README gains the missing first step as a copyable walkthrough,
with the HTTP 400 named and explained, and states that a deny or
requires_approval is a correct result rather than a failure.
Three existing fixtures passed only because the old schema accepted anything;
they now carry a structurally real envelope. A regression suite asserts the bare
shape is refused and that the real POST /v1/mandates response passes through
unchanged with its extra fields preserved.
Verified end to end against production: POST /v1/mandates returns 201 with
mandate, signature and requestId; passing that envelope to verify_action through
the built server returns decision requires_approval with the expected violation.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The defect
The MCP canary reached tool discovery and then failed on the only tool call, HTTP 400.
The free route
POST /v1/demo/verifyaccepts bare claims and works, so the landing page, the playground and the published Postman example all teach that shape. The paidPOST /v1/verifyrequires the signed envelope returned byPOST /v1/mandates.The tool schema was
z.record(z.string(), z.unknown())— it accepted the bare shape and forwarded a request that could not succeed. The developer saw"mandate.mandate" must be the claims object, an internal field path with no route to a signed mandate.This is on the only surface with verified external discovery: the Glama listing advertises this package, so it is the most likely first contact a real developer has with the product.
The fix
{mandate, signature}, so the tool refuses locally with a message naming the real cause instead of forwarding a doomed request.POST /v1/mandatesas the source of the envelope and notes bare claims belong to the keyless demo route.Why not have the tool mint the envelope itself
It would consume two metered units per verification without the caller knowing, and turn a verification-only tool into one that creates durable authority. The server's own instructions say it never issues or revokes mandates. That property is worth more than the convenience.
Tests
Three existing fixtures passed only because the old schema accepted anything; they now carry a structurally real envelope. A new regression suite asserts the bare shape is refused, an envelope without a signature is refused, an empty signature is refused, the real
/v1/mandatesresponse passes unchanged, and passthrough preserves extra fields.28/28 pass.
Verified against production
That is the correct decision for the fixture: 30000 requested against an
approvalRequiredAboveMinorof 25000.Version bumped to 0.1.1 in
package.json,server.jsonand the README install commands.🤖 Generated with Claude Code