mcp-probe-kit 3.0.21 → 3.0.23

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 (69) hide show
  1. package/README.md +8 -10
  2. package/build/index.js +1 -5
  3. package/build/lib/memory-orchestration.d.ts +1 -0
  4. package/build/lib/memory-orchestration.js +21 -0
  5. package/build/lib/shadcn-ui.d.ts +11 -0
  6. package/build/lib/shadcn-ui.js +78 -0
  7. package/build/resources/ui-ux-data/guidelines/vercel-web-interface.json +1632 -0
  8. package/build/resources/ui-ux-data/metadata.json +27 -3
  9. package/build/resources/ui-ux-data/shadcn/blocks.json +2541 -0
  10. package/build/resources/ui-ux-data/shadcn/components.json +997 -0
  11. package/build/resources/ui-ux-data/themes/presets.json +483 -0
  12. package/build/schemas/index.d.ts +0 -48
  13. package/build/schemas/memory-tools.d.ts +0 -48
  14. package/build/schemas/memory-tools.js +0 -29
  15. package/build/schemas/output/ui-ux-tools.d.ts +16 -0
  16. package/build/schemas/output/ui-ux-tools.js +4 -0
  17. package/build/schemas/ui-ux-schemas.js +3 -3
  18. package/build/tools/__tests__/cursor-history.unit.test.js +0 -49
  19. package/build/tools/__tests__/search_memory.unit.test.d.ts +1 -0
  20. package/build/tools/__tests__/search_memory.unit.test.js +83 -0
  21. package/build/tools/__tests__/start_ui.property.test.js +4 -3
  22. package/build/tools/index.d.ts +0 -2
  23. package/build/tools/index.js +0 -2
  24. package/build/tools/search_memory.js +3 -2
  25. package/build/tools/start_ui.js +30 -3
  26. package/build/tools/ui-ux-tools.js +322 -244
  27. package/build/utils/__tests__/shadcn-sync.unit.test.d.ts +1 -0
  28. package/build/utils/__tests__/shadcn-sync.unit.test.js +49 -0
  29. package/build/utils/__tests__/theme-pick.unit.test.d.ts +1 -0
  30. package/build/utils/__tests__/theme-pick.unit.test.js +9 -0
  31. package/build/utils/__tests__/themes-sync.unit.test.d.ts +1 -0
  32. package/build/utils/__tests__/themes-sync.unit.test.js +21 -0
  33. package/build/utils/__tests__/ui-metadata.unit.test.d.ts +1 -0
  34. package/build/utils/__tests__/ui-metadata.unit.test.js +35 -0
  35. package/build/utils/__tests__/vercel-guidelines-sync.unit.test.d.ts +1 -0
  36. package/build/utils/__tests__/vercel-guidelines-sync.unit.test.js +34 -0
  37. package/build/utils/bm25.d.ts +2 -1
  38. package/build/utils/bm25.js +17 -5
  39. package/build/utils/shadcn-sync.d.ts +55 -0
  40. package/build/utils/shadcn-sync.js +146 -0
  41. package/build/utils/themes-sync.d.ts +32 -0
  42. package/build/utils/themes-sync.js +201 -0
  43. package/build/utils/ui-data-loader.js +13 -2
  44. package/build/utils/ui-metadata.d.ts +27 -0
  45. package/build/utils/ui-metadata.js +39 -0
  46. package/build/utils/ui-search-engine.d.ts +1 -0
  47. package/build/utils/ui-search-engine.js +20 -6
  48. package/build/utils/ui-sync.d.ts +24 -2
  49. package/build/utils/ui-sync.js +152 -86
  50. package/build/utils/vercel-guidelines-sync.d.ts +30 -0
  51. package/build/utils/vercel-guidelines-sync.js +133 -0
  52. package/docs/data/tools.js +1 -33
  53. package/docs/i18n/all-tools/en.json +4 -14
  54. package/docs/i18n/all-tools/ja.json +3 -5
  55. package/docs/i18n/all-tools/ko.json +3 -5
  56. package/docs/i18n/all-tools/zh-CN.json +4 -14
  57. package/docs/i18n/en.json +10 -10
  58. package/docs/i18n/ja.json +9 -9
  59. package/docs/i18n/ko.json +9 -9
  60. package/docs/i18n/zh-CN.json +10 -10
  61. package/docs/pages/all-tools.html +4 -4
  62. package/docs/pages/examples.html +2 -2
  63. package/docs/pages/getting-started.html +1 -1
  64. package/docs/pages/migration.html +2 -2
  65. package/package.json +2 -2
  66. package/build/tools/cursor_list_conversations.d.ts +0 -7
  67. package/build/tools/cursor_list_conversations.js +0 -35
  68. package/build/tools/cursor_search_conversations.d.ts +0 -7
  69. package/build/tools/cursor_search_conversations.js +0 -36
