dotnet-coverage-mcp について
dotnet-coverage-mcp は、AI アシスタントに .NET テストの実行とカバレッジ分析を行う MCP ツールを提供します。分岐単位の分析、カバレッジ差分、セッションごとの成果物分離、テストコードの追記に対応します。
主な機能
- 01C# ソースファイルの検出とバッチ化
- 02フィルター付きテストとカバレッジ収集
- 03クラスおよびメソッドのカバレッジ要約
- 04未カバー分岐の特定と実行間の比較
- 05アトミック書き込みによるテストコード追記
- 06セッション単位でカバレッジ成果物を分離
活用シーン
- 01.NET プロジェクトの低カバレッジメソッドを特定
- 02テスト追加前に未カバー分岐を確認
- 03コード変更前後のカバレッジを比較
- 04別々のプロジェクトでカバレッジ処理を並行実行
MCP 対応
このサーバーは stdio で MCP クライアントと通信し、ソース検出、テスト実行、カバレッジ分析、テストコード挿入のツールを提供します。`dotnet test` と `reportgenerator` を呼び出します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
このサーバーのパッケージやリモートエンドポイントはまだ取得できていません。プロジェクトの README の手順に従ってください。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
dotnet-coverage-mcp
AI アシスタント(Claude Code、Gemini CLI など)に .NET のテストカバレッジツールへの直接アクセスを提供する MCP(Model Context Protocol)サーバーです。dotnet test の実行、Cobertura XML の解析、未カバーの分岐の特定、実行間のカバレッジ差分の比較、テストコードの追加を、すべて stdio 経由で行えます。
目的
このサーバーを使うと、AI アシスタントはチャットを離れることなく、単体テストを実行してカバレッジデータを収集し、結果を分析できます。手動で dotnet test を実行してレポートを解析する代わりに、AI はサーバーのツールを直接呼び出して、次の操作を行えます。
- ソースファイルを検出し、行数の予算に基づいてスマートなバッチを作成する
- フィルターを適用したテストを実行し、カバレッジを収集する
- 簡潔で AI 向けに最適化されたカバレッジ概要(メソッド単位の行カバレッジ率/分岐カバレッジ率)を読み取る
- 設定可能な目標率(デフォルトは 80%)に対するファイルごとのカバレッジを確認する
- 未カバーの分岐を構造化 JSON として特定する
- 実行間のカバレッジを比較し、変更点のみを確認する
- 既存のテストファイルに、新しいテストコードをアトミック書き込みで追加する
仕組み
サーバーはコンソールプロセスとして起動し、MCP プロトコルを使用して stdio 経由で通信します。MCP 対応クライアント(Claude Code、Gemini CLI など)がプロセスを起動し、関数を呼び出すようにそのツールを呼び出します。
AI Client <--stdio/MCP--> dotnet-coverage-mcp <--shell--> dotnet test + reportgenerator
利用可能なツール
| ツール | 説明 |
|---|---|
GetSourceFiles | ファイル、フォルダー、または .csproj プロジェクトから .cs ファイルを検出します。ファイルのメタデータ(行数、メソッド数)と、lineBudget でグループ化したスマートなバッチを返します。 |
RunTestsWithCoverage | XPlat Code Coverage を使用して dotnet test を実行し、reportgenerator で JSON 概要を生成します。Summary.json と coverage.cobertura.xml のパスを返します。並行実行を分離するための forceRestore と sessionId に対応しています。 |
GetCoverageSummary | Summary.json を解析し、クラス/メソッド単位のカバレッジデータを分岐カバレッジ率の低い順に返します。省略可能な belowTarget/topN/methodsPerClass フィルターを使って、対応が必要な項目にレスポンスを絞り込めます。 |
GetFileCoverage | Cobertura XML から単一のソースファイルのカバレッジを取得します。すべてのクラスが、行カバレッジと分岐カバレッジの両方で設定済みの targetRate(デフォルトは 0.8)を達成している場合、allMeetTarget は true になります。sessionId に対応しています。 |
GetUncoveredBranches | 指定した名前に一致するメソッドの未カバーの分岐条件を検索します。名前の部分一致にも対応し、一致するすべてのメソッドを返します。sessionId に対応しています。 |
GetCoverageDiff | 現在の Cobertura XML をベースラインと比較します。新規および削除されたメソッドを含む、メソッド単位の変更を表示します。並行実行を分離するための sessionId に対応しています。 |
AppendTestCode | C# のテストコードをテストファイルに挿入または追加します。アンカーベースの挿入に対応し、空白を許容するフォールバック照合も行います。ファイルの破損を防ぐため、アトミック書き込みを使用します。 |
CleanupSession | セッション状態ファイルと TestResults/coveragereport ディレクトリを削除します。sessionId を渡すと対象を限定できます。省略すると、maxAgeMinutes(デフォルトは 120)より古い成果物を削除します。 |
バッチワークフロー
ソースファイルが多数あるプロジェクトでは、次のワークフローを推奨します。
- 検出 — フォルダーまたは
.csprojに対してGetSourceFilesを呼び出し、すべてのファイルとスマートバッチを取得します - 一度実行 — 広いフィルター(例:
*)を指定してRunTestsWithCoverageを呼び出し、すべてのファイルのカバレッジを収集します - ファイルごとに確認 — 現在のバッチ内の各ファイルに対して
GetFileCoverageを呼び出します(XML を即座に解析し、テストを再実行しません) - 対象を絞る — ブランチカバレッジが最も低いメソッドを 3 つ選び、それぞれに対して
GetUncoveredBranchesを呼び出します - テストを作成 —
AppendTestCodeを使用してテストメソッドを追加します - 再実行して差分を確認 — テストを一度実行し、
GetCoverageDiffを呼び出して改善を確認します - 繰り返す — バッチ内のファイルが目標率(デフォルトは 80%)に達するか、改善のないサイクルが 3 回続くまで続け、その後、次のバッチに進みます
これにより、ファイルごとの進捗を追跡しながら、dotnet test の実行回数(主なボトルネック)を最小限に抑えられます。
並行実行
各ツール呼び出しに sessionId を渡すことで、複数の AI エージェントを並行して実行できます。これにより、カバレッジ成果物が分離されます。
- 出力ディレクトリの分離 —
RunTestsWithCoverageはセッションごとにTestResults-{hash}/とcoveragereport-{hash}/を作成し、あるエージェントが別のエージェントによる解析中に XML を削除するのを防ぎます - 状態ファイルのスコープ分離 — カバレッジの状態は
.mcp-coverage/.coverage-state-{hash}に書き込まれるため、ResolveCoberturaPathは各セッションに対応する XML を解決します - ベースラインのスコープ分離 —
GetCoverageDiffはセッションごとに.coverage-prev-{hash}.xmlとしてベースラインを保存します - アトミックな書き込み — すべてのファイル書き込み(状態ファイルとテストコード)では、一時ファイルへの書き込み後に名前を変更し、競合状態やプロセスのクラッシュによる破損を防ぎます
制限事項 — ビルド出力はセッションごとに分離されません。
sessionIdが分離するのはカバレッジの 成果物 であり、.NET の ビルド ではありません。dotnet testは対象プロジェクトを共有のobj/とbin/にコンパイルし、これらはセッションごとに分離されないため、同じテストプロジェクトに対して 2 つのエージェントが同時にRunTestsWithCoverageを実行すると、これらの出力で競合してbuildError(例:CS2012: the file is being used by another process)が発生します。異なるテストプロジェクトに対して並行実行するか、リポジトリの別々の作業コピーで実行してください。1 つのプロジェクトで複数のエージェントを使用しても、それぞれのdotnet testのビルドが重ならなければ問題ありません。
sessionId を指定しない場合、ツールは共有のデフォルト設定を使用します。単一エージェントでの使用には安全です。
要件
-
.NET 9.0 SDK(またはそれ以降) — https://dotnet.microsoft.com/download
-
reportgenerator グローバルツール — カバレッジレポートの生成にサーバーから呼び出されます(以下の インストール 手順でインストールします)
-
MCP 対応クライアント(Claude Code、Gemini CLI など)
-
COVERAGE_MCP_ALLOWED_ROOT— 設定を推奨します。リポジトリのルートに設定すると、すべてのツールのファイルシステムアクセスをそのサブツリー内に制限できます。このルート外のパスをクライアントが渡すと、pathNotAllowedで拒否されます。未設定の場合、サーバーは警告を一度ログに記録し、任意のパスを受け付けます(後方互換性のための動作ですが、共有環境では推奨されません)。export COVERAGE_MCP_ALLOWED_ROOT=/path/to/your/repo
インストール
NuGet からグローバル .NET ツールとしてサーバーをインストールします。
dotnet tool install --global dotnet-coverage-mcp
サーバーはカバレッジレポートの生成に reportgenerator グローバルツールを使用するため、こちらもインストールしてください。
dotnet tool install --global dotnet-reportgenerator-globaltool
インストール後、dotnet-coverage-mcp コマンドが PATH に追加されます。
ビルドと実行(ソースから)
cd <path-to-dotnet-coverage-mcp>
# Restore dependencies
dotnet restore
# Build
dotnet build
# Run
dotnet run
サーバーが起動し、標準入力/標準出力を介した MCP メッセージを待ち受けます。
MCP クライアントの設定
グローバルツール(dotnet tool install --global dotnet-coverage-mcp)をインストールした後、
使用する MCP クライアントにサーバーを登録します。サーバーが操作するリポジトリを
COVERAGE_MCP_ALLOWED_ROOT に設定してください。
Claude Code
claude mcp add coverage --env COVERAGE_MCP_ALLOWED_ROOT=/path/to/your/repo -- dotnet-coverage-mcp
Claude Desktop
claude_desktop_config.json に追加します(Settings → Developer → Edit Config)。
{
"mcpServers": {
"coverage": {
"command": "dotnet-coverage-mcp",
"env": {
"COVERAGE_MCP_ALLOWED_ROOT": "/path/to/your/repo"
}
}
}
}
Cursor
~/.cursor/mcp.json(グローバル)または .cursor/mcp.json(プロジェクトごと)に追加します。
{
"mcpServers": {
"coverage": {
"command": "dotnet-coverage-mcp",
"env": {
"COVERAGE_MCP_ALLOWED_ROOT": "/path/to/your/repo"
}
}
}
}
VS Code(GitHub Copilot)
.vscode/mcp.json に追加します。
{
"servers": {
"coverage": {
"type": "stdio",
"command": "dotnet-coverage-mcp",
"env": {
"COVERAGE_MCP_ALLOWED_ROOT": "/path/to/your/repo"
}
}
}
}
ソースから実行
グローバルツールではなくソースから実行するには、dotnet run を使用します。
{
"mcpServers": {
"coverage": {
"command": "dotnet",
"args": ["run", "--project", "<path-to-dotnet-coverage-mcp>"],
"transport": "stdio"
}
}
}
または、コンパイル済みの実行可能ファイルを直接指定します。
{
"mcpServers": {
"coverage": {
"command": "<path-to-dotnet-coverage-mcp>\\bin\\Debug\\net9.0\\DotNetCoverageMcp.exe",
"transport": "stdio"
}
}
}
ツールのパラメーター
GetSourceFiles
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
path | string | はい | .cs ファイル、フォルダー、または .csproj プロジェクトへのパス |
lineBudget | int | いいえ | バッチごとの最大合計行数(デフォルト:300)。小さなファイルはまとめられ、大きなファイルは個別のバッチになります。 |
RunTestsWithCoverage
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
testProjectPath | string | はい | テストプロジェクトの .csproj へのフルパス |
filter | string | はい | テストフィルター文字列(FullyQualifiedName に照合)。複数のテストクラスを対象に幅広く実行するには、* または , を使用します。 |
workingDir | string | いいえ | 作業ディレクトリ。デフォルトはプロジェクトディレクトリです |
forceRestore | bool | いいえ | true の場合、--no-restore フラグを省略します。新しいテストプロジェクトをスキャフォールディングした後や、NuGet パッケージを追加した後に使用します。 |
sessionId | string | いいえ | 並行する複数エージェントでの使用時に、出力ディレクトリ(TestResults-{hash}/、coveragereport-{hash}/)と状態ファイルを分離します。 |
includeClass | string | いいえ | この名前に一致する型のみにカバレッジ収集を制限します(coverlet の Include フィルター。--settings で渡される生成済みの runsettings ファイルを介して適用)。filter とは独立しています。カバレッジの範囲を指定するには明示的な値を渡し、実行で処理されるすべての対象についてカバレッジを収集するには省略します。名前空間で修飾した名前はサポートされていません。 |
skipReport | bool | いいえ | true の場合、reportgenerator の JSON サマリーステップを省略し、Cobertura XML のパスのみを返します。GetFileCoverage/GetUncoveredBranches/GetCoverageDiff が XML を直接読み取るテストの反復処理では、より高速です。GetCoverageSummary の Summary.json が必要な場合は、false(デフォルト)のままにします。 |
GetCoverageSummary
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
summaryJsonPath | string | はい | 生成された Summary.json ファイルへのフルパス |
belowTarget | double | いいえ | 設定すると([0,1] の範囲の小数。例:0.8)、行カバレッジまたは分岐カバレッジのいずれかがこのしきい値を下回るクラスのみを返します。すべてのクラスを対象にする場合は省略します。 |
topN | int | いいえ | 分岐カバレッジが最も低い N 個のクラスのみを返します(結果は低い順に並べられます)。すべてのクラスを対象にする場合は省略します。 |
methodsPerClass | int | いいえ | クラスごとに分岐カバレッジが最も低いメソッドをこの数まで残し、それ以外を除外します。すべてのメソッドを残す場合は省略します。 |
GetFileCoverage
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
coberturaXmlPath | string | はい | coverage.cobertura.xml へのパス(見つからない場合は .mcp-coverage/.coverage-state にフォールバックします) |
sourceFileName | string | はい | 検索するソースファイル名(例:ExampleService.cs) |
sessionId | string | いいえ | 並行実行時に分離するため、セッションスコープの状態ファイルを解決します。 |
targetRate | double | いいえ | allMeetTarget の算出に使用するカバレッジのしきい値(0.0~1.0)。デフォルトは 0.8 です。 |
GetUncoveredBranches
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
coberturaXmlPath | string | はい | coverage.cobertura.xml へのパス(見つからない場合は .mcp-coverage/.coverage-state にフォールバックします) |
methodName | string | はい | 調査するメソッド名(一部一致をサポート。該当するすべてのメソッドを返します) |
sessionId | string | いいえ | 並行実行時に分離するため、セッションスコープの状態ファイルを解決します。 |
GetCoverageDiff
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
coberturaXmlPath | string | はい | 現在の coverage.cobertura.xml へのパス |
workingDir | string | いいえ | ベースラインを保存するディレクトリ。デフォルトは XML の親ディレクトリです |
sessionId | string | いいえ | ベースラインを .coverage-prev-{hash}.xml として分離し、セッション単位の状態ファイルを解決します。 |
AppendTestCode
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
testFilePath | string | はい | 対象の .cs テストファイルへのフルパス |
codeToAppend | string | はい | 挿入する C# コード |
insertAfterAnchor | string | いいえ | 指定すると、この文字列の最後の出現箇所の後にコードを挿入します(空白を許容するフォールバックあり)。省略すると、最後の } の前に追加します。 |
CleanupSession
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
workingDir | string | はい | .mcp-coverage/ と TestResults の成果物を含む、プロジェクトの作業ディレクトリ |
sessionId | string | いいえ | 設定すると、このセッションに紐づく状態ファイルとディレクトリのみを削除します。 |
maxAgeMinutes | int | いいえ | sessionId が省略された場合、この分数より古い成果物を削除します。デフォルトは 120 です。 |
状態ファイル
すべての状態ファイルは、プロジェクトのルートを整理された状態に保つため、作業ディレクトリ内の .mcp-coverage/ サブディレクトリに書き込まれます。対象リポジトリの .gitignore に .mcp-coverage/ を追加してください。
| ファイル | 用途 |
|---|---|
.coverage-state | 単一エージェントで使用するデフォルトの Cobertura XML パス |
.coverage-state-{hash} | セッション単位の Cobertura XML パス |
.coverage-prev.xml | 差分比較用のデフォルトのカバレッジベースライン |
.coverage-prev-{hash}.xml | セッション単位のカバレッジベースライン |
プラグイン(スキルとエージェント)
このリポジトリには plugin/ ディレクトリが含まれており、テストカバレッジのワークフローをガイドする Claude Code のスキルとエージェント定義が用意されています。
plugin/
├── plugin.json
├── agents/
│ └── test-coverage.agent.md
└── skills/
├── scaffold-test-files/ — Create test directories and files mirroring source structure
├── run-coverage/ — Run tests and view coverage reports
├── analyze-coverage-gaps/ — Find uncovered branches and compare diffs
└── improve-test-coverage/ — Iterative loop to reach 80% coverage
スキルは NUnit、xUnit、MSTest に対応しており、フレームワークに依存しないリファレンスドキュメントが references/unit.md と references/integration.md にあります。
依存関係
| パッケージ | バージョン | 用途 |
|---|---|---|
Microsoft.Extensions.Hosting | 10.0.7 | DI とホスティング |
ModelContextProtocol | 1.2.0 | MCP サーバーのフレームワーク |
Microsoft.CodeAnalysis.CSharp | 5.3.0 | 安全なコード挿入と正確なメソッド数のカウントに使用する Roslyn AST(約15MB) |
セキュリティ
dotnet-coverage-mcp はローカルの stdio プロセスとして実行され、すべてのツール引数を COVERAGE_MCP_ALLOWED_ROOT に照らして検証し、ファイルシステムへのアクセスを制限します。脅威モデル、セキュリティ強化の推奨事項、脆弱性の報告方法については、SECURITY.md を参照してください。
貢献
貢献を歓迎します。開発環境のセットアップ、プルリクエストのガイドライン、コード規約については、CONTRIBUTING.md を参照してください。主な変更は CHANGELOG.md に記録されています。
リリース
メンテナー専用です。リリース手順、NuGet への公開、MCP レジストリへの登録については、RELEASING.md に記載されています。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。