
# MCP Clerk OAuth Policy

:::note{title="MCP Gateway Policy"}

This policy is for use with the [MCP Gateway](/mcp-gateway/introduction). See
the MCP Gateway documentation to learn how to proxy and secure MCP servers with
Zuplo.

:::

Use Clerk as the identity provider for MCP Gateway browser login.

## Configuration

The configuration shows how to configure the policy in the 'policies.json' document.

```json title="config/policies.json"
{
  "name": "my-mcp-clerk-oauth-inbound-policy",
  "policyType": "mcp-clerk-oauth-inbound",
  "handler": {
    "export": "McpClerkOAuthInboundPolicy",
    "module": "$import(@zuplo/runtime)",
    "options": {
      "browserLoginOverrides": {
        "remoteTimeoutMs": 10000,
        "sessionTtlSeconds": 28800,
        "stateTtlSeconds": 900
      },
      "clientId": "$env(CLERK_CLIENT_ID)",
      "clientSecret": "$env(CLERK_CLIENT_SECRET)",
      "frontendApiUrl": "https://verb-noun-00.clerk.accounts.dev",
      "gateway": {
        "accessTokenTtlSeconds": 900,
        "cimdEnabled": true,
        "refreshTokenTtlSeconds": 2592000
      },
      "scope": "openid profile email"
    }
  }
}
```

### Policy Configuration

- `name` <code className="text-green-600">&lt;string&gt;</code> - The name of your policy instance. This is used as a reference in your routes.
- `policyType` <code className="text-green-600">&lt;string&gt;</code> - The identifier of the policy. This is used by the Zuplo UI. Value should be `mcp-clerk-oauth-inbound`.
- `handler.export` <code className="text-green-600">&lt;string&gt;</code> - The name of the exported type. Value should be `McpClerkOAuthInboundPolicy`.
- `handler.module` <code className="text-green-600">&lt;string&gt;</code> - The module containing the policy. Value should be `$import(@zuplo/runtime)`.
- `handler.options` <code className="text-green-600">&lt;object&gt;</code> - The options for this policy. [See Policy Options](#policy-options) below.

### Policy Options

The options for this policy are specified below. All properties are optional unless specifically marked as required.

- `frontendApiUrl` **(required)** <code className="text-green-600">&lt;string&gt;</code> - The Clerk Frontend API URL origin, without a trailing path, query string, or fragment.
- `clientId` **(required)** <code className="text-green-600">&lt;string&gt;</code> - The Clerk OAuth application client_id registered for the gateway's browser login flow.
- `clientSecret` **(required)** <code className="text-green-600">&lt;string&gt;</code> - The Clerk OAuth application client_secret. Use $env(...) to source from a secret environment variable.
- `scope` <code className="text-green-600">&lt;string&gt;</code> - OIDC scopes requested during browser login. Defaults to `"openid profile email"`.
- `gateway` <code className="text-green-600">&lt;object&gt;</code> - Gateway-side OAuth token settings. The gateway issuer and advertised URLs are derived from the incoming request origin.
  - `accessTokenTtlSeconds` <code className="text-green-600">&lt;integer&gt;</code> - Lifetime of access tokens issued by /oauth/token. Defaults to `900`.
  - `refreshTokenTtlSeconds` <code className="text-green-600">&lt;integer&gt;</code> - Lifetime of refresh tokens issued by /oauth/token. Defaults to `2592000`.
  - `cimdEnabled` <code className="text-green-600">&lt;boolean&gt;</code> - Whether to advertise client_id_metadata_document_supported in AS metadata. Defaults to `true`.
- `browserLoginOverrides` <code className="text-green-600">&lt;object&gt;</code> - Optional overrides for the derived browser-login settings.
  - `remoteTimeoutMs` <code className="text-green-600">&lt;integer&gt;</code> - No description available. Defaults to `10000`.
  - `stateTtlSeconds` <code className="text-green-600">&lt;integer&gt;</code> - No description available. Defaults to `900`.
  - `sessionTtlSeconds` <code className="text-green-600">&lt;integer&gt;</code> - No description available. Defaults to `28800`.

## Using the Policy

# MCP Clerk OAuth

Authenticates MCP clients with gateway-issued OAuth tokens and delegates browser
login to a Clerk OAuth application.

Configure a Clerk OAuth application in the Clerk Dashboard, add the gateway
callback URL as an allowed redirect URI, then provide the Clerk Frontend API URL
and OAuth client credentials to this policy.

```json
{
  "name": "clerk-inbound",
  "policyType": "mcp-clerk-oauth-inbound",
  "handler": {
    "export": "McpClerkOAuthInboundPolicy",
    "module": "$import(@zuplo/runtime)",
    "options": {
      "frontendApiUrl": "https://verb-noun-00.clerk.accounts.dev",
      "clientId": "$env(CLERK_CLIENT_ID)",
      "clientSecret": "$env(CLERK_CLIENT_SECRET)"
    }
  }
}
```

The policy derives:

- issuer: `{frontendApiUrl}`
- JWKS URL: `{frontendApiUrl}/.well-known/jwks.json`
- authorize URL: `{frontendApiUrl}/oauth/authorize`
- token URL: `{frontendApiUrl}/oauth/token`

`frontendApiUrl` must be the origin only. Do not include a path, query string,
fragment, or userinfo.

Read more about [how policies work](/articles/policies)
