Conversation
When connect() fails with an auth error, handleAuthError re-runs auth() and, if it reports success (which it does whenever a token is already stored), connect() retries. If the server keeps returning 401 for that token — e.g. the authenticated account isn't authorized for the server — this recursion never terminates: it spins up a new transport and re-runs OAuth discovery on every iteration, hammering the server and burying the real 401 response under a flood of identical requests. Cap the re-auth retry at one attempt. One retry still covers the legitimate case (we just obtained a token), but a persistently-rejecting server now stops after the second failure, sets the error state, and surfaces a message instead of looping. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012FAFCf8AzpqyNF1oKZNGzh
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.
Summary
Fixes an infinite reconnect loop: when a connection fails auth and the stored token is accepted by the OAuth flow but rejected by the server (e.g. the authenticated account isn't authorized for that MCP server), the Inspector retries forever — spinning up a new transport and re-running OAuth discovery on every iteration, flooding the server and burying the real 401.
Type of Change
Changes Made
In
useConnection.connect(), an auth failure callshandleAuthError(), which re-runsauth().auth()returnsAUTHORIZEDwhenever a token is already stored, soshouldRetryistrueandconnect()recurses — with no cap onretryCount. If the server keeps returning 401 for that token, the recursion never terminates.MAX_CONNECT_AUTH_RETRIES = 1). One retry still covers the legitimate case (we just obtained a token); beyond that, a persistently-rejecting server stops instead of looping.connect()attempts exactly twice (initial + one retry) and lands in theerrorstate when the server keeps 401ing.Happy path and the single-retry recovery path are unchanged.
Related Issues
Surfaced while testing OAuth against a deployment where the logged-in user wasn't authorized: the server returned a legitimate 401 on every attempt and the client looped indefinitely, making the real error impossible to see.
Testing
Test Results and/or Instructions
To reproduce the original loop: connect (Streamable HTTP, Via Proxy) with OAuth to a server that will 401 the obtained token (e.g. authenticate as a user without access). Before: an endless stream of identical
/mcprequests and repeatingNew StreamableHttp connection request … Error … 401in the proxy console. After: two attempts, then the connection goes toerrorwith a toast.New unit test (
useConnection→ "Auth retry cap") covers it. Full client suite (540) + lint + build pass.Checklist
npm run prettier-fix)Breaking Changes
None. Only changes behavior in the previously-infinite failure case.
Additional Context
Independent of the "apply custom headers to OAuth requests" work (PR #1) and the dev-launcher
--strictPortfix (PR #2) — this touches only the retry recursion inuseConnection. Pre-existing behavior, not introduced by either of those.🤖 Generated with Claude Code
Generated by Claude Code