一个用于构建带有 Clerk 认证的 Model Context Protocol (MCP) 服务器的生产就绪模板,基于 Cloudflare Workers。此模板提供了创建与现有 Clerk 驱动应用程序集成的安全认证 MCP 工具所需的一切。
这个模板连接了您的现有 Clerk 认证应用程序与 Claude AI 通过 MCP 工具。非常适合:
git clone https://github.com/your-username/clerk-mcp-template.git my-mcp-server
cd my-mcp-server
npm install
复制示例环境文件:
cp .dev.vars.example .dev.vars
更新 .dev.vars 文件中的 Clerk 密钥和应用 URL:
CLERK_SECRET_KEY=sk_test_your_actual_clerk_secret_key
CLERK_PUBLISHABLE_KEY=pk_test_your_actual_clerk_publishable_key
APP_URL=https://your-app.com
重要:
APP_URL应指向您现有的 Clerk 认证应用程序,在该应用程序中您将实现 MCP 认证流程。
为 OAuth 会话存储创建一个 KV 命名空间:
wrangler kv:namespace create "OAUTH_KV"
在 wrangler.jsonc 中更新生成的命名空间 ID。
wrangler.jsonc:
name 从 "your-mcp-server" 更改为所需的 worker 名称src/index.ts:
McpServer 构造函数中的服务器名称和版本npm run dev
服务器将在 http://localhost:8788 上可用
graph TB
A[MCP 客户端] --> B[Cloudflare Worker]
B --> C[OAuth 提供者]
C --> D[Clerk 认证]
B --> E[持久对象]
B --> F[KV 存储]
B --> G[您的 API]
E --> H[MCP 会话状态]
F --> I[OAuth 会话]
D --> J[用户认证]
G --> K[您的应用程序数据]
/sse 端点/authorize 端点/callback 端点在您的现有 Clerk 应用程序中创建一个认证路由 /auth/mcp。此路由处理由 MCP 服务器发起的 OAuth 流程。
此示例展示了如何在框架模式下(以前称为 Remix)与 React Router v7 集成,但您可以将其适应于 Next.js、Express 或任何框架。
app/routes/auth.mcp.tsx:
import { createClerkClient } from '@clerk/express'
import { redirect, type LoaderFunctionArgs } from 'react-router'
export async function loader({ request }: LoaderFunctionArgs) {
const url = new URL(request.url)
const state = url.searchParams.get('state')
const callbackUrl = url.searchParams.get('callback_url')
const clientName = url.searchParams.get('client_name')
if (!state || !callbackUrl) {
throw new Error('缺少必需的参数')
}
// 获取已认证用户的会话令牌
const clerkClient = createClerkClient({
secretKey: process.env.CLERK_SECRET_KEY,
publishableKey: process.env.CLERK_PUBLISHABLE_KEY,
})
const clerkAuth = (await clerkClient.authenticateRequest(request)).toAuth()
const sessionToken = await clerkAuth?.getToken()
if (!sessionToken) {
// 如果未认证,则重定向到登录页面
const signInUrl = new URL('/sign-in', request.url)
signInUrl.searchParams.set('redirect_url', request.url)
return redirect(signInUrl.toString())
}
// 重定向回 MCP 服务器并携带令牌
const redirectUrl = new URL(callbackUrl)
redirectUrl.searchParams.set('clerk_token', sessionToken)
redirectUrl.searchParams.set('state', state)
return redirect(redirectUrl.toString())
}
// 可选:添加组件以显示同意屏幕
export default function McpAuth() {
return (
<div className="max-w-md mx-auto mt-8 p-6 bg-white rounded-lg shadow-md">
<h1 className="text-xl font-bold mb-4">授权 MCP 访问</h1>
<p className="text-gray-600 mb-4">
Claude AI 正请求访问您的账户数据。
</p>
<p className="text-sm text-gray-500">
这将自动重定向您...
</p>
</div>
)
}
在您的应用程序中添加受保护的 API 端点,MCP 服务器可以使用认证请求调用这些端点。
app/routes/api.users.tsx:
import { createClerkClient } from '@clerk/express'
import { json, type LoaderFunctionArgs } from 'react-router'
export async function loader({ request }: LoaderFunctionArgs) {
try {
const clerkClient = createClerkClient({
secretKey: process.env.CLERK_SECRET_KEY,
publishableKey: process.env.CLERK_PUBLISHABLE_KEY,
})
// 验证请求是否已认证
const clerkAuth = await clerkClient.authenticateRequest(request)
const userId = clerkAuth.toAuth()?.userId
if (!userId) {
return json({ error: '未经授权' }, { status: 401 })
}
// 您的业务逻辑在此处
const users = await getUsersForCurrentUser(userId)
return { users }
} catch (error) {
return json({ error: '内部服务器错误' }, { status: 500 })
}
}
替换 src/index.ts 中的示例工具:
// 自定义工具示例
this.server.tool(
'getUsers',
'从您的应用程序获取所有用户',
{},
this.requireAuth(async () => {
const users = await this.makeApiRequest('api/users')
return {
content: [
{
type: 'text',
text: `找到 ${users.length} 个用户:\n${JSON.stringify(users, null, 2)}`,
},
],
}
}),
)
| 变量 | 描述 | 必需 |
|---|---|---|
CLERK_SECRET_KEY | 您的 Clerk 秘密密钥 | ✅ |
CLERK_PUBLISHABLE_KEY | 您的 Clerk 发布密钥 | ✅ |
APP_URL | 您的应用程序 URL | ✅ |
向 src/types.ts 中的 Env 接口添加您自己的应用程序特定环境变量。
在您的 Clerk 控制面板中创建一个 JWT 模板以生成令牌:
src/index.ts 中的模板名称:const token = await getToken(
// ... 令牌管理器
(this as any).env.CLERK_SECRET_KEY,
'your-template-name', // 更新此内容
)
npm run dev # 启动开发服务器
npm run deploy # 部署到 Cloudflare Workers
npm run inspect # 启动 MCP Inspector
npm run lint # 运行 ESLint + 格式化
npm run typecheck # 运行 TypeScript 类型检查
npm run validate # 运行类型检查 + 校验
npm run devhttp://localhost:8788/ssewrangler secret put CLERK_SECRET_KEY
wrangler secret put CLERK_PUBLISHABLE_KEY
wrangler secret put APP_URL
wrangler kv:namespace create "OAUTH_KV" --env production
更新生产 KV 命名空间 ID 在 wrangler.jsonc 中。
npm run deploy
将部署的服务器添加到 Claude Desktop MCP 配置中:
{
"mcpServers": {
"my-app": {
"command": "npx",
"args": [
"@modelcontextprotocol/server-remote",
"https://your-mcp-server.your-subdomain.workers.dev/sse"
]
}
}
}
clerk-mcp-template/
├── src/
│ ├── index.ts # 主 MCP 服务器类和工具
│ ├── auth.ts # OAuth 认证处理器
│ ├── clerk.ts # Clerk 认证实用工具
│ ├── utils.ts # 实用函数(HMAC、日志记录等)
│ └── types.ts # TypeScript 类型定义
├── wrangler.jsonc # Cloudflare Worker 配置
├── package.json # 依赖项和脚本
├── tsconfig.json # TypeScript 配置
├── eslint.config.js # ESLint 配置
├── .dev.vars # 开发环境变量
└── README.md # 本文件
认证失败:
KV 命名空间错误:
wrangler.jsonc 中的命名空间 ID工具无法正常工作:
# 查看实时日志
wrangler tail
# 检查部署状态
wrangler deployments list
# 本地调试测试
npm run dev
git checkout -b feature/amazing-featuregit commit -m '添加神奇的功能'git push origin feature/amazing-featureMIT 许可证 - 详情见 LICENSE 文件。