teachyou.ai academy
← All posts
MCPModel Context Protocoldeveloper toolsAI agentstool discovery

The MCP Registry Explained: Discovering and Publishing Servers

Pramod Dutta · Jun 26, 2026 · 14 min read

The MCP registry is a public directory that lists Model Context Protocol servers so agent builders can find them without hunting through GitHub. If you have ever wondered "is there already an MCP server for this API before I write one," the registry is where you check first. This article walks through how the registry works, how to search it well, and the exact steps to publish your own server to it.

MCP itself needs no introduction if you have built an agent in the last year: it is the open protocol, originally released by Anthropic, that standardizes how AI applications connect to tools, data sources, and prompts. The protocol solved the "M times N" integration problem between AI apps and external systems. But once thousands of servers existed for that protocol, a second problem showed up: how do you find the right one, verify who published it, and confirm it still works before you wire it into a production agent. The MCP registry exists to answer that.

What the MCP Registry Actually Is

The MCP registry is best understood as a metadata index, not a hosting platform. It does not run your server, and it does not proxy traffic to it. What it stores, for every listed server, is a server.json document: the server's name, description, version, repository link, how to install or connect to it (npm package, PyPI package, Docker image, or a remote URL), and the transport it supports (stdio, or one of the HTTP-based transports for remote servers).

Think of it as closer to npm's registry or the Python Package Index than to an app store. It answers "does a server named X exist, who published it, and what version is current," while the actual server code lives wherever the author put it: a GitHub repo, an npm package, a container registry, or a hosted endpoint.

The official registry lives at a public API endpoint (registry.modelcontextprotocol.io) maintained by the MCP steering group, and it is designed from day one to be federated rather than a single walled garden. Anyone can run a "subregistry" that pulls from the official index, applies its own curation or security scanning, and re-exposes a filtered list. Client applications and IDEs are free to point at the official registry, a vendor's subregistry, or an internal company one.

Why a Registry Was Necessary

Before the registry existed, discovery happened through informal, unmaintained lists: awesome-mcp-servers repos on GitHub, blog posts, and word of mouth. That worked at dozens of servers. It stopped working once the ecosystem passed a few thousand. Three concrete problems pushed the community toward a real registry:

  • Duplicate and abandoned servers. Search GitHub for "mcp server slack" before the registry existed and you'd get a dozen forks, half of them stale, with no signal on which one was actively maintained.
  • No ownership verification. Nothing stopped someone from publishing a server called github-mcp that had nothing to do with GitHub, or worse, that impersonated a well-known integration.
  • No machine-readable format. IDEs and agent frameworks that wanted to offer "browse and install a server" inside their UI had nothing structured to query against.

The registry's namespace and verification rules (covered below) exist specifically to close the second problem, and the standardized server.json schema closes the third.

Discovering Servers in the MCP Registry

There are three practical ways to search the registry, depending on whether you are a human browsing or a client application doing it programmatically.

Through a client's built-in browser. Most modern MCP-capable clients (Claude Code, Claude Desktop, and various IDE extensions) expose a "browse servers" or "add server from registry" flow that queries the registry API under the hood and lets you search by name or keyword, then install with one confirmation step. This is the fastest path if you already know roughly what you're looking for, for example "postgres" or "linear."

Through the registry's own web search. The registry publishes a searchable web UI where you can filter by transport type (local vs remote), by publisher, and by keyword. This is useful when you're evaluating options rather than installing immediately, since you can read the full server.json metadata, check the linked repository, and see the version history before pulling anything into your environment.

Through the raw API. For programmatic discovery, for example if you're building your own MCP-aware tool, the registry exposes a REST API you can query directly:

GET https://registry.modelcontextprotocol.io/v0/servers?search=postgres

This returns a paginated list of matching server.json entries. You can also fetch a single server by its fully-qualified name:

GET https://registry.modelcontextprotocol.io/v0/servers/io.github.yourorg/yourserver

A minimal client-side lookup in JavaScript looks like this:

async function findServer(query) {
  const url = `https://registry.modelcontextprotocol.io/v0/servers?search=${encodeURIComponent(query)}`;
  const res = await fetch(url);
  const data = await res.json();
  return data.servers.map(s => ({
    name: s.name,
    description: s.description,
    version: s.version,
    repository: s.repository?.url,
  }));
}

Whichever path you use, apply the same evaluation checklist before trusting a server enough to give it credentials or filesystem access:

  • Publisher namespace. Does the server's name live under a namespace that matches a real, verifiable identity (a GitHub org, a verified domain)? A server published as io.github.stripe/stripe-mcp carries very different trust than one published as com.example/stripe-tools from an unrelated account.
  • Repository link resolves and is active. Click through. Check the commit history is recent and issues are being answered, not a repo that hasn't been touched in a year.
  • Declared permissions match the description. A "read-only reporting" server that requests write scopes on your calendar is a mismatch worth questioning.
  • Version pinning. Note the exact version listed and pin to it in your config rather than always pulling latest, the same discipline you'd apply to any third-party dependency.

