mcpField
M
mcp-builder

mcp-builder

github.com/pixel-process-ug开发380 次安装33 周前更新
代码仓库

关于 mcp-builder

用于设计、实现、测试和加固 MCP 服务的开发技能。它引导开发者向客户端暴露工具、资源和提示词,选择传输方式并准备客户端集成。

主要功能

  1. 01规划 MCP 能力与传输方式
  2. 02定义经过验证的工具架构
  3. 03实现工具、资源和提示词
  4. 04配置 stdio 与 SSE 传输
  5. 05添加错误处理和安全检查
  6. 06使用内存客户端测试服务

适用场景

  1. 01为应用设计 MCP 服务
  2. 02向 AI 客户端暴露数据与操作
  3. 03选择本地或远程访问的传输方式
  4. 04在部署前测试并审查服务

MCP 相关

指导完整开发可向 AI 客户端暴露工具、资源和提示词的 MCP 服务,涵盖传输配置与客户端集成。

安装

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

$npx skills add https://github.com/pixel-process-ug/superkit-agents --skill mcp-builder

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

详细介绍

MCP Builder

概述

构建可投入生产的 MCP(Model Context Protocol)服务,向 AI 客户端提供工具、资源和提示词。本技能涵盖完整的开发生命周期:工具定义、资源管理、提示词模板、传输配置(stdio、SSE)、错误处理、安全加固、测试和客户端集成。

阶段 1:设计

  1. 确定要提供的功能(工具、资源、提示词)
  2. 使用 Zod/JSON Schema 定义工具架构
  3. 规划资源 URI 模式
  4. 设计错误处理策略
  5. 选择传输层(命令行使用 stdio,Web 使用 SSE)

停止 — 向用户展示功能清单和传输方式,以供审批。

功能选择决策表
现有内容MCP 基元示例
修改状态的操作工具create-issue、send-email、deploy-app
读取或查询操作工具search-documents、get-status
AI 应读取的数据资源config://settings、docs://api/endpoints
可复用的提示词模式提示词code-review、summarize-document
实时数据流资源(可订阅)metrics://cpu/current
传输方式选择决策表
场景传输方式原因
命令行工具、本地客户端(Claude Desktop)Stdio简单,无网络开销
Web 应用、远程客户端SSE可通过网络访问,支持实时通信
本地和远程场景兼有Stdio + SSE同时支持两种用例
高吞吐量、双向通信WebSocket(自定义)比 SSE 延迟更低

阶段 2:实现

  1. 搭建 MCP 服务项目结构
  2. 实现带输入验证的工具处理程序
  3. 实现资源提供程序
  4. 添加提示词模板
  5. 配置传输方式和身份验证

停止 — 进行加固前,先运行基本冒烟测试。

项目结构
src/
  index.ts          # Server entry point
  tools/
    search.ts       # Tool implementations
    create.ts
  resources/
    documents.ts    # Resource providers
    config.ts
  prompts/
    review.ts       # Prompt templates
  lib/
    database.ts     # Shared utilities
    validation.ts
tests/
  tools.test.ts
  resources.test.ts
package.json
tsconfig.json
工具定义模式
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { z } from 'zod';

const server = new McpServer({
  name: 'my-mcp-server',
  version: '1.0.0',
});

server.tool(
  'search-documents',
  'Search documents by query. Returns matching documents with relevance scores.',
  {
    query: z.string().describe('Search query string'),
    limit: z.number().min(1).max(100).default(10).describe('Maximum results to return'),
    filter: z.object({
      type: z.enum(['article', 'page', 'note']).optional(),
      dateAfter: z.string().datetime().optional(),
    }).optional().describe('Optional filters'),
  },
  async ({ query, limit, filter }) => {
    const results = await searchEngine.search(query, { limit, ...filter });
    return {
      content: [{
        type: 'text',
        text: JSON.stringify(results, null, 2),
      }],
    };
  }
);
工具设计原则
原则规则
命名清晰使用动词-名词格式:search-documents、create-issue
描述详尽说明用途、使用时机和返回值
输入经过验证使用 Zod 架构,并为每个字段调用 .describe()
输出结构化使用格式良好的文本或 JSON
尽可能保持幂等相同输入产生相同结果
错误可采取行动提供具体错误消息,并设置 isError: true
工具响应模式
// Text response
return { content: [{ type: 'text', text: 'Operation completed successfully' }] };

// Structured data response
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };

// Multi-part response
return {
  content: [
    { type: 'text', text: `Found ${results.length} results:` },
    { type: 'text', text: results.map(r => `- ${r.title}: ${r.summary}`).join('\n') },
  ],
};

// Image response
return { content: [{ type: 'image', data: base64Data, mimeType: 'image/png' }] };

// Error response
return {
  content: [{ type: 'text', text: `Error: ${error.message}` }],
  isError: true,
};

资源管理

资源定义
// Static resource
server.resource(
  'config',
  'config://app/settings',
  { mimeType: 'application/json' },
  async () => ({
    contents: [{
      uri: 'config://app/settings',
      mimeType: 'application/json',
      text: JSON.stringify(appConfig),
    }],
  })
);

// Dynamic resource with URI template
server.resource(
  'document',
  new ResourceTemplate('docs://{category}/{id}', { list: undefined }),
  { mimeType: 'text/markdown' },
  async (uri, { category, id }) => ({
    contents: [{
      uri: uri.href,
      mimeType: 'text/markdown',
      text: await getDocument(category, id),
    }],
  })
);
资源 URI 约定
file:///path/to/file          — Local files
https://api.example.com/data  — Remote HTTP resources
db://database/table/id        — Database records
config://app/settings         — Configuration
docs://category/slug          — Documentation

