关于 typescript-mcp
这项技能指导开发者使用 TypeScript 和官方 MCP SDK 构建 MCP 服务,并部署到 Cloudflare Workers。内容涵盖工具、资源、提示词、认证、测试和常见问题防范。
主要功能
- 01提供 MCP 服务模板
- 02配置 HTTP 传输
- 03实现 API Key、OAuth 和 Zero Trust 认证
- 04集成 Cloudflare 服务
- 05涵盖单元、集成和端到端测试
- 06说明部署及常见问题防范
适用场景
- 01将外部 API 封装为 MCP 工具
- 02在 Workers 上部署无状态 MCP 端点
- 03通过 MCP 暴露 Cloudflare D1、KV 或 R2
- 04为 MCP 服务添加认证与测试
MCP 相关
指导使用 `@modelcontextprotocol/sdk` 构建 MCP 服务,向 MCP 客户端提供工具、资源和提示词。涵盖 HTTP 传输与认证设置。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ jackspace/ claudeskillz --skill typescript-mcp安装后在 Claude Code 中输入/typescript-mcp确认已加载。
附带文件README.mdSKILL.json
详细介绍
Cloudflare Workers 上的 TypeScript MCP 服务
使用 TypeScript 构建可用于生产环境的模型上下文协议(MCP)服务,并将其部署到 Cloudflare Workers 上。本技能涵盖官方 @modelcontextprotocol/sdk、HTTP 传输设置、身份验证模式、Cloudflare 服务集成,以及全面的错误预防。
何时使用此技能
在以下情况下使用此技能:
- 构建 MCP 服务,向大模型公开 API、工具或数据
- 在 Cloudflare Workers 上部署 无服务器 MCP 端点
- 将 外部 API 集成为 MCP 工具(REST、GraphQL、数据库)
- 创建用于边缘部署的 无状态 MCP 服务
- 通过 MCP 协议公开 Cloudflare 服务(D1、KV、R2、Vectorize)
- 实现通过 API 密钥、OAuth 或 Zero Trust 进行身份验证的 MCP 服务
- 构建包含资源和提示词的 多工具 MCP 服务
- 需要能够避免常见 MCP 错误的 生产就绪模板
以下情况请勿使用此技能:
- 构建 Python MCP 服务(请改用 FastMCP 技能)
- 需要使用 WebSocket 的 有状态 Agent(请使用 Cloudflare Agents SDK)
- 想要使用 SQLite 存储的 长时间运行的持久 Agent(请使用 Durable Objects)
- 构建 本地命令行工具(请使用 stdio 传输,而非 HTTP)
核心概念
MCP 协议组件
1. 工具 - 大模型可以调用的函数
- 使用 Zod 定义输入/输出架构
- 异步处理程序返回结构化内容
- 可以调用外部 API、数据库或执行计算
2. 资源 - 静态或动态数据公开
- 基于 URI 的寻址(例如,
config://app/settings) - 模板支持参数(例如,
user://{userId}) - 返回文本、JSON 或二进制数据
3. 提示词 - 预配置的提示词模板
- 提供可重用的对话开场白
- 可以包含占位符和动态内容
- 帮助标准化与大模型的交互
4. 补全(可选)- 参数自动补全
- 为工具参数建议有效值
- 改善开发者体验
快速开始
1. 基本 MCP 服务模板
使用 basic-mcp-server.ts 模板创建最精简的可运行服务:
// See templates/basic-mcp-server.ts
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
import { Hono } from 'hono';
import { z } from 'zod';
const server = new McpServer({
name: 'my-mcp-server',
version: '1.0.0'
});
// Register a simple tool
server.registerTool(
'echo',
{
description: 'Echoes back the input text',
inputSchema: z.object({
text: z.string().describe('Text to echo back')
})
},
async ({ text }) => ({
content: [{ type: 'text', text }]
})
);
// HTTP endpoint setup
const app = new Hono();
app.post('/mcp', async (c) => {
const transport = new StreamableHTTPServerTransport({
sessionIdGenerator: undefined,
enableJsonResponse: true
});
// CRITICAL: Close transport on response end to prevent memory leaks
c.res.raw.on('close', () => transport.close());
await server.connect(transport);
await transport.handleRequest(c.req.raw, c.res.raw, await c.req.json());
return c.body(null);
});
export default app;
安装依赖:
npm install @modelcontextprotocol/sdk hono zod
npm install -D @cloudflare/workers-types wrangler typescript
部署:
wrangler deploy
2. 工具服务模板
使用 tool-server.ts 公开多个工具(API 集成、计算):
// Example: Weather API tool
server.registerTool(
'get-weather',
{
description: 'Fetches current weather for a city',
inputSchema: z.object({
city: z.string().describe('City name'),
units: z.enum(['metric', 'imperial']).default('metric')
})
},
async ({ city, units }, env) => {
const response = await fetch(
`https://api.openweathermap.org/data/2.5/weather?q=${city}&units=${units}&appid=${env.WEATHER_API_KEY}`
);
const data = await response.json();
return {
content: [{
type: 'text',
text: `Temperature in ${city}: ${data.main.temp}°${units === 'metric' ? 'C' : 'F'}`
}]
};
}
);
3. 资源服务模板
使用 resource-server.ts 公开数据:
import { ResourceTemplate } from '@modelcontextprotocol/sdk/types.js';
// Static resource
server.registerResource(
'config',
new ResourceTemplate('config://app', { list: undefined }),
{ description: 'Application configuration' },
async (uri) => ({
contents: [{
uri: uri.href,
mimeType: 'application/json',
text: JSON.stringify({ version: '1.0.0', features: ['tool1', 'tool2'] })
}]
})
);
// Dynamic resource with parameter
server.registerResource(
'user-profile',
new ResourceTemplate('user://{userId}', { list: undefined }),
{ description: 'User profile data' },
async (uri, { userId }, env) => {
const user = await env.DB.prepare('SELECT * FROM users WHERE id = ?').bind(userId).first();
return {
contents: [{
uri: uri.href,
mimeType: 'application/json',
text: JSON.stringify(user)
}]
};
}
);
4. 已通过身份验证的服务模板
使用 authenticated-server.ts 实现生产环境安全性:
import { Hono } from 'hono';
const app = new Hono();
// API Key authentication middleware
app.use('/mcp', async (c, next) => {
const authHeader = c.req.header('Authorization');
if (!authHeader || !authHeader.startsWith('Bearer ')) {
return c.json({ error: 'Unauthorized' }, 401);
}
const apiKey = authHeader.replace('Bearer ', '');
const isValid = await c.env.MCP_API_KEYS.get(`key:${apiKey}`);
if (!isValid) {
return c.json({ error: 'Invalid API key' }, 403);
}
await next();
});
app.post('/mcp', async (c) => {
// MCP server logic (user is authenticated)
// ... transport setup and handling
});
身份验证模式
模式 1:API 密钥(大多数情况下推荐)
设置:
- 创建 KV 命名空间:
wrangler kv namespace create MCP_API_KEYS - 添加到
wrangler.jsonc:
{
"kv_namespaces": [
{ "binding": "MCP_API_KEYS", "id": "YOUR_NAMESPACE_ID" }
]
}
实现:
async function verifyApiKey(key: string, env: Env): Promise<boolean> {
const storedKey = await env.MCP_API_KEYS.get(`key:${key}`);
return storedKey !== null;
}
管理密钥:
# Add key
wrangler kv key put --binding=MCP_API_KEYS "key:abc123" "true"
# Revoke key
wrangler kv key delete --binding=MCP_API_KEYS "key:abc123"
模式 2:Cloudflare Zero Trust Access
import { verifyJWT } from '@cloudflare/workers-jwt';
const jwt = c.req.header('Cf-Access-Jwt-Assertion');
if (!jwt) {
return c.json({ error: 'Access denied' }, 403);
}
const payload = await verifyJWT(jwt, c.env.CF_ACCESS_TEAM_DOMAIN);
// User authenticated via Cloudflare Access
模式 3:OAuth 2.0
完整的 OAuth 实现请参阅 references/authentication-guide.md。
Cloudflare 服务集成
D1 数据库工具示例
server.registerTool(
'query-database',
{
description: 'Executes SQL query on D1 database',
inputSchema: z.object({
query: z.string(),
params: z.array(z.union([z.string(), z.number()])).optional()
})
},
async ({ query, params }, env) => {
const result = await env.DB.prepare(query).bind(...(params || [])).all();
return {
content: [{
type: 'text',
text: JSON.stringify(result.results, null, 2)
}]
};
}
);
Wrangler 配置:
{
"d1_databases": [
{ "binding": "DB", "database_name": "my-db", "database_id": "..." }
]
}
KV 存储工具示例
server.registerTool(
'get-cache',
{
description: 'Retrieves cached value by key',
inputSchema: z.object({ key: z.string() })
},
async ({ key }, env) => {
const value = await env.CACHE.get(key);
return {
content: [{ type: 'text', text: value || 'Key not found' }]
};
}
);
R2 对象存储工具示例
server.registerTool(
'upload-file',
{
description: 'Uploads file to R2 bucket',
inputSchema: z.object({
key: z.string(),
content: z.string(),
contentType: z.string().optional()
})
},
async ({ key, content, contentType }, env) => {
await env.BUCKET.put(key, content, {
httpMetadata: { contentType: contentType || 'text/plain' }
});
return {
content: [{ type: 'text', text: `File uploaded: ${key}` }]
};
}
);
Vectorize 搜索工具示例
server.registerTool(
'semantic-search',
{
description: 'Searches vector database',
inputSchema: z.object({
query: z.string(),
topK: z.number().default(5)
})
},
async ({ query, topK }, env) => {
const embedding = await env.AI.run('@cf/baai/bge-base-en-v1.5', {
text: query
});
const results = await env.VECTORIZE.query(embedding.data[0], {
topK,
returnMetadata: true
});
return {
content: [{
type: 'text',
text: JSON.stringify(results.matches, null, 2)
}]
};
}
);
测试策略
1. 使用 Vitest 进行单元测试
import { describe, it, expect } from 'vitest';
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { z } from 'zod';
describe('Calculator Tool', () => {
it('should add two numbers', async () => {
const server = new McpServer({ name: 'test', version: '1.0.0' });
server.registerTool(
'add',
{
description: 'Adds two numbers',
inputSchema: z.object({
a: z.number(),
b: z.number()
})
},
async ({ a, b }) => ({
content: [{ type: 'text', text: String(a + b) }]
})
);
// Test tool execution
const result = await server.callTool('add', { a: 5, b: 3 });
expect(result.content[0].text).toBe('8');
});
});
安装:
npm install -D vitest @cloudflare/vitest-pool-workers
运行:
npx vitest
2. 使用 MCP Inspector 进行集成测试
# Run server locally
npm run dev
# In another terminal
npx @modelcontextprotocol/inspector
# Connect to: http://localhost:8787/mcp
3. 使用 Claude Agent SDK 进行端到端测试
全面的测试模式请参阅 references/testing-guide.md。
已知问题预防
此技能可预防官方 MCP SDK 和 Cloudflare 仓库中记录的 10 多个生产环境问题:
问题 #1:导出语法问题(严重)
错误:"Cannot read properties of undefined (reading 'map')"
来源:honojs/hono#3955、honojs/vite-plugins#237
原因:Vite 构建时导出格式不正确会导致难以排查的错误
预防措施:
// ❌ WRONG - Causes cryptic build errors
export default { fetch: app.fetch };
// ✅ CORRECT - Direct export
export default app;
问题 #2:传输连接未关闭
错误:内存泄漏、连接挂起 来源:SDK 维护者的最佳实践 原因:请求结束时未关闭 StreamableHTTPServerTransport 预防措施:
app.post('/mcp', async (c) => {
const transport = new StreamableHTTPServerTransport(/*...*/);
// CRITICAL: Always close on response end
c.res.raw.on('close', () => transport.close());
// ... handle request
});
问题 #3:工具架构验证失败
错误:ListTools request handler fails to generate inputSchema
来源:GitHub modelcontextprotocol/typescript-sdk#1028
原因:Zod 架构未正确转换为 JSON Schema
预防措施:
// ✅ CORRECT - SDK handles Zod schema conversion automatically
server.registerTool(
'tool-name',
{
inputSchema: z.object({ a: z.number() })
},
handler
);
// No need for manual zodToJsonSchema() unless custom validation
问题 #4:工具参数未传递给处理程序
错误:处理程序收到 undefined 参数
来源:GitHub modelcontextprotocol/typescript-sdk#1026
原因:注册与调用之间的架构类型不匹配
预防措施:
const schema = z.object({ a: z.number(), b: z.number() });
type Input = z.infer<typeof schema>;
server.registerTool(
'add',
{ inputSchema: schema },
async (args: Input) => {
// args.a and args.b properly typed and passed
return { content: [{ type: 'text', text: String(args.a + args.b) }] };
}
);
问题 #5:CORS 配置错误
错误:浏览器客户端无法连接到 MCP 服务 来源:常见的生产环境问题 原因:HTTP 传输缺少 CORS 标头 预防措施:
import { cors } from 'hono/cors';
app.use('/mcp', cors({
origin: ['http://localhost:3000', 'https://your-app.com'],
allowMethods: ['POST', 'OPTIONS'],
allowHeaders: ['Content-Type', 'Authorization']
}));
问题 #6:缺少速率限制
错误:API 滥用、易受 DDoS 攻击 来源:生产环境安全最佳实践 原因:MCP 端点没有速率限制 预防措施:
app.post('/mcp', async (c) => {
const ip = c.req.header('CF-Connecting-IP');
const rateLimitKey = `ratelimit:${ip}`;
const count = await c.env.CACHE.get(rateLimitKey);
if (count && parseInt(count) > 100) {
return c.json({ error: 'Rate limit exceeded' }, 429);
}
await c.env.CACHE.put(
rateLimitKey,
String((parseInt(count || '0') + 1)),
{ expirationTtl: 60 }
);
// Continue...
});
问题 #7:TypeScript 编译内存问题
错误:tsc 构建期间出现 Out of memory
来源:GitHub modelcontextprotocol/typescript-sdk#985
原因:MCP SDK 的依赖树较大
预防措施:
# Add to package.json scripts
"build": "NODE_OPTIONS='--max-old-space-size=4096' tsc && vite build"
问题 #8:UriTemplate ReDoS 漏洞
错误:服务器因恶意 URI 模式而挂起 来源:GitHub modelcontextprotocol/typescript-sdk#965(安全问题) 原因:URI 模板解析中的正则表达式拒绝服务 预防措施:将 SDK 更新至 v1.20.2 或更高版本(包含修复)
问题 #9:身份验证绕过
错误:未经身份验证即可访问 MCP 工具 来源:生产环境安全最佳实践 原因:缺少身份验证或身份验证实现不当 预防措施:生产环境中的服务始终应实现身份验证(参见“身份验证模式”部分)
问题 #10:环境变量泄露
错误:机密信息暴露在错误消息或日志中 来源:Cloudflare Workers 安全最佳实践 原因:环境变量被记录到日志中或在响应中返回 预防措施:
// ❌ WRONG - Exposes secrets
console.log('Env:', JSON.stringify(env));
// ✅ CORRECT - Never log env objects
try {
// ... use env.SECRET_KEY
} catch (error) {
// Don't include env in error context
console.error('Operation failed:', error.message);
}
部署工作流
本地开发
# Install dependencies
npm install
# Run locally with Wrangler
npm run dev
# or
wrangler dev
# Server available at: http://localhost:8787/mcp
生产环境部署
# Build
npm run build
# Deploy to Cloudflare Workers
wrangler deploy
# Deploy to specific environment
wrangler deploy --env production
使用 GitHub Actions 实现 CI/CD
name: Deploy MCP Server
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: npm test
- name: Deploy to Cloudflare Workers
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
软件包版本(已于 2025-10-28 验证)
{
"dependencies": {
"@modelcontextprotocol/sdk": "^1.20.2",
"@cloudflare/workers-types": "^4.20251011.0",
"hono": "^4.10.1",
"zod": "^3.23.8",
"zod-to-json-schema": "^3.24.1"
},
"devDependencies": {
"@cloudflare/vitest-pool-workers": "^0.5.29",
"vitest": "^3.0.0",
"wrangler": "^4.43.0",
"typescript": "^5.7.0"
}
}
何时改用 Cloudflare Agents SDK
在需要以下功能时使用 Cloudflare Agents MCP:
- 有状态 Agent,支持持久化存储(SQLite,最高 1GB)
- WebSocket 支持,实现实时双向通信
- 长时间运行的会话,并保留对话历史
- 定时 Agent 任务,使用 Durable Objects 警报
- 全球分发,并自动复制状态
在需要以下功能时使用 此技能(独立 TypeScript MCP):
- 无状态工具和 API 集成
- 边缘部署,冷启动延迟极低
- 简单的身份验证(API 密钥、OAuth)
- 按请求付费(无 Durable Objects 开销)
- 最高可移植性(适用于任何平台,而不仅限于 Cloudflare)
详细比较请参阅 references/cloudflare-agents-vs-standalone.md。
使用捆绑资源
模板(templates/)
所有模板均已达到生产就绪状态,并在 Cloudflare Workers 上经过测试:
templates/basic-mcp-server.ts- 最简可用服务(回显工具示例)templates/tool-server.ts- 多工具实现(API 集成、计算)templates/resource-server.ts- 仅包含资源的服务(静态和动态资源)templates/full-server.ts- 完整服务(工具 + 资源 + 提示词)templates/authenticated-server.ts- 带有 API 密钥身份验证的生产服务templates/wrangler.jsonc- 包含所有绑定项的 Cloudflare Workers 配置
Claude 应在以下情况下使用这些模板:创建新的 MCP 服务时,根据使用场景(仅工具、仅资源、需要身份验证或功能完整)复制合适的模板。
参考指南(references/)
关于高级主题的综合文档:
references/tool-patterns.md- 常见工具实现模式(API 封装、数据库查询、计算、文件操作)references/authentication-guide.md- 详细介绍所有身份验证方法(API 密钥、OAuth 2.0、Zero Trust、JWT)references/testing-guide.md- 单元测试、使用 MCP Inspector 进行集成测试、使用 Claude Agent SDK 进行端到端测试references/deployment-guide.md- Wrangler 工作流、环境管理、使用 GitHub Actions 的 CI/CDreferences/cloudflare-integration.md- 使用 D1、KV、R2、Vectorize、Workers AI、Queues、Durable Objectsreferences/common-errors.md- 详细介绍 10 种以上错误,包括解决方案、根本原因和预防策略references/cloudflare-agents-vs-standalone.md- 用于在独立 MCP 与 Cloudflare Agents SDK 之间进行选择的决策矩阵
Claude 应在以下情况下加载这些文档:开发者需要高级实现细节、调试帮助或架构指导时。
脚本(scripts/)
用于初始化和测试 MCP 服务的自动化脚本:
scripts/init-mcp-server.sh- 初始化新的 MCP 服务项目,配置依赖项、wrangler 配置和模板选择scripts/test-mcp-connection.sh- 测试 MCP 服务的连接,并验证工具/资源端点
Claude 应在以下情况下使用这些脚本:设置新项目或排查连接问题时。
官方文档
- MCP 规范:https://spec.modelcontextprotocol.io/
- TypeScript SDK:https://github.com/modelcontextprotocol/typescript-sdk
- Cloudflare Workers:https://developers.cloudflare.com/workers/
- Hono 框架:https://hono.dev/
- Context7 库 ID:
/websites/modelcontextprotocol(如果可用)
示例服务:
- 官方示例:https://github.com/modelcontextprotocol/servers
- Cloudflare MCP 服务:https://github.com/cloudflare/mcp-server-cloudflare
关键规则
务必做到
✅ 在响应结束时关闭传输,以防止内存泄漏
✅ 使用直接导出语法(export default app),而非对象包装
✅ 为生产服务实现身份验证
✅ 添加速率限制,防止 API 滥用
✅ 使用 Zod schema 定义类型安全的工具
✅ 在部署到生产环境前,使用 MCP Inspector 进行测试
✅ 更新至 SDK v1.20.2+,以获取安全修复
✅ 使用清晰的描述记录所有工具
✅ 妥善处理错误并返回有意义的信息
✅ 使用环境变量存储密钥(切勿硬编码)
切勿这样做
❌ 使用对象包装进行导出(export default { fetch: app.fetch })
❌ 忘记关闭 StreamableHTTPServerTransport
❌ 在生产环境中部署时不配置身份验证
❌ 记录环境变量或密钥
❌ 使用 CommonJS 格式(必须使用 ES modules)
❌ 忽略面向浏览器客户端的 CORS 配置
❌ 硬编码 API 密钥或凭据
❌ 返回原始错误对象(可能泄露敏感数据)
❌ 未在本地测试工具/资源便进行部署
❌ 使用存在已知漏洞的过时 SDK 版本
完整设置清单
使用此清单验证 MCP 服务设置:
- SDK 版本为 1.20.2 或更高版本
- 导出语法正确(直接导出,而非对象包装)
- 响应结束时关闭传输
- 已实现身份验证(用于生产环境时)
- 已配置速率限制(面向公众时)
- 已设置 CORS 标头(使用浏览器客户端时)
- 所有工具都有清晰的描述和 Zod 模式
- 使用环境变量存储机密信息
-
wrangler.jsonc包含所有必需的绑定 - 使用
wrangler dev本地测试成功 - MCP Inspector 可以连接并列出工具
- 生产环境部署成功
- 所有工具和资源都返回预期响应
生产示例
此技能基于以下模式:
- 官方 MCP TypeScript SDK 示例:https://github.com/modelcontextprotocol/servers
- Cloudflare MCP 服务:https://github.com/cloudflare/mcp-server-cloudflare
- 错误:0(已避免所有 10 多个已知问题)
- Token 节省:与手动实现相比约节省 70%
- 验证:✅ 所有模板均已在 Cloudflare Workers 上测试
有问题?遇到故障?
- 查看
references/common-errors.md以排查问题 - 确认已完成快速入门部分中的所有步骤
- 使用 MCP Inspector 测试:
npx @modelcontextprotocol/inspector - 查看官方文档:https://spec.modelcontextprotocol.io/
- 确保 SDK 版本为 1.20.2 或更高版本
最后更新:2025-10-28 SDK 版本:@modelcontextprotocol/[email protected] 维护者:Claude Skills Repository