The server.json Format

Every entry in the registry is a server.json file that follows a published JSON Schema. Understanding its shape matters whether you're consuming entries or, more importantly, about to publish your own. A trimmed example for a local, npm-distributed server:

{
  "name": "io.github.yourorg/weather-mcp",
  "description": "Look up current weather and short-range forecasts by city or coordinates.",
  "version": "1.2.0",
  "repository": {
    "url": "https://github.com/yourorg/weather-mcp",
    "source": "github"
  },
  "packages": [
    {
      "registryType": "npm",
      "identifier": "@yourorg/weather-mcp",
      "version": "1.2.0",
      "transport": {
        "type": "stdio"
      }
    }
  ]
}

The key fields worth knowing:

  • `name` is the fully-qualified, namespaced identifier. It is not a free-text field: the prefix before the slash has to correspond to a namespace you've proven you control, which is what the publishing flow verifies.
  • `packages` is an array because a single logical server can ship multiple ways: an npm package for local stdio use, a Docker image for containerized use, and so on. Each package entry declares its own registry type and transport.
  • `remotes`, an alternative to packages, is used instead when the server is hosted and reachable over HTTP rather than something a client installs and runs locally. A remote entry points at a URL and declares the transport (typically streamable HTTP).
  • `version` should track your actual release, and the registry keeps version history so clients can pin to older releases if a new one breaks something.

If you're only consuming the registry, you rarely touch this file by hand, clients parse it for you. But reading a couple of real entries before you publish your own is the fastest way to avoid schema mistakes.

Publishing a Server to the MCP Registry

Publishing is a CLI-driven, verification-gated process. The steps below describe the general flow; expect small command-name differences if the tooling has moved on by the time you read this, but the sequence of proving ownership, then submitting metadata, holds.

1. Write your `server.json`. Start from the schema and a working example rather than from scratch. Get the name, description, version, repository, and at least one packages or remotes entry filled in accurately. The description is what shows up in search results and in client "browse" UIs, so write it as you would an npm package description: specific, not marketing copy.

2. Choose your namespace and prove you own it. This is the step that gives the registry its trust model, and it works one of two ways:

  • GitHub-based namespace. If your server's identifier starts with io.github.<your-org-or-username>, you authenticate via GitHub OAuth during publish. Because you're proving control of the GitHub account or org, you're automatically allowed to publish under that namespace, no separate application process.
  • Custom domain namespace. If you want your server to live under your own domain, for example com.yourcompany/yourserver, you prove ownership by adding a DNS TXT record or hosting a verification file at a well-known path on that domain. The publishing CLI checks for it before it lets the publish through.

3. Install the publisher CLI and authenticate.

npm install -g @modelcontextprotocol/publisher
mcp-publisher login github

