Scan
ringzero-mcp scan discovers every MCP server configured across your
repos — Claude Code, OpenCode, VS Code, Cursor, Claude Desktop — and runs
the canonical security checks against each one.
Teams wire AI agents to MCP servers faster than anyone reviews them. Every
.mcp.json entry is third-party code (or a third-party endpoint) running with
the agent’s privileges: typosquatted packages one transposition away from the
official server, live secrets committed in server env config, filesystem roots
that hand every session the whole home directory, unpinned versions that
re-resolve latest on each launch, and remote endpoints nobody put through
review.
RingZero treats the MCP config as a first-class security surface.
Scan
ringzero-mcp scan discovers every MCP server configured across your
repos — Claude Code, OpenCode, VS Code, Cursor, Claude Desktop — and runs
the canonical security checks against each one.
Policy & allowlist
A reviewable org allowlist in .ringzero/mcp-policy.json: propose →
review → allow. Warn first, enforce when you’re ready.
MCP Registry
An org-controlled catalog that auto-configures approved MCP servers in every harness — pinned versions, no inline secrets, dev contributions via PR, drift caught in CI.
Usage auditing
Harness hooks record supported MCP tool calls to an append-only local audit log — who called which tool on which server, and what the policy decided.
Harness guards
A Claude Code hook and an OpenCode plugin evaluate each call against your policy live — denying dangerous commands and unapproved servers in enforce mode.
| Harness | Config discovery | Usage recording | Blocking | Integration |
|---|---|---|---|---|
| Claude Code | .mcp.json, ~/.claude.json | ✅ PreToolUse / PostToolUse hooks | Best-effort (see caveat) | ringzero-mcp hook |
| OpenCode | opencode.json[c] | ✅ tool.execute.before/after | Enforce mode, primary session | @ringzero/opencode-mcp-guard |
| VS Code | .vscode/mcp.json | Scan-only | — | discovery only |
| Cursor | .cursor/mcp.json, ~/.cursor/mcp.json | Scan-only | — | discovery only |
| Claude Desktop | claude_desktop_config.json | Scan-only | — | discovery only |
All five harnesses are also MCP Registry sync targets — the org catalog auto-configures approved servers in each one’s config format.
Trust is derived from open findings, never stored — a server’s status can never disagree with its finding list:
| Status | Meaning |
|---|---|
| Flagged | Any open critical or high finding |
| Unverified | Only medium/low findings open |
| Verified | Nothing open |
Verified describes the evaluated checks, not a certification of server safety. Unevaluated checks and unsupported harness traffic remain outside this result.
The org-wide fleet trust score is max(0, 100 − Σ weights) over all open
findings, with weights critical 25 · high 15 · medium 5 · low
2 — deterministic and explainable from the current finding set alone, and
it visibly recovers as you remediate.
| Category | Severity | What it looks for | Evaluated by the CLI |
|---|---|---|---|
| Typosquat | critical | Package-name distance vs registry-official servers | ✅ |
| Secrets in config | critical | Credentials inline in server env, args, or URLs | ✅ |
| Excessive scope | high | Capability broader than the project needs (e.g. filesystem root at $HOME) | ✅ |
| Prompt injection | high | Hidden instructions in tool descriptions, aimed at the calling agent | Coming soon (platform) |
| Unpinned version | medium | Server re-resolves latest on every session launch | ✅ |
| Unapproved server | medium | Not approved by policy or catalog | ✅ (needs a policy or a strict registry catalog; manifest caveat) |
| Unsigned package | low | Resolved version published without npm provenance attestation | Coming soon (platform) |
The two platform checks need live registry/server data the local CLI does not
fetch; scan output always lists them in its checks manifest with
evaluated: false and the reason — never silently missing.
GET /v1/mcp/serversRequired scope: mcp:read
The org-wide MCP server inventory, derived from the org’s latest uploaded
scan (ringzero-mcp scan --upload): each discovered server with its
trust status and findings, plus the provenance of the
scan it came from. An org that hasn’t uploaded yet gets an empty inventory
(scanId/scannedAt null), never a 404.
{ "scanId": "mscn_7g8h", "scannedAt": "2026-08-16T10:00:00Z", "servers": [ { "id": "web/.mcp.json github", "name": "github", "source": "npm:@modelcontextprotocol/server-github@2025.4.8", "configPath": "web/.mcp.json", "transport": "stdio", "trust": "unverified", "findings": [ { "id": "unapproved-server:github", "title": "Server is not on the org allowlist", "severity": "medium", "category": "Unapproved server", "summary": "github is not covered by the org policy or registry catalog.", "status": "open" } ] } ]}id is a stable identifier derived from configPath + name, so a client’s
selection survives re-scans (a bare name collides across config files).
trust is the derived status (verified | unverified | flagged, per the
trust model above); finding status is always open today — the fix-PR
pipeline that moves findings to fixing/fixed is
Coming soon, as are the platform-enriched
finding fields (AI context and the recommended config diff) and usage
metadata (usedBy, toolCount, scopes) — absent fields are simply
omitted, never faked.