Skip to main content
Glama
Hyeonu-Cha
by Hyeonu-Cha

dotnet-coverage-mcp

build tests NuGet License: MIT

MCP-сервер (Model Context Protocol), который предоставляет AI-ассистентам — Claude Code, Gemini CLI и другим — прямой доступ к инструментам покрытия .NET-тестов. Запускайте dotnet test, разбирайте Cobertura XML, находите непокрытые ветви, сравнивайте покрытие между запусками и добавляйте тестовый код — всё через stdio.

Назначение

Этот сервер позволяет AI-ассистенту запускать модульные тесты, собирать данные о покрытии и анализировать результаты — не выходя из чата. Вместо ручного запуска dotnet test и разбора отчётов AI может напрямую вызывать инструменты сервера, чтобы:

  • Находить исходные файлы и формировать умные пакеты по бюджету строк

  • Запускать отфильтрованный набор тестов и собирать покрытие

  • Читать компактные сводки покрытия, оптимизированные для AI (показатели строк и ветвей на уровне методов)

  • Проверять покрытие по каждому файлу относительно настраиваемой целевой нормы (по умолчанию 80%)

  • Выявлять непокрытые ветви в виде структурированного JSON

  • Сравнивать покрытие между запусками, чтобы видеть только изменения

  • Добавлять новый тестовый код в существующий файл тестов с атомарной записью

Related MCP server: codecov-mcp-server

Как это работает

Сервер запускается как консольный процесс и общается через stdio по протоколу MCP. MCP-совместимый клиент (Claude Code, Gemini CLI и т. д.) запускает процесс и вызывает его инструменты, как если бы это были функции.

AI Client  <--stdio/MCP-->  dotnet-coverage-mcp  <--shell-->  dotnet test + reportgenerator

Доступные инструменты

Tool

Description

GetSourceFiles

Находит .cs-файлы в файле, папке или проекте .csproj. Возвращает метаданные файлов (строки, количество методов) и умные пакеты, сгруппированные по lineBudget.

RunTestsWithCoverage

Запускает dotnet test с XPlat Code Coverage и создаёт JSON-сводку через reportgenerator. Возвращает пути к Summary.json и coverage.cobertura.xml. Поддерживает forceRestore и sessionId для изоляции параллельных сессий.

GetCoverageSummary

Разбирает Summary.json в структурированные данные о покрытии классов/методов, отсортированные от худшего к лучшему по покрытию ветвей. Необязательные фильтры belowTarget/topN/methodsPerClass сокращают ответ до того, что ещё нужно доработать.

GetFileCoverage

Получает покрытие одного исходного файла из Cobertura XML. Возвращает allMeetTarget (true, когда все классы соответствуют заданному targetRate и по строкам, и по ветвям; по умолчанию 0.8). Поддерживает sessionId.

GetUncoveredBranches

Находит условия непокрытых ветвей для методов, соответствующих заданному имени. Возвращает все подходящие методы с поддержкой частичного совпадения имён. Поддерживает sessionId.

GetCoverageDiff

Сравнивает текущий Cobertura XML с базовым. Показывает изменения на уровне методов, включая новые и удалённые методы. Поддерживает sessionId для изоляции параллельных сессий.

AppendTestCode

Вставляет или добавляет C#-тестовый код в файл тестов. Поддерживает вставку по якорю с резервным сопоставлением, устойчивым к пробелам. Использует атомарную запись для предотвращения повреждения файла.

CleanupSession

Удаляет файлы состояния сессии и каталоги TestResults/coveragereport. Укажите sessionId для ограничения области, либо опустите его, чтобы очистить артефакты старше maxAgeMinutes (по умолчанию 120).

Пакетный рабочий процесс

Для проектов с большим количеством исходных файлов рекомендуется следующий порядок действий:

  1. Обнаружение — вызовите GetSourceFiles для папки или .csproj, чтобы получить все файлы и умные пакеты

  2. Один запуск — вызовите RunTestsWithCoverage с широким фильтром (например, *), чтобы собрать покрытие по всем файлам

  3. Проверка по файлам — вызовите GetFileCoverage для каждого файла в текущем пакете (мгновенный разбор XML, без повторного запуска тестов)

  4. Фокус — выберите 3 метода с самым низким покрытием ветвей и вызовите GetUncoveredBranches для каждого

  5. Написание тестов — используйте AppendTestCode для добавления тестовых методов

  6. Повторный запуск и сравнение — запустите тесты один раз и вызовите GetCoverageDiff, чтобы убедиться в улучшении

  7. Повторение — продолжайте, пока файлы пакета не достигнут целевой нормы (по умолчанию 80%) или не пройдут 3 цикла без улучшений, затем переходите к следующему пакету

Это сводит к минимуму количество вызовов dotnet test (основное узкое место), продолжая отслеживать прогресс по каждому файлу.

Параллельность

Несколько AI-агентов могут работать параллельно, передавая sessionId в каждый вызов инструмента, что изолирует их артефакты покрытия:

  • Изолированные выходные каталогиRunTestsWithCoverage создаёт TestResults-{hash}/ и coveragereport-{hash}/ для каждой сессии, не позволяя одному агенту удалять XML другого во время разбора

  • Изолированные файлы состояния — состояние покрытия записывается в .mcp-coverage/.coverage-state-{hash}, поэтому ResolveCoberturaPath определяет правильный XML для каждой сессии

  • Изолированные базовые линииGetCoverageDiff сохраняет базовые линии как .coverage-prev-{hash}.xml для каждой сессии

  • Атомарные записи — все файловые записи (файлы состояния и тестовый код) используют запись во временный файл с последующим переименованием, чтобы предотвратить повреждение из-за гонок или сбоев процесса

Ограничение — результаты сборки не привязаны к сессии. sessionId изолирует артефакты покрытия, но не сборку .NET. dotnet test компилирует целевой проект в общие каталоги obj/ и bin/, которые не являются персессионными, поэтому два агента, одновременно выполняющие RunTestsWithCoverage для одного и того же тестового проекта, сталкиваются при записи в эти выходные данные и завершаются с buildError (например, CS2012: the file is being used by another process). Запускайте параллельных агентов для разных тестовых проектов или в отдельных рабочих копиях репозитория. Несколько агентов в одном проекте допустимы, если их сборки 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

Установка

Установите сервер как глобальный инструмент .NET из NuGet:

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-сообщений через stdin/stdout.

Настройка 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

Parameter

Type

Required

Description

path

string

Да

Путь к .cs-файлу, папке или проекту .csproj

lineBudget

int

Нет

Максимальное суммарное количество строк в пакете (по умолчанию: 300). Небольшие файлы группируются вместе; большие файлы получают собственный пакет.

RunTestsWithCoverage

Parameter

Type

Required

Description

testProjectPath

string

Yes

Полный путь к тестовому проекту .csproj

filter

string

Yes

Строка фильтра тестов (сопоставляется с FullyQualifiedName). Используйте * или , для широких запусков по нескольким тестовым классам.

workingDir

string

No

Рабочий каталог; по умолчанию — каталог проекта

forceRestore

bool

No

Если true, пропускает флаг --no-restore. Используйте после создания нового тестового проекта или добавления пакетов NuGet.

sessionId

string

No

Изолирует выходные каталоги (TestResults-{hash}/, coveragereport-{hash}/) и файлы состояния для параллельного использования несколькими агентами.

includeClass

string

No

Ограничивает сбор покрытия типами, соответствующими этому имени (фильтр coverlet Include, применяется через сгенерированный файл runsettings, передаваемый с --settings). Не зависит от filter — передайте явное значение, чтобы ограничить покрытие; опустите его, чтобы собрать покрытие для всего, что затрагивает запуск. Имена с указанием пространства имён не поддерживаются.

skipReport

bool

No

Если true, пропускает шаг JSON-сводки reportgenerator и возвращает только путь к XML Cobertura. Быстрее для внутреннего цикла тестирования, где GetFileCoverage/GetUncoveredBranches/GetCoverageDiff читают XML напрямую. Оставьте false (по умолчанию), когда нужен Summary.json от GetCoverageSummary.

GetCoverageSummary

Parameter

Type

Required

Description

summaryJsonPath

string

Yes

Полный путь к сгенерированному файлу Summary.json

belowTarget

double

No

Если задано (доля в [0,1], например 0.8), возвращает только классы, чьё покрытие строк ИЛИ ветвей ниже этого порога. Опустите для всех классов.

topN

int

No

Возвращает только N классов с наименьшим покрытием ветвей (результаты отсортированы от худших к лучшим). Опустите для всех классов.

methodsPerClass

int

No

Оставляет не более этого количества методов с наименьшим покрытием ветвей на класс, отбрасывая остальные. Опустите, чтобы сохранить все методы.

GetFileCoverage

Parameter

Type

Required

Description

coberturaXmlPath

string

Yes

Путь к coverage.cobertura.xml (если не найден, используется .mcp-coverage/.coverage-state)

sourceFileName

string

Yes

Имя исходного файла для поиска (например, ExampleService.cs)

sessionId

string

No

Разрешает файл состояния, привязанный к сессии, для параллельной изоляции.

targetRate

double

No

Порог покрытия (0.0–1.0), используемый для вычисления allMeetTarget. По умолчанию 0.8.

GetUncoveredBranches

Parameter

Type

Required

Description

coberturaXmlPath

string

Yes

Путь к coverage.cobertura.xml (если не найден, используется .mcp-coverage/.coverage-state)

methodName

string

Yes

Имя метода для проверки (поддерживается частичное совпадение; возвращаются все подходящие методы)

sessionId

string

No

Разрешает файл состояния, привязанный к сессии, для параллельной изоляции.

GetCoverageDiff

Parameter

Type

Required

Description

coberturaXmlPath

string

Yes

Путь к текущему coverage.cobertura.xml

workingDir

string

No

Каталог для хранения базовой линии; по умолчанию — родительский каталог XML

sessionId

string

No

Изолирует базовую линию как .coverage-prev-{hash}.xml и разрешает файл состояния, привязанный к сессии.

AppendTestCode

Parameter

Type

Required

Description

testFilePath

string

Yes

Полный путь к целевому тестовому файлу .cs

codeToAppend

string

Yes

Код C# для вставки

insertAfterAnchor

string

No

Если указано, вставляет код после последнего вхождения этой строки (с запасным вариантом, допускающим пробелы). Если опущено, добавляет перед последней }.

CleanupSession

Parameter

Type

Required

Description

workingDir

string

Yes

Рабочий каталог проекта, содержащий .mcp-coverage/ и артефакты TestResults

sessionId

string

No

Если задано, удаляет только файлы состояния и каталоги, привязанные к этой сессии.

maxAgeMinutes

int

No

Если sessionId опущен, удаляет артефакты старше этого числа минут. По умолчанию 120.

Файлы состояния

Все файлы состояния записываются в подкаталог .mcp-coverage/ внутри рабочего каталога, сохраняя корень проекта чистым. Добавьте .mcp-coverage/ в .gitignore целевого репозитория.

File

Purpose

.coverage-state

Путь к XML Cobertura по умолчанию для использования одним агентом

.coverage-state-{hash}

Путь к XML Cobertura, привязанный к сессии

.coverage-prev.xml

Базовая линия покрытия по умолчанию для diff

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

Зависимости

Package

Version

Purpose

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 для настройки разработки, правил pull request и соглашений по коду. Заметные изменения отслеживаются в CHANGELOG.md.

Выпуск

Только для сопровождающих — процесс выпуска, публикация в NuGet и отправка в реестр MCP описаны в RELEASING.md.

A
license - permissive license
Not graded
quality - not tested
A
maintenance

Maintenance

Maintainers
12hResponse time
5wRelease cycle
3Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

View all related MCP servers

Related MCP Connectors

  • A comprehensive Model Context Protocol (MCP) server that enables AI assistants to interact with yo…

  • MCP server for AI access to SmartBear tools, including BugSnag, Reflect, Swagger, PactFlow, QTM4J.

  • MCP server for AI agents to plan, verify, and deploy Cloudflare-native apps.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Hyeonu-Cha/dotnet-coverage-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server