loading…
Search for a command to run...
loading…
A template for building MCP servers with optional per-tool authentication using WorkOS AuthKit and Vercel MCP adapter.
A template for building MCP servers with optional per-tool authentication using WorkOS AuthKit and Vercel MCP adapter.
A production-ready template for building authenticated MCP servers using the Vercel MCP adapter and WorkOS AuthKit. Clone this repo, add your tools, and deploy instantly to Vercel with enterprise authentication built-in.
Core insight: Individual tools decide if they need authentication. No global auth requirements, no complex middleware.
// Without auth: pure business logic
server.tool("publicData", {}, async () => {
return getPublicData();
});
// With auth: same logic + one helper call
server.tool("userData", {}, async (args, extra) => {
const user = ensureUserAuthenticated(extra.authInfo); // ← Just add this line
return getUserData(user);
});
experimental_withMcpAuth:const authHandler = experimental_withMcpAuth(handler, verifyToken, {
required: false // ← Tools decide individually
});
const verifyToken = async (req: Request, bearerToken?: string) => {
if (!bearerToken) return undefined; // Allow unauthenticated requests
const { payload } = await jwtVerify(bearerToken, JWKS); // WorkOS JWT
const user = await workos.userManagement.getUser(payload.sub); // WorkOS User API
return { token: bearerToken, clientId: user.id, extra: { user } };
};
// lib/auth/helpers.ts
export const ensureUserAuthenticated = (authInfo: AuthInfo | undefined): User => {
if (!authInfo?.extra?.user) {
throw new Error('Authentication required for this tool');
}
return authInfo.extra.user; // WorkOS user object
};
That's it! Your MCP server now has enterprise authentication with zero global auth logic.
// app/mcp/route.ts - Complete authenticated MCP server
import { createMcpHandler, experimental_withMcpAuth } from "@vercel/mcp-adapter";
import { jwtVerify } from "jose";
import { ensureUserAuthenticated, isAuthenticated } from "../../lib/auth/helpers";
// Clean MCP handler - tools decide auth individually
const handler = createMcpHandler((server) => {
// Public tool
server.tool("ping", {}, async (args, extra) => {
const authenticated = isAuthenticated(extra.authInfo);
return {
content: [{
type: "text",
text: authenticated ? "Hello authenticated user!" : "Hello world!"
}]
};
});
// Private tool - decides it needs auth
server.tool("getUserProfile", {}, async (args, extra) => {
const user = ensureUserAuthenticated(extra.authInfo); // Throws if not authenticated
return {
content: [{
type: "text",
text: `Profile: ${user.email} (${user.firstName} ${user.lastName})`
}]
};
});
});
// WorkOS token verification
const verifyToken = async (req: Request, bearerToken?: string) => {
if (!bearerToken) return undefined;
try {
const { payload } = await jwtVerify(bearerToken, JWKS);
const user = await workos.userManagement.getUser(payload.sub);
return { token: bearerToken, clientId: user.id, extra: { user, claims: payload } };
} catch (error) {
return undefined;
}
};
// Authenticated handler
const authHandler = experimental_withMcpAuth(handler, verifyToken, { required: false });
export { authHandler as GET, authHandler as POST };
Result: Enterprise authentication with SSO support, automatic user context in tools, and zero-config Vercel deployment.
This isn't just a demo—it's a complete template you can build on:
lib/business/examples.ts with your own business logicThe template includes a complete testing interface so you can verify your tools work correctly:

Test both public and authenticated tools directly from your browser, with automatic token management and clear response formatting.
git clone https://github.com/workos/vercel-mcp-example.git
cd vercel-mcp-example
pnpm install
Note: We recommend using
pnpmas it handles React 19 peer dependency warnings gracefully. If using npm, add the--legacy-peer-depsflag.
http://localhost:3000/callback as a redirect URI in AuthKit settingscp .env.example .env.local
Fill in your WorkOS credentials:
WORKOS_API_KEY=sk_test_your_api_key_here
WORKOS_CLIENT_ID=client_your_client_id_here
WORKOS_COOKIE_PASSWORD=your_32_character_secure_random_string
WORKOS_REDIRECT_URI=http://localhost:3000/callback
npm run dev
Visit http://localhost:3000 to try the authenticated MCP server!
The template includes a complete web interface for testing your MCP tools:
ping without authenticationgetUserProfile that require user contextThe interface handles token management automatically and displays responses in a clean, readable format. You can also test with any MCP client by configuring it to use your local server.
graph LR
A[MCP Client] --> B[authHandler Wrapper]
B --> C[JWT Verification]
C --> D[MCP Server Tools]
B --> E[WorkOS API]
style B fill:#ec4899,stroke:#db2777,stroke-width:2px,color:#ffffff
style D fill:#f59e0b,stroke:#d97706,stroke-width:2px,color:#ffffff
Simple flow: Client → Auth wrapper → JWT verification → Tools decide if they need user context → WorkOS API (if needed).
This template follows a recommended structure for scalable MCP servers:
lib/
├── auth/
│ ├── helpers.ts # ensureUserAuthenticated, isAuthenticated
│ └── types.ts # User, WorkOSAuthInfo types
├── business/
│ ├── examples.ts # Example business logic (replace with yours)
│ └── database.ts # Database connection/queries
├── mcp/
│ ├── tools/
│ │ ├── public.ts # Public tools (ping, status)
│ │ └── examples.ts # Example authenticated tools
│ └── server.ts # Main MCP server setup
└── utils/
├── validation.ts # Zod schemas
└── errors.ts # Custom error classes
app/mcp/route.ts - The main MCP server with authenticationlib/auth/helpers.ts - Authentication helper functionslib/business/examples.ts - Example business logic (replace with yours)lib/mcp/tools/ - MCP tool definitions organized by categoryapp/components/TestingSection.tsx - Built-in testing interfacelib/with-authkit.ts - WorkOS AuthKit setuplib/business/examples.ts with your business logic vercel deploy with your environment variablesPerfect for building production AI tools that need real user authentication and enterprise features.
We welcome contributions to this project! Here's how you can help:
git clone https://github.com/YOUR_USERNAME/vercel-mcp-example.gitpnpm install (or npm install --legacy-peer-deps)git checkout -b feature/your-feature-namepnpm run testpnpm run lint && pnpm run prettierPlease use the GitHub Issues page to report bugs or request features.
This project is licensed under the MIT License - see the LICENSE file for details.
Questions? Check the WorkOS MCP docs or Vercel MCP adapter docs.
Выполни в терминале:
claude mcp add mcp-authentication-demo -- npx Безопасность
Низкий рискАвтоматическая эвристика по публичным данным — не гарантия безопасности.