Skip to content

feat(mcp): add OAuth authentication - #1091

Closed
sam-saffron-jarvis wants to merge 1 commit into
SamSaffron:mainfrom
sam-saffron-jarvis:feat/mcp-oauth
Closed

feat(mcp): add OAuth authentication#1091
sam-saffron-jarvis wants to merge 1 commit into
SamSaffron:mainfrom
sam-saffron-jarvis:feat/mcp-oauth

Conversation

@sam-saffron-jarvis

Copy link
Copy Markdown
Contributor

Summary

  • upgrade github.com/modelcontextprotocol/go-sdk from v1.5.0 to the latest stable v1.7.0
  • add persistent OAuth authorization for remote Streamable HTTP MCP servers using the SDK's InitialTokenSource and NewTokenSource hooks
  • add first-class login, status, refresh, reauthentication, cancellation, revocation, and logout workflows across CLI, chat TUI, and Web UI
  • keep stdio, unauthenticated HTTP, and explicit static Authorization headers backward-compatible

OAuth and credential handling

  • MCP protected-resource and authorization-server discovery
  • PKCE, dynamic client registration, issuer binding, resource indicators, scope accumulation, and refresh-token guidance through go-sdk v1.7.0
  • versioned private credential file with 0700 directory / 0600 file permissions, symlink rejection, atomic writes, and cross-process locking
  • rotating refresh-token adoption and stale-write protection across processes
  • RFC 7009 revocation where advertised
  • no tokens, authorization codes, verifiers, or client secrets in web JSON, browser storage, transcripts, or logs

UX

CLI

term-llm mcp login <server>
term-llm mcp status [server]
term-llm mcp logout <server>

Includes --force, --no-browser, and --local-only variants.

TUI

  • signed-out, waiting, signed-in, transient-error, and reauthentication states
  • /mcp login and /mcp logout
  • successful authorization reconnects only the affected server

Web

  • Sign in / Sign in again / Retry / Cancel / Copy link / Sign out actions
  • popup plus polling/postMessage completion
  • state-gated callback that never reflects query data
  • serve --public-url / TERM_LLM_SERVE_PUBLIC_URL for externally visible OAuth callbacks

Review findings incorporated

A claude-bin:fable implementation review found and fixed four issues before publication:

  1. custom MCP headers could leak to authorization-server requests
  2. a stored DCR client could be reused with an incompatible redirect URI
  3. a hung refresh endpoint could hold the cross-process store lock indefinitely
  4. the Web UI could poll a flow forever after it disappeared server-side

Each fix has regression coverage.

Validation

  • go test ./internal/mcp/... ./internal/tui/chat ./internal/serveui
  • isolated go test ./cmd
  • go test -race ./internal/mcp/oauth ./internal/mcp
  • go vet ./...
  • go build ./...
  • frontend format, ESLint, Stylelint, and TypeScript checks
  • frontend tests: 425 passed across 33 files
  • live Linear OAuth smoke: browser consent, persisted restart reuse, read write scopes, and 57 tools discovered
  • live CLI and web grants were revoked after the smoke test

@SamSaffron

Copy link
Copy Markdown
Owner

merged by hand

@SamSaffron SamSaffron closed this Aug 31, 2026
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.

2 participants