{"id":37940559,"url":"https://github.com/stacklok/toolhive-registry-server","last_synced_at":"2026-04-12T11:11:15.561Z","repository":{"id":319246466,"uuid":"1073637195","full_name":"stacklok/toolhive-registry-server","owner":"stacklok","description":"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.","archived":false,"fork":false,"pushed_at":"2026-01-26T20:52:51.000Z","size":2871,"stargazers_count":14,"open_issues_count":31,"forks_count":6,"subscribers_count":3,"default_branch":"main","last_synced_at":"2026-01-27T01:55:44.701Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/stacklok.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":"MAINTAINERS.md","copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-10T11:58:48.000Z","updated_at":"2026-01-26T14:27:15.000Z","dependencies_parsed_at":"2026-01-16T19:02:12.101Z","dependency_job_id":null,"html_url":"https://github.com/stacklok/toolhive-registry-server","commit_stats":null,"previous_names":["stacklok/toolhive-registry-server"],"tags_count":21,"template":false,"template_full_name":null,"purl":"pkg:github/stacklok/toolhive-registry-server","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stacklok%2Ftoolhive-registry-server","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stacklok%2Ftoolhive-registry-server/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stacklok%2Ftoolhive-registry-server/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stacklok%2Ftoolhive-registry-server/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stacklok","download_url":"https://codeload.github.com/stacklok/toolhive-registry-server/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stacklok%2Ftoolhive-registry-server/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28853194,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-28T15:15:36.453Z","status":"ssl_error","status_checked_at":"2026-01-28T15:15:13.020Z","response_time":57,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-01-16T17:43:41.175Z","updated_at":"2026-04-12T11:11:15.554Z","avatar_url":"https://github.com/stacklok.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cpicture\u003e\n  \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"docs/images/toolhive-byline-white.svg\"\u003e\n  \u003cimg src=\"docs/images/toolhive-byline-black.svg\" alt=\"ToolHive logo\" width=\"500\"/\u003e\n\u003c/picture\u003e\n\n\u003cbr\u003e\n\n[![Release][release-img]][release] [![Build status][ci-img]][ci]\n[![Coverage Status][coveralls-img]][coveralls]\n[![License: Apache 2.0][license-img]][license]\n[![Star on GitHub][stars-img]][stars] [![Discord][discord-img]][discord]\n\n# ToolHive Registry Server\n\n**Discover, govern, and control access to MCP servers and skills across your organization**\n\nThe ToolHive Registry Server aggregates MCP servers and skills from Git repos, Kubernetes clusters, upstream registries, and internal APIs into named catalogs that your teams and AI clients can query. Each catalog has its own access control and audit trail, so you decide which entries are visible to which users -- and have a record of who accessed what.\n\nIt implements the official [Model Context Protocol (MCP) Registry API specification](https://modelcontextprotocol.io/development/roadmap#registry). If you're not familiar with MCP: it's an open protocol that lets AI assistants connect to external tools and data sources. This server is the governance layer that sits between your MCP infrastructure and the teams consuming it.\n\n---\n\n## Table of contents\n\n- [Features](#features)\n- [Quickstart](#quickstart)\n- [Core Concepts](#core-concepts)\n- [API Endpoints](#api-endpoints)\n- [Configuration](#configuration)\n- [The ToolHive Platform](#the-toolhive-platform)\n- [Documentation](#documentation)\n- [Contributing](#contributing)\n\n## Features\n\n### Governance and access control\n\n- **JWT claim-based visibility**: Control which MCP servers and skills each user or team can see, per registry. A \"production\" registry can expose only vetted entries while a \"dev-team\" registry shows everything.\n- **OAuth 2.0/OIDC authentication**: Plug in your existing identity provider (Okta, Auth0, Azure AD). OAuth is the default; anonymous mode is available for development.\n- **Role-based administration**: Separate roles for managing sources, registries, and entries. Scope each role to specific JWT claims so teams manage their own resources.\n- **SIEM-compliant audit logging**: Structured log covering all API operations with NIST SP 800-53 AU-3 compliant fields, dedicated file output, and configurable event filtering.\n\n### Aggregate from anywhere\n\n- **Five source types**: Pull entries from Git repos, upstream MCP registries, local files, Kubernetes clusters, or publish them via the Admin API.\n- **Compose catalogs from multiple sources**: Each registry aggregates one or more sources, listed in order of precedence. One source can feed multiple registries, so the same internal catalog can serve different teams with different visibility rules.\n- **Background sync**: Sources are polled on configurable intervals with retry logic. Registries stay current without manual intervention.\n\n### Kubernetes and observability\n\n- **Kubernetes-native discovery**: A built-in reconciler watches for MCP server CRDs across namespaces and syncs them into the registry automatically. Per-entry access control via CRD annotations, multi-namespace support, and leader election for HA.\n- **OpenTelemetry**: Distributed tracing and metrics out of the box.\n- **Standards-compliant**: Implements the official MCP Registry API specification. Clients that speak the spec work out of the box.\n- **PostgreSQL backend**: Database storage with automatic migrations.\n\n## Quickstart\n\n### Prerequisites\n\n- Go 1.26 or later (for building from source)\n- [Task](https://taskfile.dev) for build automation\n- PostgreSQL 16+\n\n### Build and run\n\n```bash\n# Build the binary\ntask build\n\n# Run with Git source\nthv-registry-api serve --config examples/config-git.yaml\n\n# Run with local file\nthv-registry-api serve --config examples/config-file.yaml\n```\n\nThe server starts on `http://localhost:8080` by default.\n\n### Docker quickstart\n\n```bash\n# Using Task (recommended - ensures fresh state)\ntask docker-up\n\n# Or detached mode\ntask docker-up-detached\n\n# Access the API\ncurl http://localhost:8080/registry/default/v0.1/servers\n\n# Stop and clean up\ntask docker-down\n```\n\n\u003e **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.\n\n## Core concepts\n\n### Sources and registries\n\nMost organizations have MCP servers and skills in more than one place -- a public catalog, an internal Git repo, a Kubernetes cluster running live instances. The Registry Server models this with two primitives: **sources** (where entries come from) and **registries** (what consumers query).\n\nA **source** is a connection to where MCP server and skill entries live. It tells the server \"go look here for entries.\" Sources come in five types:\n\n| Type           | What it does                        | Example                                                      | Sync         |\n| -------------- | ----------------------------------- | ------------------------------------------------------------ | ------------ |\n| **API**        | Pulls from an upstream registry API | The official MCP Registry at registry.modelcontextprotocol.io | Auto         |\n| **Git**        | Clones entries from a Git repo      | A version-controlled internal catalog                        | Auto         |\n| **File**       | Reads from the local filesystem     | A curated `registry.json` on disk                            | Auto         |\n| **Managed**    | Entries published via the Admin API | Dynamically registered internal servers                      | On-demand    |\n| **Kubernetes** | Discovers deployed MCP servers      | Servers running in your K8s clusters                         | On-demand    |\n\nA **registry** is a named catalog that aggregates one or more sources into a single consumer-facing endpoint. Each registry can pull from different sources and enforce its own access control via JWT claims. Sources are listed in order -- when the same entry appears in multiple sources, the first source in the list wins.\n\n**Why they are separate**: Sources and registries have a many-to-many relationship. One source can feed multiple registries, and one registry can pull from multiple sources. This lets you compose different catalogs for different audiences from the same underlying data:\n\n```text\nSource: \"official-catalog\"  ──┐\nSource: \"internal-tools\"    ──┼──\u003e Registry: \"production\"  (curated, vetted)\n                              │\nSource: \"internal-tools\"    ──┼──\u003e Registry: \"dev-team\"    (everything)\nSource: \"k8s-deployed\"      ──┘\n```\n\nIn this example, the \"production\" registry only exposes vetted entries from the official catalog and internal tools, while the \"dev-team\" registry includes everything plus live Kubernetes-discovered servers.\n\n**Configuration example:**\n\n```yaml\nsources:\n  - name: official-catalog\n    format: upstream\n    api:\n      endpoint: https://registry.modelcontextprotocol.io\n    syncPolicy:\n      interval: \"1h\"\n\n  - name: internal-tools\n    format: toolhive\n    git:\n      repository: https://github.com/myorg/mcp-catalog.git\n      branch: main\n      path: registry.json\n    syncPolicy:\n      interval: \"30m\"\n\nregistries:\n  - name: production\n    sources:\n      - official-catalog\n      - internal-tools\n\n  - name: dev-team\n    sources:\n      - internal-tools\n```\n\nSee [Configuration Guide](docs/configuration.md) for complete details.\n\n## API endpoints\n\n### Registry API v0.1 (read-only, standards-compliant)\n\nFully compatible with the upstream MCP Registry API specification:\n\n- `GET /registry/{registryName}/v0.1/servers` - List servers from a specific registry\n- `GET /registry/{registryName}/v0.1/servers/{name}/versions` - List all versions of a server\n- `GET /registry/{registryName}/v0.1/servers/{name}/versions/{version}` - Get a specific server version\n\n**Note:** Git, API, File, and Kubernetes sources are read-only through the registry API.\n\n### Admin API v1\n\nToolHive-specific endpoints for managing sources, registries, and entries:\n\n**Source management** (requires `manageSources` role):\n\n- `GET /v1/sources` - List all configured sources\n- `GET /v1/sources/{name}` - Get a source by name\n- `PUT /v1/sources/{name}` - Create or update a source\n- `DELETE /v1/sources/{name}` - Delete a source\n- `GET /v1/sources/{name}/entries` - List entries for a source\n\n**Registry management** (reads: authenticated; writes require `manageRegistries` role):\n\n- `GET /v1/registries` - List all configured registries with status\n- `GET /v1/registries/{name}` - Get registry details and sync status\n- `GET /v1/registries/{name}/entries` - List entries for a registry (requires `manageRegistries` role)\n- `PUT /v1/registries/{name}` - Create or update a registry\n- `DELETE /v1/registries/{name}` - Delete a registry\n\n**Entry management** (requires `manageEntries` role):\n\n- `POST /v1/entries` - Publish a server or skill entry\n- `DELETE /v1/entries/{type}/{name}/versions/{version}` - Delete a published entry\n- `PUT /v1/entries/{type}/{name}/claims` - Update entry claims\n\n### Skills extension API (ToolHive-specific)\n\nRead-only endpoints for discovering skills within a registry:\n\n- `GET /registry/{registryName}/v0.1/x/dev.toolhive/skills` - List skills (paginated)\n- `GET /registry/{registryName}/v0.1/x/dev.toolhive/skills/{namespace}/{name}` - Get latest version of a skill\n- `GET /registry/{registryName}/v0.1/x/dev.toolhive/skills/{namespace}/{name}/versions` - List all versions of a skill\n- `GET /registry/{registryName}/v0.1/x/dev.toolhive/skills/{namespace}/{name}/versions/{version}` - Get a specific skill version\n\n### Operational endpoints\n\n- `GET /health` - Health check\n- `GET /readiness` - Readiness check\n- `GET /version` - Version information\n- `GET /v1/me` - Returns the caller's identity and roles\n- `GET /.well-known/oauth-protected-resource` - OAuth discovery (RFC 9728)\n\n### Use cases\n\n- **Registry API**: Standards-compliant MCP discovery for clients and upstream integrations\n- **Admin API**: Manage sources and registries, publish entries, query registry status\n\nSee the [MCP Registry API specification](https://github.com/modelcontextprotocol/registry/blob/main/docs/reference/api/openapi.yaml) for full API details.\n\n## Configuration\n\nAll configuration is done via YAML files. The server requires a `--config` flag.\n\n### Basic example\n\n```yaml\nsources:\n  - name: local\n    format: toolhive\n    file:\n      path: /data/registry.json\n\nregistries:\n  - name: my-registry\n    sources:\n      - local\n\nauth:\n  mode: anonymous # Use \"oauth\" for production\n\ndatabase:\n  host: localhost\n  port: 5432\n  user: registry\n  database: registry\n```\n\n### Complete guides\n\n- **[Configuration reference](docs/configuration.md)** - Complete configuration options\n- **[Environment variables](docs/environment-variables.md)** - Using environment variables for configuration\n- **[Database setup](docs/database.md)** - PostgreSQL configuration, migrations, and security\n- **[Authentication](docs/authentication.md)** - OAuth/OIDC setup and security\n\n## The ToolHive platform\n\nThe Registry Server is one component of the [ToolHive](https://github.com/stacklok/toolhive) platform. Together, they cover the full MCP lifecycle:\n\n- **Registry Server** (this project) handles discovery and governance -- it knows what MCP servers and skills exist, who can access them, and tracks all operations.\n- **[ToolHive Operator](https://github.com/stacklok/toolhive)** handles deployment -- it deploys and manages MCP servers on Kubernetes, using registry metadata to drive lifecycle decisions. MCP servers deployed by the Operator automatically appear in the registry.\n- **ToolHive Enterprise UI** ties it all together -- catalog browsing, search, and admin management backed by the registry API.\n\nSee the [ToolHive documentation](https://docs.stacklok.com/toolhive/) for the complete platform architecture.\n\n## Documentation\n\n- **[Configuration reference](docs/configuration.md)** - All configuration options\n- **[Environment variables](docs/environment-variables.md)** - Environment variable overrides\n- **[Database setup](docs/database.md)** - PostgreSQL setup and migrations\n- **[Authentication](docs/authentication.md)** - OAuth/OIDC security\n- **[Observability](docs/observability.md)** - OpenTelemetry tracing and metrics\n- **[Registry sync](docs/registry-sync.md)** - How background sync works\n- **[Kubernetes deployment](docs/deployment-kubernetes.md)** - K8s deployment and HA\n- **[Docker deployment](docs/deployment-docker.md)** - Docker Compose setup\n- **[API documentation](docs/thv-registry-api/)** - Auto-generated OpenAPI docs\n- **[CLI reference](docs/cli/)** - Command-line interface docs\n- **[Examples](examples/)** - Working configuration examples\n\n## Contributing\n\nWe welcome contributions! See the **[Contributing guide](CONTRIBUTING.md)** to get started, including development setup, build commands, architecture overview, and project structure.\n\n- **[Code of conduct](CODE_OF_CONDUCT.md)** - Community guidelines\n- **[Security policy](SECURITY.md)** - Report security vulnerabilities\n\n## License\n\nThis project is licensed under the [Apache 2.0 License](LICENSE).\n\n---\n\n**Part of the [ToolHive](https://github.com/stacklok/toolhive) project** - Simplify and secure MCP servers\n\n\u003c!-- Badge links --\u003e\n\u003c!-- prettier-ignore-start --\u003e\n[release-img]: https://img.shields.io/github/v/release/stacklok/toolhive-registry-server?style=flat\u0026label=Latest%20version\n[release]: https://github.com/stacklok/toolhive-registry-server/releases/latest\n[ci-img]: https://img.shields.io/github/actions/workflow/status/stacklok/toolhive-registry-server/run-on-main.yml?style=flat\u0026logo=github\u0026label=Build\n[ci]: https://github.com/stacklok/toolhive-registry-server/actions/workflows/run-on-main.yml\n[coveralls-img]: https://coveralls.io/repos/github/stacklok/toolhive-registry-server/badge.svg?branch=main\n[coveralls]: https://coveralls.io/github/stacklok/toolhive-registry-server?branch=main\n[license-img]: https://img.shields.io/badge/License-Apache2.0-blue.svg?style=flat\n[license]: https://opensource.org/licenses/Apache-2.0\n[stars-img]: https://img.shields.io/github/stars/stacklok/toolhive-registry-server.svg?style=flat\u0026logo=github\u0026label=Stars\n[stars]: https://github.com/stacklok/toolhive-registry-server\n[discord-img]: https://img.shields.io/discord/1184987096302239844?style=flat\u0026logo=discord\u0026logoColor=white\u0026label=Discord\n[discord]: https://discord.gg/stacklok\n\u003c!-- prettier-ignore-end --\u003e\n\n\u003c!-- markdownlint-disable-file first-line-heading no-emphasis-as-heading no-inline-html --\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstacklok%2Ftoolhive-registry-server","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstacklok%2Ftoolhive-registry-server","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstacklok%2Ftoolhive-registry-server/lists"}