trackmcp
Back to directory
sofia-open-source

analyze-coverage-mcp

View on GitHub

analyze-coverage-mcp

2 stars TypeScriptOthers Updated Apr 17, 2026

Documentation

analyze-coverage-mcp

MCP Server
NPM Version
codecov
License: MIT

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

ToolDescription
`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.

ParameterRequirement
`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:

code
/          ← 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

json
{
  "mcpServers": {
    "analyze-coverage": {
      "command": "npx",
      "args": [
        "-y",
        "@sofia-open-source/analyze-coverage-mcp"
      ]
    }
  }
}

From source

Build and install

bash
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 $PATH

Configure MCP

json
{
  "mcpServers": {
    "analyze-coverage": {
      "command": "analyze-coverage-mcp"
    }
  }
}

Development

bash
# 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:coverage

How 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:

bash
pnpm add -D @vitest/coverage-v8

Configure `vitest.config.ts`:

ts
import { defineConfig } from 'vitest/config'

export default defineConfig({
  test: {
    coverage: {
      provider: 'v8',
      reporter: ['text', 'lcov'],
      reportsDirectory: './coverage',
    },
  },
})

Run tests with coverage:

bash
pnpm vitest run --coverage

Output: `./coverage/lcov.info`

Jest

Install Istanbul (used by Jest for coverage):

bash
pnpm add -D jest @types/jest

Configure `jest.config.js` or `package.json`:

json
{
  "jest": {
    "collectCoverage": true,
    "coverageReporters": ["text", "lcov"],
    "coverageDirectory": "coverage"
  }
}

Run tests with coverage:

bash
pnpm jest --coverage

Output: `./coverage/lcov.info`

Istanbul / nyc

bash
pnpm add -D nyc

Configure `package.json`:

json
{
  "nyc": {
    "reporter": ["text", "lcov"],
    "report-dir": "coverage"
  }
}

Run tests with coverage:

bash
pnpm nyc pnpm test

Output: `./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:

FieldTypeDescription
`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:

ParameterDescription
`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

Run your own MCP server? See who uses it and what to fix.

Measure it with TrackMCP