mcp-probe-kit 3.3.0 → 3.6.0

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 (81) hide show
  1. package/README.md +15 -7
  2. package/build/index.js +45 -79
  3. package/build/lib/__tests__/agents-md-template.unit.test.js +1 -0
  4. package/build/lib/__tests__/dev-workflow.unit.test.d.ts +1 -0
  5. package/build/lib/__tests__/dev-workflow.unit.test.js +22 -0
  6. package/build/lib/__tests__/handles.unit.test.d.ts +1 -0
  7. package/build/lib/__tests__/handles.unit.test.js +19 -0
  8. package/build/lib/__tests__/mcp-apps.unit.test.d.ts +1 -0
  9. package/build/lib/__tests__/mcp-apps.unit.test.js +52 -0
  10. package/build/lib/__tests__/mcp-tool-skill-registry.unit.test.d.ts +1 -0
  11. package/build/lib/__tests__/mcp-tool-skill-registry.unit.test.js +18 -0
  12. package/build/lib/__tests__/memory-client.unit.test.js +105 -0
  13. package/build/lib/__tests__/spec-gate.unit.test.d.ts +1 -0
  14. package/build/lib/__tests__/spec-gate.unit.test.js +54 -0
  15. package/build/lib/__tests__/task-defaults.unit.test.d.ts +1 -0
  16. package/build/lib/__tests__/task-defaults.unit.test.js +27 -0
  17. package/build/lib/__tests__/workflow-skill-installer.unit.test.d.ts +1 -0
  18. package/build/lib/__tests__/workflow-skill-installer.unit.test.js +110 -0
  19. package/build/lib/agents-md-template.js +10 -2
  20. package/build/lib/dev-workflow.d.ts +36 -0
  21. package/build/lib/dev-workflow.js +497 -0
  22. package/build/lib/handles.d.ts +31 -0
  23. package/build/lib/handles.js +36 -0
  24. package/build/lib/mcp-apps.d.ts +14 -0
  25. package/build/lib/mcp-apps.js +234 -0
  26. package/build/lib/mcp-tool-skill-registry.d.ts +46 -0
  27. package/build/lib/mcp-tool-skill-registry.js +256 -0
  28. package/build/lib/memory-client.d.ts +19 -0
  29. package/build/lib/memory-client.js +69 -0
  30. package/build/lib/memory-orchestration.d.ts +5 -0
  31. package/build/lib/memory-orchestration.js +20 -0
  32. package/build/lib/merge-agents-md.d.ts +2 -2
  33. package/build/lib/merge-agents-md.js +7 -4
  34. package/build/lib/output-schema-registry.d.ts +11 -0
  35. package/build/lib/output-schema-registry.js +80 -0
  36. package/build/lib/spec-gate.d.ts +32 -0
  37. package/build/lib/spec-gate.js +83 -0
  38. package/build/lib/task-defaults.d.ts +6 -0
  39. package/build/lib/task-defaults.js +20 -0
  40. package/build/lib/tool-annotations.js +3 -0
  41. package/build/lib/toolset-manager.js +2 -0
  42. package/build/lib/workflow-skill-installer.d.ts +38 -0
  43. package/build/lib/workflow-skill-installer.js +158 -0
  44. package/build/lib/workflow-skill-template.d.ts +9 -0
  45. package/build/lib/workflow-skill-template.js +85 -0
  46. package/build/lib/workflow-skill-version.d.ts +15 -0
  47. package/build/lib/workflow-skill-version.js +68 -0
  48. package/build/schemas/index.d.ts +110 -0
  49. package/build/schemas/index.js +1 -0
  50. package/build/schemas/memory-tools.d.ts +83 -0
  51. package/build/schemas/memory-tools.js +43 -0
  52. package/build/schemas/orchestration-tools.d.ts +8 -0
  53. package/build/schemas/orchestration-tools.js +8 -0
  54. package/build/schemas/output/code-insight-tools.d.ts +65 -0
  55. package/build/schemas/output/code-insight-tools.js +42 -0
  56. package/build/schemas/output/memory-tools.d.ts +576 -0
  57. package/build/schemas/output/memory-tools.js +148 -0
  58. package/build/schemas/project-tools.d.ts +19 -0
  59. package/build/schemas/project-tools.js +20 -0
  60. package/build/tools/__tests__/delete_memory_asset.unit.test.d.ts +1 -0
  61. package/build/tools/__tests__/delete_memory_asset.unit.test.js +87 -0
  62. package/build/tools/__tests__/search_memory.unit.test.js +1 -0
  63. package/build/tools/__tests__/start_bugfix.unit.test.js +34 -1
  64. package/build/tools/__tests__/update_memory_asset.unit.test.d.ts +1 -0
  65. package/build/tools/__tests__/update_memory_asset.unit.test.js +82 -0
  66. package/build/tools/__tests__/workflow.unit.test.d.ts +1 -0
  67. package/build/tools/__tests__/workflow.unit.test.js +24 -0
  68. package/build/tools/code_insight.js +5 -1
  69. package/build/tools/delete_memory_asset.d.ts +7 -0
  70. package/build/tools/delete_memory_asset.js +57 -0
  71. package/build/tools/index.d.ts +3 -0
  72. package/build/tools/index.js +3 -0
  73. package/build/tools/search_memory.js +5 -2
  74. package/build/tools/start_bugfix.js +37 -4
  75. package/build/tools/start_feature.js +4 -3
  76. package/build/tools/start_ui.js +5 -4
  77. package/build/tools/update_memory_asset.d.ts +7 -0
  78. package/build/tools/update_memory_asset.js +98 -0
  79. package/build/tools/workflow.d.ts +13 -0
  80. package/build/tools/workflow.js +69 -0
  81. package/package.json +5 -3
