fix: preserve distinct MCP structured results - #105116
JuliaF1988 wants to merge 3 commits into
Conversation
andrexibiza
left a comment
There was a problem hiding this comment.
Reviewed exact head dd0efb83639193617647a1de39f160b903feb50e against live main 478d772f2cc6421fda1d115137b8da92cd4f7d1a. The branch is currently 1 ahead / 71 behind live main. I traced the result renderer, breaker accounting/recovery path, the two changed MCP suites, exact-head Actions state, and the related MCP result/ownership lineage.
The central breaker correction is sound in principle: a completed tools/call that returns isError=true proves transport reachability and should not poison a server-level outage breaker. The explicit transport-exception negative control is good, and the new native-ID / nested structured-result / hard-cap cases are useful coverage. There are two data-contract blockers before this is safe to land; both are inline.
Verification state: the PR reports 672/672 local MCP tests plus Ruff/diff checks, but the exact head currently has CI, Docker, and Nix all completed as action_required, so this one-commit train is 0/1 hosted-green. Also, the new regressions exercise mocked sessions. The repo's network-I/O contract calls for a real-path behavioral proof; this does not require the external Defender deployment. A local/in-memory MCP SDK peer through the real handler path is enough to prove: (1) an isError=true round trip leaves the breaker closed, (2) its machine-readable error payload survives projection, (3) distinct text + structuredContent survive while exact dual-emits dedupe once, and (4) a genuine transport exception still strikes the breaker. Please rebase and rerun that proof on live main as well; tools/mcp_tool.py has moved since this branch's merge base.
Interlocks / provenance:
- Merged #96807 is the credited carrier of the current
content/structuredContentarbitration and the Kimi #3234 dedup port. This PR is a deliberate refinement of that policy for lossy summaries, not a new origin for the dedup shape; retain #96807's credit and its no-double-context/drop-notice goals. - #101344 is complementary work on the same defect-class principle: an SDK output-schema failure after a completed RPC is not evidence that the server transport is down.
- #47867 / #47871 own the adjacent
isErrornested-error readability problem. This PR should compose with that work by retaining machine-readable error data, not replace its attribution or independently fork message extraction. - #74262 is complementary downstream classification for application failures inside
isError=falseenvelopes; transport health and application outcome remain separate axes. - #104534 is complementary profile-qualified MCP connection ownership and also touches
mcp_tool_handlers.pyin lookup/check paths. Its hunks are not duplicate ownership of this renderer change, but whichever lands second needs a fresh rebase and the combined MCP suite.
This is good, focused work on a real MCP boundary. Once the two projection gaps below are closed and the exact-head train is actually green, the breaker/result split will be materially stronger. 🚀
10af635 to
621f7b2
Compare
|
Rebased on current |
|
Retriggering CI (zero-job dispatch failure on the rebased head) — reopening immediately. |
|
Upstream corroboration: MoonshotAI/kimi-code#3654 (merged Sep 8) lands the same refinement of their #3234 absolute-suppression rule this PR makes to our #96807 port — suppress |
621f7b2 to
3e62353
Compare
3e62353 to
f60c2e1
Compare
|
Reconciled the PR metadata and exact head |
f60c2e1 to
9553889
Compare
9553889 to
ef82a0b
Compare
Summary
This PR is narrowly scoped to preserving distinct MCP result data and refining exact duplicate suppression. It follows the circuit-breaker policy already merged in #109245.
Current head
ef82a0b6181d83ad5912a5aeb45f6631c38c046fis rebased ontoupstream/mainat61e730cc0b7594eeb8e92fd8a56e4259ba87cfe6.Current scope
contentandstructuredContentinstead of discarding authoritative machine-readable data whenever usable text exists.1 != true,0 != false, with the same rule inside nested objects and arrays. False negatives retain duplicate context; false positives would lose data.isError=trueresult as the established top-level human-readableerrorplus completestructuredContentand permitted/non-reserved_meta.Breaker policy
This PR follows merged #109245 and does not change the general
isError=truebreaker policy:isError=trueremains an application-error circuit-breaker strike.rejected/reachablewording.unreachablesemantics; one transport strike in a mixed streak selects that wording.Result projection and breaker accounting are separate concerns: preserving structured error data does not make the result a breaker success.
Post-RPC output-schema validation
MCP SDK output-schema validation is handled separately from ordinary
isError=trueresults. MCP SDK 2.0.0 still validates aftersend_request()completes and still emits the two specifically matchedRuntimeErrorsignatures for missing or invalid structured output. Only those narrow post-response cases reset the transport breaker; arbitraryRuntimeErrorand genuine transport/session/timeout failures remain strikes.Final rebase reconciliation
The final maintenance rebase onto
61e730cc0b7594eeb8e92fd8a56e4259ba87cfe6was conflict-free. Intervening upstream changes compose without duplicating or superseding this PR:No original #105116 hunk was dropped as upstream-equivalent. The final diff remains limited to five intended files and three commits.
Validation
Validated at exact head
ef82a0b6181d83ad5912a5aeb45f6631c38c046f:tests/tools/test_mcp*.py, refresh/setup/reconciliation paths, and all new mainline MCP regressions: 1,254 passed, 2 skipped, 0 failed across 115 files.git diff --check: PASS.Hosted CI, Docker, and Nix workflows for this exact head are
action_required, pending upstream maintainer approval. They were not manually triggered or bypassed.Provenance and interlocks
content/structuredContentarbitration and fix(mcp): send content or structuredContent to the model, never both MoonshotAI/kimi-code#3234 duplicate-context work. This PR only narrows suppression to exact JSON equality so distinct structured data survives.rejected/reachableversusunreachablebreaker wording; this PR preserves that implementation.isErrorhuman-readable error extraction; this PR preserves the machine-readable structured payload without replacing that work.This branch should now be left untouched pending upstream maintainer action. Further rebases are warranted only on maintainer request, actionable hosted-CI failure, a confirmed merge conflict at merge time, or direct upstream supersession/conflict.