test-trust
MCP server that performs mutation testing and diff scoping to score how trustworthy tests are for detecting regressions in changed code.
README
test-trust
Tells AI coding agents (Claude Code, Codex, OpenHands, Cursor, or a local model — agent-agnostic via MCP, the Model Context Protocol) not just which tests cover a change, but whether those tests can actually be trusted to catch a regression there.
"CI is green" and "this change is safe" are treated as the same thing by every agent today. They aren't. A test that covers a function isn't the same as a test that would actually fail if that function broke — over-mocked tests, snapshot tests that just re-record whatever the new output is, and assertion-free tests all show green while catching nothing.
How
- Mutation testing (wraps mature existing engines, not reimplemented — mutmut for Python, StrykerJS for JS/TS, gremlins for Go, cargo-mutants for Rust): deliberately introduce small bugs into the changed code, check whether the covering tests actually fail. Test selection per mutant comes from each engine's own coverage data, not reimplemented here — mutmut and Stryker (where a supported runner: jest/mocha/vitest) select only the specific tests that cover each mutant; gremlins and cargo-mutants skip mutants with zero coverage but re-run the full relevant test suite for every mutant that has any, a coarser (and slower on large repos) but still correct mechanism.
- Diff scoping (ours): maps a git diff's changed lines to the enclosing function via each language's own parsing, so both the mutation run and the trust score are scoped to what actually changed, not a whole file/repo.
- Fusion (the new part, not built anywhere else — verified): combine the above into one trust score per changed function, exposed as an MCP tool any agent can call before treating a green test run as evidence of safety.
See examples/weak-test-fixture/ (Python), examples/weak-test-fixture-js/
(JS), examples/weak-test-fixture-go/ (Go), examples/weak-test-fixture-rust/
(Rust), examples/plug-and-play-fixture/ (zero config at all), and
examples/multi-file-fixture-js/ (a function that imports a sibling module,
proving mutation-scoping doesn't break cross-file imports) for working, live
demonstrations: a function covered by a test that passes today but wouldn't
catch a real bug.
Validated against real repos, not just fixtures
Every fixture above is a toy. Before trusting the concept, this was also run
zero-config against real, external, unmodified repositories in all four
languages: psf/requests (Python, 37 real functions scored, e.g.
resolve_proxies correctly flagged at trust 0.0 — genuinely zero tests
reference it), kind-of (JS, ~50M weekly downloads, isArray and
isRegexp flagged despite all 36 tests passing), dustin/go-humanize (Go),
and chronotope/humantime (Rust, a genuine multi-module crate — confirms
mutation-scoping doesn't break on real cross-module code, not just our own
fixture). That process caught and fixed several real bugs in three of the
four — including one where a failed mutation run was silently reported as a
false 100% trust score, and a scaling bug where a request scoped to one file
silently mutated an entire real package instead. Rust's real-repo check
didn't surface a new bug, consistent with cargo-mutants -f being the
cleanest, most directly-supported scoping mechanism of the four. See
docs/architecture.md for the full account.
External tools this wraps (install once, per language you use)
- Python:
mutmut— installed automatically as a dependency of this project. - JS/TS:
@stryker-mutator/core— fetched automatically vianpxon first use. - Go:
gremlins—go install github.com/go-gremlins/gremlins/cmd/gremlins@latest - Rust:
cargo-mutants—cargo install cargo-mutants
Try it
Not yet published to PyPI. Every command below assumes a local clone of
this repo, run from inside it (uv run --directory <path> ... from outside
it, as in the agent-embedding example further down). Once published, all of
that collapses to a plain pip install test-trust / uvx test-trust, runnable
from anywhere — no clone, no path to remember, no uv run --directory. That
single change is the last step between "works, with setup" and "actually
easy to adopt"; nothing about how the tool behaves changes, only how you get
it.
Requires Python 3.11+ and uv. Per-language
mutation engines (see above) are only needed for the languages you actually
use — the Python example below needs nothing beyond uv sync.
uv sync
uv run test-trust check examples/plug-and-play-fixture inventory.py
No setup file, no manual mutation-testing run — this one command auto-detects the language, auto-writes config, auto-runs mutation testing scoped to that file using the repo's own real test command, and prints the trust score.
To run against a different file or repo:
uv run test-trust check <path-to-repo> <source-file> [--changed-file F] [--base-ref REF] [--threshold T]
Changing the threshold (default 0.5) — what counts as adequately
tested. Raise it (e.g. 0.8) to flag anything short of near-total mutation
coverage; lower it to only flag the worst gaps. Same parameter, three
surfaces:
- CLI:
--threshold 0.8, as shown above. - MCP tool:
thresholdis aget_test_trustargument, e.g.get_test_trust(repo_path=..., source_file=..., threshold=0.8). You don't call this yourself — the agent does — so setting it means telling the agent to (in your prompt, or as a standing instruction inCLAUDE.md: "call get_test_trust with threshold=0.8"). Left unset, it uses0.5. - GitHub Action: the
low-trust-thresholdinput in your workflow file:- uses: ./.github/actions/test-trust-pr with: github-token: ${{ secrets.GITHUB_TOKEN }} low-trust-threshold: "0.8"
Embed it in an agent
One-time setup, registered globally rather than per-project — since
repo_path is a parameter on every call rather than fixed at startup, one
registration serves every project you open afterward, not just the one it
was set up in. For Claude Code, add to ~/.claude.json (user-level, not a
project's .mcp.json):
{
"mcpServers": {
"test-trust": {
"command": "uv",
"args": ["run", "--directory", "/absolute/path/to/test-trust", "test-trust", "mcp"]
}
}
}
Same command/args shape works for Codex, Cursor, or any other MCP
client — see docs/embedding.md for those and for what changes once this
is published to PyPI (uvx test-trust mcp, no local path needed at all).
After that it's invisible day to day: the agent calls get_test_trust
itself, mid-task, the same way it already calls its file-read or bash
tools — you don't call it directly.
Or run it on every PR, no agent required
.github/actions/test-trust-pr scores every changed, supported file in a PR
and posts (or updates, on later pushes) one comment — flags any function
whose existing tests wouldn't actually catch a regression there. Useful to
any team doing code review, whether or not anyone's using an AI agent.
.github/workflows/test-trust.yml is the working example; verified end to
end (diff detection, scoring, both the "all clear" and "flagged" comment
renderings) against real commits in a real repo — only the live GitHub API
call itself is untested, since that needs an actual PR to verify against.
Developing
uv sync
uv run pytest tests/ # this project's own unit test suite
uv run test-trust check <repo> <file> # exercise it against real code
tests/ covers the deterministic logic (diff scoping, trust-score
aggregation, language auto-detection, each mutation engine's report
adapter) with crafted fixtures — fast, no external mutation-testing tools
required, and this suite is what actually runs in CI
(.github/workflows/ci.yml). It doesn't replace the real-repo validation
above — that was a manual, one-time exercise done during development (real
external clones, real engines installed), not something CI re-runs on every
push. Worth automating later; not done yet.
MIT licensed.
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.