@@ -194,6 +194,18 @@ export declare const SyncReportSchema: {
194
194
  readonly patterns: {
195
195
  readonly type: "number";
196
196
  };
197
+ readonly shadcnBlocks: {
198
+ readonly type: "number";
199
+ };
200
+ readonly shadcnComponents: {
201
+ readonly type: "number";
202
+ };
203
+ readonly themes: {
204
+ readonly type: "number";
205
+ };
206
+ readonly vercelGuidelines: {
207
+ readonly type: "number";
208
+ };
197
209
  };
198
210
  };
199
211
  readonly version: {
@@ -421,6 +433,10 @@ export interface SyncReport {
421
433
  icons?: number;
422
434
  components?: number;
423
435
  patterns?: number;
436
+ shadcnBlocks?: number;
437
+ shadcnComponents?: number;
438
+ themes?: number;
439
+ vercelGuidelines?: number;
424
440
  };
425
441
  version?: string;
426
442
  timestamp?: string;
@@ -100,6 +100,10 @@ export const SyncReportSchema = {
100
100
  icons: { type: 'number' },
101
101
  components: { type: 'number' },
102
102
  patterns: { type: 'number' },
103
+ shadcnBlocks: { type: 'number' },
104
+ shadcnComponents: { type: 'number' },
105
+ themes: { type: 'number' },
106
+ vercelGuidelines: { type: 'number' },
103
107
  },
104
108
  },
105
109
  version: { type: 'string' },
@@ -33,7 +33,7 @@ export const uiDesignSystemSchema = {
33
33
  };
