@morya-ui/mcp 0.3.4 → 0.3.5

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/dist/tools.js CHANGED
@@ -4,7 +4,7 @@ import { listGoldenPages, readGoldenPageSource, resolveGoldenPageId } from './go
4
4
  import { filterPageSnippets, findPageSnippet, pageSnippets, scorePageSnippet } from './page-snippets.js';
5
5
  import { designRules, findPattern, pagePatterns, scorePattern } from './patterns.js';
6
6
  import { countCatalogResources, countCatalogResourceTemplates } from './resources.js';
7
- import { findStylePreset, resolveStyleDirection, stylePresets, styleResolution, } from './style-presets.js';
7
+ import { resolveListCraftVariant, resolveStyleDirection, styleResolution, } from './style-presets.js';
8
8
  function inspectButtonIconOnlyUsage(code, issues) {
9
9
  const pairedTagRe = /<MButton\b([^>]*)>([\s\S]*?)<\/MButton>/gi;
10
10
  let match = pairedTagRe.exec(code);
@@ -65,6 +65,7 @@ function mapDecisionOption(option, locale) {
65
65
  avoidWhen: zh ? option.avoidWhen : option.avoidWhenEn,
66
66
  recipe,
67
67
  antiPatterns: zh ? option.antiPatterns : option.antiPatternsEn,
68
+ ...(option.relatedSnippets?.length ? { relatedSnippets: option.relatedSnippets } : {}),
68
69
  };
69
70
  }
