Ten read-only tools over per-function CRAP scores: complexity times uncovered risk, churn-ranked.
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.

crapkit scores every function in your repo on complexity times uncovered risk, ranks the worst ones by how often the file changes, and blocks commits that add more. It reads Python, TypeScript, TSX, JavaScript, Swift, Go, Rust, shell, PowerShell, C and C++, Objective-C, Vue, Java and Zig through lizard, and joins per-function branch coverage from the istanbul or coverage.py artifact your own test command already writes. JSON commands use sorted keys and a versioned schema for scripts, coding agents and the optional MCP server.
The name is not ours: C.R.A.P. (Change Risk Anti-Patterns) was coined for crap4j by Alberto Savoia and Bob Evans in 2007.
ccn is the smaller of standard and modified cyclomatic complexity, both read off one
lizard pass. cov is branch coverage inside the function's span; with no branches it
falls back to statement coverage, and with no statements to invoked-or-not, so a
half-executed straight-line function never reads as fully covered.
Above the ceiling, coverage cannot save you. Decompose. At the default target of 6, a function at ccn 7 with 100% coverage still scores 7 and still fails the gate. The only move that clears it is splitting the function.
Why 6 and not 30. crap4j's conventional threshold of 30 is a CRAP score: it lets an
untested ccn 5 through (25 + 5 = 30) and a fully covered ccn 30 too. crapkit's default
is a complexity ceiling, because coverage can at best collapse CRAP to ccn, and a
function you cannot cover past ccn 6 is one you decompose. Set target = 30 in
crapkit.toml if you want the crap4j number. A repo with existing debt does not need to:
ratchet seed marks today's over-ceiling functions at today's score, the gate then judges
only the functions a change touches, and marks may only fall, so adoption never starts with
a wall of red. Next to crap4py, radon, xenon, wily and SonarQube:
docs/comparison.md.
crapkit scores git-tracked files only. Source you have not git added is invisible to
it.
| Start with | When |
|---|---|
| Install and the 60-second start | You want the first score in an existing Git repository. |
| Python or TypeScript quickstart | You want a worked example from setup through a passing verify. |
| Adoption | You need to choose scopes, wire tests or introduce a ratchet to existing debt. |
| Upgrading | You already have saved runs, ratchet marks or an installed plugin. |
| Subcommands and JSON/MCP reference | You are scripting commands or connecting a coding agent. |
init detects pytest, Vitest and Jest from the repository's own files. Review the
generated config before running its commands. When detection leaves a commented
lane, fill it in using the lane recipes.
Commit the adoption files, then run crapkit verify to establish a passing verdict.
Install the commit gate when the config and ratchet are ready.
coverage scores, worklist ranks:
risk 14.0 is ccn times a churn weight of one: a one-commit repo has no spread of commits
to weight, so each commit counts once and the ranking is complexity order until the
history grows (Risk). crap 38.5 and cov 50% are the
score and the coverage behind it.
ratchet seed signs today's debt at today's score. From then on marks only ever fall, so
the repo can get better and never worse while you burn it down.
One thing stops most first runs: the coverage plugin. init writes a lane that shells
out to your own test runner, and the runner needs its coverage package installed:
pytest-cov for pytest, @vitest/coverage-v8 (pinned to your vitest major) for vitest.
Without it the lane produces no artifact and coverage exits 5 quoting the runner's own
error. For pytest, init probes the python its lane will run and prints the install
command when pytest_cov is missing; pip install "crapkit[py]" pulls the plugin
alongside crapkit when the two share a venv. On a Windows PATH holding only the py
launcher it writes py, not a python3 the lane could never run, and when cmd.exe cannot
start the interpreter at all (exit 9009, the Store alias) it names that instead of guessing
at pytest-cov. A repo that pins no lockfile and carries its own .venv gets that venv's
interpreter in the lane, when that interpreter can import pytest, rather than whichever
python the shell answers with. The two quickstarts below walk a real repo end to end.
On Windows a lane command is read by cmd.exe, the shell that will run it, not by sh. Double quotes are the portable quoting. A single-quoted value is refused at config load with exit 3, because cmd.exe would hand pytest five words and the lane would write no artifact:
Write it -m "not live and not perf". Carets, && and | segments, redirections and
empty quoted arguments all read the way the shell reads them, so a chained lane
(cd tests && python -m pytest --cov ...) is checked one segment at a time. doctor reads
a lane the same way, and FAILs one whose runner will not start.
That is the release on PyPI. For the unreleased tip
of main, or from a local clone (run at the clone root):
Requires Python 3.11 or newer and Git on PATH. The CLI has one runtime dependency,
lizard>=1.24.0; a package mirror needs both distributions. Install into the environment
you intend to use, then check crapkit --version. The pip install -e ".[dev]" under
Development is a different thing: it adds the test extra, for people
changing crapkit.
Python projects can install pip install "crapkit[py]" in their test environment to
include pytest-cov and subprocess-capable coverage.py. A separate tool installation
still needs the coverage plugin in the environment that runs the suite.
Analysis and scoring run locally and send no telemetry. Configured lane, mutation and alert commands run with your permissions and can contact services or change files. Review those commands before running Crapkit in a repository you do not trust (SECURITY.md).
python -m crapkit works identically to the console script and is what to use from a
source checkout. Every subcommand accepts --repo PATH (default: the nearest crapkit.toml
at or above the current directory, so a monorepo workspace finds the root's), and with it
you never have to cd into the repo you are scoring; Subcommands shows
where the flag goes.
Factual signals from GitHub, npm, and our automated checks β not a rating.
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/crapkit)<a href="https://allmcps.com/mcp/crapkit"><img src="https://allmcps.com/api/badge/crapkit?style=directory" alt="Crapkit on AllMCPs" /></a>