Skip to content

stacklok/toolhive-registry-server

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

454 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
ToolHive logo

Release Build status Coverage Status License: Apache 2.0 Star on GitHub Discord

ToolHive Registry Server

The central metadata hub for enterprise MCP governance and discovery

The ToolHive Registry Server (thv-registry-api) implements the official Model Context Protocol (MCP) Registry API specification. It serves as the centralized metadata engine for the ToolHive platform, enabling enterprises to curate, discover, and govern MCP servers with security and auditability built-in.


Table of contents

Features

Enterprise governance & security

  • OAuth 2.0/OIDC authentication: Integrate with enterprise identity providers (Okta, Auth0, Azure AD)
  • Multi-provider support: Combine corporate SSO with Kubernetes service accounts
  • Secure by default: OAuth mode enabled by default, with granular access control
  • Audit trail: Track MCP discovery and access through centralized metadata

Flexible registry sources

  • Curated registries: Aggregate multiple sources into a unified catalog
  • Upstream verified: Sync from public MCP registries implementing the standard API
  • File-based registries: Support both ToolHive and upstream server.json formats
  • Internal custom MCPs: Manage organization-specific MCP servers
  • Kubernetes discovery: Automatically discover MCPs deployed in your clusters
  • Automatic synchronization: Background sync with configurable intervals and retry logic

Enterprise integration

  • Central metadata hub: Powers the ToolHive Enterprise UI with MCP metadata
  • ToolHive Operator integration: Provides metadata for Kubernetes-native MCP deployment
  • PostgreSQL backend: Scalable database storage with automatic migrations
  • Standards-compliant: Implements the official MCP Registry API specification
  • Production-ready: Built-in health checks, graceful shutdown, and observability

Quickstart

Prerequisites

  • Go 1.23 or later (for building from source)
  • Task for build automation
  • PostgreSQL 16+ (optional, for database backend)

Build and run

# Build the binary
task build

# Run with Git source
thv-registry-api serve --config examples/config-git.yaml

# Run with local file
thv-registry-api serve --config examples/config-file.yaml

The server starts on http://localhost:8080 by default.

Docker quickstart

# Using Task (recommended - ensures fresh state)
task docker-up

# Or detached mode
task docker-up-detached

# Access the API
curl http://localhost:8080/registry/v0.1/servers

# Stop and clean up
task docker-down

Note: The task docker-up command ensures a fresh start by rebuilding the image and clearing all volumes (database + registry data). This prevents stale state issues.

What happens on startup

  1. Loads configuration from YAML file
  2. Runs database migrations automatically (if configured)
  3. Immediately fetches registry data from configured sources
  4. Starts background sync coordinator for automatic updates
  5. Serves MCP Registry API endpoints

Core concepts

Data sources

The Registry Server enables enterprises to curate MCP catalogs from multiple sources, creating a unified view for developers and knowledge workers:

Type Description Enterprise Use Case Sync
API Upstream MCP Registry APIs Official MCP Registry (registry.modelcontextprotocol.io) or any registry implementing the upstream specification βœ… Auto
Git Clone from Git repositories Version-controlled internal registries βœ… Auto
File Read from local filesystem Simple curated lists in ToolHive or upstream format βœ… Auto
Managed API-managed registry Internal custom MCPs (dynamically managed) ❌ On-demand
Kubernetes Discover from K8s deployments Organization-deployed MCPs (live discovery) ❌ On-demand

Key capability: Configure multiple registries simultaneously to create a federated catalog that combines:

  • Official MCP Registry (registry.modelcontextprotocol.io) or any registry implementing the upstream specification
  • Internal organization-specific MCPs
  • Kubernetes-deployed MCPs
  • Custom curated collections

Configuration example:

sources:
  - name: local
    format: toolhive
    file:
      path: /data/registry.json

registries:
  - name: my-registry
    sources:
      - local

For Git-based sources:

sources:
  - name: toolhive
    format: toolhive
    git:
      repository: https://github.com/stacklok/toolhive-catalog.git
      branch: main
      path: pkg/catalog/toolhive/data/registry.json
    syncPolicy:
      interval: '30m'

registries:
  - name: my-registry
    sources:
      - toolhive

See Configuration Guide for complete details.

Architecture

