TypeScriptMCP服务器构建技能Skill typescript-mcp

这个技能用于在Cloudflare Workers上使用TypeScript构建生产就绪的Model Context Protocol (MCP) 服务器,提供工具、资源和提示的实现模式,防止10多种常见错误,支持认证和云服务集成,适用于API集成、外部工具暴露或无服务器边缘部署,关键词包括MCP、TypeScript、Cloudflare Workers、AI工具、服务器部署、认证、错误预防。

AI应用 0 次安装 0 次浏览 更新于 3/20/2026

名称:typescript-mcp 描述:| 当在Cloudflare Workers上使用TypeScript构建MCP(模型上下文协议)服务器时使用此技能。此技能提供生产测试的模式,用于使用官方@modelcontextprotocol/sdk实现工具、资源和提示。它防止10多种常见错误,包括导出语法问题、模式验证失败、未关闭传输导致的内存泄漏、CORS配置错误和认证漏洞。当开发人员需要无状态MCP服务器用于API集成、外部工具暴露或无服务器边缘部署时,应使用此技能。对于具有WebSocket和持久存储的有状态代理,请考虑使用Cloudflare Agents SDK。支持多种认证方法(API密钥、OAuth、零信任)、Cloudflare服务集成(D1、KV、R2、Vectorize)和全面的测试策略。与手动实现相比,生产测试可节省约70%的令牌。

关键词:mcp、模型上下文协议、typescript mcp、cloudflare workers mcp、mcp服务器、mcp工具、mcp资源、mcp sdk、@modelcontextprotocol/sdk、hono mcp、streamablehttpservertransport、mcp认证、mcp cloudflare、边缘mcp服务器、无服务器mcp、typescript mcp服务器、mcp api、llm工具、ai工具、cloudflare d1 mcp、cloudflare kv mcp、mcp测试、mcp部署、wrangler mcp、导出语法错误、模式验证错误、内存泄漏mcp、cors mcp、速率限制mcp 许可证:MIT 元数据: 版本:1.0.0 最后更新:2025-10-28 sdk版本:“@modelcontextprotocol/sdk@1.20.2” 平台:cloudflare-workers 生产测试:true 令牌效率:70% 错误防止:10+ 允许工具:[读取、写入、编辑、Bash、Grep、Glob]

在Cloudflare Workers上使用TypeScript构建MCP服务器

使用TypeScript构建生产就绪的Model Context Protocol(MCP)服务器,并将其部署在Cloudflare Workers上。此技能涵盖官方@modelcontextprotocol/sdk、HTTP传输设置、认证模式、Cloudflare服务集成和全面的错误预防。


何时使用此技能

在以下情况下使用此技能:

  • 构建MCP服务器以向LLM暴露API、工具或数据
  • 在Cloudflare Workers上部署无服务器MCP端点
  • 集成外部API作为MCP工具(REST、GraphQL、数据库)
  • 创建用于边缘部署的无状态MCP服务器
  • 通过MCP协议暴露Cloudflare服务(D1、KV、R2、Vectorize)
  • 实现具有API密钥、OAuth或零信任的认证MCP服务器
  • 构建具有资源和提示的多工具MCP服务器
  • 需要防止常见MCP错误的生产就绪模板

在以下情况下不要使用此技能

  • 构建Python MCP服务器(使用FastMCP技能)
  • 需要具有WebSocket的有状态代理(使用Cloudflare Agents SDK)
  • 需要具有SQLite存储的长时间运行持久代理(使用Durable Objects)
  • 构建本地CLI工具(使用stdio传输,非HTTP)

核心概念

MCP协议组件

1. 工具 - LLM可以调用的函数

  • 使用Zod定义输入/输出模式
  • 异步处理程序返回结构化内容
  • 可以调用外部API、数据库或计算

2. 资源 - 静态或动态数据暴露

  • 基于URI的寻址(例如config://app/settings
  • 模板支持参数(例如user://{userId}
  • 返回文本、JSON或二进制数据

3. 提示 - 预配置的提示模板

  • 提供可重复使用的对话启动器
  • 可以包含占位符和动态内容
  • 帮助标准化LLM交互

4. 补全(可选) - 参数自动补全

  • 建议工具参数的有效值
  • 改善开发者体验

快速开始

1. 基本MCP服务器模板

使用basic-mcp-server.ts模板实现最小工作服务器:

// 参见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'
});

// 注册一个简单工具
server.registerTool(
  'echo',
  {
    description: '回显输入文本',
    inputSchema: z.object({
      text: z.string().describe('要回显的文本')
    })
  },
  async ({ text }) => ({
    content: [{ type: 'text', text }]
  })
);

// HTTP端点设置
const app = new Hono();

app.post('/mcp', async (c) => {
  const transport = new StreamableHTTPServerTransport({
    sessionIdGenerator: undefined,
    enableJsonResponse: true
  });

  // 关键:在响应结束时关闭传输以防止内存泄漏
  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集成、计算):

// 示例:天气API工具
server.registerTool(
  'get-weather',
  {
    description: '获取城市当前天气',
    inputSchema: z.object({
      city: z.string().describe('城市名称'),
      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: `${city}的温度:${data.main.temp}°${units === 'metric' ? 'C' : 'F'}`
      }]
    };
  }
);

3. 资源服务器模板

使用resource-server.ts暴露数据:

import { ResourceTemplate } from '@modelcontextprotocol/sdk/types.js';

// 静态资源
server.registerResource(
  'config',
  new ResourceTemplate('config://app', { list: undefined }),
  { description: '应用程序配置' },
  async (uri) => ({
    contents: [{
      uri: uri.href,
      mimeType: 'application/json',
      text: JSON.stringify({ version: '1.0.0', features: ['tool1', 'tool2'] })
    }]
  })
);

// 带参数的动态资源
server.registerResource(
  'user-profile',
  new ResourceTemplate('user://{userId}', { list: undefined }),
  { description: '用户配置文件数据' },
  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密钥认证中间件
app.use('/mcp', async (c, next) => {
  const authHeader = c.req.header('Authorization');
  if (!authHeader || !authHeader.startsWith('Bearer ')) {
    return c.json({ error: '未授权' }, 401);
  }

  const apiKey = authHeader.replace('Bearer ', '');
  const isValid = await c.env.MCP_API_KEYS.get(`key:${apiKey}`);

  if (!isValid) {
    return c.json({ error: '无效API密钥' }, 403);
  }

  await next();
});

app.post('/mcp', async (c) => {
  // MCP服务器逻辑(用户已认证)
  // ... 传输设置和处理
});

认证模式

模式1:API密钥(推荐用于大多数情况)

设置

  1. 创建KV命名空间:wrangler kv namespace create MCP_API_KEYS
  2. 添加到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;
}

管理密钥

# 添加密钥
wrangler kv key put --binding=MCP_API_KEYS "key:abc123" "true"

# 撤销密钥
wrangler kv key delete --binding=MCP_API_KEYS "key:abc123"

模式2:Cloudflare零信任访问

import { verifyJWT } from '@cloudflare/workers-jwt';

const jwt = c.req.header('Cf-Access-Jwt-Assertion');
if (!jwt) {
  return c.json({ error: '访问被拒绝' }, 403);
}

const payload = await verifyJWT(jwt, c.env.CF_ACCESS_TEAM_DOMAIN);
// 用户通过Cloudflare Access认证

模式3:OAuth 2.0

完整OAuth实现参见references/authentication-guide.md


Cloudflare服务集成

D1数据库工具示例

server.registerTool(
  'query-database',
  {
    description: '在D1数据库上执行SQL查询',
    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: '通过键检索缓存值',
    inputSchema: z.object({ key: z.string() })
  },
  async ({ key }, env) => {
    const value = await env.CACHE.get(key);
    return {
      content: [{ type: 'text', text: value || '未找到键' }]
    };
  }
);