提示词模板

server.prompt(
  'code-review',
  'Generate a code review for the given file',
  {
    filePath: z.string().describe('Path to the file to review'),
    severity: z.enum(['strict', 'normal', 'lenient']).default('normal'),
  },
  async ({ filePath, severity }) => {
    const code = await readFile(filePath, 'utf-8');
    return {
      messages: [{
        role: 'user',
        content: {
          type: 'text',
          text: `Review this code with ${severity} standards:\n\n\`\`\`\n${code}\n\`\`\``,
        },
      }],
    };
  }
);

传输层

Stdio 传输(命令行工具、本地开发)
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';

const transport = new StdioServerTransport();
await server.connect(transport);
SSE 传输(Web 应用、远程服务)
import express from 'express';
import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';

const app = express();

app.get('/sse', async (req, res) => {
  const transport = new SSEServerTransport('/messages', res);
  await server.connect(transport);
});

app.post('/messages', async (req, res) => {
  // Handle incoming messages
});

app.listen(3001);

阶段 3:加固

  1. 添加全面的错误处理
  2. 实现速率限制和超时
  3. 进行安全审查(输入清理、权限检查)
  4. 编写集成测试
  5. 为客户端编写工具和资源文档

停止 — 部署前必须通过所有测试并完成安全审查。

错误处理
server.tool('risky-operation', 'Performs an operation that might fail', {
  input: z.string(),
}, async ({ input }) => {
  try {
    const result = await performOperation(input);
    return { content: [{ type: 'text', text: JSON.stringify(result) }] };
  } catch (error) {
    if (error instanceof ValidationError) {
      return {
        content: [{ type: 'text', text: `Invalid input: ${error.message}` }],
        isError: true,
      };
    }
    if (error instanceof NotFoundError) {
      return {
        content: [{ type: 'text', text: `Resource not found: ${error.message}` }],
        isError: true,
      };
    }
    console.error('Unexpected error:', error);
    return {
      content: [{ type: 'text', text: 'An unexpected error occurred. Please try again.' }],
      isError: true,
    };
  }
});
错误处理规则
规则原因
切勿向客户端暴露堆栈跟踪存在安全风险
所有错误均返回 isError: true客户端可区分成功和失败
在服务端记录意外错误便于调试和监控
提供可采取行动的错误消息客户端可自行纠正
为外部调用处理超时防止请求挂起
处理前验证所有输入尽早拒绝错误数据
安全注意事项
类别规则
输入验证Zod 架构、防止路径遍历、长度限制
权限模型最小权限、目录白名单、读写工具分离
密钥仅使用环境变量,绝不在响应中返回,在日志中脱敏,并定期轮换
速率限制限制每个客户端的工具调用次数
审计记录所有工具调用及其时间戳

测试 MCP 服务

import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { InMemoryTransport } from '@modelcontextprotocol/sdk/inMemory.js';
import { Client } from '@modelcontextprotocol/sdk/client/index.js';

describe('MCP Server', () => {
  let server: McpServer;
  let client: Client;

  beforeEach(async () => {
    server = createServer();
    client = new Client({ name: 'test-client', version: '1.0.0' });
    const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
    await Promise.all([
      server.connect(serverTransport),
      client.connect(clientTransport),
    ]);
  });

  test('search-documents returns results', async () => {
    const result = await client.callTool({
      name: 'search-documents',
      arguments: { query: 'test', limit: 5 },
    });
    expect(result.content[0].type).toBe('text');
    const data = JSON.parse(result.content[0].text);
    expect(data.length).toBeLessThanOrEqual(5);
  });

  test('handles invalid input gracefully', async () => {
    const result = await client.callTool({
      name: 'search-documents',
      arguments: { query: '', limit: -1 },
    });
    expect(result.isError).toBe(true);
  });
});

客户端集成

Claude Desktop 配置
{
  "mcpServers": {
    "my-server": {
      "command": "node",
      "args": ["/path/to/server/dist/index.js"],
      "env": {
        "API_KEY": "your-key-here"
      }
    }
  }
}

反模式 / 常见错误

反模式错误原因替代做法
工具承担过多功能难以使用,也难以测试拆分为专注于单一用途的工具
缺少输入验证会导致崩溃和安全漏洞始终使用 Zod 模式
返回原始堆栈跟踪存在安全风险,也会让 AI 感到困惑使用 isError: true 并返回简洁的消息
外部调用没有超时设置会无限期挂起为所有 I/O 设置超时
在源代码中硬编码密钥会暴露凭据使用环境变量
工具没有描述客户端无法了解工具用途编写清晰的描述
使用同步操作阻塞事件循环服务会变得无响应所有 I/O 都使用 async/await
没有测试无法发现回归问题使用 InMemoryTransport 进行测试

文档查询(Context7)

使用 mcp__context7__resolve-library-id,然后使用 mcp__context7__query-docs 查询最新文档。返回的文档优先于记忆中的知识。

  • @anthropic-ai/sdk — 用于 Claude API 客户端、工具定义或流式传输

集成点

技能集成方式
senior-devops将 MCP 服务容器化并部署
agent-developmentMCP 服务为 Agent 提供工具
security-review加固工具输入和输出的安全性
test-driven-development对工具实现进行 TDD
deployment用于发布 MCP 服务的 CI/CD 流水线
planningMCP 服务设计是实施计划的一部分

技能类型

灵活 — 根据使用场景调整项目结构、传输方式和工具。强烈建议使用 Zod 验证工具,并通过 isError 处理错误。建议在生产部署前进行安全审查。

评论

支持 Markdown