Skip to content

Upgrade go-sdk to v1.5.0 and add SDK OAuth integration#488

Open
cutecatfann wants to merge 4 commits into
mainfrom
upgrade-go-sdk-15
Open

Upgrade go-sdk to v1.5.0 and add SDK OAuth integration#488
cutecatfann wants to merge 4 commits into
mainfrom
upgrade-go-sdk-15

Conversation

@cutecatfann
Copy link
Copy Markdown
Contributor

What I did
Upgrades github.com/modelcontextprotocol/go-sdk from v1.4.1 to v1.5.0 and integrates the SDK's transport-level OAuth (auth.OAuthHandler) into the gateway's remote server connections.

go-sdk v1.5.0 brings:

  • Protocol version bumped to 2025-11-25
  • Client-side OAuth APIs stabilized (no longer behind mcp_go_client_oauth build tag)
  • Data race fixes (mutex on protocol version, atomic reconnect delay)
  • Tool input validation errors returned as tool results instead of JSON-RPC errors
  • Parameterized Accept media type support
  • HTTP response flushing improvements

OAuth integration addresses a gap in how the gateway handles remote MCP server auth. Previously, tokens were pre-fetched and injected via a static headerRoundTripper. If a token expired mid-session, requests would fail with no retry. The SDK's StreamableClientTransport.OAuthHandler provides built-in 401/403 retry, but it was never wired up.

Gateway Source Changes (3 files)

pkg/oauth/sdk_handler.go (new)

  • SDKHandler implements auth.OAuthHandler from the go-sdk
  • TokenSource() reads tokens from the gateway's existing credential store (CE/Desktop/Community modes). Returns nil when no token exists, telling the transport to skip the Authorization header
  • Authorize() is called by the SDK on 401/403. Since the gateway runs as a daemon and cannot open a browser, it returns an error instructing the user to run docker mcp oauth authorize
  • gatewayTokenSource re-reads from the credential store on every Token() call, so tokens refreshed by the background Provider loop are picked up automatically
  • Expiry is intentionally unset on returned tokens since the SDK calls TokenSource() per-request (no caching)

pkg/oauth/sdk_handler_test.go (new)

  • Compile-time interface conformance check (var _ auth.OAuthHandler = (*SDKHandler)(nil))
  • No-token path: TokenSource returns nil
  • Happy path: stores a DCR client and token in a fake credential helper, verifies TokenSource returns a working TokenSource with the correct access token
  • Authorize returns actionable error message with server name and command to run
  • Handles nil response and nil body without panicking

pkg/mcp/remote.go (modified)

  • Streamable transport: sets OAuthHandler on StreamableClientTransport, giving automatic Bearer token injection and 401/403 retry. Strips Authorization from headerRoundTripper to avoid conflicts with the SDK's token injection
  • SSE transport: unchanged, keeps existing manual token injection via headerRoundTripper (SSE transport does not support OAuthHandler in v1.5.0)
  • Non-OAuth custom headers continue to flow through headerRoundTripper for both transport types

@cutecatfann cutecatfann self-assigned this May 5, 2026
@cutecatfann cutecatfann marked this pull request as ready for review May 5, 2026 22:13
@cutecatfann cutecatfann requested a review from a team as a code owner May 5, 2026 22:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant