@commercetools/nimbus-mcp 3.5.1 → 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 (119) hide show
  1. package/data/docs/route-manifest.json +275 -9
  2. package/data/docs/routes/components-buttons-toggle-button-group.json +143 -18
  3. package/data/docs/routes/components-buttons-toggle-button.json +72 -15
  4. package/data/docs/routes/components-chat.json +36 -0
  5. package/data/docs/routes/components-content.json +36 -0
  6. package/data/docs/routes/components-data-display-data-table.json +1 -1
  7. package/data/docs/routes/components-feedback-popover.json +643 -0
  8. package/data/docs/routes/components-inputs-combo-box.json +33 -11
  9. package/data/docs/routes/components-inputs-search-input.json +29 -7
  10. package/data/docs/routes/components-inputs-select-input.json +23 -1
  11. package/data/docs/routes/components-layout-stack.json +1 -1
  12. package/data/docs/routes/components-navigation-toolbar.json +1 -1
  13. package/data/docs/routes/components-navigation-tree.json +2 -2
  14. package/data/docs/routes/home-contribute.json +29 -8
  15. package/data/docs/routes/home-getting-started-collaboration.json +657 -0
  16. package/data/docs/search-index.json +1 -1
  17. package/data/docs/types/AccordionContent.json +12 -12
  18. package/data/docs/types/AccordionHeader.json +46 -46
  19. package/data/docs/types/AccordionItem.json +20 -20
  20. package/data/docs/types/AccordionRoot.json +12 -12
  21. package/data/docs/types/ActivityIndicator.json +3 -2
  22. package/data/docs/types/AlertDismissButton.json +42 -42
  23. package/data/docs/types/Button.json +47 -46
  24. package/data/docs/types/Calendar.json +43 -42
  25. package/data/docs/types/Checkbox.json +30 -29
  26. package/data/docs/types/Code.json +2 -1
  27. package/data/docs/types/ComboBoxListBox.json +34 -34
  28. package/data/docs/types/ComboBoxOption.json +20 -20
  29. package/data/docs/types/ComboBoxPopover.json +67 -86
  30. package/data/docs/types/ComboBoxRoot.json +15 -0
  31. package/data/docs/types/ComboBoxSection.json +14 -14
  32. package/data/docs/types/DataTableBody.json +10 -10
  33. package/data/docs/types/DataTableCell.json +18 -18
  34. package/data/docs/types/DataTableColumn.json +28 -28
  35. package/data/docs/types/DataTableHeader.json +10 -10
  36. package/data/docs/types/DataTableManager.json +3 -5
  37. package/data/docs/types/DataTableRow.json +24 -24
  38. package/data/docs/types/DateInput.json +33 -32
  39. package/data/docs/types/DatePicker.json +32 -32
  40. package/data/docs/types/DateRangePicker.json +46 -46
  41. package/data/docs/types/DateRangePickerField.json +46 -46
  42. package/data/docs/types/DialogCloseTrigger.json +42 -42
  43. package/data/docs/types/DraggableListField.json +28 -28
  44. package/data/docs/types/DraggableListItem.json +18 -18
  45. package/data/docs/types/DraggableListRoot.json +30 -30
  46. package/data/docs/types/DrawerCloseTrigger.json +42 -42
  47. package/data/docs/types/DropZone.json +14 -14
  48. package/data/docs/types/FloatingActionButton.json +44 -44
  49. package/data/docs/types/Group.json +9 -7
  50. package/data/docs/types/Heading.json +3 -2
  51. package/data/docs/types/Icon.json +3 -2
  52. package/data/docs/types/IconButton.json +47 -46
  53. package/data/docs/types/IconToggleButton.json +71 -35
  54. package/data/docs/types/Link.json +3 -2
  55. package/data/docs/types/LoadingSpinner.json +3 -2
  56. package/data/docs/types/LocalizedField.json +3 -2
  57. package/data/docs/types/MakeElementFocusable.json +2 -2
  58. package/data/docs/types/MenuItem.json +22 -22
  59. package/data/docs/types/MenuRoot.json +31 -31
  60. package/data/docs/types/MenuSection.json +16 -16
  61. package/data/docs/types/MenuSubmenuTrigger.json +4 -4
  62. package/data/docs/types/MenuTrigger.json +46 -46
  63. package/data/docs/types/MoneyInput.json +4 -2
  64. package/data/docs/types/MultilineTextInput.json +27 -26
  65. package/data/docs/types/MultilineTextInputField.json +27 -26
  66. package/data/docs/types/NumberInput.json +14 -12
  67. package/data/docs/types/NumberInputField.json +10 -10
  68. package/data/docs/types/PasswordInput.json +24 -24
  69. package/data/docs/types/PasswordInputField.json +24 -24
  70. package/data/docs/types/Popover.json +13 -0
  71. package/data/docs/types/PopoverContent.json +42 -0
  72. package/data/docs/types/PopoverRoot.json +651 -0
  73. package/data/docs/types/PopoverTrigger.json +914 -0
  74. package/data/docs/types/ProgressBar.json +17 -15
  75. package/data/docs/types/RadioInputOption.json +17 -17
  76. package/data/docs/types/RadioInputRoot.json +10 -10
  77. package/data/docs/types/RangeCalendar.json +42 -42
  78. package/data/docs/types/RangeSlider.json +14 -14
  79. package/data/docs/types/Region.json +3 -2
  80. package/data/docs/types/RichTextInput.json +4 -2
  81. package/data/docs/types/SearchInput.json +60 -28
  82. package/data/docs/types/SearchInputField.json +60 -28
  83. package/data/docs/types/SelectOption.json +20 -20
  84. package/data/docs/types/SelectOptionGroup.json +14 -14
  85. package/data/docs/types/SelectOptions.json +34 -34
  86. package/data/docs/types/SelectRoot.json +67 -52
  87. package/data/docs/types/Separator.json +4 -2
  88. package/data/docs/types/Slider.json +18 -16
  89. package/data/docs/types/SplitButton.json +12 -10
  90. package/data/docs/types/Switch.json +11 -10
  91. package/data/docs/types/TagGroupRoot.json +12 -12
  92. package/data/docs/types/TagGroupTag.json +16 -16
  93. package/data/docs/types/TagGroupTagList.json +12 -12
  94. package/data/docs/types/TextInput.json +27 -26
  95. package/data/docs/types/TextInputField.json +27 -26
  96. package/data/docs/types/TimeInput.json +30 -28
  97. package/data/docs/types/ToastOutlet.json +4 -2
  98. package/data/docs/types/ToggleButton.json +74 -37
  99. package/data/docs/types/ToggleButtonGroup.json +4 -2
  100. package/data/docs/types/ToggleButtonGroupButton.json +547 -55
  101. package/data/docs/types/ToggleButtonGroupRoot.json +48 -16
  102. package/data/docs/types/Toolbar.json +11 -9
  103. package/data/docs/types/Tooltip.json +3 -2
  104. package/data/docs/types/TooltipContent.json +26 -26
  105. package/data/docs/types/TooltipRoot.json +16 -16
  106. package/data/docs/types/TreeIndicator.json +40 -40
  107. package/data/docs/types/TreeItem.json +20 -20
  108. package/data/docs/types/TreeRoot.json +26 -26
  109. package/data/docs/types/VisuallyHidden.json +4 -4
  110. package/data/docs/types/createItemsFromCsvDrop.json +2 -2
  111. package/data/docs/types/createItemsFromDirectoryDrop.json +2 -2
  112. package/data/docs/types/createItemsFromFileDrop.json +2 -2
  113. package/data/docs/types/createItemsFromImageDrop.json +2 -2
  114. package/data/docs/types/createItemsFromJsonDrop.json +2 -2
  115. package/data/docs/types/manifest.json +4 -0
  116. package/data/docs/types/useTree.json +8 -8
  117. package/data/style-props-summary.json +408 -0
  118. package/dist/index.js +156 -43
  119. package/package.json +8 -8
package/dist/index.js CHANGED
@@ -84,6 +84,9 @@ var getDocsManifest = lazyJson("docs/docs.json");
84
84
  var getIconCatalog = lazyJson("icons.json");
85
85
  var getFlatTokenData = lazyJson("tokens.json");
86
86
  var getUiKitTokenMap = lazyJson("uikit-tokens.json");
87
+ var getStylePropsSummary = lazyJson(
88
+ "style-props-summary.json"
89
+ );
87
90
 
88
91
  // src/utils/markdown.ts
89
92
  function stripMarkdown(text) {
@@ -282,6 +285,24 @@ function routePathToSlug(path) {
282
285
  }
283
286
 
284
287
  // src/tools/get-component.ts
288
+ var STYLE_PROPS_HINT = 'Also accepts style props. Use get_docs_page(path: "home/style-props") for full reference.';
289
+ async function componentSupportsStyleProps(exportName) {
290
+ try {
291
+ const typeData = await getTypeData(exportName);
292
+ if (typeData.supportsStyleProps) return true;
293
+ } catch {
294
+ }
295
+ const subFiles = await findSubComponentFiles(exportName);
296
+ for (const file of subFiles) {
297
+ try {
298
+ const subName = file.replace(/\.json$/, "");
299
+ const subData = await getTypeData(subName);
300
+ if (subData.supportsStyleProps) return true;
301
+ } catch {
302
+ }
303
+ }
304
+ return false;
305
+ }
285
306
  var SECTION_KEYS = [
286
307
  "overview",
287
308
  "guidelines",
@@ -327,7 +348,7 @@ var resolveCatalogCache;
327
348
  var resolveCatalogRoutesRef;
328
349
  var topLevelNamesCache;
329
350
  var topLevelNamesRoutesRef;
330
- async function aggregateSubComponentProps(exportName) {
351
+ async function findSubComponentFiles(exportName) {
331
352
  const typesDir = resolve3(getDataDir(), "docs/types");
332
353
  let files;
333
354
  try {
@@ -344,7 +365,7 @@ async function aggregateSubComponentProps(exportName) {
344
365
  }
345
366
  const topLevelNames = topLevelNamesCache;
346
367
  const prefix = exportName.toLowerCase();
347
- const subFiles = files.filter((f) => {
368
+ return files.filter((f) => {
348
369
  const base = f.replace(/\.json$/, "");
349
370
  const baseLower = base.toLowerCase();
350
371
  return f.endsWith(".json") && baseLower.startsWith(prefix) && baseLower !== prefix && // exclude the top-level file itself
@@ -352,17 +373,25 @@ async function aggregateSubComponentProps(exportName) {
352
373
  !base.endsWith("Props") && // exclude type-only duplicates (e.g. StepsRootProps)
353
374
  !topLevelNames.has(baseLower);
354
375
  });
376
+ }
377
+ async function aggregateSubComponentPropsWithStyleInfo(exportName) {
378
+ const subFiles = await findSubComponentFiles(exportName);
379
+ const stylePropsSubComponents = [];
355
380
  const settled = await Promise.allSettled(
356
381
  subFiles.map(async (file) => {
357
382
  const subName = file.replace(/\.json$/, "");
358
383
  const typeData = await getTypeData(subName);
384
+ if (typeData.supportsStyleProps) {
385
+ stylePropsSubComponents.push(subName);
386
+ }
359
387
  return filterProps(typeData).map((p) => ({
360
388
  ...p,
361
389
  subComponent: subName
362
390
  }));
363
391
  })
364
392
  );
365
- return settled.filter((r) => r.status === "fulfilled").flatMap((r) => r.value);
393
+ const props = settled.filter((r) => r.status === "fulfilled").flatMap((r) => r.value);
394
+ return { props, stylePropsSubComponents: stylePropsSubComponents.sort() };
366
395
  }
367
396
  var CATALOG_CATEGORIES = /* @__PURE__ */ new Set(["Components", "Patterns"]);
368
397
  async function resolveComponent(name) {
@@ -441,6 +470,10 @@ function registerGetComponent(server) {
441
470
  const availableSections = [...viewSections, "props"];
442
471
  if (!section) {
443
472
  const metadata = buildMetadataResponse(entry, availableSections);
473
+ const exportName = entry.exportName ?? entry.title;
474
+ if (await componentSupportsStyleProps(exportName)) {
475
+ metadata.styleProps = STYLE_PROPS_HINT;
476
+ }
444
477
  return {
445
478
  content: [
446
479
  {
@@ -455,18 +488,27 @@ function registerGetComponent(server) {
455
488
  try {
456
489
  const typeData = await getTypeData(exportName);
457
490
  let filtered = filterProps(typeData);
491
+ const response = {
492
+ component: exportName,
493
+ propCount: filtered.length,
494
+ props: filtered
495
+ };
458
496
  if (filtered.length === 0) {
459
- filtered = await aggregateSubComponentProps(exportName);
497
+ const { props, stylePropsSubComponents } = await aggregateSubComponentPropsWithStyleInfo(exportName);
498
+ filtered = props;
499
+ response.propCount = filtered.length;
500
+ response.props = filtered;
501
+ if (stylePropsSubComponents.length > 0) {
502
+ response.styleProps = `${stylePropsSubComponents.join(", ")} also accept style props. Use get_docs_page(path: "home/style-props") for full reference.`;
503
+ }
504
+ } else if (typeData.supportsStyleProps) {
505
+ response.styleProps = STYLE_PROPS_HINT;
460
506
  }
461
507
  return {
462
508
  content: [
463
509
  {
464
510
  type: "text",
465
- text: JSON.stringify({
466
- component: exportName,
467
- propCount: filtered.length,
468
- props: filtered
469
- })
511
+ text: JSON.stringify(response)
470
512
  }
471
513
  ]
472
514
  };
@@ -1261,6 +1303,8 @@ function registerSearchIcons(server) {
1261
1303
 
1262
1304
  // src/tools/get-docs-page.ts
1263
1305
  import { z as z6 } from "zod";
1306
+ var STYLE_PROPS_HINT2 = 'Also accepts style props. Use get_docs_page(path: "home/style-props") for full reference.';
1307
+ var COMPONENT_ROUTE_PREFIX = "components/";
1264
1308
  var viewContentCache2 = /* @__PURE__ */ new WeakMap();
1265
1309
  function getCachedStripped(viewObj) {
1266
1310
  let cached = viewContentCache2.get(viewObj);
@@ -1270,6 +1314,36 @@ function getCachedStripped(viewObj) {
1270
1314
  }
1271
1315
  return cached;
1272
1316
  }
1317
+ async function enrichStylePropsLanding(content) {
1318
+ try {
1319
+ const summary = await getStylePropsSummary();
1320
+ const lines = summary.categories.map(
1321
+ (c) => `${c.name} (${c.path}): ${c.props.join(", ")}`
1322
+ );
1323
+ return content + "\n\n--- Style Props Index ---\n" + lines.join("\n") + `
1324
+
1325
+ ${summary.hint}`;
1326
+ } catch {
1327
+ return content;
1328
+ }
1329
+ }
1330
+ async function resolveExportName(route) {
1331
+ if (!route.startsWith(COMPONENT_ROUTE_PREFIX)) return void 0;
1332
+ try {
1333
+ const manifest = await getRouteManifest();
1334
+ const entry = manifest.routes.find((r) => r.path === `/${route}`);
1335
+ return entry?.exportName ?? entry?.title;
1336
+ } catch {
1337
+ return void 0;
1338
+ }
1339
+ }
1340
+ async function maybeAddStylePropsHint(result, route) {
1341
+ const exportName = await resolveExportName(route);
1342
+ if (!exportName) return;
1343
+ if (await componentSupportsStyleProps(exportName)) {
1344
+ result.styleProps = STYLE_PROPS_HINT2;
1345
+ }
1346
+ }
1273
1347
  function registerGetDocsPage(server) {
1274
1348
  server.registerTool(
1275
1349
  "get_docs_page",
@@ -1325,6 +1399,7 @@ function registerGetDocsPage(server) {
1325
1399
  sections: availableSections,
1326
1400
  content: getCachedStripped(view)
1327
1401
  };
1402
+ await maybeAddStylePropsHint(result2, meta.route);
1328
1403
  return {
1329
1404
  content: [{ type: "text", text: JSON.stringify(result2) }]
1330
1405
  };
@@ -1338,6 +1413,9 @@ ${getCachedStripped(view)}`).join("\n\n");
1338
1413
  } else {
1339
1414
  content = meta.description;
1340
1415
  }
1416
+ if (meta.route === "home/style-props") {
1417
+ content = await enrichStylePropsLanding(content);
1418
+ }
1341
1419
  const result = {
1342
1420
  title: meta.title,
1343
1421
  description: meta.description,
@@ -1345,6 +1423,7 @@ ${getCachedStripped(view)}`).join("\n\n");
1345
1423
  sections: availableSections,
1346
1424
  content
1347
1425
  };
1426
+ await maybeAddStylePropsHint(result, meta.route);
1348
1427
  return {
1349
1428
  content: [{ type: "text", text: JSON.stringify(result) }]
1350
1429
  };
@@ -1416,9 +1495,9 @@ var MIGRATION_DATA = [
1416
1495
  nimbusEquivalent: "Button",
1417
1496
  importPath: "@commercetools/nimbus",
1418
1497
  mappingType: "variant",
1419
- notes: `Use <Button variant="ghost"> for flat styling. UI Kit tone prop ('primary'|'secondary'|'inverted'|'critical') maps to Nimbus colorPalette/variant.`,
1498
+ notes: `Use <Button variant="ghost" size="sm"> for flat styling. FlatButton renders compact \u2014 set size='sm' to match. UI Kit tone prop ('primary'|'secondary'|'inverted'|'critical') maps to Nimbus colorPalette/variant.`,
1420
1499
  breakingChanges: [
1421
- "Replace FlatButton with <Button>",
1500
+ "Replace FlatButton with <Button variant='ghost' size='sm'>",
1422
1501
  "Default color changed: UI Kit FlatButton was blue (tone='primary') by default; Nimbus Button defaults to colorPalette='neutral' (gray). Add colorPalette='primary' to preserve the blue appearance.",
1423
1502
  "label prop replaced by children",
1424
1503
  "tone prop replaced by variant/colorPalette",
@@ -2142,7 +2221,7 @@ var MIGRATION_DATA = [
2142
2221
  nimbusEquivalent: "NumberInput",
2143
2222
  importPath: "@commercetools/nimbus",
2144
2223
  mappingType: "direct",
2145
- notes: "Direct replacement. UI Kit value was string|number and onChange was ChangeEvent<HTMLInputElement>; Nimbus value is a number and onChange receives a number directly. min/max/step prop names unchanged.",
2224
+ notes: "Use NumberInputField (not NumberInput) when a label is needed \u2014 it's a pre-composed field with built-in label, description, and error handling (like TextInputField). UI Kit value was string|number and onChange was ChangeEvent<HTMLInputElement>; Nimbus value is a number and onChange receives a number directly. min/max/step prop names unchanged.",
2146
2225
  breakingChanges: [
2147
2226
  "onChange now receives a number instead of ChangeEvent<HTMLInputElement>",
2148
2227
  "value was string|number; now must be a number",
@@ -2508,12 +2587,13 @@ var MIGRATION_DATA = [
2508
2587
  nimbusEquivalent: "LocalizedField",
2509
2588
  importPath: "@commercetools/nimbus",
2510
2589
  mappingType: "variant",
2511
- notes: 'Use <LocalizedField type="text"> (the default type). LocalizedField manages all locale inputs internally via its type prop.',
2590
+ notes: `Use <LocalizedField type="text"> (the default type). LocalizedField manages all locale inputs internally via its type prop. It collapses non-default locales by default (matching UIKit's behavior) \u2014 do NOT set displayAllLocalesOrCurrencies unless you explicitly want all locales visible. LocalizedField supports style props \u2014 set width='100%' to fill its container (it doesn't stretch by default).`,
2512
2591
  breakingChanges: [
2513
2592
  "Replace LocalizedTextInput with <LocalizedField> (type='text' is the default)",
2514
2593
  "selectedLanguage prop replaced by defaultLocaleOrCurrency",
2515
2594
  "value per locale replaced by valuesByLocaleOrCurrency object",
2516
- "onChange receives a LocalizedFieldChangeEvent with target.locale"
2595
+ "onChange receives a LocalizedFieldChangeEvent with target.locale",
2596
+ "Collapse behavior is built in \u2014 do not add displayAllLocalesOrCurrencies"
2517
2597
  ],
2518
2598
  propMappings: [
2519
2599
  {
@@ -2584,11 +2664,12 @@ var MIGRATION_DATA = [
2584
2664
  nimbusEquivalent: "LocalizedField",
2585
2665
  importPath: "@commercetools/nimbus",
2586
2666
  mappingType: "variant",
2587
- notes: 'Use <LocalizedField type="multiLine">. The type prop controls the input variant; no child composition needed.',
2667
+ notes: `Use <LocalizedField type="multiLine">. The type prop controls the input variant; no child composition needed. Collapses non-default locales by default \u2014 do NOT set displayAllLocalesOrCurrencies. Set width='100%' to fill container (it doesn't stretch by default).`,
2588
2668
  breakingChanges: [
2589
2669
  "Replace LocalizedMultilineTextInput with <LocalizedField type='multiLine'>",
2590
2670
  "selectedLanguage prop replaced by defaultLocaleOrCurrency",
2591
2671
  "value per locale replaced by valuesByLocaleOrCurrency object",
2672
+ "Collapse behavior is built in \u2014 do not add displayAllLocalesOrCurrencies",
2592
2673
  "onChange receives a LocalizedFieldChangeEvent with target.locale"
2593
2674
  ],
2594
2675
  propMappings: [
@@ -2846,7 +2927,7 @@ var MIGRATION_DATA = [
2846
2927
  nimbusEquivalent: "Badge",
2847
2928
  importPath: "@commercetools/nimbus",
2848
2929
  mappingType: "direct",
2849
- notes: "Rename to Badge. UI Kit used a tone prop; Nimbus uses colorPalette instead. UI Kit tones: 'critical'|'warning'|'positive'|'information'|'primary'|'secondary'. Nimbus colorPalette values: 'critical'|'warning'|'positive'|'info'|'primary'|'neutral'.",
2930
+ notes: "Rename to Badge. UI Kit used a tone prop; Nimbus uses colorPalette instead. UI Kit tones: 'critical'|'warning'|'positive'|'information'|'primary'|'secondary'. Nimbus colorPalette values: 'critical'|'warning'|'positive'|'info'|'primary'|'neutral'. Badge supports style props \u2014 use size='sm' or size='2xs' for compact contexts like table cells, and style props like px, py, fontSize for further tuning.",
2850
2931
  breakingChanges: [
2851
2932
  "Rename to Badge",
2852
2933
  "Default color changed: UI Kit Stamp was blue (tone='information') by default; Nimbus Badge defaults to colorPalette='neutral' (gray). Add colorPalette='info' to preserve the blue appearance.",
@@ -2955,7 +3036,7 @@ var MIGRATION_DATA = [
2955
3036
  nimbusEquivalent: "DataTable",
2956
3037
  importPath: "@commercetools/nimbus",
2957
3038
  mappingType: "direct",
2958
- notes: "Direct replacement. Column definitions require DataTableColumnItem<RowType>[] generic typing. Sort and selection callbacks have new signatures.",
3039
+ notes: "Direct replacement. Column definitions require DataTableColumnItem<RowType>[] generic typing. Sort and selection callbacks have new signatures. Set allowsPinning={false} unless you need row pinning (UIKit DataTable had no pin column). For sticky header with vertical scrolling, set maxHeight on the DataTable. Horizontal scroll shadows are automatic \u2014 they appear when the table overflows its container width. DataTable supports style props, so set maxW directly on it to constrain width and trigger horizontal scrolling.",
2959
3040
  breakingChanges: [
2960
3041
  "columns prop shape changed: key\u2192id, label\u2192header, accessor required (returns cell content, can be string or JSX)",
2961
3042
  "DataTableColumnItem<T> is generic \u2014 without <T> accessors return unknown and TS rejects them as ReactNode",
@@ -3176,10 +3257,10 @@ var MIGRATION_DATA = [
3176
3257
  nimbusEquivalent: "Design tokens",
3177
3258
  importPath: "@commercetools/nimbus-tokens",
3178
3259
  mappingType: "pattern",
3179
- notes: "Replace Constraints.Horizontal with maxWidth design tokens or the Box/Container component.",
3260
+ notes: `Replace <Constraints.Horizontal max={N}> with maxW on the appropriate container. Three approaches depending on context: (1) Single child: <Box maxW="TOKEN"> wrapper or maxW style prop on the child. (2) Multiple constrained siblings in a row: put maxW on the parent <Stack direction="row"> and use flex props on children to share the space proportionally (e.g. flex="2" for wider, flex="1" for narrower). (3) Page-level constraint: maxW on the outermost container. UIKit max value \u2192 Nimbus size token: max=3\u2192'3xs' (224px), max=4\u2192'2xs' (256px), max=5\u2192'xs' (320px), max=6\u2192'xs' (320px), max=7\u2192'sm' (384px), max=8\u2192'sm' (384px), max=9\u2192'md' (448px), max=10\u2192'lg' (512px), max=11\u2192'lg' (512px), max=12\u2192'xl' (576px), max=13\u2192'2xl' (672px), max=14\u2192'2xl' (672px), max=15\u2192'3xl' (768px), max=16\u2192'3xl' (768px).`,
3180
3261
  breakingChanges: [
3181
- "Remove Constraints.Horizontal",
3182
- "Use maxWidth prop with design token values on Box or Container"
3262
+ "Remove Constraints.Horizontal wrapper",
3263
+ "Use maxW with Nimbus size tokens (see notes for lookup table and three approaches)"
3183
3264
  ],
3184
3265
  layoutGuidance: LAYOUT_NESTING_GUIDANCE
3185
3266
  },
@@ -3188,10 +3269,11 @@ var MIGRATION_DATA = [
3188
3269
  nimbusEquivalent: "Stack",
3189
3270
  importPath: "@commercetools/nimbus",
3190
3271
  mappingType: "pattern",
3191
- notes: 'Use <Stack direction="row" gap={...}> with nimbus spacing tokens.',
3272
+ notes: `Use <Stack direction="row" gap={...}> with nimbus spacing tokens. Add flexWrap='wrap' when the row contains multiple form inputs or constrained children that may overflow at narrow viewport widths.`,
3192
3273
  breakingChanges: [
3193
3274
  "Replace Spacings.Inline with <Stack direction='row'>",
3194
- "Spacing values use design token scale (e.g. gap='300')"
3275
+ "Spacing values use design token scale (e.g. gap='300')",
3276
+ "Add flexWrap='wrap' for rows with multiple inputs to prevent overflow"
3195
3277
  ],
3196
3278
  layoutGuidance: LAYOUT_NESTING_GUIDANCE
3197
3279
  },
@@ -3256,7 +3338,7 @@ var MIGRATION_DATA = [
3256
3338
  nimbusEquivalent: "Accordion",
3257
3339
  importPath: "@commercetools/nimbus",
3258
3340
  mappingType: "direct",
3259
- notes: "Rename to Accordion. Uses Accordion.Root, Accordion.Item, Accordion.Header, Accordion.Content composition. UI Kit used isClosed (controlled) + onToggle; the header was a prop, not a child slot.",
3341
+ notes: `Rename to Accordion. Uses Accordion.Root, Accordion.Item, Accordion.Header, Accordion.Content composition. UI Kit used isClosed (controlled) + onToggle; the header was a prop, not a child slot. Set size="sm" on Accordion.Root to match UIKit CollapsiblePanel's compact header sizing.`,
3260
3342
  breakingChanges: [
3261
3343
  "Rename to Accordion",
3262
3344
  "Adopt compositional slot API (Accordion.Root, Accordion.Item, Accordion.Header, Accordion.Content)",
@@ -3366,36 +3448,55 @@ var MIGRATION_DATA = [
3366
3448
  },
3367
3449
  {
3368
3450
  uiKitName: "Text.Headline",
3369
- nimbusEquivalent: "Text",
3451
+ nimbusEquivalent: "Heading",
3370
3452
  importPath: "@commercetools/nimbus",
3371
- mappingType: "variant",
3372
- notes: 'Use <Text size="2xl" fontWeight="bold"> or the Heading component.',
3453
+ mappingType: "direct",
3454
+ notes: 'Use <Heading as="h1" size="lg"> for page titles, or <Heading as="h2" size="md"> for section headings. Heading supports style props \u2014 use them for spacing (e.g. mb, mt) instead of wrapper elements.',
3373
3455
  breakingChanges: [
3374
- "Replace Text.Headline with <Text size='2xl' fontWeight='bold'> or <Heading>"
3456
+ "Replace Text.Headline with <Heading>",
3457
+ "Set the appropriate heading level via the as prop (h1\u2013h6) for semantic HTML",
3458
+ "Set size prop to match visual hierarchy: 'lg' for page titles, 'md' for sections"
3375
3459
  ],
3376
3460
  propMappings: [
3377
3461
  {
3378
3462
  uiKitProp: "_component",
3379
- nimbusProp: null,
3463
+ nimbusProp: "size",
3380
3464
  changeType: "value-mapping",
3381
- fixedValue: "2xl",
3382
- notes: "Also set fontWeight='bold', or use <Heading> instead."
3465
+ fixedValue: "lg",
3466
+ notes: "Use size='lg' for page titles, 'md' for section headings."
3467
+ },
3468
+ {
3469
+ uiKitProp: "as",
3470
+ nimbusProp: "as",
3471
+ changeType: "rename",
3472
+ notes: "Keep the same heading level (h1, h2, etc.)."
3383
3473
  }
3384
3474
  ]
3385
3475
  },
3386
3476
  {
3387
3477
  uiKitName: "Text.Subheadline",
3388
- nimbusEquivalent: "Text",
3478
+ nimbusEquivalent: "Heading",
3389
3479
  importPath: "@commercetools/nimbus",
3390
- mappingType: "variant",
3391
- notes: 'Use <Text size="xl">.',
3392
- breakingChanges: ["Replace Text.Subheadline with <Text size='xl'>"],
3480
+ mappingType: "direct",
3481
+ notes: 'Use <Heading as="h4" size="xs" fontWeight="medium"> for subheadings like card titles and accordion labels. UIKit Subheadline used a medium weight \u2014 Heading defaults to bold, so set fontWeight explicitly. Heading supports style props \u2014 use them for spacing instead of wrapper elements.',
3482
+ breakingChanges: [
3483
+ "Replace Text.Subheadline with <Heading>",
3484
+ "Set the appropriate heading level via the as prop",
3485
+ "Set size='xs' and fontWeight='medium' for subheading-level text"
3486
+ ],
3393
3487
  propMappings: [
3394
3488
  {
3395
3489
  uiKitProp: "_component",
3396
- nimbusProp: null,
3490
+ nimbusProp: "size",
3397
3491
  changeType: "value-mapping",
3398
- fixedValue: "xl"
3492
+ fixedValue: "xs",
3493
+ notes: "Use size='xs' for subheadings, 'md' if slightly larger is needed."
3494
+ },
3495
+ {
3496
+ uiKitProp: "as",
3497
+ nimbusProp: "as",
3498
+ changeType: "rename",
3499
+ notes: "Keep the same heading level (h3, h4, etc.)."
3399
3500
  }
3400
3501
  ]
3401
3502
  },
@@ -5358,7 +5459,8 @@ function buildTokenRedirect(name) {
5358
5459
  hint: `Use the get_tokens tool with the uikitToken parameter to resolve each ${name} token (e.g. get_tokens(uikitToken: "constraint3"))`
5359
5460
  };
5360
5461
  }
5361
- function buildComponentResult(uiKitName) {
5462
+ var STYLE_PROPS_HINT3 = 'Also accepts style props. Use get_docs_page(path: "home/style-props") for full reference.';
5463
+ async function buildComponentResult(uiKitName) {
5362
5464
  const entry = getUiKitMigration(uiKitName);
5363
5465
  if (!entry) return null;
5364
5466
  const result = {
@@ -5385,6 +5487,11 @@ function buildComponentResult(uiKitName) {
5385
5487
  entry.notes
5386
5488
  );
5387
5489
  if (hint) result.hint = hint;
5490
+ if (entry.importPath === "@commercetools/nimbus" && entry.nimbusEquivalent) {
5491
+ if (await componentSupportsStyleProps(entry.nimbusEquivalent)) {
5492
+ result.styleProps = STYLE_PROPS_HINT3;
5493
+ }
5494
+ }
5388
5495
  return result;
5389
5496
  }
5390
5497
  function hoistLayoutGuidance(mappings) {
@@ -5530,7 +5637,7 @@ function registerMigrateFromUiKit(server) {
5530
5637
  ]
5531
5638
  };
5532
5639
  }
5533
- const result = buildComponentResult(componentName);
5640
+ const result = await buildComponentResult(componentName);
5534
5641
  if (result) {
5535
5642
  return {
5536
5643
  content: [
@@ -5543,8 +5650,10 @@ function registerMigrateFromUiKit(server) {
5543
5650
  }
5544
5651
  const compoundEntries = getUiKitCompoundMigrations(componentName);
5545
5652
  if (compoundEntries) {
5546
- const mappings2 = compoundEntries.map(
5547
- (e) => buildComponentResult(e.uiKitName)
5653
+ const mappings2 = await Promise.all(
5654
+ compoundEntries.map((e) => buildComponentResult(e.uiKitName))
5655
+ ).then(
5656
+ (results) => results.filter(Boolean)
5548
5657
  );
5549
5658
  const response2 = {
5550
5659
  compoundRoot: componentName,
@@ -5568,7 +5677,7 @@ function registerMigrateFromUiKit(server) {
5568
5677
  content: [
5569
5678
  {
5570
5679
  type: "text",
5571
- text: JSON.stringify(buildComponentResult(fuzzy))
5680
+ text: JSON.stringify(await buildComponentResult(fuzzy))
5572
5681
  }
5573
5682
  ]
5574
5683
  };
@@ -5636,7 +5745,7 @@ function registerMigrateFromUiKit(server) {
5636
5745
  mappings.push(buildTokenRedirect(name));
5637
5746
  continue;
5638
5747
  }
5639
- const result = buildComponentResult(name);
5748
+ const result = await buildComponentResult(name);
5640
5749
  if (result) {
5641
5750
  mappings.push(result);
5642
5751
  continue;
@@ -5648,7 +5757,8 @@ function registerMigrateFromUiKit(server) {
5648
5757
  );
5649
5758
  const toInclude = used.length > 0 ? used : compoundEntries;
5650
5759
  for (const entry of toInclude) {
5651
- mappings.push(buildComponentResult(entry.uiKitName));
5760
+ const entryResult = await buildComponentResult(entry.uiKitName);
5761
+ if (entryResult) mappings.push(entryResult);
5652
5762
  }
5653
5763
  continue;
5654
5764
  }
@@ -5709,3 +5819,6 @@ main().catch((error) => {
5709
5819
  console.error("Nimbus MCP server error:", error);
5710
5820
  process.exit(1);
5711
5821
  });
5822
+ export {
5823
+ createServer
5824
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@commercetools/nimbus-mcp",
3
- "version": "3.5.1",
3
+ "version": "3.6.0",
4
4
  "description": "MCP server for the Nimbus design system",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -25,19 +25,19 @@
25
25
  },
26
26
  "dependencies": {
27
27
  "@modelcontextprotocol/sdk": "^1.27.1",
28
- "zod": "^4.4.3"
28
+ "zod": "^4.5.4"
29
29
  },
30
30
  "devDependencies": {
31
31
  "@commercetools-frontend/ui-kit": "^20.6.7",
32
32
  "@commercetools-uikit/design-system": "^20.6.4",
33
- "@modelcontextprotocol/inspector": "^0.22.0",
34
- "@types/node": "^24.13.3",
33
+ "@modelcontextprotocol/inspector": "^2.5.0",
34
+ "@types/node": "^26.5.0",
35
35
  "tsup": "^8.5.1",
36
- "tsx": "^4.23.5",
36
+ "tsx": "^4.23.13",
37
37
  "typescript": "~5.9.3",
38
- "@commercetools/nimbus": "^3.5.1",
39
- "@commercetools/nimbus-icons": "^3.5.1",
40
- "@commercetools/nimbus-tokens": "^3.5.1"
38
+ "@commercetools/nimbus": "^3.6.0",
39
+ "@commercetools/nimbus-icons": "^3.6.0",
40
+ "@commercetools/nimbus-tokens": "^3.6.0"
41
41
  },
42
42
  "scripts": {
43
43
  "prebuild": "tsx scripts/prebuild.ts",