Static analyzer flagging lookahead bias & data leakage in ML/trading code before backtest.
Copy the AI prompt to install this server into Claude Code, Cursor, or another agent β or use 1-click editor setup below.
We haven't yet run this listing's install command through our automated sandbox check. This isn't a red flag β we're steadily working through the catalog.
π‘ Paste the JSON block into your client's configuration file under mcpServers, then restart the application.
Squawk for backtests. A local-first MCP server that static-analyzes agent-generated Python code and flags lookahead bias & data leakage before the backtest runs.
Works for any time-series ML code β quant trading (crypto, equities, forex, futures),
demand forecasting, energy, weather, IoT sensors β wherever a wrong .shift() or a
global normalization silently poisons your results.

AI agents (Claude Code, Cursor) write feature engineering and strategy code faster than humans can review it. But they introduce lookahead bias at scale β subtle time-boundary errors that backtest perfectly and fail catastrophically in live trading or production:
leakguard catches these in the same agent loop β before the backtest runs:
The agent reads the finding + fix snippet and self-corrects in one turn. No human review needed.
Add to your MCP config (~/.claude/claude_desktop_config.json or .claude/settings.json
in your project):
Or if installed via uv:
Restart Claude Code. leakguard's tools are now available to the agent.
Add the same block under mcpServers in your Cursor MCP settings file.
| Tool | Description |
|---|---|
lint_code(code) | Analyze a code string, return findings |
lint_file(path) | Analyze a file on disk |
lint_paths(glob) | Analyze all matching files |
list_rules() | List all rules with severities |
explain_rule(rule_id) | Full rationale + fix patterns for a rule |
The same scanner is available as a CLI β handy for a pre-commit hook or CI step (exits non-zero when leakage is found):
It prints each finding with its severity, line/col, and a concrete fix snippet β the same output shown in the demo above.
All 10 rules active, no tiers:
| ID | Severity | Pattern |
|---|---|---|
| LG001 | π΄ | Future shift as feature: shift(-n) / diff(-n) / pct_change(-n) |
| LG002 | π΄ | Centered windows: rolling(center=True) |
| LG003 | π΄ | Global-fit scaling: StandardScaler().fit(full_df) / hand-rolled mean-std before split |
| LG004 | π΄ | Shuffled time-series split: train_test_split default, KFold, cross_val_score(cv=n) |
| LG005 | π΄ | Label leakage: future-derived target column reused in features |
| LG006 | π‘ | Whole-history aggregates as features: .max() / .mean() over full series |
| LG007 | π΄ | Backfill imputation: bfill() / fillna(method='bfill') |
| LG008 | π΄ | Forward asof-joins: merge_asof(direction='forward'/'nearest') |
| LG009 | π‘ | Resample label/closed mismatch on bar timestamps |
| LG010 | π‘ | groupby().transform()/agg() spanning train/test boundary |
Each finding includes a concrete fix snippet so the calling agent can self-correct immediately.
Measured on two labeled corpora, 49 snippets total.
Reproduce with uv run python -m benchmark.run.
Honesty note: the trading corpus was written by the tool's author β treat its numbers as regression fixtures, not independent validation. The general-ML corpus is one arm's length removed in domain (author-composed reproductions of widely documented leakage anti-patterns, not a downloaded public dataset). The corpus deliberately includes adversarial snippets the scanner is known to miss; they are counted against it.
Trading corpus β 39 snippets (23 leaky, 16 clean + hard negatives):
| Rule | Precision | Recall | TP | FP | FN |
|---|---|---|---|---|---|
| LG001 | 75% | 100% | 6 | 2 | 0 |
| LG002 | 100% | 100% | 5 | 0 | 0 |
| LG003 | 75% | 100% | 3 | 1 | 0 |
| LG004 | 100% | 100% | 4 | 0 | 0 |
| LG005 | 100% | 100% | 5 | 0 | 0 |
| LG006 | 100% | 100% | 5 | 0 | 0 |
| LG007 | 100% | 100% | 5 | 0 | 0 |
| LG008 | 100% | 100% | 2 | 0 | 0 |
| LG009 | 75% | 100% | 3 | 1 | 0 |
| LG010 | 100% | 100% | 2 | 0 | 0 |
| Overall | 91% | 100% | 40 | 4 | 0 |
General-ML corpus β 10 snippets (LG003/LG004/LG010): Precision 88%, Recall 100% (TP 7 / FP 1 / FN 0).
Combined: Precision 90.4%, Recall 100% (TP 47 / FP 5 / FN 0).
Recall is 100% on this corpus β every adversarial miss exposed has since been fixed
(constant propagation, hand-rolled normalization, cv=<int>, drop-based selection).
Leak shapes not yet in the corpus are still missed β see Known Limitations below.
y β
pure AST cannot distinguish a target column from a feature.cross_val_score(...) with cv omitted (defaults to KFold).df.loc[:, 'col'] = ... or df.assign(col=...).These sets are pinned in tests/test_benchmark.py: any new miss or silent fix fails the
suite until docs and corpus are updated to match.
The scanner core lives in leakguard/core/ (pure, no MCP imports); server.py and
cli.py are thin wrappers. Each rule has a fixture pair under tests/fixtures/.
Contributions welcome: new corpus snippets (especially real bugs you've hit) strengthen the benchmark more than new rules do.
No reviews yet β be the first to share how this listing worked for you.
Showcase your server listing on GitHub or your project documentation. Embed this dynamic SVG badge to highlight official listing status and live engagement.
[](https://allmcps.com/mcp/leakguard-mcp)<a href="https://allmcps.com/mcp/leakguard-mcp"><img src="https://allmcps.com/api/badge/leakguard-mcp?style=directory" alt="Leakguard MCP on AllMCPs" /></a>