Forge
csharp5e452b8e
1using System.Text.Json;
2using ModelContextProtocol.Protocol;
3using Tool = ModelContextProtocol.Protocol.Tool;
4
5namespace DotnetDebugMcp;
6
7/// <summary>Каталог MCP-тулов. Согласован с <c>mcp-tools.manifest.json</c> и <c>docs/MCP-TOOLS.md</c> (генерация: <c>tools/ExportMcpManifest</c>).</summary>
8internal static class ToolCatalog
9{
10 private static JsonElement Schema(object schema) => JsonSerializer.SerializeToElement(schema);
11
12 private static readonly string[] RequiredFileLine = ["file_path", "line"];
13 private static readonly string[] RequiredWorkspace = ["workspace_path"];
14 private static readonly string[] RequiredWorkspaceTarget = ["workspace_path", "target_path"];
15 private static readonly string[] RequiredWorkspaceTargetBreakpoints = ["workspace_path", "target_path", "breakpoints"];
16
17 internal static List<Tool> Build()
18 {
19 var emptySchema = Schema(new { type = "object", properties = new { } });
20
21 return
22 [
23 new()
24 {
25 Name = "debug_ping",
26 Description = "Проверка доступности сервера отладки. Возвращает текущее время и статус.",
27 InputSchema = emptySchema
28 },
29 new()
30 {
31 Name = "debug_set_breakpoints",
32 Description =
33 "Записать брейкпоинты для целевого проекта/exe. Файл .dotnet-debug-mcp-breakpoints.json в каталоге workspace_path. Дальше: передача в DAP при debug_launch.",
34 InputSchema = Schema(new
35 {
36 type = "object",
37 properties = new
38 {
39 workspace_path = new { type = "string", description = "Каталог проекта/решения (здесь создаётся файл с брейкпоинтами)." },
40 target_path = new { type = "string", description = "Путь к .csproj или exe — ключ для списка брейкпоинтов (при launch будем использовать этот target)." },
41 breakpoints = new
42 {
43 type = "array",
44 description = "Список брейкпоинтов: file_path, line (1-based), condition (опционально).",
45 items = new
46 {
47 type = "object",
48 properties = new
49 {
50 file_path = new { type = "string" },
51 line = new { type = "integer" },
52 condition = new { type = "string" }
53 },
54 required = RequiredFileLine
55 }
56 }
57 },
58 required = RequiredWorkspaceTargetBreakpoints
59 })
60 },
61 new()
62 {
63 Name = "debug_list_breakpoints",
64 Description =
65 "Показать сохранённые брейкпоинты. По умолчанию — все цели в workspace; можно указать target_path.",
66 InputSchema = Schema(new
67 {
68 type = "object",
69 properties = new
70 {
71 workspace_path = new { type = "string", description = "Каталог, где лежит .dotnet-debug-mcp-breakpoints.json." },
72 target_path = new { type = "string", description = "Опционально. Путь к .csproj или exe — только брейкпоинты этой цели." }
73 },
74 required = RequiredWorkspace
75 })
76 },
77 new()
78 {
79 Name = "debug_clear_breakpoints",
80 Description =
81 "Удалить сохранённые брейкпоинты: для одной цели (target_path) или для всего workspace.",
82 InputSchema = Schema(new
83 {
84 type = "object",
85 properties = new
86 {
87 workspace_path = new { type = "string", description = "Каталог с файлом брейкпоинтов." },
88 target_path = new { type = "string", description = "Опционально. Очистить только эту цель; без указания — очистить все." }
89 },
90 required = RequiredWorkspace
91 })
92 },
93 new()
94 {
95 Name = "debug_launch",
96 Description =
97 "Запустить отладку через netcoredbg (DAP): загрузить сохранённые брейкпоинты для target, запустить программу под отладчиком. Требуется установленный netcoredbg (путь в netcoredbg_path или переменная NETCOREDBG_PATH).",
98 InputSchema = Schema(new
99 {
100 type = "object",
101 properties = new
102 {
103 workspace_path = new { type = "string", description = "Каталог с .dotnet-debug-mcp-breakpoints.json." },
104 target_path = new { type = "string", description = "Путь к .dll или .exe для запуска под отладчиком (тот же ключ, что при debug_set_breakpoints)." },
105 netcoredbg_path = new { type = "string", description = "Опционально. Путь к netcoredbg. По умолчанию: переменная NETCOREDBG_PATH или \"netcoredbg\" из PATH." },
106 program_args = new { type = "array", description = "Опционально. Аргументы командной строки для целевой программы (массив строк).", items = new { type = "string" } }
107 },
108 required = RequiredWorkspaceTarget
109 })
110 },
111 new()
112 {
113 Name = "debug_attach",
114 Description =
115 "Подключиться к уже запущенному .NET-процессу по PID (DAP attach). Опционально target_path — загрузить сохранённые брейкпоинты для этого target.",
116 InputSchema = Schema(new
117 {
118 type = "object",
119 properties = new
120 {
121 workspace_path = new { type = "string", description = "Каталог с .dotnet-debug-mcp-breakpoints.json (нужен при указании target_path)." },
122 process_id = new { type = "integer", description = "PID процесса .NET, к которому подключаемся." },
123 target_path = new { type = "string", description = "Опционально. Путь к .dll/.exe целевого процесса — для загрузки брейкпоинтов из JSON (тот же ключ, что при set_breakpoints)." },
124 netcoredbg_path = new { type = "string", description = "Опционально. Путь к netcoredbg." }
125 },
126 required = new[] { "workspace_path", "process_id" }
127 })
128 },
129 new()
130 {
131 Name = "debug_continue",
132 Description =
133 "Продолжить выполнение после остановки на брейкпоинте (DAP continue). Требуется активная сессия после debug_launch.",
134 InputSchema = emptySchema
135 },
136 new()
137 {
138 Name = "debug_step_over",
139 Description =
140 "Шаг через текущую строку (DAP next). Вызывать только когда выполнение уже остановлено на брейкпоинте (после события stopped). Требуется активная сессия после debug_launch.",
141 InputSchema = emptySchema
142 },
143 new()
144 {
145 Name = "debug_step_into",
146 Description = "Шаг в (DAP stepIn): зайти в вызов. Только при остановке на брейкпоинте. Требуется активная сессия.",
147 InputSchema = emptySchema
148 },
149 new()
150 {
151 Name = "debug_step_out",
152 Description =
153 "Шаг из (DAP stepOut): выйти из текущего кадра. Только при остановке на брейкпоинте. Требуется активная сессия.",
154 InputSchema = emptySchema
155 },
156 new()
157 {
158 Name = "debug_stop",
159 Description =
160 "Завершить текущую отладочную сессию (dispose DAP-клиент, освободить ресурсы). После вызова нужен новый debug_launch для отладки.",
161 InputSchema = emptySchema
162 },
163 new()
164 {
165 Name = "debug_stack_trace",
166 Description =
167 "Стек вызовов текущего потока (DAP stackTrace). Вызывать когда выполнение остановлено на брейкпоинте. Возвращает кадры: имя, файл, строка. Опционально frame_index для debug_variables.",
168 InputSchema = emptySchema
169 },
170 new()
171 {
172 Name = "debug_variables",
173 Description =
174 "Переменные кадра (DAP variables). Когда остановлены. frame_index (0 = верхний) по debug_stack_trace. Для тяжёлых кадров: fast=true, format=json, малый max_depth, затем дети через debug_variable_children. Лимиты: max_depth (0..32, по умол. 4; fast=true => 0), max_children_per_node (1..256, по умол. 48; fast=true => 24), time_budget_ms (100..10000; по умол. 1800, fast=true => 700). При тайм-бюджете ответ помечается partial.",
175 InputSchema = Schema(new
176 {
177 type = "object",
178 properties = new
179 {
180 frame_index = new { type = "integer", description = "Индекс кадра (0 = верхний). По умолчанию 0." },
181 fast = new { type = "boolean", description = "Быстрый режим (по умолчанию false): max_depth=0 и max_children_per_node=24, если явно не заданы." },
182 time_budget_ms = new { type = "integer", description = "Бюджет времени на раскрытие переменных, 100..10000 мс (по умол. 1800; fast=true => 700)." },
183 max_depth = new { type = "integer", description = "Глубина раскрытия по variablesReference, 0..32, по умол. 4 (или 0 в fast=true)." },
184 max_children_per_node = new { type = "integer", description = "Макс. детей на узел, 1..256, по умол. 48 (или 24 в fast=true)." },
185 format = new { type = "string", description = "text (по умол.) или json — дерево с полями name, value, type, variablesReference, children." },
186 json_indented = new { type = "boolean", description = "Для format=json: многострочный JSON, по умол. true." }
187 },
188 required = Array.Empty<string>()
189 })
190 },
191 new()
192 {
193 Name = "debug_variable_children",
194 Description =
195 "Один уровень вложенных переменных по variablesReference (из JSON debug_variables: не рекурсия). Снижает объём ответа. Подсказки indexed_variables / named_variables с родителя; max_children; json_indented.",
196 InputSchema = Schema(new
197 {
198 type = "object",
199 properties = new
200 {
201 variables_reference = new { type = "integer", description = "Ненулевой ref из DAP (поле variablesReference у родителя)." },
202 named_variables = new { type = "integer", description = "Опционально. Подсказка namedVariables родителя для fallback DAP." },
203 indexed_variables = new { type = "integer", description = "Опционально. Подсказка indexedVariables родителя (массивы)." },
204 max_children = new { type = "integer", description = "Макс. число детей, 1..256, по умол. 64." },
205 json_indented = new { type = "boolean", description = "По умол. true." }
206 },
207 required = new[] { "variables_reference" }
208 })
209 }
210 ];
211 }
212}
213
View only · write via MCP/CIDE