Add registry validators (#350)
Fixes #96 ## Motivation and Context See #96 ## How Has This Been Tested? Has some unit and integration tests, still needs proper testing of the different registry types ## Breaking Changes Yes, new package uploads will need extra verification ## Types of changes <!-- What types of changes does your code introduce? Put an `x` in all the boxes that apply: --> - [ ] Bug fix (non-breaking change which fixes an issue) - [x] New feature (non-breaking change which adds functionality) - [x] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update
This commit is contained in:
parent
6ea3828e3c
commit
694a4d8879
2 changed files with 1859 additions and 728 deletions
|
|
@ -1,218 +1,40 @@
|
|||
# MCP Registry Publisher Tool
|
||||
# MCP Publisher Tool - Development
|
||||
|
||||
The MCP Registry Publisher Tool helps you publish Model Context Protocol (MCP) servers to the official registry. It follows a simple, npm-like workflow that's familiar to most developers.
|
||||
CLI tool for publishing MCP servers to the registry.
|
||||
|
||||
## Installation
|
||||
> These docs are for contributors. See the [Publisher User Guide](../../docs/publisher/guide.md) for end-user documentation.
|
||||
|
||||
## Quick Development Setup
|
||||
|
||||
```bash
|
||||
# Build for current platform
|
||||
./build.sh
|
||||
# Build the tool
|
||||
make publisher
|
||||
|
||||
# Build for all supported platforms (optional)
|
||||
./build.sh --all
|
||||
# Test locally
|
||||
make dev-compose # Start local registry
|
||||
./bin/mcp-publisher init
|
||||
./bin/mcp-publisher login none --registry=http://localhost:8080
|
||||
./bin/mcp-publisher publish --registry=http://localhost:8080
|
||||
```
|
||||
|
||||
The compiled binary will be placed in the `bin` directory.
|
||||
## Architecture
|
||||
|
||||
## Quick Start
|
||||
### Commands
|
||||
- **`init`** - Generate server.json templates with auto-detection
|
||||
- **`login`** - Handle authentication (github, dns, http, none)
|
||||
- **`publish`** - Validate and upload servers to registry
|
||||
- **`logout`** - Clear stored credentials
|
||||
|
||||
```bash
|
||||
# 1. Create a template server.json file
|
||||
mcp-publisher init
|
||||
### Authentication Providers
|
||||
- **`github`** - Interactive OAuth flow
|
||||
- **`github-oidc`** - CI/CD with GitHub Actions
|
||||
- **`dns`** - Domain verification via DNS TXT records
|
||||
- **`http`** - Domain verification via HTTPS endpoints
|
||||
- **`none`** - No auth (testing only)
|
||||
|
||||
# 2. Edit server.json with your server details
|
||||
## Key Files
|
||||
|
||||
# 3. Authenticate with the registry (one-time setup)
|
||||
mcp-publisher login <method>
|
||||
|
||||
# 4. Publish your server
|
||||
mcp-publisher publish
|
||||
```
|
||||
|
||||
## Commands
|
||||
|
||||
### `mcp-publisher init`
|
||||
|
||||
Creates a template `server.json` file with smart defaults. This command automatically detects values from your environment when possible.
|
||||
|
||||
```bash
|
||||
mcp-publisher init
|
||||
```
|
||||
|
||||
Auto-detection sources:
|
||||
- **Git remote origin** for repository URL and server name
|
||||
- **package.json** for npm packages (name, description)
|
||||
- **pyproject.toml** for Python packages
|
||||
- **Current directory** for fallback naming
|
||||
|
||||
The generated file includes placeholder values that you should update before publishing.
|
||||
|
||||
### `mcp-publisher login <method>`
|
||||
|
||||
Authenticates with the MCP registry. You'll only need to do this once - the tool saves your credentials locally.
|
||||
|
||||
```bash
|
||||
# GitHub interactive authentication
|
||||
mcp-publisher login github
|
||||
|
||||
# GitHub Actions OIDC (for CI/CD)
|
||||
mcp-publisher login github-oidc
|
||||
|
||||
# DNS-based authentication
|
||||
mcp-publisher login dns --domain example.com --private-key abc123...
|
||||
|
||||
# HTTP-based authentication
|
||||
mcp-publisher login http --domain example.com --private-key abc123...
|
||||
```
|
||||
|
||||
**Authentication Methods:**
|
||||
|
||||
- **`github`**: Interactive GitHub OAuth flow. Opens browser for authentication.
|
||||
- **`github-oidc`**: For GitHub Actions. Uses OIDC tokens automatically.
|
||||
- **`dns`**: Domain-based auth using DNS TXT records. Requires `--domain` and `--private-key`.
|
||||
- **`http`**: Domain-based auth using HTTPS endpoint. Requires `--domain` and `--private-key`.
|
||||
|
||||
### `mcp-publisher publish`
|
||||
|
||||
Publishes your `server.json` file to the registry. You must be logged in first.
|
||||
|
||||
```bash
|
||||
mcp-publisher publish
|
||||
```
|
||||
|
||||
This command:
|
||||
- Validates your `server.json` file
|
||||
- Checks your authentication
|
||||
- Uploads the server configuration to the registry
|
||||
|
||||
### `mcp-publisher logout`
|
||||
|
||||
Clears your saved authentication credentials.
|
||||
|
||||
```bash
|
||||
mcp-publisher logout
|
||||
```
|
||||
|
||||
## GitHub Actions
|
||||
|
||||
For automated publishing from GitHub Actions:
|
||||
|
||||
```yaml
|
||||
name: Publish to MCP Registry
|
||||
on:
|
||||
push:
|
||||
tags: ['v*']
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
id-token: write # Required for OIDC
|
||||
contents: read
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup MCP Publisher
|
||||
run: |
|
||||
curl -LO https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher-linux-amd64
|
||||
chmod +x mcp-publisher-linux-amd64
|
||||
|
||||
- name: Login to Registry
|
||||
run: ./mcp-publisher-linux-amd64 login github-oidc
|
||||
|
||||
- name: Publish to Registry
|
||||
run: ./mcp-publisher-linux-amd64 publish
|
||||
```
|
||||
|
||||
The `login github-oidc` command uses GitHub's OIDC tokens for authentication in CI environments.
|
||||
|
||||
## Examples
|
||||
|
||||
### Publishing an NPM-based server
|
||||
|
||||
```bash
|
||||
# Create template server.json (auto-detects from package.json)
|
||||
# Then edit server.json to add your specific details
|
||||
mcp-publisher init
|
||||
|
||||
# Login (first time only)
|
||||
mcp-publisher login github
|
||||
|
||||
# Publish
|
||||
mcp-publisher publish
|
||||
```
|
||||
|
||||
### Publishing a Python server
|
||||
|
||||
```bash
|
||||
# Create template server.json (auto-detects from pyproject.toml)
|
||||
# Then edit server.json to add your specific details
|
||||
mcp-publisher init
|
||||
|
||||
# Publish (assuming already logged in)
|
||||
mcp-publisher publish
|
||||
```
|
||||
|
||||
### Publishing with DNS authentication
|
||||
|
||||
```bash
|
||||
# Setup DNS TXT record first (see DNS Authentication section below)
|
||||
|
||||
# Login with DNS
|
||||
mcp-publisher login dns --domain example.com --private-key YOUR_PRIVATE_KEY
|
||||
|
||||
# Publish
|
||||
mcp-publisher publish
|
||||
```
|
||||
|
||||
## Authentication Details
|
||||
|
||||
### DNS Authentication
|
||||
|
||||
For domain-based authentication using DNS:
|
||||
|
||||
1. Generate an Ed25519 keypair:
|
||||
```bash
|
||||
openssl genpkey -algorithm Ed25519 -out /tmp/key.pem && \
|
||||
echo "DNS TXT Record:" && \
|
||||
echo " v=MCPv1; k=ed25519; p=$(openssl pkey -in /tmp/key.pem -pubout -outform DER | tail -c 32 | base64)" && \
|
||||
echo "" && \
|
||||
echo "Private key for login:" && \
|
||||
echo " $(openssl pkey -in /tmp/key.pem -noout -text | grep -A3 "priv:" | tail -n +2 | tr -d ' :\n')" && \
|
||||
rm /tmp/key.pem
|
||||
```
|
||||
|
||||
2. Add the TXT record to your domain's DNS
|
||||
|
||||
3. Login with:
|
||||
```bash
|
||||
mcp-publisher login dns --domain example.com --private-key YOUR_PRIVATE_KEY
|
||||
```
|
||||
|
||||
This grants publishing rights for `example.com/*` and `*.example.com/*` namespaces.
|
||||
|
||||
### HTTP Authentication
|
||||
|
||||
For HTTP-based authentication:
|
||||
|
||||
1. Generate an Ed25519 keypair (same as DNS)
|
||||
|
||||
2. Host the public key at `https://yoursite.com/.well-known/mcp-registry-auth`:
|
||||
```
|
||||
v=MCPv1; k=ed25519; p=YOUR_PUBLIC_KEY_BASE64
|
||||
```
|
||||
|
||||
3. Login with:
|
||||
```bash
|
||||
mcp-publisher login http --domain example.com --private-key YOUR_PRIVATE_KEY
|
||||
```
|
||||
|
||||
This grants publishing rights for the `example.com/*` namespace.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**"Not authenticated" error**: Run `mcp-publisher login <method>` to authenticate (e.g., `mcp-publisher login github`).
|
||||
|
||||
**"Invalid server.json" error**: Ensure your `server.json` file is valid. You can recreate it with `mcp-publisher init`.
|
||||
|
||||
**GitHub Actions failing**: Ensure your workflow has `id-token: write` permission and you're using `mcp-publisher login github-oidc`.
|
||||
- **`main.go`** - CLI setup and command routing
|
||||
- **`commands/`** - Command implementations with auto-detection logic
|
||||
- **`auth/`** - Authentication provider implementations
|
||||
- **`build.sh`** - Cross-platform build script
|
||||
|
|
|
|||
|
|
@ -47,7 +47,6 @@ func main() {
|
|||
switch cfg.DatabaseType {
|
||||
case config.DatabaseTypeMemory:
|
||||
db = database.NewMemoryDB()
|
||||
registryService = service.NewRegistryServiceWithDB(db)
|
||||
case config.DatabaseTypePostgreSQL:
|
||||
// Use PostgreSQL for real registry service
|
||||
// Create a context with timeout for PostgreSQL connection
|
||||
|
|
@ -61,10 +60,6 @@ func main() {
|
|||
return
|
||||
}
|
||||
|
||||
// Create registry service with PostgreSQL
|
||||
registryService = service.NewRegistryServiceWithDB(db)
|
||||
log.Printf("PostgreSQL database URL: %s", cfg.DatabaseURL)
|
||||
|
||||
// Store the PostgreSQL instance for later cleanup
|
||||
defer func() {
|
||||
if err := db.Close(); err != nil {
|
||||
|
|
@ -78,6 +73,8 @@ func main() {
|
|||
return
|
||||
}
|
||||
|
||||
registryService = service.NewRegistryService(db, cfg)
|
||||
|
||||
// Import seed data if seed source is provided
|
||||
if cfg.SeedFrom != "" {
|
||||
log.Printf("Importing data from %s...", cfg.SeedFrom)
|
||||
|
|
|
|||
Loading…
Reference in a new issue