Skip to main content

Create a custom MCP registry

Overview

ToolHive includes a built-in registry of MCP servers with verified configurations that meet a minimum quality standard.

But you can also create your own custom registry to include the MCP servers that are relevant to your organization or specific use cases. This allows you to curate a list of servers that meet your specific needs.

Why create a custom registry?

Creating a custom registry allows you to:

  • Curate a list of MCP servers tailored to your organization's needs
  • Include private or internal servers not listed in the public registry
  • Pre-configure server settings for easier deployment
  • Ensure all servers meet your organization's quality and security standards

For production environments, you can also deploy the ToolHive Registry Server to host your registry with authentication, multiple data sources, and automatic synchronization. This tutorial focuses on creating the registry data file itself, which the Registry Server can also consume as a file source.

Create your first custom registry

In this tutorial, you'll create a custom MCP registry for ToolHive and configure it to use your own curated list of MCP servers. By the end, you'll have a working custom registry that you can extend with your organization's specific MCP servers.

What you'll build

You'll create a JSON registry file containing a packaged MCP server and a remote MCP server, configure ToolHive to use your custom registry, and verify it works by listing and running servers from your registry.

Prerequisites

Before you start, make sure you have:

Step 1: Create the registry file

First, create a new directory for your custom registry and navigate to it:

mkdir my-custom-registry
cd my-custom-registry

Create a new file called registry.json and add the following content:

registry.json
{
"$schema": "https://raw.githubusercontent.com/stacklok/toolhive-core/main/registry/types/data/upstream-registry.schema.json",
"version": "1.0.0",
"meta": {
"last_updated": "2025-08-15T10:00:00Z"
},
"data": {
"servers": [
{
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
"name": "corp.acme/my-fetch",
"title": "Acme Web Fetch",
"description": "A custom web content fetching MCP server for our organization",
"repository": {
"url": "https://github.acme.corp/platform/mcp-fetch",
"source": "github"
},
"version": "1.2.1",
"packages": [
{
"registryType": "oci",
"identifier": "ghcr.io/stackloklabs/gofetch/server:latest",
"transport": {
"type": "streamable-http",
"url": "http://localhost:8080"
}
}
],
"_meta": {
"io.modelcontextprotocol.registry/publisher-provided": {
"io.github.stacklok": {
"ghcr.io/stackloklabs/gofetch/server:latest": {
"custom_metadata": {
"author": "Platform Engineering",
"owner": "platform-team@acme.corp",
"internal_ticket": "MCP-042",
"license": "Proprietary"
},
"status": "Active",
"tier": "Community",
"tags": ["web", "fetch", "content"],
"tools": ["fetch"],
"args": [
"--user-agent",
"Mozilla/5.0 (compatible;MyOrgFetchBot/1.0)"
],
"permissions": {
"network": {
"outbound": {
"allow_host": [".example.com", "api.acme.corp"],
"allow_port": [80, 443]
}
}
}
}
}
}
}
},
{
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
"name": "io.github.stacklok/toolhive-doc-mcp-remote",
"description": "Search ToolHive docs for help with using and contributing to the project (hosted version)",
"title": "ToolHive Docs (Remote)",
"version": "1.0.0",
"remotes": [
{
"type": "streamable-http",
"url": "https://toolhive-doc-mcp.stacklok.com/mcp"
}
],
"_meta": {
"io.modelcontextprotocol.registry/publisher-provided": {
"io.github.stacklok": {
"https://toolhive-doc-mcp.stacklok.com/mcp": {
"custom_metadata": {
"author": "Stacklok",
"homepage": "https://github.com/StacklokLabs/toolhive-doc-mcp",
"license": "Apache-2.0"
},
"metadata": {
"last_updated": "2026-04-13T03:04:50Z",
"stars": 3
},
"overview": "The toolhive-doc-mcp-remote server allows you to search ToolHive documentation for help with using and contributing to the project.",
"status": "Active",
"tags": ["remote", "docs", "search", "stacklok"],
"tier": "Official",
"tools": ["query_docs", "get_chunk"]
}
}
}
}
}
]
}
}

This registry contains two MCP server entries in data.servers:

  • my-fetch - a packaged server distributed as a container image, with custom arguments and network permissions
  • toolhive-doc-mcp-remote - a remote server hosted at a URL

Each server entry includes everything ToolHive needs to run it:

  • A title field - the display name shown in the UI and CLI listings
  • A packages entry (for packaged servers) or a remotes entry (for remote servers) describing how to reach the server and its transport type
  • ToolHive-specific metadata (status, tier, tools, permissions, args) in the _meta extension block, keyed by the publisher namespace and the package identifier or remote URL

