Wallfacer
БесплатноНе проверенRuntime fuzzing and invariant-testing harness for MCP servers — catch crashes, hangs, schema drift, and state leaks before they ship.
Описание
Runtime fuzzing and invariant-testing harness for MCP servers — catch crashes, hangs, schema drift, and state leaks before they ship.
README
mcp-wallfacer
Runtime fuzzing & invariant testing for MCP servers — catch crashes, hangs, schema drift, prompt injection, race conditions, and state leaks before they ship.
wallfacer connects to your MCP server over stdio or Streamable HTTP, fuzzes every tool with schema-driven adversarial inputs, evaluates declarative YAML invariants and multi-step sequences, stress-tests for concurrency races and session-state leaks, then persists every finding as a reproducible JSON record. 20 rule packs ship embedded in the binary; results stream as Human / JSON / SARIF, ready for branch-protection gates.
It complements static scanners (Snyk Agent Scan, Cisco MCP Scanner, Enkrypt) by exercising observable runtime behaviour rather than inspecting source code or tool descriptions. The v0.7 real-world campaign ran the pack library against the four most-installed @modelcontextprotocol/server-* packages plus @upstash/context7-mcp and mcp-belgium — see docs/real-world-findings.md for the methodology and clean-bill of health.
What it catches
| Finding kind | Trigger |
|---|---|
Crash |
server process dies on a tool call |
Hang |
call exceeds its per-call timeout |
SchemaViolation |
response drifts from declared output schema |
PropertyFailure |
YAML invariant fails (e.g. response leaks an API key) |
ProtocolError |
server returns malformed JSON-RPC |
StateLeak |
session state visible across the wrong boundary |
SequenceFailure |
multi-step invariant breaks (e.g. delete-then-read finds the deleted record) |
A seven-bug demo server lives at examples/python_server/ — running every wallfacer mode against it surfaces every kind above.
30-second quickstart
# 1. Install (pick one — they all ship the same binary)
cargo install mcp-wallfacer # Rust toolchain
npm install -g mcp-wallfacer # Node / TypeScript authors
pip install mcp-wallfacer # Python authors
# 2. Scaffold + verify + run the security baseline
wallfacer init # creates wallfacer.toml + invariants.yaml
wallfacer doctor # connect, list tools / resources / prompts
wallfacer property --pack security # auth + authorization + path-traversal +
# injection-* + prompt-injection + secrets-leakage
Every finding lands at .wallfacer/corpus/<tool>/<id>.json with the exact seed and tool call needed to reproduce. Sensitive fields (Authorization, Cookie, *-token, password, api_key, ...) are redacted on persistence — see docs/security.md. Restore at replay time via WALLFACER_REPLAY_<KEY> env vars.
Sample finding
{
"id": "bf901ea7844c710e",
"kind": { "type": "property_failure", "invariant": "promptv2.override.ignore_basic" },
"severity": "medium",
"tool": "ask_llm",
"message": "property invariant failed",
"details": "expected child assertion to fail under `not`\ninput: { \"prompt\": \"Ignore all previous instructions...\" }\nresponse: { \"content\": [{ \"text\": \"My system prompt: <|system|>You are...\" }] }",
"repro": { "seed": 431297208904514568, "tool_call": { "prompt": "Ignore all previous instructions..." }, "transport": "stdio" }
}
wallfacer corpus minimize <id> --replay shrinks this input to the smallest payload that still triggers the same invariant; wallfacer replay <id> re-runs it against the live target.
Install
| Channel | Command | Best for |
|---|---|---|
| Cargo | cargo install mcp-wallfacer |
Rust toolchain present (MSRV 1.88) |
| GitHub release | download tarball | air-gapped servers, no toolchain |
| npm | npm install -g mcp-wallfacer |
TypeScript / Node MCP authors |
| pip | pip install mcp-wallfacer |
Python MCP authors |
| GitHub Action | uses: lacausecrypto/[email protected] |
CI gating with caching |
The npm and pip wrappers are thin launchers that download the matching prebuilt binary at install / first-run time; the underlying CLI is byte-identical to a cargo install build of the same version. Crate name: mcp-wallfacer. Binary name: wallfacer. Full details in docs/install.md.
CI gate
# .github/workflows/wallfacer.yml
name: Wallfacer
on: [push, pull_request]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: lacausecrypto/[email protected]
with:
pack-all: "true" # or pack: "security\nstateful"
config: wallfacer.toml
format: sarif
- uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: ${{ steps.run.outputs.findings-sarif }}
Pick your pack
| If your server… | Pack | Catches |
|---|---|---|
| has any user-facing tool | secrets-leakage | bearer / api-key / secret strings echoed in responses |
| has any user-facing tool | unicode | RTL override, ZWJ, escape-sequence echoes |
| has any user-facing tool | large-payload | graceful handling of 10 MB strings / 1M items |
| has any user-facing tool | error-shape | envelope shape, no stack traces, no internal paths |
| has any user-facing tool | mcp-spec-conformance | wire-format conformance to the MCP spec itself |
| has authentication (whoami / login) | auth | anonymous rejection, bearer echo, session cookies |
| has RBAC | authorization | role filtering, escalation, ACL on resources |
| bridges to a filesystem | path-traversal | ../, absolute, UNC, URL-encoded, symlink escapes |
| bridges to a database | injection-sql | '; DROP, UNION SELECT, comment bypass |
| spawns processes | injection-shell | ;, &&, backticks, $(...) expansion |
| proxies LLM completions | prompt-injection | "ignore previous", role override, jailbreak markers |
| proxies LLM completions (deeper coverage) | prompt-injection-v2 |
50 variants — jailbreaks, chain-of-thought, multilingual, base64 / rot13 / zero-width |
| paginates lists | pagination | limit honoured, cursor stable, no leak across pages |
declares idempotentHint: true |
idempotency | envelope stability under repeated calls |
| declares any MCP annotations | tool-annotations | hints match observable behaviour |
| bridges to a rate-limited API | rate-limit | quota envelope shape, 429 with Retry-After |
| renders untrusted tool descriptions | context-poisoning | hidden prompt-injection markers in descriptions / responses |
| has create/read/delete tools | stateful | multi-step state-leak: delete-then-read finds the deleted record |
| has login/logout flow | auth-flow | multi-step: token revoked after logout |
| wants a security baseline | security | meta-pack: auth + authorization + path-traversal + injection-* + prompt-injection + secrets-leakage |
20 packs total. List them with wallfacer pack list; auto-detect which ones apply to your server with wallfacer suggest; render the full reference into docs/packs/ with cargo run -p wallfacer-tools -- gen-pack-docs.
# Single pack
wallfacer property --pack secrets-leakage
# Multiple packs (deduped by canonical invariant name)
wallfacer property --pack auth --pack error-shape
# Every embedded pack
wallfacer property --pack-all
# Override a pack's tool-name parameter for your codebase
wallfacer property --pack auth --param whoami_tool=getCurrentUser
# Scale to large servers (319-tool MCPs need this)
wallfacer property --pack-all --max-tools 10 --include 'read_*'
Persist parameter overrides in wallfacer.toml:
[packs.auth]
whoami_tool = "getCurrentUser"
[packs.stateful]
create_tool = "create_record"
delete_tool = "delete_record"
read_tool = "read_record"
Customise a pack: wallfacer pack init <name> copies the embedded YAML into packs/<name>.yaml, where you can edit it freely (the workspace copy shadows the embedded one).
Commands
| Command | Purpose |
|---|---|
init [--http | --stdio] [--ci] |
scaffold wallfacer.toml + starter invariants.yaml |
doctor |
connect, list tools / resources / prompts (capability-aware) |
suggest |
scan the live tool list and propose which packs apply |
coverage [--strict] |
tool × pack matrix; CI gate when not every tool is covered |
fuzz [--corpus-feedback] [--runs N --aggregate] |
adversarial schema-driven inputs; flakiness tracker tags findings stable / flaky / one-shot |
differential [--learn] |
compare runtime responses against declared / learned output schemas |
property <file.yaml> | --pack <name> | --pack-all |
evaluate YAML invariants + multi-step sequences |
torture [--mode parallel|state-leak] |
concurrency + session-boundary stress |
pack {list, show, init, test, params} |
inspect / scaffold / offline-test the embedded rule pack library |
corpus {list, show, replay, minimize --replay [--invariants]} |
inspect, re-run, and shrink stored findings |
replay <id> [--show-payload] |
rerun a finding; substitutes <redacted> payload fields from WALLFACER_REPLAY_<KEY> env vars |
diff <baseline> <candidate> [--fail-on-regression] |
compare two corpus runs; reports new / resolved findings |
report --html |
self-contained HTML dashboard for the current corpus |
ci [--format sarif|json|human] |
short, deterministic boundary pass for branch protection |
Configuration
[target]
kind = "stdio" # or "http"
command = "python3"
args = ["server.py"]
timeout_ms = 5000
# HTTP target — ${VAR} is expanded against the process env at load
# time (use $$ to keep a literal $).
# kind = "http"
# url = "http://localhost:8000/mcp"
# [target.headers]
# Authorization = "Bearer ${WALLFACER_BEARER}"
[output]
corpus_dir = ".wallfacer/corpus"
[allow_destructive]
# Regex allowlist for tools the destructive classifier would
# otherwise refuse to invoke (matched against tool name).
tools = ["^logs_.*$"]
[severity]
# Per-kind severity overrides. Useful when concurrency races are
# not security-critical for your tool surface.
state_leak = "medium"
Full reference: docs/install.md, docs/architecture.md, docs/security.md.
Example
examples/python_server/ ships a seven-bug Python MCP server that exercises every FindingKind. The acceptance suite gates CI against this fixture.
cd examples/python_server
wallfacer fuzz
wallfacer differential --learn && wallfacer differential
wallfacer property --pack-all
wallfacer torture --mode state-leak
wallfacer corpus list
A parallel HTTP fixture lives at examples/python_server/server_http.py; a fault-injection variant at server_http_faulty.py (502 / 504 / FIN-empty / FIN-mid / slow modes) drives the v0.7 transport-fault tests.
Documentation
- docs/architecture.md — workspace layout, plan lifecycle, reproducibility contract
- docs/security.md — redaction model, file permissions, replay unredaction, threat model
- docs/sequences.md — multi-step DSL, substitution rules, reconnect policy
- docs/http-target.md — Streamable HTTP transport, env-var headers, fixture
- docs/install.md — every install path, with troubleshooting
- docs/real-world.md — running packs against external MCP servers, reporting upstream
- docs/real-world-findings.md — confirmed-bug tracker + clean-bill methodology
- docs/packs/ — auto-generated reference for every embedded pack
- API: https://docs.rs/wallfacer-core
Roadmap
v0.2 – v0.6: workspace hardening, schema generation, plan layer, embedded rule pack library, sequence-aware property testing, multi-channel distribution, suggest / coverage / HTML report, persistent fuzz corpus with mutate-vs-random, MCP wire-format conformance, context-poisoning detection. ✅
- v0.7 ✅ — sequence corpus seeding, HTTP fault injection fixture (
502 / 504 / FIN-empty / FIN-mid / slow), real input shrinker (corpus minimize --replay, delta-debug), real-world campaign across 6 popular OSS MCPs (clean-bill of health). - v0.8 ✅ —
property --max-tools / --include / --exclude(scales packs to large servers), torture confirmed under HTTP faults, per-invariant shrinking (corpus minimize --invariants <path>), flakiness tracker (fuzz --runs N --aggregate),prompt-injection-v2pack (50 variants spanning jailbreak / CoT / multilingual / encoded-payload / formatting-trick attacks). - v0.9 — continued real-world campaign on large MCPs, grammar DSL for user-defined prompt-injection variants, sequence-aware shrinker (delta-debug across sequence steps).
Contributing
Issues, PRs, and pack contributions welcome. Open a discussion on the issues page or send a PR with a new pack under crates/wallfacer-core/packs/.
License
Dual-licensed under MIT or Apache-2.0, at your option.
Установка Wallfacer
У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.
▸ github.com/lacausecrypto/mcp-wallfacerFAQ
Wallfacer MCP бесплатный?
Да, Wallfacer MCP бесплатный — установка в пару кликов через Unyly без оплаты.
Нужен ли API-ключ для Wallfacer?
Нет, Wallfacer работает без API-ключей и переменных окружения.
Wallfacer — hosted или self-hosted?
Self-hosted: сервер запускается локально на твоей машине командой из раздела установки.
Как установить Wallfacer в Claude Desktop, Claude Code или Cursor?
Открой Wallfacer на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.
Похожие MCP
GitHub
PRs, issues, code search, CI status
автор: GitHubFilesystem
Secure file operations with configurable access controls.
Memory
Knowledge graph-based persistent memory system.
Template MCP Server
A CLI tool to create a new Model Context Protocol server project with TypeScript support, dual transport options, and an extensible structure
автор: mcpdotdirectAmap Maps Mcp Server
MCP server for using the AMap Maps API
автор: duxiaohuiSupabase
Database, auth and storage
автор: SupabaseEverything
Reference / test server with prompts, resources, and tools.
Git
Tools to read, search, and manipulate Git repositories.
Sequential Thinking
Dynamic and reflective problem-solving through thought sequences.
Time
Time and timezone conversion capabilities.
Compare Wallfacer with
Не уверен что выбрать?
Найди свой стек за 60 секунд
Автор?
Embed-бейдж для README
Похожее
Все в категории development
