Skip to content

Authentication (OAuth2)

Adding auth to an MCP server usually means wiring up JWKS fetching, token validation, key rotation, scope checking, and metadata endpoints yourself. With @casys/mcp-server, it’s a one-liner.

OAuth2 Authentication Flow

Pick your identity provider. Each preset handles issuer URLs, JWKS endpoints, and key rotation automatically:

import {
ConcurrentMCPServer,
createGoogleAuthProvider,
} from "@casys/mcp-server";
const server = new ConcurrentMCPServer({
name: "my-api",
version: "1.0.0",
auth: {
provider: createGoogleAuthProvider({
audience: "https://my-mcp.example.com",
resource: "https://my-mcp.example.com",
}),
},
});

Tools can declare required scopes. The framework automatically checks the token before the handler runs:

server.registerTool(
{
name: "delete_user",
description: "Delete a user account",
inputSchema: {
type: "object",
properties: { userId: { type: "string" } },
required: ["userId"],
},
requiredScopes: ["admin", "users:delete"],
},
async ({ userId }) => {
// This code only runs if the token has BOTH admin AND users:delete
await deleteUser(userId);
return { deleted: true };
},
);

For full control over validation parameters, use JwtAuthProvider directly:

import { JwtAuthProvider } from "@casys/mcp-server";
const provider = new JwtAuthProvider({
issuer: "https://accounts.google.com",
audience: "https://my-mcp.example.com",
resource: "https://my-mcp.example.com",
authorizationServers: ["https://accounts.google.com"],
jwksUri: "https://www.googleapis.com/oauth2/v3/certs",
scopesSupported: ["read", "write"],
});
const authInfo = await provider.verifyToken(token);
// { subject, clientId, scopes, claims, expiresAt } — or null if invalid

When auth is configured on an HTTP server, the framework automatically serves a discovery endpoint. MCP clients use this to figure out how to authenticate:

GET /.well-known/oauth-protected-resource
{
"resource": "https://my-mcp.example.com",
"authorization_servers": ["https://accounts.google.com"],
"scopes_supported": ["read", "write"],
"bearer_methods_supported": ["header"]
}

Shipping a compiled binary? Your users can configure auth without touching code — see the Configuration guide.