---
title: "An MCP Server Registry Built Into Your Gateway"
description: "Zuplo gateways can expose their MCP routes through the standard MCP Server Registry API. The read-only catalog is generated from live route config, so there is no second datastore to maintain."
canonicalUrl: "https://zuplo.com/blog/2026/08/20/mcp-server-registry-gateway"
pageType: "blog"
date: "2026-08-20"
authors: "nate"
tags: "MCP, AI Gateway"
image: "https://zuplo.com/og?text=An%20MCP%20Server%20Registry%20Built%20Into%20Your%20Gateway"
---
Once you put several MCP servers behind a gateway, you have two things to
maintain: the routes themselves and the list of URLs handed to every client. The
second one tends to end up in agent config files, an internal catalog, or a wiki
that ages badly.

The Zuplo MCP Gateway now exposes that list through the
[MCP Server Registry API](https://github.com/modelcontextprotocol/registry). It
builds the registry from your live routes, so there is no catalog to populate or
synchronize.

<CalloutAudience
  variant="useIf"
  items={[
    `You run multiple MCP servers through a Zuplo MCP Gateway`,
    `You maintain endpoint lists for agents, clients, or an internal catalog`,
  ]}
/>

## The registry is generated from your routes

The registry is enabled by default at `/__zuplo/mcp-registry`. For a gateway at
`gateway.example.com`, this request lists its MCP servers:

```text
GET https://gateway.example.com/__zuplo/mcp-registry/v0.1/servers
```

The response follows the frozen v0.1 API:

```json
{
  "servers": [
    {
      "name": "com.example.gateway/linear-mcp-server",
      "description": "Linear MCP proxy",
      "title": "Linear",
      "version": "1.0.0",
      "remotes": [
        {
          "type": "streamable-http",
          "url": "https://gateway.example.com/mcp/linear-v1"
        }
      ],
      "websiteUrl": "https://linear.app",
      "icons": []
    }
  ],
  "metadata": { "count": 1 }
}
```

Zuplo reads the route configuration when it handles the request. Add a route and
it appears in the next response. Remove the route and it disappears. There is no
registry database to keep in sync with the gateway.

<CalloutDoc
  title="MCP Server Registry documentation"
  description="Endpoint details, query parameters, response fields, and configuration."
  href="https://zuplo.com/docs/mcp-gateway/server-registry"
  icon="book"
/>

## Which routes appear in the registry

The gateway creates an entry for each concrete route that serves MCP traffic:

- **Gateway virtual servers**: Routes that use MCP Gateway policies to proxy an
  upstream server such as Linear or Stripe.
- **Standalone MCP servers**: Routes that use `mcpServerHandler` or a bare
  `McpProxyHandler` without the gateway policies.

Each entry uses a reverse-DNS name derived from the request host and includes
the gateway route as a `streamable-http` remote. The title, description,
version, website URL, and icons come from the route's upstream connection
configuration.

Parameterized routes such as `/mcp/{server}` don't appear because they aren't
connectable until the path parameter has a value. Before returning an entry, the
gateway normalizes its metadata to match the registry API. It truncates long
names, limits descriptions to 100 code points, drops non-HTTPS icons, and
replaces invalid version ranges. A malformed field on one route doesn't break
discovery for the rest of the gateway.

## Public discovery does not bypass route authentication

The registry's discovery endpoints are unauthenticated and allow cross-origin
requests, as defined by the upstream registry API. They return route URLs and
descriptive metadata. They don't return upstream credentials, access tokens, or
gateway policy configuration.

A public catalog doesn't grant access to the servers behind it. A client
connecting to one of the listed routes still passes through the route's
authentication and other inbound policies. Treat route titles and descriptions
as public metadata.

## Git remains the source of truth

Zuplo gateway configuration follows a
[GitOps workflow](/features/gitops). To add, update, or remove an MCP server,
change its route configuration and deploy it the same way you change any other
gateway route. The registry reflects the deployed state on its next request.

Accepting writes through the registry API would create a second, mutable server
catalog. A record published there could drift from the route configuration in
Git, leaving clients with a catalog that doesn't match what the gateway serves.

Keeping the registry read-only avoids that split. Clients get a standard
discovery API, while server changes remain version-controlled and go through
your existing deployment workflow. Requests to publish, update, or delete a
version return `501 Not Implemented`. Status updates return `403 Forbidden`.
Error bodies use the registry API's `{"error": "..."}` format, so registry
clients can handle them without a Zuplo-specific error parser.

## Change the registry path or turn it off

The default path is `{basePath}/mcp-registry`, which resolves to
`/__zuplo/mcp-registry` with the default MCP Gateway base path. Pass a `registry`
option to `McpGatewayPlugin` to use a different path:

```ts title="modules/zuplo.runtime.ts"
import { RuntimeExtensions } from "@zuplo/runtime";
import { McpGatewayPlugin } from "@zuplo/runtime/mcp-gateway";

export function runtimeInit(runtime: RuntimeExtensions) {
  runtime.addPlugin(
    new McpGatewayPlugin({
      registry: {
        path: "/internal/mcp-registry",
      },
    }),
  );
}
```

Set `registry.enabled` to `false` if you don't want to expose a registry. Zuplo
validates custom paths at startup and rejects paths that conflict with the MCP
Gateway's OAuth or well-known endpoints.

## The trade-offs of a route-derived registry

Generating the catalog from route configuration removes a synchronization
problem, but it also means the registry has no stored history. The
`updated_since` query parameter is accepted but doesn't filter the results, so
every entry is treated as changed.

Server names also depend on the request host. If the same gateway is available
through two hostnames, each hostname produces a different reverse-DNS name.
Neither behavior prevents discovery, but both matter if you mirror this catalog
into a system that expects stable identifiers or update timestamps.

To inspect a deployed gateway, send a `GET` request to its
`/__zuplo/mcp-registry/v0.1/servers` endpoint. The
[MCP Server Registry documentation](https://zuplo.com/docs/mcp-gateway/server-registry)
covers every endpoint and query parameter, and the
[`McpGatewayPlugin` reference](https://zuplo.com/docs/programmable-api/mcp-gateway-plugin)
covers configuration. If you're deciding how local discovery fits with the
global MCP registry, read
[MCP registry vs. MCP gateway](/blog/mcp-registry-vs-mcp-gateway).