Skip to content

feat(mcp): expose show_uncovered on the test tool #1705

Description

@jmadren

Description

The MCP test tool cannot ask for uncovered lines, so an agent that hits a coverage
shortfall is told only the percentage and has to go find the missing lines some other way.

On a min_coverage failure the tool result is:

"test" failed with exit code 69.
Command: very_good dart test --coverage --min-coverage 100

Output:
Running "dart test" in . ...
✓ Optimizing tests (0.2s)
00:04 +1: All tests passed!
Expected coverage >= 100.00% but actual is 33.33%.

The CLI already knows exactly which lines are uncovered, and --show-uncovered prints them
(TestCLIRunner.handleMinCoverageNotMet logs formatUncoveredLines(e.uncoveredLines) when
MinCoverageNotMet.uncoveredLines is populated). The MCP test input schema simply has no
key for it. The registered schema (lib/src/mcp/mcp_server.dart, the registerTool block
starting around line 166) exposes:

directory, dart, coverage, recursive, optimization, concurrency, tags,
exclude_coverage, exclude_tags, min_coverage, dart-define, dart-define-from-file,
check_ignore

— but not show_uncovered.

This is the same class of gap as #1675 (paths): the MCP surface is narrower than the CLI
it wraps, and the missing argument happens to be the one that carries the diagnostic detail.
It is also the last piece of #1611 still outstanding — that issue restored command output for
failing tests, and this is the equivalent for failing coverage.

Steps To Reproduce

  1. Create a package with an uncovered function and a test that does not exercise it.
  2. Call the MCP test tool with coverage: true and min_coverage: 100.
  3. Observe the result: a percentage, and no indication of which lines are missing.
  4. Run very_good dart test --coverage --min-coverage 100 --show-uncovered in a shell and
    observe that the information was available all along:
Expected coverage >= 100.00% but actual is 33.33%.
Lines not covered:
	- lib/vgvtest.dart: 4, 5

Expected Behavior

A show_uncovered boolean on the test tool's input schema, appended as --show-uncovered
in _parseTest the same way check_ignore is handled, so the tool result carries the
uncovered lines.

Given that the consumer here is an agent rather than a human watching a terminal, defaulting
it to true for the MCP surface would be defensible — the output is bounded by the number of
uncovered lines, and an agent that has just been told "coverage is too low" will need those
line numbers on its very next step regardless. Happy to follow whichever the team prefers.

Additional Context

There is a working config-level workaround today, which is why this is a papercut rather
than a blocker. argResults.resolve() consults the config file only when the flag was not
explicitly parsed, and the MCP server never sends --show-uncovered, so a very_good.yaml
wins:

test:
  show_uncovered: true

dart:
  test:
    show_uncovered: true

Both sections are needed — very_good test reads the top-level test: block while
very_good dart test (what the MCP sends when dart: true) reads dart: test:. Verified
against 1.4.0: with that file present, the MCP result gains
Lines not covered:\n\t- lib/vgvtest.dart: 4, 5.

Two caveats that make the workaround an imperfect substitute for a schema key:

  • VeryGoodConfig.load walks ancestors innermost-outward and the first file found wins
    outright, with no merging. Any package-level very_good.yaml added later for an unrelated
    setting silently drops show_uncovered for that package, and the symptom — helpful output
    quietly stopping — is hard to trace back.
  • It requires every consuming repo to adopt a config file to get diagnostics out of a tool
    whose whole audience is automated.

Related: #1611 (output discarded — fixed in 1.3.0 by #1612), #1675 (paths on the same
tool), #1615 (structured error responses).

Verified against very_good_cli 1.4.0 on macOS.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

Status
In Progress

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions