# Publish Your MCP Server Complete guide to publishing an MCP server to the registry. ## What You'll Learn By the end of this tutorial, you'll have: - Created a server.json file for your MCP server - Authenticated with the registry - Successfully published your server - Verified your server appears in the registry ## Prerequisites - An MCP server you've already built ([follow this guide if you don't have one already](https://modelcontextprotocol.io/quickstart/server)) - Your server published to a package registry (npm, PyPI, Docker Hub, etc.) ## Step 1: Install the Publisher CLI Download and build the MCP publisher tool: ```bash # Clone the registry repository (requires Go 1.24+) git clone https://github.com/modelcontextprotocol/registry cd registry make publisher # The binary will be at cmd/publisher/bin/mcp-publisher export PATH=$PATH:$(pwd)/cmd/publisher/bin ``` ## Step 2: Initialize Your server.json Navigate to your server's directory and create a template: ```bash cd /path/to/your/mcp-server mcp-publisher init ``` This creates a `server.json` with auto-detected values. You'll see something like: ```json { "$schema": "https://static.modelcontextprotocol.io/schemas/2025-07-09/server.schema.json", "name": "io.github.yourname/your-server", "description": "A description of your MCP server", "version_detail": { "version": "1.0.0" }, "packages": [ { "registry_type": "npm", "identifier": "your-package-name", "version": "1.0.0" } ] } ``` ## Step 3: Configure Your Server Details Edit the generated `server.json`: ### Choose Your Namespace The `name` field determines authentication requirements: - **`io.github.yourname/*`** - Requires GitHub authentication - **`com.yourcompany/*`** - Requires DNS or HTTP domain verification ### Add Package Validation Your package must include validation metadata to prove ownership.
📦 NPM Packages ### Requirements Add an `mcpName` field to your `package.json`: ```json { "name": "your-npm-package", "version": "1.0.0", "mcpName": "io.github.username/server-name" } ``` ### How It Works - Registry fetches `https://registry.npmjs.org/your-npm-package` - Checks that `mcpName` field matches your server name - Fails if field is missing or doesn't match ### Example server.json ```json { "name": "io.github.username/server-name", "packages": [ { "registry_type": "npm", "identifier": "your-npm-package", "version": "1.0.0" } ] } ``` The official MCP registry currently only supports the NPM public registry (`https://registry.npmjs.org`).
🐍 PyPI Packages ### Requirements Include your server name in your package README file using this format: **MCP name format**: `mcp-name: io.github.username/server-name` Add it to your README.md file (which becomes the package description on PyPI). ### How It Works - Registry fetches `https://pypi.org/pypi/your-package/json` - Passes if `mcp-name: server-name` is in the README content ### Example server.json ```json { "name": "io.github.username/server-name", "packages": [ { "registry_type": "pypi", "identifier": "your-pypi-package", "version": "1.0.0" } ] } ``` The official MCP registry currently only supports the official PyPI registry (`https://pypi.org`).
📋 NuGet Packages ### Requirements Include your server name in your package's README using this format: **MCP name format**: `mcp-name: io.github.username/server-name` Add a README file to your NuGet package that includes the server name. ### How It Works - Registry fetches README from `https://api.nuget.org/v3-flatcontainer/{id}/{version}/readme` - Passes if `mcp-name: server-name` is found in the README content ### Example server.json ```json { "name": "io.github.username/server-name", "packages": [ { "registry_type": "nuget", "identifier": "Your.NuGet.Package", "version": "1.0.0" } ] } ``` The official MCP registry currently only supports the official NuGet registry (`https://api.nuget.org`).
🐳 Docker/OCI Images ### Requirements Add an annotation to your Docker image: ```dockerfile LABEL io.modelcontextprotocol.server.name="io.github.username/server-name" ``` ### How It Works - Registry authenticates with Docker Hub using public token - Fetches image manifest using Docker Registry v2 API - Checks that `io.modelcontextprotocol.server.name` annotation matches your server name - Fails if annotation is missing or doesn't match ### Example server.json ```json { "name": "io.github.username/server-name", "packages": [ { "registry_type": "oci", "identifier": "yourusername/your-mcp-server", "version": "1.0.0" } ] } ``` The identifier is `namespace/repository`, and version is the tag and optionally digest. The official MCP registry currently only supports the official Docker registry (`https://docker.io`).
📁 MCPB Packages ### Requirements **MCP reference** - MCPB package URLs must contain "mcp" somewhere within them, to ensure the correct artifact has been uploaded. This may be with the `.mcpb` extension or in the name of your repository. ### Example server.json ```json { "name": "io.github.username/server-name", "packages": [ { "registry_type": "mcpb", "identifier": "https://github.com/you/your-repo/releases/download/v1.0.0/server.mcpb" } ] } ``` The official MCP registry currently only supports artifacts hosted on GitHub or GitLab releases.
## Step 4: Authenticate Choose your authentication method based on your namespace: ### GitHub Authentication (for io.github.* namespaces) ```bash mcp-publisher login github ``` This opens your browser for OAuth authentication. ### DNS Authentication (for custom domains) ```bash # Generate keypair openssl genpkey -algorithm Ed25519 -out key.pem # Get public key for DNS record echo "_mcp-registry.yourcompany.com. IN TXT \"v=MCPv1; k=ed25519; p=$(openssl pkey -in key.pem -pubout -outform DER | tail -c 32 | base64)\"" # Add the TXT record to your DNS, then login mcp-publisher login dns --domain yourcompany.com --private-key $(openssl pkey -in key.pem -noout -text | grep -A3 "priv:" | tail -n +2 | tr -d ' :\n') ``` ## Step 5: Publish Your Server With authentication complete, publish your server: ```bash mcp-publisher publish ``` You'll see output like: ``` ✓ Validating server.json ✓ Checking package ownership ✓ Publishing to registry ✓ Server published successfully! Your server is now available at: https://registry.modelcontextprotocol.io/servers/io.github.yourname/weather-server ``` ## Step 6: Verify Publication Check that your server appears in the registry: ```bash curl https://registry.modelcontextprotocol.io/servers/io.github.yourname/weather-server ``` You should see your server metadata returned as JSON. ## Troubleshooting **"Package validation failed"** - Ensure your package includes the required validation metadata (mcpName field, README mention, or Docker label). **"Authentication failed"** - Verify you've correctly set up DNS records or are logged into the right GitHub account. **"Namespace not authorized"** - Your authentication method doesn't match your chosen namespace format. ## Next Steps - **Update your server**: Publish new versions with updated server.json files - **Set up CI/CD**: Automate publishing with [GitHub Actions](github-actions.md) - **Learn more**: Understand [server.json format](../../reference/server-json/generic-server-json.md) in depth ## What You've Accomplished You've successfully published your first MCP server to the registry! Your server is now discoverable by MCP clients and can be installed by users worldwide.