@salesforce/b2c-dx-mcp 0.4.0 → 0.4.2

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 (30) hide show
  1. package/dist/commands/mcp.d.ts +4 -4
  2. package/dist/commands/mcp.js +5 -5
  3. package/dist/registry.js +3 -3
  4. package/dist/tools/storefrontnext/index.js +1 -1
  5. package/dist/tools/{page-designer-decorator → storefrontnext/page-designer-decorator}/analyzer.js +2 -2
  6. package/dist/tools/{page-designer-decorator → storefrontnext/page-designer-decorator}/index.d.ts +2 -2
  7. package/dist/tools/{page-designer-decorator → storefrontnext/page-designer-decorator}/index.js +54 -35
  8. package/oclif.manifest.json +8 -5
  9. package/package.json +2 -2
  10. /package/dist/tools/{page-designer-decorator → storefrontnext/page-designer-decorator}/analyzer.d.ts +0 -0
  11. /package/dist/tools/{page-designer-decorator → storefrontnext/page-designer-decorator}/rules/1-mode-selection.d.ts +0 -0
  12. /package/dist/tools/{page-designer-decorator → storefrontnext/page-designer-decorator}/rules/1-mode-selection.js +0 -0
  13. /package/dist/tools/{page-designer-decorator → storefrontnext/page-designer-decorator}/rules/2a-auto-mode.d.ts +0 -0
  14. /package/dist/tools/{page-designer-decorator → storefrontnext/page-designer-decorator}/rules/2a-auto-mode.js +0 -0
  15. /package/dist/tools/{page-designer-decorator → storefrontnext/page-designer-decorator}/rules/2b-0-interactive-overview.d.ts +0 -0
  16. /package/dist/tools/{page-designer-decorator → storefrontnext/page-designer-decorator}/rules/2b-0-interactive-overview.js +0 -0
  17. /package/dist/tools/{page-designer-decorator → storefrontnext/page-designer-decorator}/rules/2b-1-interactive-analyze.d.ts +0 -0
  18. /package/dist/tools/{page-designer-decorator → storefrontnext/page-designer-decorator}/rules/2b-1-interactive-analyze.js +0 -0
  19. /package/dist/tools/{page-designer-decorator → storefrontnext/page-designer-decorator}/rules/2b-2-interactive-select-props.d.ts +0 -0
  20. /package/dist/tools/{page-designer-decorator → storefrontnext/page-designer-decorator}/rules/2b-2-interactive-select-props.js +0 -0
  21. /package/dist/tools/{page-designer-decorator → storefrontnext/page-designer-decorator}/rules/2b-3-interactive-configure-attrs.d.ts +0 -0
  22. /package/dist/tools/{page-designer-decorator → storefrontnext/page-designer-decorator}/rules/2b-3-interactive-configure-attrs.js +0 -0
  23. /package/dist/tools/{page-designer-decorator → storefrontnext/page-designer-decorator}/rules/2b-4-interactive-configure-regions.d.ts +0 -0
  24. /package/dist/tools/{page-designer-decorator → storefrontnext/page-designer-decorator}/rules/2b-4-interactive-configure-regions.js +0 -0
  25. /package/dist/tools/{page-designer-decorator → storefrontnext/page-designer-decorator}/rules/2b-5-interactive-confirm-generation.d.ts +0 -0
  26. /package/dist/tools/{page-designer-decorator → storefrontnext/page-designer-decorator}/rules/2b-5-interactive-confirm-generation.js +0 -0
  27. /package/dist/tools/{page-designer-decorator → storefrontnext/page-designer-decorator}/rules.d.ts +0 -0
  28. /package/dist/tools/{page-designer-decorator → storefrontnext/page-designer-decorator}/rules.js +0 -0
  29. /package/dist/tools/{page-designer-decorator → storefrontnext/page-designer-decorator}/templates/decorator-generator.d.ts +0 -0
  30. /package/dist/tools/{page-designer-decorator → storefrontnext/page-designer-decorator}/templates/decorator-generator.js +0 -0
@@ -46,13 +46,13 @@ export default class McpServerCommand extends BaseCommand<typeof McpServerComman
46
46
  lang: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
47
47
  config: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
48
48
  instance: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
49
- 'working-directory': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
49
+ 'project-directory': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
50
50
  'extra-query': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
51
51
  'extra-body': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
52
52
  'extra-headers': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
53
53
  'api-key': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
54
- project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
55
- environment: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
54
+ project: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
55
+ environment: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
56
56
  'cloud-origin': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
57
57
  'credentials-file': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
58
58
  };
@@ -78,7 +78,7 @@ export default class McpServerCommand extends BaseCommand<typeof McpServerComman
78
78
  * Priority (highest to lowest):
