mcp-probe-kit 3.0.13 → 3.0.15
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 +6 -0
- package/build/lib/__tests__/gitnexus-bridge.unit.test.js +9 -1
- package/build/lib/gitnexus-bridge.d.ts +1 -0
- package/build/lib/gitnexus-bridge.js +133 -11
- package/build/tools/__tests__/code_insight.unit.test.js +8 -5
- package/build/tools/code_insight.js +32 -47
- package/docs/i18n/en.json +2 -0
- package/docs/i18n/ja.json +2 -0
- package/docs/i18n/ko.json +2 -0
- package/docs/i18n/zh-CN.json +2 -0
- package/docs/pages/getting-started.html +3 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -347,6 +347,12 @@ Recommended on Windows:
|
|
|
347
347
|
2. Prefer stable local/global CLI usage for GitNexus when your MCP client supports `env`.
|
|
348
348
|
3. Increase GitNexus connect/call timeouts on slower or first-run environments.
|
|
349
349
|
|
|
350
|
+
Quick install command (Windows):
|
|
351
|
+
|
|
352
|
+
```powershell
|
|
353
|
+
winget install Microsoft.VisualStudio.2022.BuildTools
|
|
354
|
+
```
|
|
355
|
+
|
|
350
356
|
Example config using a preinstalled `gitnexus` CLI:
|
|
351
357
|
|
|
352
358
|
```json
|
|
@@ -3,7 +3,7 @@ import * as os from "node:os";
|
|
|
3
3
|
import * as path from "node:path";
|
|
4
4
|
import spawn from "cross-spawn";
|
|
5
5
|
import { afterEach, describe, expect, test } from "vitest";
|
|
6
|
-
import { prepareBridgeWorkspace, resolveExecutableCommand, resolveGitNexusBridgeCommand, resolveSpawnCommand, rerankQueryStructuredContent, } from "../gitnexus-bridge.js";
|
|
6
|
+
import { extractResolvedSymbolIdFromContext, prepareBridgeWorkspace, resolveExecutableCommand, resolveGitNexusBridgeCommand, resolveSpawnCommand, rerankQueryStructuredContent, } from "../gitnexus-bridge.js";
|
|
7
7
|
const tempRoots = [];
|
|
8
8
|
afterEach(() => {
|
|
9
9
|
while (tempRoots.length > 0) {
|
|
@@ -87,6 +87,14 @@ describe("gitnexus-bridge workspace preparation", () => {
|
|
|
87
87
|
expect(reranked.structuredContent.processes[0].heuristicLabel).toBe("Login -> GenerateToken");
|
|
88
88
|
expect(reranked.note).toMatch(/Top matches/i);
|
|
89
89
|
});
|
|
90
|
+
test("impact 可复用 context 解析出的 symbol id", () => {
|
|
91
|
+
expect(extractResolvedSymbolIdFromContext({
|
|
92
|
+
target: { id: "Method:sysAuthController.js:login:18", name: "login" },
|
|
93
|
+
})).toBe("Method:sysAuthController.js:login:18");
|
|
94
|
+
expect(extractResolvedSymbolIdFromContext({
|
|
95
|
+
symbol: { uid: "Function:src/auth.ts:login" },
|
|
96
|
+
})).toBe("Function:src/auth.ts:login");
|
|
97
|
+
});
|
|
90
98
|
test.runIf(process.platform === "win32")("Windows 下带空格路径的 cmd 可执行文件可以真实启动", async () => {
|
|
91
99
|
const root = makeTempDir("gitnexus-space-");
|
|
92
100
|
const executable = path.join(root, "Program Files", "tool.cmd");
|
|
@@ -77,6 +77,7 @@ export declare function resolveSpawnCommand(command: string, args: string[], pla
|
|
|
77
77
|
command: string;
|
|
78
78
|
args: string[];
|
|
79
79
|
};
|
|
80
|
+
export declare function extractResolvedSymbolIdFromContext(value: unknown): string | undefined;
|
|
80
81
|
export declare function rerankQueryStructuredContent(structuredContent: unknown, hints: {
|
|
81
82
|
query?: string;
|
|
82
83
|
goal?: string;
|
|
@@ -333,6 +333,83 @@ function buildAmbiguities(executions) {
|
|
|
333
333
|
};
|
|
334
334
|
});
|
|
335
335
|
}
|
|
336
|
+
function getLastExecutionByTool(executions, tool) {
|
|
337
|
+
for (let index = executions.length - 1; index >= 0; index -= 1) {
|
|
338
|
+
if (executions[index]?.tool === tool) {
|
|
339
|
+
return executions[index];
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
return undefined;
|
|
343
|
+
}
|
|
344
|
+
function inferSymbolKind(value) {
|
|
345
|
+
const record = toRecord(value);
|
|
346
|
+
if (!record) {
|
|
347
|
+
return undefined;
|
|
348
|
+
}
|
|
349
|
+
for (const key of ["kind", "type", "symbolType"]) {
|
|
350
|
+
const candidate = record[key];
|
|
351
|
+
if (typeof candidate === "string" && candidate.trim()) {
|
|
352
|
+
return candidate.trim();
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
const id = record.id;
|
|
356
|
+
if (typeof id === "string" && id.includes(":")) {
|
|
357
|
+
return id.split(":")[0];
|
|
358
|
+
}
|
|
359
|
+
return undefined;
|
|
360
|
+
}
|
|
361
|
+
function isNonCallableSymbolKind(kind) {
|
|
362
|
+
if (!kind) {
|
|
363
|
+
return false;
|
|
364
|
+
}
|
|
365
|
+
const normalized = kind.toLowerCase();
|
|
366
|
+
return normalized.includes("folder")
|
|
367
|
+
|| normalized.includes("file")
|
|
368
|
+
|| normalized.includes("module")
|
|
369
|
+
|| normalized.includes("community")
|
|
370
|
+
|| normalized.includes("process")
|
|
371
|
+
|| normalized.includes("package");
|
|
372
|
+
}
|
|
373
|
+
export function extractResolvedSymbolIdFromContext(value) {
|
|
374
|
+
const record = toRecord(value);
|
|
375
|
+
if (!record) {
|
|
376
|
+
return undefined;
|
|
377
|
+
}
|
|
378
|
+
const direct = [record.uid, record.id, record.targetUid, record.targetId]
|
|
379
|
+
.find((item) => typeof item === "string" && item.trim());
|
|
380
|
+
if (typeof direct === "string") {
|
|
381
|
+
return direct.trim();
|
|
382
|
+
}
|
|
383
|
+
for (const key of ["target", "symbol", "node", "element"]) {
|
|
384
|
+
const nested = toRecord(record[key]);
|
|
385
|
+
if (!nested) {
|
|
386
|
+
continue;
|
|
387
|
+
}
|
|
388
|
+
const candidate = [nested.uid, nested.id]
|
|
389
|
+
.find((item) => typeof item === "string" && item.trim());
|
|
390
|
+
if (typeof candidate === "string") {
|
|
391
|
+
return candidate.trim();
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
return undefined;
|
|
395
|
+
}
|
|
396
|
+
function normalizeImpactTargetByContext(contextExecution, originalTarget) {
|
|
397
|
+
const target = toRecord(contextExecution.structuredContent)?.target;
|
|
398
|
+
const kind = inferSymbolKind(target);
|
|
399
|
+
if (!isNonCallableSymbolKind(kind)) {
|
|
400
|
+
return contextExecution;
|
|
401
|
+
}
|
|
402
|
+
const message = `impact 目标 "${originalTarget}" 被解析为 ${kind},请改用函数/方法 uid 或补充 file_path 再重试。`;
|
|
403
|
+
contextExecution.status = "ambiguous";
|
|
404
|
+
contextExecution.text = message;
|
|
405
|
+
contextExecution.structuredContent = {
|
|
406
|
+
status: "ambiguous",
|
|
407
|
+
message,
|
|
408
|
+
suggestion: "For impact analysis, prefer Method/Function over Folder/File.",
|
|
409
|
+
candidates: target ? [target] : [],
|
|
410
|
+
};
|
|
411
|
+
return contextExecution;
|
|
412
|
+
}
|
|
336
413
|
const QUERY_STOP_WORDS = new Set([
|
|
337
414
|
"the", "and", "for", "with", "from", "into", "that", "this", "user", "flow",
|
|
338
415
|
"sign", "code", "project", "module",
|
|
@@ -383,23 +460,38 @@ function scoreQueryCandidate(candidate, terms) {
|
|
|
383
460
|
if (fields.length === 0 || terms.length === 0) {
|
|
384
461
|
return 0;
|
|
385
462
|
}
|
|
386
|
-
let score =
|
|
463
|
+
let score = -30;
|
|
387
464
|
let matchedTerms = 0;
|
|
388
465
|
for (const term of terms) {
|
|
389
466
|
let matched = false;
|
|
390
467
|
for (const field of fields) {
|
|
391
|
-
|
|
468
|
+
const value = field.value;
|
|
469
|
+
const key = field.key;
|
|
470
|
+
const exact = value === term;
|
|
471
|
+
const wholeWord = new RegExp(`\\b${term.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\b`, "i").test(value);
|
|
472
|
+
const partial = value.includes(term);
|
|
473
|
+
if (!partial) {
|
|
392
474
|
continue;
|
|
393
475
|
}
|
|
394
476
|
matched = true;
|
|
395
|
-
|
|
396
|
-
|
|
477
|
+
const inName = key.includes("name") || key.includes("title") || key.includes("label") || key.includes("symbol");
|
|
478
|
+
const inPath = key.includes("path") || key.includes("file") || key.includes("module");
|
|
479
|
+
const inDocs = key.includes("comment") || key.includes("doc") || key.includes("description") || key.includes("summary");
|
|
480
|
+
const inCode = key.includes("content") || key.includes("source") || key.includes("body") || key.includes("code");
|
|
481
|
+
if (inName) {
|
|
482
|
+
score += exact ? 120 : wholeWord ? 90 : 55;
|
|
483
|
+
}
|
|
484
|
+
else if (inPath) {
|
|
485
|
+
score += wholeWord ? 70 : 45;
|
|
486
|
+
}
|
|
487
|
+
else if (inDocs) {
|
|
488
|
+
score += wholeWord ? 26 : 16;
|
|
397
489
|
}
|
|
398
|
-
else if (
|
|
399
|
-
score += 10;
|
|
490
|
+
else if (inCode) {
|
|
491
|
+
score += wholeWord ? 18 : 10;
|
|
400
492
|
}
|
|
401
493
|
else {
|
|
402
|
-
score +=
|
|
494
|
+
score += wholeWord ? 24 : 12;
|
|
403
495
|
}
|
|
404
496
|
}
|
|
405
497
|
if (matched) {
|
|
@@ -407,15 +499,18 @@ function scoreQueryCandidate(candidate, terms) {
|
|
|
407
499
|
}
|
|
408
500
|
}
|
|
409
501
|
if (matchedTerms > 0) {
|
|
410
|
-
score += matchedTerms *
|
|
502
|
+
score += matchedTerms * 14;
|
|
503
|
+
}
|
|
504
|
+
else {
|
|
505
|
+
score -= 60;
|
|
411
506
|
}
|
|
412
507
|
if (matchedTerms === terms.length) {
|
|
413
|
-
score +=
|
|
508
|
+
score += 35;
|
|
414
509
|
}
|
|
415
510
|
const candidateRecord = toRecord(candidate);
|
|
416
511
|
const priority = candidateRecord?.priority;
|
|
417
512
|
if (typeof priority === "number" && Number.isFinite(priority)) {
|
|
418
|
-
score += priority;
|
|
513
|
+
score += matchedTerms > 0 ? (priority * 5) : (priority * 0.5);
|
|
419
514
|
}
|
|
420
515
|
return score;
|
|
421
516
|
}
|
|
@@ -957,8 +1052,35 @@ export async function runCodeInsightBridge(request) {
|
|
|
957
1052
|
warnings.push("缺少 target/uid 参数,已跳过 impact");
|
|
958
1053
|
return;
|
|
959
1054
|
}
|
|
1055
|
+
let impactTarget = request.uid || request.target;
|
|
1056
|
+
if (!request.uid && request.target) {
|
|
1057
|
+
let contextExecution = getLastExecutionByTool(executions, "context");
|
|
1058
|
+
if (!contextExecution) {
|
|
1059
|
+
contextExecution = await callBridgeTool(client, "context", {
|
|
1060
|
+
name: request.target,
|
|
1061
|
+
...(request.filePath ? { file_path: request.filePath } : {}),
|
|
1062
|
+
...(effectiveRepo ? { repo: effectiveRepo } : {}),
|
|
1063
|
+
}, request.signal, workspace);
|
|
1064
|
+
executions.push(contextExecution);
|
|
1065
|
+
}
|
|
1066
|
+
if (contextExecution.ok && contextExecution.status === "ambiguous") {
|
|
1067
|
+
warnings.push("impact_target_ambiguous");
|
|
1068
|
+
return;
|
|
1069
|
+
}
|
|
1070
|
+
if (contextExecution.ok) {
|
|
1071
|
+
normalizeImpactTargetByContext(contextExecution, request.target);
|
|
1072
|
+
if (contextExecution.status === "ambiguous") {
|
|
1073
|
+
warnings.push("impact_target_non_callable");
|
|
1074
|
+
return;
|
|
1075
|
+
}
|
|
1076
|
+
const resolvedTargetId = extractResolvedSymbolIdFromContext(contextExecution.structuredContent);
|
|
1077
|
+
if (resolvedTargetId) {
|
|
1078
|
+
impactTarget = resolvedTargetId;
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
960
1082
|
executions.push(await callBridgeTool(client, "impact", {
|
|
961
|
-
target:
|
|
1083
|
+
target: impactTarget,
|
|
962
1084
|
direction: request.direction || "upstream",
|
|
963
1085
|
...(request.maxDepth ? { maxDepth: request.maxDepth } : {}),
|
|
964
1086
|
...(typeof request.includeTests === "boolean"
|
|
@@ -101,6 +101,7 @@ describe("code_insight 单元测试", () => {
|
|
|
101
101
|
});
|
|
102
102
|
expect(status).toBe("ambiguous");
|
|
103
103
|
expect(plan?.kind).toBe("ambiguity");
|
|
104
|
+
expect(plan?.steps).toHaveLength(2);
|
|
104
105
|
expect(plan?.steps[1].action).toMatch(/uid 或 file_path/);
|
|
105
106
|
});
|
|
106
107
|
test("未显式要求保存时不生成 docs delegated plan", async () => {
|
|
@@ -113,7 +114,8 @@ describe("code_insight 单元测试", () => {
|
|
|
113
114
|
expect(result.isError).toBe(false);
|
|
114
115
|
const text = String(result.content?.[0]?.text || "");
|
|
115
116
|
const structured = result.structuredContent;
|
|
116
|
-
expect(text).not.toMatch(
|
|
117
|
+
expect(text).not.toMatch(/## delegated plan/);
|
|
118
|
+
expect(text).toMatch(/使用场景指南/);
|
|
117
119
|
expect(structured.plan).toBeUndefined();
|
|
118
120
|
expect(structured.projectDocs).toBeUndefined();
|
|
119
121
|
}
|
|
@@ -141,15 +143,16 @@ describe("code_insight 单元测试", () => {
|
|
|
141
143
|
expect(text).toMatch(/delegated plan/);
|
|
142
144
|
expect(text).toMatch(/不要只口头总结而不写文件/);
|
|
143
145
|
expect(text).toMatch(/docs\/graph-insights\/latest\.md/);
|
|
144
|
-
expect(text).toMatch(
|
|
146
|
+
expect(text).toMatch(/使用场景指南/);
|
|
145
147
|
expect(structured.projectDocs.latestMarkdownFilePath).toContain("/docs/graph-insights/latest.md");
|
|
146
148
|
expect(structured.projectDocs.archiveMarkdownFilePath).toContain("/docs/graph-insights/");
|
|
147
149
|
expect(structured.projectDocs.projectContextFilePath).toContain("/docs/project-context.md");
|
|
148
150
|
expect(structured.projectDocs.navigationSnippet).toMatch(/代码图谱洞察/);
|
|
149
151
|
expect(structured.plan.mode).toBe("delegated");
|
|
150
|
-
expect(structured.plan.steps
|
|
151
|
-
|
|
152
|
-
expect(
|
|
152
|
+
expect(structured.plan.steps).toHaveLength(2);
|
|
153
|
+
expect(structured.plan.steps[0].id).toBe("consume-result");
|
|
154
|
+
expect(structured.plan.steps[1].id).toBe("optional-save");
|
|
155
|
+
expect(structured.plan.steps[1].outputs[0]).toContain("/docs/graph-insights/latest.md");
|
|
153
156
|
expect(fs.existsSync(path.join(projectRoot, "docs", "graph-insights", "latest.md"))).toBe(false);
|
|
154
157
|
}
|
|
155
158
|
finally {
|
|
@@ -151,17 +151,12 @@ export function buildCodeInsightDelegatedPlan(input) {
|
|
|
151
151
|
kind: "ambiguity",
|
|
152
152
|
steps: [
|
|
153
153
|
{
|
|
154
|
-
id: "
|
|
155
|
-
action: "
|
|
156
|
-
note: "若存在同名符号,优先使用 uid;需要限定文件时使用 file_path",
|
|
154
|
+
id: "consume-candidates",
|
|
155
|
+
action: "消费本次 candidates 列表,确认唯一目标符号(优先 uid,其次 file_path)",
|
|
157
156
|
},
|
|
158
157
|
{
|
|
159
158
|
id: "rerun-with-disambiguate",
|
|
160
|
-
action: "重新调用 code_insight
|
|
161
|
-
},
|
|
162
|
-
{
|
|
163
|
-
id: "resume-analysis",
|
|
164
|
-
action: "消歧后再继续 context/impact 分析,必要时再决定是否保存到 docs/graph-insights",
|
|
159
|
+
action: "重新调用 code_insight,并传入 uid 或 file_path 后继续 context/impact 分析",
|
|
165
160
|
},
|
|
166
161
|
],
|
|
167
162
|
};
|
|
@@ -175,45 +170,32 @@ export function buildCodeInsightDelegatedPlan(input) {
|
|
|
175
170
|
kind: "docs",
|
|
176
171
|
steps: [
|
|
177
172
|
{
|
|
178
|
-
id: "
|
|
179
|
-
action:
|
|
180
|
-
? `确认 ${input.projectDocs.projectContextFilePath} 已存在并可更新`
|
|
181
|
-
: `检查 ${input.projectDocs.projectContextFilePath} 是否存在;若不存在,先调用 init_project_context 生成项目上下文索引`,
|
|
182
|
-
outputs: [input.projectDocs.projectContextFilePath],
|
|
183
|
-
note: projectContextExists
|
|
184
|
-
? "已有项目上下文,可直接补充图谱入口"
|
|
185
|
-
: "只有 project-context.md 存在,后续图谱文档入口才可持续复用",
|
|
186
|
-
},
|
|
187
|
-
{
|
|
188
|
-
id: "save-latest-md",
|
|
189
|
-
action: `将本次 code_insight 的文本分析结果写入 ${input.projectDocs.latestMarkdownFilePath}`,
|
|
190
|
-
outputs: [input.projectDocs.latestMarkdownFilePath],
|
|
191
|
-
},
|
|
192
|
-
{
|
|
193
|
-
id: "save-archive-md",
|
|
194
|
-
action: `将本次 code_insight 的文本分析结果归档到 ${input.projectDocs.archiveMarkdownFilePath}`,
|
|
195
|
-
outputs: [input.projectDocs.archiveMarkdownFilePath],
|
|
196
|
-
},
|
|
197
|
-
{
|
|
198
|
-
id: "save-latest-json",
|
|
199
|
-
action: `将本次 code_insight 的 structuredContent 写入 ${input.projectDocs.latestJsonFilePath}`,
|
|
200
|
-
outputs: [input.projectDocs.latestJsonFilePath],
|
|
201
|
-
note: "建议保留完整结构化结果,便于后续 AI 继续读取",
|
|
202
|
-
},
|
|
203
|
-
{
|
|
204
|
-
id: "save-archive-json",
|
|
205
|
-
action: `将本次 code_insight 的 structuredContent 归档到 ${input.projectDocs.archiveJsonFilePath}`,
|
|
206
|
-
outputs: [input.projectDocs.archiveJsonFilePath],
|
|
173
|
+
id: "consume-result",
|
|
174
|
+
action: "先消费本次分析结果(processes/symbols/impact),确认是否满足当前问题",
|
|
207
175
|
},
|
|
208
176
|
{
|
|
209
|
-
id: "
|
|
210
|
-
action:
|
|
211
|
-
outputs: [input.projectDocs.
|
|
212
|
-
note:
|
|
177
|
+
id: "optional-save",
|
|
178
|
+
action: `如需保存,再写入 ${input.projectDocs.latestMarkdownFilePath}(文本)和 ${input.projectDocs.latestJsonFilePath}(结构化)`,
|
|
179
|
+
outputs: [input.projectDocs.latestMarkdownFilePath, input.projectDocs.latestJsonFilePath],
|
|
180
|
+
note: projectContextExists
|
|
181
|
+
? `可选同步更新 ${input.projectDocs.projectContextFilePath} 的图谱入口`
|
|
182
|
+
: "若后续要持续沉淀,建议先补 init_project_context",
|
|
213
183
|
},
|
|
214
184
|
],
|
|
215
185
|
};
|
|
216
186
|
}
|
|
187
|
+
function renderUsageGuide() {
|
|
188
|
+
return `## 使用场景指南
|
|
189
|
+
- 探索调用链: \`{ mode: "query", query: "login", goal: "理解登录认证流程" }\`
|
|
190
|
+
- 深入函数上下文: \`{ mode: "context", target: "login", file_path: "src/auth/login.ts" }\`
|
|
191
|
+
- 评估影响范围: \`{ mode: "impact", target: "login", direction: "upstream", file_path: "..." }\`
|
|
192
|
+
- 查看代码内容: \`{ mode: "context", target: "login", include_content: true }\`
|
|
193
|
+
|
|
194
|
+
## 下一步建议
|
|
195
|
+
- 查询不精确: 增加 \`goal\`(例如“理解登录认证流程”)
|
|
196
|
+
- 出现歧义: 传入 \`uid\` 或 \`file_path\` 重新执行
|
|
197
|
+
- 需要落盘: 传 \`save_to_docs: true\`,再按 delegated plan 写入 docs/graph-insights`;
|
|
198
|
+
}
|
|
217
199
|
export function resolveCodeInsightQuery(input) {
|
|
218
200
|
const finalTarget = input.target || ((input.mode === "context" || input.mode === "impact") ? input.input : "");
|
|
219
201
|
const finalQuery = input.query
|
|
@@ -325,6 +307,7 @@ ${executionSummary}
|
|
|
325
307
|
|
|
326
308
|
${ambiguityText ? `歧义候选:\n${ambiguityText}\n\n` : ""}\
|
|
327
309
|
${result.warnings.length > 0 ? `警告: ${result.warnings.join(", ")}` : ""}`.trim();
|
|
310
|
+
const usageGuide = renderUsageGuide();
|
|
328
311
|
const structured = {
|
|
329
312
|
status,
|
|
330
313
|
provider: result.provider,
|
|
@@ -397,13 +380,15 @@ ${result.warnings.length > 0 ? `警告: ${result.warnings.join(", ")}` : ""}`.tr
|
|
|
397
380
|
${renderPlanSteps(delegatedPlan.steps)}
|
|
398
381
|
|
|
399
382
|
${delegatedPlan.kind === "docs" && projectDocs ? `后续操作:
|
|
400
|
-
-
|
|
401
|
-
-
|
|
402
|
-
- 如需归档,请额外保存到 ${projectDocs.archiveMarkdownFilePath}
|
|
403
|
-
- 如需结构化副本,请保存 JSON 到 ${projectDocs.latestJsonFilePath} 或 ${projectDocs.archiveJsonFilePath}` : `后续操作:
|
|
383
|
+
- 如需落盘,写入 ${projectDocs.latestMarkdownFilePath} 与 ${projectDocs.latestJsonFilePath}
|
|
384
|
+
- 如需长期沉淀,可再补充 ${projectDocs.projectContextFilePath} 的图谱入口` : `后续操作:
|
|
404
385
|
- 请先从 candidates 中选定唯一符号
|
|
405
|
-
- 重新传入 uid 或 file_path 后再继续 context / impact 分析`}
|
|
406
|
-
|
|
386
|
+
- 重新传入 uid 或 file_path 后再继续 context / impact 分析`}
|
|
387
|
+
|
|
388
|
+
${usageGuide}`
|
|
389
|
+
: `${message}
|
|
390
|
+
|
|
391
|
+
${usageGuide}`, structured);
|
|
407
392
|
}
|
|
408
393
|
catch (error) {
|
|
409
394
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
package/docs/i18n/en.json
CHANGED
|
@@ -93,6 +93,8 @@
|
|
|
93
93
|
"item1": "The first cold start may take 20+ seconds while npx checks or downloads dependencies.",
|
|
94
94
|
"item2": "Some GitNexus dependencies use tree-sitter native modules and may require Visual Studio Build Tools.",
|
|
95
95
|
"item3": "If your MCP client supports env, prefer a preinstalled gitnexus CLI and raise GitNexus timeouts.",
|
|
96
|
+
"item4": "Quick install Build Tools on Windows: winget install Microsoft.VisualStudio.2022.BuildTools",
|
|
97
|
+
"quickInstallTitle": "Quick install command:",
|
|
96
98
|
"exampleTitle": "Example using a preinstalled gitnexus CLI:"
|
|
97
99
|
},
|
|
98
100
|
"source": {
|
package/docs/i18n/ja.json
CHANGED
|
@@ -93,6 +93,8 @@
|
|
|
93
93
|
"item1": "初回のコールドスタートでは、npx が依存関係を確認またはダウンロードするため 20 秒以上かかることがあります。",
|
|
94
94
|
"item2": "GitNexus の一部依存関係は tree-sitter ネイティブモジュールを使用しており、Windows では Visual Studio Build Tools が必要になる場合があります。",
|
|
95
95
|
"item3": "MCP クライアントが env をサポートしている場合は、プリインストール済みの gitnexus CLI を優先し、GitNexus のタイムアウトを引き上げてください。",
|
|
96
|
+
"item4": "Windows では winget で Build Tools をすばやくインストールできます:winget install Microsoft.VisualStudio.2022.BuildTools",
|
|
97
|
+
"quickInstallTitle": "クイックインストールコマンド:",
|
|
96
98
|
"exampleTitle": "プリインストール済み gitnexus CLI を使う設定例:"
|
|
97
99
|
},
|
|
98
100
|
"source": {
|
package/docs/i18n/ko.json
CHANGED
|
@@ -93,6 +93,8 @@
|
|
|
93
93
|
"item1": "첫 콜드 스타트에서는 npx 가 의존성을 확인하거나 다운로드하므로 20초 이상 걸릴 수 있습니다.",
|
|
94
94
|
"item2": "GitNexus 의 일부 의존성은 tree-sitter 네이티브 모듈을 사용하며 Windows 에서는 Visual Studio Build Tools 가 필요할 수 있습니다.",
|
|
95
95
|
"item3": "MCP 클라이언트가 env 를 지원하면, 미리 설치한 gitnexus CLI 를 우선 사용하고 GitNexus 타임아웃을 늘리세요.",
|
|
96
|
+
"item4": "Windows 에서 Build Tools 빠른 설치: winget install Microsoft.VisualStudio.2022.BuildTools",
|
|
97
|
+
"quickInstallTitle": "빠른 설치 명령:",
|
|
96
98
|
"exampleTitle": "미리 설치한 gitnexus CLI 를 사용하는 구성 예시:"
|
|
97
99
|
},
|
|
98
100
|
"source": {
|
package/docs/i18n/zh-CN.json
CHANGED
|
@@ -93,6 +93,8 @@
|
|
|
93
93
|
"item1": "首次冷启动时,npx 可能检查或下载依赖,耗时可能超过 20 秒。",
|
|
94
94
|
"item2": "GitNexus 的部分依赖使用 tree-sitter 原生模块,在 Windows 上可能需要 Visual Studio Build Tools。",
|
|
95
95
|
"item3": "如果 MCP 客户端支持 env,优先使用预装的 gitnexus CLI,并适当增大 GitNexus 超时。",
|
|
96
|
+
"item4": "Windows 下可用 winget 快速安装 Build Tools:winget install Microsoft.VisualStudio.2022.BuildTools",
|
|
97
|
+
"quickInstallTitle": "快速安装命令:",
|
|
96
98
|
"exampleTitle": "使用预装 gitnexus CLI 的配置示例:"
|
|
97
99
|
},
|
|
98
100
|
"source": {
|
|
@@ -317,7 +317,10 @@ npm run build</code></pre>
|
|
|
317
317
|
<li data-i18n="gettingStarted.step1.windowsGraph.item1">The first cold start may take 20+ seconds while npx checks or downloads dependencies.</li>
|
|
318
318
|
<li data-i18n="gettingStarted.step1.windowsGraph.item2">Some GitNexus dependencies use tree-sitter native modules and may require Visual Studio Build Tools.</li>
|
|
319
319
|
<li data-i18n="gettingStarted.step1.windowsGraph.item3">If your MCP client supports env, prefer a preinstalled gitnexus CLI and raise GitNexus timeouts.</li>
|
|
320
|
+
<li data-i18n="gettingStarted.step1.windowsGraph.item4">Quick install Build Tools on Windows: winget install Microsoft.VisualStudio.2022.BuildTools</li>
|
|
320
321
|
</ul>
|
|
322
|
+
<p class="mb-2" data-i18n="gettingStarted.step1.windowsGraph.quickInstallTitle">Quick install command:</p>
|
|
323
|
+
<pre class="code-block mb-3 p-3 text-sm text-slate-200 bg-slate-900 rounded overflow-x-auto"><code>winget install Microsoft.VisualStudio.2022.BuildTools</code></pre>
|
|
321
324
|
<p class="mb-2" data-i18n="gettingStarted.step1.windowsGraph.exampleTitle">Example using a preinstalled gitnexus CLI:</p>
|
|
322
325
|
<div class="bg-slate-900 rounded-lg overflow-hidden">
|
|
323
326
|
<div class="flex items-center justify-between px-3 py-2 bg-slate-800">
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mcp-probe-kit",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.15",
|
|
4
4
|
"description": "AI-Powered Development Toolkit - MCP Server with 22 tools covering code quality, development efficiency, project management, and UI/UX design. Features: Structured Output, Workflow Orchestration, UI/UX Pro Max, and Requirements Interview.",
|
|
5
5
|
"mcpName": "io.github.mybolide/mcp-probe-kit",
|
|
6
6
|
"type": "module",
|