> ## Documentation Index
> Fetch the complete documentation index at: https://modelcontextprotocol.io/llms.txt
> Use this file to discover all available pages before exploring further.

# How to Automate Publishing with GitHub Actions

<Note>
  The MCP Registry is currently in preview. Breaking changes or data resets may occur before general availability. If you encounter any issues, please report them on [GitHub](https://github.com/modelcontextprotocol/registry/issues).
</Note>

## Step 1: Create a Workflow File

In your server project directory, create a `.github/workflows/publish-mcp.yml` file. Here is an example for npm-based local server, but the MCP Registry publishing steps are the same for all package types:

<CodeGroup>
  ```yaml OIDC authentication (recommended) theme={null}
  name: Publish to MCP Registry

  on:
    push:
      tags: ["v*"] # Triggers on version tags like v1.0.0

  jobs:
    publish:
      runs-on: ubuntu-latest
      permissions:
        id-token: write # Required for OIDC authentication
        contents: read

      steps:
        - name: Checkout code
          uses: actions/checkout@v5

        ### Publish underlying npm package:

        - name: Set up Node.js
          uses: actions/setup-node@v5
          with:
            node-version: "lts/*"

        - name: Install dependencies
          run: npm ci

        - name: Run tests
          run: npm run test --if-present

        - name: Build package
          run: npm run build --if-present

        - name: Publish package to npm
          run: npm publish
          env:
            NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

        ### Publish MCP server:

        - name: Install mcp-publisher
          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
          run: ./mcp-publisher login github-oidc

        # Optional:
        # - name: Set version in server.json
        #   run: |
        #     VERSION=${GITHUB_REF#refs/tags/v}
        #     jq --arg v "$VERSION" '.version = $v' server.json > server.tmp && mv server.tmp server.json

        - name: Publish server to MCP Registry
          run: ./mcp-publisher publish
  ```

  ```yaml PAT authentication theme={null}
  name: Publish to MCP Registry

  on:
    push:
      tags: ["v*"] # Triggers on version tags like v1.0.0

  jobs:
    publish:
      runs-on: ubuntu-latest
      permissions:
        contents: read

      steps:
        - name: Checkout code
          uses: actions/checkout@v5

        ### Publish underlying npm package:

        - name: Set up Node.js
          uses: actions/setup-node@v5
          with:
            node-version: "lts/*"

        - name: Install dependencies
          run: npm ci

        - name: Run tests
          run: npm run test --if-present

        - name: Build package
          run: npm run build --if-present

        - name: Publish package to npm
          run: npm publish
          env:
            NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

        ### Publish MCP server:

        - name: Install mcp-publisher
          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
          run: ./mcp-publisher login github --token ${{ secrets.MCP_GITHUB_TOKEN }}

        # Optional:
        # - name: Set version in server.json
        #   run: |
        #     VERSION=${GITHUB_REF#refs/tags/v}
        #     jq --arg v "$VERSION" '.version = $v' server.json > server.tmp && mv server.tmp server.json

        - name: Publish server to MCP Registry
          run: ./mcp-publisher publish
  ```

  ```yaml DNS authentication theme={null}
  name: Publish to MCP Registry

  on:
    push:
      tags: ["v*"] # Triggers on version tags like v1.0.0

  jobs:
    publish:
      runs-on: ubuntu-latest
      permissions:
        contents: read

      steps:
        - name: Checkout code
          uses: actions/checkout@v5

        ### Publish underlying npm package:

        - name: Set up Node.js
          uses: actions/setup-node@v5
          with:
            node-version: "lts/*"

        - name: Install dependencies
          run: npm ci

        - name: Run tests
          run: npm run test --if-present

        - name: Build package
          run: npm run build --if-present

        - name: Publish package to npm
          run: npm publish
          env:
            NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

        ### Publish MCP server:

        - name: Install mcp-publisher
          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

        # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        # TODO: Replace `example.com` with your domain name
        # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        - name: Authenticate to MCP Registry
          run: ./mcp-publisher login dns --domain example.com --private-key ${{ secrets.MCP_PRIVATE_KEY }}

        # Optional:
        # - name: Set version in server.json
        #   run: |
        #     VERSION=${GITHUB_REF#refs/tags/v}
        #     jq --arg v "$VERSION" '.version = $v' server.json > server.tmp && mv server.tmp server.json

        - name: Publish server to MCP Registry
          run: ./mcp-publisher publish
  ```
</CodeGroup>

## Step 2: Add Secrets

You may need to add a secret to the repository depending on which authentication method you choose:

* **GitHub OIDC Authentication**: No dedicated secret necessary.
* **GitHub PAT Authentication**: Add a `MCP_GITHUB_TOKEN` secret with a GitHub Personal Access Token (PAT) that has `read:org` and `read:user` scopes.
* **DNS Authentication**: Add a `MCP_PRIVATE_KEY` secret with your Ed25519 private key.

You may also need to add secrets for your package registry. For example, the workflow above needs an `NPM_TOKEN` secret with your npm token.

For information about how to add secrets to a repository, see [Using secrets in GitHub Actions](https://docs.github.com/en/actions/how-tos/write-workflows/choose-what-workflows-do/use-secrets).

## Step 3: Tag and Release

Create and push a version tag to trigger the workflow:

```bash theme={null}
git tag v1.0.0
git push origin v1.0.0
```

The workflow will run tests, build the package, publish the package to npm, and publish the server to the MCP Registry.

## Troubleshooting

| Error Message               | Action                                                                                                                                                                     |
| --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| "Authentication failed"     | Ensure `id-token: write` permission is set for OIDC, or check secrets.                                                                                                     |
| "Package validation failed" | Verify your package successfully published to the package registry (e.g., npm, PyPI), and that your package has the [necessary verification information](./package-types). |