The server follows clean architecture with clear separation of concerns:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  API Layer (Chi Router)                     β”‚
β”‚  β”œβ”€ Registry API v0.1                       β”‚
β”‚  β”œβ”€ Admin API v1                            β”‚
β”‚  └─ OAuth/OIDC Middleware                   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                    β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Service Layer (RegistryService)            β”‚
β”‚  └─ PostgreSQL backend                      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                    β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Data Source Layer                          β”‚
β”‚  β”œβ”€ Git Handler                             β”‚
β”‚  β”œβ”€ API Handler                             β”‚
β”‚  β”œβ”€ File Handler                            β”‚
β”‚  β”œβ”€ Managed Handler                         β”‚
β”‚  └─ Kubernetes Handler                      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                    β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Sync Layer (Background Coordinator)        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Key directories:

  • internal/api/ - HTTP API handlers
  • internal/service/ - Business logic
  • internal/sources/ - Data source handlers
  • internal/sync/ - Background synchronization
  • internal/auth/ - OAuth/OIDC authentication
  • internal/db/ - Database access (sqlc generated)
  • internal/config/ - Configuration loading
  • internal/app/ - Application builder and startup
  • internal/telemetry/ - OpenTelemetry integration
  • database/ - SQL migrations and queries

API endpoints

Registry API v0.1 (read-only, standards-compliant)

Fully compatible with the upstream MCP Registry API specification:

  • GET /registry/{registryName}/v0.1/servers - List servers from a specific registry
  • GET /registry/{registryName}/v0.1/servers/{name}/versions - List all versions of a server
  • GET /registry/{registryName}/v0.1/servers/{name}/versions/{version} - Get a specific server version

Note: Git, API, File, and Kubernetes sources are read-only through the registry API.

Admin API v1

ToolHive-specific endpoints for managing sources, registries, and entries:

Source management (requires manageSources role):

  • GET /v1/sources - List all configured sources
  • GET /v1/sources/{name} - Get a source by name
  • PUT /v1/sources/{name} - Create or update a source
  • DELETE /v1/sources/{name} - Delete a source
  • GET /v1/sources/{name}/entries - List entries for a source

Registry management (reads: authenticated; writes require manageRegistries role):

  • GET /v1/registries - List all configured registries with status
  • GET /v1/registries/{name} - Get registry details and sync status
  • GET /v1/registries/{name}/entries - List entries for a registry
  • PUT /v1/registries/{name} - Create or update a registry
  • DELETE /v1/registries/{name} - Delete a registry

Entry management (requires manageEntries role):

  • POST /v1/entries - Publish a server or skill entry
  • DELETE /v1/entries/{type}/{name}/versions/{version} - Delete a published entry
  • PUT /v1/entries/{type}/{name}/claims - Update entry claims

Operational endpoints

  • GET /health - Health check
  • GET /readiness - Readiness check
  • GET /version - Version information
  • GET /.well-known/oauth-protected-resource - OAuth discovery (RFC 9728)

Use cases

  • Registry API: Standards-compliant MCP discovery for clients and upstream integrations
  • Admin API: Manage sources and registries, publish entries, query registry status

See the MCP Registry API specification for full API details.

Configuration

All configuration is done via YAML files. The server requires a --config flag.

Basic example

sources:
  - name: local
    format: toolhive
    file:
      path: /data/registry.json

registries:
  - name: my-registry
    sources:
      - local

auth:
  mode: anonymous # Use "oauth" for production

# Optional: Add a Git-based source
# sources:
#   - name: toolhive
#     format: toolhive
#     git:
#       repository: https://github.com/stacklok/toolhive-catalog.git
#       branch: main
#       path: pkg/catalog/toolhive/data/registry.json
#     syncPolicy:
#       interval: "30m"
# registries:
#   - name: my-registry
#     sources:
#       - toolhive

# Optional: Database backend
# database:
#   host: localhost
#   port: 5432
#   user: registry
#   database: registry

πŸ“– Complete guides

Configuration examples

See examples/ directory for complete working examples:

  • config-git.yaml - Git repository source
  • config-api.yaml - API endpoint source
  • config-file.yaml - Local file source
  • config-database-dev.yaml - With database (development)
  • config-database-prod.yaml - With database (production)
  • config-docker.yaml - For Docker Compose

Deployment

Docker Compose

Quick start with PostgreSQL (ensures fresh state):

# Start with fresh state (recommended)
task docker-up

# Or detached mode
task docker-up-detached

# View logs
task docker-logs           # All logs
FOLLOW=true task docker-logs  # Tail logs

# Stop and clean up
task docker-down

