The full upstream README, mirrored here for reference. Install config, tool schemas, adoption signals, and an original overview live on the MCP Audit listing page.
Wireshark + auditd, but for MCP.
mcp-audit sits transparently in front of any MCP server and records every
tool call that passes through it — what was called, by whom, with which
arguments, and what came back. One Go binary, no daemon, no Docker, no
Kubernetes.
It answers the question every team adopting agents eventually has to answer: which tool did our agent call, when, and with what?
That is the whole setup. No config file, nothing blocked, everything recorded.
Download a binary for your platform from the latest release, or use npm:
Build from source — Go 1.24 or newer, no other dependencies:
Or install straight into your GOBIN:
Put mcp-audit run -- in front of the command you already run:
Point the proxy at the upstream server and your client at the proxy:
Authentication is not touched: Authorization headers, OAuth flows and
Mcp-Session-Id all pass through exactly as they arrive.
Every message is one JSON line:
Some things you can do with it straight away:
See examples/clients/ for drop-in config snippets for
Claude Desktop, Cursor and Windsurf. The pattern is always the same: keep the
command you had, and put mcp-audit run -- in front of it.
Recording is the default. These checks run on top of it and, apart from RBAC, never block anything — they flag the event and print an alarm to stderr.
A poisoned MCP server hides instructions in a tool description. The user only
sees a tool called echo; the model reads the rest. mcp-audit scans every
advertised description and schema field for seven patterns:
| Rule | What it looks for |
|---|---|
instruction_override | "ignore all previous instructions" and variants |
hidden_instruction | markup aimed at the model: <IMPORTANT>, <system>, <secret> |
concealment | "do not tell the user", "without informing the user" |
credential_bait | ~/.ssh, id_rsa, .env, ~/.aws/credentials, /etc/shadow |
exfiltration | "send/upload/post …" with a URL nearby |
cross_tool_instruction | orders about other tools — the tool-shadowing attack |
invisible_characters | zero-width and bidi-override characters a human cannot see |
A rug pull is a server that advertises a harmless tool, waits for you to approve
it, and changes the description days later. mcp-audit fingerprints every tool
(SHA-256 over description + input schema) and remembers it in
~/.mcp-audit/state/tools.json, so the check survives restarts — which is the
only way it could ever catch the attack.
The one check that can block. With no rules it allows everything; add a rule and a refused call never reaches the server — the client gets a JSON-RPC error instead.
Entirely optional. See config.example.yaml for the
annotated version. mcp-audit looks for a config file in this order:
--config <path>$MCP_AUDIT_CONFIG./mcp-audit.yaml~/.mcp-audit/config.yamlIf it finds none, it uses built-in defaults and says so.
Windows paths in YAML: write them with forward slashes (
"C:/Users/you/logs.jsonl") or in single quotes ('C:\Users\you\logs.jsonl'). Inside double quotes a backslash is a YAML escape character.
The local JSONL log is always on. A webhook is optional and best-effort — if it is down, delivery is retried four times over about three seconds and then that event is dropped from that sink only. The local log is never affected.
ARCHITECTURE.md for the measurements.scripts/demo.sh runs the whole story end to end — a normal
session, a blocked call, a poisoned tool description and a rug pull — against
the stub server, in a temp directory that leaves your real state alone.
TYPING_SPEED=0 PAUSE=0 ./scripts/demo.sh runs it instantly, which is handy as
a smoke test.
The race detector needs a C toolchain. On Windows, scoop install mingw (or
MSYS2) provides one; the performance assertion skips itself under -race,
since instrumented memory accesses measure the detector rather than the code.
CI runs on a self-hosted runner and therefore only on pushes to main — see
docs/ci.md for why, and for what would have to change before a
pull_request trigger would be safe. Pull requests are tested by pulling the
branch and running the suite locally.
cmd/dummy-mcp-server is a stub MCP server for testing the proxy against. It
speaks both stdio and Streamable HTTP and has flags for staging the attacks the
detectors look for:
The module layout, the data model and the design decisions behind them are in
ARCHITECTURE.md.
Apache License 2.0 — free to use, modify and redistribute,
commercially included, with an explicit patent grant. See NOTICE.