Clerk
The Clerk plugin provides authentication for your MCP server using Clerk's OAuth system.
For the complete documentation index, see llms.txt. Markdown variants of every page are available by appending .md to the URL.Installation
Install the Clerk plugin:
pnpm i @xmcp-dev/clerkClerk Setup
Before integrating the plugin, configure your Clerk application:
- Navigate to your Clerk Dashboard
- Create a new application (or use an existing one)
- Go to Configure and access to API Keys to get the following values:
- Secret Key (
sk_...) - Frontend API URL (
your-app.clerk.accounts.dev)
- Secret Key (
- Click on Development, enter to OAuth Applications and enable Dynamic Client Registration
Environment Variables
Create a .env file in the root of your project and configure the following environment variables:
CLERK_SECRET_KEY=sk_...
CLERK_DOMAIN=your-app.clerk.accounts.dev
BASE_URL=http://127.0.0.1:3001 Set up the Provider
Create a middleware.ts file in your xmcp app's src directory and import the provider from the package:
import { clerkProvider } from "@xmcp-dev/clerk";
export default clerkProvider({
secretKey: process.env.CLERK_SECRET_KEY!,
clerkDomain: process.env.CLERK_DOMAIN!,
baseURL: process.env.BASE_URL!
});Configuration Options
secretKey: Clerk Secret KeyclerkDomain: Clerk Frontend domainbaseURL: Base URL of your MCP serverscopes: (Optional) OAuth scopes to request (default:['profile', 'email'])docsURL: (Optional) URL to your MCP server's API documentation
Get a user session
Access the authenticated user in your xmcp tools using getSession:
Example: Greet the user with their Clerk identity
import { z } from "zod";
import type { InferSchema, ToolMetadata } from "xmcp";
import { getSession } from "@xmcp-dev/clerk";
// Define the schema for tool parameters
export const schema = {
name: z.string().describe("The name of the user to greet"),
};
// Define tool metadata
export const metadata: ToolMetadata = {
name: "greet",
description: "Greet the user with their Clerk identity",
};
// Tool implementation
export default function greet({ name }: InferSchema<typeof schema>): string {
const session = getSession();
return `Hello, ${name}! Your Clerk user ID is ${session.userId}`;
}Get user details
Access the authenticated user in your xmcp tools using getUser:
Example: Get user details
import type { ToolMetadata } from "xmcp";
import { getUser } from "@xmcp-dev/clerk";
// Define tool metadata
export const metadata: ToolMetadata = {
name: "get-user-info",
description: "Get user details",
};
// Tool implementation
export default async function getUserInfo(): Promise<string> {
const user = await getUser();
return JSON.stringify(user, null, 2);
}Access the client
The getClient() function gives you access to the full Clerk Backend SDK, allowing you to leverage all Clerk features in your MCP tools.
Example: Retrieve an Organization
import { getSession, getClient } from "@xmcp-dev/clerk";
export default async function getOrganization() {
const session = getSession();
const clerk = getClient();
if (!session.organizationId) {
return "User is not in an organization";
}
const org = await clerk.organizations.getOrganization({
organizationId: session.organizationId,
});
return JSON.stringify(org, null, 2);
}Troubleshooting
Missing Configuration Errors
If you see "[Clerk] Missing required config: ..." at startup:
- Ensure all required environment variables are set (
CLERK_SECRET_KEY,CLERK_DOMAIN,BASE_URL) - Check your
.envfile is being loaded correctly
Session or Client Not Initialized
If getSession(), getUser(), or getClient() throws "... not initialized":
- Ensure
clerkProvideris exported as default frommiddleware.ts - Ensure the tool is called on a route under
/mcp/* - Don't call these functions at module load time only inside tool handlers
Token Expired Errors
Access tokens are short-lived. If you see token_expired errors:
- MCP clients should automatically refresh tokens
- Users can disconnect and reconnect to get fresh tokens
Invalid Token Errors
If tokens are consistently invalid:
- Verify your
CLERK_SECRET_KEYmatches your Clerk application - Verify your
CLERK_DOMAINmatches your Clerk Frontend API URL - Check that you're using the correct environment (development vs production)
Authentication Service Misconfigured
If you see a 500 error with "Authentication service misconfigured":
- Your
CLERK_SECRET_KEYis invalid or doesn't match your Clerk application - Double-check you're using the correct key for your environment (development vs production)