mcp-probe-kit 3.0.6 → 3.0.8

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.
Files changed (35) hide show
  1. package/README.md +19 -10
  2. package/build/index.js +441 -1
  3. package/build/lib/gitnexus-bridge.d.ts +58 -0
  4. package/build/lib/gitnexus-bridge.js +379 -0
  5. package/build/lib/toolset-manager.d.ts +1 -1
  6. package/build/lib/toolset-manager.js +7 -5
  7. package/build/schemas/code-analysis-tools.d.ts +46 -0
  8. package/build/schemas/code-analysis-tools.js +47 -0
  9. package/build/schemas/index.d.ts +46 -0
  10. package/build/tools/__tests__/code_insight.unit.test.d.ts +1 -0
  11. package/build/tools/__tests__/code_insight.unit.test.js +35 -0
  12. package/build/tools/code_insight.d.ts +8 -0
  13. package/build/tools/code_insight.js +129 -0
  14. package/build/tools/index.d.ts +1 -0
  15. package/build/tools/index.js +1 -0
  16. package/build/tools/start_bugfix.js +39 -4
  17. package/build/tools/start_feature.js +43 -8
  18. package/docs/data/tools.js +34 -14
  19. package/docs/i18n/all-tools/en.json +162 -157
  20. package/docs/i18n/all-tools/ja.json +162 -157
  21. package/docs/i18n/all-tools/ko.json +162 -157
  22. package/docs/i18n/all-tools/zh-CN.json +162 -157
  23. package/docs/i18n/en.json +10 -10
  24. package/docs/i18n/ja.json +10 -10
  25. package/docs/i18n/ko.json +10 -10
  26. package/docs/i18n/zh-CN.json +10 -10
  27. package/docs/index.html +9 -9
  28. package/docs/pages/all-tools.html +9 -9
  29. package/docs/pages/examples.html +4 -4
  30. package/docs/pages/getting-started.html +3 -3
  31. package/docs/pages/migration.html +4 -4
  32. package/docs/specs/user-auth/design.md +82 -0
  33. package/docs/specs/user-auth/requirements.md +52 -0
  34. package/docs/specs/user-auth/tasks.md +55 -0
  35. package/package.json +3 -3
package/README.md CHANGED
@@ -13,7 +13,7 @@
13
13
 
14
14
  > **Talk is cheap, show me the Context.**
15
15
  >
16
- > mcp-probe-kit is a protocol-level toolkit designed for developers who want AI to truly understand their project's intent. It's not just a collection of 21 tools—it's a context-aware system that helps AI agents grasp what you're building.
16
+ > mcp-probe-kit is a protocol-level toolkit designed for developers who want AI to truly understand their project's intent. It's not just a collection of 22 tools—it's a context-aware system that helps AI agents grasp what you're building.
17
17
 
18
18
  **Languages**: [English](README.md) | [简体中文](i18n/README.zh-CN.md) | [日本語](i18n/README.ja-JP.md) | [한국어](i18n/README.ko-KR.md) | [Español](i18n/README.es-ES.md) | [Français](i18n/README.fr-FR.md) | [Deutsch](i18n/README.de-DE.md) | [Português (BR)](i18n/README.pt-BR.md)
19
19
 
@@ -24,7 +24,7 @@
24
24
 
25
25
  > 🚀 AI-Powered Complete Development Toolkit - Covering the Entire Development Lifecycle
26
26
 
27
- A powerful MCP (Model Context Protocol) server providing **21 tools** covering the complete workflow from product analysis to final release (Requirements → Design → Development → Quality → Release), all tools support **structured output**.
27
+ A powerful MCP (Model Context Protocol) server providing **22 tools** covering the complete workflow from product analysis to final release (Requirements → Design → Development → Quality → Release), all tools support **structured output**.
28
28
 
29
29
  **🎉 v3.0 Major Update**: Streamlined tool count, focus on core competencies, eliminate choice paralysis, let AI do more native work
