building-mcp-server-on-cloudflare
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseBuilding MCP Servers on Cloudflare
在Cloudflare上构建MCP服务器
Creates production-ready Model Context Protocol servers on Cloudflare Workers with tools, authentication, and deployment.
在Cloudflare Workers上创建可用于生产环境的Model Context Protocol(MCP)服务器,包含工具、认证和部署功能。
When to Use
适用场景
- User wants to build a remote MCP server
- User needs to expose tools via MCP
- User asks about MCP authentication or OAuth
- User wants to deploy MCP to Cloudflare Workers
- 用户想要构建远程MCP服务器
- 用户需要通过MCP暴露工具
- 用户询问MCP认证或OAuth相关问题
- 用户想要将MCP部署至Cloudflare Workers
Prerequisites
前置条件
- Cloudflare account with Workers enabled
- Node.js 18+ and npm/pnpm/yarn
- Wrangler CLI ()
npm install -g wrangler
- 已启用Workers的Cloudflare账户
- Node.js 18+ 及 npm/pnpm/yarn
- Wrangler CLI()
npm install -g wrangler
Quick Start
快速开始
Option 1: Public Server (No Auth)
选项1:公开服务器(无认证)
bash
npm create cloudflare@latest -- my-mcp-server \
--template=cloudflare/ai/demos/remote-mcp-authless
cd my-mcp-server
npm startServer runs at
http://localhost:8788/mcpbash
npm create cloudflare@latest -- my-mcp-server \
--template=cloudflare/ai/demos/remote-mcp-authless
cd my-mcp-server
npm start服务器运行在
http://localhost:8788/mcpOption 2: Authenticated Server (OAuth)
选项2:认证服务器(OAuth)
bash
npm create cloudflare@latest -- my-mcp-server \
--template=cloudflare/ai/demos/remote-mcp-github-oauth
cd my-mcp-serverRequires OAuth app setup. See references/oauth-setup.md.
bash
npm create cloudflare@latest -- my-mcp-server \
--template=cloudflare/ai/demos/remote-mcp-github-oauth
cd my-mcp-server需要设置OAuth应用。请查看 references/oauth-setup.md。
Core Workflow
核心工作流
Step 1: Define Tools
步骤1:定义工具
Tools are functions MCP clients can call. Define them using :
server.tool()typescript
import { McpAgent } from "agents/mcp";
import { z } from "zod";
export class MyMCP extends McpAgent {
server = new Server({ name: "my-mcp", version: "1.0.0" });
async init() {
// Simple tool with parameters
this.server.tool(
"add",
{ a: z.number(), b: z.number() },
async ({ a, b }) => ({
content: [{ type: "text", text: String(a + b) }],
})
);
// Tool that calls external API
this.server.tool(
"get_weather",
{ city: z.string() },
async ({ city }) => {
const response = await fetch(`https://api.weather.com/${city}`);
const data = await response.json();
return {
content: [{ type: "text", text: JSON.stringify(data) }],
};
}
);
}
}工具是MCP客户端可以调用的函数。使用 定义工具:
server.tool()typescript
import { McpAgent } from "agents/mcp";
import { z } from "zod";
export class MyMCP extends McpAgent {
server = new Server({ name: "my-mcp", version: "1.0.0" });
async init() {
// 带参数的简单工具
this.server.tool(
"add",
{ a: z.number(), b: z.number() },
async ({ a, b }) => ({
content: [{ type: "text", text: String(a + b) }],
})
);
// 调用外部API的工具
this.server.tool(
"get_weather",
{ city: z.string() },
async ({ city }) => {
const response = await fetch(`https://api.weather.com/${city}`);
const data = await response.json();
return {
content: [{ type: "text", text: JSON.stringify(data) }],
};
}
);
}
}Step 2: Configure Entry Point
步骤2:配置入口点
Public server ():
src/index.tstypescript
import { MyMCP } from "./mcp";
export default {
fetch(request: Request, env: Env, ctx: ExecutionContext) {
const url = new URL(request.url);
if (url.pathname === "/mcp") {
return MyMCP.serveSSE("/mcp").fetch(request, env, ctx);
}
return new Response("MCP Server", { status: 200 });
},
};
export { MyMCP };Authenticated server — See references/oauth-setup.md.
公开服务器():
src/index.tstypescript
import { MyMCP } from "./mcp";
export default {
fetch(request: Request, env: Env, ctx: ExecutionContext) {
const url = new URL(request.url);
if (url.pathname === "/mcp") {
return MyMCP.serveSSE("/mcp").fetch(request, env, ctx);
}
return new Response("MCP Server", { status: 200 });
},
};
export { MyMCP };认证服务器 — 请查看 references/oauth-setup.md。
Step 3: Test Locally
步骤3:本地测试
bash
undefinedbash
undefinedStart server
启动服务器
npm start
npm start
In another terminal, test with MCP Inspector
在另一个终端中,使用MCP Inspector进行测试
npx @modelcontextprotocol/inspector@latest
npx @modelcontextprotocol/inspector@latest
Open http://localhost:5173, enter http://localhost:8788/mcp
undefinedundefinedStep 4: Deploy
步骤4:部署
bash
npx wrangler deployServer accessible at
https://[worker-name].[account].workers.dev/mcpbash
npx wrangler deploy服务器可通过 访问
https://[worker-name].[account].workers.dev/mcpStep 5: Connect Clients
步骤5:连接客户端
Claude Desktop ():
claude_desktop_config.jsonjson
{
"mcpServers": {
"my-server": {
"command": "npx",
"args": ["mcp-remote", "https://my-mcp.workers.dev/mcp"]
}
}
}Restart Claude Desktop after updating config.
Claude桌面端():
claude_desktop_config.jsonjson
{
"mcpServers": {
"my-server": {
"command": "npx",
"args": ["mcp-remote", "https://my-mcp.workers.dev/mcp"]
}
}
}更新配置后重启Claude桌面端。
Tool Patterns
工具模式
Return Types
返回类型
typescript
// Text response
return { content: [{ type: "text", text: "result" }] };
// Multiple content items
return {
content: [
{ type: "text", text: "Here's the data:" },
{ type: "text", text: JSON.stringify(data, null, 2) },
],
};typescript
// 文本响应
return { content: [{ type: "text", text: "result" }] };
// 多个内容项
return {
content: [
{ type: "text", text: "以下是数据:" },
{ type: "text", text: JSON.stringify(data, null, 2) },
],
};Input Validation with Zod
使用Zod进行输入验证
typescript
this.server.tool(
"create_user",
{
email: z.string().email(),
name: z.string().min(1).max(100),
role: z.enum(["admin", "user", "guest"]),
age: z.number().int().min(0).optional(),
},
async (params) => {
// params are fully typed and validated
}
);typescript
this.server.tool(
"create_user",
{
email: z.string().email(),
name: z.string().min(1).max(100),
role: z.enum(["admin", "user", "guest"]),
age: z.number().int().min(0).optional(),
},
async (params) => {
// 参数已完全类型化并验证
}
);Accessing Environment/Bindings
访问环境/绑定资源
typescript
export class MyMCP extends McpAgent<Env> {
async init() {
this.server.tool("query_db", { sql: z.string() }, async ({ sql }) => {
// Access D1 binding
const result = await this.env.DB.prepare(sql).all();
return { content: [{ type: "text", text: JSON.stringify(result) }] };
});
}
}typescript
export class MyMCP extends McpAgent<Env> {
async init() {
this.server.tool("query_db", { sql: z.string() }, async ({ sql }) => {
// 访问D1绑定资源
const result = await this.env.DB.prepare(sql).all();
return { content: [{ type: "text", text: JSON.stringify(result) }] };
});
}
}Authentication
认证
For OAuth-protected servers, see references/oauth-setup.md.
Supported providers:
- GitHub
- Auth0
- Stytch
- WorkOS
- Any OAuth 2.0 compliant provider
如需搭建受OAuth保护的服务器,请查看 references/oauth-setup.md。
支持的提供商:
- GitHub
- Auth0
- Stytch
- WorkOS
- 任何兼容OAuth 2.0的提供商
Wrangler Configuration
Wrangler配置
Minimal :
wrangler.tomltoml
name = "my-mcp-server"
main = "src/index.ts"
compatibility_date = "2024-12-01"
[durable_objects]
bindings = [{ name = "MCP", class_name = "MyMCP" }]
[[migrations]]
tag = "v1"
new_classes = ["MyMCP"]With bindings (D1, KV, etc.):
toml
[[d1_databases]]
binding = "DB"
database_name = "my-db"
database_id = "xxx"
[[kv_namespaces]]
binding = "KV"
id = "xxx"最小化 :
wrangler.tomltoml
name = "my-mcp-server"
main = "src/index.ts"
compatibility_date = "2024-12-01"
[durable_objects]
bindings = [{ name = "MCP", class_name = "MyMCP" }]
[[migrations]]
tag = "v1"
new_classes = ["MyMCP"]带绑定资源(D1、KV等)的配置:
toml
[[d1_databases]]
binding = "DB"
database_name = "my-db"
database_id = "xxx"
[[kv_namespaces]]
binding = "KV"
id = "xxx"Common Issues
常见问题
"Tool not found" in Client
客户端中出现「工具未找到」
- Verify tool name matches exactly (case-sensitive)
- Ensure registers tools before connections
init() - Check server logs:
wrangler tail
- 确认工具名称完全匹配(区分大小写)
- 确保在建立连接前已注册工具
init() - 查看服务器日志:
wrangler tail
Connection Fails
连接失败
- Confirm endpoint path is
/mcp - Check CORS if browser-based client
- Verify Worker is deployed:
wrangler deployments list
- 确认端点路径为
/mcp - 若为基于浏览器的客户端,请检查CORS设置
- 验证Worker已部署:
wrangler deployments list
OAuth Redirect Errors
OAuth重定向错误
- Callback URL must match OAuth app config exactly
- Check and
GITHUB_CLIENT_IDare setGITHUB_CLIENT_SECRET - For local dev, use
http://localhost:8788/callback
- 回调URL必须与OAuth应用配置完全匹配
- 检查和
GITHUB_CLIENT_ID是否已设置GITHUB_CLIENT_SECRET - 本地开发时,请使用
http://localhost:8788/callback
References
参考资料
- references/examples.md — Official templates and production examples
- references/oauth-setup.md — OAuth provider configuration
- references/tool-patterns.md — Advanced tool examples
- references/troubleshooting.md — Error codes and fixes
- references/examples.md — 官方模板和生产环境示例
- references/oauth-setup.md — OAuth提供商配置
- references/tool-patterns.md — 高级工具示例
- references/troubleshooting.md — 错误代码及修复方案