Skip to content

feat: OAuth MCP support via Agents SDK (Phase 1)#40

Closed
jonnyparris wants to merge 6 commits intomainfrom
feat/mcp-oauth-phase1-final
Closed

feat: OAuth MCP support via Agents SDK (Phase 1)#40
jonnyparris wants to merge 6 commits intomainfrom
feat/mcp-oauth-phase1-final

Conversation

@jonnyparris
Copy link
Copy Markdown
Owner

Summary

Adds OAuth 2.1 support for MCP servers via the Cloudflare Agents SDK, alongside the existing static-header HttpMcpGatekeeper. Users can now connect to public OAuth MCP servers (*.mcp.cloudflare.com, GitHub, etc.) without pasting tokens — the SDK handles PKCE, dynamic client registration, and refresh transparently.

Why

Today Dodo forces users to generate static bearer tokens and paste them into the UI to use any MCP server. The tokens then live as envelope-encrypted secrets in UserControl. This is friction, and breaks for OAuth-only servers.

The Agents SDK already ships an MCP OAuth manager (this.mcp.addMcpServer, this.mcp.configureOAuthCallback, this.mcp.callTool). CodingAgent transitively extends Agent via Think from @cloudflare/think, so these methods are already available — Dodo just wasn't using them.

Reference implementation: chat.cloudflare.dev (cloudflare/eti/flares/chat-flare). All 8 *.mcp.cloudflare.com servers (tested live) are OAuth providers with DCR + PKCE + refresh tokens — no Access-layer hacks needed.

What changed

New OAuth code path (parallel to static-headers)

  • McpCatalogEntry, McpGatekeeperConfig, mcp_configs D1 table — added auth_type: "oauth" | "static_headers" field with schema migration for existing rows.
  • CodingAgent.onStart — calls this.mcp.configureOAuthCallback({ successRedirect, errorRedirect }).
  • CodingAgent.connectMcpServers — skips auth_type === "oauth" entries (the SDK manages them), leaves static-headers flow untouched.
  • CodingAgent.refreshMcpState — new RPC method for re-authenticating an MCP.

Routes in src/index.ts (behind auth middleware)

  • POST /api/mcp/start-auth — begins OAuth flow, returns authUrl for the browser to visit.
  • POST /api/mcp/delete-auth — removes an OAuth connection.
  • POST /api/mcp/refresh-state — re-adds an MCP (useful after expired refresh tokens).
  • ALL /agents/* — OAuth callback receiver; forwards into the user's CodingAgent DO.

Tool merging in src/agentic.ts

buildToolsForThink now merges static-gatekeeper tools with SDK-managed MCP tools. New buildSdkMcpTools helper slugifies display names for tool prefixes and dedupes by final prefixed name (64-char cap per AI SDK).

Catalog

Expanded MCP_CATALOG from 4 entries to 11 — split cloudflare-api into 8 per-service entries (cloudflare-docs, cloudflare-bindings, etc.), all flagged auth_type: "oauth". browser-rendering and github also marked oauth. dodo-self stays static for now.

Config

  • WORKER_URL added to Env (src/types.ts) and wrangler.jsonc vars (http://localhost:8787 for dev).

Tests

  • test/dodo.test.ts — two new tests that /api/mcp/start-auth and /agents/* are not publicly accessible.
  • test/mcp-config.test.ts — catalog size assertion updated from === 4 to >= 4 (robust to future growth).
  • Existing test fixtures updated to include the new required auth_type field.

What's NOT in this PR

Deliberately out of scope — will follow in later PRs:

  • Phase 2: admin-managed catalog. Move MCP_CATALOG from static array to D1 approved_mcps table with admin CRUD.
  • Phase 3: revocation hygiene. JWT email drift check + daily alarm to clear stale OAuth tokens.
  • Phase 4: user-scoped Dodo MCP tokens. Replace shared DODO_MCP_TOKEN with per-user tokens.

Verification

  • npm run typecheck — clean
  • npm test — all 384 tests pass, 2 skipped, 0 failed (up from 378 before main added autocompact test coverage)
  • Existing browser-rendering MCP (currently static-headers) still works — OAuth is additive, not replacement.

Credit where due

This PR is the output of 5 Dodo self-dispatches over ~2 hours. The first attempt hit the autocompaction bugs filed in #34, which @jonnyparris fixed in parallel — thank you. Subsequent dispatches after the fix landed (as evidenced by commits 1e0926d through be0fb78 on main) completed without context issues.

Branch feat/mcp-oauth-phase1-final is a clean rebase of the work onto post-fix main. No conflicts.

Reference doc

Full architecture + implementation notes + the chat-flare reference: ~/agent-hq/scratch/chat-flare-mcp-auth-insights.md (internal).

@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented Apr 23, 2026

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
✅ Deployment successful!
View logs
dodo 76a060a Apr 23 2026, 09:00 PM

@jonnyparris
Copy link
Copy Markdown
Owner Author

Superseded by #43 — the full 4-phase consolidated PR.

@jonnyparris jonnyparris deleted the feat/mcp-oauth-phase1-final branch April 25, 2026 19:03
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