Registry CLI Tool

MCP Publisher CLI Tool

mcp-publisher is the official command-line tool for interacting with the MCP Registry, providing server publishing, authentication, and management capabilities.

Installation

Homebrew (Recommended)

On macOS/Linux using Homebrew:

brew install mcp-publisher

Pre-built Binaries

macOS/Linux/WSL:

curl -L "https://github.com/modelcontextprotocol/registry/releases/download/v1.0.0/mcp-publisher_1.0.0_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/').tar.gz" | tar xz mcp-publisher && sudo mv mcp-publisher /usr/local/bin/

Windows PowerShell:

$arch = if ([System.Runtime.InteropServices.RuntimeInformation]::ProcessArchitecture -eq "Arm64") { "arm64" } else { "amd64" }
Invoke-WebRequest -Uri "https://github.com/modelcontextprotocol/registry/releases/download/v1.0.0/mcp-publisher_1.0.0_windows_$arch.tar.gz" -OutFile "mcp-publisher.tar.gz"
tar xf mcp-publisher.tar.gz mcp-publisher.exe
rm mcp-publisher.tar.gz

Build from Source

git clone https://github.com/modelcontextprotocol/registry
cd registry
make publisher
# Binary will be at bin/mcp-publisher

Global Options

All commands support these options:

  • --help, -h - Show command help
  • --registry - Registry URL (default: https://registry.modelcontextprotocol.io)

Command Reference

mcp-publisher init

Generate a server.json template with automatic detection.

Usage:

mcp-publisher init [options]

Behavior:

  • Creates server.json in current directory
  • Auto-detects package managers (package.json, setup.py, etc.)
  • Pre-fills fields where possible
  • Prompts for missing required fields

Example output:

{
  "name": "io.github.username/server-name",
  "description": "TODO: Add server description",
  "version": "1.0.0",
  "packages": [
    {
      "registry_type": "npm",
      "identifier": "detected-package-name",
      "version": "1.0.0"
    }
  ]
}

mcp-publisher login <method>

Authenticate with the registry.

GitHub Interactive

mcp-publisher login github [--registry=URL]
  • Opens browser for GitHub OAuth flow
  • Grants access to io.github.{username}/* and io.github.{org}/* namespaces

GitHub OIDC (CI/CD)

mcp-publisher login github-oidc [--registry=URL]
  • Uses GitHub Actions OIDC tokens automatically
  • Requires id-token: write permission in workflow
  • No browser interaction needed
For details on publishing from GitHub Actions, see the GitHub Actions automation guide.

DNS Verification

mcp-publisher login dns --domain=example.com --private-key=HEX_KEY [--registry=URL]
  • Verifies domain ownership via DNS TXT record
  • Grants access to com.example.* namespaces
  • Requires Ed25519 private key (64-character hex)

Setup Steps:

# Generate Ed25519 keypair
openssl genpkey -algorithm Ed25519 -out key.pem
# Get public key for DNS record
openssl pkey -in key.pem -pubout -outform DER | tail -c 32 | base64
# Add DNS TXT record:
example.com. IN TXT "v=MCPv1; k=ed25519; p=PUBLIC_KEY"
# Extract private key for login
openssl pkey -in key.pem -noout -text | grep -A3 "priv:" | tail -n +2 | tr -d ' :\n'

HTTP Verification

mcp-publisher login http --domain=example.com --private-key=HEX_KEY [--registry=URL]
  • Verifies domain ownership via HTTPS endpoint
  • Grants access to com.example.* namespaces
  • Requires Ed25519 private key (64-character hex)

Setup:

# Generate keypair (same as DNS)
openssl genpkey -algorithm Ed25519 -out key.pem

# Host public key at:
# https://example.com/.well-known/mcp-registry-auth
# Content: v=MCPv1; k=ed25519; p=PUBLIC_KEY

Anonymous (Testing)

mcp-publisher login none [--registry=URL]
  • No authentication - for local testing only
  • Only works with local registry instances

mcp-publisher publish

Publish server to the registry.

Usage:

mcp-publisher publish [options]

Options:

  • --file=PATH - Path to server.json (default: ./server.json)
  • --registry=URL - Registry URL override
  • --dry-run - Validate without publishing

Process:

  1. Validates server.json against schema
  2. Verifies package ownership (see Official Registry Requirements)
  3. Checks namespace authentication
  4. Publishes to registry

Examples:

# Basic publish
mcp-publisher publish

# Dry run validation
mcp-publisher publish --dry-run

# Custom file location
mcp-publisher publish --file=./config/server.json

mcp-publisher logout

Clear stored authentication credentials.

Usage:

mcp-publisher logout

Behavior:

  • Removes ~/.mcp_publisher_token
  • Does not revoke tokens on server side

Configuration

Token Storage

Authentication tokens stored in ~/.mcp_publisher_token as JSON:

{
  "token": "jwt-token-here",
  "registry_url": "https://registry.modelcontextprotocol.io",
  "expires_at": "2024-12-31T23:59:59Z"
}

Namespaces and Security

Namespace Format

All server names follow reverse-DNS format:

  • io.github.alice/weather-server - GitHub user alice
  • com.acme/internal-tool - Company domain acme.com
  • org.nonprofit.research/data-analyzer - Subdomain research.nonprofit.org

Ownership Verification

Publishing to a namespace requires proving you control the corresponding identity:

GitHub namespaces (io.github.*):

  • OAuth login to GitHub account/organization
  • OIDC tokens in GitHub Actions workflows

Domain namespaces (com.company.*):

  • DNS verification: TXT record at company.com
  • HTTP verification: File at https://company.com/.well-known/mcp-registry-auth

Namespace Scoping

Different authentication methods grant different namespace access:

GitHub OAuth/OIDC:

  • io.github.username/* (for personal accounts)
  • io.github.orgname/* (for organizations)

DNS verification:

  • com.domain/* and com.domain.*/* (domain + all subdomains)

HTTP verification:

  • com.domain/* only (exact domain, no subdomains)

Versioning Best Practices

Semantic Versioning

Server authors SHOULD use semantic versions following the MAJOR.MINOR.PATCH format:

{
  "version": "1.2.3"
}

Align with Package Versions

Server authors SHOULD use versions aligned with their underlying packages to reduce confusion:

{
  "version": "1.2.3",
  "packages": [{
    "registry_type": "npm",
    "identifier": "@myorg/my-server",
    "version": "1.2.3"
  }]
}

Multiple Registry Versions

If you need multiple registry versions for the same package version, use prerelease labels:

{
  "version": "1.2.3-1",
  "packages": [{
    "registry_type": "npm", 
    "identifier": "@myorg/my-server",
    "version": "1.2.3"
  }]
}

Common Use Cases

Basic Workflow

# 1. Initialize server.json
mcp-publisher init

# 2. Edit generated server.json

# 3. Authenticate
mcp-publisher login github

# 4. Publish
mcp-publisher publish

CI/CD Workflow

# In GitHub Actions
mcp-publisher login github-oidc
mcp-publisher publish

Version Updates

# Update version in server.json
# Then republish
mcp-publisher publish

Troubleshooting

“Authentication failed”

  • For OIDC, ensure id-token: write permission is set
  • Check secrets or tokens

“Package validation failed”

  • Verify your package published to your registry (NPM, PyPI etc.) successfully first
  • Ensure you have done the necessary validation steps

“Namespace not authorized”

  • Your authentication method doesn’t match your chosen namespace format

“Version already exists”

  • Each version for a given server name must be unique
  • Use a new version number or prerelease label

Next Steps

Learn the complete server publishing process Set up automated publishing workflows Deep dive into server.json format View complete API documentation
Pro Tip: Use the --dry-run option to validate your server.json configuration before actually publishing.