diff --git a/.github/workflows/publish-mcp-registry.yml b/.github/workflows/publish-mcp-registry.yml new file mode 100644 index 0000000000..19eb53dc37 --- /dev/null +++ b/.github/workflows/publish-mcp-registry.yml @@ -0,0 +1,87 @@ +name: Publish MCP Registry + +# Lists @paperclipai/mcp-server on the official MCP Registry +# (registry.modelcontextprotocol.io). Downstream directories — PulseMCP +# (daily), Glama, mcp.so — ingest from the official registry automatically, +# so this single publish cascades to the ecosystem. +# +# Auth is GitHub OIDC: because this workflow runs inside the `paperclipai` +# org, it is authorized to publish the `io.github.paperclipai/*` namespace +# with NO secrets, tokens, or interactive login required. +# +# Prereq: the published npm package must carry an `mcpName` field matching +# server.json `name` (added in the same PR). The gate step below skips +# gracefully until that published version exists, so this workflow is safe +# to merge before the first mcpName-bearing release lands. + +on: + workflow_dispatch: + inputs: + version: + description: "Published @paperclipai/mcp-server version to list (blank = latest on npm)." + required: false + type: string + push: + tags: + - "canary/v*" + - "v*" + +jobs: + publish: + runs-on: ubuntu-latest + permissions: + id-token: write # required for GitHub OIDC → MCP Registry auth + contents: read + + steps: + - name: Checkout code + uses: actions/checkout@v5 + + - name: Resolve target version + id: v + run: | + if [ -n "${{ github.event.inputs.version }}" ]; then + V="${{ github.event.inputs.version }}" + elif [ "${GITHUB_REF}" != "${GITHUB_REF#refs/tags/}" ]; then + V="${GITHUB_REF##*/v}" + else + V="$(npm view @paperclipai/mcp-server version)" + fi + echo "version=$V" >> "$GITHUB_OUTPUT" + echo "Resolved version: $V" + + - name: Gate — require published mcpName at this version + id: gate + run: | + V="${{ steps.v.outputs.version }}" + NAME="$(npm view @paperclipai/mcp-server@"$V" mcpName 2>/dev/null || true)" + if [ -z "$NAME" ]; then + echo "::notice::@paperclipai/mcp-server@$V does not declare mcpName yet — skipping registry publish (no-op)." + echo "ready=false" >> "$GITHUB_OUTPUT" + else + echo "ready=true" >> "$GITHUB_OUTPUT" + fi + + - name: Sync server.json version to the released package + if: steps.gate.outputs.ready == 'true' + working-directory: packages/mcp-server + env: + V: ${{ steps.v.outputs.version }} + run: | + node -e "const fs=require('fs');const s=JSON.parse(fs.readFileSync('server.json','utf8'));s.version=process.env.V;(s.packages||[]).forEach(p=>{p.version=process.env.V});fs.writeFileSync('server.json',JSON.stringify(s,null,2)+'\n')" + cat server.json + + - name: Install mcp-publisher + if: steps.gate.outputs.ready == 'true' + run: | + curl -L "https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/').tar.gz" | tar xz mcp-publisher + + - name: Authenticate to MCP Registry (GitHub OIDC) + if: steps.gate.outputs.ready == 'true' + working-directory: packages/mcp-server + run: "$GITHUB_WORKSPACE/mcp-publisher" login github-oidc + + - name: Publish to MCP Registry + if: steps.gate.outputs.ready == 'true' + working-directory: packages/mcp-server + run: "$GITHUB_WORKSPACE/mcp-publisher" publish diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index dd4aea8e06..cd0f722bbd 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -1,5 +1,6 @@ { "name": "@paperclipai/mcp-server", + "mcpName": "io.github.paperclipai/mcp-server", "version": "0.1.0", "license": "MIT", "homepage": "https://github.com/paperclipai/paperclip", diff --git a/packages/mcp-server/server.json b/packages/mcp-server/server.json new file mode 100644 index 0000000000..606f49e5fe --- /dev/null +++ b/packages/mcp-server/server.json @@ -0,0 +1,28 @@ +{ + "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json", + "name": "io.github.paperclipai/mcp-server", + "title": "Summon (Paperclip)", + "description": "MCP server for Summon/Paperclip: read and manage issues, comments, approvals, docs, and agents.", + "websiteUrl": "https://summon.company", + "repository": { + "url": "https://github.com/paperclipai/paperclip", + "source": "github" + }, + "version": "2026.707.0", + "packages": [ + { + "registryType": "npm", + "registryBaseUrl": "https://registry.npmjs.org", + "identifier": "@paperclipai/mcp-server", + "version": "2026.707.0", + "transport": { "type": "stdio" }, + "environmentVariables": [ + { "name": "PAPERCLIP_API_URL", "description": "Paperclip API base URL, e.g. https://api.summon.company", "isRequired": true }, + { "name": "PAPERCLIP_API_KEY", "description": "Bearer token used for /api requests", "isRequired": true, "isSecret": true }, + { "name": "PAPERCLIP_COMPANY_ID", "description": "Optional default company for company-scoped tools", "isRequired": false }, + { "name": "PAPERCLIP_AGENT_ID", "description": "Optional default agent for checkout helpers", "isRequired": false }, + { "name": "PAPERCLIP_RUN_ID", "description": "Optional run id forwarded on mutating requests", "isRequired": false } + ] + } + ] +}