最近给项目搭 AI 工具链,想把一堆能力(查数据、跑命令、截图)包成 MCP server 丢给 AI 用。结果写到一半就烦了:同一个 server,Claude Code 走 stdio、Mavis 那类走 HTTP,光是握手、消息格式、错误处理,我就得照着两套协议各对一遍。再加上 JSON-RPC 2.0 那堆样板—— initialize 握手、 tools/list 、 tools/call 、一长串错误码——每写一个新 server 都要从头糊一遍。
这些跟我真正想暴露的业务工具八竿子打不着,纯粹是协议层的脏活。糊到第三个 server 的时候我受不了了,干脆把这层抽出来做成 SDK—— universal-mcp-sdk 。
核心就一句话: 你只管定义 tool 和 resource,协议和传输全交给它。写一次,stdio 和 HTTP 两条通道同时支持。
它替你扛了什么
写 MCP server 真正烦人的不是业务逻辑,是底下这些重复劳动:
- 两种 transport 各写一遍——stdio 给本地子进程拉起,HTTP 给常驻服务
- JSON-RPC 2.0 的握手、分发、一堆错误码,死板又容易写错
- content block(文本/图片/音频)的封装格式,每次都得翻文档
这些 universal-mcp-sdk 全替你兜了。你写 server 的时候,眼里只剩自己的 tool。
用起来有多简单
一个能跑的 server,就这么几行:
const { createServer, tool, textContent } = require('universal-mcp-sdk');
createServer({ name: 'my-mcp', version: '1.0.0', tools: [ tool('add', '两数相加', { a: { type: 'number' }, b: { type: 'number' } }, async ({ a, b }) => textContent(String(a + b))), ],}).start();
接 Claude Code,项目根丢个 .mcp.json :
{ "mcpServers": { "my-mcp": { "command": "node", "args": ["server.js", "--stdio"] } } }
接 Mavis 这类 HTTP agent,server 用 --http 起,配上 url: http://127.0.0.1:8080/mcp 就行。
完事。一个 add 工具,Claude Code 和 HTTP agent 都能调了。同一份代码,你不传参数它还能自己看运行环境挑 stdio 还是 HTTP。
已经接通的客户端
Claude Code / Cursor / Mavis 我都实测接通了;codex(OpenAI)、kimicode(Kimi)、GitHub Copilot 这些走 stdio 的也都能接,跟接 Claude Code 一个套路,配置格式换一下而已。
唯一暂时接不了的是 GPT web 这类依赖 SSE 的标准 streamable-http 客户端——HTTP transport 的 SSE 我还在补。走 stdio 的不受影响。
一些细节
- 协议层
initialize/tools.list/tools.call/resources.list/resources.read/ping都齐了,错误分两层(协议级 + 工具执行),README 有完整的接入协议文档 - 支持运行时动态加工具(
server.addTool) - 纯 Node,零第三方依赖,
npm install不拉任何东西,嫌麻烦直接把目录拷进项目也行 - Apache-2.0,可商用
开源在这: https://github.com/HappyLifeOk/universal-mcp-sdk
要是你也在写 MCP server、被多端适配烦过,可以试试。有问题欢迎提 issue。