MCP集成详解:连接外部世界 MCP(模型上下文协议)是 OpenClaw 对接外部数据源和第三方服务的标准通道。本节从协议原理讲起,手把手带你搭一个 MCP 服务器,再对比 Skill 和 MCP 的适用场景,帮你做出正确的技术选型。 本节导航 理解 MCP 协议的三大原语(工具、资源、提示模板)及其通信机制 掌握 MCP 服务器的开发流程:初始化项目、注册工具、配置连接 能独立完成一个天气查询 MCP 服务器的搭建与 OpenClaw 对接 清楚 Skill 和 MCP 的边界,在实际项目中做出合理选择 一、MCP 协议是什么 1.1 一句话理解 MCP 就是 AI 的 USB-C 接口。
MCP(模型上下文协议)是 OpenClaw 对接外部数据源和第三方服务的标准通道。本节从协议原理讲起,手把手带你搭一个 MCP 服务器,再对比 Skill 和 MCP 的适用场景,帮你做出正确的技术选型。
MCP 就是 AI 的 USB-C 接口。就像 USB-C 让手机能连接各种外设一样,MCP 让 AI 智能体能连接各种外部系统——数据库、API、文件系统、第三方服务。
在 MCP 出现之前,每个 AI 应用要对接一个新服务,都得写一套定制代码。有了 MCP,只要服务实现了 MCP 协议,任何支持 MCP 的 AI 应用都能直接调用,不需要重复开发。
MCP 采用客户端-服务器架构,基于 JSON-RPC 2.0 协议通信:
OpenClaw 在这个架构里扮演 Host 角色,内部维护多个 MCP Client,每个 Client 连接一个 MCP Server。Server 是独立的进程,可以跑在本地(STDIO 传输),也可以跑在远程机器上(HTTP 传输)。
MCP 服务器通过三种原语向 AI 暴露能力:
| 原语 | 作用 | 典型场景 | 举例 |
|---|---|---|---|
| Tools(工具) | AI 可调用的函数 | 执行操作、写入数据 | 创建文件、发送消息、更新数据库 |
| Resources(资源) | 提供上下文的数据源 | 读取数据、获取状态 | 文件内容、数据库表结构、API 响应 |
| Prompts(提示模板) | 可复用的交互模板 | 标准化交互流程 | 系统提示、Few-shot 示例 |
工具是最常用的原语。一个工具调用走的是标准的 JSON-RPC 请求-响应流程:客户端发送工具名称和参数,服务器执行后返回结果。
💡 选择建议:如果你的场景只需要让 AI 读取信息,用 Resources 就够了;如果需要 AI 执行操作(创建、修改、删除),那就得用 Tools。Prompts 用得相对少,主要在需要标准化交互流程时才会用到。
搭建一个 MCP 服务器需要 Node.js 22+ 和 npm。先初始化项目:
mkdir my-mcp-server && cd my-mcp-server npm init -y npm install @modelcontextprotocol/sdk
在 package.json 里加上 "type": "module" 启用 ES 模块。
创建一个 index.js 文件,实现一个天气查询服务器:
import { Server } from "@modelcontextprotocol/sdk/server/index.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; const server = new Server({ name: "weather-mcp-server", version: "1.0.0" }); // 注册工具 server.addTool({ name: "get_weather", description: "查询指定城市的当前天气信息", inputSchema: { type: "object", properties: { city: { type: "string", description: "城市名称,如 Beijing、Shanghai" }, units: { type: "string", enum: ["metric", "imperial"], description: "温度单位:metric=摄氏度, imperial=华氏度" } }, required: ["city"] } }); // 处理工具调用 server.setRequestHandler("tools/call", async (request) => { const { name, arguments: args } = request.params; if (name === "get_weather") { // 这里调用实际的天气 API const weather = await fetchWeather(args.city, args.units); return { content: [{ type: "text", text: `${args.city} 当前天气:${weather.temperature}°,${weather.description}` }] }; } }); // 启动服务器 const transport = new StdioServerTransport(); await server.connect(transport);
这段代码做了三件事:定义工具的名称和参数结构、注册工具调用的处理逻辑、通过 STDIO 传输启动服务。
服务器写好后,告诉 OpenClaw 去哪里找它。编辑 OpenClaw 配置文件:
{ skills: { load: { extraDirs: ["./my-mcp-server"] } } }
OpenClaw 启动时会自动发现并启动这个 MCP 服务器。AI 智能体在对话中就能调用 get_weather 工具了。
⚠️ 端口冲突注意:STDIO 模式的 MCP 服务器不需要端口,它通过标准输入输出和 OpenClaw 通信。如果你改用 HTTP 传输模式,需要确保端口没有被其他服务占用。可以在启动脚本里加一个端口检测逻辑,发现冲突时自动切换到备用端口。
开发 MCP 服务器时,最容易遇到的问题就是"工具没被识别"。排查步骤:
inputSchema 格式正确,JSON Schema 语法没问题在实际项目中,有些功能用 Skill 实现更合适,有些用 MCP 更好。两者的核心区别在于:Skill 传递的是静态知识,MCP 连接的是动态数据。
| 维度 | Skill | MCP |
|---|---|---|
| 本质 | 知识载体(Markdown 指令) | 通信协议(JSON-RPC) |
| 部署方式 | 本地文件夹,直接读取 | 独立进程,通过网络通信 |
| Token 消耗 | 加载到上下文,占用窗口 | 仅传输调用结果,消耗低 |
| 数据时效 | 静态,手动更新 | 动态,实时获取 |
| 开发复杂度 | 低(写 Markdown) | 中(写服务器代码) |
| 适合场景 | 工作流程、领域知识、操作规范 | 外部 API、数据库、实时数据 |
| 认证管理 | 配置文件注入 | 协议层原生支持 |
| 跨平台复用 | 仅限 OpenClaw | 所有 MCP 客户端通用 |
遇到一个需求时,按这个流程判断用 Skill 还是 MCP:
举几个实际例子:
实际项目里,Skill 和 MCP 往往搭配使用。以 DevOps 助手为例:
| 能力 | 实现方式 | 原因 |
|---|---|---|
| CI/CD 流程指导 | Skill | 工作流程是静态知识 |
| Jenkins 任务查询 | MCP | 动态数据,需要认证 |
| 日志分析技巧 | Skill | 分析方法是静态知识 |
| 实时日志获取 | MCP | 动态数据,大数据量 |
| 部署规范 | Skill | 企业规范,静态知识 |
| Kubernetes 集群状态 | MCP | 实时数据,远程 API |
配置里同时启用 Skill 和 MCP:
{ skills: { entries: { "cicd-workflow": { enabled: true }, "log-analysis": { enabled: true }, "deployment-guide": { enabled: true } }, load: { extraDirs: [ "./mcp-servers/jenkins", "./mcp-servers/k8s" ] } } }
💡 经验之谈:不要纠结于"到底用 Skill 还是 MCP"这个问题。如果一个功能用 Skill 能搞定(比如只是封装一个命令行工具),那就先用 Skill,别过度设计。等到需求变复杂了(需要认证、需要实时数据),再迁移到 MCP 也不迟。
频繁访问的数据加一层缓存,减少 API 调用次数:
const cache = new Map(); server.addResource({ uri: "cache://project-status", name: "项目状态缓存", async handler() { if (!cache.has("status")) { cache.set("status", await fetchProjectStatus()); // 5 分钟后过期 setTimeout(() => cache.delete("status"), 300000); } return cache.get("status"); } });
MCP 服务器直接操作外部系统,安全不能马虎:
⚠️ 常见错误:很多初学者在开发时把 API Key 直接写在代码里,调试完忘了删,提交到代码仓库。建议从一开始就用环境变量,养成习惯。
