fix(mcp): carry resultType on unknown-argument rejections #758

Merged
hexajon merged 2 commits from issue-740-resulttype-rejection into main 2026-10-13 21:23:53 +00:00
Owner

Summary

A 2026-07-28 MCP client rejects a tools/call result that omits resultType.
Unknown-argument rejections omitted it, so the caller saw a malformed-result
error instead of the did-you-mean message (#740).

The rejection ran as a receiving middleware that short-circuited before the SDK
stamps resultType. The SDK schema validator already rejects an unknown argument
in band, and callTool stamps that result, so this removes the pre-empting
middleware and moves the did-you-mean into the existing enrichment, which mutates
the already-stamped validator result. The matcher bounds are unchanged (ADR 0005).

A new conformance gate asserts every tool's rejection carries resultType (39
tools), covering the error path the previous guard skipped.

Closes #740

## Summary A 2026-07-28 MCP client rejects a tools/call result that omits resultType. Unknown-argument rejections omitted it, so the caller saw a malformed-result error instead of the did-you-mean message (#740). The rejection ran as a receiving middleware that short-circuited before the SDK stamps resultType. The SDK schema validator already rejects an unknown argument in band, and callTool stamps that result, so this removes the pre-empting middleware and moves the did-you-mean into the existing enrichment, which mutates the already-stamped validator result. The matcher bounds are unchanged (ADR 0005). A new conformance gate asserts every tool's rejection carries resultType (39 tools), covering the error path the previous guard skipped. Closes #740
A 2026-07-28 client rejects a tools/call result that omits resultType. The
existing guard checks only success results and bails on any error result, so an
unknown-argument rejection that omitted resultType went uncaught.

TestEveryToolRejectionCarriesResultType trips the unknown-argument rejection for
every registered tool and asserts resultType on the wire;
TestRejectionResultCarriesResultType is the focused madt_repos case.

Refs #740
fix(mcp): carry resultType on unknown-argument rejections
Some checks failed
drift / govulncheck (pull_request) Has been skipped
drift / surface-diff (pull_request) Successful in 41s
drift / forgejo-smoke (pull_request) Has been skipped
ci / mcp-conformance (pull_request) Successful in 1m28s
ci / mcp-conformance (push) Successful in -27s
drift / govulncheck (push) Has been skipped
drift / surface-diff (push) Successful in -23s
drift / forgejo-smoke (push) Has been skipped
ci / gate (push) Failing after 4m18s
ci / gate (pull_request) Successful in 17m38s
93edff6708
The unknown-argument rejection ran as a receiving middleware that short-circuited
with a bare CallToolResult, before the SDK layer that stamps resultType. On a
2026-07-28 session a conforming client rejected that result as malformed, hiding
the did-you-mean message from the caller.

The SDK schema validator already rejects an unknown argument in band
(additionalProperties is false), and callTool stamps resultType on that result.
So remove the pre-empting middleware and let the validator reject;
installValidationEnrichment now carries the did-you-mean by reusing
formatUnknownArgs, mutating the already-stamped result so the message inherits
the stamp. The matcher bounds are unchanged (ADR 0005).

Refs #740
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
sixfold-space/madtea!758
No description provided.