70
71
  function generatedPageCode(patternId, intent, locale) {
@@ -734,34 +735,30 @@ export function createToolHandlers(catalog = loadCatalog()) {
734
735
  const stylePayload = {
735
736
  resolution: styleDirection.resolution,
736
737
  confidence: styleDirection.confidence,
737
- preset: styleDirection.preset
738
- ? {
739
- id: styleDirection.preset.id,
740
- title: locale === 'en-US' ? styleDirection.preset.titleEn : styleDirection.preset.title,
741
- summary: locale === 'en-US' ? styleDirection.preset.summaryEn : styleDirection.preset.summary,
742
- apply: locale === 'en-US' ? styleDirection.preset.applyEn : styleDirection.preset.apply,
743
- avoid: locale === 'en-US' ? styleDirection.preset.avoidEn : styleDirection.preset.avoid,
744
- }
745
- : null,
746
- candidates: styleDirection.candidates.map((item) => ({
747
- id: item.id,
748
- title: locale === 'en-US' ? item.titleEn : item.title,
749
- score: item.score,
750
- })),
738
+ summary: styleDirection.summary ?? null,
751
739
  guidance: locale === 'en-US' ? styleDirection.guidanceEn : styleDirection.guidanceZh,
752
740
  priority: locale === 'en-US' ? styleResolution.priorityEn : styleResolution.priorityZh,
741
+ hardRules: locale === 'en-US' ? styleResolution.hardRulesEn : styleResolution.hardRulesZh,
753
742
  note: locale === 'en-US'
754
- ? 'If the user supplied a visual reference, follow that first (map to --m-* + M*). Golden pages lock structure, not the only aesthetic.'
755
- : '若用户提供了参考样式,优先跟参考(映射到 --m-* + M*)。黄金样例锁结构,不是唯一审美。',
743
+ ? 'No named style-preset catalog. Follow an explicit user reference/description; if styleDirection.resolution is ask, ask before inventing the look. Prefer snippets for composition; golden pages are optional block-order checks, not aesthetics.'
744
+ : '没有命名风格预设表。有明确参考/描述就跟用户;若 styleDirection.resolution 为 ask,先询问再写完整视觉。优先用 snippets 拼装;黄金样例仅可选核对块顺序,不是审美模板。',
756
745
  };
746
+ const craftText = [args.style || '', args.intent || ''].join(' ');
757
747
  const resolvedGoldenId = resolveGoldenPageId({
758
748
  patternId: best.pattern.id,
759
749
  canonicalGoldenId: best.pattern.goldenPage,
760
- styleId: styleDirection.preset?.id || args.style || null,
750
+ styleId: craftText || null,
761
751
  });
762
752
  const resolvedGoldenPath = resolvedGoldenId
763
753
  ? `docs/golden-pages/${resolvedGoldenId}.vue`
764
754
  : best.pattern.goldenPage;
755
+ let suggestedSnippets = [...(best.pattern.suggestedSnippets ?? [])];
756
+ if (best.pattern.id === 'admin-list') {
757
+ const listCraft = resolveListCraftVariant(craftText);
758
+ if (listCraft === 'list-page-dense') {
759
+ suggestedSnippets = suggestedSnippets.map((id) => id === 'list-filters-stack' ? 'list-filters-dense' : id);
760
+ }
761
+ }
765
762
  const result = {
766
763
  intent: args.intent,
767
764
  pageType: args.pageType,
@@ -778,23 +775,35 @@ export function createToolHandlers(catalog = loadCatalog()) {
778
775
  interactionRules: best.pattern.interactionRules,
779
776
  avoid: best.pattern.avoid,
780
777
  alternatives: ranked.slice(1, 3).filter((item) => item.score > 0).map((item) => ({ id: item.pattern.id, score: item.score })),
778
+ suggestedSnippets,
781
779
  nextStep: (() => {
782
780
  const goldenId = resolvedGoldenId;
781
+ const snippets = suggestedSnippets;
782
+ const snippetHint = snippets.length > 0
783
+ ? locale === 'en-US'
784
+ ? ` Compose with get_page_snippet for: ${snippets.join(', ')}. Use recommend_component for L2 recipes (relatedSnippets).`
785
+ : ` 用 get_page_snippet 拼装:${snippets.join(', ')}。选型用 recommend_component(含 relatedSnippets)。`
786
+ : locale === 'en-US'
787
+ ? ' Compose with get_page_snippet + recommend_component (relatedSnippets).'
788
+ : ' 用 get_page_snippet + recommend_component(relatedSnippets)拼装。';
783
789
  const styleHint = locale === 'en-US'
784
- ? styleDirection.resolution === 'offer'
785
- ? ' Resolve style first (reference → preset → ask among quiet/soft/dense/rail/studio/ink).'
786
- : ` Apply styleDirection preset "${styleDirection.preset?.id || 'n/a'}".`
787
- : styleDirection.resolution === 'offer'
788
- ? ' 先定风格(参考 → 预设 → 请用户从 quiet/soft/dense/rail/studio/ink 选)。'
789
- : ` 套用 styleDirection 预设「${styleDirection.preset?.id || 'n/a'}」。`;
790
+ ? styleDirection.resolution === 'ask'
791
+ ? ' Style is uncertain — ask the user for a short description or reference before inventing the look.'
792
+ : ` Follow styleDirection (${styleDirection.resolution}): “${styleDirection.summary || 'user/reference'}”; honor explicit user words over companions.`
793
+ : styleDirection.resolution === 'ask'
794
+ ? ' 风格不确定 — 先请用户说明气质或贴参考,再写完整视觉。'
795
+ : ` 按 styleDirection(${styleDirection.resolution})落实「${styleDirection.summary || '用户参考/描述'}」;用户明确指定优先于 companion。`;
796
+ const goldenHint = goldenId
797
+ ? locale === 'en-US'
798
+ ? ` Optional: get_golden_page("${goldenId}") only to check whole-page block order (not the default clone target).`
799
+ : ` 可选:仅当需核对整页块顺序时再 get_golden_page("${goldenId}")(默认不要整页克隆)。`
800
+ : locale === 'en-US'
801
+ ? ' No golden page for this pattern — follow get_pattern structure + snippets.'
802
+ : ' 该模式暂无黄金样例:按 get_pattern 结构 + snippets 拼装。';
790
803
  if (locale === 'en-US') {
791
- return goldenId
792
- ? `Call get_golden_page("${goldenId}") and mirror structure.${styleHint} Look up unfamiliar APIs with get_component/get_example, then always run validate_usage and validate_page.`
793
- : `No golden page for this pattern: use get_pattern + get_design_rules.${styleHint} Look up APIs with get_component/get_example, then always run validate_usage and validate_page.`;
804
+ return `${snippetHint.trim()}${styleHint}${goldenHint} Look up unfamiliar APIs with get_component/get_example, then always run validate_usage and validate_page.`;
794
805
  }
795
- return goldenId
796
- ? `调用 get_golden_page("${goldenId}") 并镜像结构。${styleHint} 不熟悉的 API 用 get_component/get_example 核对,然后必须跑 validate_usage 与 validate_page。`
797
- : `该模式暂无黄金样例:用 get_pattern + get_design_rules。${styleHint} API 用 get_component/get_example 核对,然后必须跑 validate_usage 与 validate_page。`;
806
+ return `${snippetHint.trim()}${styleHint}${goldenHint} 不熟悉的 API 用 get_component/get_example 核对,然后必须跑 validate_usage 与 validate_page。`;
798
807
  })(),
799
808
  };
800
809
  if (args.includeScaffold) {
@@ -807,8 +816,8 @@ export function createToolHandlers(catalog = loadCatalog()) {
807
816
  files: { component: golden.source },
808
817
  warnings: [
809
818
  locale === 'en-US'
810
- ? 'Scaffold is the golden page source. Remap domain copy/data only; never invent props. Then validate_usage + validate_page.'
811
- : '脚手架即黄金样例源码。只替换域文案与数据,禁止臆造 prop。完成后必须 validate_usage + validate_page。',
819
+ ? 'Scaffold is an optional structure reference from the golden sample. Prefer composing suggestedSnippets; remap domain copy/data only if you use this source. Never invent props. Then validate_usage + validate_page.'
820
+ : '脚手架是黄金样例的可选结构参考。默认优先拼装 suggestedSnippets;若使用本源码只替换域文案与数据。禁止臆造 prop。完成后必须 validate_usage + validate_page。',
812
821
  ],
813
822
  };
814
823
  }
@@ -821,8 +830,8 @@ export function createToolHandlers(catalog = loadCatalog()) {
821
830
  files: { component: componentSource },
822
831
  warnings: [
823
832
  locale === 'en-US'
824
- ? 'No golden page for this pattern — structural fallback only. Prefer get_pattern + get_component. Must validate_usage before delivery.'
825
- : '该模式暂无黄金样例,仅为结构占位。优先 get_pattern + get_component。交付前必须 validate_usage。',
833
+ ? 'No golden page for this pattern — structural fallback only. Prefer suggestedSnippets + get_component. Must validate_usage before delivery.'
834
+ : '该模式暂无黄金样例,仅为结构占位。优先 suggestedSnippets + get_component。交付前必须 validate_usage。',
826
835
  ],
827
836
  };
828
837
  }
@@ -1155,12 +1164,9 @@ export function createToolHandlers(catalog = loadCatalog()) {
1155
1164
  const styles = {
1156
1165
  resolution: locale === 'en-US' ? styleResolution.priorityEn : styleResolution.priorityZh,
1157
1166
  hardRules: locale === 'en-US' ? styleResolution.hardRulesEn : styleResolution.hardRulesZh,
1158
- presets: stylePresets.map((preset) => ({
1159
- id: preset.id,
1160
- title: locale === 'en-US' ? preset.titleEn : preset.title,
1161
- summary: locale === 'en-US' ? preset.summaryEn : preset.summary,
1162
- lanes: preset.lanes,
1163
- })),
1167
+ note: locale === 'en-US'
1168
+ ? 'No named style-preset catalog. Follow user reference/description; ask when uncertain.'
1169
+ : '没有命名风格预设表。跟用户参考/描述;不确定就先问。',
1164
1170
  };
1165
1171
  if (locale === 'zh-CN') {
1166
1172
  return textResult({
@@ -1226,45 +1232,23 @@ export function createToolHandlers(catalog = loadCatalog()) {
1226
1232
  'Form controls should have a visible label or an equivalent accessible name.',
1227
1233
  'Overlays teleport to body by default; only change appendTo for a clear layout constraint.',
1228
1234
  'Prefer documented component variants over deep CSS overrides.',
1229
- 'Resolve visual style via reference → preset → prompt cues → offer quiet/soft/dense/rail/studio/ink; golden pages lock structure, not aesthetics.',
1235
+ 'Resolve visual style: follow explicit user reference/description first; else infer from clear prompt cues; if uncertain ask once. No named preset catalog. Golden pages lock structure, not aesthetics.',
1230
1236
  ],
1231
1237
  });
1232
1238
  }
1233
- function listStylePresets(args = {}) {
1239
+ function getStyleDirection(args = {}) {
1234
1240
  const locale = resolveLocale(args.mode);
1241
+ const direction = resolveStyleDirection({ intent: args.intent, style: args.style });
1235
1242
  return textResult({
1236
- resolution: locale === 'en-US' ? styleResolution.priorityEn : styleResolution.priorityZh,
1243
+ resolution: direction.resolution,
1244
+ confidence: direction.confidence,
1245
+ summary: direction.summary ?? null,
1246
+ guidance: locale === 'en-US' ? direction.guidanceEn : direction.guidanceZh,
1247
+ priority: locale === 'en-US' ? styleResolution.priorityEn : styleResolution.priorityZh,
1237
1248
  hardRules: locale === 'en-US' ? styleResolution.hardRulesEn : styleResolution.hardRulesZh,
1238
- presets: stylePresets.map((preset) => ({
1239
- id: preset.id,
1240
- title: locale === 'en-US' ? preset.titleEn : preset.title,
1241
- summary: locale === 'en-US' ? preset.summaryEn : preset.summary,
1242
- lanes: preset.lanes,
1243
- keywords: preset.keywords,
1244
- listGoldenPage: preset.listGoldenPage ?? null,
1245
- })),
1246
- });
1247
- }
1248
- function getStylePreset(args) {
1249
- const locale = resolveLocale(args.mode);
1250
- const preset = findStylePreset(args.style);
1251
- if (!preset) {
1252
- return textResult({
1253
- error: `Style preset not found: ${args.style}`,
1254
- available: stylePresets.map((item) => item.id),
1255
- });
1256
- }
1257
- return textResult({
1258
- id: preset.id,
1259
- title: locale === 'en-US' ? preset.titleEn : preset.title,
1260
- summary: locale === 'en-US' ? preset.summaryEn : preset.summary,
1261
- lanes: preset.lanes,
1262
- keywords: preset.keywords,
1263
- listGoldenPage: preset.listGoldenPage ?? null,
1264
- cues: locale === 'en-US' ? preset.cuesEn : preset.cues,
1265
- apply: locale === 'en-US' ? preset.applyEn : preset.apply,
1266
- avoid: locale === 'en-US' ? preset.avoidEn : preset.avoid,
1267
- resolution: locale === 'en-US' ? styleResolution.priorityEn : styleResolution.priorityZh,
1249
+ note: locale === 'en-US'
1250
+ ? 'No named style-preset catalog. Pass style as free-text user description when they specified one.'
1251
+ : '没有命名风格预设表。用户有描述时把原文放进 style;不确定时 resolution 为 ask,应先问用户。',
1268
1252
  });
1269
1253
  }
1270
1254
  function recommendComponent(args) {
@@ -1485,8 +1469,7 @@ export function createToolHandlers(catalog = loadCatalog()) {
1485
1469
  'get_pattern',
1486
1470
  'recommend_page',
1487
1471
  'get_design_rules',
1488
- 'list_style_presets',
1489
- 'get_style_preset',
1472
+ 'get_style_direction',
1490
1473
  'recommend_component',
1491
1474
  'list_golden_pages',
1492
1475
  'get_golden_page',
@@ -1510,8 +1493,7 @@ export function createToolHandlers(catalog = loadCatalog()) {
1510
1493
  getPattern,
1511
1494
  recommendPage,
1512
1495
  getDesignRules,
1513
- listStylePresets,
1514
- getStylePreset,
1496
+ getStyleDirection,
1515
1497
  recommendComponent,
1516
1498
  listGoldenPageCatalog,
1517
1499
  getGoldenPage,
package/package.json CHANGED
@@ -1,8 +1,7 @@
1
1
  {
2
2
  "name": "@morya-ui/mcp",
3
3
  "type": "module",
4
- "version": "0.3.4",
5
- "packageManager": "pnpm@10.12.4",
4
+ "version": "0.3.5",
6
5
  "description": "MCP server for morya-ui — component docs, examples, and usage guidance for AI coding agents.",
7
6
  "license": "MIT",
8
7
  "homepage": "https://github.com/morya-space/morya-ui/tree/main/packages/ui-mcp#readme",
@@ -30,6 +29,14 @@
30
29
  "engines": {
31
30
  "node": ">=20.19.0"
32
31
  },
32
+ "dependencies": {
33
+ "@modelcontextprotocol/sdk": "^1.30.0",
34
+ "zod": "^3.25.76"
35
+ },
36
+ "devDependencies": {
37
+ "@types/node": "^22.19.15",
38
+ "typescript": "^5.9.3"
39
+ },
33
40
  "scripts": {
34
41
  "generate": "node ./scripts/generate-catalog.mjs",
35
42
  "generate:recipes": "node --experimental-strip-types ./scripts/generate-decision-recipes.mjs",
@@ -41,15 +48,6 @@
41
48
  "build": "pnpm run generate && tsc -p tsconfig.json && pnpm run generate:recipes",
42
49
  "start": "node ./dist/index.js",
43
50
  "test": "vitest run --config ../../vitest.config.ts src/__tests__",
44
- "typecheck": "tsc -p tsconfig.json --noEmit",
45
- "prepublishOnly": "pnpm run build"
46
- },
47
- "dependencies": {
48
- "@modelcontextprotocol/sdk": "^1.30.0",
49
- "zod": "^3.25.76"
50
- },
51
- "devDependencies": {
52
- "@types/node": "^22.19.15",
53
- "typescript": "^5.9.3"
51
+ "typecheck": "tsc -p tsconfig.json --noEmit"
54
52
  }
55
- }
53
+ }