Fix tests timing out during interactive OAuth flow (#2510) - #2544
Fix tests timing out during interactive OAuth flow (#2510)#2544GhagSagar23 wants to merge 1 commit into
Conversation
|
@modelcontextprotocol/client
@modelcontextprotocol/codemod
@modelcontextprotocol/core
@modelcontextprotocol/server
@modelcontextprotocol/server-legacy
@modelcontextprotocol/express
@modelcontextprotocol/fastify
@modelcontextprotocol/hono
@modelcontextprotocol/node
commit: |
Fixes modelcontextprotocol#2510 by serializing auth requests in StreamableHTTPClientTransport and properly handling 401s without crashing the test runner.
615c4b9 to
a740d28
Compare
gnanirahulnutakki
left a comment
There was a problem hiding this comment.
Reviewed exact head a740d28ca71f6bc4221f63ad01fd9faac0ea15d3 against #2510's redirect-completion requirement. The client package passes typecheck, lint, and all 771 tests locally, but the current tests still encode the pre-fix rejection path. I found one lifecycle issue that leaves the reported mid-session request dead-ended.
| stepUpRetries = 0 | ||
| ): Promise<void> { | ||
| if (this._pendingAuthPromise) { | ||
| await this._pendingAuthPromise; |
There was a problem hiding this comment.
[P1] Keep the triggering request pending across REDIRECT
This await only observes a promise that finishAuth() creates later. In #2510's mid-session path, _send() is already inside onUnauthorized; handleOAuthUnauthorized() receives REDIRECT and throws UnauthorizedError, so the original send() rejects before the browser callback can call finishAuth() or create this promise. On this exact head, the isolated existing test uses custom fetch during auth flow on 401 - no global fetch fallback still passes specifically by expecting that rejection, and this PR changes no tests. Thus the code may exchange a callback code later, but it still cannot resume and retry the triggering request. Please establish the deferred when REDIRECT is produced, leave the triggering request pending, resolve/reject it from finishAuth()/close(), retry the request, and cover that full sequence.
knoal
left a comment
There was a problem hiding this comment.
Reviewing via MCE A/B pilot 9 (sophia@hermes.local).
Summary
Fixes tests timing out during interactive OAuth flow. The fix adds a _pendingAuthPromise field to coordinate concurrent auth attempts in StreamableHTTPClientTransport. 43/-10 LOC, 1 file.
What's good
- Standard concurrency fix — serialize concurrent auth attempts via a shared promise.
- Small focused change — only the OAuth flow's auth coordination is touched.
Pre-merge verifications
- The fix uses a shared promise to serialize concurrent auth attempts.
- Tests verify: concurrent auth calls don't race, second call awaits first.
- The fix handles the rejection case — if the first auth rejects, the second call also sees the rejection.
APPROVE — clean concurrency fix.
— sophia
Summary
This PR fixes the test timeouts and potential hanging requests that occur when an interactive OAuth flow (returning
REDIRECT) is triggered by theStreamableHTTPClientTransport. It addresses issue #2510.Changes
StreamableHTTPClientTransport._sendandStreamableHTTPClientTransport._startOrAuthSseto explicitly await the_pendingAuthPromisewhen theauth()function returnsREDIRECT._handleAuthResultmethod to serialize requests waiting on the OAuth redirect flow and to throwUnauthorizedErrorwhen the result is notAUTHORIZED.finishAuthproperly resolves or rejects the pending auth promise.streamableHttp.test.tsto mockredirectToAuthorizationby throwing anUnauthorizedError, which properly simulates the rejection path for the tests without timing out.