Add SDK MCP OAuth host token handlers#1669
Conversation
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Generated by SDK Consistency Review Agent for issue #1669 · sonnet46 2.1M
| export interface McpAuthToken { | ||
| /** Access token acquired by the SDK host. */ | ||
| accessToken: string; | ||
| /** OAuth token type. Defaults to Bearer when omitted. */ | ||
| tokenType?: string; | ||
| /** Refresh token supplied by the host, if available. */ | ||
| refreshToken?: string; | ||
| /** Token lifetime in seconds, if known. */ | ||
| expiresIn?: number; | ||
| } |
There was a problem hiding this comment.
what about an idToken? idTokens are useful as they contain claims that are good to display like usernames/email/etc.
There was a problem hiding this comment.
So unless I'm mistaken, the runtime wouldn't have any actual use for it; all it needs as a response from the host is the access token to be forwarded back to the MCP server for access... In fact, I'm about to remove the refreshToken from here, since as discussed in yesterday's meeting, refresh would be the host's responsibility, and so the runtime has no use for that.
But let me know if I have the wrong mental model here! Plus we can always add it later.
59694fd to
6d3d655
Compare
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Generated by SDK Consistency Review Agent for issue #1669 · sonnet46 1.8M
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Generated by SDK Consistency Review Agent for issue #1669 · sonnet46 3.1M
a4cfe07 to
e3aae80
Compare
This comment has been minimized.
This comment has been minimized.
530ce4b to
a16180e
Compare
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Generated by SDK Consistency Review Agent for issue #1669 · sonnet46 2.7M
1ef3726 to
87f1785
Compare
This comment has been minimized.
This comment has been minimized.
51c9235 to
d5c709b
Compare
d5c709b to
70ec1fd
Compare
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Generated by SDK Consistency Review Agent for issue #1669 · sonnet46 2.3M
70ec1fd to
672611c
Compare
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Pull request overview
This PR synchronizes all language SDKs in this mono-repo (Node/TS, Python, Go, .NET, Java, Rust) with the runtime’s MCP OAuth lifecycle contract by adding a host-delegated MCP OAuth callback API, wiring it through session event handling, and expanding cross-language E2E coverage using a shared OAuth-protected MCP test fixture.
Changes:
- Add MCP OAuth host callback APIs/types (request + token/cancel result) and wire them to
mcp.oauth_requiredsession events, responding viasession.mcp.oauth.handlePendingRequest. - Register
mcp.oauth_requiredevent interest only when an MCP auth handler/callback is configured (create + resume; cloud create registers after server-assigned session id). - Add a minimal OAuth-protected MCP HTTP test server plus new/expanded E2E + unit tests across languages to validate initial auth, refresh/replacement, upscope, reauth, and cancellation.
Show a summary per file
| File | Description |
|---|---|
| test/harness/test-mcp-oauth-server.mjs | New minimal OAuth-protected MCP server fixture for cross-SDK E2E coverage. |
| rust/tests/session_test.rs | Adds Rust unit tests for optional MCP OAuth metadata and interest registration behavior. |
| rust/tests/e2e/support.rs | Enables MCP Apps flags in Rust E2E environment. |
| rust/tests/e2e/mcp_oauth.rs | New Rust E2E test validating MCP OAuth lifecycle with host-provided tokens. |
| rust/tests/e2e.rs | Registers the new Rust MCP OAuth E2E module. |
| rust/src/types.rs | Adds mcp_auth_handler to Rust session configs (create + resume). |
| rust/src/session.rs | Registers MCP OAuth event interest and dispatches MCP OAuth required events to the handler. |
| rust/src/handler.rs | Introduces Rust MCP auth request/result types + wire conversion. |
| python/test_client.py | Adds Python unit tests for MCP auth interest registration and handler dispatch. |
| python/e2e/testharness/context.py | Enables MCP Apps flags in Python E2E harness environment. |
| python/e2e/test_mcp_oauth_e2e.py | New Python E2E test validating MCP OAuth lifecycle with host-provided tokens. |
| python/copilot/session.py | Adds MCP auth typed callback surface + event dispatch/response plumbing in sessions. |
| python/copilot/client.py | Wires MCP auth callback through create/resume and conditionally registers event interest. |
| python/copilot/init.py | Exposes new MCP auth types in the Python public package surface. |
| nodejs/test/e2e/provider_endpoint.e2e.test.ts | Updates harness usage to pass env via client options instead of mutating shared env. |
| nodejs/test/e2e/mcp_oauth.e2e.test.ts | New Node E2E test validating MCP OAuth lifecycle with host-provided tokens. |
| nodejs/test/e2e/harness/sdkTestContext.ts | Adds env override merging and marks test user as MCP-enabled; normalizes CLI path lookup. |
| nodejs/test/client.test.ts | Adds Node unit tests for MCP auth dispatch and conditional interest registration. |
| nodejs/src/types.ts | Adds Node public types for MCP auth request/result/callback and session config option. |
| nodejs/src/session.ts | Handles mcp.oauth_required events and responds via session.mcp.oauth.handlePendingRequest. |
| nodejs/src/client.ts | Wires MCP auth handler into sessions and conditionally registers MCP OAuth event interest. |
| java/src/test/java/com/github/copilot/McpOAuthE2ETest.java | New Java E2E test validating MCP OAuth lifecycle with host-provided tokens. |
| java/src/test/java/com/github/copilot/McpAuthInterestRegistrationTest.java | New Java unit test verifying conditional interest registration + optional metadata exposure. |
| java/src/test/java/com/github/copilot/E2ETestContext.java | Enables MCP Apps flags in Java E2E environment. |
| java/src/main/java/com/github/copilot/SessionRequestBuilder.java | Registers the MCP auth handler on sessions for create + resume. |
| java/src/main/java/com/github/copilot/rpc/SessionConfig.java | Adds onMcpAuthRequest callback to Java session config and clones it. |
| java/src/main/java/com/github/copilot/rpc/ResumeSessionConfig.java | Adds onMcpAuthRequest callback to Java resume config and clones it. |
| java/src/main/java/com/github/copilot/rpc/McpAuthToken.java | New Java public DTO for MCP OAuth token data. |
| java/src/main/java/com/github/copilot/rpc/McpAuthResult.java | New Java public DTO/factories for token vs cancellation. |
| java/src/main/java/com/github/copilot/rpc/McpAuthRequest.java | New Java public DTO for MCP OAuth request payload. |
| java/src/main/java/com/github/copilot/rpc/McpAuthInvocation.java | New Java invocation context object (session id). |
| java/src/main/java/com/github/copilot/rpc/McpAuthHandler.java | New Java functional interface for MCP OAuth callback. |
| java/src/main/java/com/github/copilot/CopilotSession.java | Dispatches MCP OAuth required events to handler and replies via pending-request RPC. |
| java/src/main/java/com/github/copilot/CopilotClient.java | Conditionally registers mcp.oauth_required interest for create + resume. |
| go/types.go | Adds Go public MCP auth types and callback signature; threads into session configs. |
| go/session.go | Dispatches MCP OAuth required events to a Go handler and responds via pending-request RPC. |
| go/session_test.go | Adds Go unit tests for MCP auth request propagation and response payloads. |
| go/internal/e2e/testharness/context.go | Enables MCP Apps flags in Go E2E harness environment. |
| go/internal/e2e/mcp_oauth_e2e_test.go | New Go E2E test validating MCP OAuth lifecycle with host-provided tokens. |
| go/client.go | Wires handler into sessions and conditionally registers MCP OAuth event interest. |
| go/client_test.go | Adds Go unit tests verifying conditional interest registration for create/resume/cloud. |
| dotnet/test/Unit/SessionEventSerializationTests.cs | Extends .NET event serialization tests for optional MCP OAuth metadata fields. |
| dotnet/test/Unit/PublicDtoTests.cs | Adds .NET DTO factory tests for MCP auth token vs cancellation results. |
| dotnet/test/Unit/ClientSessionLifetimeTests.cs | Adds .NET unit tests verifying conditional interest registration behavior. |
| dotnet/test/Harness/E2ETestContext.cs | Enables MCP Apps flags in .NET E2E environment. |
| dotnet/test/E2E/McpOAuthE2ETests.cs | New .NET E2E test validating MCP OAuth lifecycle with host-provided tokens. |
| dotnet/src/Types.cs | Adds .NET public MCP auth types and session config callback. |
| dotnet/src/Session.cs | Handles mcp.oauth_required events and responds via pending-request RPC. |
| dotnet/src/Client.cs | Registers MCP OAuth interest when a handler is configured (create + resume). |
Review details
- Files reviewed: 49/49 changed files
- Comments generated: 4
- Review effort level: Low
Expose host-delegated MCP OAuth handling across SDK languages, sync generated RPC and event models to the lifecycle contract, and add cross-language E2E coverage for initial auth, refresh, upscope, reauth, and cancellation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
672611c to
1d608df
Compare
Wait for the TCP server to observe force-closed test clients before re-registering the same external tool name from a resumed client. This avoids flaky name-clash failures in the pending-work resume E2E tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
Avoid racing the TCP server's asynchronous forced-client cleanup by explicitly disconnecting the session before reconnecting with the same tool name. This preserves the cold-client resume scenario without relying on a fixed sleep. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Cross-SDK Consistency Review ✅Update after latest 2 commits ( All six SDKs (Node.js, Python, Go, .NET, Java, Rust) continue to be covered with consistent MCP OAuth host-token handler support. No new cross-SDK consistency issues introduced.
|
Summary
reason, optionalwwwAuthenticateParams.resourceMetadataUrl, optional rawresourceMetadata, and no hostrefreshTokenin token responses.mcp.oauth_requiredinterest only when the high-level MCP auth callback is configured.scope,resourceMetadataUrl,error=insufficient_scope, and refresherror=invalid_token).Notes
Use local runtime for MCP OAuth E2E validation) points E2E harnesses at/Users/roji/.copilot/repos/copilot-worktrees/copilot-agent-runtime/roji-symmetrical-dollop/dist-cli/index.jsfor runtime PR #11277 validation. This should be removed before final merge.initial -> refresh -> upscope -> refresh-cancel -> reauthacross all supported SDK languages.session.mcp.reloadWithConfigworkaround was removed; Node E2E passes without it against the current runtime branch.Validation
cd test/harness && npm cicd nodejs && npm run typecheck && npx vitest run test/e2e/mcp_oauth.e2e.test.tscd python && uv run pytest e2e/test_mcp_oauth_e2e.pycd go && go test ./internal/e2e -run TestMCPOAuthE2E -count=1cd dotnet && DOTNET_ROLL_FORWARD=Major dotnet test test/GitHub.Copilot.SDK.Test.csproj --filter FullyQualifiedName~McpOAuthE2ETestscd rust && export PATH="$HOME/.cargo/bin:$PATH" && cargo test --features test-support --test e2e mcp_oauth -- --nocapturecd java && mvn test -Dtest=McpOAuthE2ETestgofmt -w internal/e2e/mcp_oauth_e2e_test.go,cargo fmt -- tests/e2e/mcp_oauth.rs, andmvn spotless:apply -Dspotless.check.skip=false.