写一次 MCP Server,Claude Code / Cursor / codex / Copilot 全都能接——我开源了 universal-mcp-sdk

最近给项目搭 AI 工具链,想把一堆能力(查数据、跑命令、截图)包成 MCP server 丢给 AI 用。结果写到一半就烦了:同一个 server,Claude Code 走 stdio、Mavis 那类走 HTTP,光是握手、消息格式、错误处理,我就得照着两套协议各对一遍。再加上 JSON-RPC 2.0 那堆样板—— initialize 握手、 tools/listtools/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。

3赞