ZuploZuplo
LoginStart for Free
  • Documentation
  • API Reference
Introduction
Getting Started
    Develop in the portal
      1 - Setup Your Gateway2 - Rate Limiting3 - API Key Auth4 - Deploy5 - Dynamic Rate LimitingDynamic MCP Server - Quickstart
    Develop locally with the CLI
      1 - Setup Your Gateway2 - Rate Limiting3 - API Key Auth4 - Deploy5 - Dynamic Rate LimitingDynamic MCP Server - Quickstart
Concepts
Development
Policies
Handlers
API Keys
Rate Limiting
Caching
MCP Server
MCP Gateway
    IntroductionQuickstartQuickstart (Local Dev)How it works
    Connect MCP clients
    Authentication
    Cross App Access
    Configuration
    Observability
    ReferenceServer RegistryTroubleshooting
AI Gateway
Developer Portal
Monetization
GraphQL
Deploying & Source Control
Analytics
Observability
Networking & Infrastructure
Account Management
Programming API
Build with AI
Zuplo CLI
Migration Guides
Platform LimitsVersion Support PolicySecuritySupportTrust & ComplianceChangelog
powered by Zudoku
MCP Gateway

MCP Server Registry

The MCP Gateway serves a read-only MCP Server Registry API (v0.1 freeze) that advertises every MCP route on the gateway. MCP clients and mirroring subregistries can discover the gateway's registered servers without authentication, per the registry specification.

The registry is enabled by default and mounted at /__zuplo/mcp-registry (with the default basePath). Configure or disable it through the registry option on McpGatewayPlugin.

What gets listed

The registry projects one entry per MCP-serving route — both:

  • Gateway virtual servers — routes that carry MCP gateway policies (mcp-oauth-inbound / mcp-token-exchange-inbound) and use McpProxyHandler to proxy to an upstream MCP server.
  • Standalone MCP servers — routes that use the built-in mcpServerHandler or a bare McpProxyHandler without gateway policies.

Each entry includes:

FieldSource
name<reverse-DNS of request host>/<operationId> (for example, com.example.gateway/linear-mcp-server)
remotesThe gateway route URL, using the streamable-http transport.
descriptionOpenAPI operation description or summary, clamped to 100 code points per the spec.
titlemcpServerHandler options or the OpenAPI operation summary.
versionmcpServerHandler options or upstream connection config. Range-like values (^1.2.3, 1.x) project as 0.0.0.
websiteUrlUpstream connection config, canonicalized to a valid URI.
iconsUpstream connection config. Only HTTPS URLs are included; src is clamped to 255 characters.

Server names are derived from the request host — the same posture as the OAuth issuer and Protected Resource Metadata. Names vary with the hostname the gateway is reached on, so a custom domain produces different names than the default *.zuplo.dev origin.

The projection never throws. Every spec constraint is enforced by sanitizing or omitting: names longer than 200 characters are truncated with a hash suffix, descriptions are clamped, non-HTTPS icons are dropped, and version ranges are replaced with 0.0.0. One malformed route can't take down discovery for the rest.

Parameterized routes (for example, /mcp/{server}) are omitted from the directory — a templated path is not a concretely connectable remote.

Endpoints

All paths are relative to the registry mount (default: /__zuplo/mcp-registry). Discovery GETs are unauthenticated and CORS-permissive (Access-Control-Allow-Origin: *).

GET {path}/v0.1/servers

Lists all MCP servers registered on the gateway.

Query parameterTypeDefaultDescription
cursorstring—Opaque pagination cursor from a previous response.
limitinteger30Maximum servers to return. Clamped to 100.
searchstring—Case-insensitive substring filter on server name.
versionstring—Filter to servers matching a specific version.
updated_sincestring—RFC 3339 date-time. Validated but never filters — every entry conservatively counts as changed.

Response:

Code
{ "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 } }

When cursor is present in the response, more results are available. Pass it back as the cursor query parameter on the next request.

GET {path}/v0.1/servers/{serverName}/versions

Lists versions for a single server. With the current read-only projection, every server has exactly one version entry.

{serverName} is URL-encoded — the slash in the reverse-DNS name is sent as %2F (for example, com.example.gateway%2Flinear-mcp-server).

GET {path}/v0.1/servers/{serverName}/versions/{version}

Returns a single server version. The special alias latest resolves to the server's current version.

Write endpoints (refused)

The registry is read-only. Write endpoints are refused per the spec:

EndpointMethodStatusReason
{path}/v0.1/publishPOST501Spec marks publishing optional and documents 501.
{path}/v0.1/servers/{serverName}/versions/{version}PUT501Spec marks version update optional.
{path}/v0.1/servers/{serverName}/versions/{version}DELETE501Spec marks version deletion optional.
{path}/v0.1/servers/{serverName}/versions/{version}/statusPATCH403Spec defines no 501 for status operations; returns 403 with a permissions error message.
{path}/v0.1/servers/{serverName}/statusPATCH403Same as above.

All error bodies use the spec's {"error": "..."} shape — not RFC 7807 problem details — so off-the-shelf registry clients can parse them. A catch-all under the mount ensures even unrecognized requests get the spec-shaped 404.

Configuration

The registry is configured through the McpGatewayPlugin constructor. See the registry option for the full options reference.

Code
import { RuntimeExtensions } from "@zuplo/runtime"; import { McpGatewayPlugin } from "@zuplo/runtime/mcp-gateway"; export function runtimeInit(runtime: RuntimeExtensions) { runtime.addPlugin( new McpGatewayPlugin({ registry: { enabled: true, // default path: "/mcp-registry", // default: "{basePath}/mcp-registry" }, }), ); }

Limitations

  • No publishing. The registry is a read-only projection of the gateway's live route configuration. There is no write path, no namespace-ownership model, and no stored publishedAt or updatedAt timestamps.
  • updated_since validates but never filters. Because the registry is derived from route config with no stored timestamps, every entry conservatively counts as changed. This keeps mirroring subregistries correct at the cost of re-reading everything.
  • No deployment-pinned server identity. Server names are derived from the request host, not from a stable deployment-level identifier.

Related

  • McpGatewayPlugin reference — the full plugin options, including basePath and registry.
  • Gateway reference — the full URL catalog, including the registry mount.
  • How the MCP Gateway works — architecture and request lifecycle.
  • MCP Server Registry specification — the v0.1 freeze the gateway implements.
Edit this page
Last modified on August 20, 2026
ReferenceTroubleshooting
On this page
  • What gets listed
  • Endpoints
    • GET {path}/v0.1/servers
    • GET {path}/v0.1/servers/{serverName}/versions
    • GET {path}/v0.1/servers/{serverName}/versions/{version}
    • Write endpoints (refused)
  • Configuration
  • Limitations
  • Related
JSON
TypeScript