Skip to content

Add SDK MCP OAuth host token handlers#1669

Open
roji wants to merge 3 commits into
mainfrom
roji/roji-mcp-auth-sdk
Open

Add SDK MCP OAuth host token handlers#1669
roji wants to merge 3 commits into
mainfrom
roji/roji-mcp-auth-sdk

Conversation

@roji

@roji roji commented Jun 14, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Sync SDK generated RPC/session-event surfaces to the runtime MCP OAuth lifecycle contract: required reason, optional wwwAuthenticateParams.resourceMetadataUrl, optional raw resourceMetadata, and no host refreshToken in token responses.
  • Thread MCP OAuth auth request handling through Node, Python, Go, .NET, Java, and Rust public callback APIs.
  • Preserve event-interest behavior: SDKs register mcp.oauth_required interest only when the high-level MCP auth callback is configured.
  • Expand shared OAuth-protected MCP fixture and per-language E2E coverage for host-delegated initial auth, refresh/replacement, upscope, reauth, cancellation, and structured challenge propagation (scope, resourceMetadataUrl, error=insufficient_scope, and refresh error=invalid_token).

Notes

  • A separate temporary commit (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.js for runtime PR #11277 validation. This should be removed before final merge.
  • The deterministic lifecycle E2E path now covers initial -> refresh -> upscope -> refresh-cancel -> reauth across all supported SDK languages.
  • The prior Node session.mcp.reloadWithConfig workaround was removed; Node E2E passes without it against the current runtime branch.

Validation

  • cd test/harness && npm ci
  • cd nodejs && npm run typecheck && npx vitest run test/e2e/mcp_oauth.e2e.test.ts
  • cd python && uv run pytest e2e/test_mcp_oauth_e2e.py
  • cd go && go test ./internal/e2e -run TestMCPOAuthE2E -count=1
  • cd dotnet && DOTNET_ROLL_FORWARD=Major dotnet test test/GitHub.Copilot.SDK.Test.csproj --filter FullyQualifiedName~McpOAuthE2ETests
  • cd rust && export PATH="$HOME/.cargo/bin:$PATH" && cargo test --features test-support --test e2e mcp_oauth -- --nocapture
  • cd java && mvn test -Dtest=McpOAuthE2ETest
  • Formatting: gofmt -w internal/e2e/mcp_oauth_e2e_test.go, cargo fmt -- tests/e2e/mcp_oauth.rs, and mvn spotless:apply -Dspotless.check.skip=false.

@github-actions github-actions Bot added the dependencies Pull requests that update a dependency file label Jun 14, 2026
Comment thread python/copilot/client.py Fixed
Comment thread python/copilot/generated/rpc.py Fixed
@github-actions

This comment has been minimized.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generated by SDK Consistency Review Agent for issue #1669 · sonnet46 2.1M

Comment thread rust/src/types.rs Outdated
Comment thread dotnet/src/Session.cs Fixed
Comment thread nodejs/src/types.ts
Comment thread nodejs/src/types.ts
Comment on lines +1585 to +1594
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;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what about an idToken? idTokens are useful as they contain claims that are good to display like usernames/email/etc.

@roji roji Jun 26, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@roji roji force-pushed the roji/roji-mcp-auth-sdk branch from 59694fd to 6d3d655 Compare June 24, 2026 10:28
Comment thread java/src/main/java/com/github/copilot/CopilotClient.java Fixed
Comment thread java/src/main/java/com/github/copilot/CopilotClient.java Fixed
Comment thread java/src/main/java/com/github/copilot/CopilotClient.java Fixed
Comment thread java/src/main/java/com/github/copilot/rpc/McpAuthHandler.java Fixed
@github-actions

This comment has been minimized.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generated by SDK Consistency Review Agent for issue #1669 · sonnet46 1.8M

Comment thread rust/src/types.rs Outdated
Comment thread java/src/test/java/com/github/copilot/McpOAuthE2ETest.java Fixed
@github-actions

This comment has been minimized.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generated by SDK Consistency Review Agent for issue #1669 · sonnet46 3.1M

Comment thread dotnet/src/Types.cs
Comment thread dotnet/test/E2E/McpOAuthE2ETests.cs Fixed
Comment thread dotnet/test/E2E/McpOAuthE2ETests.cs Fixed
@roji roji force-pushed the roji/roji-mcp-auth-sdk branch from a4cfe07 to e3aae80 Compare June 26, 2026 15:18
@github-actions

This comment has been minimized.

@roji roji force-pushed the roji/roji-mcp-auth-sdk branch from 530ce4b to a16180e Compare June 26, 2026 15:47
@github-actions

This comment has been minimized.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generated by SDK Consistency Review Agent for issue #1669 · sonnet46 2.7M

Comment thread go/types.go
Comment thread go/types.go Outdated
Comment thread python/copilot/session.py
@roji roji force-pushed the roji/roji-mcp-auth-sdk branch from 1ef3726 to 87f1785 Compare June 29, 2026 12:52
Comment thread java/src/main/java/com/github/copilot/CopilotClient.java Fixed
Comment thread java/src/main/java/com/github/copilot/CopilotClient.java Fixed
@github-actions

This comment has been minimized.

@roji roji force-pushed the roji/roji-mcp-auth-sdk branch 4 times, most recently from 51c9235 to d5c709b Compare June 29, 2026 13:40
@roji roji force-pushed the roji/roji-mcp-auth-sdk branch from d5c709b to 70ec1fd Compare June 29, 2026 14:05
@github-actions

This comment has been minimized.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generated by SDK Consistency Review Agent for issue #1669 · sonnet46 2.3M

Comment thread java/src/main/java/com/github/copilot/rpc/McpAuthRequest.java Outdated
Comment thread java/src/main/java/com/github/copilot/rpc/McpAuthHandler.java Outdated
@roji roji force-pushed the roji/roji-mcp-auth-sdk branch from 70ec1fd to 672611c Compare June 29, 2026 15:06
@roji roji marked this pull request as ready for review June 29, 2026 15:12
@roji roji requested a review from a team as a code owner June 29, 2026 15:12
Copilot AI review requested due to automatic review settings June 29, 2026 15:12
@github-actions

This comment has been minimized.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_required session events, responding via session.mcp.oauth.handlePendingRequest.
  • Register mcp.oauth_required event 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

Comment thread test/harness/test-mcp-oauth-server.mjs Outdated
Comment thread test/harness/test-mcp-oauth-server.mjs Outdated
Comment thread test/harness/test-mcp-oauth-server.mjs Outdated
Comment thread dotnet/src/Session.cs
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>
@roji roji force-pushed the roji/roji-mcp-auth-sdk branch from 672611c to 1d608df Compare June 29, 2026 15:32
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>
@github-actions

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>
@github-actions

Copy link
Copy Markdown
Contributor

Cross-SDK Consistency Review ✅

Update after latest 2 commits (153a7d6, 0868553): Both new commits are test-only E2E race fixes ("pending work resume" test cleanup) with no changes to MCP OAuth API surfaces or cross-SDK handler designs. The previous comprehensive review remains fully applicable.

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.

Generated by SDK Consistency Review Agent for issue #1669 · sonnet46 2.5M ·

@roji roji enabled auto-merge June 29, 2026 16:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants