AI-powered app test automation for iOS, Android, Flutter, React Native, Web
Copy the AI prompt to install this server into Claude Code, Cursor, or another agent β or use 1-click editor setup below.
π‘ Paste into ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows)
Built for vibe coders: one command, get a prioritized list of what's actually broken about your project.
Self-healing test automation for iOS, Android, Flutter, React Native and Web apps β as an MCP server.
v3.1.1 β vibe-check + honest auto-fix. One MCP call, ~30 seconds: race conditions + security issues + memory leaks + logic errors + perf smells, prioritized. Stays on your machine, no telemetry. Pass
autoFix: truefor the small, safe mechanical fixes (weak-hash, simpleMath.randomassignment) β backup + syntax-validate + rollback-on-syntax-fail. For test-verified application of harder fixes, use v3.0.0's iterate-fix loop.
You don't read the docs. You open the project, talk to Claude, and want a verdict. Here it is:
In Claude (with test-genie-mcp installed β setup):
Claude calls diagnose_project under the hood. ~30 seconds later you see:
If any finding is autoFixable: true and is at high/critical severity, the diagnose_project call accepts autoFix: true to apply the mechanical replacement directly (with backup + syntax validation β see SAFETY.md for the exact guards). The v3.1.1 honest scope is narrow: weak hash (createHash('md5'|'sha1') β createHash('sha256')) and standalone Math.random() in security-sensitive files. For broader/structural fixes (race conditions, eval, exec injection) run run_iterative_fix_loop separately β it re-runs tests and auto-rolls-back on regression.
The bottleneck in mobile + cross-platform test automation isn't writing tests β it's the loop between a failing test and a passing test. test-genie closes that loop:
This full loop is the run_iterative_fix_loop tool. The diagnose_project autoFix: true path in v3.1.1 covers a strict subset β backup + dry-run + syntax-validate + apply, without re-running tests (so no test-regression rollback in that path). Use the right tool for the job β and see SAFETY.md for the exact guards on each.
Other tools (Detox, Maestro, Playwright, xcodebuild test) run tests. test-genie runs tests and drives the fix until the bar is met or it can no longer make progress β without you scrubbing through stack traces.
Expected output (truncated):
Re-call with autoApply: true (or resumeToken: "f8b3β¦") to actually patch the files.
The flows below describe the
run_iterative_fix_looppath (v3.0 headline) β full detect β propose β dry-run β apply-with-backup β re-run-tests β rollback-on-regression. Thediagnose_project autoFixpath in v3.1.1 is the narrower mechanical-replacement-only path; see SAFETY.md Β§4 for what that one actually touches.
A team adds setInterval(...) in a useEffect and forgets cleanup. test-genie's detect_memory_leaks flags it, suggest_fixes proposes return () => clearInterval(id) (src/tools/fixing/suggestFixes.ts:169-179), the loop dry-runs the patch through the TS compiler, applies with backup, re-runs only the affected snapshot test, confirms 100% pass, stops. Before: 1 failing snapshot. After: 0 failing, 1 fix applied, 1 backup at .test-genie-backups/.
dispose() automationAnimationController left undisposed. test-genie sees the missing dispose() override, generates a Dart @override dispose() { controller.dispose(); super.dispose(); } block (suggestFixes.ts:214-217), runs dart analyze on the patched file, applies, re-runs flutter test, converges.
self.timer = Timer.scheduledTimer(...) { _ in self.tick() } β rule-based detector flags closure self-capture, fixer rewrites to [weak self] _ in guard let self = self else { return }; self.tick() (suggestFixes.ts:239-242). If swiftc is on PATH the syntax check is real; otherwise test-genie reports "downgraded validation" so you know.
See docs/ITERATE_FIX_LOOP.md for a sequence diagram and the full safety-guard list.
| # | Tool | Mode |
|---|---|---|
| 1 | analyze_app_structure | real |
| 2 | generate_scenarios | real |
| 3 | create_test_plan | real |
| 4 | run_scenario_test | hybrid |
| 5 | run_simulation | simulated |
| 6 | run_stress_test | hybrid |
| 7 | detect_memory_leaks | real |
| 8 | detect_logic_errors | real |
| 9 | suggest_fixes | real |
| 10 | confirm_fix | real |
| 11 | apply_fix | real |
| 12 | rollback_fix | real |
| 13 | run_full_automation | hybrid |
| 14 | run_iterative_fix_loop (v3.0 headline) | hybrid |
| 15 | generate_report | real |
| 16 | get_pending_fixes | real |
| 17 | get_test_history | real |
| 18 | analyze_performance | real |
| 19 | analyze_code_deep | real |
| 20 | generate_cicd_config | real |
| 21 | diagnose_project (v3.1 headline β vibe-check) | real |
| 22 | detect_race_conditions | real |
| 23 | detect_security_issues | real |
mode legend in docs/SIMULATION_VS_REAL.md.
Plus 4 resources (test-genie://iteration-logs, β¦/test-history/{path}, β¦/iteration-logs/{loopId}, β¦/applied-fixes/{path}) and 3 prompts (full-test-pipeline, diagnose-failure, vibe-check).
Race conditions (detect_race_conditions / diagnose_project):
| Pattern | Language | Severity | Auto-fixable (v3.1.1) |
|---|---|---|---|
useState setter called after await without mount guard | TS/JS/React | high | no (structural) |
useEffect with async fetch, no AbortController/cleanup | TS/JS/React | high | no (structural) |
arr.forEach(async ...) (silent fire-and-forget) | TS/JS | medium | no (ordering-sensitive) |
Adjacent fetches without Promise.all / sequencing | TS/JS | medium | no |
TOCTOU: existsSync then readFileSync without lock | TS/JS Node | medium | no |
| Non-atomic counter increment in async context | TS/JS | low | no |
@Published mutation outside @MainActor | Swift | medium | no |
Concurrent DispatchQueue writes without .barrier | Swift | medium | no |
MutableStateFlow mutated off Dispatchers.Main | Kotlin | medium | no |
Flow collected without flowOn | Kotlin | low | no |
Goroutine + shared map without sync.Mutex | Go | high | no |
v3.1.1 honesty audit:
useEffect-no-abortandforEach-awaitwere previously advertised as auto-fixable. They are not β wrapping withAbortControlleror rewriting toPromise.all(arr.map(...))changes behavior we can't verify statically. They are now report-only. See SAFETY.md.
Security (detect_security_issues / diagnose_project):
| Pattern | Severity | CWE | Auto-fixable (v3.1.1) |
|---|---|---|---|
| Hardcoded AWS / Stripe / GitHub / Google / Slack token | critical / high | CWE-798 | no (rotate) |
| Hardcoded JWT secret literal | high | CWE-798 | no |
| API token in URL query string | high | CWE-200 | no |
.env file present but not gitignored | high | CWE-538 | no (rotation must follow) |
SQL string concat with req.params / req.body | critical | CWE-89 | no |
innerHTML / dangerouslySetInnerHTML with dynamic value | high | CWE-79 | no |
eval() / new Function() with non-literal | critical | CWE-95 | no |
Math.random() in security-sensitive file, standalone assignment | high | CWE-338 | yes (crypto.randomInt) |
Math.random() mixed into arithmetic | high | CWE-338 | no (semantic) |
createHash('md5'|'sha1') in security-keyword file | high | CWE-327 | yes ('sha256') |
createHash('md5'|'sha1') elsewhere | medium | CWE-327 | no (below severity floor) |
child_process.exec with user-input template literal | critical | CWE-78 | no |
fetch(req.query.url) (SSRF) | high | CWE-918 | no |
CORS * origin + Allow-Credentials: true | high | CWE-942 | no |
Cookie set without httpOnly / secure / sameSite | low | CWE-1004 | no |
yaml.load without safe schema | medium | CWE-502 | no |
v3.1.1 honesty audit:
.env/Math.random(general)/yaml.loadwere previously advertised as auto-fixable. They were either too risky to rewrite blindly or no strategy shipped β flipped to report-only. See SAFETY.md Β§5.
This is a "catch the obvious stuff in 30s" filter, not Snyk / Semgrep / a full SAST tool. We don't catch:
db.query, the regex won't connect the dots. A real SAST traces taint across the call graph. Roadmap: ts-morph reference walking for top-N entry points.npm audit's job, and bundling a stale advisory list would lie. Run npm audit --json in parallel if you want dep-CVE coverage.Math.random() named getNonce won't fool us; a properly-named crypto.randomBytes used with a tiny entropy budget will.securityAnalyzer.SECRET_PATTERNS. PR welcome.run_stress_test / run_simulation, not static analysis.If you want deeper coverage on top of vibe-check: feed the findings into run_iterative_fix_loop for test-verified application, or escalate to Snyk / Semgrep / GitHub Advanced Security for compliance use cases.
| vibe-check (test-genie) | Snyk | Semgrep | GitHub Advanced Security | |
|---|---|---|---|---|
| Runs locally | yes | hybrid (cloud) | yes | no (cloud) |
| Telemetry-free | yes (zero network calls) | no | partial | no |
| Fix loop integration | yes (run_iterative_fix_loop) | no | no | no |
| Race-condition detection | yes (JS/Swift/Kotlin/Go) | no | partial | partial |
| Cross-file taint flow | no (roadmap) | yes | yes | yes |
| Setup time | none (already installed if test-genie is installed) | account + auth | install + ruleset | repo-level enable |
If your goal is "before I commit, what's broken?", vibe-check wins on latency. If your goal is "compliance + supply chain audit", use the dedicated tools.
autoApply: false (the default) and use it as a fix-proposal generator only.| test-genie | Detox | Maestro | xcodebuild test | |
|---|---|---|---|---|
| Runs E2E / unit tests | β (via Jest/Detox/etc.) | β | β | β |
| Detects code issues | β rule + LLM | β | β | β |
| Iterative fix loop | β
(run_iterative_fix_loop) | β | β | β |
| Auto-rollback on test regression | β
inside run_iterative_fix_loop only | β | β | β |
| Auto-rollback on syntax failure | β all apply paths | β | β | β |
| MCP-native (talks to Claude / agents) | β | β | β | β |
| Multi-platform | iOS+Android+Web+Flutter+RN | iOS+Android | iOS+Android | iOS only |
Scope note:
diagnose_project autoFix: truerolls back on syntax-validate failure (applyFix.ts:185-202) but does not re-run tests, so it cannot detect test regressions. For test-driven rollback userun_iterative_fix_loop. See SAFETY.md Β§2.4.
test-genie uses tools like Jest, Detox, and xcodebuild test under the hood β it sits at the orchestration layer, not the test-runner layer.
-typecheck mode. If the compiler isn't on PATH, we fall back to brace-balance validation and surface downgraded: true in the result. Install swiftc / kotlinc / javac / dart for real validation.strategy: 'hybrid' only kicks LLM in when rule-based confidence is below threshold. Without an API key the loop is rule-based-only β no failure.$TEST_GENIE_STORAGE_DIR (defaults to ~/.test-genie-mcp). Not synced across machines.run_simulation returns plausible anomalies, not real ones. Use run_scenario_test (hybrid) for real-device runs.| Env var | Default | Purpose |
|---|---|---|
TEST_GENIE_ALLOWED_ROOT | cwd | Capability-based path safety β server refuses to read/write outside this root. |
TEST_GENIE_STORAGE_DIR | ~/.test-genie-mcp | Where scenarios / results / iteration logs live. |
TEST_GENIE_LLM_PROVIDER | auto-detect | anthropic / openai / none. |
ANTHROPIC_API_KEY | β | Used when provider = anthropic. |
OPENAI_API_KEY | β | Used when provider = openai. |
TEST_GENIE_ANTHROPIC_MODEL | claude-haiku-4-5 | Override Anthropic model. |
TEST_GENIE_OPENAI_MODEL | gpt-4o-mini | Override OpenAI model. |
run_full_automation still works. The confirmMode / autoFix options are kept for compatibility but autoApply: boolean is the new way β autoApply: true is equivalent to confirmMode: 'auto'.Issues, PRs, and ideas welcome β see CONTRIBUTING.md (TODO). Code lives under src/, tests under tests/. Run npm test before sending a PR.
@MUSE-CODE-SPACE β Yoonkyoung Gong.
MIT β see LICENSE.
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/test-genie)<a href="https://allmcps.com/mcp/test-genie"><img src="https://allmcps.com/api/badge/test-genie?style=directory" alt="Test Genie on AllMCPs" /></a>