Skip to main content

Configuration Options

JWKS Configuration

The oauth.jwks array configures one or more JWKS providers for JWT verification.

Remote JWKS URL

For the full JWKS configuration reference including all options (refresh_unknown_kid, allowed_use, etc.), see Router Authentication.

Symmetric Secret

For development or testing, you can use a shared symmetric secret instead of a remote JWKS endpoint:

Environment Variables

HTTP Error Responses

401 Unauthorized

Returned when the token is missing, invalid, expired, or signature verification fails.
The scope parameter contains the initialize scopes (minimum scopes needed to connect). The resource_metadata URL points to the RFC 9728 metadata endpoint for OAuth discovery.

403 Forbidden

Returned when the token is valid but lacks required scopes. The exact scope parameter depends on which level of enforcement rejected the request: Method-level rejection (e.g., missing tools_call scopes):
Per-tool rejection (e.g., calling a tool that requires read:fact):
The scope parameter always contains only the scopes needed for the specific operation that failed (unless scope_challenge_include_token_scopes is enabled).
Per the MCP specification, HTTP-level authentication failures return only HTTP status codes and headers - no JSON-RPC response body is included.

RFC 9728 Protected Resource Metadata

When OAuth is enabled and authorization_server_url is configured, the MCP server exposes a public (unauthenticated) metadata endpoint at:
This follows the RFC 9728 path-aware format. MCP clients use this endpoint to automatically discover the authorization server and all supported scopes. Example response:
The scopes_supported field is automatically computed as the union of:
  • All configured static scopes (initialize, tools_list, tools_call)
  • All scopes extracted from @requiresScopes directives on fields used by registered operations

Startup Validation

The router performs startup validation when OAuth is enabled:
  • If oauth.jwks is empty, the router exits with a fatal error to prevent starting an unprotected endpoint
  • If server.base_url is empty, the router exits with a fatal error because it is required for RFC 9728 metadata discovery

Full Configuration Example