Skip to main content
Glama
README.md
# simplecov-mcp

An MCP server that lets Claude directly access SimpleCov coverage reports.

No need to read the entire `coverage/.resultset.json` (which can be tens of MB). Retrieve only the data you need via tools.

## Setup

```bash
git clone https://github.com/yourname/simplecov-mcp.git
cd simplecov-mcp
pnpm install && pnpm build
```

Then, in your Rails project root, register the MCP server:

```bash
claude mcp add simplecov node /path/to/simplecov-mcp/build/index.js
```

This adds the MCP server to your project's `.mcp.json`. The server automatically detects the `coverage/` directory from the working directory.

To specify the coverage path explicitly:

```bash
claude mcp add simplecov -e SIMPLECOV_COVERAGE_PATH=/path/to/coverage node /path/to/simplecov-mcp/build/index.js
```

After adding, restart Claude Code and verify with `/mcp`.

## Tools

### `get_summary`

Returns the overall coverage summary.

```
> get_summary

{
  "lastRun": { "line": 100, "branch": 100 },
  "totalFiles": 1669,
  "computed": { "lineCoverage": 53.56, "branchCoverage": 48.07 }
}
```

### `list_files`

Lists files with their coverage rates. Supports sorting and filtering.

| Parameter | Type | Default | Description |
|---|---|---|---|
| `sort_by` | `path` \| `line_coverage` \| `branch_coverage` \| `missed_lines` | `path` | Sort key |
| `order` | `asc` \| `desc` | `asc` | Sort order |
| `min_coverage` | number | - | Minimum coverage percentage |
| `max_coverage` | number | - | Maximum coverage percentage |
| `path_pattern` | string | - | Partial match filter for file paths |

```
> list_files sort_by=missed_lines order=desc max_coverage=50

[
  { "file": ".../inquiries_controller.rb", "line": "8.96% (37/413)", "missed": 376 },
  ...
]
```

### `get_file_coverage`

Returns detailed coverage for a specific file, including per-line hit counts, uncovered line numbers, and branch coverage.

| Parameter | Type | Description |
|---|---|---|
| `file_path` | string (required) | File path. Matched by suffix |

```
> get_file_coverage file_path=app/models/user.rb

{
  "filePath": "/usr/src/app/app/models/user.rb",
  "lineCoverage": "85.71% (12/14)",
  "uncoveredLineNumbers": [42, 43],
  "lines": [...],
  "branches": [...]
}
```

### `get_uncovered_lines`

Extracts only uncovered lines and branches. Useful when adding tests.

```
> get_uncovered_lines file_path=app/services/order_service.rb

{
  "filePath": "/usr/src/app/app/services/order_service.rb",
  "lineCoverage": "72.5%",
  "uncoveredLineNumbers": [15, 16, 42, 43, 44],
  "uncoveredBranches": [
    { "condition": "[:if, 3, 15, 6, 15, 40]", "branch": "[:else, 5, 15, 6, 15, 40]" }
  ]
}
```

### `estimate_file_coverage`

Estimates coverage after code changes without re-running tests. Compares the file saved at server startup (baseline) with the current file on disk, and maps old coverage data through a line-level diff.

| Parameter | Type | Description |
|---|---|---|
| `file_path` | string (required) | File path. Matched by suffix |

```
> estimate_file_coverage file_path=app/models/user.rb

{
  "filePath": "/usr/src/app/app/models/user.rb",
  "fileChanged": true,
  "originalCoverage": "85.71% (12/14)",
  "estimatedCoverage": "82.35% (14/17)",
  "changeSummary": { "unchanged": 45, "added": 5, "removed": 2, "modified": 3 },
  "estimatedNewLines": [
    { "line": 15, "type": "modified", "status": "covered", "confidence": "medium" },
    { "line": 22, "type": "added", "status": "likely_covered", "confidence": "low" }
  ],
  "estimatedUncoveredLineNumbers": [30, 42, 43],
  "note": "..."
}
```

**Estimation logic:**

| Line type | Method | Confidence |
|---|---|---|
| unchanged | Uses original coverage as-is | high |
| modified | Inherits original coverage (test likely still reaches the line) | medium |
| added | Estimates from surrounding block coverage | low |

This tool is designed for agentic coding workflows: run tests once, make improvements, estimate coverage impact, and move on.

## Usage Examples with Claude

```
"Show me files with low coverage"
"Show uncovered lines in app/models/user.rb"
"List controllers with coverage below 50%"
"Write tests for the uncovered lines in this file"
"Estimate coverage after my changes to user.rb"
```

## How It Works

```
Rails Project
├── coverage/
│   ├── .resultset.json  ← Generated by SimpleCov (tens of MB)
│   └── .last_run.json   ← Summary
└── .mcp.json            ← MCP configuration (created by claude mcp add)

simplecov-mcp searches for the coverage/ directory starting from cwd,
then walking up to parent directories. It parses .resultset.json and
holds the data in memory. Claude retrieves only the needed portions
via tools.

At startup, the server also reads and caches the source files referenced
in coverage data. This baseline is used by estimate_file_coverage to
detect changes and map coverage through line-level diffs (LCS-based).
```