registry/docs/contributing/add-package-registry.md
Radoslav Dimitrov a25f166b4b
docs: remove stale complete.md and fix remaining stale references (#1522)
Deletes `complete.md` and cleans up the last references to the
pre-restructuring docs layout.

## Why `complete.md` goes

It is 2,944 lines (31% of all documentation lines in the repo)
self-described as *"all documentation from the docs/ directory compiled
into a single markdown file"*. But:

- **No generator exists.** No make target, no workflow, no script. `grep
-rn "complete\.md"` finds **zero** references anywhere in the repo.
- **It mirrors a docs tree that no longer exists** — `docs/guides/`,
`docs/explanations/`, `docs/concepts/`.
- **All 72 of its relative links are broken**, and six of the basenames
it references exist nowhere in the repo.
- **~14 current docs are missing from it entirely** (`about.mdx`,
`authentication.mdx`, `package-types.mdx`, both CHANGELOGs, ...).
- **Its `server.json` examples pin the superseded `2025-07-09` schema**
(current is `2025-12-11`).

The strongest argument is its own last commit. [PR
#1278](https://github.com/modelcontextprotocol/registry/pull/1278)
closed [issue
#767](https://github.com/modelcontextprotocol/registry/issues/767) — a
real user-reported CLI flag bug — by editing **only `complete.md`**. A
genuine fix landed in a file nobody reads, while the docs a reader would
actually find stayed wrong.

A generated file with no generator degrades into a trap: authoritative
enough that people edit it, with nothing validating it. If the
LLM-consumption use case is worth keeping, the right shape is a `make
docs-bundle` target plus a `check-docs-bundle` CI job mirroring the
existing `check-schema` pattern — happy to do that instead if you would
rather keep it.

## Remaining stale references

| File | Was | Now |
|---|---|---|
| `contributing/add-package-registry.md` | Add
`docs/guides/publishing/publish-[yourregistry].md`, update
`docs/guides/publishing/README.md` | Add a section to
`package-types.mdx`. These were the **last live references** to the
obsolete `docs/guides/` layout outside `complete.md` |
| `administration/maintainer-onboarding.md` | Add them to "Current key
maintainers" in README | "Registry Working Group" — the section that
actually exists |
| `reference/README.md` | Omitted 6 reference docs | Adds
`api/extensions.md`, `api/openapi.yaml`, `api/CHANGELOG.md`,
`server-json/CHANGELOG.md`, `server-json/CONTRIBUTING.md`,
`server-json/draft/` |
| `docs/README.md` | Index omitted `community-projects.md` | Listed |
| `reference/api/generic-registry-api.md` | `PUT .../versions/{version}`
"not implemented by official registry" | It **is** implemented
([edit.go:36](https://github.com/modelcontextprotocol/registry/blob/main/internal/api/handlers/v0/edit.go#L36)),
and `official-registry-api.md` already lists it as an admin endpoint |
| `reference/api/official-registry-api.md` | Omitted 3 registered routes
| Adds `POST /v0.1/validate` (which `mcp-publisher validate` calls),
`GET /v0.1/ping`, `GET /v0.1/version`, and notes these plus `/health`
are absent from `openapi.yaml` |
| `server-json/official-registry-requirements.md` | Per-registry
verification → `quickstart.mdx` | → `package-types.mdx`, which has an
Ownership Verification section per registry |
| `design/design-principles.md` | Sections 1,2,3,4,**6**,7 | Renumbered
1–6 |
| `contributing/releasing.md` | Steps 1,2,3,**5**,6 | Renumbered 1–5 |

I left the sibling `DELETE` claim in `generic-registry-api.md` alone —
it is accurate, no DELETE route is registered (the `http.MethodDelete`
hit in `server.go` is CORS config, not a route).

## Staleness banners rather than rewrites

**`design/tech-architecture.md`** is substantially fictional. Rather
than a vague "may be outdated", the banner lists what I verified is
wrong:

- Describes Helm-chart deployment; the registry is a plain `Deployment`
([registry.go:65](https://github.com/modelcontextprotocol/registry/blob/main/deploy/pkg/k8s/registry.go#L65)).
Helm is used only for third-party components.
- Diagram shows a `StatefulSet` on port **27017** — MongoDB's port. The
DB is PostgreSQL on 5432 via the CloudNativePG operator.
- Documents a `verify-domain` challenge flow (`POST /verify-domain`,
`/verify-domain/check`, server-issued tokens) that **was never built**.
- Documents `/admin/*` routes that are not registered.
- Says the DB stores user auth state and DNS verification records; only
`servers` and `server_extensions` tables exist.

**`design/roadmap.md`** still says "Phase 1: MVP/Go-Live (Current
Focus)" ~11 months after launch. I added a dated note rather than
inventing a current phase — that is a working-group call.

## Verification

All **101** remaining relative links across every `.md`/`.mdx` in the
repo resolve. The only two non-resolving matches are the intentional
`[project-name](link)` template placeholder and the moderation link
fixed in #1518.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 16:32:37 +03:00

5 KiB

Adding a new package registry

The MCP Registry project is a metaregistry, meaning that it hosts metadata for MCP servers but does not host the code for the servers directly.

For local MCP servers, the MCP Registry has pointers in the packages node of the server.json schema that refer to packages in supported package managers.

The list of supported package managers for hosting MCP servers is defined by the properties.packages[N].properties.registryType string enum in the server.json schema. For example, this could be "npm" (for npmjs.com packages) or "pypi" (for PyPI packages).

For remote MCP servers, the package registry is not relevant. The MCP client consumes the server via a URL instead of by downloading and running a package. In other words, this document only applies to local MCP servers.

For the sake of illustration, this document will use npm (the Node.js package manager) as an example at each step.

Prerequisites

The package registry must meet the following requirements:

  1. The package registry supports packaging and executing CLI apps. Local MCP servers use the stdio transport.
  2. The package registry (or associated client tooling) has a widely accepted single-shot CLI command.
    • npm's npx tool executes CLI commands using a documented execution heuristic
    • For example, the MCP client can map the server.json metadata to an npx CLI execution, with args and environment variables populated via user input.
  3. The package registry supports anonymous package downloads. This allows the MCP client software to use the metadata found in the MCP registry to discover, download, and execute package-based local MCP servers with minimal user intervention.
    • npx by default connects to the public npmjs.com registry, allowing simple consumption of public npm packages.
  4. The package registry should support a validation mechanism to verify ownership of the server name. This prevents misattribution and ensures that only the actual package owner can reference their packages in server registrations. For example:
    • npm requires an mcpName field in package.json that matches the server name being registered
    • PyPI requires a mcp-name: line in the package README/description
    • Each registry type must implement a validation mechanism accessible via public API

Steps

These steps may evolve as additional validations or details are discovered and mandated.

  1. Create a feature request issue on the MCP Registry repository to begin the discussion about adding the package registry.
  2. Open a PR with the following changes:
    • Update the server.json schema
      • Add your package registry name to the registryType example array.
      • Add your package registry base url to the registryBaseUrl example array.
      • Add the single-shot CLI command name to the runtimeHint example value array.
    • Update the openapi.yaml
      • Add your package registry name to the registryType enum value array.
      • Add your package registry base url to the registryBaseUrl enum value array.
      • Add the single-shot CLI command name to the runtimeHint example value array.
    • Add a sample, minimal server.json to the server.json examples.
    • Implement a registry validator:
      • Create a new validator file: internal/validators/registries/yourregistry.go, following the pattern of existing validators. Examples:
        • npm: Checks for an mcpName field in package.json that matches the server name
        • PyPI: Searches for mcp-name: server-name format in the package README content
        • NuGet: Looks for mcp-name: server-name format in the package README file
        • Docker/OCI: Validates a Docker image label io.modelcontextprotocol.server.name in the image manifest
      • Add corresponding unit tests: internal/validators/registries/yourregistry_test.go
      • Register your validator in internal/validators/validators.go
    • Update the publishing documentation:
      • Add a section for your registry to docs/modelcontextprotocol-io/package-types.mdx, following the pattern of the existing registries (npm, PyPI, NuGet, ...)
      • Include instructions on how to prepare packages for your registry, and an ### Ownership Verification subsection describing the validation your registry requires