R2对象存储工具示例

server.registerTool(
  'upload-file',
  {
    description: '上传文件到R2存储桶',
    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: `文件已上传:${key}` }]
    };
  }
);

Vectorize搜索工具示例

server.registerTool(
  'semantic-search',
  {
    description: '搜索向量数据库',
    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('计算器工具', () => {
  it('应该将两个数字相加', async () => {
    const server = new McpServer({ name: 'test', version: '1.0.0' });

    server.registerTool(
      'add',
      {
        description: '将两个数字相加',
        inputSchema: z.object({
          a: z.number(),
          b: z.number()
        })
      },
      async ({ a, b }) => ({
        content: [{ type: 'text', text: String(a + b) }]
      })
    );

    // 测试工具执行
    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检查器进行集成测试

# 本地运行服务器
npm run dev

# 在另一个终端中
npx @modelcontextprotocol/inspector

# 连接到:http://localhost:8787/mcp

3. 使用Claude Agent SDK进行端到端测试

完整测试模式参见references/testing-guide.md


已知问题预防

此技能防止官方MCP SDK和Cloudflare仓库中记录的10多种生产问题:

问题#1:导出语法问题(关键)

错误“无法读取未定义的属性(读取'map')” 来源:honojs/hono#3955, honojs/vite-plugins#237 原因:Vite构建中的错误导出格式导致神秘错误 预防

// ❌ 错误 - 导致构建错误
export default { fetch: app.fetch };

// ✅ 正确 - 直接导出
export default app;

问题#2:未关闭的传输连接

错误:内存泄漏、挂起连接 来源:SDK维护者的最佳实践 原因:未在请求结束时关闭StreamableHTTPServerTransport 预防

app.post('/mcp', async (c) => {
  const transport = new StreamableHTTPServerTransport(/*...*/);

  // 关键:始终在响应结束时关闭
  c.res.raw.on('close', () => transport.close());

  // ... 处理请求
});

问题#3:工具模式验证失败

错误ListTools请求处理程序无法生成inputSchema 来源:GitHub modelcontextprotocol/typescript-sdk#1028 原因:Zod模式未正确转换为JSON模式 预防

// ✅ 正确 - SDK自动处理Zod模式转换
server.registerTool(
  'tool-name',
  {
    inputSchema: z.object({ a: z.number() })
  },
  handler
);

// 除非自定义验证,否则无需手动zodToJsonSchema()

问题#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和args.b正确类型化并传递
    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: '超过速率限制' }, 429);
  }

  await c.env.CACHE.put(
    rateLimitKey,
    String((parseInt(count || '0') + 1)),
    { expirationTtl: 60 }
  );

  // 继续...
});

问题#7:TypeScript编译内存问题

错误tsc构建期间内存不足 来源:GitHub modelcontextprotocol/typescript-sdk#985 原因:MCP SDK中大型依赖树 预防

# 添加到package.json脚本
"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安全最佳实践 原因:环境变量被记录或返回在响应中 预防

// ❌ 错误 - 暴露秘密
console.log('环境:', JSON.stringify(env));

// ✅ 正确 - 永不记录环境对象
try {
  // ... 使用env.SECRET_KEY
} catch (error) {
  // 不要在错误上下文中包含环境
  console.error('操作失败:', error.message);
}

部署工作流程

本地开发

# 安装依赖
npm install

# 使用Wrangler本地运行
npm run dev
# 或
wrangler dev

# 服务器可用:http://localhost:8787/mcp

生产部署

# 构建
npm run build

# 部署到Cloudflare Workers
wrangler deploy

# 部署到特定环境
wrangler deploy --env production

使用GitHub Actions的CI/CD

名称:部署MCP服务器
触发:
  推送:
    分支:[main]

任务:
  部署:
    运行环境:ubuntu-latest
    步骤:
      - 使用:actions/checkout@v4
      - 使用:actions/setup-node@v4
        带:
          node-version: '20'

      - 运行:npm ci
      - 运行:npm test

      - 名称:部署到Cloudflare Workers
        使用:cloudflare/wrangler-action@v3
        带:
          apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
          accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}

