analyze-coverage-mcp
analyze-coverage-mcp
Documentation
analyze-coverage-mcp
MCP server that bridges LCOV coverage reports to AI agents. It runs locally and gives agents precise, structured visibility into test coverage — which lines are hit, which branches are missed, and where to focus testing efforts.
What is LCOV?
LCOV is a standard text format for code coverage data. It records which lines, functions, and branches were executed during tests. The format is widely supported by test runners (Vitest, Jest, Istanbul, etc.) and is typically written to `lcov.info`. Each record describes coverage for a source file: line hits, branch hits, and function hits.
Tools
| Tool | Description |
|---|---|
| `get_coverage_overview` | Aggregated and per-file coverage stats (lines, functions, branches %). Supports filtering by directory prefix, threshold, and sort order. |
| `list_uncovered_regions` | Uncovered lines (merged into ranges) and uncovered branches for a specific file. |
| `get_annotated_source` | Full source file annotated line-by-line with `[COVERED]`, `[NOT COV]`, or `[NO DATA]`. Supports `start_line`/`end_line` windowing. |
The server also watches `lcov.info` for changes (polling every 1 s) and auto-reloads — so coverage stays current while tests run in watch mode.
Requirements
All MCP tools (`get_coverage_overview`, `list_uncovered_regions`, `get_annotated_source`) require these parameters in every call. They identify which coverage report to load and how to resolve source file paths.
| Parameter | Requirement |
|---|---|
| `lcov_path` | Must be an absolute path. The file must exist on disk. |
| `project_root` | Must be an absolute path. In single projects, use the directory where tests run (same as package root below). In monorepos, you can use the repo root — the MCP derives the package root from `lcov_path`. |
Expected project structure
The directory where tests run (the package root) must have this layout:
/ ← same as project_root in single projects; in monorepos, parent of coverage/ (e.g. apps/app-api)
├── coverage/
│ └── lcov.info
└── src/
└── ...`src/` and `coverage/` must be siblings under the package root. In single projects, pass that directory as `project_root`. In monorepos, `project_root` can be the repo root; the MCP infers the package root from the `lcov_path` location.
If your structure differs, use `source_root` or `additional_roots` (see Path resolution and file locations).
Installation
From npm
Configure MCP
{
"mcpServers": {
"analyze-coverage": {
"command": "npx",
"args": [
"-y",
"@sofia-open-source/analyze-coverage-mcp"
]
}
}
}From source
Build and install
pnpm bundle # generates js bundle in ./analyze-coverage-mcp with shebang node executable
chmod +x ./analyze-coverage-mcp # make it executable
cp ./analyze-coverage-mcp ~/.local/bin/analyze-coverage-mcp # available in $PATHConfigure MCP
{
"mcpServers": {
"analyze-coverage": {
"command": "analyze-coverage-mcp"
}
}
}Development
# Install dependencies
pnpm install
# Run in watch mode (no build needed)
pnpm dev
# Type-check and build
pnpm build
# Run tests
pnpm test
# Run tests with coverage
pnpm test:coverageHow it works
1. The agent calls `get_coverage_overview` with `lcov_path` and `project_root` to load the report.
2. The LCOV file is parsed in-memory into a `Map` and cached.
3. Subsequent tool calls reuse the cache (identified by `lcov_path` + `project_root`) or trigger a reload via `refresh_coverage`.
4. Source paths are resolved with fallbacks: `project_root` + path, common prefix stripping (`src/`, `lib/`, etc.), and when lcov is in `coverage/`, the parent directory is used for monorepos. See Path resolution and file locations.
Generating LCOV reports
The MCP server reads `lcov.info` files. Here’s how to generate them with common test runners:
Vitest
Install the coverage provider:
pnpm add -D @vitest/coverage-v8Configure `vitest.config.ts`:
import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
coverage: {
provider: 'v8',
reporter: ['text', 'lcov'],
reportsDirectory: './coverage',
},
},
})Run tests with coverage:
pnpm vitest run --coverageOutput: `./coverage/lcov.info`
Jest
Install Istanbul (used by Jest for coverage):
pnpm add -D jest @types/jestConfigure `jest.config.js` or `package.json`:
{
"jest": {
"collectCoverage": true,
"coverageReporters": ["text", "lcov"],
"coverageDirectory": "coverage"
}
}Run tests with coverage:
pnpm jest --coverageOutput: `./coverage/lcov.info`
Istanbul / nyc
pnpm add -D nycConfigure `package.json`:
{
"nyc": {
"reporter": ["text", "lcov"],
"report-dir": "coverage"
}
}Run tests with coverage:
pnpm nyc pnpm testOutput: `./coverage/lcov.info` (or `.nyc_output/lcov.info` depending on config)
Other runners
Most runners support LCOV via plugins or built-in options. Ensure the reporter outputs `lcov` and that the path to `lcov.info` is passed as `lcov_path` to the MCP tools.
Inputs
All tools require:
| Field | Type | Description |
|---|---|---|
| `lcov_path` | `string` | Absolute path to the `lcov.info` file generated by your test suite |
| `project_root` | `string` | Absolute path to the root of the project being analysed |
Typical `lcov_path` values:
- Vitest with `@vitest/coverage-v8`: `/coverage/lcov.info`
- Jest with `--coverage`: `/coverage/lcov.info`
- Istanbul/nyc: `/.nyc_output/lcov.info`
Path resolution and file locations
See Requirements for parameter and structure requirements.
How paths work in LCOV
LCOV records store source file paths relative to the package that ran the tests. For example, if tests run from `apps/app-api`, paths look like `src/core/auth/service.ts`, not `apps/app-api/src/core/auth/service.ts`.
Monorepos
In monorepos, `project_root` is often the repo root (e.g. `/repo`), but LCOV paths are relative to the package root (e.g. `apps/app-api`). The MCP handles this automatically:
- When `lcov_path` is inside a `coverage/` directory (e.g. `apps/app-api/coverage/lcov.info`), the parent of that directory is used as a fallback source root.
- So `project_root` can be the monorepo root; source files under `apps/app-api/src/` are still resolved correctly.
Example: `lcov_path: /repo/apps/app-api/coverage/lcov.info` with `project_root: /repo` → sources resolve under `/repo/apps/app-api/`.
Source path resolution order
For `get_annotated_source`, the MCP resolves LCOV paths to filesystem paths in this order:
1. Absolute path — if the LCOV path is already absolute.
2. `source_root` + path — when `source_root` is provided (optional param).
3. `project_root` + path — e.g. `project_root/src/foo.ts`.
4. Stripped prefixes — if the path contains `src/`, `lib/`, `dist/`, or `app/`, tries `project_root` + the path from that segment onward.
5. `additional_roots` — for each root in this optional array, tries `root + path`.
6. Derived from lcov location — when lcov is in `coverage/`, tries the parent directory of `coverage/` as root.
Flexible overrides (`get_annotated_source`)
When the automatic heuristics fail, use these optional parameters:
| Parameter | Description |
|---|---|
| `source_root` | Override root for resolving source files. Tried before `project_root`. Use when you know the package root (e.g. `apps/app-api`). |
| `additional_roots` | Array of extra roots to try. For each, `resolve(root, file_path)` is attempted. Useful when sources live in multiple directories. |
Example: `get_annotated_source` with `source_root: "/repo/apps/app-api"` forces resolution under that directory, ignoring `project_root` for that call.
`file_path` matching
For `list_uncovered_regions` and `get_annotated_source`, `file_path` can be:
- The exact path as it appears in the LCOV report (e.g. `src/core/auth/service.ts`).
- A suffix that uniquely identifies the file (e.g. `auth/service.ts` or `service.ts`).
- A filename if it is unique across the report (e.g. `service.ts`).
Use `get_coverage_overview` to list available paths when unsure.
Restrictions and pitfalls
- Source file must exist on disk for `get_annotated_source`. That tool reads the source to annotate it. If resolution fails: *"Source file not found on disk. Try setting project_root, source_root, or additional_roots to the directory containing your source files."* `list_uncovered_regions` only uses coverage data and does not require the source file.
- Use `source_root` or `additional_roots` when heuristics fail. When the automatic monorepo detection fails, pass `source_root` with the package root (e.g. `apps/app-api`), or use `additional_roots` to add extra search paths.
- Paths are case-sensitive on most systems.
License
MIT
Frequently asked questions
What is analyze-coverage-mcp?
analyze-coverage-mcp is analyze-coverage-mcp
How do I install analyze-coverage-mcp?
Open the GitHub repository and follow its README. Most MCP servers are added to your client's MCP config, then called by your agent.
Is analyze-coverage-mcp open source?
Yes — it is hosted on GitHub at https://github.com/sofia-open-source/analyze-coverage-mcp and has 2 stars.
Related MCP tools
Model Context Protocol Servers
The Open-Source Multimodal AI Agent Stack: Connecting Cutting-Edge AI Models and Agent Infra
A MCP for Claude Desktop / Claude Code / Windsurf / Cursor to build n8n workflows for you
MCP server to provide Figma layout information to AI coding agents like Cursor
The world's best AI personal assistant for email. Open source app to help you reach inbox zero fast.
Instant is the best backend for AI-coded apps. You get auth, permissions, storage, presence, and streams — everything you need to ship apps your users will love.
Run your own MCP server? See who uses it and what to fix.
Measure it with TrackMCP