34
34
  export const uiSearchSchema = {
35
35
  name: "ui_search",
36
- description: "搜索 UI/UX 数据库,包括颜色、图标、图表、组件、设计模式等。支持三种模式:search(搜索数据)、catalog(查看组件目录)、template(搜索 UI 模板)。使用 BM25 算法进行智能搜索,支持按类别和技术栈过滤。数据来源:uipro-cli npm 包(v2.2.0+)。",
36
+ description: "搜索 UI/UX 数据库,包括颜色、图标、图表、组件、设计模式,以及 shadcn/ui blocks、UI 主题预设(CSS variables)、Vercel Web Interface Guidelines 等。支持 search / catalog / template 三种模式。",
37
37
  inputSchema: {
38
38
  type: "object",
39
39
  properties: {
@@ -48,7 +48,7 @@ export const uiSearchSchema = {
48
48
  },
49
49
  category: {
50
50
  type: "string",
51
- description: "数据类别(仅 search 模式):colors(颜色)、icons(图标)、charts(图表)、landing(落地页)、products(产品)、typography(字体)、styles(样式)、ux-guidelines(UX 指南)、web-interface(Web 界面)等",
51
+ description: "数据类别(search 模式):colorsiconschartslandingproductstypographystylesux-guidelines、shadcn-blocks、shadcn-components、ui-themes、ui-guidelines-vercel ",
52
52
  },
53
53
  stack: {
54
54
  type: "string",
@@ -69,7 +69,7 @@ export const uiSearchSchema = {
69
69
  };
70
70
  export const syncUiDataSchema = {
71
71
  name: "sync_ui_data",
72
- description: "同步 UI/UX 数据到本地缓存。从 npm 包 uipro-cli 下载最新数据,支持自动检查更新和强制同步。数据存储在 ~/.mcp-probe-kit/ui-ux-data/,默认在下次启动时生效以保证当前会话一致性。",
72
+ description: "同步 UI/UX 数据到本地缓存。来源:uipro-cli、shadcn/ui registry、内嵌 UI 主题预设、Vercel Web Interface Guidelines。",
73
73
  inputSchema: {
74
74
  type: "object",
75
75
  properties: {
@@ -1,67 +1,18 @@
1
1
  import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest';
2
- const listConversationsMock = vi.fn();
3
- const searchHistoryMock = vi.fn();
4
2
  const readConversationMock = vi.fn();
5
3
  vi.mock('../../lib/cursor-history-client.js', () => ({
6
4
  createCursorHistoryClient: () => ({
7
- listConversations: listConversationsMock,
8
- searchHistory: searchHistoryMock,
9
5
  readConversation: readConversationMock,
10
6
  }),
11
7
  }));
12
- import { cursorListConversations } from '../cursor_list_conversations.js';
13
- import { cursorSearchConversations } from '../cursor_search_conversations.js';
14
8
  import { cursorReadConversation } from '../cursor_read_conversation.js';
15
9
  beforeEach(() => {
16
- listConversationsMock.mockReset();
17
- searchHistoryMock.mockReset();
18
10
  readConversationMock.mockReset();
19
11
  });
20
12
  afterEach(() => {
21
13
  vi.clearAllMocks();
22
14
  });
23
15
  describe('cursor history tools', () => {
24
- test('cursor_list_conversations 返回摘要列表', async () => {
25
- listConversationsMock.mockResolvedValue([
26
- { composerId: 'c1', name: '新需求', source: 'composerHeaders' },
27
- ]);
28
- const result = await cursorListConversations({ title_query: '新需求', limit: 10 });
29
- expect(result.isError).toBe(false);
30
- expect('structuredContent' in result).toBe(true);
31
- if (!('structuredContent' in result)) {
32
- throw new Error('structuredContent 缺失');
33
- }
34
- expect(result.content[0].text).toContain('已获取 1 条 Cursor 会话摘要');
35
- expect(result.structuredContent.count).toBe(1);
36
- expect(listConversationsMock).toHaveBeenCalledWith({
37
- titleQuery: '新需求',
38
- workspaceQuery: '',
39
- includeArchived: false,
40
- limit: 10,
41
- });
42
- });
43
- test('cursor_search_conversations 缺少 query 时返回错误', async () => {
44
- const result = await cursorSearchConversations({});
45
- expect(result.isError).toBe(true);
46
- expect(result.content[0].text).toContain('缺少必填参数: query');
47
- });
48
- test('cursor_search_conversations 返回命中结果', async () => {
49
- searchHistoryMock.mockResolvedValue([
50
- { composerId: 'c1', conversationName: '新需求', bubbleId: 'b1', type: 1, text: '我们先聊需求' },
51
- ]);
52
- const result = await cursorSearchConversations({ query: '需求', composer_id: 'c1', limit: 5 });
53
- expect(result.isError).toBe(false);
54
- expect('structuredContent' in result).toBe(true);
55
- if (!('structuredContent' in result)) {
56
- throw new Error('structuredContent 缺失');
57
- }
58
- expect(result.structuredContent.count).toBe(1);
59
- expect(searchHistoryMock).toHaveBeenCalledWith({
60
- query: '需求',
61
- composerId: 'c1',
62
- limit: 5,
63
- });
64
- });
65
16
  test('cursor_read_conversation 返回消息时间线', async () => {
66
17
  readConversationMock.mockResolvedValue({
67
18
  composerId: 'c1',
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,83 @@
1
+ import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest';
2
+ const searchMock = vi.fn();
3
+ const isEnabledMock = vi.fn();
4
+ vi.mock('../../lib/memory-client.js', () => ({
5
+ createMemoryClient: () => ({
6
+ isEnabled: isEnabledMock,
7
+ search: searchMock,
8
+ }),
9
+ }));
10
+ import { searchMemory } from '../search_memory.js';
11
+ import { formatSearchMemoryResultsText } from '../../lib/memory-orchestration.js';
12
+ beforeEach(() => {
13
+ isEnabledMock.mockReset();
14
+ searchMock.mockReset();
15
+ });
16
+ afterEach(() => {
17
+ vi.clearAllMocks();
18
+ });
19
+ describe('formatSearchMemoryResultsText', () => {
20
+ test('renders id, summary, description and read hint', () => {
21
+ const text = formatSearchMemoryResultsText([
22
+ {
23
+ id: '6c97bd10-654e-4f25-a560-99f7469dc11a',
24
+ score: 0.678,
25
+ name: 'playwright-e2e-testing-speed-pattern',
26
+ type: 'pattern',
27
+ description: 'Speed up Playwright E2E suites',
28
+ summary: 'Playwright E2E parallelization pattern',
29
+ tags: ['pattern', 'e2e'],
30
+ },
31
+ ]);
32
+ expect(text).toContain('找到 1 条相关记忆');
33
+ expect(text).toContain('id: 6c97bd10-654e-4f25-a560-99f7469dc11a');
34
+ expect(text).toContain('摘要: Playwright E2E parallelization pattern');
35
+ expect(text).toContain('描述: Speed up Playwright E2E suites');
36
+ expect(text).toContain('read_memory_asset {"asset_id": "6c97bd10-654e-4f25-a560-99f7469dc11a"}');
37
+ });
38
+ test('returns empty-state text', () => {
39
+ expect(formatSearchMemoryResultsText([])).toBe('未找到相关记忆');
40
+ });
41
+ });
42
+ describe('search_memory 单元测试', () => {
43
+ test('记忆服务未开启时返回跳过结果', async () => {
44
+ isEnabledMock.mockReturnValue(false);
45
+ const result = await searchMemory({ query: 'test' });
46
+ expect(result.isError).toBe(false);
47
+ expect('structuredContent' in result).toBe(true);
48
+ if (!('structuredContent' in result)) {
49
+ throw new Error('structuredContent 缺失');
50
+ }
51
+ expect(result.content[0].text).toContain('记忆服务未开启');
52
+ expect(result.structuredContent).toEqual({ enabled: false, results: [] });
53
+ expect(searchMock).not.toHaveBeenCalled();
54
+ });
55
+ test('命中结果时文本输出包含 asset 字段', async () => {
56
+ isEnabledMock.mockReturnValue(true);
57
+ searchMock.mockResolvedValue([
58
+ {
59
+ id: 'asset-1',
60
+ score: 0.88,
61
+ name: 'feishu-proxy-bug',
62
+ type: 'bugfix',
63
+ description: 'Feishu proxy mismatch',
64
+ summary: 'proxy caused 400 on HTTPS',
65
+ tags: ['bugfix', 'proxy'],
66
+ },
67
+ ]);
68
+ const result = await searchMemory({ query: 'proxy', limit: 1 });
69
+ expect(result.isError).toBe(false);
70
+ expect('structuredContent' in result).toBe(true);
71
+ if (!('structuredContent' in result)) {
72
+ throw new Error('structuredContent 缺失');
73
+ }
74
+ expect(result.content[0].text).toContain('id: asset-1');
75
+ expect(result.content[0].text).toContain('摘要: proxy caused 400 on HTTPS');
76
+ expect(result.content[0].text).toContain('描述: Feishu proxy mismatch');
77
+ expect(result.structuredContent.results[0]).toEqual(expect.objectContaining({
78
+ id: 'asset-1',
79
+ description: 'Feishu proxy mismatch',
80
+ summary: 'proxy caused 400 on HTTPS',
81
+ }));
82
+ });
83
+ });
@@ -17,8 +17,8 @@ describe('start_ui 属性测试', () => {
17
17
  const text = result.content[0].text || '';
18
18
  // 简单的 token 估算:按空格和标点分割
19
19
  const tokenCount = text.split(/[\s\n]+/).length;
20
- // 硬性约束:必须少于 800 tokens
21
- expect(tokenCount).toBeLessThan(800);
20
+ // 硬性约束:必须少于 1050 tokens(含 shadcn/主题/规范路径后略增)
21
+ expect(tokenCount).toBeLessThan(1050);
22
22
  }), { numRuns: 100 });
23
23
  });
24
24
  // Feature: ui-workflow-execution-issue, Property 18: 一致的 Markdown 结构
@@ -242,7 +242,8 @@ test('任务 6.4: 无模糊语言', async () => {
242
242
  match.includes('文件') ||
243
243
  match.includes('权限') ||
244
244
  match.includes('docs/') ||
245
- match.includes('目录');
245
+ match.includes('目录') ||
246
+ match.includes('`');
246
247
  expect(hasSpecific).toBe(true);
247
248
  });
248
249
  }), { numRuns: 100 });
@@ -20,8 +20,6 @@ export { searchMemory } from "./search_memory.js";
20
20
  export { readMemoryAsset } from "./read_memory_asset.js";
21
21
  export { memorizeAsset } from "./memorize_asset.js";
22
22
  export { scanAndExtractPatterns } from "./scan_and_extract_patterns.js";
23
- export { cursorListConversations } from "./cursor_list_conversations.js";
24
- export { cursorSearchConversations } from "./cursor_search_conversations.js";
25
23
  export { cursorReadConversation } from "./cursor_read_conversation.js";
26
24
  export { startProduct } from "./start_product.js";
27
25
  export { gitWorkReport } from "./git_work_report.js";
@@ -24,8 +24,6 @@ export { searchMemory } from "./search_memory.js";
24
24
  export { readMemoryAsset } from "./read_memory_asset.js";
25
25
  export { memorizeAsset } from "./memorize_asset.js";
26
26
  export { scanAndExtractPatterns } from "./scan_and_extract_patterns.js";
27
- export { cursorListConversations } from "./cursor_list_conversations.js";
28
- export { cursorSearchConversations } from "./cursor_search_conversations.js";
29
27
  export { cursorReadConversation } from "./cursor_read_conversation.js";
30
28
  // 产品设计工作流
31
29
  export { startProduct } from "./start_product.js";
@@ -1,7 +1,7 @@
1
1
  import { parseArgs, getString, getNumber } from '../utils/parseArgs.js';
2
2
  import { okStructured } from '../lib/response.js';
3
3
  import { createMemoryClient } from '../lib/memory-client.js';
4
- import { shouldShowSourceInSearch } from '../lib/memory-orchestration.js';
4
+ import { formatSearchMemoryResultsText, shouldShowSourceInSearch, } from '../lib/memory-orchestration.js';
5
5
  import { getMemoryConfig } from '../lib/memory-config.js';
6
6
  import { handleToolError } from '../utils/error-handler.js';
7
7
  export async function searchMemory(args) {
@@ -40,11 +40,12 @@ export async function searchMemory(args) {
40
40
  score: item.score,
41
41
  name: item.name,
42
42
  type: item.type,
43
+ description: item.description,
43
44
  summary: item.summary,
44
45
  tags: item.tags,
45
46
  sourcePath: shouldShowSourceInSearch(item, config) ? item.sourcePath : undefined,
46
47
  }));
47
- return okStructured(results.length > 0 ? `找到 ${results.length} 条相关记忆` : '未找到相关记忆', {
48
+ return okStructured(formatSearchMemoryResultsText(results, config), {
48
49
  enabled: true,
49
50
  query,
50
51
  count: results.length,
@@ -17,6 +17,27 @@ import { detectProjectType } from "../lib/project-detector.js";
17
17
  import { resolveWorkspaceRoot, isLikelyProjectNamedRelativePath, buildProjectRootRetryHint } from "../lib/workspace-root.js";
18
18
  import { reportToolProgress, throwIfAborted, } from "../lib/tool-execution-context.js";
19
19
  import { buildMemoryPlanStep, loadMemoryInjectionContext, renderMemoryGuideSection, } from "../lib/memory-orchestration.js";
20
+ import { isShadcnStack } from "../lib/shadcn-ui.js";
21
+ function buildShadcnBlocksPlanStep(description, framework) {
22
+ if (!isShadcnStack(framework)) {
23
+ return [];
24
+ }
25
+ return [
26
+ {
27
+ id: 'shadcn-blocks',
28
+ tool: 'ui_search',
29
+ when: 'React/Next 栈:调用 ui_search(category=shadcn-blocks)匹配 block',
30
+ args: {
31
+ mode: 'search',
32
+ query: description,
33
+ category: 'shadcn-blocks',
34
+ stack: framework,
35
+ limit: 5,
36
+ },
37
+ outputs: [],
38
+ },
39
+ ];
40
+ }
20
41
  function inferProductType(description) {
21
42
  const text = (description || '').toLowerCase();
22
43
  if (/电商|e-?commerce|shop|商城|购物/.test(text))
@@ -651,6 +672,7 @@ start_ui <描述> --requirements_mode=loop
651
672
  args: {},
652
673
  outputs: ['docs/ui/component-catalog.json'],
653
674
  },
675
+ ...buildShadcnBlocksPlanStep(description, framework),
654
676
  {
655
677
  id: 'template',
656
678
  tool: 'ui_search',
@@ -867,6 +889,7 @@ ${recommendation.reasoning}
867
889
  args: {},
868
890
  outputs: ['docs/ui/component-catalog.json'],
869
891
  },
892
+ ...buildShadcnBlocksPlanStep(description, inferredStack),
870
893
  {
871
894
  id: 'template',
872
895
  tool: 'ui_search',
@@ -1078,6 +1101,7 @@ start_ui "设置页面" --framework=react
1078
1101
  args: {},
1079
1102
  outputs: ['docs/ui/component-catalog.json'],
1080
1103
  },
1104
+ ...buildShadcnBlocksPlanStep(description, framework),
1081
1105
  {
1082
1106
  id: 'template',
1083
1107
  tool: 'ui_search',
@@ -1151,9 +1175,12 @@ start_ui "设置页面" --framework=react
1151
1175
  ],
1152
1176
  artifacts: [],
1153
1177
  nextSteps: [
1154
- '检查项目上下文,如不存在则调用 init_project_context',
1155
- '检查设计系统文件,如不存在则调用 ui_design_system',
1156
- '检查组件目录,如不存在则调用 init_component_catalog',
1178
+ '检查 docs/project-context.md,如不存在则调用 init_project_context',
1179
+ '检查 docs/design-system.md,如不存在则调用 ui_design_system',
1180
+ '检查 docs/ui/component-catalog.json,如不存在则调用 init_component_catalog',
1181
+ ...(isShadcnStack(framework)
1182
+ ? [`调用 ui_search --category=shadcn-blocks --query="${description}" 匹配 shadcn block`]
1183
+ : []),
1157
1184
  `调用 ui_search --mode=template --query="${description}"`,
1158
1185
  `保存模板到 docs/ui/${templateName}.json`,
1159
1186
  `调用 render_ui --framework="${framework}"`,