Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,81 @@ bundle.mcpb (ZIP file)
- Include all required shared libraries if dynamic linking used
- Test on clean systems without development tools

## Publishing Your Bundle

Once you've packed an `.mcpb`, you need a way to distribute it. The recommended pattern is to attach it as an asset on a GitHub Release — tagged, versioned, and addressable without any additional hosting.

### Why GitHub Releases

- Release tags give consumers a stable, versioned URL per bundle.
- Standard tooling (`gh`, `curl`, release-feed polling) can pull assets directly.
- Monorepos can ship multiple bundles under different tag prefixes.
- No extra infrastructure to run.

### Tag Convention

Use a prefixed tag pattern so a single repository can ship more than one bundle:

```
<ServerName>-<SemVer>
```

Examples:

```
my-company-mcp-1.3.0
analytics-mcp-2.0.1
```

### Per-Platform Assets

If your server bundles platform-specific binaries, attach one `.mcpb` per platform with a consistent naming suffix:

```
<ServerName>-<SemVer>-darwin-arm64.mcpb
<ServerName>-<SemVer>-darwin-x64.mcpb
<ServerName>-<SemVer>-win32-x64.mcpb
```

If your server is cross-platform (Node.js, Python, pure script), a single `.mcpb` per release is sufficient.

Declare `compatibility.platforms` in each bundle's `manifest.json` to match what's actually in the bundle. Do not list platforms you haven't built for — consumers rely on this field to reject incompatible installs.

### Uploading from CI

After `mcpb pack` produces the bundle:

```sh
gh release upload "$TAG" dist/*.mcpb --clobber
```

`--clobber` keeps the release job idempotent on re-run.

### Minimum CI Shape

Triggered by a tag push or release event, a workflow does four things in order:

1. **Build** your server for each target platform.
2. **Stage** `manifest.json` + server code + `icon.png` + `LICENSE` into a bundle directory.
3. **Pack** with `mcpb pack <staging-dir>` to produce the `.mcpb`.
4. **Upload** to the GitHub Release via `gh release upload`.

Signing, if required by your policy, slots in between steps 3 and 4.

### Entry Point Paths

`manifest.json` should set `entry_point` to a relative path inside the bundle, and `mcp_config.args` should reference it via `${__dirname}`:

```json
"entry_point": "server/index.js",
"mcp_config": {
"command": "node",
"args": ["${__dirname}/server/index.js"]
}
```

This keeps the bundle relocatable — consumers install to arbitrary paths, and `${__dirname}` resolves to the extracted bundle root at runtime.

# Contributing

We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
Expand Down
Loading