Configuration Reference

July 15, 2026 · View on GitHub

Complete configuration reference for the ToolHive Registry API server.

Table of Contents

Overview

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

Command-line Flags

FlagDescriptionRequiredDefault
--configPath to YAML configuration fileYes-
--addressServer listen addressNo:8080
--auth-modeOverride auth mode (anonymous or oauth)No-

Configuration File Structure

Minimal Configuration

sources:
  - name: default
    file:
      path: /data/registry.json

registries:
  - name: default
    sources: ["default"]

database:
  host: localhost
  port: 5432
  user: registry
  database: registry

Complete Configuration

# Sources define where registry data comes from
sources:
  - name: toolhive
    git:
      repository: https://github.com/stacklok/toolhive-catalog.git
      branch: main
      path: pkg/catalog/toolhive/data/registry-upstream.json
    syncPolicy:
      interval: "30m"
    filter:
      names:
        include: ["official/*"]
        exclude: ["*/deprecated"]
      tags:
        include: ["production"]
        exclude: ["experimental"]

# Registries aggregate one or more sources into a named view (required)
registries:
  - name: default
    sources: ["toolhive"]

# Authentication configuration (required)
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"

Source Configuration

Sources define where registry data comes from. Multiple sources can be configured, each with its own data provider, sync policy, and filters.

Top-Level Fields

FieldTypeRequiredDefaultDescription
sourcesarrayYes-List of data source configurations
registriesarrayYes-List of registry aggregations (at least one required)

Source Entry Fields

FieldTypeRequiredDescription
namestringYesUnique name for this source
gitobjectNo*Git repository configuration
apiobjectNo*API endpoint configuration
fileobjectNo*Local file configuration
managedobjectNo*Managed registry configuration
kubernetesobjectNo*Kubernetes resource configuration
syncPolicyobjectYes†Sync policy configuration
filterobjectNoServer filtering rules
claimsmapNoKey-value pairs for authorization purposes

* Exactly one data source must be configured per source entry † Required for synced sources (git, api, file); not applicable for managed or kubernetes sources

Registry Entry Fields

The registries: block aggregates sources into named registry views. At least one registry must be configured.

FieldTypeRequiredDescription
namestringYesUnique name for this registry
sourcesarrayYesOrdered list of source names that feed this registry
claimsmapNoKey-value pairs for authorization purposes

Data Sources

Git Repository

Clone and sync from Git repositories. Ideal for version-controlled registries.

git:
  repository: https://github.com/stacklok/toolhive-catalog.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/catalog/toolhive/data/registry-upstream.json
  auth:                           # Optional: for private repos
    username: user
    passwordFile: /secrets/git-password

Fields:

FieldTypeRequiredDescription
repositorystringYesGit repository URL (HTTPS or SSH)
branchstringNoBranch name (default: default branch)
tagstringNoTag name (mutually exclusive with branch/commit)
commitstringNoCommit SHA (mutually exclusive with branch/tag)
pathstringYesPath to registry JSON file within repo
auth.usernamestringNoGit username for private repos
auth.passwordFilestringNoPath to file containing Git password/token

Supports:

  • Automatic background synchronization
  • Per-registry filtering
  • Branch, tag, or commit pinning

API Endpoint

Sync from upstream MCP Registry APIs. Ideal for federation scenarios.

api:
  endpoint: https://registry.example.com
  timeout: 30s

Fields:

FieldTypeRequiredDescription
endpointstringYesBase API URL (without path); the server appends MCP Registry API v0.1 paths automatically
timeoutstringNoPer-request HTTP timeout as a Go duration (e.g. 30s, 1m). Defaults to 10s; must be greater than 0 and at most 5m. Raise this for public or occasionally-slow upstreams where individual requests can take longer.

Supports:

  • Automatic background synchronization
  • Per-registry filtering

Local File

Read from local filesystem. Ideal for development and testing.

file:
  path: /data/registry.json

Fields:

FieldTypeRequiredDescription
pathstringYesAbsolute path to registry JSON file

Supports:

  • Automatic background synchronization (monitors file changes)
  • Per-registry filtering

Managed

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

Kubernetes

Discover MCP servers from Kubernetes deployments.

kubernetes:
  namespaces:                    # Optional: specific namespaces to watch
    - default

Fields:

FieldTypeRequiredDescription
namespacesarrayNoKubernetes namespaces to watch (empty = uses THV_REGISTRY_WATCH_NAMESPACE env var)

Per-entry claims: CRDs can carry per-entry authorization claims via the toolhive.stacklok.dev/authz-claims JSON annotation. The annotation value uses the same map[string]any format as source claims (strings or arrays of strings). Source claims are not merged — entries get exactly the claims from the annotation. Entries without the annotation have no claims and are invisible when authz is configured (default-deny).

