Skip to content

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.

.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):

.ringzero/mcp-registry.json
{
"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"]
}
]
}
FieldMeaning
controlLevelOptional top-level org control level (open, monitored, strict) — see Org control levels
nameUnique config key ([A-Za-z0-9._-]+)
transportstdio (command/args/env) or http (url/headers)
harnesses"all" or a subset of claude-code, vscode, cursor, opencode, claude-desktop
scopeproject (repo configs, default) or machine (user-level configs; required for claude-desktop)
enabledfalse removes the server from managed configs — the rollout kill switch
owner, descriptionAttribution — 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.

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.

Project scope writes exactly one config per harness at the catalog root (nested configs are scanned, never managed); --machine writes user-level configs:

HarnessProject scopeMachine scope (--machine)
Claude Code.mcp.json~/.claude.json (top-level servers only)
VS Code.vscode/mcp.json
Cursor.cursor/mcp.json~/.cursor/mcp.json
OpenCodeopencode.json[c]~/.config/opencode/opencode.json
Claude Desktopclaude_desktop_config.json (stdio entries only)

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.

Developers propose servers with one command and a PR:

  1. Scaffold the entry — from flags, or from a server already configured locally (--from never 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"
  2. The entry is validated on the spot (pinning, references, shape) and appended to .ringzero/mcp-registry.json.

  3. Commit and open a PR — review is the approval step. On merge, every deployment channel rolls the server out org-wide.

CommandDoesExit
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 nothingalways 0
registry listPrint catalog entries (--json)0
registry validateLint the catalog0 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 pullFetch the org catalog from RingZero0 · 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.

Next: deploy the registry to your org.