包版本(验证于2025-10-28)

{
  "依赖": {
    "@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"
  },
  "开发依赖": {
    "@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

  • 具有持久存储的有状态代理(SQLite高达1GB)
  • WebSocket支持用于实时双向通信
  • 具有对话历史的长时间运行会话
  • 具有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、零信任、JWT)
  • references/testing-guide.md - 单元测试、使用MCP检查器的集成测试、使用Claude Agent SDK的端到端测试
  • references/deployment-guide.md - Wrangler工作流程、环境管理、使用GitHub Actions的CI/CD
  • references/cloudflare-integration.md - 使用D1、KV、R2、Vectorize、Workers AI、Queues、Durable Objects
  • references/common-errors.md - 所有10多种错误的详细解决方案、根本原因和预防策略
  • references/cloudflare-agents-vs-standalone.md - 选择独立MCP和Cloudflare Agents SDK的决策矩阵

当Claude应加载这些时:当开发人员需要高级实现细节、调试帮助或架构指导时。

脚本(scripts/)

用于初始化和测试MCP服务器的自动化脚本:

  • scripts/init-mcp-server.sh - 使用依赖项、wrangler配置和模板选择初始化新MCP服务器项目
  • scripts/test-mcp-connection.sh - 测试MCP服务器连接并验证工具/资源端点

当Claude应使用这些时:当设置新项目或调试连接问题时。


官方文档

示例服务器


关键规则

始终做

✅ 在响应结束时关闭传输以防止内存泄漏 ✅ 使用直接导出语法(export default app)而不是对象包装器 ✅ 为生产服务器实施认证 ✅ 添加速率限制以防止API滥用 ✅ 使用Zod模式进行类型安全的工具定义 ✅ 部署前使用MCP检查器测试 ✅ 更新到SDK v1.20.2+以获取安全修复 ✅ 使用清晰描述记录所有工具 ✅ 优雅处理错误并返回有意义消息 ✅ 对秘密使用环境变量(永不硬编码)

永不做

❌ 使用对象包装器导出(export default { fetch: app.fetch }) ❌ 忘记关闭StreamableHTTPServerTransport ❌ 生产中部署无认证 ❌ 记录环境变量或秘密 ❌ 使用CommonJS格式(必须使用ES模块) ❌ 浏览器客户端跳过CORS配置 ❌ 硬编码API密钥或凭据 ❌ 返回原始错误对象(可能泄漏敏感数据) ❌ 未本地测试工具/资源就部署 ❌ 使用具有已知漏洞的过时SDK版本


完整设置检查列表

使用此检查列表验证您的MCP服务器设置:

  • [ ] SDK版本为1.20.2或更高
  • [ ] 导出语法正确(直接导出,非对象包装器)
  • [ ] 传输在响应结束时关闭
  • [ ] 已实施认证(如果生产)
  • [ ] 已配置速率限制(如果面向公众)
  • [ ] 已设置CORS头部(如果浏览器客户端)
  • [ ] 所有工具具有清晰描述和Zod模式
  • [ ] 对秘密使用环境变量
  • [ ] wrangler.jsonc包含所有必要绑定
  • [ ] 本地测试wrangler dev成功
  • [ ] MCP检查器可以连接并列出工具
  • [ ] 生产部署成功
  • [ ] 所有工具/资源返回预期响应

生产示例

此技能基于以下模式:


问题?故障?

  1. 查看references/common-errors.md进行故障排除
  2. 验证快速开始部分的所有步骤
  3. 使用MCP检查器测试:npx @modelcontextprotocol/inspector
  4. 查看官方文档:https://spec.modelcontextprotocol.io/
  5. 确保SDK版本为1.20.2或更高

最后更新:2025-10-28 SDK版本:@modelcontextprotocol/sdk@1.20.2 维护者:Claude技能仓库