simplecov-mcp 0.3.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +21 -0
  3. data/README.md +173 -356
  4. data/docs/ADVANCED_USAGE.md +967 -0
  5. data/docs/ARCHITECTURE.md +79 -0
  6. data/docs/BRANCH_ONLY_COVERAGE.md +81 -0
  7. data/docs/CLI_USAGE.md +637 -0
  8. data/docs/DEVELOPMENT.md +82 -0
  9. data/docs/ERROR_HANDLING.md +93 -0
  10. data/docs/EXAMPLES.md +430 -0
  11. data/docs/INSTALLATION.md +352 -0
  12. data/docs/LIBRARY_API.md +635 -0
  13. data/docs/MCP_INTEGRATION.md +488 -0
  14. data/docs/TROUBLESHOOTING.md +276 -0
  15. data/docs/arch-decisions/001-x-arch-decision.md +93 -0
  16. data/docs/arch-decisions/002-x-arch-decision.md +157 -0
  17. data/docs/arch-decisions/003-x-arch-decision.md +163 -0
  18. data/docs/arch-decisions/004-x-arch-decision.md +199 -0
  19. data/docs/arch-decisions/005-x-arch-decision.md +187 -0
  20. data/docs/arch-decisions/README.md +60 -0
  21. data/docs/presentations/simplecov-mcp-presentation.md +249 -0
  22. data/exe/simplecov-mcp +4 -4
  23. data/lib/simplecov_mcp/app_context.rb +26 -0
  24. data/lib/simplecov_mcp/base_tool.rb +74 -0
  25. data/lib/simplecov_mcp/cli.rb +234 -0
  26. data/lib/simplecov_mcp/cli_config.rb +56 -0
  27. data/lib/simplecov_mcp/commands/base_command.rb +78 -0
  28. data/lib/simplecov_mcp/commands/command_factory.rb +39 -0
  29. data/lib/simplecov_mcp/commands/detailed_command.rb +24 -0
  30. data/lib/simplecov_mcp/commands/list_command.rb +13 -0
  31. data/lib/simplecov_mcp/commands/raw_command.rb +22 -0
  32. data/lib/simplecov_mcp/commands/summary_command.rb +24 -0
  33. data/lib/simplecov_mcp/commands/uncovered_command.rb +26 -0
  34. data/lib/simplecov_mcp/commands/version_command.rb +18 -0
  35. data/lib/simplecov_mcp/constants.rb +22 -0
  36. data/lib/simplecov_mcp/error_handler.rb +124 -0
  37. data/lib/simplecov_mcp/error_handler_factory.rb +31 -0
  38. data/lib/simplecov_mcp/errors.rb +179 -0
  39. data/lib/simplecov_mcp/formatters/source_formatter.rb +148 -0
  40. data/lib/simplecov_mcp/mcp_server.rb +40 -0
  41. data/lib/simplecov_mcp/mode_detector.rb +55 -0
  42. data/lib/simplecov_mcp/model.rb +300 -0
  43. data/lib/simplecov_mcp/option_normalizers.rb +92 -0
  44. data/lib/simplecov_mcp/option_parser_builder.rb +134 -0
  45. data/lib/simplecov_mcp/option_parsers/env_options_parser.rb +50 -0
  46. data/lib/simplecov_mcp/option_parsers/error_helper.rb +109 -0
  47. data/lib/simplecov_mcp/path_relativizer.rb +61 -0
  48. data/lib/simplecov_mcp/presenters/base_coverage_presenter.rb +44 -0
  49. data/lib/simplecov_mcp/presenters/coverage_detailed_presenter.rb +16 -0
  50. data/lib/simplecov_mcp/presenters/coverage_raw_presenter.rb +16 -0
  51. data/lib/simplecov_mcp/presenters/coverage_summary_presenter.rb +16 -0
  52. data/lib/simplecov_mcp/presenters/coverage_uncovered_presenter.rb +16 -0
  53. data/lib/simplecov_mcp/presenters/project_coverage_presenter.rb +52 -0
  54. data/lib/simplecov_mcp/resolvers/coverage_line_resolver.rb +126 -0
  55. data/lib/simplecov_mcp/resolvers/resolver_factory.rb +28 -0
  56. data/lib/simplecov_mcp/resolvers/resultset_path_resolver.rb +78 -0
  57. data/lib/simplecov_mcp/resultset_loader.rb +136 -0
  58. data/lib/simplecov_mcp/staleness_checker.rb +243 -0
  59. data/lib/{simple_cov_mcp → simplecov_mcp}/tools/all_files_coverage_tool.rb +31 -13
  60. data/lib/{simple_cov_mcp → simplecov_mcp}/tools/coverage_detailed_tool.rb +7 -7
  61. data/lib/{simple_cov_mcp → simplecov_mcp}/tools/coverage_raw_tool.rb +7 -7
  62. data/lib/{simple_cov_mcp → simplecov_mcp}/tools/coverage_summary_tool.rb +7 -7
  63. data/lib/simplecov_mcp/tools/coverage_table_tool.rb +90 -0
  64. data/lib/{simple_cov_mcp → simplecov_mcp}/tools/help_tool.rb +13 -4
  65. data/lib/{simple_cov_mcp → simplecov_mcp}/tools/uncovered_lines_tool.rb +7 -7
  66. data/lib/{simple_cov_mcp → simplecov_mcp}/tools/version_tool.rb +11 -3
  67. data/lib/simplecov_mcp/util.rb +82 -0
  68. data/lib/{simple_cov_mcp → simplecov_mcp}/version.rb +1 -1
  69. data/lib/simplecov_mcp.rb +144 -2
  70. data/spec/MCP_INTEGRATION_TESTS_README.md +111 -0
  71. data/spec/TIMESTAMPS.md +48 -0
  72. data/spec/all_files_coverage_tool_spec.rb +29 -25
  73. data/spec/base_tool_spec.rb +11 -10
  74. data/spec/cli/show_default_report_spec.rb +33 -0
  75. data/spec/cli_config_spec.rb +137 -0
  76. data/spec/cli_enumerated_options_spec.rb +68 -0
  77. data/spec/cli_error_spec.rb +105 -47
  78. data/spec/cli_source_spec.rb +82 -23
  79. data/spec/cli_spec.rb +140 -5
  80. data/spec/cli_success_predicate_spec.rb +141 -0
  81. data/spec/cli_table_spec.rb +1 -1
  82. data/spec/cli_usage_spec.rb +10 -26
  83. data/spec/commands/base_command_spec.rb +187 -0
  84. data/spec/commands/command_factory_spec.rb +72 -0
  85. data/spec/commands/detailed_command_spec.rb +48 -0
  86. data/spec/commands/raw_command_spec.rb +46 -0
  87. data/spec/commands/summary_command_spec.rb +47 -0
  88. data/spec/commands/uncovered_command_spec.rb +49 -0
  89. data/spec/constants_spec.rb +61 -0
  90. data/spec/coverage_table_tool_spec.rb +17 -33
  91. data/spec/error_handler_spec.rb +22 -13
  92. data/spec/error_mode_spec.rb +143 -0
  93. data/spec/errors_edge_cases_spec.rb +239 -0
  94. data/spec/errors_stale_spec.rb +2 -2
  95. data/spec/file_based_mcp_tools_spec.rb +99 -0
  96. data/spec/fixtures/project1/lib/bar.rb +0 -1
  97. data/spec/fixtures/project1/lib/foo.rb +0 -1
  98. data/spec/help_tool_spec.rb +11 -17
  99. data/spec/integration_spec.rb +845 -0
  100. data/spec/logging_fallback_spec.rb +128 -0
  101. data/spec/mcp_logging_spec.rb +44 -0
  102. data/spec/mcp_server_integration_spec.rb +23 -0
  103. data/spec/mcp_server_spec.rb +15 -4
  104. data/spec/mode_detector_spec.rb +148 -0
  105. data/spec/model_error_handling_spec.rb +210 -0
  106. data/spec/model_staleness_spec.rb +40 -10
  107. data/spec/option_normalizers_spec.rb +204 -0
  108. data/spec/option_parsers/env_options_parser_spec.rb +233 -0
  109. data/spec/option_parsers/error_helper_spec.rb +222 -0
  110. data/spec/path_relativizer_spec.rb +83 -0
  111. data/spec/presenters/coverage_detailed_presenter_spec.rb +19 -0
  112. data/spec/presenters/coverage_raw_presenter_spec.rb +15 -0
  113. data/spec/presenters/coverage_summary_presenter_spec.rb +15 -0
  114. data/spec/presenters/coverage_uncovered_presenter_spec.rb +16 -0
  115. data/spec/presenters/project_coverage_presenter_spec.rb +86 -0
  116. data/spec/resolvers/coverage_line_resolver_spec.rb +57 -0
  117. data/spec/resolvers/resolver_factory_spec.rb +61 -0
  118. data/spec/resolvers/resultset_path_resolver_spec.rb +55 -0
  119. data/spec/resultset_loader_spec.rb +167 -0
  120. data/spec/shared_examples/README.md +115 -0
  121. data/spec/shared_examples/coverage_presenter_examples.rb +66 -0
  122. data/spec/shared_examples/file_based_mcp_tools.rb +174 -0
  123. data/spec/shared_examples/mcp_tool_text_json_response.rb +16 -0
  124. data/spec/simple_cov_mcp_module_spec.rb +16 -0
  125. data/spec/simplecov_mcp_model_spec.rb +340 -9
  126. data/spec/simplecov_mcp_opts_spec.rb +182 -0
  127. data/spec/spec_helper.rb +147 -4
  128. data/spec/staleness_checker_spec.rb +373 -0
  129. data/spec/staleness_more_spec.rb +16 -13
  130. data/spec/support/mcp_runner.rb +64 -0
  131. data/spec/tools_error_handling_spec.rb +144 -0
  132. data/spec/util_spec.rb +109 -34
  133. data/spec/version_spec.rb +117 -9
  134. data/spec/version_tool_spec.rb +131 -10
  135. metadata +120 -63
  136. data/lib/simple_cov/mcp.rb +0 -9
  137. data/lib/simple_cov_mcp/base_tool.rb +0 -70
  138. data/lib/simple_cov_mcp/cli.rb +0 -390
  139. data/lib/simple_cov_mcp/error_handler.rb +0 -131
  140. data/lib/simple_cov_mcp/error_handler_factory.rb +0 -38
  141. data/lib/simple_cov_mcp/errors.rb +0 -176
  142. data/lib/simple_cov_mcp/mcp_server.rb +0 -30
  143. data/lib/simple_cov_mcp/model.rb +0 -104
  144. data/lib/simple_cov_mcp/staleness_checker.rb +0 -125
  145. data/lib/simple_cov_mcp/tools/coverage_table_tool.rb +0 -61
  146. data/lib/simple_cov_mcp/util.rb +0 -122
  147. data/lib/simple_cov_mcp.rb +0 -102
  148. data/spec/coverage_detailed_tool_spec.rb +0 -36
  149. data/spec/coverage_raw_tool_spec.rb +0 -32
  150. data/spec/coverage_summary_tool_spec.rb +0 -39
  151. data/spec/legacy_shim_spec.rb +0 -13
  152. data/spec/uncovered_lines_tool_spec.rb +0 -33
data/README.md CHANGED
@@ -1,455 +1,272 @@
1
1
  # simplecov-mcp
2
2
 
3
- MCP server + CLI for inspecting SimpleCov coverage data.
3
+ > MCP server + CLI + Ruby library for inspecting SimpleCov coverage data
4
4
 
5
- This gem provides:
5
+ [![Gem Version](https://badge.fury.io/rb/simplecov-mcp.svg)](https://badge.fury.io/rb/simplecov-mcp)
6
6
 
7
- - An MCP (Model Context Protocol) server exposing tools to query coverage for files.
8
- - A flexible CLI with subcommands to list all files, show a file summary, print raw coverage arrays, list uncovered lines, and display detailed per-line hits. Supports JSON output, displaying annotated source code (full file or uncovered lines with context), and custom resultset locations.
7
+ ## What is simplecov-mcp?
9
8
 
10
- ## Features
9
+ **simplecov-mcp** makes SimpleCov coverage data queryable and actionable through three interfaces:
11
10
 
12
- - MCP server tools for coverage queries: raw, summary, uncovered, detailed, all-files list, and version.
13
- - Per-file staleness flag in list outputs to highlight files newer than coverage or with line-count mismatches (shown as a compact '!' column in the CLI).
14
- - CLI subcommands: `list`, `summary`, `raw`, `uncovered`, `detailed`, `version` (default `list`).
15
- - JSON output with `--json` for machine use; human-readable tables/rows by default.
16
- - Annotated source snippets with `--source[=full|uncovered]` and `--source-context N`; optional colors with `--color/--no-color`.
17
- - Flexible resultset location: `--resultset PATH` or `SIMPLECOV_RESULTSET`; accepts file or directory; sensible default search order.
18
- - Works installed as a gem, via Bundler (`bundle exec`), or directly from this repo’s `exe/` (symlink-safe).
11
+ - **MCP server** - Let AI assistants analyze your coverage
12
+ - **CLI** - Fast command-line coverage reports and queries
13
+ - **Ruby library** - Programmatic API for custom tooling
19
14
 
20
- ## SimpleCov Independence
15
+ Works with any SimpleCov-generated `.resultset.json` file—no runtime dependency on your test suite.
21
16
 
22
- This codebase does not require, and is not connected to, the `simplecov` library at runtime. Its only interaction is reading the JSON resultset file that SimpleCov generates (`.resultset.json`). As long as that file exists in your project (in a default or specified location), the CLI and MCP server can operate without `require "simplecov"` in your app or test process.
17
+ ### Key capabilities
23
18
 
24
- ## Installation
19
+ - Flexible path resolution (absolute or relative paths)
20
+ - Staleness detection (identifies outdated coverage files)
21
+ - Multi-suite resultset merging when needed
22
+ - Multiple useful output formats (tables, JSON, annotated source)
25
23
 
26
- Add to your Gemfile or install directly:
24
+ ### Practical use cases
25
+
26
+ - Query coverage data from AI assistants, e.g.:
27
+ - "Using simplecov-mcp, analyze test coverage data and write a report to a markdown file containing a free text analysis of each issue and then two tables, one sorted in descending order of urgency, the other in ascending order of level of effort."
28
+ - "Using simplecov-mcp, generate a table of directories and their average coverage rates, in ascending order of coverage."
29
+ - Find files with the lowest coverage
30
+ - Investigate specific files or directories
31
+ - Generate CI/CD coverage reports
32
+
33
+ ## Quick Start
34
+
35
+ ### Installation
27
36
 
28
37
  ```sh
29
38
  gem install simplecov-mcp
30
39
  ```
31
40
 
32
- Require path is `simple_cov_mcp` (also `simplecov_mcp`). Legacy `simple_cov/mcp` is supported via shim. Executable is `simplecov-mcp`.
41
+ ### Generate Coverage Data
33
42
 
34
- ## Usage
43
+ ```sh
44
+ # Run your tests with SimpleCov enabled
45
+ bundle exec rspec # or your test command
35
46
 
36
- ### Library Usage (Ruby)
47
+ # Verify coverage was generated
48
+ ls coverage/.resultset.json
49
+ ```
37
50
 
38
- Use this gem programmatically to inspect coverage without running the CLI or MCP server. The primary entry point is `SimpleCovMcp::CoverageModel`.
51
+ ### Basic Usage
39
52
 
40
- Basics:
53
+ **CLI - View Coverage Table:**
54
+ ```sh
55
+ simplecov-mcp
56
+ ```
41
57
 
58
+ **CLI - Check Specific File:**
59
+ ```sh
60
+ simplecov-mcp summary lib/simplecov_mcp/model.rb
61
+ simplecov-mcp uncovered lib/simplecov_mcp/cli.rb
62
+ ```
63
+
64
+ **Ruby Library:**
42
65
  ```ruby
43
- require "simple_cov_mcp"
66
+ require "simplecov_mcp"
44
67
 
45
- # Defaults (omit args; shown here with comments):
46
- # - root: "."
47
- # - resultset: resolved from SIMPLECOV_RESULTSET or common paths under root
48
- # - staleness: "off" (no stale checks)
49
- # - tracked_globs: nil (no project-level file-set checks)
50
68
  model = SimpleCovMcp::CoverageModel.new
51
-
52
- # Custom configuration (non-default values):
53
- model = SimpleCovMcp::CoverageModel.new(
54
- root: "/path/to/project", # non-default project root
55
- resultset: "build/coverage", # file or directory containing .resultset.json
56
- staleness: "error", # enable stale checks (raise on stale)
57
- tracked_globs: ["lib/**/*.rb"] # for 'all_files' staleness: flag new/missing files
58
- )
59
-
60
- # List all files with coverage summary, sorted ascending by % (default)
61
69
  files = model.all_files
62
- # => [ { 'file' => '/abs/path/lib/foo.rb', 'covered' => 12, 'total' => 14, 'percentage' => 85.71, 'stale' => false }, ... ]
63
-
64
- # Per-file summaries
65
- summary = model.summary_for("lib/foo.rb")
66
- # => { 'file' => '/abs/.../lib/foo.rb', 'summary' => {'covered'=>12, 'total'=>14, 'pct'=>85.71} }
67
-
68
- raw = model.raw_for("lib/foo.rb")
69
- # => { 'file' => '/abs/.../lib/foo.rb', 'lines' => [nil, 1, 0, 3, ...] }
70
+ # => [{ "file" => "lib/simplecov_mcp/model.rb", "covered" => 114, "total" => 118, "percentage" => 96.61, "stale" => false }, ...]
70
71
 
71
- uncovered = model.uncovered_for("lib/foo.rb")
72
- # => { 'file' => '/abs/.../lib/foo.rb', 'uncovered' => [5, 9, 12], 'summary' => { ... } }
73
-
74
- detailed = model.detailed_for("lib/foo.rb")
75
- # => { 'file' => '/abs/.../lib/foo.rb', 'lines' => [{'line' => 1, 'hits' => 1, 'covered' => true}, ...], 'summary' => { ... } }
72
+ summary = model.summary_for("lib/simplecov_mcp/model.rb")
73
+ # => { "file" => "lib/simplecov_mcp/model.rb", "summary" => { "covered" => 114, "total" => 118, "pct" => 96.61 }, "stale" => false }
76
74
  ```
77
75
 
78
- ### MCP Quick Start
79
-
80
- - Prereqs: Ruby 3.2+; run tests once so `coverage/.resultset.json` exists.
81
- - One-off MCP requests can be made by piping JSON-RPC to the server:
76
+ **MCP Server:**
77
+ See [MCP Integration Guide](docs/MCP_INTEGRATION.md) for AI assistant setup.
82
78
 
83
- **Important**: JSON-RPC messages must be on a single line (no line breaks). Multi-line JSON will cause parse errors.
79
+ ## Key Features
84
80
 
85
- ```sh
86
- # Per-file summary (staleness off)
87
- echo '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"coverage_summary_tool","arguments":{"path":"lib/foo.rb","resultset":"coverage","stale":"off"}}}' | simplecov-mcp
88
-
89
- # All files with project-level staleness checks
90
- echo '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"all_files_coverage_tool","arguments":{"resultset":"coverage","stale":"error","tracked_globs":["lib/**/*.rb"]}}}' | simplecov-mcp
91
- ```
81
+ - ✅ **Multiple interfaces** - MCP server, CLI, and Ruby API
82
+ - ✅ **Rich output formats** - Tables, JSON, annotated source code
83
+ - ✅ **Staleness detection** - Identify outdated coverage (missing files, timestamp mismatches, line count changes)
84
+ - ✅ **Multi-suite support** - Automatic merging of multiple test suites (RSpec + Cucumber, etc.)
85
+ - **Flexible path resolution** - Works with absolute or relative paths
86
+ - ✅ **Comprehensive error handling** - Context-aware messages for each mode
87
+ - ⚠️ **Branch coverage limitation** - Branch-level metrics are collapsed to per-line totals. Use native SimpleCov reports for branch-by-branch analysis.
92
88
 
93
- Tip: In an MCP-capable editor/agent, configure `simplecov-mcp` as a stdio server and call the same tool names with the `arguments` shown above.
89
+ ## Multi-Suite Coverage Merging
94
90
 
95
- Response content types (MCP):
91
+ ### How It Works
96
92
 
97
- - JSON data returns as a single `type: "resource"` item with `resource.mimeType: "application/json"` and the JSON string in `resource.text` (e.g., `name: "coverage_summary.json"`).
98
- - Human-readable strings (e.g., the table and version) return as `type: "text"`.
99
- - Errors return as `type: "text"` with a friendly message.
93
+ When a `.resultset.json` file contains multiple test suites (e.g., RSpec + Cucumber), `simplecov-mcp` automatically merges them using SimpleCov's combine logic. All covered files from every suite become available to the CLI, library, and MCP tools.
100
94
 
101
- Resultset resolution:
95
+ **Performance:** Single-suite projects avoid loading SimpleCov at runtime. Multi-suite resultsets trigger a lazy SimpleCov load only when needed, keeping the tool fast for the simpler coverage configurations.
102
96
 
103
- - If `resultset:` is provided, it may be:
104
- - a file path to `.resultset.json`, or
105
- - a directory containing `.resultset.json` (e.g., `coverage/`).
106
- - If `resultset:` is omitted, resolution follows:
107
- 1) `ENV["SIMPLECOV_RESULTSET"]` (file or directory), then
108
- 2) `.resultset.json`, 3) `coverage/.resultset.json`, 4) `tmp/.resultset.json` under `root`.
97
+ ### Current Limitations
109
98
 
