| 1 | # Dotnet Build Test MCP |
| 2 | |
| 3 | MCP-сервер с тулами **build_structured**, **run_tests** и **publish_structured** (плюс **get_job_status**, **get_job_log**, **cancel_job**). Те же контракты, что в Cascade IDE (ide_build, ide_run_tests), но работают без IDE — в Cursor или любом хосте с MCP. Поддерживаются типичные флаги CLI: `configuration` (-c), `framework` (-f), `no_restore`, `no_build` (test/publish), `filter` (test), `output` (-o для publish), `additional_arguments`. |
| 4 | |
| 5 | ## Стек |
| 6 | |
| 7 | - C#, .NET 10, win-x64, self-contained. |
| 8 | - Библиотека **[AIGuiders.DotNetBuildTestParsers](https://www.nuget.org/packages/AIGuiders.DotNetBuildTestParsers)** — разбор вывода dotnet build и dotnet test ([репозиторий](https://github.com/KarataevDmitry/dotnet-build-test-parsers)). |
| 9 | |
| 10 | ## Публикация |
| 11 | |
| 12 | ```bash |
| 13 | dotnet publish -c Release -o publish |
| 14 | ``` |
| 15 | |
| 16 | Junction: например `D:\dotnet-build-test-mcp` → каталог `publish`; в Cursor в mcp.json указать `command`: `D:\dotnet-build-test-mcp\DotnetBuildTestMcp.exe`, `args`: `[]`. |
| 17 | |
| 18 | ### Быстрый локальный publish (рекомендуется) |
| 19 | |
| 20 | `publish-and-deploy.ps1` делает publish self-contained `win-x64`, зеркалит в фиксированный путь (по умолчанию `D:\dotnet-build-test-mcp`) и гасит процесс, если он лочит файлы: |
| 21 | |
| 22 | ```powershell |
| 23 | .\publish-and-deploy.ps1 |
| 24 | ``` |
| 25 | |
| 26 | ### Релизы (zip + GitLab upload) |
| 27 | |
| 28 | `scripts/publish-release-win.ps1` — мультиплатформенный сценарий (win/linux/osx): упаковка в zip и загрузка в GitLab Generic Packages/Release. |
| 29 | |
| 30 | ## Каталог тулов (автогенерация) |
| 31 | |
| 32 | Полные тексты `description` — в [`docs/MCP-TOOLS.md`](docs/MCP-TOOLS.md) (блок из `ToolCatalog` + примеры JSON из [`docs/MCP-TOOLS-appendix.md`](docs/MCP-TOOLS-appendix.md)); манифест — [`mcp-tools.manifest.json`](mcp-tools.manifest.json). Обновление: |
| 33 | |
| 34 | ```bash |
| 35 | dotnet run --project tools/ExportMcpManifest -- --write |
| 36 | ``` |
| 37 | |
| 38 | Примеры для агентов правь в `docs/MCP-TOOLS-appendix.md`, затем снова `--write`. |
| 39 | |
| 40 | ## Тулы |
| 41 | |
| 42 | | Имя | Описание | Аргументы | |
| 43 | | ----- | ---------- | ----------- | |
| 44 | | `build_structured` | Запустить `dotnet build` через single-flight очередь. Поддерживает sync/async режим и timeout. | `solution_path` (required), `wait_for_completion`, `include_raw_output`, `timeout_seconds` (default `600`), опционально `configuration`, `framework`, `no_restore`, `additional_arguments` | |
| 45 | | `run_tests` | Запустить `dotnet test` через single-flight очередь. | `solution_path` (required), те же базовые поля; опционально `configuration`, `framework`, `no_restore`, `no_build`, `filter`, `additional_arguments` | |
| 46 | | `publish_structured` | Запустить `dotnet publish`, разбор как у build. | `solution_path` (required), `output` (-o), `configuration`, `framework`, `no_restore`, `no_build`, `additional_arguments` | |
| 47 | | `get_job_status` | Вернуть статус job: `queued/running/done/failed/cancelled/timed_out` + итоговый result после завершения; в ответе поле `dotnet_options`. | `job_id` | |
| 48 | | `get_job_log` | Читать лог job чанками (offset/limit), чтобы не отдавать гигантский payload одним JSON. | `job_id`, `offset_lines` (default `0`), `limit_lines` (default `200`, max `2000`) | |
| 49 | | `cancel_job` | Отменить queued/running job. | `job_id` | |
| 50 | |
| 51 | ## Поведение очереди (single-flight) |
| 52 | |
| 53 | - Тяжёлые операции (`build_structured`, `run_tests`, `publish_structured`) выполняются **строго по одной**. |
| 54 | - Очередь bounded (`capacity=8`). |
| 55 | - При перегрузе возвращается компактный ответ: |
| 56 | - `accepted: false` |
| 57 | - `status: "busy"` |
| 58 | - `retry_after_seconds` |
| 59 | - По умолчанию heavy-тулы возвращают **summary**; полный `raw_output` только при `include_raw_output=true`. |
| 60 | |
| 61 | ## Примеры |
| 62 | |
| 63 | Синхронный build (дождаться завершения): |
| 64 | |
| 65 | ```json |
| 66 | { |
| 67 | "solution_path": "D:/repo/MyApp.sln" |
| 68 | } |
| 69 | ``` |
| 70 | |
| 71 | Асинхронный test + опрос статуса: |
| 72 | |
| 73 | ```json |
| 74 | { |
| 75 | "solution_path": "D:/repo/MyApp.sln", |
| 76 | "wait_for_completion": false, |
| 77 | "timeout_seconds": 1200 |
| 78 | } |
| 79 | ``` |
| 80 | |
| 81 | Далее: |
| 82 | |
| 83 | ```json |
| 84 | { |
| 85 | "job_id": "<id-from-run_tests>" |
| 86 | } |
| 87 | ``` |
| 88 | |
| 89 | для `get_job_status` и `get_job_log`. |
| 90 | |
| 91 | Формат ответа совпадает с ide_build и ide_run_tests в Cascade IDE — агент может использовать один и тот же разбор и с IDE, и без неё. |
| 92 | |
| 93 | ## Проверенные кейсы |
| 94 | |
| 95 | Поведение проверено в Cursor с тестовым решением; агент получает структурированный вывод без парсинга лога. |
| 96 | |
| 97 | | Кейс | Ожидание | Результат | |
| 98 | | ------ | ---------- | ----------- | |
| 99 | | `build_structured`, сборка успешна | success: true, errors: [], warnings: [] | ✓ | |
| 100 | | `build_structured`, ошибки компиляции | success: false, errors[] с file, line, column, code, message | ✓ | |
| 101 | | `run_tests`, все тесты прошли | success: true, failed_tests: [] | ✓ | |
| 102 | | `run_tests`, есть упавшие | success: false, failed_tests[] с name, message?, duration_ms? | ✓ | |
| 103 | | Параллельные heavy-вызовы | не падают, второй уходит в очередь/busy | ✓ | |
| 104 | | Большой лог | читается через `get_job_log` чанками | ✓ | |
| 105 | |