Agent Guard
A runtime security proxy for MCP (Model Context Protocol) agent tool calls.
Agent Guard sits between your MCP client (Claude Desktop, etc.) and your real MCP servers, inspecting every tool call for:
- Secrets in transit - API keys, AWS credentials, private keys, tokens found in tool call arguments or results (one level of base64/hex decoding is checked too).
- Dangerous commands -
rm -rf,curl | sh, destructive SQL without aWHEREclause,chmod 777, etc. - Malicious inbound args - heuristic tripwires (warn by default) for
path traversal (encoded
../, null bytes,/etc/passwd-style targets) and SQL injection (tautologies, stacked queries,UNION SELECT) in tool call arguments. Tripwires, not guarantees - see Limitations. - Accidental data exfiltration (taint tracking) - if an agent reads a
sensitive file (e.g.
.env) and a value from it later appears in a call to an external-facing tool (HTTP, email, Slack), the call is blocked. - Prompt injection markers - a tripwire, not a defense (see Limitations below).
Every tool call is logged to ~/.agent-guard/audit.log as JSONL with a
risk score and verdict. The log is safe for concurrent writers (cross-process
file lock) and rotates at 50 MB to one prior file (audit.log.1).
Install
Not yet published to PyPI. Install from source:
git clone https://github.com/mmbinumer/agent-guard
cd agent-guard
pip install -e .
Windows note: if
agent-guardisn't found after install, pip installed the script to aScriptsdirectory that isn't on yourPATH(pip will print a warning showing the path). Add that directory to yourPATHand open a new terminal, or invoke it aspython -m agent_guard <command>.
Quick start
- Copy
agent-guard.example.yamltoagent-guard.yamland list your downstream MCP servers underservers:. - Run
agent-guard run --config agent-guard.yamlto start Agent Guard as a stdio MCP proxy server, and point your MCP client (e.g. Claude Desktop) at this running process instead of your servers directly. - Run
agent-guard tail --no-followto see recent activity, oragent-guard reportfor a summary. - If a legitimate call gets blocked, set
mode: audit-onlyinagent-guard.yamlto downgrade all blocks to warnings while you tune the config, or runagent-guard killto halt everything immediately.
Examples
examples/verdict_demos.py runs Agent Guard in-process against a real
@modelcontextprotocol/server-filesystem, scoped to a temp directory, and
walks through all four verdicts (allowed, warned, blocked for a
credential in args, blocked for a taint leak), printing the resulting
audit log:
pip install -e .
python examples/verdict_demos.py
Requires Node.js (npx) on PATH.
Detections
Each detection has a configurable action (block / redact / warn /
allow). Defaults below; override any of them under actions: in your config.
| Detection | Catches | Phase | Default |
|---|---|---|---|
dangerous_command |
rm -rf, curl | sh, chmod 777, destructive SQL (DROP/DELETE/UPDATE without WHERE) |
pre-call args | block |
secret_in_args |
API keys, AWS creds, tokens, private keys in args (+1 level base64/hex) | pre-call args | block |
path_traversal |
encoded ../, null bytes, deep climbs (../../../), sensitive targets (/etc/passwd, .ssh/) |
pre-call args | warn |
sql_injection |
tautologies (' OR '1'='1), stacked queries ('; DROP), UNION SELECT, comment terminators |
pre-call args | warn |
taint_leak |
a value read from a sensitive source reappearing in a call to an external sink | pre-call args | block |
taint_unknown |
a sink call scanned clean after taint evidence was evicted, so the result isn't conclusive | pre-call args | warn |
secret_in_output |
secrets in tool results (redacted in audit log only) | post-call result | redact |
prompt_injection_marker |
verbatim phrases like "ignore previous instructions" in results | post-call result | warn |
path_traversal, sql_injection, and prompt_injection_marker are
heuristic tripwires (see Limitations). They default to warn so they surface
suspicious activity in the audit log without blocking legitimate calls while
you tune. Set them to block once you trust them for your workload.
Configuration
See agent-guard.example.yaml for the full schema: per-detection actions
(block / redact / warn / allow), taint sources/sinks, size limits,
and the global kill switch.
Limitations (read this)
- Redaction is audit-log-only: when a secret is detected in a tool's output, it's redacted in the audit log but the agent still receives the unredacted result (so its reasoning isn't disrupted). This means the audit log is not a faithful record of what the agent saw - relevant if you're using this for compliance purposes.
- The prompt injection scanner is a tripwire, not a defense. It matches verbatim/near-verbatim phrasing like "ignore previous instructions". A rephrased or obfuscated injection will not be caught. A clean scan does not mean the output is safe.
- Taint tracking matches exact values (plus one level of base64/hex decoding). An agent that paraphrases a secret or applies further encoding will not be caught.
- The taint store is bounded and per-session. It holds at most
max_taint_entriesvalues and evicts oldest-first. Once anything has been evicted, a sink call that scans clean is no longer conclusive, so Agent Guard reportstaint_unknowninstead of silently treating the call as clean. Raisemax_taint_entriesfor long sessions, or settaint_unknown: blockto fail closed. - The path-traversal and SQL-injection checks are tripwires, not
validators. They match known-suspicious patterns in tool call args
(encoded traversal, tautologies, etc.) and default to
warn. They scan top-level string args only, won't catch novel/obfuscated payloads, and are no substitute for the downstream server doing real input validation and parameterized queries. - The config file is not tamper-proof. Anyone with filesystem access to
agent-guard.yamlcan disable detections or flip the kill switch. This is not a hardened security boundary in v1.
Security
Found a way past a detection? See SECURITY.md for how to report it privately, and for what is in scope versus a known limitation.
License
MIT
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mcp_agent_guard-0.1.0.tar.gz.
File metadata
- Download URL: mcp_agent_guard-0.1.0.tar.gz
- Upload date:
- Size: 44.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5ccdc4d83aa9f4959e52d99e035641748ad25acf4479ef54d3f0d9c09acf1d06
|
|
| MD5 |
a34d7d4abb27fc953eeb5ea79507b4f4
|
|
| BLAKE2b-256 |
619c5f3ee392a874824614effed97a2c0dc43a55dab2b02ab4090ea929a1f7bf
|
File details
Details for the file mcp_agent_guard-0.1.0-py3-none-any.whl.
File metadata
- Download URL: mcp_agent_guard-0.1.0-py3-none-any.whl
- Upload date:
- Size: 19.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
aec4a3fc2b216e3af5b0fe8aad1d8b4a11c6e316af6bf3bb811361e65d14f12d
|
|
| MD5 |
ecb8e376376f251c66a6f7155f72b3b7
|
|
| BLAKE2b-256 |
3426ad74158d7596f41d4ab9900ca5433c3811e03ea09d1575df8212b27dc3ff
|