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>
223 lines
No EOL
6.8 KiB
Markdown
223 lines
No EOL
6.8 KiB
Markdown
# MCP Registry Technical Architecture
|
|
|
|
> [!WARNING]
|
|
> **This document has drifted from the shipped system and is kept as a design record.**
|
|
> For the architecture as deployed, see [deploy/README.md](../../deploy/README.md); for the API as
|
|
> implemented, see the [API reference](../reference/api/official-registry-api.md).
|
|
>
|
|
> Known inaccuracies below, as of 2026-08-10:
|
|
> - The registry is not deployed via a Helm chart. It is a plain Kubernetes `Deployment` created by
|
|
> Pulumi; Helm is used only for third-party components (ingress-nginx, cert-manager,
|
|
> cloudnative-pg, k8up, monitoring).
|
|
> - The database diagram shows a `StatefulSet` on port `27017` (MongoDB). The database is PostgreSQL
|
|
> on `5432`, provisioned by the CloudNativePG operator.
|
|
> - The DNS verification sequence (`mcp verify-domain`, `POST /verify-domain`,
|
|
> `POST /verify-domain/check`, server-issued challenge tokens) describes a design that was never
|
|
> built. The shipped flow signs a timestamp with the operator's key and posts it to
|
|
> `POST /v0/auth/dns`, with the public key published in a `v=MCPv1; k=...; p=...` TXT record.
|
|
> - No `/admin/*` routes exist. Admin actions use the regular server endpoints with an
|
|
> admin-permissioned token.
|
|
> - The CLI is `mcp-publisher`, not `mcp`, and publishing posts to `/v0/publish`.
|
|
> - The database stores servers and server extensions only; it holds no user authentication state
|
|
> and no DNS verification records.
|
|
|
|
This document describes the technical architecture of the MCP Registry, including system components, deployment strategies, and data flows.
|
|
|
|
## System Overview
|
|
|
|
The MCP Registry is designed as a lightweight metadata service that bridges MCP server creators with consumers (MCP clients and aggregators).
|
|
|
|
## Core Components
|
|
|
|
### REST API (Go)
|
|
|
|
The main application server implemented in Go, providing:
|
|
- Public read endpoints for server discovery
|
|
- Authenticated write endpoints for server publication
|
|
- GitHub OAuth integration (extensible to other providers)
|
|
- DNS verification system (optional for custom namespaces)
|
|
|
|
### Database (PostgreSQL)
|
|
|
|
Primary data store for:
|
|
- Versioned server metadata (server.json contents)
|
|
- User authentication state
|
|
- DNS verification records
|
|
|
|
### CDN Layer
|
|
|
|
Critical for scalability:
|
|
- Caches all public read endpoints
|
|
- Reduces load on origin servers
|
|
- Enables global distribution
|
|
- Designed for daily consumer polling patterns
|
|
|
|
### CLI Tool
|
|
|
|
Developer interface for:
|
|
- Server publication workflow
|
|
- GitHub OAuth flow
|
|
- DNS verification
|
|
|
|
## Deployment Architecture
|
|
|
|
### Kubernetes Deployment (Helm)
|
|
|
|
The registry is designed to run on Kubernetes using Helm charts:
|
|
|
|
```mermaid
|
|
graph TB
|
|
subgraph "Kubernetes Cluster"
|
|
subgraph "Namespace: mcp-registry"
|
|
subgraph "Registry Service"
|
|
LB[Load Balancer<br/>:80]
|
|
RS[Registry Service<br/>:8080]
|
|
RP1[Registry Pod 1]
|
|
RP2[Registry Pod 2]
|
|
RP3[Registry Pod N]
|
|
end
|
|
|
|
subgraph "Database Service"
|
|
DBS[DB Service<br/>:27017]
|
|
SS[StatefulSet]
|
|
PV[Persistent Volume]
|
|
end
|
|
|
|
subgraph "Secrets"
|
|
GHS[GitHub OAuth Secret]
|
|
end
|
|
end
|
|
end
|
|
|
|
LB --> RS
|
|
RS --> RP1
|
|
RS --> RP2
|
|
RS --> RP3
|
|
RP1 --> DBS
|
|
RP2 --> DBS
|
|
RP3 --> DBS
|
|
DBS --> SS
|
|
SS --> PV
|
|
RP1 -.-> GHS
|
|
RP2 -.-> GHS
|
|
RP3 -.-> GHS
|
|
```
|
|
|
|
## Data Flow Patterns
|
|
|
|
### 1. Server Publication Flow
|
|
|
|
```mermaid
|
|
sequenceDiagram
|
|
participant Dev as Developer
|
|
participant CLI as CLI Tool
|
|
participant API as Registry API
|
|
participant DB as Database
|
|
participant GH as GitHub
|
|
participant DNS as DNS Provider
|
|
|
|
Dev->>CLI: mcp publish server.json
|
|
CLI->>CLI: Validate server.json
|
|
CLI->>GH: OAuth flow
|
|
GH-->>CLI: Access token
|
|
CLI->>API: POST /servers
|
|
API->>GH: Verify token
|
|
API->>DNS: Verify domain (if applicable)
|
|
API->>DB: Store metadata
|
|
API-->>CLI: Success
|
|
CLI-->>Dev: Published!
|
|
```
|
|
|
|
### 2. Consumer Discovery Flow
|
|
|
|
```mermaid
|
|
sequenceDiagram
|
|
participant Client as MCP Client Host App
|
|
participant INT as Intermediary<br/>(Marketplace/Aggregator)
|
|
participant CDN as CDN Cache
|
|
participant API as Registry API
|
|
participant DB as Database
|
|
|
|
Note over INT,CDN: Daily ETL Process
|
|
INT->>CDN: GET /servers
|
|
alt Cache Hit
|
|
CDN-->>INT: Cached response
|
|
else Cache Miss
|
|
CDN->>API: GET /servers
|
|
API->>DB: Query servers
|
|
DB-->>API: Server list
|
|
API-->>CDN: Response + cache headers
|
|
CDN-->>INT: Response
|
|
end
|
|
INT->>INT: Process & enhance data
|
|
INT->>INT: Store in local cache
|
|
|
|
Note over Client,INT: Real-time Client Access
|
|
Client->>INT: Request server list
|
|
INT-->>Client: Curated/enhanced data
|
|
```
|
|
|
|
### 3. DNS Verification Flow
|
|
|
|
```mermaid
|
|
sequenceDiagram
|
|
participant User as User
|
|
participant CLI as CLI Tool
|
|
participant API as Registry API
|
|
participant DNS as DNS Provider
|
|
participant DB as Database
|
|
|
|
User->>CLI: mcp verify-domain example.com
|
|
CLI->>API: POST /verify-domain
|
|
API->>API: Generate verification token
|
|
API->>DB: Store pending verification
|
|
API-->>CLI: TXT record: mcp-verify=abc123
|
|
CLI-->>User: Add TXT record to DNS
|
|
User->>DNS: Configure TXT record
|
|
User->>CLI: Confirm added
|
|
CLI->>API: POST /verify-domain/check
|
|
API->>DNS: Query TXT records
|
|
DNS-->>API: TXT records
|
|
API->>API: Validate token
|
|
API->>DB: Store verification
|
|
API-->>CLI: Domain verified
|
|
CLI-->>User: Success!
|
|
```
|
|
|
|
### 4. Admin OIDC Authentication Flow
|
|
|
|
For registry administration, users with @modelcontextprotocol.io Google Cloud Identity accounts can authenticate using OIDC:
|
|
|
|
```mermaid
|
|
sequenceDiagram
|
|
participant Admin as Admin User
|
|
participant CLI as Admin CLI
|
|
participant GCP as Google Cloud Identity
|
|
participant API as Registry API
|
|
|
|
Admin->>CLI: Request admin token
|
|
CLI->>GCP: gcloud auth print-identity-token --audiences=mcp-registry
|
|
GCP-->>CLI: ID Token (with hd: "modelcontextprotocol.io")
|
|
CLI->>API: POST /v0.1/auth/oidc {"oidc_token": "eyJ..."}
|
|
API->>GCP: Verify token signature (JWKS)
|
|
API->>API: Validate claims (issuer, audience, hd)
|
|
API->>API: Grant admin permissions (edit: *, publish: *)
|
|
API-->>CLI: Registry JWT Token
|
|
CLI->>API: POST /admin/* (with Registry JWT)
|
|
API->>API: Validate JWT + permissions
|
|
API-->>CLI: Admin operation success
|
|
```
|
|
|
|
**Usage:**
|
|
```bash
|
|
# Get Google Cloud Identity token
|
|
ID_TOKEN=$(gcloud auth print-identity-token)
|
|
|
|
# Exchange for Registry JWT token
|
|
REGISTRY_TOKEN=$(curl -X POST /v0.1/auth/oidc \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"oidc_token": "'$ID_TOKEN'"}' | jq -r .registry_token)
|
|
|
|
# Use for admin operations
|
|
curl -H "Authorization: Bearer $REGISTRY_TOKEN" /v0.1/...
|
|
``` |