假设你写了一个 MCP server,本地跑得挺好。同事想用,你发过去一段配置:
json
{"command": "npx", "args": ["-y", "github:你的用户名/你的仓库"]}
能跑,但每次都要克隆整个仓库。仓库大一点,第一次启动要等十几秒。更麻烦的是,别人装的是哪一版说不清楚------你在 main 上改了东西,对方下次启动可能就拿到一个新行为。
这篇记录的是我把自己写的 MCP server 发到 npm 和 MCP 官方注册表的完整过程。中途踩了三个坑,都是「不遇到就不知道」的那种,写下来省你一遍。
先分清两个东西
npm 是包仓库,MCP Registry 是目录。
npm 存的是代码,npx 从这里下载并运行。MCP Registry 只存元数据------名字、描述、版本、包在哪里、用什么传输方式。它不存代码,也不保证你的 server 一定能跑。
两者都要发,但顺序固定:先发 npm,再发 Registry。Registry 里要填 npm 包的标识符,包不存在它验不过。
官方注册表的地址是 registry.modelcontextprotocol.io,可以用浏览器直接搜名字确认自己有没有发成功。
第一步:让包能被 npx 直接跑
package.json 里这四项是关键:
json
{
"name": "你的包名",
"version": "1.2.1",
"bin": { "你的包名": "dist/server.mjs" },
"files": ["dist/server.mjs"]
}
bin 的键要和包名一致,用户才能直接 npx -y 你的包名。键名不同的话,npx 会找不到可执行文件。
files 决定哪些文件会被打包发出去。只列运行必需的产物,别把源码和测试一起推上去------包体积和安装速度都受影响。
发之前先看一眼包里有什么:
bash
npm pack --dry-run
它会列出文件名和体积,不真的生成压缩包。我这次打出来是 231 kB 压缩、973 kB 解压、6 个文件。如果看到不该出现的目录,回去改 files。
第二步:发布,然后等
bash
npm publish --access public
这里第一个坑。 终端会打印:
css
+ 你的包名@1.2.1
看起来成功了。但如果你马上去 registry.npmjs.org 查,可能查不到,dist-tag 还指着别的版本。
原因是 npm 返回的是 202 Accepted,不是 200 OK------它接受了你的请求,不代表处理完了。本机实测从提交到可查大约 3 分钟。
判断标准不是终端那行输出,而是这两个命令:
bash
npm view 你的包名 dist-tags
curl -s https://registry.npmjs.org/你的包名 | head -c 300
dist-tags 里的 latest 指向你刚发的版本,才算真的上线。
第二个坑,更迷惑。 新包第一次发布时,registry 里会先出现一个 0.0.0-stage。我第一次看到时以为包名被别人占了,去查了半天。
它其实是 npm 的分阶段发布机制------先占住包名,真版本随后出现。看到这个不用慌,等几分钟再看,1.2.1 会自己出现。
第三步:加 mcpName,否则 Registry 不认
这是第三个坑,也是最容易漏的一个。
MCP Registry 需要确认「这个 npm 包确实属于你声明的这个 GitHub 命名空间」。它的做法是:
- 你声明一个以
io.github.你的用户名/开头的名字 - 它去 npm 包里找
mcpName字段 - 两个对得上,才允许发布
所以 package.json 里必须加这个字段:
json
{
"mcpName": "io.github.你的GitHub用户名/你的服务名"
}
关键点:这个字段要打进包里。 我第一版(1.2.0)没带它,Registry 那边验不过,只能改完重发一个 1.2.1。多花了一次 2FA 验证。
文件名和 mcpName 的路径可以不一样,但 io.github. 后面的用户名必须和你的 GitHub 账号对得上,否则认证过不去。
第四步:写 server.json
Registry 读的是仓库根目录的 server.json。最简版本长这样:
json
{
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
"name": "io.github.你的用户名/你的服务名",
"title": "显示名",
"description": "一句话说清这个 server 能做什么",
"repository": {
"url": "https://github.com/你的用户名/你的仓库",
"source": "github"
},
"version": "1.2.1",
"packages": [
{
"registryType": "npm",
"identifier": "你的包名",
"version": "1.2.1",
"transport": { "type": "stdio" }
}
]
}
写的时候会撞到一条限制:description 最多 100 字符 。我第一版写了三百多字,校验直接报 is too long。
100 字符大概是一句话加一个从句。与其硬塞功能列表,不如说清「这是什么、给谁用」。我的最终版本是 86 字符:
78 verified AI tools for engineering teams, with fit, limits, licence and open issues.
packages[].version 和顶层 version 要一致,都跟你刚发的 npm 版本对齐。
第五步:校验、登录、发布
官方给了命令行工具 mcp-publisher,从 registry 仓库的 releases 页下载对应平台的压缩包。
先校验,这一步不用登录:
bash
mcp-publisher validate
输出 ✅ server.json is valid 才算过关。schema 错误、字段超长都会在这一步被拦下。
然后登录。它支持 GitHub 认证,有现成的 PAT 就能直接用:
bash
mcp-publisher login github --token "$(gh auth token)"
最后发布:
bash
mcp-publisher publish
成功会打印 ✓ Successfully published。之后用 API 或网页都能查到:
bash
curl -s 'https://registry.modelcontextprotocol.io/v0.1/servers?search=你的服务名'
返回里会带 status: active 和一个 publishedAt 时间戳。
发布之后,别人怎么用
发布前用户的配置是这样(要克隆仓库):
json
{"command": "npx", "args": ["-y", "github:你的用户名/你的仓库"]}
发布后:
json
{"command": "npx", "args": ["-y", "你的包名"]}
差别不只是短。npm 有版本号,npx 你的包名 拿到的是一个确定的发布版本;github: 形式拿的是仓库当前状态,你在 main 上改了什么,对方下次启动就是什么。
这正是发布的意义:把「你本机能跑」变成「别人拿到的是哪一版说得清」。
三个坑的对照
| 现象 | 你以为的 | 实际的 |
|---|---|---|
registry 出现 0.0.0-stage |
包名被人占了 | npm 分阶段发布的占位版本 |
终端打印 + 包名@版本 但查不到 |
发布失败 | 返回 202,异步处理,等几分钟 |
mcp-publisher 验不过 mcpName |
server.json 写错了 | 包里的 mcpName 没打进去,要重发版本 |
三个都属于「知道就不难,不知道就卡住」。我这次全程花在排查上的时间,比写代码多。
要不要发,看两件事
如果你的 MCP server 只自己用 ,本地跑就行,不用折腾这些。mcp-publisher 和 server.json 是为了让别人能发现并安装。
如果你想让别人用上,npm + Registry 是目前最短的路径。Registry 是官方目录,一些 MCP 客户端会直接读它。
至于目录站和 awesome-list,那是另一条路。我同时在几个社区目录提交过,反馈周期长且结果不可控------有个 97k star 的目录,最近 30 个已关闭的 PR 合并数是我自己数的:零。所以我把精力放在官方注册表上,那里是自助发布,不用排队等 review。
发布命令和检查方式都在上面。如果你也在做 MCP server,可以先跑一次 npm pack --dry-run,看看包里到底有什么------这一步不花时间,但能省掉后面很多来回。
想看我按这套流程发出去的例子,可以直接查:
- npm 包页:awesome-ai-for-teams
- 官方注册表条目:io.github.c-k-x/awesome-ai-...
那个 server 做的事,是把 78 个团队 AI 工具的适用条件、限制和许可整理成可查询的条目。装了之后在 Claude Desktop 或 Cursor 里问「哪个自托管的记忆层适合我们」,它会带着 stars、许可和已知 issue 一起答。工具本身的说明在 ToolHive 详情页,可以作为「一个 MCP server 对外长什么样」的参考。
资料核对于 2026-11-13。文中命令均在本机实际运行,失败与成功的输出都来自当次日志。mcp-publisher 版本为 1.8.9。