Note: Always use task docker-up instead of docker-compose up directly. The task command ensures fresh state by rebuilding the image and clearing volumes.

See Docker deployment guide for details.

Kubernetes

Basic deployment:

kubectl apply -f examples/kubernetes/

See Kubernetes deployment guide for production setup.

Standalone binary

# Linux/macOS
./bin/thv-registry-api serve --config config.yaml

# With environment variables
export THV_REGISTRY_DATABASE_HOST=postgres.example.com
export THV_REGISTRY_AUTH_MODE=anonymous
./bin/thv-registry-api serve --config config.yaml

πŸ“– Deployment guides

Development

Build commands

# Build the binary
task build

# Run linting (auto-fix)
task lint-fix

# Run tests
task test

# Generate mocks
task gen

# Build container image
task build-image

# Run database migrations
task migrate-up CONFIG=examples/config-database-dev.yaml

# Regenerate documentation
task docs

# All checks (lint + test + build)
task all

Testing

# Generate mocks before testing
task gen

# Run all tests
task test

# Run specific test
go test ./internal/service/... -v

The project uses table-driven tests with mocks generated via go.uber.org/mock.

Project structure

cmd/thv-registry-api/    # Main application
β”œβ”€β”€ app/                 # CLI commands (serve, migrate, prime-db, version)
└── main.go

internal/                # Internal packages
β”œβ”€β”€ api/                 # HTTP API handlers
β”œβ”€β”€ auth/                # OAuth/OIDC authentication
β”œβ”€β”€ config/              # Configuration loading
β”œβ”€β”€ db/                  # Database access (sqlc generated)
β”œβ”€β”€ service/             # Business logic
β”œβ”€β”€ sources/             # Data source handlers (Git, API, File, Managed, Kubernetes)
β”œβ”€β”€ sync/                # Background sync coordination
β”œβ”€β”€ app/                 # Application builder and startup
β”œβ”€β”€ filtering/           # Registry entry filtering
β”œβ”€β”€ telemetry/           # OpenTelemetry integration
β”œβ”€β”€ validators/          # Input validation
└── registry/            # Registry data models

database/                # Database schema and queries
β”œβ”€β”€ migrations/          # SQL migrations
└── queries/             # SQL queries for sqlc

examples/                # Example configurations
docs/                    # Documentation

Documentation

πŸ“š Complete documentation

Common Tasks

I want to... See...
Get started quickly Quickstart
Configure the server Configuration reference
Set up PostgreSQL Database setup
Enable authentication Authentication guide
Deploy to Kubernetes Kubernetes guide
Use Docker Compose Docker guide
Contribute code Contributing

Integration with ToolHive

The Registry API server is the central metadata engine of the ToolHive platform:

Enterprise UI integration

  • Metadata source: Provides MCP details (name, description, URL, version, branding)
  • Server status: Reports sync status and availability for each registry
  • Discovery experience: Powers the catalog browsing and search in the Enterprise UI
  • Authentication: Enforces OAuth/OIDC access control from your identity provider

ToolHive Operator integration

  • Deployment metadata: Operator references registry data when deploying MCPs to Kubernetes
  • Automated discovery: Kubernetes-deployed MCPs automatically appear in the registry
  • Custom Resource binding: MCPRegistry CRDs are backed by Registry Server data
  • Lifecycle management: Tracks deployed MCP versions and configurations

Security & governance

  • Centralized control: Single source of truth for approved MCPs
  • Identity integration: Seamless integration with Okta, Auth0, Azure AD, and other providers
  • Kubernetes-native: All MCP execution stays within your Kubernetes boundary
  • Audit trail: Track MCP discovery and consumption patterns

See the ToolHive documentation for the complete platform architecture.

Contributing

We welcome contributions! Please see:

Development guidelines

  • Run task lint-fix before committing
  • Ensure tests pass with task test
  • Follow Go standard project layout
  • Use mockgen for test mocks (never hand-written)
  • Write table-driven tests
  • Keep documentation up to date

Quick start for contributors

# Clone the repository
git clone https://github.com/stacklok/toolhive-registry-server.git
cd toolhive-registry-server

# Install dependencies
go mod download

# Run all checks
task all

# Make your changes...

# Run tests
task gen
task test

# Submit PR

License

This project is licensed under the Apache 2.0 License.


Part of the ToolHive project - Simplify and secure MCP servers

About

An API server that implements the official MCP Registry API, providing standardised access to MCP servers from multiple backends, including file-based and other API-compliant registries.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages