用GitHub发布包上架MCP注册表
文章演示通过GitHub Release托管MCPB文件,将MCP服务登记到官方注册表,无需先发布npm包。配置涉及下载地址、SHA-256校验,以及在GitHub Actions中通过OIDC登录。
AI 深度解读
没有 npm token,MCP 服务还能上官方注册表吗?作者用 GitHub Release 上的 MCPB 文件完成了发布,GitHub Actions 再通过 OIDC 登录注册表,整条链路不需要保存 npm 凭证。
这篇实践值得看的地方,是它把打包、校验、发布和验收串了起来。其中最容易踩的坑:源码和文件内容都相同,重新打出来的压缩包,SHA-256 也可能不同。另外,注册成功和客户端能正常安装,是两件需要分别验证的事。
官方注册表收录的,其实是包的地址
MCP 官方注册表存储元数据,代码包放在别处。server.json 负责描述服务,并指向实际分发地址。原文列出的包类型包括 npm、PyPI、NuGet、Docker/OCI、MCPB 和 Cargo,因此 npm 发布受阻,不等于整个服务无法登记。
MCPB 是包含服务文件和 manifest.json 的 ZIP 归档。作者使用的清单版本是 manifest_version: "0.2",服务名为 publish-gate,版本为 0.1.0。它通过 node 启动 server.js,参数使用 ${__dirname}/server.js 定位入口。
按原文所述,MCPB 登记需要满足三个条件:文件放在 GitHub 或 GitLab Release,下载 URL 包含字符串 mcp,并在 server.json 中提供文件的 SHA-256,即 fileSha256。使用 GitHub 身份登录时,服务名称必须符合 io.github.<user>/<name>。
作者的服务没有依赖,因此不用附带 node_modules。通过 .mcpbignore 排除测试和 server.json 后,归档只留下 server.js、README.md、package.json、manifest.json 四个文件。校验命令是 npx -y @anthropic-ai/mcpb@2.1.2 validate manifest.json,打包命令是 npx -y @anthropic-ai/mcpb@2.1.2 pack . publish-gate.mcpb。
他们还解压了产物,对解压后的副本运行 6 个测试,并通过 stdio 发送 initialize 和 check_numbers 调用,两者都有响应。这一步检查的是包里的程序能否运行,比只验证清单格式更进一步。
为什么必须对上传的那个文件计算哈希
作者把相同的四个文件打包两次,得到了两个不同的 SHA-256,而且都与已经上传的文件不同。逐项检查后,各文件的 CRC 相同,差异出在 ZIP 条目的时间戳。
内容相同,不保证压缩包的字节完全相同。
fileSha256 校验的是整个归档,所以必须用最终上传的文件执行 sha256sum publish-gate.mcpb,不能在发布时重新打包,再拿新哈希替代。
下面这段配置把下载地址和实际产物绑定起来:
"packages": [
{
"registryType": "mcpb",
"identifier": "https://github.com/skibuff22/agent-ops-kit-lite/releases/download/mcp-v0.1.0/publish-gate.mcpb",
"fileSha256": "1b032ae3ce70dc974726da444fe0e448ae8bdfa39a92d53bd1001c9f51ff4aca",
"transport": { "type": "stdio" }
}
]
要盯住的是 fileSha256:它必须对应 identifier 下载到的文件。这里的 mcp-v0.1.0 同时出现在 Release 路径中。
正式发布前,作者运行了 mcp-publisher validate。工具连接线上注册表验证,返回 server.json is valid。这证明配置通过了验证,还不能代替后面的发布和安装验收。
Actions 负责验证已有产物,再登记到注册表
工作流由 mcp-v* 标签触发,不重新构建 MCPB,而是下载 Release 附件,将实际哈希与仓库里的 server.json 比较,一致才继续发布:
permissions:
id-token: write
contents: read
steps:
- uses: actions/checkout@v4
- run: npm test
- name: Release asset matches server.json
run: |
gh release download "$TAG" -R "$GITHUB_REPOSITORY" -p publish-gate.mcpb -D /tmp/rel
want=$(node -e 'const s=require("./server.json");const p=s.packages.find(p=>p.registryType==="mcpb");console.log(p?p.fileSha256:"")')
got=$(sha256sum /tmp/rel/publish-gate.mcpb | cut -d" " -f1)
test -n "$want" && test "$want" = "$got"
- run: curl -L "https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher_linux_amd64.tar.gz" | tar xz mcp-publisher
- run: ./mcp-publisher login github-oidc
- run: ./mcp-publisher publish
关键是 test -n "$want" && test "$want" = "$got":既拒绝空哈希,也拒绝不一致的附件。id-token: write 用于 OIDC 登录,无须保存注册表登录密钥;作者的公开仓库用 contents: read 即可下载 Release 附件。
这是一段缩略配置。完整工作流还包含 workflow_dispatch 手动触发、setup-node、工作目录、GH_TOKEN、TAG,以及缺少 NPM_TOKEN 时自动跳过的 npm 发布步骤,不能直接把片段当作完整模板。
作者先推送带哈希的 server.json,再执行 gh release create mcp-v0.1.0 publish-gate.mcpb --target master --notes-file notes.md。该命令创建标签并触发工作流。此次运行耗时 17 秒,测试和哈希检查通过,npm 跳过,最后输出 Successfully published。
但验收没有停在日志。他们使用 curl -s "https://registry.modelcontextprotocol.io/v0/servers?search=io.github.skibuff22/publish-gate" 查询注册表 API,确认返回的 _meta 包含 "status": "active" 和 "isLatest": true。
我的判断
这条路径适合已经有可分发产物、暂时不具备 npm 发布条件的 MCP 项目。它复用 GitHub Release 和 Actions,通过 OIDC 完成登记,做法清楚,产物校验也有实测支撑。
局限同样明确:作者没有在支持 MCPB 的客户端里安装过这个包。实际验证的安装路径仍然是克隆仓库,再执行 claude mcp add。由于 npm 包尚未发布,npx -y publish-gate-mcp 也不能使用。
注册表已收录,只能证明登记成功,不能证明客户端安装链路已经跑通。
这个服务零依赖,打包负担较小;一般 Node 项目如果有运行时依赖,就不能照搬四文件方案。17 秒也是单次工作流结果,原文没有与 npm 路径做耗时、成功率或维护成本对照,不能据此判断 MCPB 全面更优。
作者计划后续发布新版本,在 server.json 中同时列出两种包。该实践的本地命令与 Actions 均运行于 2026-11-09,环境为 Node v26.7.0、mcpb 2.1.2。项目采用 MIT 许可,检查草稿数字和失效链接;文末另有 $19 的付费 Publish Gate,但没有提供其效果对照。
能拿来做什么
- 如果你的 Node MCP 服务卡在 npm 凭证配置,可以先评估 MCPB 分发,并分别安排注册表验收和客户端安装验收。
- 将打包产物作为固定发布对象,计算该文件的哈希,再让 CI 下载 Release 附件复核,避免重新打包造成哈希失配。
- 测试解压后的服务副本,并通过 stdio 调用初始化和关键工具,确认入口文件及所需资源确实进入了包。
- 发布后查询注册表 API,核对服务元数据与状态;如果还要提供
npx安装入口,就把 npm 发布作为单独需要完成的交付项。