docs: simplify GitHub Actions publishing guide (#446)

Simplifies the GitHub Actions publishing guide to be more concise and
easier to follow:

## Changes
- Streamlined MCP publisher installation with single-line curl command
(no more chmod/directory operations)
- Condensed authentication methods into compact sections
- Reduced language-specific examples to essential steps only
- Updated GitHub Actions to use latest versions (v5)
- Made test/build steps optional with `--if-present` flag
- Added helpful AI assistant prompt tip to publish-server.md

## Result
The guide is now much more succinct while maintaining all essential
information, following the same simplified approach as the main
publishing guide.
This commit is contained in:
adam jones 2025-09-12 02:57:46 -07:00 • committed by GitHub
commit ba86c6beb5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 42 additions and 186 deletions

View file

@ -13,49 +13,46 @@ By the end of this tutorial, you'll have:
## Prerequisites
- Already published your server manually (complete [Publishing Tutorial](publish-server.md) first)
- Understand general publishing requirements like package verification (see the [publishing guide](publish-server.md))
- GitHub repository with your MCP server code
- Basic understanding of CI/CD concepts
- 20-30 minutes
## GitHub Actions Setup
### Step 1: Create Workflow File
Create `.github/workflows/publish-mcp.yml` in your repository:
Create `.github/workflows/publish-mcp.yml`. Here's an example for NPM-based packages, but the MCP registry publishing steps are the same for all package types:
```yaml
name: Publish to MCP Registry
on:
push:
tags: ["v*"] # Triggers on version tags like v1.0.0
tags: ["v*"] # Triggers on version tags like v1.0.0
jobs:
publish:
runs-on: ubuntu-latest
permissions:
id-token: write # Required for OIDC authentication
id-token: write # Required for OIDC authentication
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: Setup Node.js # Adjust for your language
uses: actions/setup-node@v4
- name: Setup Node.js # Adjust for your language
uses: actions/setup-node@v5
with:
node-version: "20"
registry-url: "https://registry.npmjs.org"
node-version: "lts/*"
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
run: npm run test --if-present
- name: Build package
run: npm run build
run: npm run build --if-present
- name: Publish to npm
run: npm publish
@ -64,13 +61,7 @@ jobs:
- name: Install MCP Publisher
run: |
# Build publisher from source (requires Go)
git clone https://github.com/modelcontextprotocol/registry publisher-repo
cd publisher-repo
make publisher
cp bin/mcp-publisher ../mcp-publisher
cd ..
chmod +x mcp-publisher
curl -L "https://github.com/modelcontextprotocol/registry/releases/download/v1.0.0/mcp-publisher_1.0.0_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/').tar.gz" | tar xz mcp-publisher
- name: Login to MCP Registry
run: ./mcp-publisher login github-oidc
@ -81,12 +72,9 @@ jobs:
### Step 2: Configure Secrets
For npm publishing, add your NPM token to repository secrets:
You don't need any secrets for publishing to the MCP Registry using GitHub OIDC.
1. Go to repository Settings → Secrets and variables → Actions
2. Add `NPM_TOKEN` with your npm access token
**Note:** GitHub OIDC authentication requires no additional secrets for MCP Registry publishing.
However you might need to add secrets for your package registry. For example the workflow above needs a `NPM_TOKEN` (which you can add in Settings → Secrets and variables → Actions).
### Step 3: Tag and Release
@ -97,30 +85,18 @@ git tag v1.0.0
git push origin v1.0.0
```
The workflow will:
The workflow runs tests, builds your package, publishes to npm, and publishes to the MCP Registry.
1. Run tests
2. Build your package
3. Publish to npm
4. Automatically authenticate with the MCP Registry
5. Publish updated server.json
## Authentication Methods
## Authentication Methods by CI Platform
### GitHub Actions - OIDC (Recommended)
### GitHub Actions OIDC (Recommended)
```yaml
- name: Login to MCP Registry
run: mcp-publisher login github-oidc
```
**Advantages:**
- No secrets to manage
- Automatically scoped to your repository
- Most secure option
### GitHub Actions - Personal Access Token
### GitHub Personal Access Token
```yaml
- name: Login to MCP Registry
@ -131,7 +107,7 @@ The workflow will:
Add `MCP_GITHUB_TOKEN` secret with a GitHub PAT that has repo access.
### DNS Authentication (Any CI)
### DNS Authentication
For custom domain namespaces (`com.yourcompany/*`):
@ -144,155 +120,22 @@ For custom domain namespaces (`com.yourcompany/*`):
Add your Ed25519 private key as `MCP_PRIVATE_KEY` secret.
## Language-Specific Examples
## Examples
### Python Project
See these real-world examples of automated publishing workflows:
- [NPM, Docker and MCPB](https://github.com/domdomegg/airtable-mcp-server)
- [NuGet](https://github.com/domdomegg/time-mcp-nuget)
- [PyPI](https://github.com/domdomegg/time-mcp-pypi)
## Tips
You can keep your package version and server.json version in sync automatically with something like:
```yaml
name: Publish Python MCP Server
on:
push:
tags: ["v*"]
jobs:
publish:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: "3.11"
- name: Install Poetry
run: pipx install poetry
- name: Build package
run: poetry build
- name: Publish to PyPI
run: poetry publish
env:
POETRY_PYPI_TOKEN_PYPI: ${{ secrets.PYPI_TOKEN }}
- name: Install MCP Publisher
run: |
git clone https://github.com/modelcontextprotocol/registry publisher-repo
cd publisher-repo && make publisher && cd ..
cp publisher-repo/bin/mcp-publisher mcp-publisher
- name: Publish to MCP Registry
run: |
./mcp-publisher login github-oidc
./mcp-publisher publish
```
### Docker Project
```yaml
name: Publish Docker MCP Server
on:
push:
tags: ["v*"]
jobs:
publish:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- uses: actions/checkout@v4
- name: Setup Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Extract version
id: version
run: echo "version=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: yourname/your-server:${{ steps.version.outputs.version }}
labels: |
io.modelcontextprotocol.server.name=io.github.yourname/your-server
- name: Install MCP Publisher
run: |
git clone https://github.com/modelcontextprotocol/registry publisher-repo
cd publisher-repo && make publisher && cd ..
cp publisher-repo/bin/mcp-publisher mcp-publisher
- name: Publish to MCP Registry
run: |
./mcp-publisher login github-oidc
./mcp-publisher publish
```
## Best Practices
### 1. Version Alignment
Keep your package version and server.json version in sync:
```yaml
- name: Update server.json version
run: |
- run: |
VERSION=${GITHUB_REF#refs/tags/v}
jq --arg version "$VERSION" '.version = $version' server.json > tmp.json
mv tmp.json server.json
```
### 2. Conditional Publishing
Only publish to registry after package publishing succeeds:
```yaml
- name: Publish to npm
run: npm publish
id: npm-publish
- name: Publish to MCP Registry
if: steps.npm-publish.outcome == 'success'
run: ./mcp-publisher publish
jq --arg v "$VERSION" '.version = $v' server.json > tmp && mv tmp server.json
```
## Troubleshooting
**"Publisher binary not found"** - Ensure you download the correct binary for your CI platform (linux/mac/windows).
**"Authentication failed"** - For GitHub OIDC, verify `id-token: write` permission is set. For other methods, check secret configuration.
**"Package validation failed"** - Ensure your package was published successfully before MCP Registry publishing runs.
**"Version already exists"** - Each server.json version must be unique. Consider using build numbers: `1.0.0-build.123`.
## What You've Accomplished
You now have automated MCP server publishing that:
- Triggers on version tags
- Runs tests before publishing
- Publishes to package registry first
- Automatically publishes to MCP Registry
- Handles authentication securely
- Provides failure notifications
Your MCP server publishing is now fully automated - just tag a release and everything happens automatically!
- **"Authentication failed"**: Ensure `id-token: write` permission is set for OIDC, or check secrets
- **"Package validation failed"**: Verify your package published to your registry (NPM, PyPi etc.) successfully first, and that you have done the necessary validation steps in the [Publishing Tutorial](publish-server.md)

View file

@ -2,6 +2,12 @@
Complete guide to publishing an MCP server to the registry.
> [!TIP]
> Using an agentic AI coding assistant? Just use this prompt:
> ```
> Read https://raw.githubusercontent.com/modelcontextprotocol/registry/refs/heads/main/docs/guides/publishing/publish-server.md and https://raw.githubusercontent.com/modelcontextprotocol/registry/refs/heads/main/docs/guides/publishing/github-actions.md. Evaluate the best way to publish this server to the registry (prefer automated CI flows over manual flows where possible), and implement that. If possible, validate the server.json against the $schema before telling the user you are done, using a proper json schema library or tool available on the user's machine. If you get stuck, guide the user through the parts of the publishing process they need to do (e.g. logging into the publisher CLI if doing manual pubishing).
> ```
## What You'll Learn
By the end of this tutorial, you'll have:
@ -339,6 +345,13 @@ You should see your server metadata returned in the JSON response.
**"Namespace not authorized"** - Your authentication method doesn't match your chosen namespace format.
## Examples
See these real-world examples of published servers:
- [NPM, Docker and MCPB example](https://github.com/domdomegg/airtable-mcp-server)
- [NuGet example](https://github.com/domdomegg/time-mcp-nuget)
- [PyPI example](https://github.com/domdomegg/time-mcp-pypi)
## Next Steps
- **Update your server**: Publish new versions with updated server.json files