关于 cloudflare-mcp-server
cloudflare-mcp-server 是一项指导开发者用 TypeScript 在 Cloudflare Workers 构建和部署远程 MCP 服务的技能。内容涵盖工具定义、认证、会话状态、传输方式及部署测试,并提供模板和常见错误说明。
主要功能
- 01McpAgent 与工具定义模式
- 02SSE 和 Streamable HTTP 传输
- 03JWT 与 OAuth 认证方案
- 04使用 Durable Objects 保存会话状态
- 05WebSocket 休眠配置
- 06本地测试与 Workers 部署流程
适用场景
- 01从模板创建远程 MCP 服务
- 02为服务添加 OAuth 或令牌验证
- 03构建带有持久会话状态的 MCP 服务
- 04排查 Cloudflare MCP 部署问题
MCP 相关
该技能指导构建远程 MCP 服务,介绍如何注册工具、资源和提示词,并处理 SSE 与 Streamable HTTP 请求。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ jackspace/ claudeskillz --skill cloudflare-mcp-server安装后在 Claude Code 中输入/cloudflare-mcp-server确认已加载。
附带文件README.mdSKILL.json
详细介绍
Cloudflare MCP 服务 Skill
使用 TypeScript 在 Cloudflare Workers 上构建和部署 模型上下文协议(MCP)服务。
这是什么 Skill?
本 Skill 将教你如何在 Cloudflare 上构建远程 MCP 服务——截至 2025 年,Cloudflare 是唯一官方支持远程 MCP 的平台。
在以下情况下使用本 Skill:
- 使用 TypeScript(@modelcontextprotocol/sdk)构建 MCP 服务
- 将远程 MCP 服务部署到 Cloudflare Workers
- 实现 OAuth 身份验证(GitHub、Google、Azure、自定义)
- 使用 Durable Objects 创建有状态的 MCP 服务
- 使用 WebSocket 休眠优化成本
- 同时支持 SSE 和 Streamable HTTP 传输
- 避免 15 种以上常见的 MCP + Cloudflare 错误
你将学习:
- McpAgent 类模式和工具定义
- OAuth 集成(全部 4 种身份验证模式)
- 用于每会话状态的 Durable Objects
- WebSocket 休眠 API
- 双传输配置(SSE + HTTP)
- 完整的部署工作流
快速开始(5 分钟)
选项 1:从模板部署
# Create new MCP server from Cloudflare template
npm create cloudflare@latest -- my-mcp-server \
--template=cloudflare/ai/demos/remote-mcp-authless
cd my-mcp-server
npm install
npm run dev
你的 MCP 服务现已运行在 http://localhost:8788/sse
选项 2:从本 Skill 复制模板
# Copy basic MCP server template
cp ~/.claude/skills/cloudflare-mcp-server/templates/basic-mcp-server.ts src/index.ts
cp ~/.claude/skills/cloudflare-mcp-server/templates/wrangler-basic.jsonc wrangler.jsonc
cp ~/.claude/skills/cloudflare-mcp-server/templates/package.json package.json
# Install dependencies
npm install
# Start development server
npm run dev
使用 MCP Inspector 测试
# In a new terminal, start MCP Inspector
npx @modelcontextprotocol/inspector@latest
# Open http://localhost:5173
# Enter your MCP server URL: http://localhost:8788/sse
# Click "Connect" and test tools
部署到 Cloudflare
# Deploy to production
npx wrangler deploy
# Your MCP server is now live at:
# https://my-mcp-server.your-account.workers.dev/sse
核心概念
1. McpAgent 类
Cloudflare Agents SDK 中的 McpAgent 基类提供:
- 自动集成 Durable Objects
- 内置 SQL 数据库状态管理
- 工具、资源和提示词注册
- 传输处理(SSE + HTTP)
基本模式:
import { McpAgent } from "agents/mcp";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
export class MyMCP extends McpAgent<Env> {
server = new McpServer({
name: "My MCP Server",
version: "1.0.0"
});
async init() {
// Register tools here
this.server.tool(
"tool_name",
"Tool description",
{ param: z.string() },
async ({ param }) => ({
content: [{ type: "text", text: "Result" }]
})
);
}
}
2. 工具定义
工具是 MCP 客户端可以调用的函数。使用 Zod 验证参数。
模式:
this.server.tool(
"tool_name", // Tool identifier
"Tool description", // What it does (for LLM)
{ // Parameters (Zod schema)
param1: z.string().describe("Parameter description"),
param2: z.number().optional()
},
async ({ param1, param2 }) => { // Handler
// Your logic here
return {
content: [{ type: "text", text: "Result" }]
};
}
);
最佳实践:
- 详细描述:帮助大模型理解工具的用途
- 参数描述:说明预期值和限制条件
- 错误处理:失败时返回
{ isError: true } - 少量、聚焦的工具:优于大量细分工具
3. 传输方式
MCP 支持两种传输方式:
SSE(服务器发送事件)——旧版,支持广泛:
MyMCP.serveSSE("/sse").fetch(request, env, ctx)
Streamable HTTP——2025 年标准,效率更高:
MyMCP.serve("/mcp").fetch(request, env, ctx)
同时支持两者,以实现最大兼容性:
export default {
fetch(request: Request, env: Env, ctx: ExecutionContext) {
const { pathname } = new URL(request.url);
if (pathname.startsWith("/sse")) {
return MyMCP.serveSSE("/sse").fetch(request, env, ctx);
}
if (pathname.startsWith("/mcp")) {
return MyMCP.serve("/mcp").fetch(request, env, ctx);
}
return new Response("Not Found", { status: 404 });
}
};
身份验证模式
Cloudflare MCP 服务支持 4 种身份验证模式:
模式 1:无需身份验证
适用场景:内部工具、开发、公共 API
模板:templates/basic-mcp-server.ts
设置:无需设置
安全性:⚠️ 任何人都可以访问你的 MCP 服务
模式 2:令牌验证(JWTVerifier)
适用场景:预先完成身份验证的客户端、自定义身份验证系统
工作原理:客户端发送 Bearer 令牌,服务端进行验证
模板:创建自定义 JWTVerifier 中间件
设置:
import { JWTVerifier } from "agents/mcp";
const verifier = new JWTVerifier({
secret: env.JWT_SECRET,
issuer: "your-auth-server"
});
// Validate token before serving MCP requests
安全性:✅ 正确管理令牌即可确保安全
模式 3:OAuth 代理(workers-oauth-provider)
适用场景:集成 GitHub、Google、Azure OAuth
工作原理:Cloudflare Worker 将 OAuth 请求代理到第三方提供方
模板:templates/mcp-oauth-proxy.ts
设置:
import { OAuthProvider, GitHubHandler } from "@cloudflare/workers-oauth-provider";
export default new OAuthProvider({
authorizeEndpoint: "/authorize",
tokenEndpoint: "/token",
clientRegistrationEndpoint: "/register",
defaultHandler: new GitHubHandler({
clientId: (env) => env.GITHUB_CLIENT_ID,
clientSecret: (env) => env.GITHUB_CLIENT_SECRET,
scopes: ["repo", "user:email"],
context: async (accessToken) => {
// Fetch user info from GitHub
const octokit = new Octokit({ auth: accessToken });
const { data: user } = await octokit.rest.users.getAuthenticated();
return {
login: user.login,
email: user.email,
accessToken
};
}
}),
kv: (env) => env.OAUTH_KV,
apiHandlers: {
"/sse": MyMCP.serveSSE("/sse"),
"/mcp": MyMCP.serve("/mcp")
},
allowConsentScreen: true,
allowDynamicClientRegistration: true
});
所需绑定:
{
"kv_namespaces": [
{ "binding": "OAUTH_KV", "id": "YOUR_KV_ID" }
]
}
安全性:✅✅ 安全,可用于生产环境
模式 4:使用 DCR 的远程 OAuth
适用场景:完整的 OAuth 提供方、自定义授权页面
工作原理:你的 Worker 就是 OAuth 提供方
模板:参见 Cloudflare 的 remote-mcp-authkit 演示
设置:较复杂,需要完整实现 OAuth 2.1
安全性:✅✅✅ 最安全,完全可控
使用 Durable Objects 构建有状态的 MCP 服务
当 MCP 服务需要以下功能时,请使用 Durable Objects:
- 每会话持久状态
- 对话历史
- 游戏状态(国际象棋、井字棋)
- 缓存的 API 响应
- 用户偏好设置
存储 API 模式
模板:templates/mcp-stateful-do.ts
存储值:
await this.state.storage.put("key", "value");
await this.state.storage.put("user_prefs", { theme: "dark" });
获取值:
const value = await this.state.storage.get<string>("key");
const prefs = await this.state.storage.get<object>("user_prefs");
列出键:
const allKeys = await this.state.storage.list();
删除键:
await this.state.storage.delete("key");
配置
wrangler.jsonc:
{
"durable_objects": {
"bindings": [
{
"name": "MY_MCP",
"class_name": "MyMCP",
"script_name": "my-mcp-server"
}
]
},
"migrations": [
{ "tag": "v1", "new_classes": ["MyMCP"] }
]
}
重要:首次部署时必须执行迁移!
用于成本优化的 WebSocket 休眠
问题:长时间运行的 WebSocket 连接会消耗 CPU 时间
解决方案:WebSocket 休眠 API 会在连接空闲时将其挂起
模式
序列化元数据(在休眠期间保留数据):
webSocket.serializeAttachment({
userId: "123",
sessionId: "abc",
connectedAt: Date.now()
});
唤醒时检索:
const metadata = webSocket.deserializeAttachment();
console.log(metadata.userId); // "123"
持久化状态的存储:
// ❌ DON'T: In-memory state lost on hibernation
this.userId = "123";
// ✅ DO: Use storage API
await this.state.storage.put("userId", "123");
成本节省
未启用休眠:
- 1000 个并发 WebSocket × 10ms CPU/秒 = 10 CPU-秒/秒
- 成本:约 0.50 美元/天
启用休眠后:
- 仅在收到消息时使用 CPU(99% 的空闲时间处于挂起状态)
- 成本:约 0.01 美元/天(降低 50 倍!)
Worker 和 Durable Objects 基础知识
可独立使用的自包含章节
Worker 导出模式
Worker 必须导出 fetch 处理程序:
export default {
fetch(request: Request, env: Env, ctx: ExecutionContext): Response | Promise<Response> {
// Handle request
return new Response("Hello");
}
};
Durable Objects 类结构
DO 继承 McpAgent(用于 MCP 服务):
export class MyMCP extends McpAgent<Env> {
constructor(state: DurableObjectState, env: Env) {
super(state, env);
}
// Your methods here
}
绑定配置
环境绑定让 Worker 能够访问资源:
{
"kv_namespaces": [{ "binding": "MY_KV", "id": "..." }],
"durable_objects": {
"bindings": [{ "name": "MY_DO", "class_name": "MyDO" }]
},
"r2_buckets": [{ "binding": "MY_BUCKET", "bucket_name": "..." }]
}
在代码中访问:
env.MY_KV.get("key");
env.MY_DO.idFromName("session-123").getStub(env);
env.MY_BUCKET.get("file.txt");
部署与测试
本地开发
# Start dev server (uses Miniflare for local DOs)
npm run dev
# Start dev server with remote Durable Objects (more accurate)
npx wrangler dev --remote
访问地址:http://localhost:8788/sse
使用 MCP Inspector 测试
npx @modelcontextprotocol/inspector@latest
- 打开
http://localhost:5173 - 输入 MCP 服务 URL
- 点击“Connect”
- 使用“List Tools”查看可用工具
- 使用参数测试工具调用
部署到 Cloudflare
# First time: Login
npx wrangler login
# Deploy
npx wrangler deploy
# Check deployment
npx wrangler tail
你的服务已上线,地址为:
https://my-mcp-server.YOUR_ACCOUNT.workers.dev/sse
连接 Claude Desktop
~/.config/claude/claude_desktop_config.json(Linux/Mac):
{
"mcpServers": {
"my-mcp": {
"url": "https://my-mcp-server.your-account.workers.dev/sse"
}
}
}
%APPDATA%/Claude/claude_desktop_config.json(Windows)
使用 OAuth:
{
"mcpServers": {
"my-mcp": {
"url": "https://my-mcp-oauth.your-account.workers.dev/sse",
"auth": {
"type": "oauth",
"authorizationUrl": "https://my-mcp-oauth.your-account.workers.dev/authorize",
"tokenUrl": "https://my-mcp-oauth.your-account.workers.dev/token"
}
}
}
}
更改配置后,重启 Claude Desktop。
常见模式
API 代理 MCP 服务
使用场景:将外部 API 封装为 MCP 工具
模式:
this.server.tool(
"search_wikipedia",
"Search Wikipedia for a topic",
{ query: z.string() },
async ({ query }) => {
const response = await fetch(
`https://en.wikipedia.org/api/rest_v1/page/summary/${encodeURIComponent(query)}`
);
const data = await response.json();
return {
content: [{
type: "text",
text: data.extract
}]
};
}
);
数据库支持的工具
使用场景:查询 D1、KV 或外部数据库
模式:
this.server.tool(
"get_user",
"Get user details from database",
{ userId: z.string() },
async ({ userId }) => {
// Query Durable Objects storage
const user = await this.state.storage.get<User>(`user:${userId}`);
// Or query D1 database
const result = await env.DB.prepare(
"SELECT * FROM users WHERE id = ?"
).bind(userId).first();
return {
content: [{
type: "text",
text: JSON.stringify(user || result, null, 2)
}]
};
}
);
多工具协作
使用场景:调用其他工具的工具
模式:
// Store result from first tool
await this.state.storage.put("last_search", result);
// Second tool reads it
const lastSearch = await this.state.storage.get("last_search");
缓存策略
使用场景:缓存开销较大的 API 调用
模式:
this.server.tool(
"get_weather",
"Get weather (cached 5 minutes)",
{ city: z.string() },
async ({ city }) => {
const cacheKey = `weather:${city}`;
const cached = await this.state.storage.get<CachedWeather>(cacheKey);
// Check cache freshness
if (cached && Date.now() - cached.timestamp < 5 * 60 * 1000) {
return {
content: [{ type: "text", text: cached.data }]
};
}
// Fetch fresh data
const weather = await fetchWeatherAPI(city);
// Cache it
await this.state.storage.put(cacheKey, {
data: weather,
timestamp: Date.now()
});
return {
content: [{ type: "text", text: weather }]
};
}
);
使用 Durable Objects 进行速率限制
使用场景:防止滥用,遵守上游速率限制
模式:
async rateLimit(key: string, maxRequests: number, windowMs: number): Promise<boolean> {
const now = Date.now();
const requests = await this.state.storage.get<number[]>(`ratelimit:${key}`) || [];
// Remove old requests outside window
const recentRequests = requests.filter(ts => now - ts < windowMs);
if (recentRequests.length >= maxRequests) {
return false; // Rate limited
}
// Add this request
recentRequests.push(now);
await this.state.storage.put(`ratelimit:${key}`, recentRequests);
return true; // Allowed
}
// Use in tool
if (!await this.rateLimit(userId, 10, 60 * 1000)) {
return {
content: [{ type: "text", text: "Rate limit exceeded (10 requests/minute)" }],
isError: true
};
}
15 个已知错误(及解决方案)
1. 未导出 McpAgent 类
错误:TypeError: Cannot read properties of undefined (reading 'serve')
原因:忘记导出 McpAgent 类
解决方案:
export class MyMCP extends McpAgent { ... } // ✅ Must export
export default { fetch() { ... } }
2. 传输方式不匹配
错误:Connection failed: Unexpected response format
原因:客户端期望 /sse,但服务端只提供 /mcp
解决方案:同时提供两种传输方式(参见“传输方式”部分)
3. OAuth 重定向 URI 不匹配
错误:OAuth error: redirect_uri does not match
原因:客户端配置使用 localhost,但服务已部署到 workers.dev
解决方案:部署后更新 claude_desktop_config.json
4. WebSocket 休眠导致状态丢失
错误:重新连接后工具调用失败,并提示“state not found”
原因:休眠时内存中的状态被清除
解决方案:使用 this.state.storage,而不是实例属性
5. 缺少 Durable Objects 绑定
错误:Error: Cannot read properties of undefined (reading 'idFromName')
原因:忘记在 wrangler.jsonc 中配置 DO 绑定
解决方案:添加绑定(参见“有状态 MCP 服务”部分)
6. 未定义迁移
错误:Error: Durable Object class MyMCP has no migration defined
原因:首次部署 DO 时需要迁移
解决方案:
{
"migrations": [
{ "tag": "v1", "new_classes": ["MyMCP"] }
]
}
7. 远程 MCP 上的 CORS 错误
错误:Access to fetch at '...' blocked by CORS policy
原因:MCP 服务未返回 CORS 标头
解决方案:使用 OAuthProvider(会处理 CORS),或手动添加标头
8. 客户端配置格式错误
错误:Claude Desktop 无法识别服务
原因:claude_desktop_config.json 中的 JSON 格式错误
解决方案:正确格式请参见“连接 Claude Desktop”部分
9. 未使用 serializeAttachment()
错误:休眠唤醒时丢失 WebSocket 元数据
原因:未使用 serializeAttachment()
解决方案:参见 WebSocket 休眠部分
10. OAuth 同意屏幕已禁用
安全风险:用户看不到权限
原因:在生产环境中设置了 allowConsentScreen: false
解决方案:在生产环境中始终设置 allowConsentScreen: true
11. 缺少 JWT 签名密钥
错误:Error: JWT_SIGNING_KEY environment variable not set
原因:OAuth Provider 需要签名密钥
解决方案:
openssl rand -base64 32
# Add to wrangler.jsonc vars
12. 未配置环境变量
错误:env.MY_VAR is undefined
原因:变量已添加到 .dev.vars,但未添加到 wrangler.jsonc
解决方案:将其添加到 wrangler.jsonc 的 "vars" 部分
13. 工具架构验证错误
错误:ZodError: Invalid input type
原因:客户端发送字符串,但架构需要数字
解决方案:使用 Zod 转换:
z.string().transform(val => parseInt(val, 10))
14. 多个传输端点冲突
错误:添加 /mcp 后,/sse 返回 404
原因:路径匹配不正确
解决方案:使用 startsWith() 或精确匹配
15. 使用 Miniflare 进行本地测试的限制
错误:OAuth 流程在本地开发环境中失败
原因:Miniflare 不支持所有 DO 功能
解决方案:使用 npx wrangler dev --remote 以获得完整的 DO 支持
配置参考
完整的 wrangler.jsonc(所有功能)
{
"name": "my-mcp-server",
"main": "src/index.ts",
"compatibility_date": "2025-01-01",
"compatibility_flags": ["nodejs_compat"],
"account_id": "YOUR_ACCOUNT_ID",
"vars": {
"ENVIRONMENT": "production",
"GITHUB_CLIENT_ID": "optional-pre-configured-id"
},
"kv_namespaces": [
{
"binding": "OAUTH_KV",
"id": "YOUR_KV_ID",
"preview_id": "YOUR_PREVIEW_KV_ID"
}
],
"durable_objects": {
"bindings": [
{
"name": "MY_MCP",
"class_name": "MyMCP",
"script_name": "my-mcp-server"
}
]
},
"migrations": [
{ "tag": "v1", "new_classes": ["MyMCP"] }
],
"node_compat": true
}
完整的 package.json
参见 templates/package.json
完整的 claude_desktop_config.json
参见 templates/claude_desktop_config.json
其他资源
官方文档
- Cloudflare Agents:https://developers.cloudflare.com/agents/
- MCP 规范:https://modelcontextprotocol.io/
- workers-oauth-provider:https://github.com/cloudflare/workers-oauth-provider
- Durable Objects:https://developers.cloudflare.com/durable-objects/
官方示例
- Cloudflare AI 演示:https://github.com/cloudflare/ai/tree/main/demos
- 13 个 MCP 服务:https://blog.cloudflare.com/thirteen-new-mcp-servers-from-cloudflare/
工具
- MCP Inspector:https://github.com/modelcontextprotocol/inspector
- Wrangler CLI:https://developers.cloudflare.com/workers/wrangler/
不适用此技能的情况
以下情况请勿使用此技能:
- 构建 Python MCP 服务(请改用
fastmcp技能) - 构建仅限本地使用的 MCP 服务(请改用
typescript-mcp技能) - 需要使用非 Cloudflare 托管服务(如 AWS Lambda、GCP 等)
- 使用 Claude.ai 网页界面的技能(与 MCP 不同)
此技能专用于:TypeScript + Cloudflare Workers + 远程 MCP
版本信息
- @modelcontextprotocol/sdk:1.21.0
- @cloudflare/workers-oauth-provider:0.0.13
- agents(Cloudflare Agents SDK):0.2.20
- 上次验证:2025-11-04
已通过生产环境测试:基于 Cloudflare 官方 MCP 服务(mcp-server-cloudflare、workers-mcp)
Token 效率
不使用此技能时:
- 查阅分散的文档:约 10k 个 token
- 调试 15 个错误:约 30k 个 token
- 总计:约 40k 个 token
使用此技能时:
- 阅读技能文档:约 4k 个 token
- 复制模板:约 1k 个 token
- 总计:约 5k 个 token
节省:约 87%(40k → 5k 个 token)
可预防的错误:15 个(预防率 100%)
有疑问?请查阅:
references/authentication.md- 身份验证模式对比references/transport.md- SSE 与 HTTP 的技术细节references/oauth-providers.md- GitHub、Google、Azure 配置references/common-issues.md- 错误排查深入指南references/official-examples.md- Cloudflare 示例精选链接