@phake/mcp supports five authentication strategies. Set AUTH_STRATEGY in your environment to select one, or let the framework infer it from which env vars are present.
If AUTH_STRATEGY is not set, the framework infers the strategy:
api_key — if API_KEY is present
bearer — if BEARER_TOKEN is present
none — otherwise
Strategies at a glance
oauth — OAuth 2.1 PKCE
Use oauth when you want users to authenticate with a third-party provider (Google, GitHub, Spotify, etc.). The server runs a full OAuth 2.1 authorization code flow with PKCE and maintains a mapping between its own RS tokens and the provider’s access tokens.
When to use it: when your tools need to call external APIs on behalf of individual users, or when you need multi-user isolation with per-session tokens.
Once a user completes the flow, context.providerToken in tool handlers is set to the provider’s access token. Use context.resolvedHeaders to forward it:
The OAuth endpoints exposed by the server are:
bearer — Static Bearer token
Use bearer for server-to-server integrations or personal deployments where a single shared secret is sufficient. Every incoming request must include Authorization: Bearer <token>.
When to use it: simple scenarios where you control all clients and a single token is enough.
In your tools, context.providerToken is set to the value of BEARER_TOKEN and context.resolvedHeaders contains { Authorization: "Bearer super-secret-token" }.
Configure clients to send the header:
api_key — Static API key
Use api_key to authenticate with a key sent in a custom header instead of the Authorization header. The header name defaults to x-api-key but is configurable.
When to use it: APIs that expect a non-standard auth header (e.g., x-api-key, Api-Key), or when you want to avoid the Authorization header for routing reasons.
context.resolvedHeaders will contain { "x-api-key": "my-api-key-value" } (or whichever header name you configure).
Use custom when the upstream API you’re wrapping expects arbitrary headers that don’t fit the bearer or API key patterns — for example, multiple headers or non-standard schemes.
When to use it: wrapping APIs that use proprietary auth headers, or when you need to forward multiple headers to every tool call.
Provide headers as a comma-separated key:value string:
All headers in CUSTOM_HEADERS are available via context.resolvedHeaders:
none — No authentication
Use none to accept all requests without checking credentials. Suitable for local development or fully public tools.
Do not use none in production deployments that are publicly accessible. Any client can call your tools without restrictions.
assertProviderToken
When a tool has requiresAuth: true the dispatcher already rejects unauthenticated calls before your handler runs. If you need a compile-time guarantee that context.providerToken is typed as string (not string | undefined), call assertProviderToken:
assertProviderToken throws Error("Authentication required") if the token is absent. In practice this only happens in tools without requiresAuth: true, since the dispatcher already guards authenticated tools.
Prefer context.resolvedHeaders over constructing headers manually. The framework builds the correct header shape for the active strategy automatically: