Fix MCP OAuth resume order in Node.js SDK#1861
Merged
Merged
Conversation
resumeSession issued the session-scoped session.eventLog.registerInterest RPC for mcp.oauth_required BEFORE session.resume. The runtime only registers the session in its routing table while handling session.resume, so a fresh process resuming a persisted session rejected the pre-resume registerInterest with 'Session not found for sessionId: <id>'. VS Code always passes onMcpAuthRequest, so every resume threw. Move the registerInterest block to after the session.resume response is processed, mirroring the already-correct createSession path. Add a unit test asserting resume is sent before registerInterest, and an e2e test that reproduces the runtime error end-to-end via a fresh-client resume. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes a Node.js SDK session-resume regression where registering mcp.oauth_required interest could occur before the runtime had routed/registered the resumed session, causing Session not found for sessionId: <id> when onMcpAuthRequest is configured (a common VS Code path).
Changes:
- Move
session.eventLog.registerInterest(mcp.oauth_required)inresumeSessionto run after thesession.resumeRPC completes. - Update unit coverage to assert resume ordering and handler/no-handler behavior.
- Add an E2E that reproduces the cross-process resume scenario (new CLI process) and a new replay snapshot.
Show a summary per file
| File | Description |
|---|---|
| nodejs/src/client.ts | Moves MCP OAuth interest registration to after session.resume to avoid runtime “session not found”. |
| nodejs/test/client.test.ts | Updates unit test to assert session.resume occurs before registerInterest when auth handler is configured. |
| nodejs/test/e2e/session.e2e.test.ts | Adds E2E coverage for resuming a persisted session from a fresh client with onMcpAuthRequest. |
| test/snapshots/session/resumes_a_persisted_session_from_a_new_client_when_an_mcp_oauth_handler_is_configured.yaml | Adds replay snapshot used by the new E2E. |
Review details
- Files reviewed: 4/4 changed files
- Comments generated: 2
- Review effort level: Low
stephentoub
reviewed
Jun 30, 2026
This comment has been minimized.
This comment has been minimized.
The resume path in the Python, Go, .NET, and Rust SDKs issued the session-scoped session.eventLog.registerInterest RPC (mcp.oauth_required) before session.resume. The runtime only registers the session while handling session.resume, so a fresh process resuming a persisted session was rejected with "Session not found for sessionId: <id>". Moved the registerInterest call after the resume response is processed in each SDK, mirroring the already-correct create path. Java was already correct. Added cold-resume + MCP-auth E2E tests for all six SDKs, updated the Python/Go unit-test ordering assertions, and addressed PR review feedback: matched harness token selection in the Node E2E and normalized snapshot files to LF. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
Contributor
Cross-SDK Consistency Review ✅This PR applies the
No consistency gaps found
|
stephentoub
approved these changes
Jul 1, 2026
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.
Why
Resuming a session with an
onMcpAuthRequesthandler failed against the current runtime (1.0.66) withSession not found for sessionId: <id>. VS Code always passesonMcpAuthRequest, so every resume threw, and VS Code then fell back to destructively recreating the session under the same id, which is why users saw old sessions return only asession.startevent fromgetEvents().Root cause
PR #1669 added, in both
createSessionandresumeSession, a block guarded byif (config.onMcpAuthRequest)that issues a session-scopedsession.eventLog.registerInterestRPC formcp.oauth_required. The placement was asymmetric:createSessioncorrectly placed it AFTERsession.create, so the session is already registered.resumeSessionplaced it BEFOREsession.resume. The runtime only registers the session in its routing table while handlingsession.resume, so a fresh process resuming a persisted session hit an unregistered session and the runtime rejected the call.Fix
Move the
registerInterestblock inresumeSessionto AFTER thesession.resumeresponse is processed, mirroring the already-correctcreateSessionpath. The create path is unchanged. Local session registration (this.sessions.set/setupSessionFs) and the surrounding try/catch are untouched; only the runtime RPC moved.registerInterest(mcp.oauth_required)is a gating switch the runtime reads when it builds the MCP OAuth handler as MCP servers connect later, not a buffered subscription, so issuing it aftersession.resumeis still early enough (the create path proves this), and there is no lost-event race.Tests
nodejs/test/client.test.ts): rewrote the resume ordering test to assertsession.resumeis sent BEFOREsession.eventLog.registerInterest, plus the no-handler case. Fails on the old ordering, passes after the fix.nodejs/test/e2e/session.e2e.test.ts+ new snapshot): creates a session withonMcpAuthRequest, takes a turn to persist it, then resumes from a fresh CLI process. Against the unfixed SDK this reproduces the literal runtime errorSession not found for sessionId: <id>onregisterInterest; with the fix it passes.Note on the E2E shape: the runtime gates session-scoped RPCs per process, not per connection, so the bug only surfaces when a different CLI process resumes a persisted session (the VS Code restart scenario). That required a real turn to persist the session, hence the accompanying replay snapshot.
typecheck, eslint, and prettier are clean.