A GitHub Action to package MCP servers into distributable bundles and publish them to the mpak registry.
MCP (Model Context Protocol) is a standard for AI assistants to interact with external tools and services. An MCP server exposes tools (like "search files" or "query database") that AI assistants can call.
MCPB is a bundle format (.mcpb files) that packages an MCP server with all its dependencies into a single portable file. This makes MCP servers easy to distribute and install.
mpak is a public registry where you can publish and discover MCP bundles. Think of it like npm, but for MCP servers.
This action automates the entire workflow: build your MCP server into a bundle, attach it to your GitHub release, and register it with mpak so others can find and install it.
Your repository needs:
- A
manifest.jsondescribing your MCP server:
{
"manifest_version": "0.4",
"name": "@your-github-org/your-server",
"version": "1.0.0",
"description": "What your server does",
"server": {
"type": "python",
"entry_point": "your_package.server",
"mcp_config": {
"command": "python",
"args": ["-m", "your_package.server"]
}
}
}Note: The
@scopemust match your GitHub organization or username. The registry verifies this via OIDC.
- Your MCP server code with stdio entrypoint:
# At end of server.py
if __name__ == "__main__":
mcp.run() # Required for mpak run / Claude DesktopAdd this to .github/workflows/release.yml:
name: Release
on:
release:
types: [published]
permissions:
contents: write
id-token: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: NimbleBrainInc/mcpb-pack@v3When you publish a GitHub release, this will:
- Vendor all dependencies into the bundle
- Build a
.mcpbfile - Upload it to your release
- Register it with mpak.dev
Your server is now discoverable via mpak search and installable via mpak bundle pull.
For pure Python/Node servers without native dependencies:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: NimbleBrainInc/mcpb-pack@v3For servers with native dependencies (C extensions, Rust bindings, etc.), you need to build on each target platform:
jobs:
build:
strategy:
matrix:
include:
- os: linux
arch: x64
runner: ubuntu-latest
- os: linux
arch: arm64
runner: ubuntu-24.04-arm
- os: darwin
arch: arm64
runner: macos-latest
- os: darwin
arch: x64
runner: macos-15-intel
runs-on: ${{ matrix.runner }}
steps:
- uses: actions/checkout@v4
- uses: NimbleBrainInc/mcpb-pack@v3
with:
output: "{name}-{version}-${{ matrix.os }}-${{ matrix.arch }}.mcpb"Each job builds and registers its own platform-specific bundle. The registry merges them automatically.
| Platform | Runner Label | Architecture | Notes |
|---|---|---|---|
| Linux x64 | ubuntu-latest |
x64 | Free |
| Linux ARM | ubuntu-24.04-arm |
arm64 | Free |
| macOS ARM | macos-latest / macos-15 |
arm64 (M1) | Free, 3 vCPU, 7 GB |
| macOS Intel | macos-15-intel |
x64 | Free, 4 vCPU, 14 GB |
Paid larger runners (Team/Enterprise plans):
| Platform | Runner Label | Architecture | Notes |
|---|---|---|---|
| macOS Intel | macos-15-large |
x64 | 12 vCPU, 30 GB |
| macOS ARM | macos-15-xlarge |
arm64 (M2) | 5 vCPU + 8 GPU, 14 GB |
Note:
macos-13is retiring December 2025. Usemacos-15-intelfor Intel macOS builds.
For CI validation or private servers:
- uses: NimbleBrainInc/mcpb-pack@v3
with:
upload: false
announce: falseIf you already build your .mcpb bundle separately (e.g., committed to the repo or built in a prior step), you can skip the build and just upload/announce:
- uses: NimbleBrainInc/mcpb-pack@v3
with:
directory: packages/mcp/mcpb
bundle-path: context7.mcpb
build: falseThis is useful when:
- Your bundle is pre-built and committed to the repository
- You have a custom build process
- You want to announce an existing bundle to mpak.dev
The action will compute the SHA256 hash and size from the provided bundle, upload it to the release, and announce it to the registry.
For pure Node.js or Python servers without native dependencies, you can announce a single bundle as cross-platform using any:
- uses: NimbleBrainInc/mcpb-pack@v3
with:
platform-os: any
platform-arch: anyThis registers the bundle as universal, so users on any platform can install it. The registry will serve this bundle when no platform-specific build is available.
To re-announce an existing release (e.g., if the registry was down or you're announcing to a different registry), add workflow_dispatch to your workflow:
on:
release:
types: [published]
workflow_dispatch:
inputs:
build:
description: 'Build bundle'
type: boolean
default: true
announce:
description: 'Announce to registry'
type: boolean
default: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: NimbleBrainInc/mcpb-pack@v3
with:
build: ${{ inputs.build }}
announce: ${{ inputs.announce }}Then trigger manually from the Actions tab, checking out the release tag. The action uses github.ref_name as the release tag when not triggered by a release event.
Note: The
uploadinput only works with release events. For manual triggers, upload the bundle to the release manually or usegh release upload.
| Input | Default | Description |
|---|---|---|
directory |
. |
Directory containing manifest.json and server code |
bundle-path |
Path to existing .mcpb bundle (use with build: false) |
|
output |
{name}-{version}.mcpb |
Output filename ({name} and {version} are replaced) |
python-version |
3.13 |
Python version for vendoring (if Python server) |
build |
true |
Whether to build the bundle |
upload |
true |
Whether to upload to the GitHub release |
announce |
true |
Whether to register with mpak.dev |
announce-required |
false |
Whether announce failures should fail the workflow |
announce-url |
https://registry.mpak.dev/v1/bundles/announce |
Registry endpoint (change for self-hosted registries) |
platform-os |
Override detected OS (darwin, linux, win32, any) | |
platform-arch |
Override detected arch (x64, arm64, any) |
| Output | Description |
|---|---|
bundle-path |
Path to the generated .mcpb file |
bundle-size |
Size of the bundle in bytes |
bundle-sha256 |
SHA256 hash for integrity checks |
announced |
Whether registration succeeded |
permissions:
contents: write # Required to upload to releases
id-token: write # Required for OIDC authentication with registryThe action:
- Validates
manifest.json(mcpb v0.4 required fields, optional reverse-DNS name override) - Detects your server type from
manifest.json(Python or Node.js) - Vendors all dependencies into the bundle (Python:
deps/, Node:node_modules/) - Packages everything into a
.mcpbfile using the mcpb CLI
When you announce to mpak.dev:
- The action uploads the
.mcpbbundle to the GitHub release - The action requests an OIDC token from GitHub
- This token cryptographically proves the bundle came from your repository
- The registry verifies the token and registers your bundle; the registry composes the MCP
ServerDetaildiscovery shape from yourmanifest.json - No API keys or secrets needed
Each platform build announces its own artifact. The registry tracks all artifacts for a version, so users can install the right bundle for their system.
To build without publishing to the public registry:
- uses: NimbleBrainInc/mcpb-pack@v3
with:
announce: falseYou might want this if:
- Your server is private or internal
- You're using a self-hosted registry
- You want to test before publishing
- You distribute through other channels
mpak automatically composes the MCP Registry's ServerDetail discovery shape from your bundle's manifest.json — there is no separate server.json file to maintain. Every announced bundle is reachable at:
GET /v1/servers/<your-name>— latestServerDetailGET /v1/servers/<your-name>/versions/<version>— version-specificGET /v1/servers/search?q=...— paginated search
By default the registry assigns a reverse-DNS name mechanically from your npm-style package name:
@your-org/your-server→dev.mpak.your-org/your-server
If you want a branded reverse-DNS name (e.g. com.example/your-server), set it in your manifest's _meta:
{
"manifest_version": "0.4",
"name": "@your-org/your-server",
"version": "1.0.0",
"description": "What your server does",
"_meta": {
"dev.mpak/registry": {
"name": "com.example/your-server"
}
}
}The override must match the upstream pattern ^[a-zA-Z0-9.-]+/[a-zA-Z0-9._-]+$ (one slash separating the reverse-DNS namespace from the server name).
If you previously shipped a server.json file alongside your bundle, you can delete it. Versions of this action prior to v3 validated and uploaded server.json to the GitHub release; v3 no longer reads or uploads it. The registry composes the ServerDetail discovery shape from manifest.json instead.
git rm server.json
# Optional: add a reverse-DNS name override to manifest.json (see "Naming" above).
git add manifest.json
git commit -m "drop server.json (mcpb-pack@v3 composes registry metadata from manifest)"| Runtime | Detected via | Dependency vendoring |
|---|---|---|
| Python | server.type: "python" |
uv pip install --target |
| Node.js | server.type: "node" |
npm install --omit=dev |
| Binary | server.type: "binary" |
None (you build the binary) |
For compiled languages, build your binary before running mcpb-pack:
jobs:
build:
strategy:
matrix:
include:
- os: linux
arch: x64
runner: ubuntu-latest
- os: linux
arch: arm64
runner: ubuntu-24.04-arm
- os: darwin
arch: arm64
runner: macos-latest
- os: darwin
arch: x64
runner: macos-15-intel
runs-on: ${{ matrix.runner }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: "1.22"
- name: Build binary
run: |
mkdir -p bin
go build -o bin/server ./cmd/server
- uses: NimbleBrainInc/mcpb-pack@v3
with:
output: "{name}-{version}-${{ matrix.os }}-${{ matrix.arch }}.mcpb"The manifest.json for binary servers:
{
"name": "@your-org/your-server",
"version": "1.0.0",
"server": {
"type": "binary",
"entry_point": "bin/server",
"mcp_config": {
"command": "${__dirname}/bin/server",
"args": []
}
}
}{
"name": "@your-org/your-server",
"version": "1.0.0",
"server": {
"type": "node",
"entry_point": "dist/index.js",
"mcp_config": {
"command": "node",
"args": ["${__dirname}/dist/index.js"]
}
}
}- mcp-echo - Simple Python MCP server with multi-platform builds
- MCP Documentation - Model Context Protocol specification
- mpak Registry - Browse and search published MCP bundles
- mcpb CLI - Command-line tool for building bundles locally
MIT