MCP Registry
Scanning tells you which MCP servers are bad; the MCP Registry puts the
good ones on developer machines. The org publishes a reviewed catalog, and
ringzero-mcp registry sync projects it into every supported harness’s
config file — Claude Code, VS Code, Cursor, OpenCode, and (machine scope)
Claude Desktop. Orgs control the offering and the security posture;
developers get working agents by pulling; internal servers join through the
same PR review as any code change.
The catalog file
Section titled “The catalog file”.ringzero/mcp-registry.json, committed at the repo root (resolution:
--registry flag > RINGZERO_MCP_REGISTRY env > walk-up from cwd — point
the env at a shared path to distribute one catalog across many repos):
{ "schemaVersion": 1, "organization": "org_9f3k", "servers": [ { "name": "github", "description": "Official GitHub MCP server", "owner": "platform-team", "transport": "stdio", "command": "npx", "args": ["-y", "@modelcontextprotocol/server-github@2025.4.8"], "env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "${env:GITHUB_TOKEN}" }, "harnesses": "all", "scope": "project" }, { "name": "linear", "transport": "http", "url": "https://mcp.linear.app/sse", "headers": { "Authorization": "${env:LINEAR_MCP_KEY}" }, "harnesses": ["claude-code", "opencode"] } ]}| Field | Meaning |
|---|---|
controlLevel | Optional top-level org control level (open, monitored, strict) — see Org control levels |
name | Unique config key ([A-Za-z0-9._-]+) |
transport | stdio (command/args/env) or http (url/headers) |
harnesses | "all" or a subset of claude-code, vscode, cursor, opencode, claude-desktop |
scope | project (repo configs, default) or machine (user-level configs; required for claude-desktop) |
enabled | false removes the server from managed configs — the rollout kill switch |
owner, description | Attribution — recommended for dev-provided internal servers |
Validation is the security gate. ringzero-mcp registry validate rejects:
unknown keys, duplicate names, unpinned stdio sources (same rules as the
scanner’s Unpinned version check),
literal env/header values, and secrets smuggled into args or URLs. An org
cannot ship a bad catalog.
How sync works
Section titled “How sync works”ringzero-mcp registry sync compares the catalog projection against each
target config and applies the difference:
- add — catalog entry missing from the config.
- update — a managed entry differs from the catalog (the registry wins for entries it owns).
- remove — a managed entry left the catalog or was
enabled: false. - conflict — an entry you created yourself has the same name as a catalog entry: sync never touches it and reports the conflict until a human resolves it.
Ownership lives in a lock file — .ringzero/mcp-registry.lock.json
(committed) for project scope, ~/.ringzero/mcp-registry-state.json for
machine scope. Entries the registry didn’t create are never modified or
removed, and unrelated keys in the config files are always preserved.
Sync is idempotent: only drifted files are written, so clean files stay
byte-identical. One caveat: the first managed write to a .jsonc file
(.vscode/mcp.json, opencode.jsonc) rewrites it as plain JSON — comments
are lost on that first change.
What gets written where
Section titled “What gets written where”Project scope writes exactly one config per harness at the catalog root
(nested configs are scanned, never managed); --machine writes user-level
configs:
| Harness | Project scope | Machine scope (--machine) |
|---|---|---|
| Claude Code | .mcp.json | ~/.claude.json (top-level servers only) |
| VS Code | .vscode/mcp.json | — |
| Cursor | .cursor/mcp.json | ~/.cursor/mcp.json |
| OpenCode | opencode.json[c] | ~/.config/opencode/opencode.json |
| Claude Desktop | — | claude_desktop_config.json (stdio entries only) |
Registry entries are approved
Section titled “Registry entries are approved”A server matching a catalog entry (name + source) is automatically
approved by the scanner’s Unapproved server check — the catalog is the
allowlist for everything it manages, with no duplicated
policy entries. The policy still governs everything
else: runtime dangerous patterns, non-registry servers, and enforce-mode
gating.
Adding an internal server
Section titled “Adding an internal server”Developers propose servers with one command and a PR:
-
Scaffold the entry — from flags, or from a server already configured locally (
--fromnever copies literal env values; every env key becomes a${env:KEY}reference):Terminal window ringzero-mcp registry add docs-search \--command npx --arg=-y --arg @acme-internal/docs-search-mcp@1.2.0 \--env 'DOCS_TOKEN=${env:DOCS_TOKEN}' \--owner devex --description "Internal docs search" -
The entry is validated on the spot (pinning, references, shape) and appended to
.ringzero/mcp-registry.json. -
Commit and open a PR — review is the approval step. On merge, every deployment channel rolls the server out org-wide.
Command reference
Section titled “Command reference”| Command | Does | Exit |
|---|---|---|
registry sync [path] | Apply the catalog (--check --machine --json --quiet --registry <f>) | 0 · 1 on drift with --check · 2 |
registry status [path] | Drift report, writes nothing | always 0 |
registry list | Print catalog entries (--json) | 0 |
registry validate | Lint the catalog | 0 valid · 1 invalid · 2 none found |
registry add <name> | Propose an entry (--from <server> or flags) | 0 · 1 · 2 |
registry remove <name> | Drop an entry (next sync removes it from configs) | 0 · 1 · 2 |
registry pull | Fetch the org catalog from RingZero | 0 · 1 · 2 |
No catalog found → sync and status are silent exit-0 no-ops, so
hooks are safe in repos that haven’t adopted the registry.
Manage in the app Coming soon
Section titled “Manage in the app ”The RingZero app adds an org management surface on top of the same catalog
shape: browse and edit entries under the same validation gates, enable
servers per team (new teams inherit all-targeted entries), and set
per-repository overrides (inherit | force on | force off) with a live
preview of the effective .ringzero/mcp-registry.json each repo receives —
exactly what ringzero-mcp registry pull writes there. Catalog management
is role-gated to Admins/Owners. Assignment data lives in the platform, never
in the catalog file, so the file format you commit today doesn’t change.
Platform sync Coming soon
Section titled “Platform sync ”GET /v1/mcp/registry (scope mcp:read) serves the org catalog centrally;
ringzero-mcp registry pull is the shipped client — it validates the payload
before overwriting the local file, and without a RINGZERO_API_KEY it
explains and exits 0. Central management UI and staged rollouts build on the
same shape.