MCP server for tangled

add publishing documentation: explain MCP registry setup, workflow, and lessons learned

+135
+135
docs/publishing.md
··· 1 + # publishing to mcp registry 2 + 3 + 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. 4 + 5 + ## overview 6 + 7 + 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. 8 + 9 + ## setup 10 + 11 + ### required files 12 + 13 + 1. **`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 + 18 + 2. **`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 + 23 + 3. **`.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 + 30 + only one secret required: 31 + - `PYPI_API_TOKEN` - from https://pypi.org/manage/account/token/ 32 + 33 + ## workflow 34 + 35 + when you push a version tag: 36 + 37 + ```bash 38 + git tag v0.0.6 39 + git push origin v0.0.6 40 + ``` 41 + 42 + the workflow automatically: 43 + 1. runs tests 44 + 2. builds the package with `uv build` 45 + 3. publishes to PyPI with `uv publish` 46 + 4. installs `mcp-publisher` binary (v1.2.3) 47 + 5. authenticates using GitHub OIDC 48 + 6. publishes to MCP registry 49 + 50 + ## key learnings 51 + 52 + ### mcp-publisher installation 53 + 54 + the official docs suggest using a "latest" URL that doesn't actually work: 55 + 56 + ```bash 57 + # ❌ doesn't work - 404s 58 + curl -L "https://github.com/modelcontextprotocol/registry/releases/download/latest/..." 59 + 60 + # ✅ use specific version 61 + curl -L "https://github.com/modelcontextprotocol/registry/releases/download/v1.2.3/mcp-publisher_1.2.3_linux_amd64.tar.gz" 62 + ``` 63 + 64 + the publisher is a Go binary, not an npm package. don't try `npm install`. 65 + 66 + ### version synchronization 67 + 68 + `server.json` version must match the PyPI package version: 69 + 70 + ```json 71 + { 72 + "version": "0.0.6", 73 + "packages": [{ 74 + "version": "0.0.6" 75 + }] 76 + } 77 + ``` 78 + 79 + if they don't match, registry validation fails with: 80 + ``` 81 + PyPI package 'tangled-mcp' not found (status: 404) 82 + ``` 83 + 84 + ### readme validation 85 + 86 + the `mcp-name:` line just needs to exist somewhere in the README content. the validator uses: 87 + 88 + ```go 89 + strings.Contains(description, "mcp-name: io.github.username/server-name") 90 + ``` 91 + 92 + so you can place it wherever looks best aesthetically. we put it at the bottom after a horizontal rule. 93 + 94 + ### authentication 95 + 96 + GitHub OIDC is the recommended method for CI/CD: 97 + 98 + ```yaml 99 + permissions: 100 + id-token: write 101 + contents: read 102 + 103 + steps: 104 + - name: login to mcp registry (github oidc) 105 + run: mcp-publisher login github-oidc 106 + ``` 107 + 108 + no need for additional tokens or secrets - GitHub handles it automatically. 109 + 110 + ## common errors 111 + 112 + ### "PyPI package not found (status: 404)" 113 + 114 + **cause**: version mismatch between `server.json` and actual PyPI package 115 + 116 + **fix**: ensure `server.json` versions match the git tag and PyPI will build that version 117 + 118 + ### "ownership validation failed" 119 + 120 + **cause**: missing or incorrect `mcp-name:` in README 121 + 122 + **fix**: add `mcp-name: io.github.username/server-name` anywhere in README.md 123 + 124 + ### "failed to install mcp-publisher" 125 + 126 + **cause**: wrong download URL or npm package attempt 127 + 128 + **fix**: use specific version binary download from GitHub releases 129 + 130 + ## resources 131 + 132 + - [MCP registry docs](https://github.com/modelcontextprotocol/registry/tree/main/docs) 133 + - [MCP publisher source](https://github.com/modelcontextprotocol/registry) 134 + - [our workflow](.github/workflows/publish-mcp.yml) 135 + - [our server.json](server.json)