@@ -1,5 +1,6 @@
1
1
  import { createMemoryClient } from './memory-client.js';
2
2
  import { getMemoryConfig } from './memory-config.js';
3
+ import { buildMemoryAssetHandles, DEFAULT_GRAPH_RESOURCE_URI, mergeHandles, } from './handles.js';
3
4
  function kindSearchPreferences(kind) {
4
5
  switch (kind) {
5
6
  case 'bugfix':
@@ -195,6 +196,25 @@ export function renderMemoryGuideSection(context) {
195
196
  }
196
197
  return blocks.join('\n');
197
198
  }
199
+ export function buildMemoryInjectionHandles(context) {
200
+ if (!context.enabled || context.results.length === 0) {
201
+ return {};
202
+ }
203
+ return {
204
+ memory_assets: buildMemoryAssetHandles(context.results.map((item) => ({
205
+ id: item.id,
206
+ name: item.name,
207
+ type: item.type,
208
+ summary: item.summary,
209
+ }))),
210
+ };
211
+ }
212
+ export function buildOrchestrationHandles(memoryContext, options) {
213
+ const memoryHandles = memoryContext ? buildMemoryInjectionHandles(memoryContext) : {};
214
+ return mergeHandles(memoryHandles, {
215
+ graph_resource: options?.graphResourceUri ?? DEFAULT_GRAPH_RESOURCE_URI,
216
+ });
217
+ }
198
218
  export function buildMemoryPlanStep(kind = 'default') {
199
219
  if (kind === 'bugfix') {
200
220
  return {
@@ -1,6 +1,6 @@
1
1
  export type AgentsMdMergeMode = "created" | "prepended" | "replaced-and-moved-to-top" | "skipped-empty";
2
- export declare function wrapMcpProbeBlock(innerMarkdown: string): string;
3
- export declare function mergeAgentsMdBlock(existingContent: string | null | undefined, generatedInner: string): {
2
+ export declare function wrapMcpProbeBlock(innerMarkdown: string, contextVersion?: string): string;
3
+ export declare function mergeAgentsMdBlock(existingContent: string | null | undefined, generatedInner: string, contextVersion?: string): {
4
4
  content: string;
5
5
  mergeMode: AgentsMdMergeMode;
6
6
  };
@@ -1,7 +1,10 @@
1
+ import { VERSION } from "../version.js";
2
+ import { formatAgentsContextVersionMarker } from "./workflow-skill-version.js";
1
3
  const BLOCK_BEGIN = "<!-- mcp-probe:context begin — auto-generated; re-run init_project_context updates this block only -->";
2
4
  const BLOCK_END = "<!-- mcp-probe:context end -->";
3
- export function wrapMcpProbeBlock(innerMarkdown) {
4
- return `${BLOCK_BEGIN}\n${innerMarkdown.trim()}\n${BLOCK_END}`;
5
+ export function wrapMcpProbeBlock(innerMarkdown, contextVersion = VERSION) {
6
+ const versionLine = formatAgentsContextVersionMarker(contextVersion);
7
+ return `${BLOCK_BEGIN}\n${versionLine}\n${innerMarkdown.trim()}\n${BLOCK_END}`;
5
8
  }
6
9
  function stripExistingBlock(content) {
7
10
  const beginIdx = content.indexOf(BLOCK_BEGIN);
@@ -28,8 +31,8 @@ function stripExistingBlock(content) {
28
31
  const after = content.slice(endIdx + BLOCK_END.length).trimStart();
29
32
  return [before, after].filter(Boolean).join("\n\n").trim();
30
33
  }
31
- export function mergeAgentsMdBlock(existingContent, generatedInner) {
32
- const block = wrapMcpProbeBlock(generatedInner);
34
+ export function mergeAgentsMdBlock(existingContent, generatedInner, contextVersion = VERSION) {
35
+ const block = wrapMcpProbeBlock(generatedInner, contextVersion);
33
36
  if (!existingContent?.trim()) {
34
37
  return { content: `${block}\n`, mergeMode: "created" };
35
38
  }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * tools/list 的 outputSchema 注册表(与 tools-manifest.json structuredOutput.schemas 对齐)
3
+ */
4
+ type JsonSchema = Record<string, unknown>;
5
+ export declare function getOutputSchemaForTool(toolName: string): JsonSchema | undefined;
6
+ export declare function withOutputSchema<T extends {
7
+ name: string;
8
+ }>(tool: T): T & {
9
+ outputSchema?: JsonSchema;
10
+ };
11
+ export {};
@@ -0,0 +1,80 @@
1
+ /**
2
+ * tools/list 的 outputSchema 注册表(与 tools-manifest.json structuredOutput.schemas 对齐)
3
+ */
4
+ import { CodeReviewReportSchema, BugAnalysisSchema, TestSuiteSchema, RefactorPlanSchema, } from '../schemas/output/core-tools.js';
5
+ import { FeatureSpecSchema, ProjectInitSchema, ProjectContextSchema, EstimateSchema, } from '../schemas/output/project-tools.js';
6
+ import { DesignSystemSchema, UISearchResultSchema, SyncReportSchema, } from '../schemas/output/ui-ux-tools.js';
7
+ import { InterviewReportSchema } from '../schemas/output/product-design-tools.js';
8
+ import { CommitGuidanceSchema, FeatureReportSchema, BugFixReportSchema, UIReportSchema, OnboardingReportSchema, RalphLoopReportSchema, WorkflowReportSchema, } from '../schemas/structured-output.js';
9
+ import { MemorySearchSchema, MemoryAssetDetailSchema, MemorizeResultSchema, DeleteMemoryResultSchema, UpdateMemoryResultSchema, PatternExtractionSchema, } from '../schemas/output/memory-tools.js';
10
+ import { CodeInsightSchema } from '../schemas/output/code-insight-tools.js';
11
+ const SpecValidationReportSchema = {
12
+ type: 'object',
13
+ properties: {
14
+ passed: { type: 'boolean' },
15
+ errorCount: { type: 'number' },
16
+ warningCount: { type: 'number' },
17
+ issues: {
18
+ type: 'array',
19
+ items: {
20
+ type: 'object',
21
+ properties: {
22
+ file: { type: 'string' },
23
+ severity: { type: 'string', enum: ['error', 'warning'] },
24
+ code: { type: 'string' },
25
+ message: { type: 'string' },
26
+ },
27
+ required: ['file', 'severity', 'message'],
28
+ },
29
+ },
30
+ frIds: { type: 'array', items: { type: 'string' } },
31
+ summary: { type: 'string' },
32
+ },
33
+ required: ['passed', 'errorCount', 'warningCount', 'issues', 'summary'],
34
+ };
35
+ const UserQuestionSchema = {
36
+ type: 'object',
37
+ properties: {
38
+ question: { type: 'string' },
39
+ options: { type: 'array', items: { type: 'string' } },
40
+ context: { type: 'string' },
41
+ },
42
+ required: ['question'],
43
+ };
44
+ const OUTPUT_SCHEMA_BY_TOOL = {
45
+ gencommit: CommitGuidanceSchema,
46
+ code_insight: CodeInsightSchema,
47
+ code_review: CodeReviewReportSchema,
48
+ fix_bug: BugAnalysisSchema,
49
+ gentest: TestSuiteSchema,
50
+ refactor: RefactorPlanSchema,
51
+ add_feature: FeatureSpecSchema,
52
+ check_spec: SpecValidationReportSchema,
53
+ estimate: EstimateSchema,
54
+ start_feature: FeatureReportSchema,
55
+ start_bugfix: BugFixReportSchema,
56
+ start_onboard: OnboardingReportSchema,
57
+ start_ui: UIReportSchema,
58
+ start_product: WorkflowReportSchema,
59
+ start_ralph: RalphLoopReportSchema,
60
+ init_project: ProjectInitSchema,
61
+ init_project_context: ProjectContextSchema,
62
+ interview: InterviewReportSchema,
63
+ ask_user: UserQuestionSchema,
64
+ ui_design_system: DesignSystemSchema,
65
+ ui_search: UISearchResultSchema,
66
+ sync_ui_data: SyncReportSchema,
67
+ search_memory: MemorySearchSchema,
68
+ read_memory_asset: MemoryAssetDetailSchema,
69
+ memorize_asset: MemorizeResultSchema,
70
+ delete_memory_asset: DeleteMemoryResultSchema,
71
+ update_memory_asset: UpdateMemoryResultSchema,
72
+ scan_and_extract_patterns: PatternExtractionSchema,
73
+ };
74
+ export function getOutputSchemaForTool(toolName) {
75
+ return OUTPUT_SCHEMA_BY_TOOL[toolName];
76
+ }
77
+ export function withOutputSchema(tool) {
78
+ const outputSchema = getOutputSchemaForTool(tool.name);
79
+ return outputSchema ? { ...tool, outputSchema } : tool;
80
+ }
@@ -0,0 +1,32 @@
1
+ export interface SpecGateContext {
2
+ featureName: string;
3
+ docsDir: string;
4
+ specDir: string;
5
+ detected: boolean;
6
+ }
7
+ export declare function specArtifactsExist(projectRoot: string, docsDir: string, featureName: string): boolean;
8
+ /**
9
+ * 解析 Bug 修复关联的 feature_name:
10
+ * 1) 显式传入优先
11
+ * 2) specs 下仅有一个目录时自动采用
12
+ * 3) 错误描述中唯一匹配某个 spec 目录名
13
+ */
14
+ export declare function resolveBugfixFeatureName(explicitFeatureName: string, projectRoot: string, docsDir: string, hintText: string): string | null;
15
+ export declare function resolveBugfixSpecGate(input: {
16
+ featureName?: string;
17
+ projectRoot: string;
18
+ docsDir: string;
19
+ hintText: string;
20
+ }): SpecGateContext | null;
21
+ export declare function buildCheckSpecPlanStep(featureName: string, docsDir: string): {
22
+ id: string;
23
+ tool: string;
24
+ when: string;
25
+ args: {
26
+ feature_name: string;
27
+ docs_dir: string;
28
+ };
29
+ outputs: string[];
30
+ note: string;
31
+ };
32
+ export declare function renderSpecGatePromptSection(specGate: SpecGateContext): string;
@@ -0,0 +1,83 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ export function specArtifactsExist(projectRoot, docsDir, featureName) {
4
+ const specDir = path.join(projectRoot, docsDir, 'specs', featureName);
5
+ return (fs.existsSync(path.join(specDir, 'requirements.md')) ||
6
+ fs.existsSync(path.join(specDir, 'design.md')) ||
7
+ fs.existsSync(path.join(specDir, 'tasks.md')));
8
+ }
9
+ /**
10
+ * 解析 Bug 修复关联的 feature_name:
11
+ * 1) 显式传入优先
12
+ * 2) specs 下仅有一个目录时自动采用
13
+ * 3) 错误描述中唯一匹配某个 spec 目录名
14
+ */
15
+ export function resolveBugfixFeatureName(explicitFeatureName, projectRoot, docsDir, hintText) {
16
+ const explicit = explicitFeatureName.trim();
17
+ if (explicit) {
18
+ return explicit;
19
+ }
20
+ const specsRoot = path.join(projectRoot, docsDir, 'specs');
21
+ if (!fs.existsSync(specsRoot)) {
22
+ return null;
23
+ }
24
+ const dirs = fs
25
+ .readdirSync(specsRoot, { withFileTypes: true })
26
+ .filter((entry) => entry.isDirectory())
27
+ .map((entry) => entry.name);
28
+ if (dirs.length === 1) {
29
+ return dirs[0] ?? null;
30
+ }
31
+ const lowerHint = hintText.toLowerCase();
32
+ const matched = dirs.filter((name) => {
33
+ const lowerName = name.toLowerCase();
34
+ if (lowerHint.includes(lowerName)) {
35
+ return true;
36
+ }
37
+ return lowerName
38
+ .split(/[-_]+/)
39
+ .filter((part) => part.length > 3)
40
+ .some((part) => lowerHint.includes(part));
41
+ });
42
+ return matched.length === 1 ? (matched[0] ?? null) : null;
43
+ }
44
+ export function resolveBugfixSpecGate(input) {
45
+ const featureName = resolveBugfixFeatureName(input.featureName ?? '', input.projectRoot, input.docsDir, input.hintText);
46
+ if (!featureName || !specArtifactsExist(input.projectRoot, input.docsDir, featureName)) {
47
+ return null;
48
+ }
49
+ return {
50
+ featureName,
51
+ docsDir: input.docsDir,
52
+ specDir: `${input.docsDir}/specs/${featureName}`,
53
+ detected: !input.featureName?.trim(),
54
+ };
55
+ }
56
+ export function buildCheckSpecPlanStep(featureName, docsDir) {
57
+ return {
58
+ id: 'check-spec',
59
+ tool: 'check_spec',
60
+ when: '修复与回归测试通过后,且本次 Bug 关联功能规格存在时',
61
+ args: {
62
+ feature_name: featureName,
63
+ docs_dir: docsDir,
64
+ },
65
+ outputs: [`${docsDir}/specs/${featureName}/`],
66
+ note: '若修复改动影响 requirements/design/tasks,先更新规格文档再重跑 check_spec;未通过不得视为修复闭环',
67
+ };
68
+ }
69
+ export function renderSpecGatePromptSection(specGate) {
70
+ const detectNote = specGate.detected
71
+ ? `\n- 自动识别关联规格: \`${specGate.specDir}/\``
72
+ : `\n- 关联规格: \`${specGate.specDir}/\``;
73
+ return `
74
+
75
+ ## 📐 步骤 3: 规格闸门(修复后)
76
+
77
+ **调用**: \`check_spec\`
78
+ \`\`\`json
79
+ { "feature_name": "${specGate.featureName}", "docs_dir": "${specGate.docsDir}" }
80
+ \`\`\`
81
+ ${detectNote}
82
+ **未通过**:按报告补全 requirements/design/tasks 后**重跑 check_spec**;规格与实现不一致时不得结案。`;
83
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * 长耗时工具默认走 MCP Task,避免阻塞 stdio 宿主。
3
+ */
4
+ export declare function isAutoTaskTool(toolName: string): boolean;
5
+ export declare function isAutoTaskEnabled(): boolean;
6
+ export declare function shouldAutoEscalateToTask(toolName: string, hasExplicitTaskRequest: boolean): boolean;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * 长耗时工具默认走 MCP Task,避免阻塞 stdio 宿主。
3
+ */
4
+ const AUTO_TASK_TOOLS = new Set(['code_insight', 'scan_and_extract_patterns']);
5
+ export function isAutoTaskTool(toolName) {
6
+ return AUTO_TASK_TOOLS.has(toolName);
7
+ }
8
+ export function isAutoTaskEnabled() {
9
+ const raw = process.env.MCP_DISABLE_AUTO_TASK?.trim();
10
+ if (raw && /^(1|true|yes|on)$/i.test(raw)) {
11
+ return false;
12
+ }
13
+ return true;
14
+ }
15
+ export function shouldAutoEscalateToTask(toolName, hasExplicitTaskRequest) {
16
+ if (hasExplicitTaskRequest) {
17
+ return false;
18
+ }
19
+ return isAutoTaskEnabled() && isAutoTaskTool(toolName);
20
+ }
@@ -15,6 +15,7 @@
15
15
  export const TOOL_ANNOTATIONS = {
16
16
  // —— 只读指南型(可安全自动放行)——
17
17
  init_project: { title: '初始化项目', readOnlyHint: true, idempotentHint: true, openWorldHint: false },
18
+ workflow: { title: '开发工作流路由', readOnlyHint: true, idempotentHint: true, openWorldHint: false },
18
19
  gencommit: { title: '生成提交信息', readOnlyHint: true, idempotentHint: true, openWorldHint: false },
19
20
  code_review: { title: '代码审查', readOnlyHint: true, idempotentHint: true, openWorldHint: false },
20
21
  gentest: { title: '生成测试', readOnlyHint: true, idempotentHint: true, openWorldHint: false },
@@ -44,6 +45,8 @@ export const TOOL_ANNOTATIONS = {
44
45
  // —— 写型(工具自身落盘 / 写记忆 / 写缓存,非破坏)——
45
46
  init_project_context: { title: '生成项目上下文', readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false }, // 自己写 docs/.mcp-probe/layout.json(其余为指令)
46
47
  memorize_asset: { title: '沉淀记忆资产', readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true }, // 写 Qdrant
48
+ delete_memory_asset: { title: '删除记忆资产', readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: true }, // 删 Qdrant
49
+ update_memory_asset: { title: '更新记忆资产', readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true }, // 写 Qdrant
47
50
  sync_ui_data: { title: '同步 UI 数据', readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true }, // 下载 + 写缓存
48
51
  };
49
52
  /**
@@ -14,6 +14,7 @@ import { allToolSchemas } from '../schemas/index.js';
14
14
  export const TOOLSET_DEFINITIONS = {
15
15
  // 核心工具集 - 日常高频工具
16
16
  core: [
17
+ 'workflow',
17
18
  'gencommit',
18
19
  'code_review',
19
20
  'code_insight',
@@ -35,6 +36,7 @@ export const TOOLSET_DEFINITIONS = {
35
36
  ],
36
37
  // 工作流工具集 - 包含核心 + 编排 + 交互
37
38
  workflow: [
39
+ 'workflow',
38
40
  // 核心工具
39
41
  'gencommit',
40
42
  'code_review',
@@ -0,0 +1,38 @@
1
+ export interface SkillEnsureResult {
2
+ skillPath: string;
3
+ skillRelPath: string;
4
+ existed: boolean;
5
+ created: boolean;
6
+ updated: boolean;
7
+ version: string;
8
+ previousVersion: string | null;
9
+ }
10
+ export interface AgentsMdEnsureResult {
11
+ path: string;
12
+ existed: boolean;
13
+ created: boolean;
14
+ updated: boolean;
15
+ }
16
+ export interface McpProbeKitBootstrapResult {
17
+ projectRoot: string;
18
+ skill: SkillEnsureResult;
19
+ agentsMd: AgentsMdEnsureResult;
20
+ }
21
+ export declare function resolveProjectRootFromToolArgs(args: unknown): string;
22
+ /**
23
+ * 同步用户项目 Skill:缺失则创建;已安装版本落后于 kit 则覆盖升级。
24
+ */
25
+ export declare function ensureMcpProbeSkill(projectRoot: string): SkillEnsureResult;
26
+ /**
27
+ * 确保 AGENTS.md 存在且含 mcp-probe 块与 Skill 引用;无则创建,有则按版本合并更新。
28
+ */
29
+ export declare function ensureAgentsMdSkillReference(projectRoot: string): AgentsMdEnsureResult;
30
+ /**
31
+ * 任意 MCP 工具调用前的项目增强:安装 Skill + 同步 AGENTS.md 引用(始终开启)。
32
+ */
33
+ export declare function ensureMcpProbeKitBootstrap(projectRoot: string): McpProbeKitBootstrapResult;
34
+ export declare function ensureMcpProbeKitBootstrapForToolCall(_toolName: string, args: unknown): McpProbeKitBootstrapResult | null;
35
+ /** @deprecated 使用 ensureMcpProbeKitBootstrap */
36
+ export declare function ensureProjectWorkflowSkill(projectRoot: string): McpProbeKitBootstrapResult;
37
+ /** @deprecated 使用 ensureMcpProbeKitBootstrapForToolCall */
38
+ export declare function ensureWorkflowSkillForToolCall(toolName: string, args: unknown): McpProbeKitBootstrapResult | null;
@@ -0,0 +1,158 @@
1
+ import * as fs from "node:fs";
2
+ import * as path from "node:path";
3
+ import { generateAgentsMdInner } from "./agents-md-template.js";
4
+ import { mergeAgentsMdBlock } from "./merge-agents-md.js";
5
+ import { detectDocumentLocale, resolveProjectContextLayout, toPosixPath, } from "./project-context-layout.js";
6
+ import { generateWorkflowSkillContent, LEGACY_WORKFLOW_SKILL_REL_PATH, MCP_PROBE_SKILL_REL_PATH, } from "./workflow-skill-template.js";
7
+ import { agentsContextNeedsUpgrade, getMcpProbeSkillVersion, parseSkillVersionMarker, skillContentNeedsUpgrade, } from "./workflow-skill-version.js";
8
+ import { isLikelyProjectNamedRelativePath, resolveWorkspaceRoot, } from "./workspace-root.js";
9
+ function flattenToolArgs(args) {
10
+ if (!args || typeof args !== "object" || Array.isArray(args)) {
11
+ return {};
12
+ }
13
+ const base = args;
14
+ const nested = base.input && typeof base.input === "object" && !Array.isArray(base.input)
15
+ ? base.input
16
+ : {};
17
+ return { ...base, ...nested };
18
+ }
19
+ export function resolveProjectRootFromToolArgs(args) {
20
+ const record = flattenToolArgs(args);
21
+ const explicit = (typeof record.project_root === "string" ? record.project_root.trim() : "") ||
22
+ (typeof record.projectRoot === "string" ? record.projectRoot.trim() : "") ||
23
+ (typeof record.project_path === "string" ? record.project_path.trim() : "");
24
+ if (explicit && !isLikelyProjectNamedRelativePath(explicit)) {
25
+ return resolveWorkspaceRoot(explicit);
26
+ }
27
+ return resolveWorkspaceRoot("");
28
+ }
29
+ function buildAgentsMdInner(projectRoot, existingAgentsContent) {
30
+ const layout = resolveProjectContextLayout(projectRoot);
31
+ const locale = detectDocumentLocale(projectRoot, existingAgentsContent);
32
+ const graphReady = fs.existsSync(path.join(projectRoot, layout.latestMarkdownPath));
33
+ return generateAgentsMdInner({
34
+ layout,
35
+ locale,
36
+ projectName: path.basename(projectRoot),
37
+ projectVersion: "0.0.0",
38
+ description: "",
39
+ language: "",
40
+ category: "app",
41
+ docs: [],
42
+ projectRootPosix: toPosixPath(projectRoot),
43
+ graphReady,
44
+ });
45
+ }
46
+ function agentsMdNeedsUpdate(content, skillRelPath, targetVersion) {
47
+ if (!content?.trim()) {
48
+ return true;
49
+ }
50
+ if (!content.includes("mcp-probe:context")) {
51
+ return true;
52
+ }
53
+ if (content.includes(LEGACY_WORKFLOW_SKILL_REL_PATH)) {
54
+ return true;
55
+ }
56
+ if (!content.includes(skillRelPath)) {
57
+ return true;
58
+ }
59
+ if (agentsContextNeedsUpgrade(content, targetVersion)) {
60
+ return true;
61
+ }
62
+ return false;
63
+ }
64
+ function writeSkillFile(skillPath, version) {
65
+ fs.mkdirSync(path.dirname(skillPath), { recursive: true });
66
+ fs.writeFileSync(skillPath, generateWorkflowSkillContent(version), "utf8");
67
+ }
68
+ /**
69
+ * 同步用户项目 Skill:缺失则创建;已安装版本落后于 kit 则覆盖升级。
70
+ */
71
+ export function ensureMcpProbeSkill(projectRoot) {
72
+ const root = path.resolve(projectRoot);
73
+ const skillPath = path.join(root, MCP_PROBE_SKILL_REL_PATH);
74
+ const targetVersion = getMcpProbeSkillVersion();
75
+ const existing = fs.existsSync(skillPath) ? fs.readFileSync(skillPath, "utf8") : null;
76
+ const previousVersion = existing ? parseSkillVersionMarker(existing) : null;
77
+ if (!skillContentNeedsUpgrade(existing, targetVersion)) {
78
+ return {
79
+ skillPath,
80
+ skillRelPath: MCP_PROBE_SKILL_REL_PATH,
81
+ existed: Boolean(existing?.trim()),
82
+ created: false,
83
+ updated: false,
84
+ version: targetVersion,
85
+ previousVersion,
86
+ };
87
+ }
88
+ writeSkillFile(skillPath, targetVersion);
89
+ const hadContent = Boolean(existing?.trim());
90
+ return {
91
+ skillPath,
92
+ skillRelPath: MCP_PROBE_SKILL_REL_PATH,
93
+ existed: hadContent,
94
+ created: !hadContent,
95
+ updated: hadContent,
96
+ version: targetVersion,
97
+ previousVersion,
98
+ };
99
+ }
100
+ /**
101
+ * 确保 AGENTS.md 存在且含 mcp-probe 块与 Skill 引用;无则创建,有则按版本合并更新。
102
+ */
103
+ export function ensureAgentsMdSkillReference(projectRoot) {
104
+ const root = path.resolve(projectRoot);
105
+ const layout = resolveProjectContextLayout(root);
106
+ const agentsPath = path.join(root, layout.indexPath);
107
+ const existing = fs.existsSync(agentsPath) ? fs.readFileSync(agentsPath, "utf8") : null;
108
+ const targetVersion = getMcpProbeSkillVersion();
109
+ if (!agentsMdNeedsUpdate(existing, MCP_PROBE_SKILL_REL_PATH, targetVersion)) {
110
+ return {
111
+ path: layout.indexPath,
112
+ existed: Boolean(existing?.trim()),
113
+ created: false,
114
+ updated: false,
115
+ };
116
+ }
117
+ const inner = buildAgentsMdInner(root, existing ?? undefined);
118
+ const { content, mergeMode } = mergeAgentsMdBlock(existing, inner, targetVersion);
119
+ fs.mkdirSync(path.dirname(agentsPath), { recursive: true });
120
+ fs.writeFileSync(agentsPath, content, "utf8");
121
+ const hadContent = Boolean(existing?.trim());
122
+ return {
123
+ path: layout.indexPath,
124
+ existed: hadContent,
125
+ created: !hadContent,
126
+ updated: hadContent && mergeMode !== "skipped-empty",
127
+ };
128
+ }
129
+ /**
130
+ * 任意 MCP 工具调用前的项目增强:安装 Skill + 同步 AGENTS.md 引用(始终开启)。
131
+ */
132
+ export function ensureMcpProbeKitBootstrap(projectRoot) {
133
+ const root = path.resolve(projectRoot);
134
+ return {
135
+ projectRoot: root,
136
+ skill: ensureMcpProbeSkill(root),
137
+ agentsMd: ensureAgentsMdSkillReference(root),
138
+ };
139
+ }
140
+ export function ensureMcpProbeKitBootstrapForToolCall(_toolName, args) {
141
+ try {
142
+ const projectRoot = resolveProjectRootFromToolArgs(args);
143
+ return ensureMcpProbeKitBootstrap(projectRoot);
144
+ }
145
+ catch (error) {
146
+ const message = error instanceof Error ? error.message : String(error);
147
+ console.error(`[MCP Probe Kit] mcp-probe-kit bootstrap failed: ${message}`);
148
+ return null;
149
+ }
150
+ }
151
+ /** @deprecated 使用 ensureMcpProbeKitBootstrap */
152
+ export function ensureProjectWorkflowSkill(projectRoot) {
153
+ return ensureMcpProbeKitBootstrap(projectRoot);
154
+ }
155
+ /** @deprecated 使用 ensureMcpProbeKitBootstrapForToolCall */
156
+ export function ensureWorkflowSkillForToolCall(toolName, args) {
157
+ return ensureMcpProbeKitBootstrapForToolCall(toolName, args);
158
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * 由 mcp-tool-skill-registry 生成 Skill 正文(勿在此硬编码工具表)。
3
+ * 本仓库 dogfood 文件由 `npm run sync-workflow-skill`(prebuild)自动写入。
4
+ */
5
+ export declare const MCP_PROBE_SKILL_REL_PATH = ".agents/skills/mcp-probe-kit/SKILL.md";
6
+ /** @deprecated 旧路径,仅用于检测并升级 AGENTS.md 引用 */
7
+ export declare const LEGACY_WORKFLOW_SKILL_REL_PATH = ".agents/skills/workflow/SKILL.md";
8
+ export declare function generateWorkflowSkillBody(skillVersion?: string): string;
9
+ export declare function generateWorkflowSkillContent(skillVersion?: string): string;
@@ -0,0 +1,85 @@
1
+ /**
2
+ * 由 mcp-tool-skill-registry 生成 Skill 正文(勿在此硬编码工具表)。
3
+ * 本仓库 dogfood 文件由 `npm run sync-workflow-skill`(prebuild)自动写入。
4
+ */
5
+ import { VERSION } from "../version.js";
6
+ import { MCP_INTENT_QUICK_LOOKUP, MCP_SKILL_AVOID_RULES, MCP_SKILL_COMMON_FLOWS, MCP_TOOL_SKILL_GROUPS, } from "./mcp-tool-skill-registry.js";
7
+ import { formatSkillVersionMarker } from "./workflow-skill-version.js";
8
+ export const MCP_PROBE_SKILL_REL_PATH = ".agents/skills/mcp-probe-kit/SKILL.md";
9
+ /** @deprecated 旧路径,仅用于检测并升级 AGENTS.md 引用 */
10
+ export const LEGACY_WORKFLOW_SKILL_REL_PATH = ".agents/skills/workflow/SKILL.md";
11
+ function renderIntentQuickLookup() {
12
+ const rows = MCP_INTENT_QUICK_LOOKUP.map((entry) => `| ${entry.signal} | \`${entry.firstTool}\` |`).join("\n");
13
+ return `| 用户说什么 / 什么情况 | 第一个 MCP |
14
+ |----------------------|------------|
15
+ ${rows}`;
16
+ }
17
+ function renderToolGroups() {
18
+ return MCP_TOOL_SKILL_GROUPS.map((group) => {
19
+ const rows = group.tools
20
+ .map((tool) => `| \`${tool.name}\` | ${tool.whenToCall} |`)
21
+ .join("\n");
22
+ const note = group.note ? `\n\n*${group.note}*` : "";
23
+ return `### ${group.title}
24
+
25
+ | MCP | 何时调用 |
26
+ |-----|----------|
27
+ ${rows}${note}`;
28
+ }).join("\n\n");
29
+ }
30
+ function renderCommonFlows() {
31
+ return MCP_SKILL_COMMON_FLOWS.map((flow) => `**${flow.label}**:\`${flow.chain}\``).join("\n\n");
32
+ }
33
+ function renderAvoidRules() {
34
+ return MCP_SKILL_AVOID_RULES.map((rule) => `- ${rule}`).join("\n");
35
+ }
36
+ export function generateWorkflowSkillBody(skillVersion = VERSION) {
37
+ return `# MCP 调用时机 — mcp-probe-kit
38
+
39
+ > 本 Skill 只回答一件事:**什么情况 → 调哪个 MCP**。不是开发流程剧本。
40
+ > 由 mcp-probe-kit 自动安装;Cursor 从 \`.agents/skills/\` 加载。
41
+
42
+ ## 总规则
43
+
44
+ 1. **先查下表**,有对应 MCP 就先调,再写代码 / 改文件
45
+ 2. **拿不准** → \`workflow\`:\`{ "intent": "<用户原话>" }\`
46
+ 3. \`start_*\` 会列出后续该调的 MCP;按返回逐步调用即可
47
+
48
+ ---
49
+
50
+ ## 意图速查(第一个该调的 MCP)
51
+
52
+ ${renderIntentQuickLookup()}
53
+
54
+ ---
55
+
56
+ ## 全工具:何时调用
57
+
58
+ ${renderToolGroups()}
59
+
60
+ ---
61
+
62
+ ## 常见链路(只是调用顺序参考)
63
+
64
+ ${renderCommonFlows()}
65
+
66
+ ---
67
+
68
+ ## 不要
69
+
70
+ ${renderAvoidRules()}
71
+
72
+ ---
73
+
74
+ *mcp-probe-kit 按版本自动同步(当前 \`${skillVersion}\`)。路径:\`${MCP_PROBE_SKILL_REL_PATH}\`*
75
+ `;
76
+ }
77
+ export function generateWorkflowSkillContent(skillVersion = VERSION) {
78
+ const versionMarker = formatSkillVersionMarker(skillVersion);
79
+ return `${versionMarker}
80
+
81
+ ${generateWorkflowSkillBody(skillVersion)}
82
+
83
+ ${versionMarker}
84
+ `;
85
+ }
@@ -0,0 +1,15 @@
1
+ /** Skill 文件首行版本标记:`<!-- mcp-probe-kit-skill-version: 3.5.0 -->` */
2
+ export declare const SKILL_VERSION_MARKER = "mcp-probe-kit-skill-version";
3
+ /** AGENTS.md mcp-probe 块内版本标记 */
4
+ export declare const AGENTS_CONTEXT_VERSION_MARKER = "mcp-probe:context-version";
5
+ export declare function getMcpProbeSkillVersion(): string;
6
+ export declare function formatSkillVersionMarker(version?: string): string;
7
+ export declare function formatAgentsContextVersionMarker(version?: string): string;
8
+ export declare function parseSkillVersionMarker(content: string): string | null;
9
+ export declare function parseAgentsContextVersion(content: string): string | null;
10
+ /** 比较 semver(仅主版本号段,忽略 prerelease 后缀) */
11
+ export declare function compareSemver(a: string, b: string): number;
12
+ /** 已安装 Skill 是否落后于当前 kit 版本(无标记视为过期) */
13
+ export declare function skillContentNeedsUpgrade(existing: string | null | undefined, targetVersion?: string): boolean;
14
+ /** AGENTS.md mcp-probe 块是否落后于当前 kit 版本 */
15
+ export declare function agentsContextNeedsUpgrade(existing: string | null | undefined, targetVersion?: string): boolean;