MCP Auth

A spec-compliant OAuth 2.0 gateway that puts authentication, access control, and usage monitoring in front of any Streamable HTTP MCP server.

Open Dashboard

What this is

MCP Auth is an OAuth authorization server + reverse proxy for Model Context Protocol servers. You register an upstream MCP server URL, set email or domain-based access rules, and get a stable authenticated endpoint that any MCP client (Cursor, Claude Desktop, etc.) can connect to using the standard MCP auth flow — no custom headers, no API keys, no workarounds.

For server owners

Register your MCP server, share it with specific emails or entire domains, and monitor who's using which tools.

For MCP users

One-click install via Cursor deeplink. Authenticate once with Google, access all servers shared with you.

How the auth flow works

The flow follows the MCP authorization specification (spec § Authorization), which is built on OAuth 2.1 with PKCE, Resource Indicators (RFC 8707), and Protected Resource Metadata (RFC 9728).

1
Client sends a request to /mcp/{serverId} without a token. Gateway responds 401 with WWW-Authenticate: Bearer resource_metadata="...".
2
Client fetches /.well-known/oauth-protected-resource to discover the authorization server.
3
Client fetches /.well-known/oauth-authorization-server (or /.well-known/openid-configuration) for endpoint details, supported scopes, and PKCE requirements.
4
Client starts an authorization code flow to /authorize with PKCE S256. The gateway redirects to Google OIDC for identity verification.
5
After Google login, the gateway checks the ACL for the target server against the user's identity. If allowed, it issues an authorization code and redirects back to the client.
6
Client exchanges the code at POST /token for a JWT access token (RS256, audience-bound) and a rotating refresh token.
7
Client retries the original MCP request with Authorization: Bearer {token}. Gateway validates the JWT, checks ACL, proxies to the upstream server, and logs usage.

Spec compliance & quirks

Things we learned the hard way

What we implement from the MCP auth spec

What we deliberately skip (for now)

API endpoints

POST /mcp/{serverId} — MCP JSON-RPC proxy (Bearer token required)
GET /.well-known/oauth-protected-resource — Protected Resource Metadata
GET /.well-known/oauth-authorization-server — OAuth AS Metadata
GET /.well-known/openid-configuration — OIDC Discovery
GET /authorize — OAuth authorization (redirects to Google)
POST /token — Token exchange (code → JWT + refresh)
GET /jwks.json — RS256 public key set
POST /register — Dynamic Client Registration

Architecture

Single AWS Lambda (Node.js 22, arm64) behind CloudFront. DynamoDB single-table design for all state. No cold-start dependencies on external services — the RSA signing key is generated on first invocation and cached in Lambda memory.

Cursor ──HTTPS──▸ CloudFront ──▸ Lambda Function URL
                                    │
                      ┌─────────────┼──────────────┐
                      │             │              │
                 MCP Proxy    OAuth Server    Dashboard
                 /mcp/*       /authorize      /dashboard
                      │       /token
                      │       /register
                      ▼
              Upstream MCP Server
              (your Lambda Function URL)

JWT access tokens

Tokens are RS256-signed JWTs. The signing key is auto-generated and stored in DynamoDB. The public key is served at /jwks.json.

{
  "iss": "https://mcp-auth.cloud",
  "sub": "google-oauth2-subject-id",
  "aud": "https://mcp-auth.cloud/mcp/",
  "scope": "mcp:connect mcp:invoke",
  "email": "user@example.com",
  "exp": 1775231000,
  "iat": 1775227400,
  "jti": "unique-token-id"
}

User identity is keyed by Google sub (stable), not email (can change). Domain ACLs validate the hd claim per Google's token verification guidance.

Access control

Server owners configure access per server with two ACL types:

The server owner always has implicit access. ACLs are checked both at authorization time (before issuing a code) and at proxy time (on every request).

MCP protocol version

Current spec version: 2025-11-25. The gateway propagates the MCP-Protocol-Version header to upstream and manages Mcp-Session-Id mapping between client and upstream sessions. See the spec changelog for what changed in each version.

Quick start

  1. Sign in with your Google account.
  2. Register your upstream MCP server URL.
  3. Add email or domain ACLs for your users.
  4. Share the config snippet or Cursor install deeplink.
{
  "mcpServers": {
    "my-server": {
      "url": "https://mcp-auth.cloud/mcp/srv_abc123..."
    }
  }
}