30
30
 
@@ -39,7 +39,7 @@ A powerful MCP (Model Context Protocol) server providing **21 tools** covering t
39
39
  **👉 [https://mcp-probe-kit.bytezonex.com](https://mcp-probe-kit.bytezonex.com/)**
40
40
 
41
41
  - [Quick Start](https://mcp-probe-kit.bytezonex.com/pages/getting-started.html) - Setup in 5 minutes
42
- - [All Tools](https://mcp-probe-kit.bytezonex.com/pages/all-tools.html) - Complete list of 21 tools
42
+ - [All Tools](https://mcp-probe-kit.bytezonex.com/pages/all-tools.html) - Complete list of 22 tools
43
43
  - [Best Practices](https://mcp-probe-kit.bytezonex.com/pages/examples.html) - Full development workflow guide
44
44
  - [v3.0 Migration Guide](https://mcp-probe-kit.bytezonex.com/pages/migration.html) - Upgrade from v2.x to v3.0
45
45
 
@@ -47,20 +47,29 @@ A powerful MCP (Model Context Protocol) server providing **21 tools** covering t
47
47
 
48
48
  ## ✨ Core Features
49
49
 
50
- ### 📦 21 Tools
50
+ ### 📦 22 Tools
51
51
 
52
52
  - **🔄 Workflow Orchestration** (6 tools) - One-click complex development workflows
53
53
  - `start_feature`, `start_bugfix`, `start_onboard`, `start_ui`, `start_product`, `start_ralph`
54
- - **🔍 Code Analysis** (3 tools) - Code quality and refactoring
55
- - `code_review`, `fix_bug`, `refactor`
54
+ - **🔍 Code Analysis** (4 tools) - Code quality, refactoring, and graph insight
55
+ - `code_review`, `code_insight`, `fix_bug`, `refactor`
56
56
  - **📝 Git Tools** (2 tools) - Git commits and work reports
57
57
  - `gencommit`, `git_work_report`
58
58
  - **⚡ Code Generation** (1 tool) - Test generation
59
59
  - `gentest`
60
- - **📦 Project Management** (7 tools) - Project initialization and requirements management
61
- - `init_project`, `init_project_context`, `add_feature`, `estimate`, `interview`, `ask_user`
62
- - **🎨 UI/UX Tools** (3 tools) - Design systems and data synchronization
63
- - `ui_design_system`, `ui_search`, `sync_ui_data`
60
+ - **📦 Project Management** (6 tools) - Project initialization and requirements management
61
+ - `init_project`, `init_project_context`, `add_feature`, `estimate`, `interview`, `ask_user`
62
+ - **🎨 UI/UX Tools** (3 tools) - Design systems and data synchronization
63
+ - `ui_design_system`, `ui_search`, `sync_ui_data`
64
+
65
+ ### 🧠 Code Graph Bridge (GitNexus)
66
+
67
+ - `code_insight` bridges GitNexus by default for query/context/impact analysis
68
+ - `start_feature` and `start_bugfix` automatically enrich plans with graph context when available
69
+ - If GitNexus is unavailable, the server falls back automatically without breaking orchestration
70
+ - Graph snapshots are exposed as resources (`probe://graph/latest`, `probe://graph/history`, `probe://graph/latest.md`)
71
+ - Graph snapshots are also persisted to readable files in `.mcp-probe-kit/graph-snapshots` (customizable via `MCP_GRAPH_SNAPSHOT_DIR`)
72
+ - Tool responses include `_meta.graph` with snapshot URI and local JSON/Markdown file paths
64
73
 
65
74
  ### 🎯 Structured Output
66
75
 
package/build/index.js CHANGED
@@ -3,15 +3,21 @@ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
3
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
4
  import { InMemoryTaskMessageQueue, InMemoryTaskStore, } from "@modelcontextprotocol/sdk/experimental/index.js";
5
5
  import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ProgressNotificationSchema, ReadResourceRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
6
- import { initProject, gencommit, codeReview, gentest, refactor, initProjectContext, addFeature, fixBug, estimate, startFeature, startBugfix, startOnboard, startRalph, interview, askUser, uiDesignSystem, uiSearch, syncUiData, startUi, startProduct, gitWorkReport } from "./tools/index.js";
6
+ import * as fs from "node:fs";
7
+ import * as path from "node:path";
8
+ import { initProject, gencommit, codeReview, codeInsight, gentest, refactor, initProjectContext, addFeature, fixBug, estimate, startFeature, startBugfix, startOnboard, startRalph, interview, askUser, uiDesignSystem, uiSearch, syncUiData, startUi, startProduct, gitWorkReport } from "./tools/index.js";
7
9
  import { VERSION, NAME } from "./version.js";
8
10
  import { allToolSchemas } from "./schemas/index.js";
9
11
  import { filterTools, getToolsetFromEnv } from "./lib/toolset-manager.js";
10
12
  import { isAbortError, } from "./lib/tool-execution-context.js";
11
13
  const EXTENSIONS_CAPABILITY_KEY = "io.github.mybolide/extensions";
12
14
  const MAX_UI_APP_RESOURCES = 30;
15
+ const MAX_GRAPH_SNAPSHOTS = 20;
16
+ const DEFAULT_GRAPH_SNAPSHOT_DIR = path.resolve(process.cwd(), ".mcp-probe-kit", "graph-snapshots");
13
17
  const uiAppResources = new Map();
14
18
  const uiAppResourceOrder = [];
19
+ const graphSnapshots = new Map();
20
+ const graphSnapshotOrder = [];
15
21
  function isEnvEnabled(name, fallback = false) {
16
22
  const raw = process.env[name];
17
23
  if (raw === undefined) {
@@ -19,9 +25,17 @@ function isEnvEnabled(name, fallback = false) {
19
25
  }
20
26
  return /^(1|true|yes|on)$/i.test(raw.trim());
21
27
  }
28
+ function resolveGraphSnapshotDir() {
29
+ const raw = process.env.MCP_GRAPH_SNAPSHOT_DIR?.trim();
30
+ if (!raw) {
31
+ return DEFAULT_GRAPH_SNAPSHOT_DIR;
32
+ }
33
+ return path.isAbsolute(raw) ? raw : path.resolve(process.cwd(), raw);
34
+ }
22
35
  const extensionsCapabilityEnabled = isEnvEnabled("MCP_ENABLE_EXTENSIONS_CAPABILITY", false);
23
36
  const uiAppsEnabled = isEnvEnabled("MCP_ENABLE_UI_APPS", false);
24
37
  const traceMetaKey = process.env.MCP_TRACE_META_KEY || "trace";
38
+ const graphSnapshotDir = resolveGraphSnapshotDir();
25
39
  const serverCapabilities = {
26
40
  tools: {},
27
41
  resources: {},
@@ -178,8 +192,203 @@ function withUiResourceMeta(result, resourceUri) {
178
192
  },
179
193
  };
180
194
  }
195
+ function withGraphSnapshotMeta(result, snapshot) {
196
+ const currentGraphMeta = result._meta?.graph;
197
+ const currentGraphMetaRecord = currentGraphMeta && typeof currentGraphMeta === "object"
198
+ ? currentGraphMeta
199
+ : {};
200
+ return {
201
+ ...result,
202
+ _meta: {
203
+ ...(result._meta ?? {}),
204
+ graph: {
205
+ ...currentGraphMetaRecord,
206
+ snapshotUri: snapshot.uri,
207
+ snapshotId: snapshot.id,
208
+ status: snapshot.status,
209
+ createdAt: snapshot.createdAt,
210
+ jsonFilePath: snapshot.jsonFilePath ?? null,
211
+ markdownFilePath: snapshot.markdownFilePath ?? null,
212
+ },
213
+ },
214
+ };
215
+ }
216
+ function trimText(value, maxLen) {
217
+ if (value.length <= maxLen) {
218
+ return value;
219
+ }
220
+ return `${value.slice(0, maxLen - 3)}...`;
221
+ }
222
+ function toPosixPath(value) {
223
+ return value.replace(/\\/g, "/");
224
+ }
225
+ function makeSafeFileSegment(value) {
226
+ return value
227
+ .toLowerCase()
228
+ .replace(/[^a-z0-9._-]+/g, "-")
229
+ .replace(/-+/g, "-")
230
+ .replace(/^-|-$/g, "")
231
+ .slice(0, 48) || "snapshot";
232
+ }
233
+ function ensureGraphSnapshotDir() {
234
+ if (!fs.existsSync(graphSnapshotDir)) {
235
+ fs.mkdirSync(graphSnapshotDir, { recursive: true });
236
+ }
237
+ }
238
+ function renderGraphSnapshotMarkdown(snapshot) {
239
+ return [
240
+ "# Graph Snapshot",
241
+ "",
242
+ `- id: ${snapshot.id}`,
243
+ `- tool: ${snapshot.toolName}`,
244
+ `- status: ${snapshot.status}`,
245
+ `- createdAt: ${snapshot.createdAt}`,
246
+ `- summary: ${snapshot.summary}`,
247
+ "",
248
+ "## Payload",
249
+ "```json",
250
+ JSON.stringify(snapshot.payload, null, 2),
251
+ "```",
252
+ "",
253
+ ].join("\n");
254
+ }
255
+ function persistGraphSnapshot(snapshot) {
256
+ try {
257
+ ensureGraphSnapshotDir();
258
+ const safeTool = makeSafeFileSegment(snapshot.toolName);
259
+ const baseName = `${snapshot.id}-${safeTool}`;
260
+ const jsonPath = path.join(graphSnapshotDir, `${baseName}.json`);
261
+ const markdownPath = path.join(graphSnapshotDir, `${baseName}.md`);
262
+ const jsonText = JSON.stringify({
263
+ id: snapshot.id,
264
+ uri: snapshot.uri,
265
+ toolName: snapshot.toolName,
266
+ createdAt: snapshot.createdAt,
267
+ status: snapshot.status,
268
+ summary: snapshot.summary,
269
+ payload: snapshot.payload,
270
+ }, null, 2);
271
+ fs.writeFileSync(jsonPath, jsonText, "utf-8");
272
+ fs.writeFileSync(markdownPath, renderGraphSnapshotMarkdown(snapshot), "utf-8");
273
+ return {
274
+ ...snapshot,
275
+ jsonFilePath: toPosixPath(jsonPath),
276
+ markdownFilePath: toPosixPath(markdownPath),
277
+ };
278
+ }
279
+ catch (error) {
280
+ const message = error instanceof Error ? error.message : String(error);
281
+ console.error(`[MCP Probe Kit] graph snapshot persist failed: ${message}`);
282
+ return snapshot;
283
+ }
284
+ }
285
+ function sanitizeGraphPayload(payload) {
286
+ if (!payload || typeof payload !== "object") {
287
+ return payload;
288
+ }
289
+ if (Array.isArray(payload)) {
290
+ return payload.slice(0, 20).map((item) => sanitizeGraphPayload(item));
291
+ }
292
+ const record = payload;
293
+ const next = {};
294
+ for (const [key, value] of Object.entries(record)) {
295
+ if (typeof value === "string") {
296
+ next[key] = trimText(value, 6000);
297
+ continue;
298
+ }
299
+ if (key === "executions" && Array.isArray(value)) {
300
+ next[key] = value.slice(0, 8).map((item) => {
301
+ if (!item || typeof item !== "object") {
302
+ return item;
303
+ }
304
+ const exec = item;
305
+ return {
306
+ ...exec,
307
+ text: typeof exec.text === "string" ? trimText(exec.text, 6000) : exec.text,
308
+ };
309
+ });
310
+ continue;
311
+ }
312
+ next[key] = sanitizeGraphPayload(value);
313
+ }
314
+ return next;
315
+ }
316
+ function readGraphPayload(toolName, result) {
317
+ if (result.isError) {
318
+ return null;
319
+ }
320
+ if (toolName === "code_insight" && result.structuredContent && typeof result.structuredContent === "object") {
321
+ const structured = result.structuredContent;
322
+ const status = typeof structured.status === "string" ? structured.status : "ok";
323
+ const summary = typeof structured.summary === "string"
324
+ ? structured.summary
325
+ : "code_insight 图谱结果";
326
+ return {
327
+ status,
328
+ summary,
329
+ payload: sanitizeGraphPayload(structured),
330
+ };
331
+ }
332
+ if ((toolName === "start_feature" || toolName === "start_bugfix")
333
+ && result.structuredContent
334
+ && typeof result.structuredContent === "object") {
335
+ const structured = result.structuredContent;
336
+ const metadata = structured.metadata;
337
+ if (!metadata || typeof metadata !== "object") {
338
+ return null;
339
+ }
340
+ const graphContext = metadata.graphContext;
341
+ if (!graphContext || typeof graphContext !== "object") {
342
+ return null;
343
+ }
344
+ const graphRecord = graphContext;
345
+ const status = graphRecord.available === false ? "degraded" : "ok";
346
+ const summary = typeof graphRecord.summary === "string"
347
+ ? graphRecord.summary
348
+ : `${toolName} 图谱上下文`;
349
+ return {
350
+ status,
351
+ summary,
352
+ payload: sanitizeGraphPayload({
353
+ graphContext,
354
+ plan: metadata.plan ?? null,
355
+ }),
356
+ };
357
+ }
358
+ return null;
359
+ }
360
+ function rememberGraphSnapshot(toolName, result) {
361
+ const graph = readGraphPayload(toolName, result);
362
+ if (!graph) {
363
+ return null;
364
+ }
365
+ const id = `${Date.now()}-${Math.random().toString(16).slice(2, 8)}`;
366
+ const uri = `probe://graph/${id}`;
367
+ const snapshot = persistGraphSnapshot({
368
+ id,
369
+ uri,
370
+ toolName,
371
+ createdAt: new Date().toISOString(),
372
+ status: graph.status,
373
+ summary: graph.summary,
374
+ payload: graph.payload,
375
+ });
376
+ graphSnapshots.set(id, snapshot);
377
+ graphSnapshotOrder.push(id);
378
+ while (graphSnapshotOrder.length > MAX_GRAPH_SNAPSHOTS) {
379
+ const oldest = graphSnapshotOrder.shift();
380
+ if (oldest) {
381
+ graphSnapshots.delete(oldest);
382
+ }
383
+ }
384
+ return snapshot;
385
+ }
181
386
  function decorateResult(toolName, args, raw, traceMeta) {
182
387
  let result = withTraceMeta(raw, traceMeta);
388
+ const snapshot = rememberGraphSnapshot(toolName, result);
389
+ if (snapshot) {
390
+ result = withGraphSnapshotMeta(result, snapshot);
391
+ }
183
392
  if (uiAppsEnabled && isUiTool(toolName) && !result.isError) {
184
393
  const resourceUri = putUiAppResource(toolName, args, result);
185
394
  result = withUiResourceMeta(result, resourceUri);
@@ -212,6 +421,8 @@ async function executeTool(name, args, context) {
212
421
  return await gencommit(args);
213
422
  case "code_review":
214
423
  return await codeReview(args);
424
+ case "code_insight":
425
+ return await codeInsight(args, context);
215
426
  case "gentest":
216
427
  return await gentest(args);
217
428
  case "refactor":
@@ -424,7 +635,43 @@ server.setRequestHandler(ListResourcesRequestSchema, async () => {
424
635
  description: "MCP Probe Kit 服务器当前状态",
425
636
  mimeType: "application/json",
426
637
  },
638
+ {
639
+ uri: "probe://graph/latest",
640
+ name: "图谱快照(最新)",
641
+ description: "最近一次 code_insight 或 start_* 生成的图谱快照",
642
+ mimeType: "application/json",
643
+ },
644
+ {
645
+ uri: "probe://graph/history",
646
+ name: "图谱快照(历史)",
647
+ description: `最近 ${graphSnapshotOrder.length} 条图谱快照摘要`,
648
+ mimeType: "application/json",
649
+ },
650
+ {
651
+ uri: "probe://graph/latest.md",
652
+ name: "图谱快照(最新 Markdown)",
653
+ description: "最近一次图谱快照的 Markdown 视图",
654
+ mimeType: "text/markdown",
655
+ },
656
+ {
657
+ uri: "probe://graph/files",
658
+ name: "图谱快照(文件索引)",
659
+ description: `图谱快照落盘目录: ${toPosixPath(graphSnapshotDir)}`,
660
+ mimeType: "application/json",
661
+ },
427
662
  ];
663
+ for (const id of graphSnapshotOrder.slice().reverse().slice(0, 10)) {
664
+ const snapshot = graphSnapshots.get(id);
665
+ if (!snapshot) {
666
+ continue;
667
+ }
668
+ resources.push({
669
+ uri: snapshot.uri,
670
+ name: `图谱快照 · ${snapshot.toolName}`,
671
+ description: `${snapshot.status} · ${trimText(snapshot.summary, 120)} (${snapshot.createdAt})`,
672
+ mimeType: "application/json",
673
+ });
674
+ }
428
675
  if (uiAppsEnabled) {
429
676
  for (const uri of uiAppResourceOrder.slice().reverse()) {
430
677
  const entry = uiAppResources.get(uri);
@@ -470,6 +717,30 @@ server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
470
717
  createMessageStream: typeof server.experimental.tasks.createMessageStream === "function",
471
718
  elicitInputStream: typeof server.experimental.tasks.elicitInputStream === "function",
472
719
  },
720
+ graphSnapshots: {
721
+ count: graphSnapshotOrder.length,
722
+ snapshotDir: toPosixPath(graphSnapshotDir),
723
+ latest: (() => {
724
+ const latestId = graphSnapshotOrder[graphSnapshotOrder.length - 1];
725
+ if (!latestId) {
726
+ return null;
727
+ }
728
+ const latest = graphSnapshots.get(latestId);
729
+ if (!latest) {
730
+ return null;
731
+ }
732
+ return {
733
+ id: latest.id,
734
+ uri: latest.uri,
735
+ toolName: latest.toolName,
736
+ status: latest.status,
737
+ summary: trimText(latest.summary, 140),
738
+ createdAt: latest.createdAt,
739
+ jsonFilePath: latest.jsonFilePath ?? null,
740
+ markdownFilePath: latest.markdownFilePath ?? null,
741
+ };
742
+ })(),
743
+ },
473
744
  toolCount: allToolSchemas.length,
474
745
  }, null, 2),
475
746
  },
@@ -491,6 +762,175 @@ server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
491
762
  ],
492
763
  };
493
764
  }
765
+ if (uri === "probe://graph/latest") {
766
+ const latestId = graphSnapshotOrder[graphSnapshotOrder.length - 1];
767
+ if (!latestId) {
768
+ return {
769
+ contents: [
770
+ {
771
+ uri,
772
+ mimeType: "application/json",
773
+ text: JSON.stringify({
774
+ status: "empty",
775
+ message: "暂无图谱快照,请先调用 code_insight 或 start_feature/start_bugfix。",
776
+ }, null, 2),
777
+ },
778
+ ],
779
+ };
780
+ }
781
+ const snapshot = graphSnapshots.get(latestId);
782
+ if (!snapshot) {
783
+ throw new Error(`图谱快照不存在: ${latestId}`);
784
+ }
785
+ return {
786
+ contents: [
787
+ {
788
+ uri,
789
+ mimeType: "application/json",
790
+ text: JSON.stringify({
791
+ id: snapshot.id,
792
+ uri: snapshot.uri,
793
+ toolName: snapshot.toolName,
794
+ createdAt: snapshot.createdAt,
795
+ status: snapshot.status,
796
+ summary: snapshot.summary,
797
+ payload: snapshot.payload,
798
+ files: {
799
+ json: snapshot.jsonFilePath ?? null,
800
+ markdown: snapshot.markdownFilePath ?? null,
801
+ },
802
+ }, null, 2),
803
+ },
804
+ ],
805
+ };
806
+ }
807
+ if (uri === "probe://graph/latest.md") {
808
+ const latestId = graphSnapshotOrder[graphSnapshotOrder.length - 1];
809
+ if (!latestId) {
810
+ return {
811
+ contents: [
812
+ {
813
+ uri,
814
+ mimeType: "text/markdown",
815
+ text: "# Graph Snapshot\n\n暂无图谱快照,请先调用 code_insight 或 start_feature/start_bugfix。",
816
+ },
817
+ ],
818
+ };
819
+ }
820
+ const snapshot = graphSnapshots.get(latestId);
821
+ if (!snapshot) {
822
+ throw new Error(`图谱快照不存在: ${latestId}`);
823
+ }
824
+ const markdown = snapshot.markdownFilePath && fs.existsSync(snapshot.markdownFilePath)
825
+ ? fs.readFileSync(snapshot.markdownFilePath, "utf-8")
826
+ : renderGraphSnapshotMarkdown(snapshot);
827
+ return {
828
+ contents: [
829
+ {
830
+ uri,
831
+ mimeType: "text/markdown",
832
+ text: markdown,
833
+ },
834
+ ],
835
+ };
836
+ }
837
+ if (uri === "probe://graph/history") {
838
+ const history = graphSnapshotOrder
839
+ .slice()
840
+ .reverse()
841
+ .map((id) => graphSnapshots.get(id))
842
+ .filter((item) => Boolean(item))
843
+ .map((item) => ({
844
+ id: item.id,
845
+ uri: item.uri,
846
+ toolName: item.toolName,
847
+ createdAt: item.createdAt,
848
+ status: item.status,
849
+ summary: trimText(item.summary, 200),
850
+ files: {
851
+ json: item.jsonFilePath ?? null,
852
+ markdown: item.markdownFilePath ?? null,
853
+ },
854
+ }));
855
+ return {
856
+ contents: [
857
+ {
858
+ uri,
859
+ mimeType: "application/json",
860
+ text: JSON.stringify({
861
+ count: history.length,
862
+ items: history,
863
+ }, null, 2),
864
+ },
865
+ ],
866
+ };
867
+ }
868
+ if (uri === "probe://graph/files") {
869
+ const latestId = graphSnapshotOrder[graphSnapshotOrder.length - 1];
870
+ const latest = latestId ? graphSnapshots.get(latestId) ?? null : null;
871
+ const hasDir = fs.existsSync(graphSnapshotDir);
872
+ const files = hasDir
873
+ ? fs
874
+ .readdirSync(graphSnapshotDir, { withFileTypes: true })
875
+ .filter((entry) => entry.isFile() && /\.(json|md)$/i.test(entry.name))
876
+ .map((entry) => toPosixPath(path.join(graphSnapshotDir, entry.name)))
877
+ .sort((a, b) => b.localeCompare(a))
878
+ .slice(0, 40)
879
+ : [];
880
+ return {
881
+ contents: [
882
+ {
883
+ uri,
884
+ mimeType: "application/json",
885
+ text: JSON.stringify({
886
+ snapshotDir: toPosixPath(graphSnapshotDir),
887
+ exists: hasDir,
888
+ latest: latest
889
+ ? {
890
+ id: latest.id,
891
+ uri: latest.uri,
892
+ toolName: latest.toolName,
893
+ jsonFilePath: latest.jsonFilePath ?? null,
894
+ markdownFilePath: latest.markdownFilePath ?? null,
895
+ }
896
+ : null,
897
+ files,
898
+ }, null, 2),
899
+ },
900
+ ],
901
+ };
902
+ }
903
+ if (uri.startsWith("probe://graph/")) {
904
+ const id = uri.slice("probe://graph/".length);
905
+ if (!id || id === "latest" || id === "history" || id === "files" || id === "latest.md") {
906
+ throw new Error(`未知图谱资源: ${uri}`);
907
+ }
908
+ const snapshot = graphSnapshots.get(id);
909
+ if (!snapshot) {
910
+ throw new Error(`图谱快照不存在: ${id}`);
911
+ }
912
+ return {
913
+ contents: [
914
+ {
915
+ uri,
916
+ mimeType: "application/json",
917
+ text: JSON.stringify({
918
+ id: snapshot.id,
919
+ uri: snapshot.uri,
920
+ toolName: snapshot.toolName,
921
+ createdAt: snapshot.createdAt,
922
+ status: snapshot.status,
923
+ summary: snapshot.summary,
924
+ payload: snapshot.payload,
925
+ files: {
926
+ json: snapshot.jsonFilePath ?? null,
927
+ markdown: snapshot.markdownFilePath ?? null,
928
+ },
929
+ }, null, 2),
930
+ },
931
+ ],
932
+ };
933
+ }
494
934
  throw new Error(`未知资源: ${uri}`);
495
935
  });
496
936
  // 启动服务器
@@ -0,0 +1,58 @@
1
+ export type CodeInsightMode = "auto" | "query" | "context" | "impact";
2
+ export type CodeInsightDirection = "upstream" | "downstream";
3
+ export interface CodeInsightRequest {
4
+ mode?: CodeInsightMode;
5
+ query?: string;
6
+ target?: string;
7
+ repo?: string;
8
+ goal?: string;
9
+ taskContext?: string;
10
+ direction?: CodeInsightDirection;
11
+ maxDepth?: number;
12
+ includeTests?: boolean;
13
+ signal?: AbortSignal;
14
+ }
15
+ export interface CodeInsightExecution {
16
+ tool: string;
17
+ ok: boolean;
18
+ durationMs: number;
19
+ args: Record<string, unknown>;
20
+ text?: string;
21
+ structuredContent?: unknown;
22
+ error?: string;
23
+ }
24
+ export interface CodeInsightBridgeResult {
25
+ provider: "gitnexus";
26
+ enabled: boolean;
27
+ available: boolean;
28
+ degraded: boolean;
29
+ modeRequested: CodeInsightMode;
30
+ modeResolved: "query" | "context" | "impact";
31
+ summary: string;
32
+ executions: CodeInsightExecution[];
33
+ warnings: string[];
34
+ repo?: string;
35
+ }
36
+ export interface EmbeddedGraphContext {
37
+ enabled: boolean;
38
+ available: boolean;
39
+ degraded: boolean;
40
+ summary: string;
41
+ warnings: string[];
42
+ provider: "gitnexus";
43
+ mode: "query" | "context" | "impact";
44
+ highlights: string[];
45
+ }
46
+ export declare function runCodeInsightBridge(request: CodeInsightRequest): Promise<CodeInsightBridgeResult>;
47
+ export declare function buildFeatureGraphContext(input: {
48
+ featureName: string;
49
+ description: string;
50
+ signal?: AbortSignal;
51
+ repo?: string;
52
+ }): Promise<EmbeddedGraphContext>;
53
+ export declare function buildBugfixGraphContext(input: {
54
+ errorMessage: string;
55
+ stackTrace?: string;
56
+ signal?: AbortSignal;
57
+ repo?: string;
58
+ }): Promise<EmbeddedGraphContext>;