110
- Path semantics:
99
+ **Staleness checks:** When suites are merged, we keep a single "latest suite" timestamp. This matches prior behavior but may under-report stale files if only some suites were re-run after a change. A per-file timestamp refinement is planned. Until then, consider multi-suite staleness checks advisory rather than definitive.
111
100
 
112
- - Methods accept paths relative to `root` or absolute paths. Internally, the model resolves to an absolute path and looks up coverage by:
113
- 1) exact absolute path,
114
- 2) the path without the current working directory prefix,
115
- 3) filename (basename) match as a last resort.
101
+ **Multiple resultset files:** Only suites stored inside a *single* `.resultset.json` are merged automatically. If your project produces separate resultset files (e.g., different CI jobs writing `coverage/job1/.resultset.json`, `coverage/job2/.resultset.json`), you must merge them yourself before pointing `simplecov-mcp` at the combined file.
116
102
 
117
- Sorting:
103
+ ## Documentation
118
104
 
119
- ```ruby
120
- model.all_files(sort_order: :descending) # or :ascending (default)
121
- ```
105
+ **Getting Started:**
106
+ - [Installation](docs/INSTALLATION.md) - Setup for different environments
107
+ - [CLI Usage](docs/CLI_USAGE.md) - Command-line reference
108
+ - [Examples](docs/EXAMPLES.md) - Common use cases
122
109
 
123
- ## Example Prompts
110
+ **Advanced Usage:**
111
+ - [MCP Integration](docs/MCP_INTEGRATION.md) - AI assistant configuration
112
+ - [Library API](docs/LIBRARY_API.md) - Ruby API documentation
113
+ - [Error Handling](docs/ERROR_HANDLING.md) - Error modes and exceptions
124
114
 
125
- Using simplecov-mcp, show me a table of all files and their coverages.
115
+ **Reference:**
116
+ - [Troubleshooting](docs/TROUBLESHOOTING.md) - Common issues
117
+ - [Development](docs/DEVELOPMENT.md) - Contributing guide
126
118
 
127
- ----
119
+ ## Requirements
128
120
 
129
- Using simplecov-mcp, find the uncovered code lines and report to me, in a markdown file:
121
+ - **Ruby >= 3.2** (required by `mcp` gem dependency)
122
+ - SimpleCov-generated `.resultset.json` file
123
+ - `simplecov` gem >= 0.21
124
+ - RVM users: export your preferred ruby/gemset *before* running commands (e.g. `rvm use 3.4.5@simplecov-mcp`)
130
125
 
131
- * the most important coverage omissions to address
132
- * the simplest coverage omissions to address
133
- * analyze the risk of the current state of coverage
134
- * propose a plan of action (if any) to improve coverage state
126
+ ## Configuring the Resultset
135
127
 
136
- ----
128
+ `simplecov-mcp` automatically searches for `.resultset.json` in standard locations (`coverage/.resultset.json`, `.resultset.json`, `tmp/.resultset.json`). For non-standard locations:
137
129
 
130
+ ```sh
131
+ # Command-line option (highest priority)
132
+ simplecov-mcp --resultset /path/to/your/coverage
138
133
 
139
- ## Error Handling
140
-
141
- This tool provides different error handling behavior depending on how it's used:
142
-
143
- ### CLI Mode
144
- When used as a command-line tool, errors are displayed as user-friendly messages without stack traces:
134
+ # Environment variable (project-wide default)
135
+ export SIMPLECOV_MCP_OPTS="--resultset /path/to/your/coverage"
145
136
 
146
- ```bash
147
- $ simplecov-mcp summary nonexistent.rb
148
- File error: No coverage data found for the specified file
137
+ # MCP server configuration
138
+ # Add to your MCP client config:
139
+ # "args": ["--resultset", "/path/to/your/coverage"]
149
140
  ```
150
141
 
151
- For debugging, set the `SIMPLECOV_MCP_DEBUG=1` environment variable to see full stack traces.
142
+ See [CLI Usage Guide](docs/CLI_USAGE.md#-r---resultset-path) for complete details.
152
143
 
153
- ### Library Mode
154
- When used as a Ruby library, errors are raised as custom exception classes that can be caught and handled:
155
-
156
- ```ruby
157
- begin
158
- SimpleCovMcp.run_as_library(['summary', 'missing.rb'])
159
- rescue SimpleCovMcp::FileError => e
160
- puts "Handled gracefully: #{e.user_friendly_message}"
161
- end
162
- ```
163
144
 
164
- Available exception classes:
165
- - `SimpleCovMcp::Error` - Base error class
166
- - `SimpleCovMcp::FileError` - File not found or access issues
167
- - `SimpleCovMcp::CoverageDataError` - Invalid or missing coverage data
168
- - `SimpleCovMcp::ConfigurationError` - Configuration problems
169
- - `SimpleCovMcp::UsageError` - Command usage errors
170
145
 
171
- ### MCP Server Mode
172
- When running as an MCP server, errors are handled internally and returned as structured responses to the MCP client. The MCP server uses:
146
+ ## Common Workflows
173
147
 
174
- - **Logging enabled** - Errors are logged to `~/simplecov_mcp.log` for server debugging
175
- - **Clean error messages** - User-friendly messages are returned to the client (no stack traces unless `SIMPLECOV_MCP_DEBUG=1`)
176
- - **Structured responses** - Errors are returned as proper MCP tool responses, not exceptions
148
+ ### Find Coverage Gaps
177
149
 
178
- The MCP server automatically configures error handling appropriately for server usage.
150
+ ```sh
151
+ # Files with worst coverage
152
+ simplecov-mcp list --sort-order d # display table in descending order, worst will be at end of output
153
+ simplecov-mcp list -o d # same as above, short form option
154
+ simplecov-mcp list | less # display table in pager, worst files first
155
+ simplecov-mcp list | head -10 # truncate the table
179
156
 
180
- ### Custom Error Handlers
181
- Library usage defaults to no logging to avoid side effects, but you can customize this:
157
+ # Specific directory
158
+ simplecov-mcp list --tracked-globs "lib/simplecov_mcp/tools/**/*.rb"
182
159
 
183
- ```ruby
184
- # Default library behavior - no logging
185
- SimpleCovMcp.run_as_library(['summary', 'file.rb'])
186
-
187
- # Custom error handler with logging enabled
188
- handler = SimpleCovMcp::ErrorHandler.new(
189
- log_errors: true, # Enable logging for library usage
190
- show_stack_traces: false # Clean error messages
191
- )
192
- SimpleCovMcp.run_as_library(argv, error_handler: handler)
193
-
194
- # Or configure globally for MCP tools
195
- SimpleCovMcp.configure_error_handling do |handler|
196
- handler.log_errors = true
197
- handler.show_stack_traces = true # For debugging
198
- end
160
+ # Export for analysis
161
+ simplecov-mcp list --json > coverage-report.json
199
162
  ```
200
163
 
201
- ### Legacy Error Handling Tips
202
-
203
- - Missing resultset: `SimpleCov::Mcp::CovUtil.find_resultset` raises with guidance to run tests or set `SIMPLECOV_RESULTSET`.
204
- - Missing file coverage: lookups raise `"No coverage entry found for <path>"`.
205
-
206
- Example: fail CI if a file has uncovered lines
164
+ ### CI/CD Integration
207
165
 
