Forge
csharp9332cf7c
1using System.Text.Json;
2using ModelContextProtocol.Protocol;
3using Tool = ModelContextProtocol.Protocol.Tool;
4
5namespace HybridCodebaseIndex.Mcp;
6
7internal static class ToolCatalog
8{
9 private static JsonElement Schema(object schema) => JsonSerializer.SerializeToElement(schema);
10
11 private static readonly string[] RequiredWorkspace = ["workspace_path"];
12
13 internal static List<Tool> Build()
14 {
15 return
16 [
17 new Tool
18 {
19 Name = "codebase_index_version",
20 Description = "Версия MCP сервера: assembly version + informational version (commit), runtime.",
21 InputSchema = Schema(new
22 {
23 type = "object",
24 properties = new { },
25 }),
26 },
27 new Tool
28 {
29 Name = "codebase_index_search",
30 Description =
31 "Гибридный полнотекстовый поиск по индексу workspace (SQLite FTS5; архитектурное решение — ADR 0105 в CascadeIDE: docs/adr/0105-hybrid-codebase-index-for-csharp-web.md). hit_kind=text_fts. До reindex база может отсутствовать.",
32 InputSchema = Schema(new
33 {
34 type = "object",
35 properties = new
36 {
37 workspace_path = new { type = "string", description = "Корень workspace (решение/репозиторий)." },
38 solution_path = new { type = "string", description = "Опционально: путь к .sln/.slnx/.csproj (relative to workspace или absolute). Используется для области индекса: одна БД на (workspace_root, solution_path)." },
39 query = new { type = "string", description = "Поисковая строка (ключевые слова, AND по токенам)." },
40 top_n = new { type = "integer", description = "Максимум попаданий (по умолчанию 15)." },
41 semantic = new { type = "boolean", description = "Опционально: включить semantic (vec) канал, если он проиндексирован и semantic_enabled=true." },
42 alpha = new { type = "number", description = "Опционально: вес FTS канала при фьюжне (по умолчанию 0.65)." },
43 beta = new { type = "number", description = "Опционально: вес vec канала при фьюжне (по умолчанию 0.35)." },
44 vec_top_k = new { type = "integer", description = "Опционально: внутренний top-K по vec (по умолчанию 30)." },
45 path_prefix = new { type = "string", description = "Опционально: ограничить попадания путями, начинающимися с префикса (unix-style, например 'src/')." },
46 exclude_path_prefixes = new { type = "array", items = new { type = "string" }, description = "Опционально: исключить пути по префиксам (unix-style)." },
47 extensions = new { type = "array", items = new { type = "string" }, description = "Опционально: ограничить расширениями (например ['.md','.csproj'] или ['md','csproj'])." },
48 },
49 required = new[] { "workspace_path", "query" },
50 }),
51 },
52 new Tool
53 {
54 Name = "codebase_index_explain",
55 Description = "Explain для одного попадания (по hit_id из search): вернуть контекст чанка и метаданные.",
56 InputSchema = Schema(new
57 {
58 type = "object",
59 properties = new
60 {
61 workspace_path = new { type = "string", description = "Корень workspace." },
62 solution_path = new { type = "string", description = "Опционально: путь к .sln/.slnx/.csproj (relative to workspace или absolute). Должен совпадать со scope при search, иначе hit_id может не найтись." },
63 hit_id = new { type = "integer", description = "Идентификатор попадания (hitId из search)." },
64 },
65 required = new[] { "workspace_path", "hit_id" },
66 }),
67 },
68 new Tool
69 {
70 Name = "codebase_index_status",
71 Description = "Статус локального индекса: путь к SQLite, число документов, версия формата.",
72 InputSchema = Schema(new
73 {
74 type = "object",
75 properties = new
76 {
77 workspace_path = new { type = "string", description = "Корень workspace." },
78 solution_path = new { type = "string", description = "Опционально: путь к .sln/.slnx/.csproj (relative to workspace или absolute). Используется для области индекса: одна БД на (workspace_root, solution_path)." },
79 },
80 required = RequiredWorkspace,
81 }),
82 },
83 new Tool
84 {
85 Name = "codebase_index_reindex",
86 Description = "Перестройка индекса (FTS5). По умолчанию инкрементальная по файлам; full_rebuild=true — полная.",
87 InputSchema = Schema(new
88 {
89 type = "object",
90 properties = new
91 {
92 workspace_path = new { type = "string", description = "Корень workspace." },
93 solution_path = new { type = "string", description = "Опционально: путь к .sln/.slnx/.csproj (relative to workspace или absolute). Используется для области индекса: одна БД на (workspace_root, solution_path)." },
94 full_rebuild = new { type = "boolean", description = "Если true — полный rebuild вместо инкремента." },
95 },
96 required = RequiredWorkspace,
97 }),
98 },
99 new Tool
100 {
101 Name = "codebase_index_watch",
102 Description =
103 "Включить/выключить watcher для авто-инкрементальной индексации (debounced). Важно: это best-effort фоновая синхронизация, не заменяет явный reindex.",
104 InputSchema = Schema(new
105 {
106 type = "object",
107 properties = new
108 {
109 workspace_path = new { type = "string", description = "Корень workspace." },
110 solution_path = new { type = "string", description = "Опционально: путь к .sln/.slnx/.csproj (relative to workspace или absolute). Определяет область watcher (одна БД на (workspace_root, solution_path))." },
111 enabled = new { type = "boolean", description = "true — включить watcher, false — выключить." },
112 debounce_ms = new { type = "integer", description = "Опционально: debounce в миллисекундах (по умолчанию 750)." },
113 },
114 required = new[] { "workspace_path", "enabled" },
115 }),
116 },
117 new Tool
118 {
119 Name = "codebase_index_verify",
120 Description =
121 "Анти-галлюцинации: проверить список идентификаторов через индекс (FTS) и вернуть exists/missing + подсказки похожих (prefix search).",
122 InputSchema = Schema(new
123 {
124 type = "object",
125 properties = new
126 {
127 workspace_path = new { type = "string", description = "Корень workspace." },
128 solution_path = new { type = "string", description = "Опционально: путь к .sln/.slnx/.csproj (relative to workspace или absolute). Scope: одна БД на (workspace_root, solution_path)." },
129 identifiers = new { type = "array", items = new { type = "string" }, description = "Список идентификаторов для проверки (методы/типы/свойства; можно с точками/дженериками)." },
130 top_n = new { type = "integer", description = "Максимум попаданий на идентификатор (по умолчанию 5)." },
131 suggestions = new { type = "integer", description = "Максимум подсказок на missing-идентификатор (по умолчанию 8)." },
132 extensions = new { type = "array", items = new { type = "string" }, description = "Опционально: ограничить расширениями (по умолчанию ['.cs'])." },
133 path_prefix = new { type = "string", description = "Опционально: ограничить попадания путями, начинающимися с префикса (unix-style)." },
134 exclude_path_prefixes = new { type = "array", items = new { type = "string" }, description = "Опционально: исключить пути по префиксам (unix-style)." },
135 },
136 required = new[] { "workspace_path", "identifiers" },
137 }),
138 },
139 new Tool
140 {
141 Name = "codebase_index_draft_doc",
142 Description =
143 "Синтез документации (черновик): собрать markdown-скелет с выдержками из изменённых файлов (по индексу).",
144 InputSchema = Schema(new
145 {
146 type = "object",
147 properties = new
148 {
149 workspace_path = new { type = "string", description = "Корень workspace." },
150 solution_path = new { type = "string", description = "Опционально: путь к .sln/.slnx/.csproj (relative to workspace или absolute). Scope: одна БД на (workspace_root, solution_path)." },
151 title = new { type = "string", description = "Заголовок документа (например 'ADR: ...' или 'Design notes: ...')." },
152 changed_paths = new { type = "array", items = new { type = "string" }, description = "Список путей (relative to workspace) для включения в черновик." },
153 },
154 required = new[] { "workspace_path", "title", "changed_paths" },
155 }),
156 },
157 new Tool
158 {
159 Name = "codebase_index_vec_reindex",
160 Description =
161 "Построить/обновить vec-индекс (эмбеддинги) для текущей SQLite базы. Требует semantic_enabled=true.",
162 InputSchema = Schema(new
163 {
164 type = "object",
165 properties = new
166 {
167 workspace_path = new { type = "string", description = "Корень workspace." },
168 solution_path = new { type = "string", description = "Опционально: путь к .sln/.slnx/.csproj (relative to workspace или absolute). Scope: одна БД на (workspace_root, solution_path)." },
169 },
170 required = new[] { "workspace_path" },
171 }),
172 },
173 ];
174 }
175}
176
View only · write via MCP/CIDE