Quickstart¶
See it work first¶
With uv installed, one command runs the demo with no API key and nothing to install or configure:
On every pull request, CI builds Mylonite from source and runs this command against that
build on Python 3.14, on Linux and Windows, in an 80-column terminal. To keep Mylonite
installed instead, use pip as below.
Install¶
Requires Python 3.11–3.14. The mylonite CLI is on PyPI:
pip install mylonite # the CLI that scans your app
pip install "mylonite[demo]" # + the reference app, for `mylonite demo`
Then, with no API key and nothing to configure:
That replays a recorded run against the bundled reference app's vulnerable and guarded
builds. It shows a kept finding with its suggested fix, then the regression test
generated for it failing on the vulnerable build and passing on the guarded one, then the
scan table for every weakness class. It is the fastest way to see what the tool does. See demo for exactly
what "replay" means and how it differs from a live scan.
The [demo] extra adds the reference target (mcp-kitchen-sink), which is a separate
package: a plain pip install mylonite never pulls the deliberately-vulnerable reference
agent. The extra pins it exactly, because the demo's recorded fixtures are keyed on that
package's tool schemas.
To hack on Mylonite or the reference target, use a development checkout with two
editable installs (the mylonite package, then the reference target):
On Linux / macOS (bash):
git clone https://github.com/Abidemialade/mylonite.git
cd mylonite
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
pip install -e ./reference_targets/mcp_kitchen_sink
On Windows (PowerShell):
git clone https://github.com/Abidemialade/mylonite.git
cd mylonite
python -m venv .venv
.venv\Scripts\Activate.ps1
pip install -e ".[dev]"
pip install -e ./reference_targets/mcp_kitchen_sink
Contributors should also run pre-commit install after installing.
Choose a model¶
demo replays a recording and needs no model. Every other live command
(scan, validate, gate, ablate) needs one picked — there is no
default provider or model. Set it once so you don't have to repeat it on
every command:
export MYLONITE_MODEL=anthropic/claude-haiku-4-5-20251001 # needs ANTHROPIC_API_KEY
export ANTHROPIC_API_KEY=sk-ant-...
The full provider table, and how to hand over a key, is on Choose a model.
Any LiteLLM provider works the same way: a provider/model prefix (e.g.
--model openai/gpt-4o) plus that provider's own key env var — --model
and mylonite.yaml's model: key both work instead of the environment
variable, same precedence as everywhere else in the CLI. No key at all? Run
a local model instead: --model ollama_chat/llama3.2:3b with
Ollama running. With none of the three set, every
live command stops before touching a target, naming the approved providers
and exiting 4 — see "No model chosen at all?" in
the CLI reference for the exact message. This key pays
for Mylonite's own planner, customiser and judge calls, never for a call
your app's own agent made.
Commands that work today¶
mylonite version
mylonite scan reference:vulnerable
mylonite scan mcp:fetch --authorize fetch
mylonite gate reference:vulnerable # scan -> test -> validate, the full pipeline
mylonite report .mylonite/scans/<dir> --sarif out.sarif --json finding.json
mylonite scan <target>— run the live exploit-finding loop. On an MCP target, Mylonite drives your tools itself with its own agent (the planner), reading your system prompt and tool descriptions — it is not your app's own model or framework making the calls. Needs the model and key from Choose a model above. Targets:reference:vulnerable/reference:guarded(the in-process reference app builds), and the bundled MCP (Model Context Protocol) stdio familiesmcp:filesystem:<sandbox>,mcp:fetch,mcp:github:<owner/repo>— these require--authorizenaming the family itself (fetchabove) or, formcp:filesystem/mcp:github, the scope after the second colon (see the responsible-use policy) plus the family's runtime:uvformcp:fetch(spawns viauvx), Node.js formcp:filesystem/mcp:github(spawn vianpx). Add--dry-runto enumerate seeds without an API key.mylonite gate <target>— the whole pipeline (scan → generate → validate → optional PR) in one command; only a kept test makes it through. See CI gating.mylonite report <dir>— render a scan/validation as a terminal panel,--sarif(GitHub code scanning), or--jsonbundle. See Reading the results.
The full flow: scan → generate → validate¶
The end-to-end pipeline works today. Scan a target for a weakness, emit a regression test from the finding, then validate that the test is meaningful through the differential oracle.
On Linux / macOS (bash):
mylonite scan reference:vulnerable
mylonite generate --latest
mylonite validate .mylonite/generated/indirect_injection_note_body_direct
On Windows (PowerShell):
mylonite scan reference:vulnerable
mylonite generate --latest
mylonite validate .mylonite\generated\indirect_injection_note_body_direct
mylonite scan reference:vulnerable— runs the live exploit-finding loop against the in-process vulnerable build and writesexploit_*.jsonartefacts under.mylonite/scans/<ts>/. Live — needs an API key (see below).mylonite generate --latest— offline and deterministic (no LLM call). Reads the newest scan's exploit, emits a testkit-based pytest regression test, and prints the exactmylonite validate <dir>command to run next. The test is stamped UNVALIDATED untilvalidatekeeps it.--latestpicks the newest scan; pass an explicitexploit_*.jsonor scan dir instead if you prefer.mylonite validate <dir>— runs theDifferentialValidator(the validation engine). Live — it makes real LLM calls against the model you chose in Choose a model, so it needs that provider's API key; it states the work it will run up front and reports the LLM calls and tokens it used at the end. It runs the finding's own attack against both reference builds across a 5-run flakiness filter and reportskeptplus the mutation score. Exits0when the test is kept and5when it is cleanly rejected.
generate is the only offline command here; scan and validate both make
live LLM calls. Whether the committed regression test that generate emits
replays offline at the CI gate depends on the target: for the bundled
reference:* builds it replays offline (no API key needed there); for a
real, custom target (--target-file) there is no recorded twin to replay, so
the emitted test re-drives your actual app live, gated behind
MYLONITE_LIVE_TARGET=1 (the CI workflow sets it for you) — see
The validation engine and CI gating.
Gate it (CI) and read the results¶
Turn a finding into a committed regression test and a gating PR with one command, then render it in whatever format your pipeline consumes:
mylonite gate --target-file app.yaml --authorize my-app --open-pr # against YOUR app
mylonite report .mylonite/generated/<dir> --sarif out.sarif # GitHub code scanning
mylonite report .mylonite/generated/<dir> --json finding.json # dashboards / SIEM / bots
Where to go next¶
- Test your own app — the custom MCP on-ramp (
scan --scaffold→ scan → gate). - Weakness classes — what W1–W4 mean.
- Try it — the reference app — the deliberately vulnerable playground (W1–W4 walkthrough).
- Attack modes — the single-shot W1–W4 attack engine.
- The validation engine — why a generated test means what it claims.
- Reading the results · CLI reference.