208
- ```ruby
209
- require "simple_cov_mcp"
210
-
211
- model = SimpleCovMcp::CoverageModel.new(root: Dir.pwd)
212
- res = model.uncovered_for("lib/foo.rb")
213
- if res['uncovered'].any?
214
- warn "Uncovered lines in lib/foo.rb: #{res['uncovered'].join(", ")}"
215
- exit 1
216
- end
217
- ```
218
-
219
- Example: enforce a project-wide minimum percentage
166
+ ```sh
167
+ # Fail build if coverage is stale
168
+ simplecov-mcp --stale error || exit 1
220
169
 
221
- ```ruby
222
- require "simple_cov_mcp"
223
-
224
- threshold = 90.0
225
- min = model.all_files.map { |r| r['percentage'] }.min || 100.0
226
- if min < threshold
227
- warn "Min coverage %.2f%% is below threshold %.2f%%" % [min, threshold]
228
- exit 1
229
- end
170
+ # Generate coverage report artifact
171
+ simplecov-mcp list --json > artifacts/coverage.json
230
172
  ```
231
173
 
232
- Public API stability:
233
-
234
- - Consider the following public and stable under SemVer:
235
- - `SimpleCovMcp::CoverageModel.new(root:, resultset:, staleness: 'off', tracked_globs: nil)`
236
- - `#raw_for(path)`, `#summary_for(path)`, `#uncovered_for(path)`, `#detailed_for(path)`, `#all_files(sort_order:)`
237
- - Return shapes shown above (keys and value types). For `all_files`, each row also includes `'stale' => true|false`.
238
- - CLI (`SimpleCovMcp.run(argv)`) and MCP tools remain stable but are separate surfaces.
239
- - Internal helpers under `SimpleCovMcp::CovUtil` may change; prefer `CoverageModel` unless you need low-level access.
240
-
241
- ### Resultset Location
242
-
243
- - Defaults (search order):
244
- 1. `.resultset.json`
245
- 2. `coverage/.resultset.json`
246
- 3. `tmp/.resultset.json`
247
- - Override via CLI: `--resultset PATH` (PATH may be the file itself or a directory containing `.resultset.json`).
248
- - Override via environment: `SIMPLECOV_RESULTSET=PATH` (file or directory). This takes precedence over defaults. The CLI flag, when present, takes precedence over the environment variable.
249
-
250
- ### CLI Mode
251
-
252
- ### Stale Coverage Errors
174
+ ### Investigate Specific Files
253
175
 
254
- When strict staleness checking is enabled, the model (and CLI) raise a
255
- `CoverageDataStaleError` if a source file appears newer than the coverage data
256
- or the line counts differ.
257
-
258
- - Enable per instance: `SimpleCovMcp::CoverageModel.new(staleness: 'error')`
259
-
260
- The error message is detailed and includes:
176
+ ```sh
177
+ # Quick summary
178
+ simplecov-mcp summary lib/simplecov_mcp/model.rb
261
179
 
262
- - File and Coverage times (UTC and local) and line counts
263
- - A delta indicating how much newer the file is than coverage
264
- - The absolute path to the `.resultset.json` used
180
+ # See uncovered lines
181
+ simplecov-mcp uncovered lib/simplecov_mcp/cli.rb
265
182
 
266
- Example excerpt:
183
+ # View in context
184
+ simplecov-mcp uncovered lib/simplecov_mcp/cli.rb --source=uncovered --source-context 3
267
185
 
268
- ```
269
- Coverage data stale: Coverage data appears stale for lib/foo.rb
270
- File - time: 2025-09-16T14:03:22Z (local 2025-09-16T07:03:22-07:00), lines: 226
271
- Coverage - time: 2025-09-15T21:11:09Z (local 2025-09-15T14:11:09-07:00), lines: 220
272
- Delta - file is +123s newer than coverage
273
- Resultset - /path/to/your/project/coverage/.resultset.json
186
+ # Detailed hit counts
187
+ simplecov-mcp detailed lib/simplecov_mcp/util.rb
274
188
  ```
275
189
 
276
- Run in a project directory with a SimpleCov resultset:
190
+ ## Commands and Tools
277
191
 
278
- ```sh
279
- simplecov-mcp # same as 'list'
280
- ```
192
+ **CLI Subcommands:** `list`, `summary`, `uncovered`, `detailed`, `raw`, `version`
281
193
 
282
- Subcommands:
194
+ **MCP Tools:** `coverage_summary_tool`, `coverage_detailed_tool`, `coverage_raw_tool`, `uncovered_lines_tool`, `all_files_coverage_tool`, `coverage_table_tool`, `help_tool`, `version_tool`
283
195
 
284
- - `list` — show the table of all files (sorted ascending by default)
285
- - `summary <path>` show covered/total/% for a file
286
- - `raw <path>` show the original SimpleCov lines array
287
- - `uncovered <path>` — show uncovered lines and summary
288
- - `detailed <path>` — show per-line rows with hits and covered
289
- - `version` — show version information
196
+ 📖 **See also:**
197
+ - [CLI Usage Guide](docs/CLI_USAGE.md) - Complete command-line reference
198
+ - [MCP Integration Guide](docs/MCP_INTEGRATION.md#available-mcp-tools) - MCP tools documentation
290
199
 
291
- Global flags (OptionParser):
200
+ ## Troubleshooting
292
201
 
293
- - `--cli` (alias `--report`) force CLI output
294
- - `--resultset PATH` path or directory for `.resultset.json`
295
- - `--root PATH` project root (default `.`)
296
- - `--json` print JSON output for machine use
297
- - `--sort-order ascending|descending` for `list`
298
- - `--source[=MODE]` — include source text for `summary`, `uncovered`, `detailed` (MODE: `full` or `uncovered`; default `full`)
299
- - `--source-context N` — for `--source=uncovered`, lines of context (default 2)
300
- - `--color` / `--no-color` — enable/disable ANSI colors in source output
301
- - `--stale off|error` — staleness checking mode (default `off`)
302
- - `--tracked-globs x,y,z` — globs for files that should be covered (applies to `list` staleness only)
303
- - `--help` — show usage
202
+ - **"command not found"** - See [Installation Guide](docs/INSTALLATION.md#path-configuration)
203
+ - **"cannot load such file -- mcp"** - Upgrade to Ruby >= 3.2
204
+ - **"Could not find .resultset.json"** - Run tests to generate coverage. See the [Configuring the Resultset](#configuring-the-resultset) section for more details.
205
+ - **MCP server won't connect** - Check PATH and Ruby version in [MCP Troubleshooting](docs/MCP_INTEGRATION.md#troubleshooting)
206
+ - **Codex on macOS with RVM** - Codex's macOS sandbox disallows `/bin/ps`, which RVM needs. Use a different version manager (rbenv, chruby) or run outside the Codex environment.
304
207
 
305
- Select a nonstandard resultset path:
208
+ For more detailed help, see the full [Troubleshooting Guide](docs/TROUBLESHOOTING.md).
306
209
 
307
- ```sh
308
- simplecov-mcp --cli --resultset build/coverage/.resultset.json
309
- # or
310
- SIMPLECOV_RESULTSET=build/coverage/.resultset.json simplecov-mcp --cli
311
- ```
312
-
313
- You can also pass a directory that contains `.resultset.json` (common when the file lives in a `coverage/` folder):
210
+ ## Development
314
211
 
315
212
  ```sh
316
- simplecov-mcp --cli --resultset coverage
317
- # or via env
318
- SIMPLECOV_RESULTSET=coverage simplecov-mcp --cli
319
- ```
320
-
321
- Forces CLI mode:
213
+ # Clone and setup
214
+ git clone https://github.com/keithrbennett/simplecov-mcp.git
215
+ cd simplecov-mcp
216
+ bundle install
322
217
 
323
- ```sh
324
- simplecov-mcp --cli
325
- # or
326
- SIMPLECOV_MCP_CLI=1 simplecov-mcp
327
- ```
218
+ # Run tests
219
+ bundle exec rspec
328
220
 
329
- Example output:
221
+ # Test locally
222
+ ruby -Ilib exe/simplecov-mcp
330
223
 
331
- ```text
332
- ┌───────────────────────────┬──────────┬──────────┬────────┬───┐
333
- File │ % │ Covered │ Total │ ! │
334
- ├───────────────────────────┼──────────┼──────────┼────────┼───┤
335
- │ spec/user_spec.rb │ 85.71 │ 12 │ 14 │ │
336
- │ lib/models/user.rb │ 92.31 │ 12 │ 13 │ ! │
337
- │ lib/services/auth.rb │ 100.00 │ 8 │ 8 │ │
338
- └───────────────────────────┴──────────┴──────────┴────────┴───┘
224
+ # Build and install
225
+ gem build simplecov-mcp.gemspec
226
+ gem install simplecov-mcp-*.gem
339
227
  ```
340
228
 
341
- Files are sorted by percentage (ascending), then by path.
342
-
343
- ### MCP Server Mode
344
-
345
- When stdin has data (e.g., from an MCP client), the program runs as an MCP server over stdio.
346
-
347
- Available tools:
348
-
349
- - `coverage_raw_tool(path, root=".", resultset=nil, stale='off')`
350
- - `coverage_summary_tool(path, root=".", resultset=nil, stale='off')`
351
- - `uncovered_lines_tool(path, root=".", resultset=nil, stale='off')`
352
- - `coverage_detailed_tool(path, root=".", resultset=nil, stale='off')`
353
- - `all_files_coverage_tool(root=".", resultset=nil, stale='off', tracked_globs=nil)`
354
- - Returns `{ files: [{"file","covered","total","percentage","stale"}, ...] }` where `stale` is a boolean.
355
- - `version_tool()` — returns version information
229
+ See [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md) for more *(coming soon)*.
356
230
 
357
- Response shape and content types:
231
+ ## SimpleCov Dependency
358
232
 
359
- - JSON tools above return a single content item `{ "type": "resource", "resource": { "mimeType": "application/json", "text": "{...}", "name": "<tool>.json" } }`.
360
- - `coverage_table_tool` and `version_tool` return `{ "type": "text", "text": "..." }`.
233
+ `simplecov-mcp` declares a runtime dependency on `simplecov` (>= 0.21) to support multi-suite merging using SimpleCov's combine helpers. The dependency is lazy-loaded only when needed, ensuring fast startup for single-suite projects.
361
234
 
362
- Notes:
235
+ ## Contributing
363
236
 
364
- - `resultset` lets clients pass a nonstandard path to `.resultset.json` directly (absolute or relative to `root`). It may be:
365
- - a file path to `.resultset.json`, or
366
- - a directory path containing `.resultset.json` (e.g., `coverage/`).
367
- - If `resultset` is omitted, the server checks `SIMPLECOV_RESULTSET`, then searches `.resultset.json`, `coverage/.resultset.json`, `tmp/.resultset.json` in that order.
368
- - `stale` controls staleness checking per call (`off` or `error`).
369
- - For `all_files_coverage`, `tracked_globs` detects new project files missing from coverage, and the tool also flags covered files that are newer than the coverage timestamp or present in coverage but deleted in the project.
237
+ Contributions are welcome! Please:
370
238
 
371
- Example (manual - note single-line JSON-RPC format):
239
+ 1. Fork the repository
240
+ 2. Create a feature branch
241
+ 3. Add tests for new functionality
242
+ 4. Ensure all tests pass (`bundle exec rspec`)
243
+ 5. Submit a pull request
372
244
 
373
- ```sh
374
- echo '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"coverage_summary_tool","arguments":{"path":"lib/foo.rb"}}}' | simplecov-mcp
375
- ```
376
-
377
- With an explicit resultset path:
378
-
379
- ```sh
380
- echo '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"coverage_summary_tool","arguments":{"path":"lib/foo.rb","resultset":"build/coverage/.resultset.json"}}}' | simplecov-mcp
381
- ```
382
-
383
- With a resultset directory:
384
-
385
- ```sh
386
- echo '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"coverage_summary_tool","arguments":{"path":"lib/foo.rb","resultset":"coverage"}}}' | simplecov-mcp
387
- ```
245
+ ## License
388
246
 
389
- CLI vs MCP summary:
247
+ MIT License - see [LICENSE](LICENSE) file for details.
390
248
 
391
- - CLI: use subcommands. Pass `--resultset PATH` or set `SIMPLECOV_RESULTSET`.
392
- - MCP: pass `resultset` in tool arguments, or set `SIMPLECOV_RESULTSET`.
249
+ ## Links
393
250
 
394
- ## Troubleshooting
251
+ - **GitHub:** https://github.com/keithrbennett/simplecov-mcp
252
+ - **RubyGems:** https://rubygems.org/gems/simplecov-mcp
253
+ - **Issues:** https://github.com/keithrbennett/simplecov-mcp/issues
254
+ - **Changelog:** [RELEASE_NOTES.md](RELEASE_NOTES.md)
395
255
 
396
- - MCP client fails to start or times out
397
- - Likely cause: launching `simplecov-mcp` with an older Ruby that cannot load the `mcp` gem. This gem requires Ruby >= 3.2.
398
- - Check the Ruby your MCP client uses: run `ruby -v` in the same environment your client inherits; ensure it reports 3.2+.
399
- - Fix PATH or select a newer Ruby via rbenv/rvm/asdf, then retry. You can configure your MCP client to point to the shim/binary for that Ruby version. For example:
400
- - rbenv shim: `~/.rbenv/shims/simplecov-mcp`
401
- - asdf shim: `~/.asdf/shims/simplecov-mcp`
402
- - RVM wrapper: `/Users/you/.rvm/wrappers/ruby-3.3.0/simplecov-mcp` (adjust version)
403
- - Codex CLI example (`~/.codex/config.toml`):
404
- ```toml
405
- # Use the Ruby 3.2+ shim for the MCP server
406
- [tools.simplecov_mcp]
407
- command = "/Users/you/.rbenv/shims/simplecov-mcp"
408
- cwd = "/path/to/your/project"
409
- ```
410
- - Validate manually: `simplecov-mcp --cli` (or from this repo: `ruby -Ilib exe/simplecov-mcp --cli`). If you see the coverage table, the binary starts correctly.
411
- - On failures, check `~/simplecov_mcp.log` for details.
412
-
413
- ### Notes
414
-
415
- - Library entrypoint: `require "simple_cov_mcp"` (also `simplecov_mcp`). Legacy `simple_cov/mcp` is supported.
416
- - Programmatic run: `SimpleCovMcp.run(ARGV)`
417
- - Staleness checks: pass `staleness: 'error'` to `CoverageModel` (or use CLI `--stale error`) to
418
- raise if source mtimes are newer than coverage or line counts mismatch. Use
419
- `--tracked-globs` (CLI) or `tracked_globs` (API/MCP) to flag new files.
420
- - Logs basic diagnostics to `~/simplecov_mcp.log`.
421
-
422
- ## Executables and PATH
423
-
424
- To run `simplecov-mcp` globally, your PATH must include where Ruby installs executables.
425
-
426
- - Version managers
427
- - RVM, rbenv, asdf, chruby typically add the right bin/shim directories to PATH.
428
- - Ensure your shell is initialized (e.g., rbenv init, asdf reshim ruby after installs).
429
- - Without a manager
430
- - Add the gem bin dir to PATH: see it with `gem env` (look for "EXECUTABLE DIRECTORY") or `ruby -e 'puts Gem.bindir'`.
431
- - Example: `export PATH="$HOME/.gem/ruby/3.2.0/bin:$PATH"` (adjust version).
432
- - Alternatives
433
- - Use Bundler: `bundle exec simplecov-mcp` with cwd set to your project.
434
- - Symlink the repo executable into a bin on your PATH; the script resolves its lib/ via realpath.
435
- - Or configure Codex to run the executable by filename (`simplecov-mcp`) and inherit the current workspace as cwd.
256
+ ## Related Files
436
257
 
437
- ## Development
258
+ - [CLAUDE.md](CLAUDE.md) - Claude Code integration notes
259
+ - [AGENTS.md](AGENTS.md) - AI agent configuration
260
+ - [GEMINI.md](GEMINI.md) - Gemini-specific guidance
438
261
 
439
- Standard Ruby gem structure. After cloning:
262
+ ---
440
263
 
441
- ```sh
442
- bundle install
443
- ruby -Ilib exe/simplecov-mcp --cli
444
- ```
264
+ ## Next Steps
445
265
 
446
- Run tests with coverage (SimpleCov writes to `coverage/`):
266
+ 📦 **Install:** `gem install simplecov-mcp`
447
267
 
448
- ```sh
449
- bundle exec rspec
450
- # open coverage/index.html for HTML report, or run exe/simplecov-mcp for table summary
451
- ```
268
+ 📖 **Read:** [CLI Usage Guide](docs/CLI_USAGE.md) | [MCP Integration](docs/MCP_INTEGRATION.md)
452
269
 
453
- ## License
270
+ 🐛 **Report issues:** [GitHub Issues](https://github.com/keithrbennett/simplecov-mcp/issues)
454
271
 
455
- MIT
272
+ ⭐ **Star the repo** if you find it useful!