MCP Cooperative Guard
@controlzero/mcp-server is a tiny MCP (Model Context Protocol)
server that exposes Control Zero's DLP rules as tools an AI
client can call before invoking other tools. It's the third leg of
the Control Zero enforcement triangle:
The MCP guard is cooperative. The AI client could ignore the result. The point is to give well-behaved clients (and well- behaved agents acting on user intent) a way to surface DLP context without forcing every client to run the SDK.
Pair the MCP guard with the SDK or gateway when hard enforcement matters.
Why cooperative?
Hard enforcement requires either:
- The Control Zero SDK in the same process as the agent (Python, Node, or Go), OR
- The Control Zero gateway as an HTTP proxy in front of the LLM provider URL.
Some AI clients are neither: a desktop chat app like Claude Desktop runs Anthropic's API directly, with no SDK to wrap and no gateway to proxy through. The user is the only enforcement point. The MCP guard gives the agent a way to ask the Control Zero backend what the user's org allows, and surface that to the user before the agent commits to running a tool.
Install
npm install -g @controlzero/mcp-server
The package ships a controlzero-mcp binary that speaks MCP over
stdio.
Configure
The exact config file depends on your AI client.
Claude Desktop
Edit ~/Library/Application Support/Claude/claude_desktop_config.json
(macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):
{
"mcpServers": {
"controlzero": {
"command": "controlzero-mcp",
"env": {
"CONTROLZERO_API_URL": "https://api.controlzero.ai/api/v1",
"CONTROLZERO_API_KEY": "cz_live_xxxxxxxxxxxxxxxx"
}
}
}
}
Restart Claude Desktop. The new tools appear in the tool picker.
Cursor
Cursor reads MCP config from its settings UI. Go to Settings → Features → MCP and add:
{
"name": "controlzero",
"command": "controlzero-mcp",
"env": {
"CONTROLZERO_API_KEY": "cz_live_xxxxxxxxxxxxxxxx"
}
}
Cline / Continue
Both clients read MCP config from a project-level file. Create
.cline/mcp.json (or the equivalent for Continue) and add the
controlzero entry as above.
Other clients
Any client that supports MCP stdio servers works. The command is
always controlzero-mcp and the only required env var is
CONTROLZERO_API_KEY.
The three guard tools
guard_check_tool_call
The main one. Asks Control Zero whether a proposed tool call is allowed by the org's DLP rules.
Inputs:
org_id— UUID of the org whose rules should evaluatetool_name— name of the tool the client wants to invoke (e.g.,bash,read_file,fetch,send_message)tool_args_text— flat text representation of the tool args (the client should join all string args with newlines)scope— optional, defaults to"sdk". Set to"gateway"to evaluate against gateway-scoped rules instead.
Output:
{
"decision": "deny",
"rule_matches": [
{
"rule_id": "abc-123",
"rule_name": "US Social Security Numbers",
"category": "pii",
"action": "block",
"matched_text": "123-45-6789"
}
],
"reason": "tool 'bash' blocked by DLP rule 'US Social Security Numbers' (category=pii)"
}
Decisions:
allow— no rules matched, the call is fine.warn— at least one detect or mask rule matched. The client should show the warning to the user but the call is not blocked. If a mask rule matched, the response also includesmasked_textwith the matched span replaced by a placeholder.deny— at least one block rule matched. The client should NOT invoke the tool.
guard_test_pattern
Compile a candidate regex and check whether it matches a sample. Useful for an admin iterating on a new DLP rule from inside an AI client without leaving the chat.
Inputs:
org_idpattern— RE2 regexsample— sample input text (max 64 KB)
Output:
{
"compiles": true,
"matched": true,
"matches": ["123-45-6789"]
}
If the pattern fails to compile, compiles is false and error
contains the error message.
guard_list_active_rules
Read-only enumeration of currently-live DLP rules for the org. Useful for an agent that wants to proactively warn the user before they paste sensitive content.
Inputs:
org_id
Output:
{
"active_rules": [
{
"id": "abc-123",
"name": "US Social Security Numbers",
"category": "pii",
"action": "block",
"scopes": ["sdk", "gateway"]
}
]
}
Patterns and prompts
If you're a power user setting up an AI agent that uses these tools, here are some prompts that work well:
Pre-flight check before a destructive command
Before running any shell command that touches /etc, /var,
or any file owned by another user, call guard_check_tool_call
with `tool_name="bash"` and `tool_args_text` set to the proposed command.
If decision is deny, abort and show the rule name to the user.
If decision is warn, ask the user for explicit confirmation
before proceeding.
Proactive warning at conversation start
At the start of every conversation, call guard_list_active_rules
once and remember the result. If any rule has category="pii" or
"secret", warn the user upfront: "This org has DLP rules that
will block content matching: [rule names]. Don't paste real
customer data, credentials, or financial info into the chat."
Mid-stream paste check
Whenever the user pastes text containing what looks like an SSN,
credit card, API key, or email, call guard_check_tool_call with
`tool_name="paste_check"` and `tool_args_text` set to the pasted text
before proceeding. If decision is deny, refuse to use the
content and explain why.
Cost and rate limits
Each guard call is cheap on the backend side: it's one read of the org's DLP rules (cached) and a regex scan over the supplied text. No analytical store writes, no audit entries, no policy bundle downloads.
Rate limits per API key:
| Tool | Limit |
|---|---|
guard_check_tool_call | 100 / min |
guard_test_pattern | 30 / min |
guard_list_active_rules | 60 / min |
If you hit a limit, the MCP server returns an error with the HTTP 429 details. Back off and retry.
Security model
The MCP guard tool only reads DLP rules. It cannot modify them,
publish drafts, approve pending rules, or do anything else
admin-facing. The CZ API key only needs the dlp:read scope.
The guard tool does NOT receive or store any sensitive content
itself. The tool_args_text you pass to guard_check_tool_call
is scanned client-side in the MCP server process (which lives on
your laptop), not transmitted to Control Zero. Only the rule
metadata (which patterns to evaluate) comes from the Control
Zero backend.
This is intentional: a cooperative guard call should not become a way for sensitive content to leave the machine just to be scanned. The local-only scan also avoids a network round-trip for every call, even on multi-KB inputs.
Troubleshooting
"401 Unauthorized" on every call
The CONTROLZERO_API_KEY is missing, expired, or doesn't have
the dlp:read scope. Generate a new one from the dashboard's
Settings → API Keys page.
"Tool not found: guard_check_tool_call"
The MCP server isn't loading the guard tools. Verify:
npm list -g @controlzero/mcp-server— installed at the global location your client looks atcontrolzero-mcp --version— runs without error- The client's MCP config points at the binary by absolute path
(some clients don't search
$PATHfor stdio commands)
Decisions are stale after I publish a new rule
The MCP server fetches the rule list on every guard_check_tool_call
invocation, so there's no client-side cache to invalidate. If you
see stale results, the staleness is on the backend side: the
DLP rule store writes are immediately visible. Force a refresh by
calling guard_list_active_rules; if the new rule isn't there, the
publish didn't actually land.
Calls feel slow
Open the MCP server logs (controlzero-mcp writes to stderr by
default). Look for the callAPI request log lines. If the
backend round-trip is slow, the bottleneck is your network, not
the regex scan. Switch to a CZ API endpoint closer to your
location or use a regional cache.
Version compatibility
@controlzero/mcp-server >= 0.2.0 includes the guard tools.
Earlier versions only ship the policy/project/audit/governance/
blueprint tool families.
controlzero-mcp --version
If you're on an older version, upgrade:
npm install -g @controlzero/mcp-server@latest
The MCP protocol version is 2024-11-05 (the spec version the
@modelcontextprotocol/sdk v1 ships with). Any client that
supports MCP 2024-11-05 stdio transport works.