Custom
Wire any OAuth authorization server with custom() or jwtOAuthProvider().
Use a custom provider when your identity provider is not covered by a built-in plugin, you need token introspection instead of JWT verification, or claim mapping differs from the defaults.
JWT identity providers
Use jwtOAuthProvider() with a short spec:
import { defineConfig } from "bitmcp";
import { jwtOAuthProvider } from "bitmcp/oauth";
export default defineConfig({
auth: jwtOAuthProvider({
name: "my-provider",
resolveIssuer: () => "https://auth.example.com",
jwksUrl: (issuer) => new URL(`${issuer}/.well-known/jwks.json`),
oauthMetadata: (issuer) => ({
issuer,
authorization_endpoint: `${issuer}/oauth/authorize`,
token_endpoint: `${issuer}/oauth/token`,
registration_endpoint: `${issuer}/oauth/register`,
response_types_supported: ["code"],
grant_types_supported: ["authorization_code", "refresh_token"],
code_challenge_methods_supported: ["S256"],
}),
mapUser: (payload) => ({
id: String(payload.sub),
email: typeof payload.email === "string" ? payload.email : undefined,
}),
audience: "https://mcp.example.com/mcp",
}),
});Full control with custom()
Use custom() when verification logic is not a standard JWT flow:
import { custom, createJwtVerifier } from "bitmcp/oauth";
auth: custom({
createTokenVerifier: (resource) =>
createJwtVerifier({
issuer: "https://auth.example.com",
jwksUrl: new URL("https://auth.example.com/.well-known/jwks.json"),
resource,
audience: resource.href,
}),
oauthMetadata: {
issuer: "https://auth.example.com",
authorization_endpoint: "https://auth.example.com/oauth/authorize",
token_endpoint: "https://auth.example.com/oauth/token",
response_types_supported: ["code"],
},
mapUser: (authInfo) => ({
id: String(authInfo.extra?.payload?.sub ?? authInfo.clientId),
}),
});Resource binding
Tokens must target your MCP server. In production set MCP_URL to the same URL you use as the OAuth resource (for example https://mcp.example.com/mcp). You can also pass resource on the provider options.
OAuth requires HTTP. app.stdio() throws when auth is set.
Options
custom(options: {
createTokenVerifier: (resource: URL) => OAuthTokenVerifier;
oauthMetadata: OAuthMetadata;
mapUser: (authInfo: AuthInfo) => BitmcpUser;
resource?: URL | string;
requiredScopes?: string[];
scopesSupported?: string[];
resourceName?: string;
})| Variable | Purpose |
|---|---|
MCP_URL | Canonical public MCP URL in production |
BITMCP_STATE_KEY | MRTR state when using confirm or ctx.ask |
Options passed to a factory override environment variables.