A harness that runs MCP servers in an instrumented sandbox and records what they actually do at runtime β every network connection they open and every file they touch β so you can see a server's real behavior instead of trusting its description.
The official MCP registry verifies who published a server (namespace authentication tied to a GitHub account or domain). It does not verify what a server does once you run it. The existing trust tooling in the ecosystem is almost entirely static analysis β scanning source code and metadata. Static scans miss an entire class of risk that only shows up at runtime:
- a server that connects somewhere unrelated to its stated purpose
- a server that reads credentials or files outside its lane
- a "rug pull": a server whose behavior changes in a later version, afteryou've already reviewed and trusted it
This project captures runtime behavior directly, which is the part almost nobody is watching yet.
Each server is launched inside a disposable Linux container (Docker) under
strace
, with syscalls for file access (openat
) and network connections
(connect
) logged. A fake credential is seeded into the environment as a canary, so any attempt to read or transmit it is visible in the trace. The container is throwaway; nothing the server does touches the host.
docker + strace βββΊ per-server syscall trace βββΊ behavior manifest
Everything runs locally. No server code executes on the host machine.
70 MCP servers audited: the 20 most-downloaded on npm, plus 50 from the long tail. Full per-server summaries are in manifests/; the headline findings are in
RESULTS.md
67 clean at startup β no sensitive-file reads, no unexpected network.3 made outbound HTTPS connections at startup(okx-trade-mcp
,razorpay/blade-mcp
,notebooklm-mcp-server
) to external hosts consistent with each server's function (an exchange integration, a GitHub fetch, cloud/CDN endpoints). None read sensitive files or touched the seeded canary.1(bullmq-mcp
) reads/etc/passwd
at startup via a standard glibc user lookup β flagged by the harness, thenverified benign: the contents never leave the process.** No server transmitted sensitive data.**
The value shown here isn't "everything was clean" β it's that the harness surfaced the three servers that phone home and the one that touches a sensitive file, and each could be run down to a verdict from the trace. That is behavior static scanners don't see.
Scope note:this capturesstartup and idlebehavior only β the server booting and waiting. It does not yet exercise individual tool calls, which is where more behavior lives. See roadmap.
Tool-call tracingβ drive each server through its advertised tools and record behavior per call, not just at boot. (The 3 outbound servers above are the first place this matters.)Version diffingβ re-run servers across releases and diff behavior to detect rug pulls β the highest-value, least-covered case.** Behavior manifests as a feed**β a stable, diffable per-server output that clients or registries could consume before install.** Wider coverage**β deeper into the long tail of single-maintainer servers.
git clone <this repo> && cd mcp-audit
docker run --rm -v "$PWD":/audit -w /audit node:22 bash -c \
'apt-get update -qq && apt-get install -y -qq strace && bash run.sh' # batch 1
python3 summarize.py
Reading raw traces: a read inside the server's own dependencies is normal (it's
its own code); a failed open (-1 ENOENT
) is normal (a config file that
isn't there); DNS (port 53
) and package-download connections (Cloudflare
104.16.x.x
) are normal. You're looking for a server that reads a sensitive file, or connects to a host with nothing to do with its job, once it's running.
Anything that looks like a genuine issue is reported privately to the server's maintainer first, with time to fix, before it appears in any public writeup. Observations here are characterized conservatively β a flagged behavior is not an accusation until it's confirmed with the maintainer.
Built by Bhavesh Thapar