Skip to content

LIFEAI/cf-oauth-mcp-proxy

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

21 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

cf-oauth-mcp-proxy

GitHub Sponsors License: MIT Cloudflare Workers MCP

Cloudflare Worker — OAuth 2.1 + DCR + PKCE edge proxy for any PAT-authenticated MCP server.
Connects claude.ai (and any OAuth MCP client) to MCP servers that only support PAT/token auth — like the official GitHub MCP server.


💛 Support This Work

This tool is free, open source, and took real time to build.

If it saves you hours of debugging OAuth flows, Dockerfiles, and Cloudflare configs — please consider sponsoring. Every contribution directly funds continued open source tooling for the regenerative AI ecosystem.

"Life before Profits."
— Dave Ladouceur / LIFEAI / Regen Dev Corp


The Problem

claude.ai speaks OAuth 2.1. GitHub's MCP server speaks PAT. There is no official bridge.

api.githubcopilot.com/mcp requires a registered GitHub OAuth App per host — something only GitHub controls. Third-party clients including claude.ai are not registered, and the workaround in their own docs is "use Docker locally" — which defeats the purpose of a cloud AI assistant.

The Solution

A single Cloudflare Worker (~200 lines) that:

  1. Speaks OAuth 2.1 to claude.ai — full DCR, PKCE, auth codes, access tokens
  2. Speaks PAT to the upstream MCP server
  3. Stores nothing sensitive in code — all secrets are CF Worker bindings
  4. Gates authorization with a PIN — only you can approve new connections
  5. Runs at the CF edge — zero infrastructure, zero maintenance, ~$0/month
claude.ai  ──OAuth 2.1──▶  [this Worker]  ──PAT──▶  api.githubcopilot.com/mcp
                            (Cloudflare edge)

OAuth Flow

1. claude.ai  →  GET /.well-known/oauth-authorization-server  →  discovers OAuth metadata
2. claude.ai  →  POST /register                               →  gets client_id (DCR, RFC 7591)
3. claude.ai  →  GET /authorize?code_challenge=...            →  Worker serves PIN consent page
4. You        →  enter PIN in browser                         →  Worker issues auth code
5. claude.ai  →  POST /token {code, code_verifier}            →  Worker issues access token (PKCE)
6. claude.ai  →  POST /mcp  Authorization: Bearer <token>     →  Worker validates, injects PAT, proxies

Deploy with Claude (No CLI Required)

Any Claude instance with the Cloudflare Developer Platform MCP connected can deploy this Worker entirely from chat — no Wrangler, no terminal, no local machine.

See deploy-with-claude.md for the complete step-by-step CF API runbook.



Prerequisites

  • Cloudflare account (free tier works)
  • Wrangler CLI
  • GitHub PAT with repo scope (or any upstream Bearer token)
  • A domain on Cloudflare DNS — or use the free *.workers.dev subdomain

Setup

1. Clone

git clone https://github.com/LIFEAI/cf-oauth-mcp-proxy.git
cd cf-oauth-mcp-proxy

2. Create KV namespace

wrangler kv namespace create github-mcp-oauth
# Copy the id from output

3. Configure wrangler.toml

[vars]
BASE_URL     = "https://YOUR_WORKER_DOMAIN"   # your Worker's public URL
UPSTREAM_MCP = "https://api.githubcopilot.com/mcp"  # target MCP endpoint

[[kv_namespaces]]
binding = "OAUTH_KV"
id      = "PASTE_YOUR_KV_ID_HERE"

4. Set secrets

wrangler secret put UPSTREAM_TOKEN   # your GitHub PAT (ghp_...)
wrangler secret put AUTH_PIN         # PIN you'll type in browser to authorize

AUTH_PIN — alphanumeric, 6–12 chars, store in your password manager. Anyone with this PIN can authorize a new client connection.

Generating an AUTH_PIN

Your AUTH_PIN is a short alphanumeric string you type in the browser consent page to authorize a new client connection. Generate one before running wrangler secret put AUTH_PIN.

Linux / macOS:

openssl rand -base64 12 | tr -dc 'A-Z0-9' | head -c 8

Windows PowerShell:

-join ((65..90 + 48..57) | Get-Random -Count 8 | % {[char]$_})

Windows cmd.exe (no PowerShell):

powershell -command "-join ((65..90 + 48..57) | Get-Random -Count 8 | % {[char]$_})"

Rules: 6–12 characters, alphanumeric only (A-Z, 0-9). Store it in your password manager — you'll need it every time a new client connects. Anyone with this PIN can authorize a connection to your proxy.

Once you have it:

wrangler secret put AUTH_PIN
# paste your generated PIN when prompted

To rotate: run wrangler secret put AUTH_PIN again with a new value. All existing tokens remain valid — only new OAuth flows are affected.


5. Deploy

wrangler deploy

6. (Optional) Add custom domain via Cloudflare DNS

