@znt/mcp 1.1.1 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS_EXAMPLE.md +50 -0
- package/README.md +459 -90
- package/index.js +18 -119
- package/package.json +30 -21
- package/src/credential-setup.js +726 -0
- package/src/metrics.js +121 -0
- package/src/server.js +30 -0
- package/src/tool-definitions.js +143 -0
- package/src/znt-tools.js +555 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Recommended Znt MCP workflow
|
|
2
|
+
|
|
3
|
+
Этот фрагмент можно адаптировать для инструкций AI-агента проекта.
|
|
4
|
+
|
|
5
|
+
## Выбор инструмента
|
|
6
|
+
|
|
7
|
+
1. В начале работы вызови `setup` без параметров. Покажи пользователю
|
|
8
|
+
доступные режимы и не выбирай провайдера или передачу данных внешнему API
|
|
9
|
+
без его решения. После настройки проверь `setup_status`.
|
|
10
|
+
2. Затем вызови `status`, при необходимости передав
|
|
11
|
+
абсолютный `project_path` открытого workspace. Если
|
|
12
|
+
`is_current_project=false`, вызови `scan` с тем же путём,
|
|
13
|
+
затем проверяй status до завершения scan. Если daemon уже индексирует
|
|
14
|
+
родительский каталог, вложенный workspace получает `coverage=ancestor` и
|
|
15
|
+
повторно не сканируется.
|
|
16
|
+
3. Точный символ, функция, класс, CamelCase или snake_case:
|
|
17
|
+
`search` с `mode: "lexical"`.
|
|
18
|
+
4. Описание поведения или архитектурного назначения:
|
|
19
|
+
`search` с `mode: "hybrid"` и подходящим boost/filter.
|
|
20
|
+
5. Аналог существующей реализации:
|
|
21
|
+
`similar`.
|
|
22
|
+
6. Call/dependency graph или путь между символами:
|
|
23
|
+
`graph`.
|
|
24
|
+
7. Структура известного файла:
|
|
25
|
+
`outline` до чтения файла целиком.
|
|
26
|
+
8. Ошибки scan/index/daemon:
|
|
27
|
+
`logs`.
|
|
28
|
+
|
|
29
|
+
## Проверка результата
|
|
30
|
+
|
|
31
|
+
- Graph edges и semantic roles являются сильными подсказками, но критические
|
|
32
|
+
выводы нужно сверять с исходным кодом.
|
|
33
|
+
- Пустые callers/callees не доказывают отсутствие вызовов: запросите subgraph.
|
|
34
|
+
- При ambiguous symbol повторите запрос с квалифицированным именем кандидата.
|
|
35
|
+
- Для exhaustive или regex-поиска используйте локальный `rg` после Znt.
|
|
36
|
+
- Не смешивайте точный code token и длинное смысловое описание в одном hybrid
|
|
37
|
+
query; разделите exact lexical и behavioral hybrid запросы.
|
|
38
|
+
- Не используйте HTTP route как graph symbol: сначала найдите handler.
|
|
39
|
+
|
|
40
|
+
## Пример последовательности
|
|
41
|
+
|
|
42
|
+
```text
|
|
43
|
+
1. setup и подтверждение выбранного пользователем режима
|
|
44
|
+
2. project status и при необходимости scan current project
|
|
45
|
+
3. lexical search по имени entrypoint
|
|
46
|
+
4. file outline файла entrypoint
|
|
47
|
+
5. subgraph от найденного qualified name
|
|
48
|
+
6. hybrid search по недостающему поведению
|
|
49
|
+
7. проверка ключевых мест по исходникам
|
|
50
|
+
```
|
package/README.md
CHANGED
|
@@ -1,140 +1,509 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @znt/mcp
|
|
2
|
+
|
|
3
|
+
Локальный Model Context Protocol server для Znt. Он публикует инструменты
|
|
4
|
+
поиска и анализа кода через MCP stdio и вызывает `znt-core` напрямую через
|
|
5
|
+
`znt-sdk-nodejs`.
|
|
6
|
+
|
|
7
|
+
```text
|
|
8
|
+
AI client / IDE
|
|
9
|
+
│ MCP over stdio
|
|
10
|
+
▼
|
|
11
|
+
znt-mcp-server (Node.js)
|
|
12
|
+
│ znt-sdk-nodejs
|
|
13
|
+
│ JSON-RPC 2.0 over Unix socket / Windows named pipe
|
|
14
|
+
▼
|
|
15
|
+
znt-core daemon
|
|
16
|
+
│
|
|
17
|
+
▼
|
|
18
|
+
indexed workspace
|
|
19
|
+
```
|
|
2
20
|
|
|
3
|
-
|
|
21
|
+
Новый сервер заменяет прежнюю двойную ретрансляцию:
|
|
4
22
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
* 🛠 **Репозиторий MCP-адаптера**: [https://github.com/boottaa/znt_mcp](https://github.com/boottaa/znt_mcp)
|
|
23
|
+
```text
|
|
24
|
+
Было:
|
|
25
|
+
MCP client -> znt_mcp stdio adapter -> HTTP/SSE -> Go MCP engine -> core internals
|
|
9
26
|
|
|
10
|
-
|
|
27
|
+
Стало:
|
|
28
|
+
MCP client -> znt-mcp-server stdio -> znt-sdk-nodejs -> znt-core IPC
|
|
29
|
+
```
|
|
11
30
|
|
|
12
|
-
|
|
31
|
+
Go-файл `internal/engine/mcp_engine.go` и HTTP-сервер для MCP больше не нужны в
|
|
32
|
+
runtime нового пакета. Источником контракта core является SDK.
|
|
33
|
+
|
|
34
|
+
## Основные свойства
|
|
35
|
+
|
|
36
|
+
- Node.js 18+;
|
|
37
|
+
- официальный MCP stdio transport;
|
|
38
|
+
- одно переиспользуемое IPC-соединение;
|
|
39
|
+
- Unix socket на Linux/macOS и named pipe на Windows;
|
|
40
|
+
- десять публичных tools: `setup`, `setup_status`, `search`, `similar`, `graph`,
|
|
41
|
+
`outline`, `logs`, `status`, `scan`, `stats`;
|
|
42
|
+
- совместимые имена параметров старого MCP преобразуются в параметры SDK;
|
|
43
|
+
- daemon не запускается до успешного setup;
|
|
44
|
+
- если managed core отсутствует, server устанавливает setup-capable релиз `1.1`;
|
|
45
|
+
- завершение MCP server разрывает только клиентское соединение и не завершает
|
|
46
|
+
общий daemon;
|
|
47
|
+
- RPC/transport ошибки возвращаются как MCP tool result с `isError: true`;
|
|
48
|
+
- поддерживаются MCP cancellation и настраиваемый timeout;
|
|
49
|
+
- локальная статистика использования сохраняется без SQLite-зависимости.
|
|
50
|
+
|
|
51
|
+
## Требования
|
|
52
|
+
|
|
53
|
+
- Node.js 18 или новее;
|
|
54
|
+
- собранный `../znt-sdk-nodejs`;
|
|
55
|
+
- доступ к GitHub для первой автоматической установки `znt-core`;
|
|
56
|
+
- доступный workspace с исходниками; при необходимости агент может запустить
|
|
57
|
+
его первичное сканирование;
|
|
58
|
+
- embeddings в core для полноценного vector search и `findSimilar()`.
|
|
59
|
+
|
|
60
|
+
MCP server не публикует download/remove. Агент может передать существующий
|
|
61
|
+
каталог через `project_path`; если путь не задан, используется workspace самого
|
|
62
|
+
MCP-процесса. Повторный scan вложенного каталога не запускается, когда его уже
|
|
63
|
+
покрывает индекс родительского каталога. Для интерактивного управления анализом
|
|
64
|
+
и мониторингом можно использовать `znt-ui-dashboard`.
|
|
65
|
+
|
|
66
|
+
## Установка
|
|
67
|
+
|
|
68
|
+
Сначала соберите локальный SDK:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
cd znt-sdk-nodejs
|
|
72
|
+
npm install
|
|
73
|
+
npm run build
|
|
74
|
+
```
|
|
13
75
|
|
|
14
|
-
|
|
76
|
+
Затем установите зависимости MCP server:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
cd ../znt-mcp-server
|
|
80
|
+
npm install
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Запуск
|
|
84
|
+
|
|
85
|
+
В каталоге пакета:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
npm start
|
|
89
|
+
```
|
|
15
90
|
|
|
16
|
-
|
|
91
|
+
Из корня monorepo:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
npm run mcp
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
При обычном запуске server использует stdio для MCP-протокола. Нельзя писать
|
|
98
|
+
диагностические сообщения в stdout: он зарезервирован для JSON-RPC. Ошибки
|
|
99
|
+
bootstrap выводятся в stderr.
|
|
100
|
+
|
|
101
|
+
## Подключение MCP-клиента
|
|
102
|
+
|
|
103
|
+
Обобщённая конфигурация для клиента, поддерживающего локальные stdio servers:
|
|
17
104
|
|
|
18
105
|
```json
|
|
19
106
|
{
|
|
20
107
|
"mcpServers": {
|
|
21
|
-
"znt
|
|
108
|
+
"znt": {
|
|
109
|
+
"command": "node",
|
|
110
|
+
"args": [
|
|
111
|
+
"/absolute/path/to/Znt/znt-mcp-server/index.js"
|
|
112
|
+
],
|
|
113
|
+
"env": {
|
|
114
|
+
"ZNT_PROJECT_ROOT": "/absolute/path/to/project"
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Для опубликованного npm-пакета вместо полного пути можно будет использовать
|
|
122
|
+
`npx`:
|
|
123
|
+
|
|
124
|
+
```json
|
|
125
|
+
{
|
|
126
|
+
"mcpServers": {
|
|
127
|
+
"znt": {
|
|
22
128
|
"command": "npx",
|
|
23
129
|
"args": ["-y", "@znt/mcp"],
|
|
24
130
|
"env": {
|
|
25
|
-
"
|
|
131
|
+
"ZNT_PROJECT_ROOT": "/absolute/path/to/project"
|
|
26
132
|
}
|
|
27
133
|
}
|
|
28
134
|
}
|
|
29
135
|
}
|
|
30
136
|
```
|
|
31
137
|
|
|
32
|
-
|
|
138
|
+
При глобальной установке доступна bin-команда `znt-mcp`.
|
|
139
|
+
|
|
140
|
+
## Жизненный цикл core
|
|
141
|
+
|
|
142
|
+
При bootstrap server не запускает daemon и не сканирует проект:
|
|
143
|
+
|
|
144
|
+
1. `setup_status` проверяет наличие бинарника и YAML.
|
|
145
|
+
2. `setup` при необходимости устанавливает Core и получает встроенные YAML-дефолты.
|
|
146
|
+
3. MCP сохраняет выбранный `config.yaml` рядом с управляемым бинарником.
|
|
147
|
+
4. После валидации первый рабочий tool запускает daemon с этим конфигом.
|
|
148
|
+
5. `scan` до успешного setup возвращает `setup_required`.
|
|
149
|
+
|
|
150
|
+
SDK скачивает бинарник только из официальных GitHub Releases `znt-app/core` и
|
|
151
|
+
проверяет SHA-256 из release manifest. Стандартные каталоги:
|
|
152
|
+
|
|
153
|
+
| Платформа | Каталог |
|
|
154
|
+
|---|---|
|
|
155
|
+
| Linux | `$XDG_DATA_HOME/znt/bin` или `~/.local/share/znt/bin` |
|
|
156
|
+
| macOS | `~/Library/Application Support/Znt/bin` |
|
|
157
|
+
| Windows | `%LOCALAPPDATA%\\Znt\\bin` |
|
|
158
|
+
|
|
159
|
+
Рабочий YAML находится в этом же каталоге под именем `config.yaml`. Явный
|
|
160
|
+
`ZNT_CONFIG` имеет приоритет и считается внешним: MCP проверяет, но не
|
|
161
|
+
перезаписывает его.
|
|
162
|
+
|
|
163
|
+
При остановке MCP server вызывается только `client.disconnect()`. Это важно,
|
|
164
|
+
потому что один daemon может одновременно использоваться Dashboard и другими
|
|
165
|
+
SDK-клиентами.
|
|
166
|
+
|
|
167
|
+
## Переменные окружения
|
|
168
|
+
|
|
169
|
+
| Переменная | Назначение |
|
|
170
|
+
|---|---|
|
|
171
|
+
| `ZNT_ENDPOINT` | Unix socket или Windows named pipe |
|
|
172
|
+
| `ZNT_CORE_HOME` | Пользовательский каталог установки core |
|
|
173
|
+
| `ZNT_CORE_BINARY` | Полный путь к development-бинарнику |
|
|
174
|
+
| `ZNT_CONFIG` | Конфигурация, передаваемая при запуске daemon |
|
|
175
|
+
| `ZNT_CORE_CWD` | Рабочий каталог запускаемого daemon |
|
|
176
|
+
| `ZNT_RUNTIME_DIR` | Runtime-файлы core |
|
|
177
|
+
| `ZNT_PROJECT_ROOT` | Текущий проект MCP; по умолчанию `process.cwd()` |
|
|
178
|
+
| `ZNT_MCP_REQUEST_TIMEOUT_MS` | Timeout одного SDK-вызова, по умолчанию 30000 ms |
|
|
179
|
+
| `ZNT_MCP_METRICS_FILE` | Путь к JSONL-файлу MCP metrics |
|
|
180
|
+
|
|
181
|
+
Если `ZNT_ENDPOINT` не задан, SDK использует:
|
|
182
|
+
|
|
183
|
+
- Linux/macOS: `~/.znt/znt.sock`;
|
|
184
|
+
- Windows: `\\.\pipe\znt-core`.
|
|
185
|
+
|
|
186
|
+
`ZNT_PROJECT_ROOT` задаёт проект по умолчанию для IDE, которая запускает MCP
|
|
187
|
+
server не из корня открытого проекта. `status` и
|
|
188
|
+
`scan` также принимают необязательный `project_path`: абсолютный
|
|
189
|
+
путь либо путь относительно `ZNT_PROJECT_ROOT`. Приоритет выбора:
|
|
190
|
+
`project_path` → `ZNT_PROJECT_ROOT` → `cwd`.
|
|
191
|
+
|
|
192
|
+
## Tools
|
|
193
|
+
|
|
194
|
+
### `setup`
|
|
195
|
+
|
|
196
|
+
Без параметров возвращает состояние и рекомендации: BM25, Ollama или
|
|
197
|
+
OpenAI-compatible provider. С выбранным `mode` создаёт и проверяет managed
|
|
198
|
+
`config.yaml`. API-ключ запрещено передавать аргументом tool.
|
|
199
|
+
|
|
200
|
+
Для keyring MCP возвращает одноразовый loopback `setup_url`: пользователь
|
|
201
|
+
вводит ключ напрямую в локальную форму, после чего Core сохраняет его в
|
|
202
|
+
Windows Credential Manager, macOS Keychain или Linux Secret Service. В YAML
|
|
203
|
+
остаётся только `token_ref`.
|
|
204
|
+
|
|
205
|
+
### `setup_status`
|
|
206
|
+
|
|
207
|
+
Проверяет Core, YAML и credential. С `check_provider: true` дополнительно
|
|
208
|
+
проверяет endpoint и настроенные модели. Значение секрета не возвращается.
|
|
209
|
+
|
|
210
|
+
### `search`
|
|
211
|
+
|
|
212
|
+
Ищет компоненты в semantic index.
|
|
213
|
+
|
|
214
|
+
| Параметр | Тип | По умолчанию | Описание |
|
|
215
|
+
|---|---|---:|---|
|
|
216
|
+
| `query` | string | обязателен | Имя символа или описание поведения |
|
|
217
|
+
| `mode` | enum | `hybrid` | `lexical`, `vector`, `hybrid` |
|
|
218
|
+
| `limit` | integer | `10` | Количество результатов |
|
|
219
|
+
| `callers_level` | integer | `0` | Глубина входящих связей |
|
|
220
|
+
| `callees_level` | integer | `0` | Глубина исходящих связей |
|
|
221
|
+
| `compact` | boolean | `false` | Исключить граф связей |
|
|
222
|
+
| `include_code` | boolean | `false` | Включить тело AST-узла |
|
|
223
|
+
| `max_code_lines` | integer | `30` | Максимум строк кода |
|
|
224
|
+
| `role_boost` | string | — | Мягкий boost роли |
|
|
225
|
+
| `type_boost` | string | — | Мягкий boost AST-типа |
|
|
226
|
+
| `file_pattern` | string | — | Фильтр пути |
|
|
227
|
+
|
|
228
|
+
Старые имена `role_boost`, `type_boost`, `file_pattern` преобразуются в SDK
|
|
229
|
+
поля `role`, `type`, `file_path`.
|
|
230
|
+
|
|
231
|
+
Примеры:
|
|
232
|
+
|
|
233
|
+
```json
|
|
234
|
+
{
|
|
235
|
+
"query": "SemanticService.SearchWithOptions",
|
|
236
|
+
"mode": "lexical",
|
|
237
|
+
"type_boost": "function",
|
|
238
|
+
"include_code": true
|
|
239
|
+
}
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
```json
|
|
243
|
+
{
|
|
244
|
+
"query": "как строится индекс после сканирования",
|
|
245
|
+
"mode": "hybrid",
|
|
246
|
+
"role_boost": "service",
|
|
247
|
+
"limit": 10
|
|
248
|
+
}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
Практика выбора режима:
|
|
252
|
+
|
|
253
|
+
- точный CamelCase/snake_case идентификатор — `lexical`;
|
|
254
|
+
- поведение или архитектурный смысл — `hybrid`;
|
|
255
|
+
- гипотетическое имя или чистая семантическая близость — `vector`.
|
|
256
|
+
|
|
257
|
+
### `similar`
|
|
258
|
+
|
|
259
|
+
Ищет аналоги и возможные дубликаты. Требуется хотя бы один параметр `target`
|
|
260
|
+
или `query`.
|
|
261
|
+
|
|
262
|
+
```json
|
|
263
|
+
{
|
|
264
|
+
"target": "SemanticService.SearchWithOptions",
|
|
265
|
+
"limit": 10,
|
|
266
|
+
"edge_types": "call,implements",
|
|
267
|
+
"include_code": true
|
|
268
|
+
}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
Дополнительные параметры: `role_boost`, `type_boost`, `file_pattern`,
|
|
272
|
+
`max_code_lines`. Инструмент зависит от embeddings; пустой результат без
|
|
273
|
+
embedding не означает, что lexical symbol отсутствует.
|
|
33
274
|
|
|
34
|
-
|
|
275
|
+
### `graph`
|
|
35
276
|
|
|
36
|
-
|
|
277
|
+
Поддерживает локальный BFS-граф и трассировку пути.
|
|
37
278
|
|
|
38
|
-
|
|
39
|
-
* **Назначение**: Семантический и гибридный поиск (BM25 + Векторы + RRF) по элементам кодовой базы.
|
|
40
|
-
* **Параметры**:
|
|
41
|
-
* `query` *(string, обязательный)*: Поисковый запрос на естественном языке.
|
|
42
|
-
* `limit` *(number)*: Максимальное число результатов (по умолчанию `10`, макс `100`).
|
|
43
|
-
* `callers_level` *(number)*: Глубина графа входящих вызовов (по умолчанию `3`).
|
|
44
|
-
* `callees_level` *(number)*: Глубина графа исходящих вызовов (по умолчанию `3`).
|
|
45
|
-
* `include_code` *(boolean)*: Включать ли фрагменты исходного кода узлов.
|
|
46
|
-
* `max_code_lines` *(number)*: Максимум строк кода на узел (по умолчанию `30`).
|
|
47
|
-
* `role` *(string)*: Фильтр по архитектурной роли (`"controller"`, `"service"`, `"repository"`, `"model"`).
|
|
48
|
-
* `type` *(string)*: Фильтр по типу узла AST (`"function"`, `"struct"`, `"class"`, `"interface"`).
|
|
49
|
-
* `file_pattern` *(string)*: Маска пути файла (например `"pkg/semantic/*"` или `"*.go"`).
|
|
50
|
-
* `mode` *(string)*: Режим поиска: `"hybrid"` (RRF гибридный), `"lexical"` (точный BM25/FTS5), `"vector"` (чисто векторный). По умолчанию `"hybrid"`.
|
|
279
|
+
Локальное окружение:
|
|
51
280
|
|
|
52
|
-
|
|
281
|
+
```json
|
|
282
|
+
{
|
|
283
|
+
"from": "SemanticService.SearchWithOptions",
|
|
284
|
+
"depth": 2,
|
|
285
|
+
"edge_types": "call,implements,inherits",
|
|
286
|
+
"format": "text"
|
|
287
|
+
}
|
|
288
|
+
```
|
|
53
289
|
|
|
54
|
-
|
|
55
|
-
* **Назначение**: Умный мультифакторный поиск аналогов и дубликатов кода (60% векторный косинус + 30% граф вызовов Jaccard + 10% AST-роли).
|
|
56
|
-
* **Параметры**:
|
|
57
|
-
* `target` *(string)*: Имя символа, функции или класса в проекте (например `"Server.runFullScan"`). При указании вектор берется из БД напрямую **без обращения к LLM**.
|
|
58
|
-
* `query` *(string)*: Текстовое описание или код для поиска аналогов (используется, если `target` не задан).
|
|
59
|
-
* `limit` *(number)*: Максимальное число результатов (по умолчанию `10`).
|
|
60
|
-
* `edge_types` *(string)*: Фильтр связей для ранжирования (`"call,inherits,implements"`).
|
|
61
|
-
* `include_code` *(boolean)* / `max_code_lines` *(number)*: Параметры включения кода (по умолчанию `30` строк).
|
|
62
|
-
* `role` / `type` / `file_pattern` *(string)*: Фильтры по архитектуре и путям файлов.
|
|
290
|
+
Трассировка:
|
|
63
291
|
|
|
64
|
-
|
|
292
|
+
```json
|
|
293
|
+
{
|
|
294
|
+
"from": "Server.ExecuteSearch",
|
|
295
|
+
"to": "SemanticStore.SearchFTS5",
|
|
296
|
+
"depth": 2,
|
|
297
|
+
"format": "mermaid"
|
|
298
|
+
}
|
|
299
|
+
```
|
|
65
300
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
* `target` *(string)*: Символ или относительный путь файла для вывода его окрестностей.
|
|
70
|
-
* `from` / `to` *(string)*: Точки трассировки цепочки вызовов (DFS по графу).
|
|
71
|
-
* `depth` *(number)*: Глубина обхода подграфа (по умолчанию `2`).
|
|
72
|
-
* `max_nodes` *(number)*: Максимальное количество узлов подграфа (по умолчанию `30`).
|
|
73
|
-
* `format` *(string)*: Формат ответа (`"mermaid"` для Markdown-диаграмм или `"json"`, по умолчанию `"mermaid"`).
|
|
301
|
+
Допустимые `edge_types`: `contains`, `call`, `inherits`, `implements`.
|
|
302
|
+
Допустимые форматы: `text`, `json`, `mermaid`. Для неоднозначного короткого
|
|
303
|
+
имени core возвращает кандидатов; повторите запрос с квалифицированным `name`.
|
|
74
304
|
|
|
75
|
-
|
|
305
|
+
### `outline`
|
|
76
306
|
|
|
77
|
-
|
|
78
|
-
* **Назначение**: Анатомический семантический атлас (оглавление) файла за 1 запрос без замусоривания контекста.
|
|
79
|
-
* **Параметры**:
|
|
80
|
-
* `path` *(string, обязательный)*: Путь к целевому файлу (например `"internal/engine/server.go"`).
|
|
81
|
-
* `include_code` *(boolean)*: Включать ли фрагменты исходного кода для каждого символа.
|
|
307
|
+
Возвращает полное top-level оглавление проиндексированного файла:
|
|
82
308
|
|
|
83
|
-
|
|
309
|
+
```json
|
|
310
|
+
{
|
|
311
|
+
"path": "internal/engine/queries.go",
|
|
312
|
+
"include_code": true
|
|
313
|
+
}
|
|
314
|
+
```
|
|
84
315
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
* **Параметры**: Отсутствуют.
|
|
316
|
+
MCP сохраняет старое имя параметра `path`, затем преобразует его в SDK
|
|
317
|
+
`file_path`. Используйте outline перед чтением большого файла.
|
|
88
318
|
|
|
89
|
-
|
|
319
|
+
### `logs`
|
|
90
320
|
|
|
91
|
-
|
|
92
|
-
* **Назначение**: Детальная метрика работы MCP-сервера и статистика сэкономленных токенов из SQLite.
|
|
93
|
-
* **Параметры**: Отсутствуют.
|
|
321
|
+
Без параметров возвращает текущий snapshot кольцевого буфера core:
|
|
94
322
|
|
|
95
|
-
|
|
323
|
+
```json
|
|
324
|
+
{}
|
|
325
|
+
```
|
|
96
326
|
|
|
97
|
-
|
|
327
|
+
Для следующего delta-запроса передайте оба значения из ответа:
|
|
98
328
|
|
|
99
|
-
|
|
329
|
+
```json
|
|
330
|
+
{
|
|
331
|
+
"stream_id": "stream_1234_...",
|
|
332
|
+
"after_id": 42
|
|
333
|
+
}
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
Если continuity потеряна, core возвращает `truncated: true` и полный доступный
|
|
337
|
+
snapshot.
|
|
338
|
+
|
|
339
|
+
### `status`
|
|
340
|
+
|
|
341
|
+
Проверяет, совпадает ли текущий MCP workspace с проектом, загруженным в daemon:
|
|
342
|
+
|
|
343
|
+
```json
|
|
344
|
+
{
|
|
345
|
+
"project_path": "/workspace/current"
|
|
346
|
+
}
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
`project_path` необязателен. Каталог должен существовать. Символические ссылки
|
|
350
|
+
разворачиваются через `realpath`.
|
|
351
|
+
|
|
352
|
+
Источник истины — `status().project_root`. `info()` содержит версию,
|
|
353
|
+
capabilities, конфигурацию и языки, но не содержит активный project root.
|
|
354
|
+
|
|
355
|
+
Ответ включает:
|
|
100
356
|
|
|
101
357
|
```json
|
|
102
358
|
{
|
|
103
|
-
"
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
"
|
|
359
|
+
"current_project": "/workspace/current",
|
|
360
|
+
"daemon_project": "/workspace/loaded",
|
|
361
|
+
"is_current_project": false,
|
|
362
|
+
"is_exact_project": false,
|
|
363
|
+
"coverage": "none",
|
|
364
|
+
"daemon_status": "Monitoring",
|
|
365
|
+
"has_index": false,
|
|
366
|
+
"stats": {
|
|
367
|
+
"files": 76,
|
|
368
|
+
"declarations": 249,
|
|
369
|
+
"functions": 75,
|
|
370
|
+
"members": 111,
|
|
371
|
+
"dependencies": 336,
|
|
372
|
+
"edges": 495
|
|
115
373
|
},
|
|
116
|
-
"
|
|
374
|
+
"scan": {}
|
|
117
375
|
}
|
|
118
376
|
```
|
|
119
377
|
|
|
120
|
-
|
|
378
|
+
`coverage` принимает `exact`, `ancestor` или `none`. Если daemon индексирует
|
|
379
|
+
`/workspace`, запрос для `/workspace/src/features` получает `ancestor` и
|
|
380
|
+
считается покрытым существующим индексом. `stats` относятся к `daemon_project`.
|
|
381
|
+
`has_index` становится true, когда запрошенный путь покрыт индексом и daemon
|
|
382
|
+
сообщает ненулевое количество файлов.
|
|
383
|
+
|
|
384
|
+
### `scan`
|
|
121
385
|
|
|
122
|
-
|
|
386
|
+
Безопасно переключает daemon на текущий MCP workspace:
|
|
387
|
+
|
|
388
|
+
```json
|
|
389
|
+
{
|
|
390
|
+
"project_path": "/workspace/current",
|
|
391
|
+
"language": "auto"
|
|
392
|
+
}
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
`project_path` необязателен и разрешает агенту явно указать открытый проект.
|
|
396
|
+
Относительные значения вычисляются от `ZNT_PROJECT_ROOT`.
|
|
397
|
+
|
|
398
|
+
Алгоритм:
|
|
399
|
+
|
|
400
|
+
1. получает `status().project_root`;
|
|
401
|
+
2. проверяет и канонизирует выбранный каталог через `realpath`;
|
|
402
|
+
3. если daemon индексирует этот каталог либо его родителя, возвращает
|
|
403
|
+
`started: false` (`already_current_project` или `already_covered`);
|
|
404
|
+
4. если другой scan уже выполняется, возвращает `scan_in_progress` и не
|
|
405
|
+
переключает daemon;
|
|
406
|
+
5. иначе вызывает SDK `scan()` для выбранного каталога;
|
|
407
|
+
6. всегда передаёт `restart: false`, сохраняя существующий `.znt` индекс;
|
|
408
|
+
7. немедленно возвращает `scan_id`; прогресс проверяется через
|
|
409
|
+
`status`.
|
|
410
|
+
|
|
411
|
+
Если daemon прямо сейчас сканирует другой проект, core может вернуть `Busy`.
|
|
412
|
+
Нужно дождаться терминального scan status и повторить вызов.
|
|
413
|
+
|
|
414
|
+
### `stats`
|
|
415
|
+
|
|
416
|
+
Возвращает session/total calls, приблизительный объём ответа, оценку экономии,
|
|
417
|
+
среднее время, top tools и последние вызовы.
|
|
418
|
+
|
|
419
|
+
```json
|
|
420
|
+
{}
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
После получения `status.project_root` статистика дописывается в
|
|
424
|
+
`<workspace>/.znt/mcp-usage.jsonl`. Путь можно переопределить через
|
|
425
|
+
`ZNT_MCP_METRICS_FILE`. Ошибка записи метрик никогда не превращает успешный
|
|
426
|
+
Znt tool call в ошибку.
|
|
427
|
+
|
|
428
|
+
Token metrics являются оценкой `ceil(characters / 4)`, а savings — сравнительной
|
|
429
|
+
эвристикой, не billing-статистикой LLM provider.
|
|
430
|
+
|
|
431
|
+
## Формат ответов
|
|
432
|
+
|
|
433
|
+
Все tools возвращают MCP `content` с текстовым блоком.
|
|
434
|
+
|
|
435
|
+
- semantic search форматируется в компактные секции `Score/Name/File/Code`;
|
|
436
|
+
- file outline возвращает `formatted_text` core без JSON-обёртки;
|
|
437
|
+
- text/mermaid subgraph возвращается непосредственно;
|
|
438
|
+
- JSON subgraph, find similar, logs и stats форматируются как JSON;
|
|
439
|
+
- отсутствие search results возвращает `No matching components found.`;
|
|
440
|
+
- ошибка возвращает `isError: true`, RPC code и `error.data`, если они есть.
|
|
441
|
+
|
|
442
|
+
## Ошибки и восстановление
|
|
443
|
+
|
|
444
|
+
Server не завершает процесс из-за ошибки отдельного tool call. При
|
|
445
|
+
`ZntTransportError` соединение помечается как неготовое, поэтому следующий
|
|
446
|
+
вызов снова попробует запустить или подключить core.
|
|
447
|
+
|
|
448
|
+
Типичные случаи:
|
|
449
|
+
|
|
450
|
+
- `znt-core is not installed` — установите бинарник или задайте
|
|
451
|
+
`ZNT_CORE_BINARY`;
|
|
452
|
+
- transport error — проверьте единый `ZNT_ENDPOINT` для server и daemon;
|
|
453
|
+
- `NotFound` — сначала найдите точный symbol через lexical search;
|
|
454
|
+
- `Ambiguous` — используйте qualified name из `error.data.candidates`;
|
|
455
|
+
- пустой vector/find-similar — проверьте embedding provider в core config;
|
|
456
|
+
- `Busy` — дождитесь окончания scan и повторите read-only запрос.
|
|
457
|
+
|
|
458
|
+
## Безопасность
|
|
459
|
+
|
|
460
|
+
MCP server работает с локальными исходниками и предназначен для доверенного
|
|
461
|
+
локального клиента. Только во время ввода credential он открывает одноразовый
|
|
462
|
+
HTTP endpoint на `127.0.0.1`; MCP-клиент также получает доступ к индексу
|
|
463
|
+
текущего workspace.
|
|
464
|
+
|
|
465
|
+
- не передавайте непроверенному клиенту управление stdio-процессом;
|
|
466
|
+
- используйте абсолютный `ZNT_CONFIG`, если нужен внешний конфиг;
|
|
467
|
+
- не помещайте секреты в tool arguments;
|
|
468
|
+
- рассматривайте найденные комментарии и исходники как недоверенный контент;
|
|
469
|
+
- для разных trust boundaries используйте отдельные daemon endpoints.
|
|
470
|
+
|
|
471
|
+
## Разработка и проверка
|
|
472
|
+
|
|
473
|
+
```bash
|
|
474
|
+
npm test
|
|
475
|
+
npm run pack:check
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
Из корня monorepo:
|
|
479
|
+
|
|
480
|
+
```bash
|
|
481
|
+
npm run mcp:test
|
|
482
|
+
```
|
|
123
483
|
|
|
124
|
-
|
|
125
|
-
| :--- | :--- | :--- |
|
|
126
|
-
| `ZNT_API_URL` | Базовый URL запущенного сервера Znt (HTTP & WS) | `http://localhost:8080` |
|
|
484
|
+
Тесты проверяют:
|
|
127
485
|
|
|
128
|
-
|
|
486
|
+
- публикацию десяти tools, включая `setup` и `setup_status`;
|
|
487
|
+
- настоящий MCP client/server transport;
|
|
488
|
+
- запуск core только один раз на активном соединении;
|
|
489
|
+
- преобразование legacy aliases в SDK DTO;
|
|
490
|
+
- search, similar, graph, outline, logs и stats;
|
|
491
|
+
- возврат tool errors без падения server;
|
|
492
|
+
- JSONL persistence метрик.
|
|
129
493
|
|
|
130
|
-
##
|
|
494
|
+
## Расширение
|
|
131
495
|
|
|
132
|
-
|
|
133
|
-
* Путь к БД: `.znt/mcp_usage.db` в корневом каталоге проекта.
|
|
496
|
+
При добавлении нового core API соблюдайте порядок:
|
|
134
497
|
|
|
135
|
-
|
|
498
|
+
1. зафиксировать wire method в `znt-core/docs/sdk-specification.md`;
|
|
499
|
+
2. добавить типизированный метод в `znt-sdk-nodejs`;
|
|
500
|
+
3. добавить узкий MCP tool и JSON Schema в `tool-definitions.js`;
|
|
501
|
+
4. вызвать только публичный метод SDK в `znt-tools.js`;
|
|
502
|
+
5. добавить protocol и adapter tests;
|
|
503
|
+
6. не импортировать Go internals и не восстанавливать HTTP relay.
|
|
136
504
|
|
|
137
|
-
##
|
|
505
|
+
## Связанные документы
|
|
138
506
|
|
|
139
|
-
|
|
140
|
-
|
|
507
|
+
- [`../znt-sdk-nodejs/README.md`](../znt-sdk-nodejs/README.md)
|
|
508
|
+
- [`../znt-core/docs/sdk-specification.md`](../znt-core/docs/sdk-specification.md)
|
|
509
|
+
- [`AGENTS_EXAMPLE.md`](AGENTS_EXAMPLE.md)
|