fix(mcp): report transient session-endpoint failures as 503, not invalid token - #1587
Open
Sravanjangam wants to merge 2 commits into
Open
fix(mcp): report transient session-endpoint failures as 503, not invalid token#1587Sravanjangam wants to merge 2 commits into
Sravanjangam wants to merge 2 commits into
Conversation
…lid token validateApiKey collapsed every fetchSession failure (network error, timeout, any non-OK status) to null, which the transport mapped to 'Invalid or expired token'. During api.supermemory.ai outages that made MCP clients discard perfectly valid sm_ keys and forced users through re-authentication at exactly the wrong moment (supermemoryai#1551). - new TransientAuthError: validateApiKey rethrows it for timeouts and non-401/403 upstream statuses; only genuine rejections return null - transport maps TransientAuthError to a 503 JSON-RPC response with Retry-After instead of the invalid_token error - tests cover the 500 and timeout paths; 401 still resolves null
| const authUser = isApiKey(token) | ||
| ? await validateApiKey(token, apiUrl) | ||
| : await validateOAuthToken(token, apiUrl, mcpResource) | ||
| let authUser: AuthUser | null |
There was a problem hiding this comment.
The variable authUser is declared with let on line 185. While let is technically required here because the variable is assigned inside a try block, the style guide states 'Use const by default. Use let only when reassignment is needed.' In this case the variable is not reassigned after initial assignment — it is only assigned once inside the try block. Consider restructuring to avoid let by extracting the try/catch into a helper function that returns the value, allowing const authUser = await resolveAuthUser(...) at the call site.
Spotted by Graphite (based on custom rule: TypeScript style guide (Google))
Is this helpful? React 👍 or 👎 to let us know.
Extracts resolveAuthUser() returning AuthResolution (ok/user vs invalid vs transient), so the call site is all-const and the transient 503 mapping stays explicit. Behavior unchanged; addressed from Graphite's inline review on supermemoryai#1587.
graphite-app Bot
pushed a commit
that referenced
this pull request
Aug 24, 2026
…#1591) Cherry-picks #1587 from @Sravanjangam, plus the OAuth half on top. When the auth backend is slow or returns a 5xx, the MCP server currently answers `invalid_token`. That is the protocol's signal to discard the credential and re-authenticate, so a brief upstream blip logs every connected client out, and `sm_` API key users have no automatic way back. These requests now return 503 with `Retry-After: 5` so clients retry instead. His change covered the API key path only. This shares one `transientAuthErrorFor` helper between `validateApiKey` and `validateOAuthToken`, so a JWKS timeout or a 5xx also returns 503 on the OAuth path that Claude, Cursor and browser clients use. Genuinely bad tokens are unaffected: bad signature, expired, and no-matching-key still resolve to 401. Verified across all seven cases. Co-Authored-By: Sravanjangam <163002695+Sravanjangam@users.noreply.github.com>
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.
Fixes #1551.
Hi supermemory team 👋 Thanks for building such a great product! While running a security & quality audit of the repo we hit this issue and put together a small, tested fix — details below.
Problem
validateApiKeycollapsed everyfetchSessionfailure — network errors, timeouts, any non-OK status — intonull, which the transport maps to JSON-RPC-32000 "Invalid or expired token". During an api.supermemory.ai/Hyperdrive outage this made MCP clients discard perfectly validsm_keys and forced users through browser re-authentication at exactly the wrong moment, amplifying incidents into support load.Solution
Classify failures instead of collapsing them. A new
TransientAuthErroris thrown for timeouts (AbortError/TimeoutError) and upstream statuses other than 401/403; the transport maps it to a 503 JSON-RPC response withRetry-After: 5. Genuine rejections (401/403/schema failures/missing org) still resolvenull→ unchangedinvalid_tokenbehavior. Success-path caching untouched.Changes
apps/mcp/src/server/auth/index.ts→TransientAuthErrorclass + typed catch invalidateApiKeyapps/mcp/src/server/index.ts→ try/catch around token validation → 503 response withRetry-Afterapps/mcp/src/server/auth/index.test.ts→ +2 tests (500 → TransientAuthError; timeout → TransientAuthError)resolveAuthUser()returning a typedAuthResolutionunion — call site is all-const, behavior unchangedVerification
Fresh from the committed branch:
bunx vitest run src/server/auth→ 15/15 pass, including the pre-existing revoked-key →nullcase proving rejection behavior is unchanged;tscadds zero new errors vs baseline; Biome clean.Happy to iterate on any of this — feedback and reworks very welcome! 🙏
Environment
fix/mcp-transient-session-errors— all gates re-run fresh at commitb561e12a27c5