79
79
  * 1. CLI flags (--server, --username, --api-key, etc.)
80
80
  * 2. Environment variables (SFCC_SERVER, SFCC_USERNAME, SFCC_MRT_API_KEY, etc.)
81
- * 3. dw.json file (via --config flag or auto-discovered from --working-directory)
81
+ * 3. dw.json file (via --config flag or auto-discovered from --project-directory)
82
82
  * 4. ~/.mobify file (for MRT API key)
83
83
  */
84
84
  protected loadConfiguration(): ResolvedB2CConfig;
@@ -47,7 +47,7 @@
47
47
  * ### Global Flags (inherited from BaseCommand)
48
48
  * | Flag | Env Variable | Description |
49
49
  * |------|--------------|-------------|
50
- * | `--working-directory` | `SFCC_WORKING_DIRECTORY` | Project working directory (see note below) |
50
+ * | `--project-directory` | `SFCC_PROJECT_DIRECTORY` | Project directory (see note below) |
51
51
  * | `--config` | `SFCC_CONFIG` | Path to dw.json config file (auto-discovered if not provided) |
52
52
  * | `--instance` | `SFCC_INSTANCE` | Instance name from configuration file |
53
53
  * | `--log-level` | `SFCC_LOG_LEVEL` | Set logging verbosity (trace, debug, info, warn, error, silent) |
@@ -55,13 +55,13 @@
55
55
  * | `--json` | - | Output logs as JSON lines |
56
56
  * | `--lang` | - | Language for messages |
57
57
  *
58
- * **Note on `--working-directory`**: Many MCP clients (Cursor, Claude Desktop) spawn servers from the
58
+ * **Note on `--project-directory`**: Many MCP clients (Cursor, Claude Desktop) spawn servers from the
59
59
  * user's home directory (`~`) rather than the project directory. This flag is used for:
60
60
  * - Auto-discovery (detecting project type when no `--toolsets` or `--tools` are provided)
61
61
  * - Scaffolding tools (creating files in the correct project location)
62
62
  * - Any tool that needs to operate on the project directory
63
63
  *
64
- * Use `--working-directory` or `SFCC_WORKING_DIRECTORY` env var to specify the actual project path.
64
+ * Use `--project-directory` or `SFCC_PROJECT_DIRECTORY` env var to specify the actual project path.
65
65
  *
66
66
  * ## Configuration
67
67
  *