In Cloudflare dashboard: DNS → add proxied A record → Workers → Routes → add YOUR_WORKER_DOMAIN/*cf-oauth-mcp-proxy

7. Connect your clients

Important: Each MCP client (claude.ai, Claude Code, etc.) runs its own independent OAuth flow and gets its own KV access token. They never interfere with each other. You will enter your PIN once per client. Connect claude.ai first — it is the fastest sanity check that your Worker, KV, PIN, and redirect are all working correctly.

Step 7a — claude.ai (do this first)

  1. Settings → Connectors → Add custom connector
  2. URL: https://YOUR_WORKER_DOMAIN/mcp
  3. Click Connect — browser opens the PIN consent page
  4. Enter your AUTH_PIN → click Authorize Access
  5. Redirected back to claude.ai ✅

Verify it works by asking Claude to list your private repos before moving on.

Step 7b — Claude Code CLI (after claude.ai is confirmed working)

# Add the connector (Claude Code handles OAuth automatically)
claude mcp add-json github '{"type":"http","url":"https://YOUR_WORKER_DOMAIN/mcp"}'

Restart Claude Code. On first use run /mcp — browser opens for PIN auth. Claude Code stores its own token in your system keychain independently of claude.ai.

# Verify
claude mcp list
claude mcp get github

Windows note: If add-json returns Invalid input, use: claude mcp add --transport http github https://YOUR_WORKER_DOMAIN/mcp

How tokens work across clients

Each client that completes the OAuth flow gets its own entry in KV:

KV store:
  token:<uuid-A>  →  { client_id: "claude-ai-dcr-id",   created_at: ... }   ← claude.ai token
  token:<uuid-B>  →  { client_id: "claude-code-dcr-id", created_at: ... }   ← Claude Code token

Both tokens are valid simultaneously. Each expires after 30 days independently. To revoke a specific client: disconnect it in claude.ai settings or run claude mcp remove github.



Connecting MCP Clients

Claude Code users: You don't need this proxy. Claude Code uses the gh CLI which is already pre-authenticated with full private repo access. This proxy is built for claude.ai web and other OAuth MCP clients that can't inject a PAT directly.


claude.ai (Web) — Primary Use Case

  1. Go to Settings → Connectors → Add custom connector
  2. Enter your Worker URL:
    https://YOUR_WORKER_DOMAIN/mcp
    
  3. Click Connect — your browser opens the PIN consent page
  4. Enter your AUTH_PIN and click Authorize Access
  5. Redirected back to claude.ai ✅ Full private repo access.

To enable per-conversation: click +Connectors → toggle on.

To revoke: Settings → Connectors → remove the connector. Token expires automatically after 30 days.


Other OAuth MCP Clients — Windows Installer

For any other MCP client that supports OAuth 2.1 (not Claude Code), use the included install-mcp.cmd:

install-mcp.cmd https://YOUR_WORKER_DOMAIN

Or run without arguments to be prompted:

install-mcp.cmd

The script will:

  1. Check claude CLI is installed
  2. Remove any existing github MCP entry
  3. Try claude mcp add-json (Claude Code 2.1.1+)
  4. Fall back to claude mcp add --transport http if needed
  5. Verify with claude mcp list
  6. Print next steps including the OAuth PIN URL

.mcp.json (project-level, for non-Claude Code teams)

If your team uses an OAuth-capable MCP host other than Claude Code:

{
  "mcpServers": {
    "github": {
      "type": "http",
      "url": "https://YOUR_WORKER_DOMAIN/mcp"
    }
  }
}

Each member authorizes individually with the PIN — tokens are personal and stored locally.

Configuration Reference

wrangler.toml vars

Variable Required Description
BASE_URL Public URL of this Worker (used in OAuth metadata)
UPSTREAM_MCP URL of the upstream MCP server

Secrets

Secret Description
UPSTREAM_TOKEN PAT or Bearer token for the upstream MCP server
AUTH_PIN PIN to gate the consent page

KV binding

Binding Purpose
OAUTH_KV Clients, auth codes (5 min TTL), access tokens (30 day TTL)

Endpoints

Method Path Description
GET /.well-known/oauth-authorization-server RFC 8414 discovery
POST /register RFC 7591 Dynamic Client Registration
GET /authorize PIN consent page
POST /authorize PIN submit → issues auth code
POST /token Auth code + PKCE verifier → access token
POST /revoke Token revocation
* /* Authenticated MCP proxy to upstream

Security Model

Layer Mechanism
Upstream token CF Worker secret binding — encrypted at rest, never in source
Client authorization PIN-gated consent page — only PIN holder can authorize
Code interception PKCE S256 — stolen auth codes are useless without code_verifier
Token storage KV with 30-day TTL — revocable at any time
Unauthenticated requests 401 with WWW-Authenticate header

Optional hardening: Add a Cloudflare WAF rule to restrict /mcp to Anthropic's IP ranges only.


Adapting for Other MCP Servers

Change UPSTREAM_MCP in wrangler.toml. The Worker is fully generic.

# Any PAT-authenticated MCP server
UPSTREAM_MCP = "https://mcp.linear.app/sse"
UPSTREAM_MCP = "https://my-internal-mcp.company.com/mcp"

Why Not Docker / Coolify?

We tried. The official ghcr.io/github/github-mcp-server image requires the right CMD args. The npm package is deprecated. Supergateway crashes on reconnect. Cloudflare Worker is 200 lines with zero runtime dependencies, deploys in 3 seconds, and costs nothing.

Stay on CF Workers for this pattern.


💛 If This Helped You

This pattern emerged from hours of trial and error building the LIFEAI regenerative AI ecosystem. If it saved you time — please sponsor:

Even $5/month helps sustain open tooling for the people building at the intersection of AI, regenerative systems, and financial engineering. Thank you.


Built by Dave Ladouceur / LIFEAI / Regen Dev Corp
Life before Profits.


License

MIT — use freely, fork liberally, adapt for any MCP server.

About

Cloudflare Worker — OAuth 2.1 + DCR + PKCE edge proxy for any MCP server. Connect claude.ai to private GitHub repos (or any PAT-authenticated MCP) via standard OAuth flow.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors