@znt/mcp 2.0.2 → 2.0.3
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/README.md +12 -0
- package/package.json +1 -1
- package/src/tool-definitions.js +2 -2
- package/src/znt-tools.js +77 -25
package/README.md
CHANGED
|
@@ -207,6 +207,10 @@ Windows Credential Manager, macOS Keychain или Linux Secret Service. В YAML
|
|
|
207
207
|
Проверяет Core, YAML и credential. С `check_provider: true` дополнительно
|
|
208
208
|
проверяет endpoint и настроенные модели. Значение секрета не возвращается.
|
|
209
209
|
|
|
210
|
+
Ключевые поля ответа:
|
|
211
|
+
- `config_managed` (boolean): `true`, если конфигурация управляется MCP-сервером, или `false`, если выбран внешний файл конфигурации через `ZNT_CONFIG`.
|
|
212
|
+
- `model`: имя генеративной LLM-модели. Если выбран `semantic_mode: "fast"` (локальные эвристики AST без вызовов LLM) и модель не задана, поле возвращает `"not_required (fast mode)"`.
|
|
213
|
+
|
|
210
214
|
### `search`
|
|
211
215
|
|
|
212
216
|
Ищет компоненты в semantic index.
|
|
@@ -302,6 +306,14 @@ embedding не означает, что lexical symbol отсутствует.
|
|
|
302
306
|
Допустимые форматы: `text`, `json`, `mermaid`. Для неоднозначного короткого
|
|
303
307
|
имени core возвращает кандидатов; повторите запрос с квалифицированным `name`.
|
|
304
308
|
|
|
309
|
+
Дополнительные параметры направления:
|
|
310
|
+
- `direction` (`"down"` | `"up"` | `"both"`, по умолчанию `"down"`): в локальном режиме задает направление обхода вызовов:
|
|
311
|
+
- `"down"` (по умолчанию): исследует только исходящие вызовы (дерево вызовов / callees), исключая комбинаторный взрыв тестами и сторонними клиентами на `depth >= 2`;
|
|
312
|
+
- `"up"`: исследует иерархию вызывающих (callers / кто вызывает данный символ);
|
|
313
|
+
- `"both"`: двунаправленный обход (одновременно callers и callees).
|
|
314
|
+
|
|
315
|
+
> 💡 **Чистый граф проекта**: MCP автоматически отсекает методы стандартных библиотек и вендоров (JDK, Go stdlib, Spring boilerplate: `HashMap`, `put`, `get`, `ok`), поэтому граф содержит только реальный код проекта.
|
|
316
|
+
|
|
305
317
|
### `outline`
|
|
306
318
|
|
|
307
319
|
Возвращает полное top-level оглавление проиндексированного файла:
|
package/package.json
CHANGED
package/src/tool-definitions.js
CHANGED
|
@@ -79,6 +79,7 @@ export const TOOL_DEFINITIONS = Object.freeze([
|
|
|
79
79
|
depth: { type: "integer", minimum: 1, maximum: 100, default: 1 },
|
|
80
80
|
format: { type: "string", enum: ["text", "json", "mermaid"], default: "text" },
|
|
81
81
|
edge_types: { type: "string", description: "Comma-separated contains,call,inherits,implements values." },
|
|
82
|
+
direction: { type: "string", enum: ["down", "up", "both"], default: "down", description: "Call direction: 'down' for call tree (callees, default), 'up' for callers (call hierarchy), 'both' for bidirectional context." },
|
|
82
83
|
},
|
|
83
84
|
required: ["from"],
|
|
84
85
|
additionalProperties: false,
|
|
@@ -123,12 +124,11 @@ export const TOOL_DEFINITIONS = Object.freeze([
|
|
|
123
124
|
},
|
|
124
125
|
{
|
|
125
126
|
name: "scan",
|
|
126
|
-
description: "
|
|
127
|
+
description: "Index the project workspace. Scans all supported source files, declarative schemas, and project resources.",
|
|
127
128
|
inputSchema: {
|
|
128
129
|
type: "object",
|
|
129
130
|
properties: {
|
|
130
131
|
project_path: { type: "string", minLength: 1, description: "Optional absolute project directory or a path relative to ZNT_PROJECT_ROOT. Defaults to ZNT_PROJECT_ROOT or cwd." },
|
|
131
|
-
language: { type: "string", minLength: 1, default: "auto", description: "Parser name from info.languages, or auto." },
|
|
132
132
|
},
|
|
133
133
|
additionalProperties: false,
|
|
134
134
|
},
|
package/src/znt-tools.js
CHANGED
|
@@ -27,11 +27,13 @@ export class ZntTools {
|
|
|
27
27
|
this.managedConfig = options.managedConfig ?? (explicitConfig === undefined);
|
|
28
28
|
this.client = options.client ?? new ZntClient({
|
|
29
29
|
configPath: this.configPath,
|
|
30
|
+
configManaged: this.managedConfig,
|
|
30
31
|
...(options.coreBinaryPath ? { coreBinaryPath: options.coreBinaryPath } : {}),
|
|
31
32
|
});
|
|
32
33
|
if (typeof this.client.setupManagedConfig !== "function") {
|
|
33
34
|
this.client.setupManagedConfig = (opts) => setupManagedConfig(opts, {
|
|
34
35
|
configPath: this.configPath,
|
|
36
|
+
configManaged: this.managedConfig,
|
|
35
37
|
coreBinaryPath: this.customCoreBinary,
|
|
36
38
|
client: this.client,
|
|
37
39
|
});
|
|
@@ -39,6 +41,7 @@ export class ZntTools {
|
|
|
39
41
|
if (typeof this.client.getSetupStatus !== "function") {
|
|
40
42
|
this.client.getSetupStatus = (opts) => getSetupStatus(opts, {
|
|
41
43
|
configPath: this.configPath,
|
|
44
|
+
configManaged: this.managedConfig,
|
|
42
45
|
coreBinaryPath: this.customCoreBinary,
|
|
43
46
|
client: this.client,
|
|
44
47
|
});
|
|
@@ -145,10 +148,16 @@ export class ZntTools {
|
|
|
145
148
|
}
|
|
146
149
|
|
|
147
150
|
async setupStatus(checkProvider = false, signal) {
|
|
148
|
-
const status = await this.client.getSetupStatus({
|
|
151
|
+
const status = await this.client.getSetupStatus({
|
|
152
|
+
configPath: this.configPath,
|
|
153
|
+
configManaged: this.managedConfig,
|
|
154
|
+
checkProvider,
|
|
155
|
+
signal,
|
|
156
|
+
});
|
|
149
157
|
return {
|
|
150
158
|
...status,
|
|
151
|
-
|
|
159
|
+
config_managed: this.managedConfig,
|
|
160
|
+
...(status?.semantic_mode === "fast" && !status?.model ? { model: "not_required (fast mode)" } : {}),
|
|
152
161
|
};
|
|
153
162
|
}
|
|
154
163
|
|
|
@@ -179,7 +188,9 @@ export class ZntTools {
|
|
|
179
188
|
"clear_api_key",
|
|
180
189
|
].some((key) => args[key] !== undefined);
|
|
181
190
|
|
|
182
|
-
|
|
191
|
+
const isInteractive = args.interactive !== false && args.interactive !== "false";
|
|
192
|
+
|
|
193
|
+
if (isInteractive && (!hasExplicitSettings || args.interactive === true || args.interactive === "true")) {
|
|
183
194
|
return this.openSetupWizard(args, signal);
|
|
184
195
|
}
|
|
185
196
|
|
|
@@ -266,43 +277,55 @@ export class ZntTools {
|
|
|
266
277
|
!args.clear_api_key
|
|
267
278
|
);
|
|
268
279
|
|
|
280
|
+
const isInteractive = args.interactive !== false && args.interactive !== "false";
|
|
269
281
|
const mode = args.mode ?? previousStatus?.mode ?? "openapi";
|
|
270
282
|
const isInteractiveOpenapi = mode === "openapi" && !args.api_key && args.credential_source !== "env" && !hasExistingCredential;
|
|
271
283
|
|
|
272
284
|
const status = await this.client.setupManagedConfig({
|
|
273
285
|
...args,
|
|
274
286
|
config_path: this.configPath,
|
|
275
|
-
check_provider: isInteractiveOpenapi ? false : (args.check_provider !== false),
|
|
287
|
+
check_provider: (isInteractiveOpenapi && isInteractive) ? false : (args.check_provider !== false),
|
|
276
288
|
});
|
|
277
289
|
|
|
278
290
|
if (isInteractiveOpenapi || status.status === "credential_required") {
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
291
|
+
if (isInteractive) {
|
|
292
|
+
const providerUrl = args.provider_url ?? status.provider_url ?? "https://api.openai.com/v1";
|
|
293
|
+
const reference = credentialReference(providerUrl);
|
|
294
|
+
const setupUrl = await this.credentialSetup.open({
|
|
295
|
+
provider: providerUrl,
|
|
296
|
+
onCredential: async (credential) => {
|
|
297
|
+
if (typeof this.client.storeSecret === "function") {
|
|
298
|
+
await this.client.storeSecret(reference, credential);
|
|
299
|
+
}
|
|
300
|
+
if (typeof this.client.validateConfig === "function") {
|
|
301
|
+
await this.client.validateConfig(this.configPath, { checkProvider: true });
|
|
302
|
+
}
|
|
303
|
+
this.setupReady = true;
|
|
304
|
+
},
|
|
305
|
+
});
|
|
306
|
+
return {
|
|
307
|
+
status: "credential_required",
|
|
308
|
+
config_path: this.configPath,
|
|
309
|
+
credential_source: "keyring",
|
|
310
|
+
setup_url: setupUrl,
|
|
311
|
+
next: "Open setup_url, save the API key, then call setup_status with check_provider=true.",
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
|
|
293
315
|
return {
|
|
316
|
+
...status,
|
|
294
317
|
status: "credential_required",
|
|
295
318
|
config_path: this.configPath,
|
|
296
|
-
|
|
297
|
-
setup_url: setupUrl,
|
|
298
|
-
next: "Open setup_url, save the API key, then call setup_status with check_provider=true.",
|
|
319
|
+
instruction: "API key is required. Pass api_key directly in setup arguments or set interactive: true to open the browser setup wizard.",
|
|
299
320
|
};
|
|
300
321
|
}
|
|
301
322
|
|
|
323
|
+
|
|
302
324
|
this.setupReady = status.status === "ready";
|
|
303
325
|
return {
|
|
304
326
|
...status,
|
|
305
|
-
|
|
327
|
+
config_managed: this.managedConfig,
|
|
328
|
+
...(status?.semantic_mode === "fast" && !status?.model ? { model: "not_required (fast mode)" } : {}),
|
|
306
329
|
scan_required: this.setupReady,
|
|
307
330
|
};
|
|
308
331
|
}
|
|
@@ -327,7 +350,7 @@ export class ZntTools {
|
|
|
327
350
|
case "similar":
|
|
328
351
|
return this.client.findSimilar(normalizeSimilarArgs(args), requestOptions);
|
|
329
352
|
case "graph":
|
|
330
|
-
return this.client.getSubgraph(
|
|
353
|
+
return this.client.getSubgraph(normalizeGraphArgs(args), requestOptions);
|
|
331
354
|
case "outline":
|
|
332
355
|
return this.client.fileOutline({ file_path: args.path, include_code: args.include_code }, requestOptions);
|
|
333
356
|
case "logs":
|
|
@@ -457,10 +480,31 @@ export class ZntTools {
|
|
|
457
480
|
}
|
|
458
481
|
}
|
|
459
482
|
|
|
483
|
+
export const TYPE_BOOST_MAP = {
|
|
484
|
+
class: "declaration",
|
|
485
|
+
struct: "declaration",
|
|
486
|
+
interface: "declaration",
|
|
487
|
+
type: "declaration",
|
|
488
|
+
enum: "declaration",
|
|
489
|
+
declaration: "declaration",
|
|
490
|
+
method: "function",
|
|
491
|
+
function: "function",
|
|
492
|
+
constructor: "function",
|
|
493
|
+
field: "member",
|
|
494
|
+
property: "member",
|
|
495
|
+
member: "member",
|
|
496
|
+
};
|
|
497
|
+
|
|
498
|
+
export function normalizeAstType(type) {
|
|
499
|
+
if (!type || typeof type !== "string") return type;
|
|
500
|
+
const lower = type.trim().toLowerCase();
|
|
501
|
+
return TYPE_BOOST_MAP[lower] ?? type;
|
|
502
|
+
}
|
|
503
|
+
|
|
460
504
|
function normalizeSearchArgs(args) {
|
|
461
505
|
return copyDefined({
|
|
462
506
|
...args,
|
|
463
|
-
type: args.type_boost,
|
|
507
|
+
type: normalizeAstType(args.type_boost),
|
|
464
508
|
role: args.role_boost,
|
|
465
509
|
file_path: args.file_pattern,
|
|
466
510
|
}, ["query", "mode", "limit", "callers_level", "callees_level", "compact", "include_code", "max_code_lines", "type", "role", "file_path"]);
|
|
@@ -469,12 +513,20 @@ function normalizeSearchArgs(args) {
|
|
|
469
513
|
function normalizeSimilarArgs(args) {
|
|
470
514
|
return copyDefined({
|
|
471
515
|
...args,
|
|
472
|
-
type: args.type_boost,
|
|
516
|
+
type: normalizeAstType(args.type_boost),
|
|
473
517
|
role: args.role_boost,
|
|
474
518
|
file_path: args.file_pattern,
|
|
475
519
|
}, ["target", "query", "limit", "include_code", "max_code_lines", "type", "role", "file_path", "edge_types"]);
|
|
476
520
|
}
|
|
477
521
|
|
|
522
|
+
function normalizeGraphArgs(args) {
|
|
523
|
+
return copyDefined({
|
|
524
|
+
...args,
|
|
525
|
+
direction: args.direction ?? "down",
|
|
526
|
+
internal_only: true,
|
|
527
|
+
}, ["from", "to", "depth", "format", "edge_types", "direction", "internal_only"]);
|
|
528
|
+
}
|
|
529
|
+
|
|
478
530
|
function copyDefined(source, keys) {
|
|
479
531
|
return Object.fromEntries(keys.filter((key) => source[key] !== undefined).map((key) => [key, source[key]]));
|
|
480
532
|
}
|