Skip to main content

mcp-behave

Runtime behavioral auditor for MCP servers. Runs an MCP server under strace, exercises every tool / resource / prompt it advertises, and then compares what it declared against what it actually did — file reads, network egress, subprocess execution.

Static scanners read tool descriptions. mcp-behave watches behavior.

The idea in one contrast

targets/leaky_server.py and targets/honest_server.py advertise the identical tool:

format_note — "Formats a markdown note. Purely local text formatting."

A static scanner reads two harmless tools. mcp-behave sees the difference:

Target network egress sensitive file read findings
honest_server none none 0
leaky_server 93.184.216.34:80 ~/.ssh/id_rsa (a canary) 2 HIGH

The honest server producing zero findings matters as much as the leaky one tripping two — false positives would kill credibility.

Install

pip install mcp-behave

Requires Linux + strace for the syscall-trace backend. On macOS/Windows, use the bundled Dockerfile (see below).

Use

# Audit any stdio MCP server -- pass its launch command:
mcp-behave python -m mcp_server_fetch
mcp-behave npx -y @modelcontextprotocol/server-filesystem /tmp
mcp-behave uvx mcp-server-git

# Machine-readable output for CI:
mcp-behave --json --fail-on high python -m mcp_server_fetch

# Connect to an already-running remote server (manifest analysis only,
# no syscall trace possible):
mcp-behave --transport sse http://localhost:8000/sse

Exit codes: 0 clean, 3 findings at or above --fail-on threshold, 2 strace/ptrace setup failed, 1 other error.

Useful flags

  • --json — emit findings as JSON on stdout.
  • --fail-on {never,info,high} — severity that triggers exit code 3 (default high).
  • --no-dns — skip reverse-DNS lookups (faster, offline-safe).
  • --timeout SECONDS — per-call timeout (default 15).
  • --transport {stdio,sse,streamable-http} — remote transports skip syscall tracing.
  • --out-dir PATH — where manifest.json and trace.log are written.

Push results to a dashboard

mcp-behave push uploads a JSON audit result to an mcp-behave dashboard.

# 1. Sign in at https://<your-dashboard>.vercel.app/settings and mint a token.
export MCP_BEHAVE_DASHBOARD_URL=https://<your-dashboard>.vercel.app
export MCP_BEHAVE_TOKEN=mcpb_...

# 2. Audit something with --json and pipe it to push.
mcp-behave --json python -m mcp_server_fetch \
  | mcp-behave push --server-name server-fetch --category network

# Or save to a file first, then push.
mcp-behave --json python -m mcp_server_fetch > audit.json
mcp-behave push audit.json --server-name server-fetch --category network

Flags worth knowing:

  • --server-name NAME — canonical name on the dashboard. Defaults to the joined server command from the audit JSON; usually you want to set this.
  • --description TEXT — used the first time this server is submitted.
  • --github-url URL, --npm-package PKG, --author NAME — optional server metadata.
  • --category {local,network,database,other} — defaults to other.
  • --dry-run — print the JSON payload that would be POSTed and exit.

The endpoint is rate-limited per token (20 req/min); push exits 1 on HTTP error and prints the response body to stderr.

What it detects

  • Undeclared network egress — IP:port destinations reached during tool calls (reverse-DNS resolved in findings when available).
  • Sensitive-path reads — ~/.ssh/*, ~/.aws/*, ~/.env, ~/.netrc, etc.
  • Rug-pull — the declared manifest hash changes between runs of the same server (e.g. a tool's description silently changes after the user trusts it). Hashes persist under $XDG_DATA_HOME/mcp-behave/manifests/.

Findings are framed as observations ("does X, undeclared"), never accusations.

Docker (works on macOS / Windows hosts)

docker build -t mcp-behave .
# default: runs the bundled leaky target so you can see findings immediately
docker run --rm --cap-add=SYS_PTRACE mcp-behave
# point at a real server
docker run --rm --cap-add=SYS_PTRACE mcp-behave python -m mcp_server_fetch

--cap-add=SYS_PTRACE is required for strace to attach inside the container.

The image bundles Node.js (for npx servers), uv (for uvx servers), and sandbox canary files (sandbox_home/) mounted as $HOME so credential reads are detectable.

Development

pip install -e ".[test]"
pytest -v

CI runs on Ubuntu (strace is Linux-only); see .github/workflows/ci.yml.

Known limits

  • Linux-only ground truth via strace. eBPF/seccomp backend is on the roadmap — see ROADMAP.md.
  • stdio is the only transport with syscall tracing. sse and streamable-http connect to a remote server we cannot trace; only manifest analysis and rug-pull detection apply there.
  • Input synthesis is heuristic — JSON Schema format, key-name hints, and type defaults. Schema-coverage fuzzing (hypothesis-jsonschema) is roadmap.
  • AF_UNIX egress isn't matched — a server exfiltrating over a unix domain socket would slip past the current network detection.
  • Single call per capability — servers that misbehave only on specific inputs or after N calls may not be triggered.

License

MIT. See LICENSE.

Metadata

Release files for mcp-behave 0.1.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for mcp-behave 0.1.3
File Size Uploaded
mcp_behave-0.1.3.tar.gz 22.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for mcp-behave 0.1.3
File Interpreter ABI Platform
mcp_behave-0.1.3-py3-none-any.whl Python 3 none any Details

Total release size: 41.5 kB

Release files / mcp_behave-0.1.3.tar.gz

Download URL mcp_behave-0.1.3.tar.gz
Size 22.1 kB
Tags Source
SHA-256 checksum
How to use checksums
e05bc5f34a641cb78504f865b9a9046d80c4edf99b3428a4f06b5f7db9ebe6aa
BLAKE2b-256 checksum
How to use checksums
3581b9fffb2452ccf3af5fab316859bce97f0961eb03067e9263e0f35772a2f5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 25, 2026.

Transparency log

Release files / mcp_behave-0.1.3-py3-none-any.whl

Download URL mcp_behave-0.1.3-py3-none-any.whl
Size 19.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
dbcffdf6c59908b722725077746938e849d728d4dc7b827287a5a31cb1cd0b2a
BLAKE2b-256 checksum
How to use checksums
d73143aff2003593e0776f3d8dc96135dab156d21115f4a5108a919ac42d7fd5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 25, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.3 This release

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page