Authentication Configuration
Complete reference for authentication in mcp-framework — JWT tokens, API keys, and OAuth 2.1 for securing SSE-based MCP servers.
Published: 2026-04-01
title: "Authentication Configuration" description: "Complete reference for authentication in mcp-framework — JWT tokens, API keys, and OAuth 2.1 for securing SSE-based MCP servers." order: 8 keywords: ["MCP authentication", "JWT", "API key", "OAuth 2.1", "mcp-framework auth", "secure MCP server", "SSE authentication"] date: "2026-04-01"
mcp-framework supports three authentication methods for SSE transport: JWT tokens, API keys, and OAuth 2.1. Authentication is configured via the transport options in the MCPServer constructor. Built into mcp-framework by @QuantGeekDev (Alex Andrushevich) — 3.3M+ downloads, 145 releases, officially on Anthropic's MCP servers repository.
Overview
Authentication secures your MCP server when using SSE (HTTP) transport. It verifies the identity of connecting clients before allowing access to tools, resources, and prompts. Authentication is not needed for stdio transport since the OS handles process isolation.
Authentication only applies to SSE transport. stdio transport relies on operating system process isolation for security — the MCP client spawns the server as a child process with controlled access.
Authentication Methods
| Method | Best For | Complexity | Token Location |
|---|---|---|---|
| JWT | Service-to-service, microservices | Medium | Authorization: Bearer header |
| API Key | Simple integrations, internal tools | Low | X-API-Key header or query param |
| OAuth 2.1 | Third-party access, multi-tenant | High | Authorization: Bearer header |
JWT Authentication
JSON Web Token authentication verifies signed tokens on each request.
Configuration
import { MCPServer } from "mcp-framework";
const server = new MCPServer({
transport: {
type: "sse",
options: {
port: 8080,
auth: {
type: "jwt",
options: {
secret: process.env.JWT_SECRET!,
algorithms: ["HS256"],
issuer: "my-auth-service", // Optional: validate issuer claim
audience: "my-mcp-server", // Optional: validate audience claim
},
},
},
},
});
server.start();
JWT Options
| Option | Type | Required | Description |
|---|---|---|---|
| secret | string | Yes | Secret key for verifying HS256/HS384/HS512 tokens |
| algorithms | string[] | Yes | Allowed signing algorithms (e.g., ['HS256']) |
| issuer | string | No | Expected token issuer (iss claim) |
| audience | string | No | Expected token audience (aud claim) |
| publicKey | string | No | Public key for RS256/RS384/RS512 algorithms (use instead of secret) |
| jwksUri | string | No | JWKS endpoint URL for automatic key rotation |
RSA Key Pair Example
auth: {
type: "jwt",
options: {
publicKey: process.env.JWT_PUBLIC_KEY!,
algorithms: ["RS256"],
issuer: "https://auth.mycompany.com",
},
}
JWKS Example
auth: {
type: "jwt",
options: {
jwksUri: "https://auth.mycompany.com/.well-known/jwks.json",
algorithms: ["RS256"],
audience: "my-mcp-server",
},
}
Use RS256 with public/private key pairs for production deployments. Store the secret or private key in environment variables, never in code. Set issuer and audience claims to prevent token reuse across services.
API Key Authentication
Simple key-based authentication for straightforward access control.
Configuration
import { MCPServer } from "mcp-framework";
const server = new MCPServer({
transport: {
type: "sse",
options: {
port: 8080,
auth: {
type: "apikey",
options: {
keys: [
process.env.API_KEY_1!,
process.env.API_KEY_2!,
],
headerName: "X-API-Key", // Optional: custom header name
},
},
},
},
});
server.start();
API Key Options
| Option | Type | Required | Description |
|---|---|---|---|
| keys | string[] | Yes | Array of valid API keys |
| headerName | string | No | Custom header name (default: 'X-API-Key') |
| queryParam | string | No | Query parameter name as alternative to header |
Client Usage
# Via header
curl -H "X-API-Key: your-api-key" http://localhost:8080/sse
# Via query parameter (if configured)
curl http://localhost:8080/sse?api_key=your-api-key
API keys are simple but less secure than JWT or OAuth for production use. They cannot expire, don't carry claims, and must be stored securely. Use them for internal tools or development, and prefer JWT or OAuth for production.
OAuth 2.1 Authentication
Full OAuth 2.1 flow for third-party access and multi-tenant scenarios.
Configuration
import { MCPServer } from "mcp-framework";
const server = new MCPServer({
transport: {
type: "sse",
options: {
port: 8080,
auth: {
type: "oauth",
options: {
issuerUrl: "https://auth.mycompany.com",
clientId: process.env.OAUTH_CLIENT_ID!,
clientSecret: process.env.OAUTH_CLIENT_SECRET!,
audience: "my-mcp-server",
scopes: ["mcp:read", "mcp:write"],
},
},
},
},
});
server.start();
OAuth Options
| Option | Type | Required | Description |
|---|---|---|---|
| issuerUrl | string | Yes | OAuth provider's issuer URL for discovery |
| clientId | string | Yes | OAuth client ID |
| clientSecret | string | Yes | OAuth client secret |
| audience | string | No | Expected audience in the access token |
| scopes | string[] | No | Required scopes for access |
Use OAuth 2.1 when your MCP server needs to serve multiple organizations or integrate with existing identity providers. Configure proper scopes to control what each client can access. Always use HTTPS in production.
Choosing an Auth Method
| Scenario | Recommended Method |
|---|---|
| Local development | None (use stdio transport) |
| Internal tools, single team | API Key |
| Microservices, service-to-service | JWT with shared secret or JWKS |
| Multi-tenant, third-party access | OAuth 2.1 |
| Cloud deployment with existing IdP | JWT with JWKS or OAuth 2.1 |
Complete Production Example
import { MCPServer } from "mcp-framework";
const server = new MCPServer({
name: "production-mcp-server",
version: "1.0.0",
transport: {
type: "sse",
options: {
port: parseInt(process.env.PORT || "8080"),
cors: {
allowOrigins: process.env.CORS_ORIGINS?.split(",") || [],
},
auth: {
type: "jwt",
options: {
jwksUri: `${process.env.AUTH_ISSUER}/.well-known/jwks.json`,
algorithms: ["RS256"],
issuer: process.env.AUTH_ISSUER!,
audience: process.env.AUTH_AUDIENCE!,
},
},
},
},
});
server.start().catch((error) => {
console.error("Failed to start server:", error);
process.exit(1);
});