Install
$ agentstack add mcp-redhat-community-ai-tools-mcp-auth-adapter ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
MCP Auth Adapter
[](https://github.com/redhat-community-ai-tools/mcp-auth-adapter/actions/workflows/ci.yml) [](https://github.com/redhat-community-ai-tools/mcp-auth-adapter/actions/workflows/ci.yml) [](https://securityscorecards.dev/viewer/?uri=github.com/redhat-community-ai-tools/mcp-auth-adapter)
An OAuth/OIDC authentication adapter for Model Context Protocol (MCP) clients. It sits in front of any OAuth 2.0 / OIDC upstream IdP - such as Keycloak, Auth0, Okta, Azure AD, Google Identity, or any provider serving standard OAuth 2.0 / OIDC discovery metadata - and provides functionality required by the MCP Authorization specification for the most common MCP clients (Claude Code/Desktop, Cursor IDE, ChatGPT, Gemini CLI, VS Code, ...) and [their known problematic behaviours](#known-mcp-client-behaviors).
MCP servers announce this adapter as their authorization server. MCP clients discover it via .well-known and interact with its endpoints. Authentication itself and token issuing are performed by the upstream IdP - this adapter is only a very thin, transparent, stateless facade.
MCP Spec Compatibility
- MCP Authorization Specification 2025-11-25 — v1.0 fully compatible
- MCP Authorization Specification 2026-07-28 RC — v2.0 fully compatible (adds mandatory RFC 9207
issparameter validation) - MCP OAuth Client Credentials extension — supported in v2.1 (passthrough to upstream IdP)
- MCP Enterprise-Managed Authorization extension — supported in v2.1 (passthrough to upstream IdP)
Features
- Well-known discovery - filtered, MCP-focused view of the upstream IdP metadata with injected adapter endpoints and tailored configurations. See [Upstream Well-Known Handling](#upstream-well-known-handling).
- Open Dynamic Client Registration (DCR) (optional) - returns a pre-configured
client_idfor registering MCP clients per RFC 7591. Supports per-MCP-client IdP client mapping based onclient_namewith optional per-client redirect URI enforcement. See [Open DCR and its Security Limitations](#open-dcr-and-its-security-limitations) and [Per-MCP-Client IdP Client Mapping](#per-mcp-client-idp-client-mapping). - Scope filtering (optional) - intercepts
/authorizeand/parrequests to modify scopes before forwarding to the upstream IdP. - RFC 9207
issparameter validation - mandatory authorization response issuer verification preventing OAuth mix-up attacks per the MCP Auth Spec. See [RFC 9207 iss parameter validation](#rfc-9207-iss-parameter-validation). - Resource parameter validation (optional) - validates the RFC 8707
resourceparameter required by the MCP specification, with configurable enforcement, format checking, and allowlist filtering. See [Resource Parameter Validation (RFC 8707)](#resource-parameter-validation-rfc-8707). - Client Credentials passthrough - transparently proxies
client_credentialsand JWT bearer grants to the upstream IdP per the MCP OAuth Client Credentials extension. See [Client Credentials Passthrough](#client-credentials-passthrough). - PAR proxy (optional) - proxies RFC 9126 Pushed Authorization Requests when the authorize proxy is active and the Upstream IdP advertises PAR. See [PAR (RFC 9126)](#par-rfc-9126).
- DPoP header forwarding - always forwards
DPoP/DPoP-Nonceon/tokenand/par; discovery advertisement is opt-in. See [DPoP (RFC 9449)](#dpop-rfc-9449). - CIMD adapter (EXPERIMENTAL, optional) - accepts Client ID Metadata Document style
client_idURLs, validates metadata documents, and maps them to upstream IdP clientids. See [CIMD Adapter](#cimd-adapter-experimental).
See [Flow Diagrams](#flow-diagrams) to understand functionality better.
Container Image
Pre-built container images are published to GitHub Container Registry on every release. This is the recommended way to deploy in production - no Node.js installation required.
Image: ghcr.io/redhat-community-ai-tools/mcp-auth-adapter with tags X.Y.Z, X.Y, X, and latest.
Older tags were published under ghcr.io/velias/mcp-auth-adapter. GHCR does not redirect to the new org namespace, so update to ghcr.io/redhat-community-ai-tools/mcp-auth-adapter in pull/run commands.
Prerequisites: Docker or Podman
Pull and run
Podman is used in examples, but you can use docker command instead:
podman run -d --name mcp-auth-adapter \
-p 3000:3000 \
-e MCP_BASE_URL=https://mcp-auth.example.com \
-e MCP_UPSTREAM_SSO_URL=https://sso.example.com/auth/realms/external \
-e MCP_PROXY_DCR_CLIENT_ID=mcp-client \
ghcr.io/redhat-community-ai-tools/mcp-auth-adapter:latest
Or use an env file for all configuration (see [Configuration](#configuration) below):
podman run -d -p 3000:3000 --env-file .env ghcr.io/redhat-community-ai-tools/mcp-auth-adapter:latest
Available tags
Each release vX.Y.Z produces the following image tags:
X.Y.Z- exact version (recommended for production)X.Y- latest patch within a minor versionX- latest minor within a major versionlatest- most recent release
To build the image locally from source, see [CONTRIBUTING.md](CONTRIBUTING.md#running-with-docker--podman).
npm Package
The adapter is published on npm and can be run directly with npx — no cloning or building required.
Prerequisites: Node.js >= 20.x, npx or npm
npx mcp-auth-adapter
Or install globally with npm install -g mcp-auth-adapter and run as mcp-auth-adapter.
Or install it into your Node.js project with npm install mcp-auth-adapter to use it.
Build from Source
Prerequisites: Node.js >= 20.x (uses native fetch), npm
npm install
npm run build
# Create .env from the template and edit it
cp .env.example .env
npm start
Configuration
Environment variables are used. All variables are prefixed with MCP_. A .env file in the project root is loaded automatically, explicit environment variables take precedence.
| Variable | Required | Default | Description | |---|---|---|---| | | | | Core | | MCP_BASE_URL | Yes | -- | Public base URL of this adapter. Used as issuer (RFC 8414 §3.3) and to construct endpoint URLs. Must be http or https; trailing slashes are stripped automatically. Must exactly match what MCP servers advertise in their Protected Resource Metadata authorization_servers array. | | MCP_UPSTREAM_SSO_URL | Yes | -- | Base URL (issuer) of the upstream IdP. Must be http or https; trailing slashes are stripped automatically. Works with any OAuth 2.0 / OIDC provider. Discovery is attempted via /.well-known/openid-configuration, then /.well-known/oauth-authorization-server (RFC 8414); on failure, fallback endpoints are derived using Keycloak URL conventions ([see below](#upstream-well-known-handling)). | | MCP_PORT | No | 3000 | Port this app listens on. | | MCP_SHUTDOWN_TIMEOUT_SECONDS | No | 30 | Maximum seconds to wait for in-flight requests to drain after SIGTERM/SIGINT before force-exiting. | | | | | Authorize proxy (RFC 9207 iss interception, scopes, resource; auto-enables /authorize + /token; /par when upstream advertises PAR — see [PAR](#par-rfc-9126)) | | MCP_PROXY_AUTH_STATE_SECRET | Conditional | -- | Hex-encoded HMAC secret for signing state blobs (min 32 bytes = 64 hex chars). Required when the /authorize proxy is active (scope filtering, CIMD, or standalone). Generate with openssl rand -hex 32. Must be identical across all pods. | | MCP_PROXY_AUTH_STATE_SECRET_PREVIOUS | No | -- | Previous HMAC secret for zero-downtime key rotation (same format). Set to the old key during rotation; remove after TTL has elapsed. | | MCP_PROXY_AUTH_STATE_TTL_MINUTES | No | 30 | How long (minutes) the signed state blob remains valid. Must cover full user interaction at the upstream IdP (login + registration + MFA + consent). | | MCP_PROXY_AUTH_ALLOWED_REDIRECT_URIS | Conditional | -- | Comma-separated allowed redirect URI patterns. Trailing * = host-aware wildcard (exact hostname; http://host* / http://host:* = any port and path; https://host/path* = path prefix); no * = exact match. Domain-extension attacks (host.evil.com) are rejected. Required when /authorize proxy is active (unless CIMD-only, or all MCP_PROXY_DCR_CLIENT_NAME_MAP entries have per-client allowed_redirect_uris with no fallback MCP_PROXY_DCR_CLIENT_ID). See [known MCP client patterns](#known-mcp-client-redirect-uri-patterns) for common values. | | MCP_PROXY_AUTH_SCOPES_REMOVED | No | -- | Comma-separated scopes to strip from /authorize and /par requests (e.g. offline_access). Ignored if MCP_PROXY_AUTH_SCOPES_PRESERVED is also set. Setting this (or scopes preserved / CIMD) auto-enables the authorize proxy. | | MCP_PROXY_AUTH_SCOPES_PRESERVED | No | -- | Comma-separated scopes to keep in /authorize and /par requests; all others are stripped. Takes precedence over MCP_PROXY_AUTH_SCOPES_REMOVED. | | MCP_PROXY_AUTH_REQUIRE_RESOURCE | No | false | Reject /authorize, /par, and /token requests missing the RFC 8707 resource parameter. Enable for strict MCP spec compliance; leave disabled if MCP clients don't yet include it. | | MCP_PROXY_AUTH_ALLOWED_RESOURCES | No | -- | Comma-separated allowed resource URI patterns. Trailing * = prefix match, *.domain.com = domain wildcard (matches domain and all subdomains), no * = exact match. When set, resource must match a pattern; unmatched values are rejected with 400. | | | | | Dynamic Client Registration | | MCP_PROXY_DCR_CLIENT_ID | No | -- | Default client_id returned by POST /register. Setting this enables the DCR proxy. Must be pre-registered at the upstream IdP as a public client. When MCP_PROXY_DCR_CLIENT_NAME_MAP is also set, this serves as the fallback for unmatched client names. | | MCP_PROXY_DCR_CLIENT_NAME_MAP | No | -- | JSON object mapping client_name patterns to upstream IdP clientids, with optional per-client redirect URI restrictions. Setting this enables the DCR proxy (even without MCP_PROXY_DCR_CLIENT_ID). See [Per-MCP-Client IdP Client Mapping](#per-mcp-client-idp-client-mapping). | | | | | CIMD adapter (EXPERIMENTAL, auto-enables authorize proxy) | | MCP_PROXY_CIMD_MAP | No | -- | JSON object mapping CIMD URLs to upstream IdP clientids. Format: {"":"", ...}. N:1 mapping supported. CIMD auto-enables when this is non-empty or MCP_PROXY_CIMD_DEFAULT_CLIENT_ID is set. | | MCP_PROXY_CIMD_DEFAULT_CLIENT_ID | No | -- | Fallback upstream client_id for CIMD URLs not in the map. If unset, unknown CIMD URLs are rejected with 403 (strict allowlist). | | MCP_PROXY_CIMD_CACHE_MINUTES | No | 30 | Cache TTL (in minutes) for validated CIMD metadata documents. | | | | | Well-known discovery | | MCP_WELL_KNOWN_SCOPES_SUPPORTED | No | -- | Comma-separated scopes to announce in scopes_supported. If empty, the field is omitted. Note: some MCP clients request all announced scopes -- this controls announced scopes, not forwarded scopes. | | MCP_WELL_KNOWN_REFRESH_MINUTES | No | 60 | How often (in minutes) to re-fetch the upstream well-known document. | | | | | Protocol opt-ins | | MCP_PROXY_DPOP_ENABLED | No | false | When true, advertise upstream dpop_signing_alg_values_supported in discovery only if the Upstream IdP announces it. Off by default — see [DPoP](#dpop-rfc-9449). Header forwarding on /token and /par is always on. PAR has no env flag (see authorize proxy note above). | | | | | Observability | | MCP_ACCESS_LOG | No | true | Emit per-request access logs at info level with client identification (User-Agent, method, path, IP, plus route-specific fields). Set to false to disable. | | MCP_METRICS_ENABLED | No | true | Enable Prometheus metrics endpoint (GET /metrics) and request instrumentation. Set to false to disable (zero overhead). | | MCP_DEBUG | No | false | Emit structured debug logs for every request. |
Open DCR and its Security Limitations
MCP Clients need a way to get client_id necessary to login through the upstream IdP. You can use Open DCR functionality of this adapter if your IdP does not provide it, or if you do not want to use it.
The Open DCR endpoint returns a fixed public client_id (token_endpoint_auth_method: none) to be used by MCP Clients. But as many MCP Clients are local apps, any local application can obtain this client_id and start an OAuth flow. IdP do not know who is asking for the client_id. Two emerging standards address this:
- DCR with Software Statement Assertion (SSA) - cryptographically proves client identity via signed JWTs (RFC 7591 §2.3). No major MCP client currently includes Software Statements in DCR requests.
- Client ID Metadata Documents (CIMD) - the
client_idis an HTTPS URL pointing to a metadata document. Default mechanism in the MCP Auth Spec (2025-11-25), not yet universally adopted. This adapter includes experimental CIMD support - see [CIMD Adapter](#cimd-adapter-experimental).
Until "DCR with SSA" or CIMD is widely supported, user consent during login at the upstream IdP is the last line of defense. This is an accepted limitation of the MCP auth ecosystem.
Per-client IdP client mapping (see below) provides partial mitigation: operators can isolate IdP clients per MCP application.
Per-MCP-Client IdP Client Mapping
Operators often want different MCP clients (Cursor, Claude Code, VS Code, etc.) to use different upstream IdP clients — for per-client consent screens, scope policies, audit logging, and access revocation. DCR client name mapping (below) and [CIMD client mapping](#cimd-adapter-experimental) both support this, using different client identification methods. For how redirect URIs are validated across all client types, see [Redirect URIs at the upstream IdP](#redirect-uris-at-the-upstream-idp).
DCR Client Name Mapping
MCP_PROXY_DCR_CLIENT_NAME_MAP maps client_name values from DCR requests to upstream IdP client_ids. Pattern matching is case-insensitive; trailing * means prefix match, no * means exact match. Exact matches are checked first, then prefix matches in declaration order.
Simple format (all clients use global MCP_PROXY_AUTH_ALLOWED_REDIRECT_URIS):
MCP_PROXY_DCR_CLIENT_NAME_MAP={"Cursor":"cursor-sso-client","Claude Code*":"claude-sso-client","VS Code*":"vscode-sso-client"}
Extended format (per-client redirect URI enforcement — recommended):
MCP_PROXY_DCR_CLIENT_NAME_MAP={
"Cursor": {
"client_id": "cursor-sso-client",
"allowed_redirect_uris": "cursor://anysphere.cursor-mcp/*"
},
"Claude Code*": {
"client_id": "claude-sso-client",
"allowed_redirect_uris": "http://localhost:*,http://127.0.0.1:*"
},
"VS Code*": "vscode-sso-client"
}
When allowed_redirect_uris is set, these patterns are
…
Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: redhat-community-ai-tools
- Source: redhat-community-ai-tools/mcp-auth-adapter
- License: Apache-2.0
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.