如何使用 GitHub Actions 自动发布
社区译文;来源: MCP 80041ab0
把包上传与 Registry 登记作为两个可单独恢复的步骤
正文工作流写入两个系统:包仓和 MCP Registry。二者认证不同,失败后的恢复方式也不同。推送发布标签之前,应先确定命名空间、包版本和 Registry 版本,再让日志能回答“哪一步已成功写入”。
| 停止位置 | 先查什么 | 恢复方向 |
|---|---|---|
| 构建或测试 | 源码 revision、依赖锁和失败输出 | 修复后再产生发布副作用 |
| 包上传 | 包仓身份、名称和版本 | 判断指定版本是否已经存在 |
| Registry 登录 | OIDC 权限或所选 PAT、域名证明 | 修复身份,避免无关地重发包 |
| Registry 登记 | 已上传包的验证标记与 server.json | 制品正确时复用该版本 |
| 发布后查询 | 精确服务器名与 Registry 版本 | 将读回结果与任务状态分开验收 |
OIDC 在对应认证路径上省去 Registry 专用 secret,不会自动授予 npm 发布权限。反过来,拥有 NPM_TOKEN 也不代表能写入某个 Registry 命名空间。应选定一种正文列出的 Registry 认证方式,并独立配置包仓身份。
自动化之前,对齐标签、server.json 顶层版本和包版本。若脚本从标签生成版本,发布前应查看生成后的实际文件。为了重现发布环境,建议固定已审阅的 publisher 版本并记录工作流 revision;直接下载 latest 会让不同运行取得不同版本。
如果包上传成功、Registry 登记失败,不应盲目重跑整个任务:包仓可能拒绝再次发布同一个版本。先确认现有制品,再从失败阶段恢复。需要修订 Registry 元数据时按版本管理产生新版本,不尝试覆盖旧记录。本导读是对正文示例的工作流审查建议,并非本站向公共包仓和 Registry 执行过的发布实验。
第 1 步:创建工作流文件
在服务器项目目录中创建 .github/workflows/publish-mcp.yml 文件。以下示例适用于基于 npm 的本地服务器,但所有包类型的 MCP Registry 发布步骤都相同:
name: Publish to MCP Registry
on:
push:
tags: ["v*"] # Triggers on version tags like v1.0.0
jobs:
publish:
runs-on: ubuntu-latest
permissions:
id-token: write # Required for OIDC authentication
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v5
### Publish underlying npm package:
- name: Set up Node.js
uses: actions/setup-node@v5
with:
node-version: "lts/*"
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm run test --if-present
- name: Build package
run: npm run build --if-present
- name: Publish package to npm
run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
### Publish MCP server:
- name: Install mcp-publisher
run: |
curl -L "https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/').tar.gz" | tar xz mcp-publisher
- name: Authenticate to MCP Registry
run: ./mcp-publisher login github-oidc
# Optional:
# - name: Set version in server.json
# run: |
# VERSION=${GITHUB_REF#refs/tags/v}
# jq --arg v "$VERSION" '.version = $v' server.json > server.tmp && mv server.tmp server.json
- name: Publish server to MCP Registry
run: ./mcp-publisher publishname: Publish to MCP Registry
on:
push:
tags: ["v*"] # Triggers on version tags like v1.0.0
jobs:
publish:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v5
### Publish underlying npm package:
- name: Set up Node.js
uses: actions/setup-node@v5
with:
node-version: "lts/*"
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm run test --if-present
- name: Build package
run: npm run build --if-present
- name: Publish package to npm
run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
### Publish MCP server:
- name: Install mcp-publisher
run: |
curl -L "https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/').tar.gz" | tar xz mcp-publisher
- name: Authenticate to MCP Registry
run: ./mcp-publisher login github --token ${{ secrets.MCP_GITHUB_TOKEN }}
# Optional:
# - name: Set version in server.json
# run: |
# VERSION=${GITHUB_REF#refs/tags/v}
# jq --arg v "$VERSION" '.version = $v' server.json > server.tmp && mv server.tmp server.json
- name: Publish server to MCP Registry
run: ./mcp-publisher publishname: Publish to MCP Registry
on:
push:
tags: ["v*"] # Triggers on version tags like v1.0.0
jobs:
publish:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v5
### Publish underlying npm package:
- name: Set up Node.js
uses: actions/setup-node@v5
with:
node-version: "lts/*"
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm run test --if-present
- name: Build package
run: npm run build --if-present
- name: Publish package to npm
run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
### Publish MCP server:
- name: Install mcp-publisher
run: |
curl -L "https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/').tar.gz" | tar xz mcp-publisher
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# TODO: Replace `example.com` with your domain name
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- name: Authenticate to MCP Registry
run: ./mcp-publisher login dns --domain example.com --private-key ${{ secrets.MCP_PRIVATE_KEY }}
# Optional:
# - name: Set version in server.json
# run: |
# VERSION=${GITHUB_REF#refs/tags/v}
# jq --arg v "$VERSION" '.version = $v' server.json > server.tmp && mv server.tmp server.json
- name: Publish server to MCP Registry
run: ./mcp-publisher publish第 2 步:添加 Secret
根据所选的身份验证方法,你可能需要向仓库添加 secret:
- GitHub OIDC 身份验证:不需要专用 secret。
- GitHub PAT 身份验证:添加名为
MCP_GITHUB_TOKEN的 secret,其值为具有read:org和read:userscope 的 GitHub Personal Access Token(PAT)。 - DNS 身份验证:添加名为
MCP_PRIVATE_KEY的 secret,其值为你的 Ed25519 私钥。
你可能还需要为包注册表添加 secret。例如,上面的工作流需要名为 NPM_TOKEN 的 secret,其值为 npm token。
有关如何向仓库添加 secret 的信息,请参阅 在 GitHub Actions 中使用 secret。
第 3 步:创建标签并发布
创建并推送版本标签以触发工作流:
git tag v1.0.0
git push origin v1.0.0工作流将运行测试、构建包、把包发布到 npm,并把服务器发布到 MCP Registry。
故障排除
| 错误消息 | 操作 |
|---|---|
| “Authentication failed” | 确保为 OIDC 设置了 id-token: write 权限,或检查 secret。 |
| “Package validation failed” | 确认包已成功发布到包注册表(例如 npm、PyPI),并且包中包含必要的验证信息。 |