TestTrout
MCP server for testing assistance that scans codebases, identifies untested areas, generates and runs tests, and reports results.
README
<div align="center">
<img src="assets/trout-256.png" alt="" width="112" height="112">
TestTrout
The testing assistant for AI-built apps.
Run it as an app, or hand it to your coding agent over MCP. Either way it writes the tests your app never had, and tells you when they break.
</div>
Trout are an indicator species. They only live in clean, well-oxygenated water — find one in a stream and you know the water is healthy without testing it yourself.
That is what a good test suite is: not a chore, but a signal you can read at a glance.
The problem
Coding agents ship fast. They also break things quietly, and the apps they build — Lovable, v0, Bolt, hand-rolled React on Vercel — almost never have tests. So the loop ends with "looks good to me" from the thing that just wrote the code.
TestTrout closes that loop. It reads the repository, connects to the running deployment, works out what is untested and in what order it matters, writes real tests, runs them, and reports results you can actually act on.
Get it running
pip install testtrout
trout up
That starts everything: storage, a background worker, and the interface at
localhost:7411. No Docker, no daemon, no database to install — storage is SQLite
under ~/.testtrout and the worker runs in-process.
Then link a repository, from the interface or the terminal:
trout link ~/code/my-app # a folder you already have
trout link --github owner/name # cloned with your GitHub token
Linking a local folder never modifies it. A scan starts automatically, and the Setup tab has every setting: deployments, Supabase, test accounts, model provider.
Two things make that safe and useful:
It tells you what credentials your app needs, discovered by reading your source — which variables it reaches for, what each is likely for, and the line it appears on. No re-deriving something the code already states.
A partial set gives a partial suite. With only a URL you can probe and run API tests; add an anon key and a second account and authorization tests become possible. Each blocked capability names the single next thing it needs, never "configure it properly".
Secret values are written to a gitignored .env; committed configuration holds only
env:NAME references, and a literal secret typed into a config field is rejected.
Or stay in your coding agent
The app is one way in, not the only one. Everything it does is available as typed MCP tools and as CLI commands, so anyone who would rather not leave their editor does not have to:
pip install 'testtrout[mcp]'
trout mcp /path/to/your/project
Point your agent at the skill in .claude/skills/, or tell it:
Use the TestTrout MCP server. Scan the repo, show me what's untested ranked by importance, draft tests for the top five, and run them.
Thirteen tools, bound to one project so an agent cannot act on the wrong repository:
scan surfaces |
Understand the codebase. No API key, no network. |
probe |
See what the deployed app actually does, in a real browser. |
intent gaps |
Rank what is untested, and say why. |
propose approve generate |
Draft, review, compile to real test files. |
run certify report |
Execute, prove determinism, read evidence. |
doctor |
What is missing, and how to fix it. |
Plus trout://surfaces, trout://intent, trout://config, trout://scenarios as
resources, so bulk state never crowds out an agent's context window.
What it understands
trout scan is fully deterministic — no model, no network, safe on a repo you just
cloned. On a typical Supabase app it finds:
| Surface | Example |
|---|---|
| Screens | /orders/:id → OrderDetail, and the data it reaches |
| Data operations | supabase.from('orders').delete().eq('id', …) |
| RLS policies | Users manage own orders — a testable authorization claim |
| Server actions | 'use server' functions — endpoints that look like helpers |
| Route handlers | app/api/checkout/route.ts → POST |
| Third parties | Stripe, Resend — the substitution boundary |
| Schema | Tables, columns, foreign keys, RLS status |
It also tells you when a table is written from browser code with no row-level security — meaning it is world-writable through the anon key. That is usually news.
Why the tests are worth trusting
It builds a baseline, not per-PR guesses. A test derived from the code you just changed asserts the new behaviour is correct by construction — it cannot catch a regression. TestTrout certifies a suite against a working deployment first, so a failure means something.
Deterministic core, model at the edges. Scanning, ranking, execution, and failure classification never call a model. The model only interprets your intent, refines wording, and picks which observed elements to assert on. Every ranking is the sum of named contributions:
critical authorization A user cannot read another user's rows in payments 100
· critical surface
· policy: exists (select 1 from orders o where o.id = payments.order_id …)
Every assertion carries its provenance. derived from a policy, observed in a
real browser, or inferred by a model — and inferred alone can never block anything.
A failure is classified before it is reported. Only assertion_failure is a product
signal. Auth failures, unreachable databases, and blocked third-party calls are about
the harness, and an inconclusive run is never upgraded to a pass.
Everything from the terminal
trout scan # understand the code
trout init # connect a deployment
trout gaps # what's missing, ranked, with reasons
trout run # execute, with evidence behind every result
Every command supports --json. Full walkthrough in docs/setup.md.
How it stores things
Your test suite stays in your repository, committed and reviewable:
.trout/scenarios/*.yaml what each test asserts, in plain language
.trout/config.yaml deployments and env: references, never secrets
tests/trout/ generated Playwright and Vitest files
Run history, coverage over time, and the job queue live in SQLite under
~/.testtrout. That split is deliberate: the suite belongs next to the code where a
pull request can review it, and the questions files cannot answer — is this test
getting flakier, is coverage going up — belong in a database.
Optional web view
trout web
Coverage at a glance, the ranked gap list, scenario review, run history with evidence,
live log. Same .trout/ files as the CLI — no database, nothing hosted, loopback only.
Entirely optional; the CLI and MCP are complete on their own.
Safety
The tool needs your database credentials and can drive your deployment, so the guarantees are enforced in code rather than documented:
- Production is read-only by default. Mutating requests are blocked at the network
layer unless an entrypoint is explicitly marked
disposable. The guard sits below navigation, because "just loading a page is read-only" is false — plenty of these apps write on mount. No agent, and no web click, can change that setting. - Third parties are intercepted. A test run cannot charge a card or email a customer. Unmatched outbound requests fail loudly; a mock that silently matches nothing is how a suite reports green while testing nothing.
- Secrets stay out of committed files.
.trout/config.yamlholdsenv:references only. Values live in a gitignored.env. - Nothing is hosted. Nothing leaves your machine except calls to the model provider you chose. No telemetry.
Model providers
Anthropic, OpenAI, or Kimi — or any OpenAI-compatible endpoint via base_url.
model:
provider: anthropic
api_key: env:ANTHROPIC_API_KEY
Analysis never calls a model, so trout scan, trout gaps, and trout run all work
with no key at all.
Supported stacks
React + Vite (Lovable, v0, Bolt) and Next.js App Router, in TypeScript, with Supabase, deployed anywhere reachable over HTTP. Auth via Supabase, Clerk, or NextAuth.
Deliberately narrow. Depth on one stack beats shallow coverage of many — and these codebases are regular enough that static analysis is genuinely accurate on them. Other stacks are an adapter away: see docs/adapters.md.
Roadmap
| ✅ | Repository analysis, deployment probing, gap ranking |
| ✅ | Scenario authoring, generation, execution, certification |
| ✅ | MCP server, CLI, and a local app with storage and a worker |
| ✅ | Change-based test selection, base-branch differential |
| ✅ | Multi-repository: link local folders or clone with a GitHub token |
| ✅ | Full configuration from the interface or the CLI, with credential discovery |
| 🔜 | GitHub pull-request checks |
| 🔜 | Observed coverage index (today's selection uses declared coverage) |
Contributing
Adding a framework, auth provider, or test runner means implementing one protocol and registering an entry point — no fork required. See CONTRIBUTING.md and docs/adapters.md.
The full test suite runs offline with no API key. That is deliberate and worth keeping.
License
Apache 2.0
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。