Claude Code integration
Claude Code exposes lifecycle hooks around every tool call. MCP tools are
named mcp__<server>__<tool> (e.g. mcp__github__create_issue), so one
matcher wires the RingZero guard around every MCP server at once — no proxy,
nothing in the request path.
How it works
Section titled “How it works”- PreToolUse fires before a tool runs. Claude Code pipes the call as JSON
to
ringzero-mcp hook, which writes an audit record, evaluates your policy, and answers with a permission decision. - PostToolUse fires after — the guard records the outcome (
event: "post"). - Non-MCP tools pass through untouched, with no audit record.
- The hook always exits 0 and fails open: a broken guard logs to stderr and allows. Enforcement posture comes from the policy file, not from crash behavior.
Configuration
Section titled “Configuration”-
Install the CLI where Claude Code runs:
Terminal window npm install -g @ringzero/mcp-scan -
Connect your org — org id (
org_9f3kfrom Settings → General) in the policy file, API key (Settings → API keys, scopemcp:upload) inRINGZERO_API_KEY. Optional but recommended: without it, auditing stays local-only (which also works). -
Make sure a policy file is reachable from your project (
ringzero-mcp initto bootstrap). -
Print the hook wiring and merge it into
.claude/settings.json(project, commit it for the whole team) or~/.claude/settings.json(per-user):Terminal window ringzero-mcp init --print-hooks claude-code.claude/settings.json {"hooks": {"SessionStart": [{"hooks": [{ "type": "command", "command": "npx -y @ringzero/mcp-scan registry sync --quiet" }]}],"PreToolUse": [{"matcher": "mcp__.*","hooks": [{ "type": "command", "command": "ringzero-mcp hook --harness claude-code --event pre" }]}],"PostToolUse": [{"matcher": "mcp__.*","hooks": [{ "type": "command", "command": "ringzero-mcp hook --harness claude-code --event post" }]}]}}The
SessionStarthook is the MCP Registry deployment channel: every session applies the org catalog before work starts (silent no-op in repos without one). -
Verify: run any MCP tool in a Claude Code session, then
Terminal window ringzero-mcp audit report --since 1h
What gets blocked vs audited
Section titled “What gets blocked vs audited”| Policy state | Dangerous pattern match | Unapproved server |
|---|---|---|
| No policy file | audited (allow) | audited (allow) |
mode: warn | audited as warn + a note in the session | audited as warn |
mode: enforce | denied | denied when runtime.blockUnapproved: true |
A denied call answers with permissionDecision: "deny" and a reason naming
the rule, e.g. RingZero policy: server 'slack-mpc' is not on the org allowlist (.ringzero/mcp-policy.json). The guard never answers
"allow" — approved calls fall through to your normal Claude Code
permission flow, so the guard can only ever add protection.
Usage recording
Section titled “Usage recording”Every MCP call produces a record like this in
~/.ringzero/mcp-audit/YYYY-MM-DD.jsonl (schema:
Usage auditing):
{ "ts": "2026-07-26T14:03:11.402Z", "org": "org_9f3k", "harness": "claude-code", "event": "pre", "sessionId": "sess_01j9…", "server": "github", "tool": "create_issue", "decision": "allow", "rule": null, "argsSha256": "9f2c8a41…", "argsBytes": 412, "args": null, "cwd": "/work/acme-web", "policyPath": "/work/acme-web/.ringzero/mcp-policy.json", "policyMode": "warn"}pre events carry the decision; post events record that the call
completed. Arguments are hashed, never stored raw, unless you
opt in.
Team rollout
Section titled “Team rollout”- Commit
.claude/settings.json(hooks) and.ringzero/mcp-policy.json(allowlist) to the repo — every dev gets the guard on clone. - Start in
warnmode; reviewringzero-mcp audit reportweekly. - Flip the committed policy to
enforce(+blockUnapproved) once the warn stream is quiet. - Add the CI gate so config changes can’t outrun the allowlist.
Troubleshooting
Section titled “Troubleshooting”- A guard bug is blocking work —
RINGZERO_MCP_DISABLE=1allows everything while still auditing; unset it after the fix. - Nothing appears in the audit log — check the hook is registered
(
/hooksin Claude Code), and thatringzero-mcpis on the PATH Claude Code uses. - Wrong policy picked up — the hook walks up from the session’s
cwd; pinRINGZERO_MCP_POLICYwhen running outside the repo.