MCP server for tangled
at main 172 lines 4.6 kB view raw view rendered
1# publishing to mcp registry 2 3this document explains how we set up automated publishing to the [MCP registry](https://github.com/modelcontextprotocol/registry) and the lessons learned along the way. 4 5## overview 6 7the 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. 8 9## setup 10 11### required files 12 131. **`server.json`** - registry metadata 14 - must match PyPI package version exactly 15 - uses namespace format: `io.github.username/server-name` 16 - validated against https://static.modelcontextprotocol.io/schemas/2025-09-29/server.schema.json 17 182. **`README.md`** - must contain `mcp-name:` line 19 - format: `mcp-name: io.github.username/server-name` 20 - can appear anywhere in the file (we put it at the bottom) 21 - validation uses simple `strings.Contains()` check 22 233. **`.github/workflows/publish-mcp.yml`** - automation workflow 24 - triggers on version tags (e.g., `v0.0.6`) 25 - publishes to PyPI first, then MCP registry 26 - uses GitHub OIDC for authentication (no secrets needed) 27 28### github secrets 29 30only one secret required: 31- `PYPI_API_TOKEN` - from https://pypi.org/manage/account/token/ 32 33## workflow 34 35when you push a version tag: 36 37```bash 38git tag v0.0.6 39git push origin v0.0.6 40``` 41 42the workflow automatically: 431. runs tests 442. builds the package with `uv build` 453. publishes to PyPI with `uv publish` 464. installs `mcp-publisher` binary (v1.2.3) 475. authenticates using GitHub OIDC 486. publishes to MCP registry 49 50## cutting a release 51 52to cut a new release: 53 541. **update server.json version** (both fields must match the version you're releasing) 55 ```json 56 { 57 "version": "0.0.9", 58 "packages": [{ 59 "version": "0.0.9" 60 }] 61 } 62 ``` 63 642. **run pre-commit checks** 65 ```bash 66 just check 67 ``` 68 693. **commit and push your changes** 70 ```bash 71 git add . 72 git commit -m "your commit message" 73 git push origin main 74 ``` 75 764. **create and push the version tag** 77 ```bash 78 git tag v0.0.9 79 git push origin v0.0.9 80 ``` 81 825. **verify the release** 83 - workflow: https://github.com/zzstoatzz/tangled-mcp/actions/workflows/publish-mcp.yml 84 - pypi: https://pypi.org/project/tangled-mcp/ 85 - mcp registry: `https://registry.modelcontextprotocol.io/v0/servers/io.github.zzstoatzz%2Ftangled-mcp/versions/X.Y.Z` 86 87## key learnings 88 89### mcp-publisher installation 90 91the official docs suggest using a "latest" URL that doesn't actually work: 92 93```bash 94# ❌ doesn't work - 404s 95curl -L "https://github.com/modelcontextprotocol/registry/releases/download/latest/..." 96 97# ✅ use specific version 98curl -L "https://github.com/modelcontextprotocol/registry/releases/download/v1.2.3/mcp-publisher_1.2.3_linux_amd64.tar.gz" 99``` 100 101the publisher is a Go binary, not an npm package. don't try `npm install`. 102 103### version synchronization 104 105`server.json` version must match the PyPI package version: 106 107```json 108{ 109 "version": "0.0.6", 110 "packages": [{ 111 "version": "0.0.6" 112 }] 113} 114``` 115 116if they don't match, registry validation fails with: 117``` 118PyPI package 'tangled-mcp' not found (status: 404) 119``` 120 121### readme validation 122 123the `mcp-name:` line just needs to exist somewhere in the README content. the validator uses: 124 125```go 126strings.Contains(description, "mcp-name: io.github.username/server-name") 127``` 128 129so you can place it wherever looks best aesthetically. we put it at the bottom after a horizontal rule. 130 131### authentication 132 133GitHub OIDC is the recommended method for CI/CD: 134 135```yaml 136permissions: 137 id-token: write 138 contents: read 139 140steps: 141 - name: login to mcp registry (github oidc) 142 run: mcp-publisher login github-oidc 143``` 144 145no need for additional tokens or secrets - GitHub handles it automatically. 146 147## common errors 148 149### "PyPI package not found (status: 404)" 150 151**cause**: version mismatch between `server.json` and actual PyPI package 152 153**fix**: ensure `server.json` versions match the git tag and PyPI will build that version 154 155### "ownership validation failed" 156 157**cause**: missing or incorrect `mcp-name:` in README 158 159**fix**: add `mcp-name: io.github.username/server-name` anywhere in README.md 160 161### "failed to install mcp-publisher" 162 163**cause**: wrong download URL or npm package attempt 164 165**fix**: use specific version binary download from GitHub releases 166 167## resources 168 169- [MCP registry docs](https://github.com/modelcontextprotocol/registry/tree/main/docs) 170- [MCP publisher source](https://github.com/modelcontextprotocol/registry) 171- [our workflow](.github/workflows/publish-mcp.yml) 172- [our server.json](server.json)