A spec-compliant OAuth 2.0 gateway that puts authentication, access control, and usage monitoring in front of any Streamable HTTP MCP server.
Open DashboardMCP 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.
Register your MCP server, share it with specific emails or entire domains, and monitor who's using which tools.
One-click install via Cursor deeplink. Authenticate once with Google, access all servers shared with you.
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).
/mcp/{serverId} without a token. Gateway responds 401 with WWW-Authenticate: Bearer resource_metadata="..."./.well-known/oauth-protected-resource to discover the authorization server./.well-known/oauth-authorization-server (or /.well-known/openid-configuration) for endpoint details, supported scopes, and PKCE requirements./authorize with PKCE S256. The gateway redirects to Google OIDC for identity verification.POST /token for a JWT access token (RS256, audience-bound) and a rotating refresh token.Authorization: Bearer {token}. Gateway validates the JWT, checks ACL, proxies to the upstream server, and logs usage.resource parameter during OAuth authorization (as of 2026). The spec says clients should include it (spec § 2.4), but Cursor relies on audience discovery from the PRM. We accept both server-specific and base MCP audiences on token verification.cursor:// redirect URIs for its OAuth callback. Your DCR endpoint must accept custom URL schemes, not just https://.POST /token request arrives with isBase64Encoded: true for application/x-www-form-urlencoded content. You must decode before parsing grant_type.OPTIONS in AllowMethods — preflight is handled automatically by the Function URL layer. Including it causes a CloudFormation validation error (AWS::EarlyValidation::PropertyValidation).WWW-Authenticate header gets remapped. Behind CloudFront + Lambda Function URL, it becomes x-amzn-remapped-www-authenticate. Cursor handles this correctly.POST /register endpoint must work before /authorize will succeed./.well-known/oauth-protected-resource/.well-known/oauth-authorization-server/.well-known/openid-configuration (added in MCP 2025-11-25)POST /register/jwks.jsonresource parameter (RFC 8707). Cursor doesn't send it; we bind audience at code issuance.Last-Event-ID) is deferred./mcp/{serverId} — MCP JSON-RPC proxy (Bearer token required)/.well-known/oauth-protected-resource — Protected Resource Metadata/.well-known/oauth-authorization-server — OAuth AS Metadata/.well-known/openid-configuration — OIDC Discovery/authorize — OAuth authorization (redirects to Google)/token — Token exchange (code → JWT + refresh)/jwks.json — RS256 public key set/register — Dynamic Client RegistrationSingle 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)
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.
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).
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.
{
"mcpServers": {
"my-server": {
"url": "https://mcp-auth.cloud/mcp/srv_abc123..."
}
}
}