···11+# publishing to mcp registry
22+33+this document explains how we set up automated publishing to the [MCP registry](https://github.com/modelcontextprotocol/registry) and the lessons learned along the way.
44+55+## overview
66+77+the MCP registry is Anthropic's official directory of Model Context Protocol servers. publishing makes your server discoverable and installable through Claude Desktop and other MCP clients.
88+99+## setup
1010+1111+### required files
1212+1313+1. **`server.json`** - registry metadata
1414+ - must match PyPI package version exactly
1515+ - uses namespace format: `io.github.username/server-name`
1616+ - validated against https://static.modelcontextprotocol.io/schemas/2025-09-29/server.schema.json
1717+1818+2. **`README.md`** - must contain `mcp-name:` line
1919+ - format: `mcp-name: io.github.username/server-name`
2020+ - can appear anywhere in the file (we put it at the bottom)
2121+ - validation uses simple `strings.Contains()` check
2222+2323+3. **`.github/workflows/publish-mcp.yml`** - automation workflow
2424+ - triggers on version tags (e.g., `v0.0.6`)
2525+ - publishes to PyPI first, then MCP registry
2626+ - uses GitHub OIDC for authentication (no secrets needed)
2727+2828+### github secrets
2929+3030+only one secret required:
3131+- `PYPI_API_TOKEN` - from https://pypi.org/manage/account/token/
3232+3333+## workflow
3434+3535+when you push a version tag:
3636+3737+```bash
3838+git tag v0.0.6
3939+git push origin v0.0.6
4040+```
4141+4242+the workflow automatically:
4343+1. runs tests
4444+2. builds the package with `uv build`
4545+3. publishes to PyPI with `uv publish`
4646+4. installs `mcp-publisher` binary (v1.2.3)
4747+5. authenticates using GitHub OIDC
4848+6. publishes to MCP registry
4949+5050+## key learnings
5151+5252+### mcp-publisher installation
5353+5454+the official docs suggest using a "latest" URL that doesn't actually work:
5555+5656+```bash
5757+# ❌ doesn't work - 404s
5858+curl -L "https://github.com/modelcontextprotocol/registry/releases/download/latest/..."
5959+6060+# ✅ use specific version
6161+curl -L "https://github.com/modelcontextprotocol/registry/releases/download/v1.2.3/mcp-publisher_1.2.3_linux_amd64.tar.gz"
6262+```
6363+6464+the publisher is a Go binary, not an npm package. don't try `npm install`.
6565+6666+### version synchronization
6767+6868+`server.json` version must match the PyPI package version:
6969+7070+```json
7171+{
7272+ "version": "0.0.6",
7373+ "packages": [{
7474+ "version": "0.0.6"
7575+ }]
7676+}
7777+```
7878+7979+if they don't match, registry validation fails with:
8080+```
8181+PyPI package 'tangled-mcp' not found (status: 404)
8282+```
8383+8484+### readme validation
8585+8686+the `mcp-name:` line just needs to exist somewhere in the README content. the validator uses:
8787+8888+```go
8989+strings.Contains(description, "mcp-name: io.github.username/server-name")
9090+```
9191+9292+so you can place it wherever looks best aesthetically. we put it at the bottom after a horizontal rule.
9393+9494+### authentication
9595+9696+GitHub OIDC is the recommended method for CI/CD:
9797+9898+```yaml
9999+permissions:
100100+ id-token: write
101101+ contents: read
102102+103103+steps:
104104+ - name: login to mcp registry (github oidc)
105105+ run: mcp-publisher login github-oidc
106106+```
107107+108108+no need for additional tokens or secrets - GitHub handles it automatically.
109109+110110+## common errors
111111+112112+### "PyPI package not found (status: 404)"
113113+114114+**cause**: version mismatch between `server.json` and actual PyPI package
115115+116116+**fix**: ensure `server.json` versions match the git tag and PyPI will build that version
117117+118118+### "ownership validation failed"
119119+120120+**cause**: missing or incorrect `mcp-name:` in README
121121+122122+**fix**: add `mcp-name: io.github.username/server-name` anywhere in README.md
123123+124124+### "failed to install mcp-publisher"
125125+126126+**cause**: wrong download URL or npm package attempt
127127+128128+**fix**: use specific version binary download from GitHub releases
129129+130130+## resources
131131+132132+- [MCP registry docs](https://github.com/modelcontextprotocol/registry/tree/main/docs)
133133+- [MCP publisher source](https://github.com/modelcontextprotocol/registry)
134134+- [our workflow](.github/workflows/publish-mcp.yml)
135135+- [our server.json](server.json)