1. 项目概述一个为AI时代量身定制的MCP模板如果你正在开发一个AI应用尤其是基于Claude、GPTs或其他支持工具调用Tool Calling的智能体那么你一定遇到过这样的困境如何高效、规范地管理你的工具集如何让不同的工具比如数据库查询、API调用、文件操作能够被AI模型稳定、安全地调用这就是MCPModel Context Protocol要解决的核心问题。而bsmi021/custom-mcp-template这个项目就是一个为你快速搭建自定义MCP服务器而生的“脚手架”。简单来说MCP就像是一个翻译官和调度员。AI模型比如Claude说“我想查一下数据库里的用户数据。” 它自己不会直接操作数据库。这时MCP服务器就登场了它理解AI的请求将其翻译成具体的数据库查询命令执行操作拿到结果再翻译成AI能理解的格式返回回去。custom-mcp-template则为你提供了搭建这个“翻译调度中心”所需的一切基础框架、目录结构和最佳实践示例让你无需从零开始造轮子能立刻聚焦于实现你自己的业务逻辑工具。这个模板非常适合两类开发者一是希望为自己的AI应用如企业内部知识库助手、自动化流程机器人增加稳定工具调用能力的团队二是想要学习MCP协议并快速实践一个可用服务器的个人开发者。它用TypeScript写成结构清晰注释详尽哪怕你对MCP概念还比较陌生也能通过这个模板快速上手。2. 核心架构与设计思路拆解2.1 为什么需要MCP从AI的“手”和“眼”说起AI大模型很强大能理解、能推理、能生成但它本质上是一个“大脑”缺少直接与外界系统交互的“手”和“眼”。它无法直接执行一段SQL也无法直接调用一个需要OAuth认证的HTTP API。早期的解决方案是让应用开发者自己写大量的胶水代码将AI的请求硬编码成具体的函数调用。这种方式耦合度高难以维护更无法实现工具在不同AI应用间的复用。MCP协议的出现就是为了标准化这个“工具调用”的接口。它定义了一套清晰的通信规范包括工具Tools的声明服务器告诉AI客户端“我这里有这些工具可用这是它们的名字、描述和参数格式。”调用InvocationAI客户端说“请使用‘查询用户’这个工具参数是user_id: 123。”结果Result与错误Error处理服务器执行后返回成功的结果或明确的错误信息。custom-mcp-template正是基于这套协议为你搭建了一个标准的MCP服务器骨架。它的设计思路可以概括为“开箱即用易于扩展”。2.2 模板工程结构深度解析当你克隆并打开这个模板项目你会看到一个精心设计的目录结构。理解这个结构是高效使用和扩展它的关键。custom-mcp-template/ ├── src/ │ ├── index.ts # 服务器主入口初始化与配置 │ ├── tools/ # 核心目录所有自定义工具的实现 │ │ ├── index.ts # 工具集的注册中心 │ │ ├── exampleTool.ts # 示例工具1获取服务器时间 │ │ └── anotherTool.ts # 示例工具2模拟计算 │ ├── clients/ # 可选如需主动通知客户端可在此实现 │ └── types/ # TypeScript类型定义 ├── package.json ├── tsconfig.json └── README.mdsrc/index.ts服务器的心脏这个文件是启动入口。它主要做三件事导入工具从src/tools/index.ts集中导入所有已定义的工具。创建服务器实例使用modelcontextprotocol/sdk提供的Server类创建一个MCP服务器实例。注册工具与资源将导入的工具列表注册到服务器实例上这样客户端如Claude Desktop在连接时就能自动发现这些可用的工具。src/tools/工具的“武器库”这是你需要投入最多精力的目录。模板已经提供了两个示例工具exampleTool.ts一个简单的工具返回当前服务器时间。它演示了如何定义一个无参数的工具。anotherTool.ts一个带参数的工具接受两个数字并返回它们的和。它演示了如何定义参数模式JSON Schema并进行输入验证。每个工具文件都遵循相同的模式导出一个符合MCPTool接口的对象。这个对象必须包含name工具名、description描述AI会根据这个决定是否使用该工具和inputSchema输入参数JSON Schema。最关键的是execute函数这里是工具具体业务逻辑实现的地方。src/tools/index.ts工具的“登记处”这个文件的作用是集中导出所有工具。你每新建一个工具文件都需要在这里import并添加到导出的tools数组中。这种设计保证了src/index.ts只需从一个地方导入所有工具管理起来非常清晰。设计心法这种“分散实现集中注册”的模式是大型项目保持可维护性的关键。当你的工具数量增长到几十个时你依然能轻松地找到和管理每一个。2.3 协议传输方式Stdio vs SSEMCP服务器与客户端通信有两种主要方式Stdio标准输入输出和SSE服务器发送事件。这个模板默认配置为Stdio这也是Claude Desktop目前最常用的方式。Stdio服务器作为一个独立的子进程启动通过标准输入stdin接收客户端的JSON-RPC请求通过标准输出stdout发送JSON-RPC响应。这种方式简单、通用几乎任何编程环境都支持适合桌面集成或命令行工具。SSE基于HTTP服务器通过一个长连接持续向客户端推送事件。这种方式更适合Web应用场景。在模板的package.json中你通常会看到一个mcp配置段其中指明了command用于Stdio启动。对于初学者专注于Stdio方式即可它能覆盖绝大多数使用场景。3. 从零到一手把手创建你的第一个自定义工具理解了架构我们立刻动手增加一个实实在在的、有业务价值的工具。假设我们要为一个人力资源AI助手创建一个工具get_employee_info获取员工信息。3.1 步骤一创建工具文件在src/tools/目录下新建一个文件getEmployeeInfo.ts。// src/tools/getEmployeeInfo.ts import { Tool } from modelcontextprotocol/sdk/server.js; export const getEmployeeInfoTool: Tool { // 工具的唯一标识建议使用蛇形命名清晰易懂 name: get_employee_info, // 描述至关重要AI模型如Claude完全依赖此描述来判断何时调用此工具。 // 描述应清晰说明功能、适用场景和参数含义。 description: 根据员工工号employee_id查询员工的基本信息包括姓名、部门、职位和入职日期。, // 定义输入参数的JSON Schema。这既是给AI的说明也是运行时的验证规则。 inputSchema: { type: object, properties: { employee_id: { type: string, description: 员工的唯一工号例如EMP2024001 } }, // required 字段指定哪些参数是调用时必须提供的 required: [employee_id], additionalProperties: false // 禁止传入未定义的参数保证安全 }, // 工具的核心执行函数 async execute(arg: any, extra: { server: any }) { // 1. 参数提取与验证SDK通常会根据inputSchema做初步验证这里可做二次校验 const { employee_id } arg; if (!employee_id || typeof employee_id ! string) { throw new Error(Invalid employee_id provided.); } // 2. 这里是你的业务逻辑 // 模拟一个数据库查询或API调用 console.log([MCP Server] Querying info for employee: ${employee_id}); // 模拟根据工号返回数据 const mockDatabase: Recordstring, any { EMP2024001: { name: 张三, department: 技术研发部, position: 高级软件工程师, hire_date: 2024-03-15, status: 在职 }, EMP2024002: { name: 李四, department: 市场部, position: 市场经理, hire_date: 2023-11-20, status: 在职 } }; const employeeInfo mockDatabase[employee_id]; // 3. 处理结果与错误 if (!employeeInfo) { // 返回一个结构化的错误信息AI客户端能很好地理解并告知用户 return { content: [{ type: text, text: 未找到工号为 ${employee_id} 的员工信息。请检查工号是否正确。 }], isError: true // 标记为错误结果 }; } // 4. 返回成功结果 // 返回的内容应结构化、信息丰富。使用文本格式清晰呈现。 const infoText 员工信息查询成功 - 姓名${employeeInfo.name} - 部门${employeeInfo.department} - 职位${employeeInfo.position} - 入职日期${employeeInfo.hire_date} - 状态${employeeInfo.status} .trim(); return { content: [{ type: text, text: infoText }] // 你还可以返回更丰富的内容类型如图片、嵌入式数据等 }; } };3.2 步骤二注册工具到中心打开src/tools/index.ts文件导入并添加我们新创建的工具。// src/tools/index.ts import { exampleTool } from ./exampleTool.js; import { anotherTool } from ./anotherTool.js; // 导入新创建的工具 import { getEmployeeInfoTool } from ./getEmployeeInfo.js; // 将新工具添加到这个数组中 export const tools [ exampleTool, anotherTool, getEmployeeInfoTool, // 新增这一行 ];3.3 步骤三测试你的工具现在我们需要测试这个工具是否正常工作。模板项目通常已经配置好了开发脚本。构建项目在终端运行npm run build或yarn build、pnpm build。这将把TypeScript代码编译成JavaScript到dist/目录。本地运行测试你可以写一个简单的测试脚本或者直接使用MCP客户端进行测试。更简单的方式是利用模板可能提供的简易测试模式检查package.json中的scripts是否有dev或test命令。一个更贴近真实场景的测试方法是配置Claude Desktop来连接你本地开发的MCP服务器。配置Claude Desktop以Mac为例 找到Claude Desktop的配置文件通常位于~/Library/Application Support/Claude/claude_desktop_config.json。在其中添加你的MCP服务器配置{ mcpServers: { my-custom-hr-tools: { command: node, args: [ /ABSOLUTE/PATH/TO/YOUR/PROJECT/dist/index.js ], env: { NODE_ENV: development } } } }保存配置并重启Claude Desktop。之后当你在Claude对话中提及“查询一下员工EMP2024001的信息”Claude就会自动识别并建议使用get_employee_info这个工具调用后你将看到返回的结构化员工信息。实操心得在开发初期我强烈建议在工具的execute函数内部多使用console.log打印关键步骤和中间数据。这些日志会在Claude Desktop的MCP服务器日志窗口或你的终端中显示是调试工具执行流程和排查参数问题最直接有效的手段。4. 高级技巧与生产环境实践当你的工具越来越多功能越来越复杂就需要考虑更多工程化和安全性的问题。4.1 工具设计的“松耦合”与“单一职责”一个好的MCP工具应该像Unix哲学中的小程序一样只做好一件事并把它做到极致。避免创建“巨无霸”工具。反面例子manage_employee工具内部通过一个action参数来区分“创建”、“查询”、“更新”、“删除”操作。这会导致inputSchema异常复杂AI模型也难以准确理解和使用。正面例子拆分成四个独立的工具create_employee、get_employee_info、update_employee、delete_employee。每个工具描述清晰参数简单AI调用起来准确率更高你的代码也更容易维护和测试。4.2 错误处理与用户友好反馈在execute函数中错误处理至关重要。不要只是抛出一个原始的JavaScript Error。提供有意义的错误信息如上面的示例当员工未找到时返回isError: true的结构化内容并给出可操作的提示“请检查工号是否正确”。区分系统错误与业务错误网络超时、数据库连接失败是系统错误可以记录详细日志并返回“服务暂时不可用”。参数无效、资源不存在是业务错误应返回给用户和AI清晰的业务提示。使用Try-Catch包裹异步操作所有可能出错的IO操作网络请求、数据库查询、文件读写都必须用try-catch包裹防止服务器进程因未捕获的异常而崩溃。async execute(arg: any) { try { const result await someAsyncOperation(arg.input); return { content: [{ type: text, text: result }] }; } catch (error) { console.error([Tool Error] Failed operation:, error); // 返回用户友好的错误而非堆栈信息 return { content: [{ type: text, text: 操作失败${error instanceof Error ? error.message : 未知错误}。请稍后重试或联系管理员。 }], isError: true }; } }4.3 安全性考量MCP工具本质上是将你系统的内部能力暴露给AI模型安全是重中之重。输入验证Input ValidationinputSchema是第一道防线务必严格定义type、format、pattern正则表达式和enum枚举值。利用additionalProperties: false阻止额外参数注入。权限控制Authorization不是所有连接过来的AI客户端都应该能调用所有工具。你可以在execute函数的extra参数中获取会话信息如果传输层支持或要求客户端在调用特定工具前传递一个认证令牌token并在服务器端进行校验。输出净化Output Sanitization返回给AI的内容如果最终要展示给用户需注意避免返回敏感信息如密码、密钥、完整个人身份证号。对于数据库查询结果考虑进行字段脱敏。速率限制Rate Limiting为防止滥用可以在服务器层面或工具层面实现简单的调用频率限制。4.4 性能优化与状态管理MCP服务器默认是无状态的每次工具调用都是独立的。但有些工具可能需要昂贵的初始化如数据库连接池、第三方SDK实例。连接池与缓存你可以在服务器启动时src/index.ts中初始化这些重量级资源然后通过依赖注入或全局上下文的方式传递给各个工具的execute函数使用。避免每次调用都创建新连接。避免阻塞操作execute函数必须是async的。确保所有IO操作都是非阻塞的使用异步API不要让工具调用长时间阻塞事件循环否则会影响其他并发请求的处理。5. 调试、部署与生态集成5.1 调试技巧实录开发MCP服务器最常见的两个问题是“为什么AI不调用我的工具”和“为什么工具调用失败了”问题一AI不识别/不调用工具检查清单工具描述description字段是否清晰、准确地描述了工具的功能和使用场景AI完全依赖这个描述来做决策。用自然语言写包含关键词。Claude Desktop配置配置文件路径是否正确JSON格式是否有效重启Claude Desktop了吗服务器日志启动Claude时查看MCP服务器日志在Claude Desktop设置中可找到确认你的服务器是否成功连接并上报了工具列表。名称冲突工具name是否与已有工具重复确保唯一性。问题二工具调用失败或返回意外结果检查清单参数验证在execute函数开头打印收到的arg确认AI传递的参数是否符合你的inputSchema预期。控制台日志在业务逻辑的关键步骤添加console.log观察执行流。错误处理确保所有异步操作都有try-catch并返回了结构化的错误信息而不是抛出未捕获的异常。数据类型注意JSON-RPC传输中数字可能会变成字符串。在代码中做好类型转换。5.2 部署为生产服务当你完成开发测试后可能需要将MCP服务器部署到生产环境供团队或产品使用。构建优化使用npm run build生成生产环境的dist代码。确保tsconfig.json中设置了合适的目标JS版本和优化选项。进程管理对于Stdio模式客户端如你的后端服务会负责启动和管理MCP服务器进程。你需要确保运行环境的Node.js版本合适且所有依赖已安装npm install --production。容器化推荐使用Docker将你的MCP服务器及其运行环境打包成镜像。这能保证环境一致性简化部署。# Dockerfile 示例 FROM node:18-alpine WORKDIR /app COPY package*.json ./ RUN npm ci --onlyproduction COPY dist ./dist EXPOSE 8000 # 如果使用SSE方式可能需要暴露端口 CMD [node, dist/index.js]健康检查可以考虑在服务器中实现一个简单的健康检查工具或端点对于SSE模式方便运维监控。5.3 融入更大的AI开发生态custom-mcp-template构建的服务器不仅可以被Claude Desktop使用还可以集成到更多地方Claude API Workbench在构建基于Claude API的AI应用时你可以将MCP服务器作为“后端工具服务”集成让你的AI助手获得强大的工具调用能力。GPTs Custom Actions虽然OpenAI有自己的Function Calling规范但MCP的设计理念是相通的。你可以将工具抽象成通用的接口方便适配不同的AI平台。自主开发的AI Agent框架如果你在使用LangChain、LlamaIndex等框架开发自主的智能体你可以将MCP服务器视为一个集中化、标准化的工具库让你的智能体通过MCP协议来调用实现架构上的解耦。这个模板的价值在于它为你提供了一个符合业界最佳实践的起点。你无需关心协议底层的JSON-RPC通信细节只需专注于实现那些真正创造价值的工具逻辑。随着AI应用对工具调用需求的爆炸式增长掌握如何快速构建稳定、安全的MCP服务器将成为AI应用开发者的一项核心技能。从克隆这个模板实现第一个get_employee_info工具开始你已经踏上了这条实战之路。