mcp-guard
A firewall for your AI agent's tools. Your assistant's GitHub server can delete repos; your database server can drop tables. The model is polite — but politeness is not a security boundary. mcp-guard wraps any MCP server with hard limits, human approval gates, and a full audit log.
One config change. The wrapped server needs no modifications and never knows the guard is there.

60-second setup
In your MCP client config (Claude Desktop, Cursor, Windsurf, Cline, Zed — anything that speaks MCP over stdio), wrap the server command:
{
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@aroha-sdk/mcp-guard",
"--block", "delete_*",
"--gate", "merge_*,create_repository",
"--limit", "create_*:10",
"--",
"npx", "-y", "@modelcontextprotocol/server-github"]
}
}
}Everything after -- is your original server command, unchanged.
Four rules, fail-closed
--block <globs>Always denyMatching tools are refused every time. The model gets a clear denial message; the wrapped server never sees the call.
--block "delete_*,drop_*,execute_sql"
--limit <glob>:<n>Session budgetAt most n calls per session across all tools matching the glob. The n+1th call is denied with an explicit do-not-retry message the model understands.
--limit "create_*:10,send_email:1"
--gate <globs>Human approvalEach call pauses and asks you first — your MCP client shows an approve/deny prompt with the tool name and arguments (via MCP elicitation). Timeout or unsupported client = deny. Fails closed, always.
--gate "merge_*,deploy_*,publish_*"
(always on)Audit logEvery decision is appended to ~/.aroha/mcp-guard.jsonl with a session receipt on exit — what ran, what was denied, what you approved. Disable with --no-log.
--name "github" --log ./github-audit.jsonl
Every ambiguous situation resolves to deny — approval timeouts, clients without elicitation support, malformed rules at startup. A guard that fails open is decoration.
Why a proxy, not harness config
Because permission logic implemented inside an agent framework scatters. The Harness Handbook (Wang et al., arXiv:2607.13285) traced one rule — “confirm before file deletion” — through a production harness and found it implemented across 2,267 files. Scattered rules drift, fork, and silently break on refactor; auditing them is archaeology.
A boundary proxy inverts that: one rule, one enforcement point, one audit log — uniform across every server you wrap, immune to prompt injection against the server (it can't be talked out of a proxy it doesn't know exists), and unchanged when the harness behind it is rewritten. Guardrails as architecture, not as documentation. Each rule's enforcement site and proving test are listed in the guarantee-evidence table.
Recipes
Read-only database
--block "insert_*,update_*,delete_*,drop_*,execute_*"
Filesystem with a write budget
--limit "write_file:20" --block "delete_*" --gate "move_*"
Anything irreversible needs a human
--gate "send_*,delete_*,merge_*,deploy_*,publish_*"
Observe before you restrict
--name "github" # audit log only, no rules
When you outgrow globs
mcp-guard rules are session-scoped and local. When you need authority that is signed, verifiable, delegable across agents, and auditable across organisations — spending mandates, task mandates, receipts — the same concepts become Ed25519-signed mandates in the full Aroha Protocol.