Complete configuration reference for the ToolHive Registry API server.
- Overview
- Configuration File Structure
- Registry Configuration
- Data Sources
- Sync Policy
- Filtering
- Authentication
- Database
- Environment Variables
- Examples
All configuration is done via YAML files. The server requires a --config flag pointing to a configuration file.
thv-registry-api serve --config config.yaml| Flag | Description | Required | Default |
|---|---|---|---|
--config |
Path to YAML configuration file | Yes | - |
--address |
Server listen address | No | :8080 |
--auth-mode |
Override auth mode (anonymous or oauth) | No | - |
registryName: my-registry
registries:
- name: default
format: toolhive
file:
path: /data/registry.json
database:
host: localhost
port: 5432
user: registry
database: registry# Registry name/identifier (optional, defaults to "default")
registryName: my-registry
# Registries configuration - multiple registries can be configured
registries:
- name: toolhive
format: toolhive
git:
repository: https://github.com/stacklok/toolhive.git
branch: main
path: pkg/registry/data/registry.json
syncPolicy:
interval: "30m"
filter:
names:
include: ["official/*"]
exclude: ["*/deprecated"]
tags:
include: ["production"]
exclude: ["experimental"]
# Authentication configuration (optional, defaults to OAuth)
auth:
mode: oauth
oauth:
resourceUrl: https://registry.example.com
providers:
- name: my-idp
issuerUrl: https://idp.example.com
audience: api://registry
# Database configuration (required)
database:
host: localhost
port: 5432
user: registry
database: registry
sslMode: require
maxOpenConns: 25
maxIdleConns: 5
connMaxLifetime: "5m"Multiple registries can be configured, each with its own data source and settings.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
registryName |
string | No | default |
Global registry name identifier |
registries |
array | Yes | - | List of registry configurations |
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Unique name for this registry |
format |
string | Yes | Data format: toolhive or upstream |
git |
object | No* | Git repository configuration |
api |
object | No* | API endpoint configuration |
file |
object | No* | Local file configuration |
managed |
object | No* | Managed registry configuration |
kubernetes |
object | No* | Kubernetes resource configuration |
syncPolicy |
object | No | Sync policy configuration |
filter |
object | No | Server filtering rules |
* Exactly one data source must be configured per registry
Clone and sync from Git repositories. Ideal for version-controlled registries.
git:
repository: https://github.com/stacklok/toolhive.git
branch: main # Optional: defaults to default branch
tag: v1.0.0 # Optional: use specific tag
commit: abc123 # Optional: pin to specific commit
path: pkg/registry/data/registry.json
auth: # Optional: for private repos
username: user
passwordFile: /secrets/git-passwordFields:
| Field | Type | Required | Description |
|---|---|---|---|
repository |
string | Yes | Git repository URL (HTTPS or SSH) |
branch |
string | No | Branch name (default: default branch) |
tag |
string | No | Tag name (mutually exclusive with branch/commit) |
commit |
string | No | Commit SHA (mutually exclusive with branch/tag) |
path |
string | Yes | Path to registry JSON file within repo |
auth.username |
string | No | Git username for private repos |
auth.passwordFile |
string | No | Path to file containing Git password/token |
Supports:
- Automatic background synchronization
- Per-registry filtering
- Branch, tag, or commit pinning
Sync from upstream MCP Registry APIs. Ideal for federation scenarios.
api:
url: https://registry.example.com/v0.1
headers: # Optional: custom headers
Authorization: Bearer token
timeout: 30s # Optional: request timeoutFields:
| Field | Type | Required | Description |
|---|---|---|---|
url |
string | Yes | API endpoint URL |
headers |
map | No | Custom HTTP headers |
timeout |
string | No | Request timeout (default: "30s") |
Supports:
- Automatic background synchronization
- Per-registry filtering
- Format conversion (upstream → toolhive)
Read from local filesystem. Ideal for development and testing.
file:
path: /data/registry.jsonFields:
| Field | Type | Required | Description |
|---|---|---|---|
path |
string | Yes | Absolute path to registry JSON file |
Supports:
- Automatic background synchronization (monitors file changes)
- Per-registry filtering
Directly managed via API. No external data source.
managed: {}Features:
- Create, update, and delete servers through API calls
- No background synchronization
- Requires database backend
- Ideal for custom, dynamically-managed registries
Does NOT support:
- Sync policy configuration
- Filtering configuration
Discover MCP servers from Kubernetes deployments.
kubernetes:
namespace: default # Optional: specific namespace
labelSelector: # Optional: filter by labels
app: mcp-serverFields:
| Field | Type | Required | Description |
|---|---|---|---|
namespace |
string | No | Kubernetes namespace (empty = all namespaces) |
labelSelector |
map | No | Label selector for filtering pods |
Features:
- Queries running Kubernetes resources
- No background synchronization (on-demand only)
- Requires in-cluster service account or kubeconfig
Does NOT support:
- Sync policy configuration
- Filtering configuration
Controls automatic background synchronization for Git, API, and File registries.
syncPolicy:
interval: "30m" # Sync interval
retryInterval: "5m" # Retry interval on failure
retryLimit: 3 # Maximum retry attemptsFields:
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
interval |
string | No | 30m |
Sync interval (e.g., "30m", "1h", "24h") |
retryInterval |
string | No | 5m |
Retry interval on sync failure |
retryLimit |
int | No | 3 |
Maximum number of retry attempts |
Not applicable for:
- Managed registries (no sync)
- Kubernetes registries (no sync)
Filter which servers are exposed from a registry.
filter:
names:
include: ["official/*", "approved/*"]
exclude: ["*/deprecated", "*/test"]
tags:
include: ["production", "stable"]
exclude: ["experimental", "beta"]Fields:
| Field | Type | Description |
|---|---|---|
names.include |
array | Include servers matching these patterns (glob) |
names.exclude |
array | Exclude servers matching these patterns (glob) |
tags.include |
array | Include servers with these tags |
tags.exclude |
array | Exclude servers with these tags |
Behavior:
- If
includeis specified, only matching servers are included excludeis then applied to remove servers- Both name patterns and tags are evaluated
- Empty filter = no filtering (all servers included)
Pattern matching:
- Uses glob patterns (wildcards:
*,?,[...]) - Examples:
official/*,company/*/stable,*-prod
Not applicable for:
- Managed registries (controlled via API)
- Kubernetes registries (use labelSelector instead)
See detailed Authentication Guide.
auth:
mode: oauth # "oauth" (default) or "anonymous"
publicPaths: # Optional: additional public paths
- /metrics
oauth:
resourceUrl: https://registry.example.com
realm: mcp-registry # Optional
scopesSupported: # Optional
- mcp-registry:read
- mcp-registry:write
providers:
- name: my-idp
issuerUrl: https://idp.example.com
audience: api://registry
clientId: client-id # Optional
clientSecretFile: /secrets/secret # Optional
caCertPath: /certs/ca.crt # OptionalSee detailed Database Guide.
database:
host: localhost
port: 5432
user: registry_app
migrationUser: registry_migrator # Optional
database: toolhive_registry
sslMode: require # disable, require, verify-ca, verify-full
maxOpenConns: 25 # Optional
maxIdleConns: 5 # Optional
connMaxLifetime: "5m" # OptionalPassword management:
Passwords are provided via PostgreSQL's standard pgpass file (~/.pgpass or $PGPASSFILE). See Database Configuration for details.
Configuration values can be overridden using environment variables with the THV_REGISTRY_ prefix. For complete documentation, see Environment Variables Guide.
| Variable | Description |
|---|---|
THV_REGISTRY_DATABASE_HOST |
Override database host |
THV_REGISTRY_DATABASE_PORT |
Override database port |
THV_REGISTRY_DATABASE_USER |
Override database user |
THV_REGISTRY_AUTH_MODE |
Override authentication mode (anonymous or oauth) |
THV_REGISTRY_LOG_LEVEL |
Set log level (debug, info, warn, error) |
Database passwords are managed via PostgreSQL's pgpass file:
| Variable | Description |
|---|---|
PGPASSFILE |
Path to pgpass file (default: ~/.pgpass) |
See Database Configuration for password management details.
| Variable | Description |
|---|---|
CONFIG_FILE |
Override config file path |
THV_REGISTRY_INSECURE_URL |
Allow HTTP URLs for development (default: false) |
registryName: dev-registry
registries:
- name: local
format: toolhive
file:
path: ./examples/registry-sample.json
auth:
mode: anonymous
database:
host: localhost
port: 5432
user: registry
database: registry
sslMode: disableregistryName: prod-registry
registries:
- name: toolhive
format: toolhive
git:
repository: https://github.com/stacklok/toolhive.git
branch: main
path: pkg/registry/data/registry.json
syncPolicy:
interval: "15m"
retryLimit: 5
filter:
names:
include: ["official/*"]
tags:
exclude: ["experimental"]
auth:
mode: oauth
oauth:
resourceUrl: https://registry.company.com
providers:
- name: company-sso
issuerUrl: https://auth.company.com
audience: api://toolhive-registry
database:
host: postgres.production.svc.cluster.local
port: 5432
user: registry_app
migrationUser: registry_migrator
database: toolhive_registry
sslMode: verify-full
maxOpenConns: 50
maxIdleConns: 10
connMaxLifetime: "1h"registryName: multi-registry
registries:
# Official ToolHive registry
- name: toolhive
format: toolhive
git:
repository: https://github.com/stacklok/toolhive.git
branch: main
path: pkg/registry/data/registry.json
syncPolicy:
interval: "30m"
# Company internal registry
- name: internal
format: upstream
api:
url: https://internal-registry.company.com/v0.1
headers:
Authorization: Bearer ${INTERNAL_REGISTRY_TOKEN}
syncPolicy:
interval: "1h"
filter:
tags:
include: ["approved"]
# Managed registry for custom servers
- name: custom
format: toolhive
managed: {}
# Kubernetes-deployed servers
- name: k8s-deployed
format: toolhive
kubernetes:
namespace: mcp-servers
labelSelector:
environment: production
auth:
mode: oauth
oauth:
resourceUrl: https://registry.company.com
providers:
- name: company-sso
issuerUrl: https://auth.company.com
audience: api://registry
- name: kubernetes
issuerUrl: https://kubernetes.default.svc
audience: https://kubernetes.default.svc
database:
host: postgres
port: 5432
user: registry
database: registryThe configuration is validated on startup. Common validation errors:
- Missing required fields: Ensure all required fields are present
- Invalid data source: Exactly one data source must be configured per registry
- Invalid duration format: Use format like "30m", "1h", "24h"
- Invalid auth mode: Must be "anonymous" or "oauth"
- Missing OAuth providers: At least one provider required when mode is "oauth"
- Invalid filter patterns: Check glob pattern syntax
- Database connection: Verify connection parameters
Run with --debug flag for detailed validation output:
thv-registry-api serve --config config.yaml --debug- Database Configuration - Detailed database setup
- Authentication - OAuth and security
- Kubernetes Deployment - Kubernetes configuration examples
- Docker Deployment - Docker configuration examples
- examples/ - Complete configuration examples