Forge
markdown551a3611
1# RoslynMcp
2
3MCP-сервер для помощи агенту при рефакторинге C#: доступ к **Roslyn** (синтаксические деревья, семантика, символы, find usages, rename, code actions). Цель — стабильный тул без глюков (альтернатива Bifrost).
4
5**Cursor:** примеры `.cursor/rules` для копипаста — **[docs/cursor-rules-examples.md](docs/cursor-rules-examples.md)**.
6
7**Текущий статус:** работают `roslyn_ping`, `roslyn_get_document_symbols`, `roslyn_get_symbol_at_position`, `roslyn_find_usages`, `roslyn_go_to_definition`, `roslyn_rename`, `roslyn_get_code_actions`, `roslyn_apply_code_action`, `roslyn_get_diagnostics`, `roslyn_get_workspace_navigation_context` (эвристики «связанных файлов» по MSBuild solution; не эквивалентно дереву файлов Cascade IDE — см. описание тула).
8
9## MSBuild workspace
10
11### Семантическая навигация (`roslyn_get_workspace_navigation_context`)
12
13Источник файлов — документы, которые поднимает **MSBuildWorkspace** по переданному `.sln`/`.csproj`, а не произвольное дерево из IDE. Встроенные пресеты (`peers_only`, `no_namespace_noise`, `tests_and_peers`, `structure_only`) задаются аргументом `preset` или своими `include_kinds` / `exclude_kinds`.
14
15### Свойство `RoslynMcpWorkspace` и блокировка DLL анализаторов при `dotnet build`
16
17RoslynMcp всегда передаёт в MSBuild свойство **`RoslynMcpWorkspace=true`** вместе с отключением design-only сборки (см. `ServiceLayer/RoslynMcpWorkspaceProperties.cs`). Это **не привязка к конкретному репозиторию**: любой `.csproj` может при желании проверять `$(RoslynMcpWorkspace)` и, например, **не подключать** `ProjectReference` на локальный проект Roslyn-анализатора (`OutputItemType="Analyzer"`), пока workspace открыт через MCP.
18
19Зачем: процесс RoslynMcp иначе может держать загруженной ту же сборку в `bin\…`, которую `dotnet build` затем перезаписывает — на Windows это даёт «file is being used by another process». Отключение такой ссылки **только при** `RoslynMcpWorkspace=true` оставляет обычные сборки и CI без этого флага с полным набором анализаторов; детали опт-in — в документации **того** решения, где условие добавлено.
20
21### Source generators (MVVM Toolkit и др.)
22
23Для проектов с **source generators** (например `[ObservableProperty]` / `[RelayCommand]` в CommunityToolkit.Mvvm) `roslyn_get_diagnostics` поднимает сгенерированные документы через **`GetSourceGeneratedDocumentsAsync`** и берёт проект и компиляцию из актуального **`workspace.CurrentSolution`** — см. **`ServiceLayer/GetDiagnostics.cs`**. Глобальные свойства MSBuild те же, что для остальных вызовов `MSBuildWorkspace` в этом сервере (**`RoslynMcpWorkspaceProperties`**).
24
25Раньше без такого конвейёра при зелёном **`dotnet build`** возможны были ложные **CS1061**; в текущей реализации это учтено. Если вывод инструмента всё же расходится со сборкой, ориентир — **`dotnet build`**. Подробнее — **[docs/source-generators-and-diagnostics.md](docs/source-generators-and-diagnostics.md)**.
26
27## Требования
28
29- .NET 10
30
31## Сборка
32
33```bash
34cd roslyn-mcp
35dotnet build
36dotnet run
37```
38
39Полный перечень имён и описаний (как у инструментов в MCP) — **[docs/MCP-TOOLS.md](docs/MCP-TOOLS.md)**. Тот же источник даёт `mcp-tools.manifest.json` в корне проекта. Обновить оба файла из кода:
40
41`dotnet run --project tools/ExportMcpManifest -- --write` (рабочий каталог — корень `roslyn-mcp`).
42
43## Публикация exe (для MCP в Cursor)
44
45Чтобы Cursor запускал MCP из **exe**, а не из проекта, сборка не будет блокироваться запущенным процессом.
46
47### Быстрый локальный publish (рекомендуется)
48
49В репозитории есть `publish-and-deploy.ps1`: он прогоняет генерацию `mcp-tools.manifest.json` / `docs/MCP-TOOLS.md`, публикует self-contained `win-x64`, зеркалит в фиксированный путь (по умолчанию `D:\roslyn-mcp`) и гасит процесс, если он лочит файлы. Скрипт проверяет наличие **`BuildHost-netcore\Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.dll`** рядом с `RoslynMcp.exe` — без этой папки MSBuildWorkspace в Cursor падает с *«build host could not be found»*.
50
51```powershell
52.\publish-and-deploy.ps1
53# Если в mcp.json указан другой каталог (например D:\RoslynMcp):
54.\publish-and-deploy.ps1 -Target "D:\RoslynMcp"
55```
56
57### Релизы (zip + GitLab upload)
58
59`scripts/publish-release-win.ps1` — это отдельный сценарий: мультиплатформа (win/linux/osx), упаковка в zip и загрузка в GitLab Generic Packages/Release.
60
61В **csproj** заданы `RuntimeIdentifiers` (в т.ч. `win-x64`) и `SelfContained=true` — самодостаточная сборка (рантайм в папке, не зависит от установленного .NET в системе). Достаточно:
62
63```bash
64cd roslyn-mcp
65dotnet publish -c Release -r win-x64 -o publish
66```
67
68Exe появится в `roslyn-mcp/publish/RoslynMcp.exe`. В конфиге MCP в Cursor укажи этот exe (command — полный путь к нему, args — `[]`).
69
70Обновить exe после правок: снова выполни ту же команду publish, затем перезапусти MCP или Cursor.
71
72## VS Code + Claude Code
73
74Сервер работает по **stdio**. Подключение через [Claude Code](https://code.claude.com/docs/en/mcp) (VS Code с расширением Claude).
75
76**Требования:** .NET 10 (или собранный exe), установленный [Claude Code CLI](https://docs.anthropic.com/en/docs/build-with-claude/claude-code).
77
78### Вариант 1: через exe (рекомендуется)
79
80Собери exe (см. «Публикация exe» выше), затем добавь MCP:
81
82```bash
83claude mcp add --transport stdio roslyn -- C:\path\to\roslyn-mcp\publish\RoslynMcp.exe
84```
85
86На macOS/Linux подставь свой путь к exe, например `~/projects/roslyn-mcp/publish/RoslynMcp`.
87
88### Вариант 2: через dotnet run (из папки проекта)
89
90Если не собираешь exe, можно запускать из папки репо:
91
92```bash
93cd /path/to/roslyn-mcp
94claude mcp add --transport stdio roslyn -- dotnet run --project .
95```
96
97(При первом запуске Claude Code выполнит `dotnet run --project .` в текущей папке — открой проект так, чтобы текущим каталогом была папка `roslyn-mcp`, или укажи полный путь: `dotnet run --project /path/to/roslyn-mcp/RoslynMcp.csproj`.)
98
99### Общий конфиг в проекте (.mcp.json)
100
101Чтобы все в команде использовали один и тот же MCP, положи в корень C#-проекта файл `.mcp.json`:
102
103```json
104{
105 "mcpServers": {
106 "roslyn": {
107 "type": "stdio",
108 "command": "C:\\path\\to\\roslyn-mcp\\publish\\RoslynMcp.exe",
109 "args": []
110 }
111 }
112}
113```
114
115Путь к `command` каждый подставляет свой (или используй переменные окружения, если Claude Code их поддерживает в `.mcp.json`). После сохранения Claude Code предложит доверять серверу; в чате можно проверить статус командой `/mcp`.
116
117## Стиль кода и .editorconfig
118
119Генераторы кода (конструктор, override, интерфейс, базовый класс) учитывают **.editorconfig** в каталоге файла и выше (ближайший к файлу переопределяет). Учитываются опции в `[*.cs]`:
120
121- **Типы:** `dotnet_style_predefined_type_for_locals_parameters_members`, `dotnet_style_predefined_type_for_member_access` — ключевые слова C# (`int`, `string`, …) vs .NET (`Int32`, `String`).
122- **Отступы:** `indent_style`, `indent_size`, `tab_width` — при вставке в файл используется отступ из файла, при его отсутствии — из .editorconfig.
123- **var:** `csharp_style_var_for_built_in_types`, `csharp_style_var_when_type_is_apparent`, `csharp_style_var_elsewhere` — зарезервировано для будущего использования в генерируемом коде.
124- **Скобки и переносы:** `csharp_prefer_braces`, `csharp_new_line_before_open_brace` — зарезервировано для форматирования блоков.
125
126В **Generate constructor** не добавляются backing-поля, если для них уже есть свойство (например `_source` при наличии `Source`).
127
128**Сам проект RoslynMcp** имеет свой `.editorconfig` в корне: стиль (indent, типы, var, скобки) и **severities анализаторов** (IDE0049, IDE0055, CS0219, naming и т.д. — suggestion/warning/info/hidden/none). Сборка с `EnforceCodeStyleInBuild` и `AnalysisLevel` учитывает эти настройки.
129
130## Инструменты (tools)
131
132| Инструмент | Описание |
133|------------|----------|
134| `roslyn_ping` | Проверка доступности сервера. |
135| `roslyn_get_document_symbols` | Структура C# файла: namespace, class, method, property, field, enum, enum_member, delegate с номерами строк. Параметр: `file_path`. |
136| `roslyn_get_symbol_at_position` | Символ в позиции (файл + строка + столбец, 1-based): kind и имя. Опционально `solution_or_project_path` — тогда в ответе Qualified (полное имя). Параметры: `file_path`, `line`, `column`. |
137| `roslyn_find_usages` | Все ссылки на символ в solution/project. В выводе: квалифицированное имя (FullyQualifiedFormat), место определения (Definition:), затем список ссылок. Параметры: `solution_or_project_path`, `file_path`, `line`, `column` (на идентификаторе). |
138| `roslyn_go_to_definition` | Переход к определению символа: по позиции возвращает file:line:column объявления (для partial — несколько строк). Параметры: `solution_or_project_path`, `file_path`, `line`, `column`. |
139| `roslyn_rename` | Переименование символа по solution. Параметры: `solution_or_project_path`, `file_path`, `line`, `column`, `new_name`, опционально `apply` (превью/запись), `rename_in_comments`, `rename_in_strings`, `rename_overloads`, `rename_file` (аналог опций в VS), `rename_partial_type_files` (для топ-уровневого типа — переименовать все `TypeName.cs` / `TypeName.*.cs` в проекте под новое имя типа). |
140| `roslyn_get_code_actions` | Список Quick Actions / рефакторингов в позиции (как лампочка в VS). Параметры: `solution_or_project_path`, `file_path`, `line`, `column`. Опционально `end_line`, `end_column` — диапазон выделения для рефакторингов вроде Extract method / Extract local function. Возвращает нумерованный список. |
141| `roslyn_apply_code_action` | Применить выбранное code action. Параметры: `solution_or_project_path`, `file_path`, `line`, `column`, `action_index` (0-based). Опционально: `end_line`, `end_column` (тот же диапазон, что при get); `fix_all_scope`: `"document"` \| `"project"` \| `"solution"`; `constant_name` — для Introduce constant; `action_options` — JSON-объект опций для действий с диалогом (Extract interface, Extract base class: имена членов и т.д.). Подробнее: [REFACTORINGS.md](REFACTORINGS.md). |
142| `roslyn_get_diagnostics` | Диагностики компиляции и анализаторов по solution/project. Учитывается .editorconfig целевого проекта: исключаются диагностики с `dotnet_diagnostic.<Id>.severity = none` и уровень Hidden от анализаторов. Параметры: `solution_or_project_path`, опционально `file_path`. |
143| `roslyn_get_solution_structure` | Список проектов в solution (имя, путь к .csproj). Параметр: `solution_or_project_path` (.sln или .csproj). Для реп с только .slnx: передай путь к главному .csproj — вернётся список подгруженных проектов. |
144| `roslyn_generate_interface_from_class` | Сгенерировать C# интерфейс по классу **без диалогов** (обходной путь для Extract Interface). Позиция на класс: `solution_or_project_path`, `file_path`, `line`, `column`. Опционально: `interface_name`, `output_file_path`, `member_names` (массив). Дальше вручную или через code action добавь классу `: IName` и примени «Implement interface». |
145| `roslyn_generate_base_class_from_class` | Сгенерировать абстрактный базовый класс по классу **без диалогов** (обходной путь для Extract Base Class). Позиция на класс: `solution_or_project_path`, `file_path`, `line`, `column`. Опционально: `base_class_name`, `output_file_path`, `member_names` (массив). Дальше: добавить классу `: BaseName` и проставить `override` у членов. |
146| `roslyn_generate_overrides` | **Generate Overrides** без диалога: по позиции на класс генерирует override виртуальных/абстрактных членов базового типа. Опционально: `member_names` (массив), `insert_into_file` (true — вставить в тело класса). |
147| `roslyn_generate_constructor_from_members` | **Generate constructor** без диалога: по позиции на класс генерирует конструктор по instance полям и свойствам с set. Опционально: `member_names`, `insert_into_file`. |
148| `roslyn_generate_equals_gethashcode` | **Generate Equals and GetHashCode** без диалога: по позиции на класс генерирует override Equals/GetHashCode по выбранным полям/свойствам. Опционально: `member_names`, `insert_into_file`. |
149
150## Лицензия
151
152MIT License. См. [LICENSE](LICENSE).
153
View only · write via MCP/CIDE