@@ -233,7 +233,7 @@ export default class McpServerCommand extends BaseCommand {
233
233
  * Priority (highest to lowest):
234
234
  * 1. CLI flags (--server, --username, --api-key, etc.)
235
235
  * 2. Environment variables (SFCC_SERVER, SFCC_USERNAME, SFCC_MRT_API_KEY, etc.)
236
- * 3. dw.json file (via --config flag or auto-discovered from --working-directory)
236
+ * 3. dw.json file (via --config flag or auto-discovered from --project-directory)
237
237
  * 4. ~/.mobify file (for MRT API key)
238
238
  */
239
239
  loadConfiguration() {
@@ -298,7 +298,7 @@ export default class McpServerCommand extends BaseCommand {
298
298
  allowNonGaTools: this.flags['allow-non-ga-tools'],
299
299
  configPath: this.flags.config,
300
300
  // Working directory for auto-discovery. oclif handles flag with env fallback.
301
- workingDirectory: this.flags['working-directory'],
301
+ workingDirectory: this.flags['project-directory'],
302
302
  };
303
303
  // Add toolsets to telemetry attributes
304
304
  if (this.telemetry && startupFlags.toolsets) {
package/dist/registry.js CHANGED
@@ -95,13 +95,13 @@ export function createToolRegistry(loadServices) {
95
95
  */
96
96
  async function performAutoDiscovery(flags, reason) {
97
97
  const logger = getLogger();
98
- // Working directory from --working-directory flag or SFCC_WORKING_DIRECTORY env var
98
+ // Working directory from --project-directory flag or SFCC_PROJECT_DIRECTORY env var
99
99
  const workingDirectory = flags.workingDirectory ?? process.cwd();
100
100
  // Warn if working directory wasn't explicitly configured
101
101
  if (!flags.workingDirectory) {
102
- logger.warn({ cwd: workingDirectory }, 'No --working-directory flag or SFCC_WORKING_DIRECTORY env var provided. ' +
102
+ logger.warn({ cwd: workingDirectory }, 'No --project-directory flag or SFCC_PROJECT_DIRECTORY env var provided. ' +
103
103
  'MCP clients like Cursor and Claude Desktop often spawn servers from ~ instead of the project directory. ' +
104
- 'Set --working-directory or SFCC_WORKING_DIRECTORY for reliable auto-discovery.');
104
+ 'Set --project-directory or SFCC_PROJECT_DIRECTORY for reliable auto-discovery.');
105
105
  }
106
106
  const detectionResult = await detectWorkspaceType(workingDirectory);
107
107
  // Map all detected project types to MCP toolsets (union)
@@ -23,7 +23,7 @@
23
23
  import { z } from 'zod';
24
24
  import { createToolAdapter, jsonResult } from '../adapter.js';
25
25
  import { createDeveloperGuidelinesTool } from './developer-guidelines.js';
26
- import { createPageDesignerDecoratorTool } from '../page-designer-decorator/index.js';
26
+ import { createPageDesignerDecoratorTool } from './page-designer-decorator/index.js';
27
27
  /**
28
28
  * Creates a placeholder tool for Storefront Next development.
29
29
  *
@@ -506,7 +506,7 @@ export function resolveComponent(input, workspaceRoot, searchPaths) {
506
506
  `Full path checked: ${fullPath}\n\n` +
507
507
  `Tips:\n` +
508
508
  ` 1. Use component name instead (e.g., "ProductCard") for automatic discovery\n` +
509
- ` 2. If components are in a different repo, set --working-directory flag or SFCC_WORKING_DIRECTORY env var`);
509
+ ` 2. If components are in a different repo, set --project-directory flag or SFCC_PROJECT_DIRECTORY env var`);
510
510
  }
511
511
  // Treat as component name - search for it
512
512
  const found = findComponentByName(input, workspaceRoot, searchPaths);
@@ -528,7 +528,7 @@ export function resolveComponent(input, workspaceRoot, searchPaths) {
528
528
  ` 1. Provide full path: component: "src/components/ProductCard.tsx"\n` +
529
529
  ` 2. Add custom search: searchPaths: ["packages/retail/src"]\n` +
530
530
  ` 3. Check component name spelling and casing\n` +
531
- ` 4. If components are in a different repo, set --working-directory flag or SFCC_WORKING_DIRECTORY env var`);
531
+ ` 4. If components are in a different repo, set --project-directory flag or SFCC_PROJECT_DIRECTORY env var`);
532
532
  }
533
533
  return found;
534
534
  }
@@ -1,6 +1,6 @@
1
1
  import { z } from 'zod';
2
- import type { McpTool } from '../../utils/index.js';
3
- import type { Services } from '../../services.js';
2
+ import type { McpTool } from '../../../utils/index.js';
3
+ import type { Services } from '../../../services.js';
4
4
  export declare const pageDesignerDecoratorSchema: z.ZodObject<{
5
5
  component: z.ZodString;
6
6
  searchPaths: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
@@ -303,8 +303,49 @@ function handleConfigureRegionsStep(args, workspaceRoot) {
303
303
  ],
304
304
  };
305
305
  }
306
+ function hasNonEmptyConfig(config) {
307
+ return config !== null && config !== undefined && Object.keys(config).length > 0;
308
+ }
309
+ function buildAttributesFromProps(selectedProps, props, attributeConfig) {
310
+ return selectedProps.flatMap((propName) => {
311
+ const prop = props.find((p) => p.name === propName);
312
+ if (!prop)
313
+ return [];
314
+ const config = attributeConfig[propName];
315
+ return [
316
+ {
317
+ name: propName,
318
+ tsType: prop.type,
319
+ optional: prop.optional,
320
+ hasConfig: hasNonEmptyConfig(config),
321
+ config,
322
+ },
323
+ ];
324
+ });
325
+ }
326
+ function buildAttributesFromNewAttrs(newAttributes, attributeConfig) {
327
+ return newAttributes.map((attr) => {
328
+ const config = attributeConfig[attr.name];
329
+ return {
330
+ name: attr.name,
331
+ tsType: 'string',
332
+ optional: !attr.required,
333
+ hasConfig: hasNonEmptyConfig(config),
334
+ config,
335
+ };
336
+ });
337
+ }
338
+ function resolveRegions(conversationContext) {
339
+ const regionConfig = conversationContext?.regionConfig;
340
+ const enabled = Boolean(regionConfig?.enabled && regionConfig.regions?.length);
341
+ return {
342
+ hasRegions: enabled,
343
+ regions: enabled ? regionConfig.regions : [],
344
+ regionCount: enabled ? regionConfig.regions.length : 0,
345
+ };
346
+ }
306
347
  function handleConfirmGenerationStep(args, workspaceRoot) {
307
- const { componentMetadata, selectedProps = [], newAttributes = [], attributeConfig = {}, } = args.conversationContext || {};
348
+ const { componentMetadata, selectedProps = [], newAttributes = [], attributeConfig = {}, } = args.conversationContext ?? {};
308
349
  if (!componentMetadata) {
309
350
  return {
310
351
  content: [
@@ -318,45 +359,23 @@ function handleConfirmGenerationStep(args, workspaceRoot) {
318
359
  }
319
360
  const fullPath = resolveComponent(args.component, workspaceRoot, args.searchPaths);
320
361
  const componentInfo = componentAnalyzer.analyzeComponent(fullPath);
321
- const attributes = [];
322
- for (const propName of selectedProps) {
323
- const prop = componentInfo.props.find((p) => p.name === propName);
324
- if (!prop)
325
- continue;
326
- const config = attributeConfig[propName];
327
- const hasConfig = config && Object.keys(config).length > 0;
328
- attributes.push({
329
- name: propName,
330
- tsType: prop.type,
331
- optional: prop.optional,
332
- hasConfig,
333
- config,
334
- });
335
- }
336
- for (const attr of newAttributes) {
337
- const config = attributeConfig[attr.name];
338
- const hasConfig = config && Object.keys(config).length > 0;
339
- attributes.push({
340
- name: attr.name,
341
- tsType: 'string',
342
- optional: !attr.required,
343
- hasConfig,
344
- config,
345
- });
346
- }
347
- const regionConfig = args.conversationContext?.regionConfig;
348
- const hasRegions = regionConfig?.enabled && regionConfig.regions && regionConfig.regions.length > 0;
362
+ const attributes = [
363
+ ...buildAttributesFromProps(selectedProps, componentInfo.props, attributeConfig),
364
+ ...buildAttributesFromNewAttrs(newAttributes, attributeConfig),
365
+ ];
366
+ const { hasRegions, regions, regionCount } = resolveRegions(args.conversationContext);
367
+ const componentGroup = componentMetadata.group ?? 'odyssey_base';
349
368
  const context = {
350
369
  needsImports: true,
351
370
  componentId: componentMetadata.id,
352
371
  componentName: componentMetadata.name,
353
372
  componentDescription: componentMetadata.description,
354
- componentGroup: componentMetadata.group || 'odyssey_base',
373
+ componentGroup,
355
374
  metadataClassName: `${componentInfo.componentName}Metadata`,
356
375
  hasAttributes: attributes.length > 0,
357
- hasRegions: hasRegions || false,
376
+ hasRegions,
358
377
  hasLoader: false,
359
- regions: hasRegions ? regionConfig.regions || [] : [],
378
+ regions,
360
379
  attributes,
361
380
  };
362
381
  const decoratorCode = generateDecoratorCode(context);
@@ -364,11 +383,11 @@ function handleConfirmGenerationStep(args, workspaceRoot) {
364
383
  decoratorCode,
365
384
  componentName: componentInfo.componentName,
366
385
  componentId: componentMetadata.id,
367
- componentGroup: componentMetadata.group || 'odyssey_base',
386
+ componentGroup,
368
387
  file: args.component,
369
388
  attributeCount: attributes.length,
370
- hasRegions: hasRegions || false,
371
- regionCount: hasRegions && regionConfig.regions ? regionConfig.regions.length : 0,
389
+ hasRegions,
390
+ regionCount,
372
391
  });
373
392
  return {
374
393
  content: [
@@ -99,11 +99,14 @@
99
99
  "multiple": false,
100
100
  "type": "option"
101
101
  },
102
- "working-directory": {
103
- "description": "Project working directory",
104
- "env": "SFCC_WORKING_DIRECTORY",
102
+ "project-directory": {
103
+ "aliases": [
104
+ "working-directory"
105
+ ],
106
+ "description": "Project directory",
107
+ "env": "SFCC_PROJECT_DIRECTORY",
105
108
  "helpGroup": "GLOBAL",
106
- "name": "working-directory",
109
+ "name": "project-directory",
107
110
  "hasDynamicHelp": false,
108
111
  "multiple": false,
109
112
  "type": "option"
@@ -384,5 +387,5 @@
384
387
  "enableJsonFlag": false
385
388
  }
386
389
  },
387
- "version": "0.4.0"
390
+ "version": "0.4.2"
388
391
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/b2c-dx-mcp",
3
- "version": "0.4.0",
3
+ "version": "0.4.2",
4
4
  "description": "MCP server for B2C Commerce Cloud developer experience tools",
5
5
  "author": "Salesforce",
6
6
  "license": "MIT",
@@ -79,7 +79,7 @@
79
79
  "ts-morph": "^27.0.0",
80
80
  "yaml": "2.8.1",
81
81
  "zod": "3.25.76",
82
- "@salesforce/b2c-tooling-sdk": "0.5.0"
82
+ "@salesforce/b2c-tooling-sdk": "0.5.2"
83
83
  },
84
84
  "devDependencies": {
85
85
  "@eslint/compat": "^1",