The login step opens a device-code OAuth flow against GitHub (or walks you through domain verification if you're using a custom namespace).

4. Validate before you submit. Run the schema validator locally so you catch mistakes before they hit the network call:

mcp-publisher validate ./server.json

This checks required fields, confirms your packages or remotes entries are well-formed, and confirms the referenced npm package or Docker image actually exists and matches the version you declared. A common failure here is publishing server.json with a version that doesn't match what you've actually pushed to npm yet, publish the package first, then the registry entry.

5. Publish.

mcp-publisher publish ./server.json

On success you get back the canonical registry URL for your server. It typically appears in search results and client browse UIs within minutes, though propagation to third-party subregistries that mirror the official index can take longer since they run on their own sync schedules.

6. Publishing new versions. You don't edit the old entry, you submit a new server.json with an incremented version. The registry keeps the full version history, and clients that pinned an older version keep working. Treat this exactly like a package registry release: bump the version, update the changelog in your repo, then republish.

Namespaces and Verification, in Practice

The namespace system is worth dwelling on because it's the part of the registry that actually prevents impersonation, and it's easy to get wrong on your first publish.

Namespaces follow reverse-DNS style naming: io.github.<account> for GitHub-verified publishers, or <your-domain-in-reverse> for domain-verified publishers, for example ai.teachyou for a domain like teachyou.ai. You cannot publish under a namespace you haven't verified, the CLI will reject the attempt. This means two different people can never both claim io.github.acme/acme-tools, because only whoever controls the acme GitHub account can pass the OAuth check for that prefix.

For an individual developer, the GitHub route is almost always the right choice: it's instant, requires no DNS access, and is what most personal and open-source servers use. Reach for the domain-verification route when you're publishing on behalf of a company and want the namespace to read as the company's official domain rather than an individual's GitHub handle, since that's a stronger trust signal to anyone evaluating your server before installing it.

Security Considerations When Using the Registry

The registry solves discovery and identity verification. It does not solve "is this server's code safe to run," and treating a registry listing as a safety certification is the single most common mistake teams make when adopting MCP servers at scale.

A few practical rules:

  • Namespace verification proves identity, not safety. Knowing that io.github.someuser/some-server really is published by GitHub user someuser tells you nothing about whether that code is well-written or malicious. Read the source, especially for any server that touches credentials, executes shell commands, or reaches the filesystem.
  • Prefer well-known namespaces for high-privilege servers. For servers that get database credentials or write access to production systems, favor entries under a verified company domain or a GitHub org you already trust, over an anonymous individual account, all else equal.
  • Pin versions in production configs. Don't let your MCP client auto-update to "latest" for anything wired into a real workflow. Pin the version, review the changelog, then bump deliberately.
  • Run untrusted servers sandboxed first. If you're evaluating a server you found through the registry and don't already trust the publisher, run it in a container or restricted environment before pointing it at real credentials.

Subregistries and Private Registries

Because the official registry is designed to be mirrored rather than monopolized, several patterns have emerged worth knowing about:

  • Public mirrors with extra scanning. Some third parties sync the official registry and layer their own automated security scanning or curation on top, exposing a filtered subset through their own API or UI.
  • Company-internal registries. Enterprises building internal agent platforms run a private registry populated with only their approved, internally-vetted servers, sometimes seeded from the public registry and sometimes entirely proprietary. Internal servers for internal APIs never need to touch the public registry at all, the server.json format and publish tooling work the same way against a self-hosted registry endpoint.
  • Client-side allowlists. Rather than running infrastructure, some teams simply configure their MCP client to only resolve servers from a specific allowlist of namespaces, using the public registry for discovery but enforcing policy at the client.

If you're building for an enterprise audience, understanding this federation model matters more than memorizing the public registry's API, since the servers you publish need to work whether they're being resolved through the official index or an internal mirror.

Common Mistakes When Publishing

A short list worth checking before you hit publish, since these account for most rejected or broken submissions:

  • Version mismatch between `server.json` and the actual package. Push the npm/PyPI/Docker artifact first, confirm it installs cleanly, then publish the registry entry pointing at that exact version.
  • Vague descriptions. "A useful MCP server" tells nobody anything and won't surface well in search. Say exactly what API or system it wraps and what operations it exposes.
  • Wrong transport declared. If your server only supports stdio but you declare a remote HTTP transport (or vice versa), clients will fail to connect even though the registry entry looks valid.
  • Forgetting to update `packages` when you rename the npm package. The registry entry and the actual package identifier have to match exactly, byte for byte.
  • Publishing before testing with a real client. Validate schema correctness with mcp-publisher validate, but also actually connect a client to your server locally before publishing, schema-valid does not mean functionally correct.

FAQ

Is the MCP registry the only place to find MCP servers? No. It's the canonical, protocol-maintained index, but plenty of servers are still only listed in GitHub awesome-lists or a vendor's own docs. The registry is the right first stop because of its verification model, but treat "not in the registry" as a yellow flag to investigate further, not an automatic disqualifier.

Do I need to pay to publish a server to the registry? No, publishing is free. What costs you time is the namespace verification step, GitHub OAuth is instant, domain verification takes as long as your DNS propagation does.

Can I unpublish or delete a server from the registry? The registry is designed around version history rather than deletion, similar to how package registries work. You can publish a new version marked deprecated in its description, and stop maintaining it, but check the current publisher CLI docs for any explicit deprecation or delisting flag, since this tooling has evolved since launch.

What's the difference between the MCP registry and an MCP client's "app store"? The registry is the underlying data source. A client's built-in browse UI, whether that's an IDE extension or a desktop app, is a consumer of the registry API, often with its own additional curation, ratings, or one-click install convenience layered on top.

How is a remote MCP server different from one installed via the registry's package listing? A packages entry means the client installs and runs the server locally, via npm, PyPI, or a container image, communicating over stdio. A remotes entry means the server is already running somewhere and the client connects to it over HTTP, no local install step. Both are equally valid registry entries, the difference is purely in how the client reaches the server, not in trust or quality.

Should my company run its own private registry instead of using the public one? Only if you have internal-only servers that shouldn't be public, or you want centralized policy enforcement over which namespaces your agents can pull from. For anything you're comfortable open-sourcing, publishing to the public registry gets you far more discovery and community vetting than a private index ever will.

The MCP Registry Explained: Discovering and Publishing Servers · TeachYou Academy