{
  "markdown": "# test-genie-mcp\n\n**Built for vibe coders: one command, get a prioritized list of what's actually broken about your project.**\n\nSelf-healing test automation for iOS, Android, Flutter, React Native and Web apps — as an MCP server.\n\n[![npm version](https://img.shields.io/npm/v/test-genie-mcp.svg)](https://www.npmjs.com/package/test-genie-mcp)\n[![CI](https://img.shields.io/github/actions/workflow/status/MUSE-CODE-SPACE/test-genie-mcp/ci.yml?branch=main)](https://github.com/MUSE-CODE-SPACE/test-genie-mcp/actions)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![MCP](https://img.shields.io/badge/MCP-1.29-blue)](https://modelcontextprotocol.io)\n\n> **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: true` for the small, safe mechanical fixes (weak-hash, simple `Math.random` assignment) — backup + syntax-validate + rollback-on-syntax-fail. For test-verified application of harder fixes, use [v3.0.0](#how-the-iterate-fix-loop-works)'s iterate-fix loop.\n\n---\n\n## Vibe coders quickstart\n\nYou don't read the docs. You open the project, talk to Claude, and want a verdict. Here it is:\n\nIn Claude (with test-genie-mcp installed — [setup](#5-minute-quickstart)):\n\n```\n/vibe-check /Users/me/my-app\n```\n\nClaude calls `diagnose_project` under the hood. ~30 seconds later you see:\n\n```text\n# vibe-check report\n\n- Project: /Users/me/my-app\n- Platform: web\n- Findings: 11 total — 4 critical, 4 high, 1 medium, 1 low\n- Estimated fix time: ~85 min\n\n## Top 5 issues\n\n### 1. [CRIT] Hardcoded AWS access key id found in source\n- File: `server.js:7`\n- Category: security / secret (CWE-798)\n- Confidence: 95%\n- Fix: Move the value to an env var, gitignore the config, rotate the leaked key.\n\n### 2. [CRIT] SQL string built by concatenating user input\n- File: `server.js:21`\n- Category: security / injection (CWE-89)\n- Fix: Use parameterized queries (`db.query(\"... WHERE id = ?\", [id])`).\n\n### 3. [HIGH] useState setter called after await without mount guard\n- File: `UserProfile.tsx:16`\n- Category: race-condition / react-setstate-after-await (CWE-362)\n- Confidence: 78%\n- Fix: Use AbortController and check signal.aborted before calling setters.\n\n… (top 5 shown — full list at output: \"detailed\")\n\n## Next steps\n1. Address the critical / high findings above.\n2. Re-run diagnose_project after fixing to confirm convergence.\n3. Use run_iterative_fix_loop for test-driven verification of each fix.\n```\n\nIf 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](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.\n\n---\n\n## Why test-genie?\n\nThe 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:\n\n```\nfailing test → analyzer flags issue → fix proposed → dry-run + syntax check →\napplied with backup → affected tests re-run → regression check → loop or stop\n```\n\nThis 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](SAFETY.md) for the exact guards on each.\n\nOther 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.\n\n---\n\n## 5-minute Quickstart\n\n```bash\n# 1. Install\nnpm install -g test-genie-mcp\n\n# 2. Add to Claude Desktop config (~/.config/claude/claude_desktop_config.json)\n{\n  \"mcpServers\": {\n    \"test-genie\": {\n      \"command\": \"npx\",\n      \"args\": [\"test-genie-mcp\"],\n      \"env\": {\n        \"TEST_GENIE_ALLOWED_ROOT\": \"/path/to/your/project\"\n      }\n    }\n  }\n}\n\n# 3. Restart Claude Desktop. From a chat:\n#    \"Run the iterate-fix loop on /Users/me/my-rn-app with autoApply=false\"\n```\n\nExpected output (truncated):\n\n```\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\nIterative fix loop f8b3… — PAUSED-FOR-CONFIRMATION\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\nIterations completed: 1\nFixes applied:        0\nRegressions rolled back: 0\nFinal tests:          7/10 passing (3 failing)\n\nPending confirmations (3):\n  - 71fbe…: Fix: useEffect missing cleanup for setInterval (confidence: 85)\n  - 92ad1…: Fix: Force-unwrap on possibly-undefined name (confidence: 85)\n  - …\n\nResume token: f8b3…\n```\n\nRe-call with `autoApply: true` (or `resumeToken: \"f8b3…\"`) to actually patch the files.\n\n---\n\n## Real use cases\n\n> The flows below describe the **`run_iterative_fix_loop` path** (v3.0\n> headline) — full detect → propose → dry-run → apply-with-backup →\n> re-run-tests → rollback-on-regression. The `diagnose_project autoFix`\n> path in v3.1.1 is the narrower mechanical-replacement-only path; see\n> [SAFETY.md](SAFETY.md) §4 for what that one actually touches.\n\n### 1. React Native memory-leak self-healing\n\nA 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/`.\n\n### 2. Flutter widget `dispose()` automation\n\n`AnimationController` 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.\n\n### 3. iOS retain-cycle (closure capture)\n\n`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.\n\n---\n\n## How the iterate-fix loop works\n\n```\n┌────────────────────┐\n│   collect tests    │  (run_scenario_test / supplied list)\n└─────────┬──────────┘\n          │\n   pass-rate ≥ threshold? ── yes ──▶  SUCCESS\n          │ no\n          ▼\n┌────────────────────┐\n│  detect issues     │   memory + logic analyzers\n└─────────┬──────────┘\n          │\n┌────────────────────┐\n│  suggest fixes     │   rule-based (default) → LLM (hybrid, optional)\n└─────────┬──────────┘\n          │\n┌────────────────────┐\n│  dry-run + syntax  │   TS compiler API / platform compiler / brace check\n└─────────┬──────────┘\n          │\n┌────────────────────┐\n│  apply with backup │   per-file `.test-genie-backups/`\n└─────────┬──────────┘\n          │\n┌────────────────────┐\n│  re-run tests      │   regression?  yes → auto-rollback\n└─────────┬──────────┘\n          │\n          ▼\n   loop (≤ maxIterations, ≤ totalTimeout)\n```\n\nSee **[docs/ITERATE_FIX_LOOP.md](docs/ITERATE_FIX_LOOP.md)** for a sequence diagram and the full safety-guard list.\n\n---\n\n## Tools (23)\n\n| # | Tool | Mode |\n|---|------|------|\n| 1 | `analyze_app_structure` | real |\n| 2 | `generate_scenarios` | real |\n| 3 | `create_test_plan` | real |\n| 4 | `run_scenario_test` | hybrid |\n| 5 | `run_simulation` | simulated |\n| 6 | `run_stress_test` | hybrid |\n| 7 | `detect_memory_leaks` | real |\n| 8 | `detect_logic_errors` | real |\n| 9 | `suggest_fixes` | real |\n| 10 | `confirm_fix` | real |\n| 11 | `apply_fix` | real |\n| 12 | `rollback_fix` | real |\n| 13 | `run_full_automation` | hybrid |\n| 14 | `run_iterative_fix_loop` (v3.0 headline) | hybrid |\n| 15 | `generate_report` | real |\n| 16 | `get_pending_fixes` | real |\n| 17 | `get_test_history` | real |\n| 18 | `analyze_performance` | real |\n| 19 | `analyze_code_deep` | real |\n| 20 | `generate_cicd_config` | real |\n| 21 | **`diagnose_project`** (v3.1 headline — vibe-check) | real |\n| 22 | `detect_race_conditions` | real |\n| 23 | `detect_security_issues` | real |\n\n`mode` legend in **[docs/SIMULATION_VS_REAL.md](docs/SIMULATION_VS_REAL.md)**.\n\nPlus 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`).\n\n---\n\n## What vibe-check catches\n\nRace conditions (`detect_race_conditions` / `diagnose_project`):\n\n| Pattern | Language | Severity | Auto-fixable (v3.1.1) |\n|---|---|---|---|\n| `useState` setter called after `await` without mount guard | TS/JS/React | high | no (structural) |\n| `useEffect` with async fetch, no AbortController/cleanup | TS/JS/React | high | no (structural) |\n| `arr.forEach(async ...)` (silent fire-and-forget) | TS/JS | medium | no (ordering-sensitive) |\n| Adjacent fetches without `Promise.all` / sequencing | TS/JS | medium | no |\n| TOCTOU: `existsSync` then `readFileSync` without lock | TS/JS Node | medium | no |\n| Non-atomic counter increment in async context | TS/JS | low | no |\n| `@Published` mutation outside `@MainActor` | Swift | medium | no |\n| Concurrent `DispatchQueue` writes without `.barrier` | Swift | medium | no |\n| `MutableStateFlow` mutated off `Dispatchers.Main` | Kotlin | medium | no |\n| `Flow` collected without `flowOn` | Kotlin | low | no |\n| Goroutine + shared map without `sync.Mutex` | Go | high | no |\n\n> v3.1.1 honesty audit: `useEffect-no-abort` and `forEach-await` were\n> previously advertised as auto-fixable. They are not — wrapping with\n> `AbortController` or rewriting to `Promise.all(arr.map(...))` changes\n> behavior we can't verify statically. They are now report-only. See\n> [SAFETY.md](SAFETY.md).\n\nSecurity (`detect_security_issues` / `diagnose_project`):\n\n| Pattern | Severity | CWE | Auto-fixable (v3.1.1) |\n|---|---|---|---|\n| Hardcoded AWS / Stripe / GitHub / Google / Slack token | critical / high | CWE-798 | no (rotate) |\n| Hardcoded JWT secret literal | high | CWE-798 | no |\n| API token in URL query string | high | CWE-200 | no |\n| `.env` file present but not gitignored | high | CWE-538 | no (rotation must follow) |\n| SQL string concat with `req.params` / `req.body` | critical | CWE-89 | no |\n| `innerHTML` / `dangerouslySetInnerHTML` with dynamic value | high | CWE-79 | no |\n| `eval()` / `new Function()` with non-literal | critical | CWE-95 | no |\n| `Math.random()` in security-sensitive file, **standalone assignment** | high | CWE-338 | **yes** (`crypto.randomInt`) |\n| `Math.random()` mixed into arithmetic | high | CWE-338 | no (semantic) |\n| `createHash('md5'\\|'sha1')` in security-keyword file | high | CWE-327 | **yes** (`'sha256'`) |\n| `createHash('md5'\\|'sha1')` elsewhere | medium | CWE-327 | no (below severity floor) |\n| `child_process.exec` with user-input template literal | critical | CWE-78 | no |\n| `fetch(req.query.url)` (SSRF) | high | CWE-918 | no |\n| CORS `*` origin + `Allow-Credentials: true` | high | CWE-942 | no |\n| Cookie set without `httpOnly` / `secure` / `sameSite` | low | CWE-1004 | no |\n| `yaml.load` without safe schema | medium | CWE-502 | no |\n\n> v3.1.1 honesty audit: `.env`/`Math.random` (general)/`yaml.load` were\n> previously advertised as auto-fixable. They were either too risky to\n> rewrite blindly or no strategy shipped — flipped to report-only. See\n> [SAFETY.md](SAFETY.md) §5.\n\n---\n\n## What vibe-check misses (honest list)\n\nThis is a \"catch the obvious stuff in 30s\" filter, not Snyk / Semgrep / a full SAST tool. We don't catch:\n\n- **Cross-file data-flow.** If user input flows through three files before reaching a `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.\n- **Vulnerable transitive deps.** We don't query npm advisories — that's `npm audit`'s job, and bundling a stale advisory list would lie. Run `npm audit --json` in parallel if you want dep-CVE coverage.\n- **Race conditions across processes.** We catch in-process JS / Swift / Kotlin / Go races. Distributed races (lock ordering across services, DB transactions) need different tooling.\n- **Type-correct but logic-broken code.** The analyzer is syntactic, not semantic. A `Math.random()` named `getNonce` won't fool us; a properly-named `crypto.randomBytes` used with a tiny entropy budget will.\n- **Custom secret formats.** Internal company tokens with unique prefixes need a regex you can add to `securityAnalyzer.SECRET_PATTERNS`. PR welcome.\n- **Real-time / dynamic issues.** Memory leaks under load, network timeouts, slow renders mid-interaction — those need `run_stress_test` / `run_simulation`, not static analysis.\n\nIf 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.\n\n---\n\n## vibe-check vs alternatives\n\n|                        | vibe-check (test-genie) | Snyk | Semgrep | GitHub Advanced Security |\n|------------------------|-------------------------|------|---------|--------------------------|\n| Runs locally           | yes                     | hybrid (cloud) | yes  | no (cloud) |\n| Telemetry-free         | yes (zero network calls) | no  | partial | no |\n| Fix loop integration   | yes (`run_iterative_fix_loop`) | no | no | no |\n| Race-condition detection | yes (JS/Swift/Kotlin/Go) | no | partial | partial |\n| Cross-file taint flow  | no (roadmap)            | yes  | yes     | yes |\n| Setup time             | none (already installed if test-genie is installed) | account + auth | install + ruleset | repo-level enable |\n\nIf 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.\n\n---\n\n## When NOT to use test-genie\n\n- **Production-gate test runs.** test-genie is built for the *development* feedback loop. For shipping decisions, use a proper CI that you control end-to-end.\n- **Code your team must hand-review every line of.** The loop's job is to *propose and apply* fixes; if every fix needs a human eye, leave `autoApply: false` (the default) and use it as a fix-proposal generator only.\n- **No backup / no version control situations.** test-genie's auto-rollback is best-effort and requires the per-file backup to exist. Always run inside a git working tree.\n\n---\n\n## Comparison\n\n| | test-genie | Detox | Maestro | xcodebuild test |\n|---|---|---|---|---|\n| Runs E2E / unit tests | ✅ (via Jest/Detox/etc.) | ✅ | ✅ | ✅ |\n| Detects code issues | ✅ rule + LLM | ❌ | ❌ | ❌ |\n| **Iterative fix loop** | **✅** (`run_iterative_fix_loop`) | ❌ | ❌ | ❌ |\n| Auto-rollback on test regression | ✅ inside `run_iterative_fix_loop` only | ❌ | ❌ | ❌ |\n| Auto-rollback on syntax failure | ✅ all apply paths | ❌ | ❌ | ❌ |\n| MCP-native (talks to Claude / agents) | ✅ | ❌ | ❌ | ❌ |\n| Multi-platform | iOS+Android+Web+Flutter+RN | iOS+Android | iOS+Android | iOS only |\n\n> Scope note: `diagnose_project autoFix: true` rolls back on syntax-validate\n> failure (`applyFix.ts:185-202`) but does **not** re-run tests, so it\n> cannot detect test regressions. For test-driven rollback use\n> `run_iterative_fix_loop`. See [SAFETY.md](SAFETY.md) §2.4.\n\ntest-genie *uses* tools like Jest, Detox, and `xcodebuild test` under the hood — it sits at the orchestration layer, not the test-runner layer.\n\n---\n\n## Known limitations\n\n- **Platform syntax check downgrade.** For Swift/Kotlin/Java/Dart we try the platform compiler in `-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.\n- **LLM is optional and gated.** `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.\n- **Storage is per-machine.** Test history / iteration logs live under `$TEST_GENIE_STORAGE_DIR` (defaults to `~/.test-genie-mcp`). Not synced across machines.\n- **Simulated mode is \"simulation,\" not magic.** `run_simulation` returns *plausible* anomalies, not real ones. Use `run_scenario_test` (hybrid) for real-device runs.\n\n---\n\n## Configuration\n\n| Env var | Default | Purpose |\n|---|---|---|\n| `TEST_GENIE_ALLOWED_ROOT` | `cwd` | Capability-based path safety — server refuses to read/write outside this root. |\n| `TEST_GENIE_STORAGE_DIR` | `~/.test-genie-mcp` | Where scenarios / results / iteration logs live. |\n| `TEST_GENIE_LLM_PROVIDER` | auto-detect | `anthropic` / `openai` / `none`. |\n| `ANTHROPIC_API_KEY` | — | Used when provider = `anthropic`. |\n| `OPENAI_API_KEY` | — | Used when provider = `openai`. |\n| `TEST_GENIE_ANTHROPIC_MODEL` | `claude-haiku-4-5` | Override Anthropic model. |\n| `TEST_GENIE_OPENAI_MODEL` | `gpt-4o-mini` | Override OpenAI model. |\n\n---\n\n## Migrating from v2.x\n\n- `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'`.\n- Subprocess hardening means platform tools now reject scheme / device / package-name arguments that contain shell metacharacters. If your CI was passing weird-looking values, sanitize them first.\n- See **[CHANGELOG.md](CHANGELOG.md)** for the full breaking-change list + migration recipes.\n\n---\n\n## Roadmap\n\n- LLM-based fix-proposal **voting** (multiple proposals → pick the best by syntax + retest delta)\n- Multi-repo sync (run the loop across N repos in parallel from one MCP call)\n- A \"watch mode\" that runs the loop on file save\n- Better Detox / Maestro artifact ingestion (link videos into iteration logs)\n\n---\n\n## Contributing\n\nIssues, PRs, and ideas welcome — see **[CONTRIBUTING.md](CONTRIBUTING.md)** (TODO). Code lives under `src/`, tests under `tests/`. Run `npm test` before sending a PR.\n\n## Maintainer\n\n[@MUSE-CODE-SPACE](https://github.com/MUSE-CODE-SPACE) — Yoonkyoung Gong.\n\n## License\n\nMIT — see [LICENSE](LICENSE).\n",
  "bytes": 18750,
  "sha": "85812dd0588750417c790cacf06036a4952ce6c44a988d3ac7a39cce37174d77",
  "repo_slug": "muse-code-space/test-genie-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_muse_code_space_test_genie_910faddb/readme"
}