# Example CRD annotation for per-entry claims:
metadata:
  annotations:
    toolhive.stacklok.dev/authz-claims: '{"team": "platform"}'

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

Sync Policy

Controls automatic background synchronization for Git, API, and File registries.

syncPolicy:
  interval: "30m"                # Sync interval

Fields:

FieldTypeRequiredDefaultDescription
intervalstringYes-Sync interval (e.g., "30m", "1h", "24h")

Not applicable for:

  • Managed registries (no sync)
  • Kubernetes registries (no sync)

Filtering

Filter which servers are exposed from a registry.

filter:
  names:
    include: ["official/*", "approved/*"]
    exclude: ["*/deprecated", "*/test"]
  tags:
    include: ["production", "stable"]
    exclude: ["experimental", "beta"]

Fields:

FieldTypeDescription
names.includearrayInclude servers matching these patterns (glob)
names.excludearrayExclude servers matching these patterns (glob)
tags.includearrayInclude servers with these tags
tags.excludearrayExclude servers with these tags

Behavior:

  1. If include is specified, only matching servers are included
  2. exclude is then applied to remove servers
  3. Both name patterns and tags are evaluated
  4. 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)

Authentication

See detailed Authentication Guide.

Quick Reference

auth:
  mode: oauth                    # "oauth" (default) or "anonymous"
  publicPaths:                   # Optional: additional public paths
    - /metrics
  oauth:
    resourceUrl: https://registry.example.com
    realm: mcp-registry          # Optional
    providers:
      - name: my-idp
        issuerUrl: https://idp.example.com
        audience: api://registry
        clientId: client-id      # Optional
        clientSecretFile: /secrets/secret  # Optional
        caCertPath: /certs/ca.crt  # Optional

Database

See detailed Database Guide.

Quick Reference

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"                       # Optional

Password management: Passwords can be provided via THV_REGISTRY_DATABASE_PASSWORD / THV_REGISTRY_DATABASE_MIGRATIONPASSWORD environment variables, the password / migrationPassword config fields, or PostgreSQL's pgpass file (~/.pgpass or $PGPASSFILE). See Database Configuration for details.

Environment Variables

Configuration values can be overridden using environment variables with the THV_REGISTRY_ prefix. For complete documentation, see Environment Variables Guide.

Common Configuration Overrides

VariableDescription
THV_REGISTRY_DATABASE_HOSTOverride database host
THV_REGISTRY_DATABASE_PORTOverride database port
THV_REGISTRY_DATABASE_USEROverride database user
THV_REGISTRY_AUTH_MODEOverride authentication mode (anonymous or oauth)
THV_REGISTRY_LOG_LEVELSet log level (debug, info, warn, error)

Database Passwords

VariableDescription
THV_REGISTRY_DATABASE_PASSWORDDatabase password for the application user
THV_REGISTRY_DATABASE_MIGRATIONPASSWORDDatabase password for the migration user
PGPASSFILEPath to pgpass file (default: ~/.pgpass) — used as fallback when password env vars are not set

See Database Configuration for password management details.

Other

VariableDescription
CONFIG_FILEOverride config file path
THV_REGISTRY_INSECURE_URLAllow HTTP URLs for development (default: false)

Examples

Development (Local File)

sources:
  - name: local
    file:
      path: ./examples/registry-sample.json

auth:
  mode: anonymous

database:
  host: localhost
  port: 5432
  user: registry
  database: registry
  sslMode: disable

Production (Git + Database + OAuth)

sources:
  - name: toolhive
    git:
      repository: https://github.com/stacklok/toolhive-catalog.git
      branch: main
      path: pkg/catalog/toolhive/data/registry-upstream.json
    syncPolicy:
      interval: "15m"
    filter:
      names:
        include: ["official/*"]
      tags:
        exclude: ["experimental"]

registries:
  - name: default
    sources: ["toolhive"]

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"

Multi-Registry Setup

sources:
  # Official ToolHive registry
  - name: toolhive
    git:
      repository: https://github.com/stacklok/toolhive-catalog.git
      branch: main
      path: pkg/catalog/toolhive/data/registry-upstream.json
    syncPolicy:
      interval: "30m"

  # Company internal registry
  - name: internal
    api:
      endpoint: https://internal-registry.company.com
    syncPolicy:
      interval: "1h"
    filter:
      tags:
        include: ["approved"]

  # Managed registry for custom servers
  - name: custom
    managed: {}

  # Kubernetes-deployed servers
  - name: k8s-deployed
    kubernetes:
      namespaces:
        - mcp-servers

registries:
  - name: default
    sources: ["toolhive", "internal", "custom", "k8s-deployed"]

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: registry

Validation

The 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

See Also