Both entries also include a custom_metadata block under _meta. This is a free-form object you can use to track whatever information matters to your organization - things like the owning team, an internal ticket reference, a license, or links to internal documentation. ToolHive preserves these fields so they're available wherever you consume the registry.

Step 2: Configure ToolHive to use your registry

Configure ToolHive to use your custom registry.

  1. Open the ToolHive application
  2. Navigate to SettingsRegistry
  3. Select the Local Registry option
  4. Enter the full path to your registry.json file (for example: /Users/<YOUR_NAME>/my-custom-registry/registry.json)
  5. Click Save to apply the configuration

The UI will validate the registry file and confirm it's been set successfully.

Step 3: Test your custom registry

Verify your custom registry is working.

  1. Navigate to the Registry page from the menu bar
  2. You should see your my-fetch and toolhive-doc-mcp-remote servers displayed
  3. Click on a server to view its details, including description, tools, and configuration options

Step 4: Run a server from your registry

Finally, run the MCP server from your custom registry.

  1. On the Registry page, click on your my-fetch server
  2. Click the Install server button
  3. Configure any required settings (the defaults from your registry will be pre-populated)
  4. Click Install server to start the MCP server
  5. Navigate to the MCP Servers page to see your running server and manage it

The server will appear in your MCP servers list, where you can start, stop, view logs, and manage it like any other MCP server.

Step 5: Add more servers (optional)

You can extend your registry by adding more servers to data.servers. For example, add a second server (note this is just an example, it will not function if you try to run it):

registry.json
{
"$schema": "https://raw.githubusercontent.com/stacklok/toolhive-core/main/registry/types/data/upstream-registry.schema.json",
"version": "1.0.0",
"meta": { "last_updated": "2025-08-15T10:00:00Z" },
"data": {
"servers": [
{
// ... existing entries ...
},
{
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
"name": "corp.acme/company-tools",
"title": "Acme Internal Tools",
"description": "Internal company tools and utilities MCP server",
"version": "2.0.3",
"packages": [
{
"registryType": "oci",
"identifier": "registry.acme.corp/mcp/company-tools:v2.0.3",
"transport": { "type": "stdio" },
"environmentVariables": [
{
"name": "COMPANY_API_KEY",
"description": "API key for accessing company internal services",
"isRequired": true,
"isSecret": true
}
]
}
],
"_meta": {
"io.modelcontextprotocol.registry/publisher-provided": {
"io.github.stacklok": {
"registry.acme.corp/mcp/company-tools:v2.0.3": {
"status": "Active",
"tier": "Community",
"tags": ["internal", "company", "tools"],
"tools": [
"get_employee_info",
"create_ticket",
"check_inventory"
]
}
}
}
}
}
]
}
}

After updating the file, the new server is immediately available for ToolHive CLI commands. For the UI, navigate to the registry settings and click Save to see the new server listed.

Production considerations

While this tutorial uses a local file for simplicity, production deployments should harden the registry with:

  • Hosting on a secure HTTP server
  • Version control to track changes to your registry
  • Access controls to prevent unauthorized modifications
  • Automated validation to ensure registry entries follow the schema
  • Regular updates to add new servers and remove deprecated ones

If you host the registry as a static file, point ToolHive at the URL:

thv config set-registry https://registry.acme.corp/mcp-registry.json

For more capable production deployments, run the ToolHive Registry Server. It consumes the same schema you've built in this tutorial as a file source, and adds built-in authentication, multiple data sources, Kubernetes integration, and automatic synchronization. Follow the Registry Server quickstart to deploy your own.

What you've learned

You've successfully:

  • Created a custom MCP registry following the JSON schema
  • Configured ToolHive to use your custom registry
  • Added both packaged and remote MCP servers with proper metadata and permissions
  • Tested your registry by listing and running a server

You can now maintain your own curated list of MCP servers tailored to your organization's needs. The registry can include packaged servers from container registries (public or private) as well as remote servers hosted at a URL.

Next steps

Cleanup: Revert to the default registry

If you want to switch back to using ToolHive's built-in registry after completing this tutorial, you can easily revert your configuration.

To revert to the default registry through the UI:

  1. Navigate to SettingsRegistry
  2. Select the Default Registry option
  3. Click Save to apply the configuration

The UI will confirm that you're now using the built-in ToolHive registry.

After reverting, all registry commands (thv registry list, thv registry info, thv search) will use ToolHive's built-in registry instead of your custom one.