mcpField
T
typescript-mcp

typescript-mcp

github.com/ovachiever开发5653 次安装48 周前更新
代码仓库

关于 typescript-mcp

面向在 Cloudflare Workers 上构建 TypeScript MCP 服务的开发者技能。提供模板及 HTTP 传输、身份验证、Cloudflare 服务、测试、部署和常见错误防范指南。

主要功能

  1. 01工具与资源服务模板
  2. 02Streamable HTTP 传输配置
  3. 03API 密钥、OAuth 和 Zero Trust 模式
  4. 04Cloudflare 服务集成示例
  5. 05测试与部署指南
  6. 06常见错误防范

适用场景

  1. 01将外部 API 暴露为 MCP 工具
  2. 02在 Workers 上构建无状态 MCP 端点
  3. 03为 MCP 服务添加身份验证
  4. 04测试并部署 TypeScript 服务

MCP 相关

指导使用官方 TypeScript SDK 实现 MCP 服务,向 MCP 客户端提供工具、资源和提示词。内容涵盖 HTTP 传输及在 Cloudflare Workers 上的部署。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/ovachiever/droid-tings --skill typescript-mcp

安装后在 Claude Code 中输入/typescript-mcp确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

README.md
.claude-plugin/
plugin.json
references/
authentication-guide.md
cloudflare-agents-vs-standalone.md
cloudflare-integration.md
common-errors.md
deployment-guide.md
testing-guide.md
tool-patterns.md
scripts/
init-mcp-server.sh
test-mcp-connection.sh
templates/
authenticated-server.ts
basic-mcp-server.ts
full-server.ts
resource-server.ts
tool-server.ts
wrangler.jsonc

详细介绍

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 密钥(大多数情况下推荐)

设置:

  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;
}

管理密钥:

# 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/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 - 初始化新的 MCP 服务项目,配置依赖项、wrangler 配置和模板选择
  • scripts/test-mcp-connection.sh - 测试 MCP 服务的连接,并验证工具/资源端点

Claude 应在以下情况下使用这些脚本:设置新项目或排查连接问题时。


官方文档

示例服务:


关键规则

务必做到

✅ 在响应结束时关闭传输,以防止内存泄漏
✅ 使用直接导出语法(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 可以连接并列出工具
  • 生产环境部署成功
  • 所有工具和资源都返回预期响应

生产示例

此技能基于以下模式:


有问题?遇到故障?

  1. 查看 references/common-errors.md 以排查问题
  2. 确认已完成快速入门部分中的所有步骤
  3. 使用 MCP Inspector 测试:npx @modelcontextprotocol/inspector
  4. 查看官方文档:https://spec.modelcontextprotocol.io/
  5. 确保 SDK 版本为 1.20.2 或更高版本

最后更新:2025-10-28 SDK 版本:@modelcontextprotocol/[email protected] 维护者:Claude Skills Repository

评论

支持 Markdown