fix(mcp): recovered retry keeps the tool's real answer, breaker strike intact (salvage #106753) - #109180
Merged
Conversation
The pick returns the real result after a transport recovery instead of dropping it, but it also skipped the breaker bookkeeping. Application errors counting as strikes is the point of the breaker (3ff18ff, #10447: a server answering errors made the model hammer it 8x in 10s). Route the recovered result through _record_call_outcome so the caller sees the tool's answer and the counter still moves the right way.
Contributor
૮ >ﻌ< ა ci reviewran on d89b7bb — chore: map contributor email d.hermsmeier@mittwald.de -> Her
|
19 tasks
This was referenced Sep 12, 2026
teknium1
added a commit
that referenced
this pull request
Sep 12, 2026
…able" Application errors (isError payloads) keep counting as breaker strikes: that is #10447's point (a server answering errors made the model hammer it 8x in 10s) and #109180 just reasserted it. What #11113 actually hit is the open-breaker MESSAGE: after three rejected fetches the model was told the server was "unreachable" and went to the user instead of fixing its URL. Track whether the streak was all application errors and word the pause accordingly; one transport strike restores the unreachable text.
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.
After an MCP transport recovery (OAuth refresh or session reconnect), the retried call's real result now reaches the model even when the tool answered with an application error, instead of being dropped for a generic "needs reauth" / "call failed" message.
Salvages #106753 from @Hermsi1337 (earliest fix on this path).
What was wrong
tools/mcp_tool_handlers.py::_retry_oncereturnedNonewhen the retried call came back with an{"error": ...}payload, so the caller fell through to_strike(... needs_reauth=True)or the generic failure path. The tool had actually answered; the model just never saw it. Code-path reachable on every recovery path (_handle_auth_error_and_retry,_handle_session_expired_and_retry).Changes
_retry_oncereturns the retried result whenever the RPC completed (@Hermsi1337's commit, cherry-picked verbatim)._record_call_outcomeso an application error still counts as one breaker strike. The strike is the feature: 3ff18ff (fix: add circuit breaker to MCP tool handler to prevent retry burn loops #10776, closes Gateway hangs when Google Workspace MCP skill returns error — infinite retry loop #10447) added the breaker precisely because a server answering errors made the model hammer it 8× in 10 s. The contributor's version reset the counter on error answers; this variant keeps the answer and the semantics.test_call_tool_handler_rebuilds_configured_server_transportis parametrized overapplication_error(contributor) and asserts the counter is1after an error answer,0after a success (mine). Conflict with main's newer stdiooutcome_uncertainbranch resolved keep-both.contributors/emails/d.hermsmeier@mittwald.de→ Hermsi1337.Not salvaged
Validation
scripts/run_tests.sh tests/tools/test_mcp_tool_session_expired.py tests/tools/test_mcp_circuit_breaker.pyorigin/mainhandlers swapped in)application-error-httpparam fails:{'error': 'MCP call failed: ClosedResourceError…'} != {'error': 'reconnected'}git diff --checkInfographic