@salesforce/b2c-dx-mcp 2.0.0 → 2.1.1

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 (124) hide show
  1. package/README.md +15 -62
  2. package/dist/commands/mcp.d.ts +1 -0
  3. package/dist/commands/mcp.js +41 -9
  4. package/dist/registry.d.ts +3 -4
  5. package/dist/registry.js +7 -14
  6. package/dist/server.d.ts +1 -1
  7. package/dist/server.js +3 -1
  8. package/dist/services.d.ts +21 -1
  9. package/dist/services.js +39 -6
  10. package/dist/tools/adapter.d.ts +18 -2
  11. package/dist/tools/adapter.js +49 -10
  12. package/dist/tools/cartridges/index.js +16 -22
  13. package/dist/tools/diagnostics/config-inspect.js +4 -8
  14. package/dist/tools/diagnostics/debug-capture-at-breakpoint.js +3 -9
  15. package/dist/tools/diagnostics/debug-list-sessions.js +1 -0
  16. package/dist/tools/diagnostics/debug-start-session.js +16 -9
  17. package/dist/tools/diagnostics/debug-wait-for-stop.js +1 -3
  18. package/dist/tools/diagnostics/log-watch-registry.d.ts +3 -0
  19. package/dist/tools/diagnostics/log-watch-registry.js +1 -0
  20. package/dist/tools/diagnostics/logs-get-recent.js +2 -5
  21. package/dist/tools/diagnostics/logs-list-files.js +1 -1
  22. package/dist/tools/diagnostics/logs-watch-list.js +1 -0
  23. package/dist/tools/diagnostics/logs-watch-start.js +10 -10
  24. package/dist/tools/diagnostics/mrt-log-watch-registry.d.ts +3 -0
  25. package/dist/tools/diagnostics/mrt-log-watch-registry.js +0 -0
  26. package/dist/tools/diagnostics/mrt-logs-watch-list.js +1 -0
  27. package/dist/tools/diagnostics/mrt-logs-watch-poll.js +2 -5
  28. package/dist/tools/diagnostics/mrt-logs-watch-start.js +9 -8
  29. package/dist/tools/diagnostics/session-registry.d.ts +3 -0
  30. package/dist/tools/diagnostics/session-registry.js +2 -1
  31. package/dist/tools/docs/docs-list.js +4 -6
  32. package/dist/tools/docs/docs-read.js +2 -9
  33. package/dist/tools/docs/docs-schema-list.js +1 -1
  34. package/dist/tools/docs/docs-schema-read.js +2 -3
  35. package/dist/tools/docs/docs-schema-search.js +2 -2
  36. package/dist/tools/docs/docs-search.js +3 -9
  37. package/dist/tools/docs/storefront.js +3 -3
  38. package/dist/tools/docs/topics.js +3 -1
  39. package/dist/tools/index.d.ts +0 -1
  40. package/dist/tools/index.js +0 -1
  41. package/dist/tools/mrt/index.js +6 -2
  42. package/dist/tools/project-context.d.ts +38 -11
  43. package/dist/tools/project-context.js +32 -15
  44. package/dist/tools/pwav3/pwa-kit-development-guidelines.js +3 -43
  45. package/dist/tools/scapi/metrics-get.js +5 -23
  46. package/dist/tools/scapi/scapi-custom-api-generate-scaffold.d.ts +4 -0
  47. package/dist/tools/scapi/scapi-custom-api-generate-scaffold.js +29 -14
  48. package/dist/tools/scapi/scapi-custom-apis-get-status.js +3 -14
  49. package/dist/tools/scapi/scapi-schemas-list.js +11 -11
  50. package/dist/utils/constants.d.ts +2 -13
  51. package/dist/utils/constants.js +1 -20
  52. package/oclif.manifest.json +2 -2
  53. package/package.json +5 -5
  54. package/content/sfnext/auth.md +0 -62
  55. package/content/sfnext/components.md +0 -123
  56. package/content/sfnext/config.md +0 -180
  57. package/content/sfnext/data-fetching.md +0 -323
  58. package/content/sfnext/extensions.md +0 -80
  59. package/content/sfnext/i18n.md +0 -121
  60. package/content/sfnext/page-designer.md +0 -78
  61. package/content/sfnext/performance.md +0 -80
  62. package/content/sfnext/pitfalls.md +0 -141
  63. package/content/sfnext/quick-reference.md +0 -226
  64. package/content/sfnext/state-management.md +0 -75
  65. package/content/sfnext/styling.md +0 -51
  66. package/content/sfnext/testing.md +0 -232
  67. package/dist/tools/storefrontnext/figma/figma-to-component/figma-url-parser.d.ts +0 -24
  68. package/dist/tools/storefrontnext/figma/figma-to-component/figma-url-parser.js +0 -53
  69. package/dist/tools/storefrontnext/figma/figma-to-component/index.d.ts +0 -45
  70. package/dist/tools/storefrontnext/figma/figma-to-component/index.js +0 -332
  71. package/dist/tools/storefrontnext/figma/generate-component/decision.d.ts +0 -40
  72. package/dist/tools/storefrontnext/figma/generate-component/decision.js +0 -312
  73. package/dist/tools/storefrontnext/figma/generate-component/formatter.d.ts +0 -9
  74. package/dist/tools/storefrontnext/figma/generate-component/formatter.js +0 -92
  75. package/dist/tools/storefrontnext/figma/generate-component/index.d.ts +0 -117
  76. package/dist/tools/storefrontnext/figma/generate-component/index.js +0 -102
  77. package/dist/tools/storefrontnext/figma/map-tokens/css-parser.d.ts +0 -71
  78. package/dist/tools/storefrontnext/figma/map-tokens/css-parser.js +0 -260
  79. package/dist/tools/storefrontnext/figma/map-tokens/index.d.ts +0 -64
  80. package/dist/tools/storefrontnext/figma/map-tokens/index.js +0 -242
  81. package/dist/tools/storefrontnext/figma/map-tokens/token-matcher.d.ts +0 -65
  82. package/dist/tools/storefrontnext/figma/map-tokens/token-matcher.js +0 -268
  83. package/dist/tools/storefrontnext/index.d.ts +0 -30
  84. package/dist/tools/storefrontnext/index.js +0 -28
  85. package/dist/tools/storefrontnext/page-designer-decorator/analyzer.d.ts +0 -169
  86. package/dist/tools/storefrontnext/page-designer-decorator/analyzer.js +0 -567
  87. package/dist/tools/storefrontnext/page-designer-decorator/index.d.ts +0 -259
  88. package/dist/tools/storefrontnext/page-designer-decorator/index.js +0 -622
  89. package/dist/tools/storefrontnext/page-designer-decorator/rules/1-mode-selection.d.ts +0 -8
  90. package/dist/tools/storefrontnext/page-designer-decorator/rules/1-mode-selection.js +0 -65
  91. package/dist/tools/storefrontnext/page-designer-decorator/rules/2a-auto-mode.d.ts +0 -13
  92. package/dist/tools/storefrontnext/page-designer-decorator/rules/2a-auto-mode.js +0 -87
  93. package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-0-interactive-overview.d.ts +0 -4
  94. package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-0-interactive-overview.js +0 -55
  95. package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-1-interactive-analyze.d.ts +0 -22
  96. package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-1-interactive-analyze.js +0 -109
  97. package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-2-interactive-select-props.d.ts +0 -21
  98. package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-2-interactive-select-props.js +0 -60
  99. package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-3-interactive-configure-attrs.d.ts +0 -27
  100. package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-3-interactive-configure-attrs.js +0 -68
  101. package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-4-interactive-configure-regions.d.ts +0 -4
  102. package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-4-interactive-configure-regions.js +0 -65
  103. package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-5-interactive-confirm-generation.d.ts +0 -11
  104. package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-5-interactive-confirm-generation.js +0 -92
  105. package/dist/tools/storefrontnext/page-designer-decorator/rules.d.ts +0 -51
  106. package/dist/tools/storefrontnext/page-designer-decorator/rules.js +0 -70
  107. package/dist/tools/storefrontnext/page-designer-decorator/templates/decorator-generator.d.ts +0 -116
  108. package/dist/tools/storefrontnext/page-designer-decorator/templates/decorator-generator.js +0 -350
  109. package/dist/tools/storefrontnext/sfnext-development-guidelines.d.ts +0 -9
  110. package/dist/tools/storefrontnext/sfnext-development-guidelines.js +0 -141
  111. package/dist/tools/storefrontnext/site-theming/color-contrast.d.ts +0 -92
  112. package/dist/tools/storefrontnext/site-theming/color-contrast.js +0 -186
  113. package/dist/tools/storefrontnext/site-theming/color-mapping.d.ts +0 -16
  114. package/dist/tools/storefrontnext/site-theming/color-mapping.js +0 -131
  115. package/dist/tools/storefrontnext/site-theming/guidance-merger.d.ts +0 -11
  116. package/dist/tools/storefrontnext/site-theming/guidance-merger.js +0 -78
  117. package/dist/tools/storefrontnext/site-theming/index.d.ts +0 -14
  118. package/dist/tools/storefrontnext/site-theming/index.js +0 -128
  119. package/dist/tools/storefrontnext/site-theming/response-builder.d.ts +0 -16
  120. package/dist/tools/storefrontnext/site-theming/response-builder.js +0 -316
  121. package/dist/tools/storefrontnext/site-theming/theming-store.d.ts +0 -64
  122. package/dist/tools/storefrontnext/site-theming/theming-store.js +0 -417
  123. package/dist/tools/storefrontnext/site-theming/types.d.ts +0 -36
  124. package/dist/tools/storefrontnext/site-theming/types.js +0 -7
@@ -9,9 +9,8 @@ import { createToolAdapter, errorResult, jsonResult } from '../adapter.js';
9
9
  export function createDocsSchemaReadTool(loadServices) {
10
10
  return createToolAdapter({
11
11
  name: 'docs_schema_read',
12
- description: 'Read the contents of a bundled B2C Commerce XSD schema (raw XML). ' +
13
- 'Accepts an exact id or fuzzy query. Returns the schema body plus the on-disk path. ' +
14
- 'Schemas can be large; if you do not know the id, call docs_schema_search first.',
12
+ description: 'Read a bundled B2C Commerce (SFCC/Demandware) XSD schema as XML by ID or fuzzy query. ' +
13
+ 'Use docs_schema_search to find IDs.',
15
14
  toolsets: ['CARTRIDGES', 'DIAGNOSTICS', 'MRT', 'PWAV3', 'SCAPI', 'STOREFRONTNEXT'],
16
15
  inputSchema: {
17
16
  query: z.string().min(1).describe('Schema name or partial match.'),
@@ -9,8 +9,8 @@ import { createToolAdapter, jsonResult } from '../adapter.js';
9
9
  export function createDocsSchemaSearchTool(loadServices) {
10
10
  return createToolAdapter({
11
11
  name: 'docs_schema_search',
12
- description: 'Fuzzy-search bundled B2C Commerce XSD schemas by id (e.g., "catalog", "order", "system-objecttype"). ' +
13
- 'Returns matching schema ids + relevance score. Use BEFORE docs_schema_read when the exact id is unknown.',
12
+ description: 'Search bundled B2C Commerce (SFCC/Demandware) XSD schemas by ID. ' +
13
+ 'Returns matching IDs and scores; use docs_schema_read for content.',
14
14
  toolsets: ['CARTRIDGES', 'DIAGNOSTICS', 'MRT', 'PWAV3', 'SCAPI', 'STOREFRONTNEXT'],
15
15
  inputSchema: {
16
16
  query: z.string().min(1).describe('Schema name or partial match (e.g., "catalog", "order").'),
@@ -38,13 +38,8 @@ function leanResult(entry, score, verbose) {
38
38
  export function createDocsSearchTool(loadServices, detectedWorkspaces = [], enabledCategories) {
39
39
  return createToolAdapter({
40
40
  name: 'docs_search',
41
- description: 'PRIMARY entry point for B2C Commerce docs: Script API reference (e.g. "ProductMgr"), standard job steps, ' +
42
- 'Developer Center guides (commerce-api, pwa-kit-managed-runtime, sfnext, sfra, b2c-commerce), and this ' +
43
- "tooling's own guides. Use for ANY B2C Commerce developer or admin question not already grounded in a " +
44
- 'loaded skill or the current project. Content-aware ranking — pass a natural-language query (prefer this ' +
45
- 'over docs_list, which only enumerates). Optionally restrict by category or workspace. Returns id, title, ' +
46
- 'category, summary, and score for triage; pass verbose=true for keywords+url. Call this BEFORE docs_read ' +
47
- 'when you do not know the exact id.' +
41
+ description: 'Search B2C Commerce (SFCC/Demandware) Script API, job steps, developer guides, admin/merchant help, and tooling docs. ' +
42
+ 'Use for natural-language queries or unknown IDs; call docs_read with a result ID.' +
48
43
  enabledCategoriesNote(enabledCategories) +
49
44
  detectedWorkspaceNote(detectedWorkspaces),
50
45
  toolsets: ['CARTRIDGES', 'DIAGNOSTICS', 'MRT', 'PWAV3', 'SCAPI', 'STOREFRONTNEXT'],
@@ -54,8 +49,7 @@ export function createDocsSearchTool(loadServices, detectedWorkspaces = [], enab
54
49
  workspace: z
55
50
  .enum(WORKSPACE_VALUES)
56
51
  .optional()
57
- .describe('Workspace context. "auto" (default) favors the auto-detected workspace\'s docs; ' +
58
- '"all" disables the preference; or name a type (cartridges, sfra, pwa-kit-v3, storefront-next).'),
52
+ .describe('"auto" uses startup workspace; "all" disables weighting; or select a workspace type.'),
59
53
  limit: z
60
54
  .number()
61
55
  .int()
@@ -9,8 +9,8 @@
9
9
  */
10
10
  export const PROJECT_TYPE_LABELS = {
11
11
  cartridges: 'Cartridges',
12
- sfra: 'SFRA (cartridges)',
13
- 'pwa-kit-v3': 'PWA Kit (Composable Storefront)',
12
+ sfra: 'SFRA',
13
+ 'pwa-kit-v3': 'PWA Kit',
14
14
  'storefront-next': 'Storefront Next',
15
15
  };
16
16
  /**
@@ -43,6 +43,6 @@ export function detectedWorkspaceNote(detected) {
43
43
  if (detected.length === 0)
44
44
  return '';
45
45
  const labels = detected.map((t) => PROJECT_TYPE_LABELS[t] ?? t).join(' + ');
46
- return ` Detected workspace: ${labels} — by default results favor this workspace's docs (pass workspace="all" to disable).`;
46
+ return ` Workspace at startup: ${labels}.`;
47
47
  }
48
48
  //# sourceMappingURL=storefront.js.map
@@ -33,6 +33,8 @@ export function categoryEnumValues(enabledCategories) {
33
33
  export function enabledCategoriesNote(enabledCategories) {
34
34
  if (!enabledCategories || enabledCategories.length === 0)
35
35
  return '';
36
- return ` Documentation is restricted at startup to: ${enabledCategories.join(', ')}.`;
36
+ if (DOC_CATEGORIES.every((category) => enabledCategories.includes(category)))
37
+ return '';
38
+ return ` Topics: ${enabledCategories.join(', ')}.`;
37
39
  }
38
40
  //# sourceMappingURL=topics.js.map
@@ -14,4 +14,3 @@ export * from './docs/index.js';
14
14
  export * from './mrt/index.js';
15
15
  export * from './pwav3/index.js';
16
16
  export * from './scapi/index.js';
17
- export * from './storefrontnext/index.js';
@@ -21,5 +21,4 @@ export * from './docs/index.js';
21
21
  export * from './mrt/index.js';
22
22
  export * from './pwav3/index.js';
23
23
  export * from './scapi/index.js';
24
- export * from './storefrontnext/index.js';
25
24
  //# sourceMappingURL=index.js.map
@@ -137,11 +137,11 @@ function createMrtBundlePushTool(loadServices, injections) {
137
137
  ssrOnly: z
138
138
  .string()
139
139
  .optional()
140
- .describe('Glob patterns for server-only files (comma-separated or JSON array). Defaults vary by project type: Storefront Next, PWA Kit v3, or generic.'),
140
+ .describe('Server-only globs; comma-separated or JSON array. Defaults by project type.'),
141
141
  ssrShared: z
142
142
  .string()
143
143
  .optional()
144
- .describe('Glob patterns for shared files (comma-separated or JSON array). Defaults vary by project type: Storefront Next, PWA Kit v3, or generic.'),
144
+ .describe('Shared-file globs; comma-separated or JSON array. Defaults by project type.'),
145
145
  deploy: z
146
146
  .boolean()
147
147
  .optional()
@@ -175,6 +175,10 @@ function createMrtBundlePushTool(loadServices, injections) {
175
175
  const ssrOnly = args.ssrOnly ? parseGlobPatterns(args.ssrOnly) : defaults.ssrOnly;
176
176
  const ssrShared = args.ssrShared ? parseGlobPatterns(args.ssrShared) : defaults.ssrShared;
177
177
  const buildDirectory = context.services.resolveWithProjectDirectory(args.buildDirectory ?? defaults.buildDirectory, args.projectDirectory);
178
+ context.setResolvedDirectory('buildDirectory', {
179
+ path: buildDirectory,
180
+ source: args.buildDirectory ? 'argument' : 'projectDirectory',
181
+ });
178
182
  // Log all computed variables before pushing bundle
179
183
  const logger = getLogger();
180
184
  logger.debug({
@@ -1,22 +1,49 @@
1
- import { z } from 'zod';
1
+ import { z, type ZodRawShape } from 'zod';
2
2
  /** Input shared by MCP tools that resolve files or configuration from a project. */
3
3
  export interface ProjectContextInput {
4
4
  /** Per-call project directory override. */
5
5
  projectDirectory?: string;
6
- /** Per-call explicit dw.json-format configuration path. */
6
+ /** Per-call explicit primary dw.json-format configuration path. */
7
7
  configPath?: string;
8
+ /** Per-call named instance selection. */
9
+ instanceName?: string;
8
10
  }
9
11
  /** Effective project directory and the source that selected it. */
10
12
  export interface ProjectDirectoryInfo {
11
13
  path: string;
12
14
  source: 'argument' | 'config' | 'cwd';
13
15
  }
14
- /** Shared schema field injected into every project-aware MCP tool. */
15
- export declare const projectDirectoryInput: z.ZodOptional<z.ZodString>;
16
- /** Shared explicit dw.json path field injected into every project-aware MCP tool. */
17
- export declare const configPathInput: z.ZodOptional<z.ZodString>;
18
- /** Shared schema fields injected into every project-aware MCP tool. */
19
- export declare const projectContextInputSchema: {
20
- projectDirectory: z.ZodOptional<z.ZodString>;
21
- configPath: z.ZodOptional<z.ZodString>;
22
- };
16
+ /** How the selected dw.json file entered the configuration resolver. */
17
+ export type ConfigurationResolutionSource = 'argument' | 'globalDefault' | 'none' | 'projectDirectory' | 'projectEnvironment' | 'server';
18
+ /** Compact selected-configuration provenance returned by project-aware tools. */
19
+ export interface ConfigurationResolutionInfo {
20
+ hostname?: string;
21
+ instanceName?: string;
22
+ path?: string;
23
+ source: ConfigurationResolutionSource;
24
+ }
25
+ /** Provenance for a specialized project-relative directory. */
26
+ export interface DirectoryResolutionInfo {
27
+ path: string;
28
+ source: 'argument' | 'projectDirectory';
29
+ }
30
+ /** Compact, common provenance block returned by project/config-aware tools. */
31
+ export interface ToolResolution {
32
+ configuration?: ConfigurationResolutionInfo;
33
+ directories?: Record<string, DirectoryResolutionInfo>;
34
+ projectDirectory: ProjectDirectoryInfo;
35
+ }
36
+ /** Whether a tool needs only a project root or full configuration selection. */
37
+ export type ProjectContextKind = 'configuration' | 'project';
38
+ /** Build the canonical project-directory field. */
39
+ export declare function createProjectDirectoryInput(): z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>;
40
+ /** Build the canonical explicit primary dw.json field. */
41
+ export declare function createConfigPathInput(): z.ZodOptional<z.ZodString>;
42
+ /** Build the canonical named-instance selection field. */
43
+ export declare function createInstanceNameInput(): z.ZodOptional<z.ZodString>;
44
+ /** Build flat canonical schema fields for a local-project or configuration-aware tool. */
45
+ export declare function createProjectContextInputSchema(kind: ProjectContextKind): ZodRawShape;
46
+ /** Static field for schemas declared outside the shared adapter. */
47
+ export declare const projectDirectoryInput: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>;
48
+ /** Static configuration schema for legacy/manual tool definitions. */
49
+ export declare const projectContextInputSchema: z.ZodRawShape;
@@ -3,20 +3,37 @@
3
3
  * SPDX-License-Identifier: Apache-2
4
4
  * For full license text, see the license.txt file in the repo root or http://www.apache.org/licenses/LICENSE-2.0
5
5
  */
6
+ import path from 'node:path';
6
7
  import { z } from 'zod';
7
- /** Shared schema field injected into every project-aware MCP tool. */
8
- export const projectDirectoryInput = z
9
- .string()
10
- .optional()
11
- .describe('Absolute project directory for this call. Overrides --project-directory / SFCC_PROJECT_DIRECTORY and the MCP process working directory. Also controls project-local configuration discovery.');
12
- /** Shared explicit dw.json path field injected into every project-aware MCP tool. */
13
- export const configPathInput = z
14
- .string()
15
- .optional()
16
- .describe('Explicit path to a dw.json-format configuration file for this call. Overrides startup --config / SFCC_CONFIG and project .env SFCC_CONFIG. Relative paths resolve from projectDirectory.');
17
- /** Shared schema fields injected into every project-aware MCP tool. */
18
- export const projectContextInputSchema = {
19
- projectDirectory: projectDirectoryInput,
20
- configPath: configPathInput,
21
- };
8
+ /** Build the canonical project-directory field. */
9
+ export function createProjectDirectoryInput() {
10
+ return z
11
+ .string()
12
+ .refine((value) => path.isAbsolute(value), 'projectDirectory must be an absolute path')
13
+ .optional()
14
+ .describe('Absolute project root; overrides server default. See config_inspect for resolved paths.');
15
+ }
16
+ /** Build the canonical explicit primary dw.json field. */
17
+ export function createConfigPathInput() {
18
+ return z.string().optional().describe('Path to dw.json-format config; relative to projectDirectory.');
19
+ }
20
+ /** Build the canonical named-instance selection field. */
21
+ export function createInstanceNameInput() {
22
+ return z.string().min(1).optional().describe('Named instance from dw.json.');
23
+ }
24
+ /** Build flat canonical schema fields for a local-project or configuration-aware tool. */
25
+ export function createProjectContextInputSchema(kind) {
26
+ const project = { projectDirectory: createProjectDirectoryInput() };
27
+ if (kind === 'project')
28
+ return project;
29
+ return {
30
+ ...project,
31
+ configPath: createConfigPathInput(),
32
+ instanceName: createInstanceNameInput(),
33
+ };
34
+ }
35
+ /** Static field for schemas declared outside the shared adapter. */
36
+ export const projectDirectoryInput = createProjectDirectoryInput();
37
+ /** Static configuration schema for legacy/manual tool definitions. */
38
+ export const projectContextInputSchema = createProjectContextInputSchema('configuration');
22
39
  //# sourceMappingURL=project-context.js.map
@@ -61,16 +61,6 @@ const SECTIONS_METADATA = [
61
61
  * Derived: array of section keys for validation.
62
62
  */
63
63
  const _SECTIONS = SECTIONS_METADATA.map((s) => s.key);
64
- /**
65
- * Generates the topics list for the tool description.
66
- * Excludes meta-sections (like quick-reference) that don't have descriptions.
67
- * @returns Comma-separated list of topics
68
- */
69
- function generateTopicsList() {
70
- return SECTIONS_METADATA.filter((s) => s.description !== null)
71
- .map((s) => s.description)
72
- .join(', ');
73
- }
74
64
  /**
75
65
  * Detailed section content loaded from markdown files.
76
66
  * Built dynamically from SECTIONS_METADATA to avoid duplication.
@@ -96,12 +86,7 @@ const DEFAULT_SECTIONS = ['quick-reference', 'components', 'data-fetching', 'rou
96
86
  export function createDeveloperGuidelinesTool(loadServices) {
97
87
  return createToolAdapter({
98
88
  name: 'pwakit_get_guidelines',
99
- description: 'ESSENTIAL FIRST STEP for PWA Kit v3 development. Returns critical architecture rules, coding standards, and best practices. ' +
100
- 'Use this tool FIRST before writing any PWA Kit code to understand non-negotiable patterns for React components, ' +
101
- 'data fetching, routing, configuration, and framework constraints. Returns comprehensive guidelines by default (quick-reference + key sections); ' +
102
- 'supports retrieving specific topic sections. ' +
103
- 'CRITICAL INSTRUCTION: ALWAYS present ALL returned content in FULL - DO NOT SUMMARIZE, DO NOT ADD SUMMARIES, ' +
104
- 'DO NOT ADD OVERVIEWS. The returned content IS the complete answer - display it exactly as provided.',
89
+ description: 'Get PWA Kit v3 architecture and implementation guidelines. Returns core sections by default; use sections to narrow the result.',
105
90
  toolsets: ['PWAV3'],
106
91
  isGA: true,
107
92
  requiresInstance: false,
@@ -109,13 +94,7 @@ export function createDeveloperGuidelinesTool(loadServices) {
109
94
  sections: z
110
95
  .array(z.enum([..._SECTIONS]))
111
96
  .optional()
112
- .describe('Optional array of specific sections to retrieve. If not specified, returns comprehensive guidelines ' +
113
- '(quick-reference, components, data-fetching, routing). ' +
114
- 'CRITICAL: Present ALL returned content in FULL - DO NOT SUMMARIZE. ' +
115
- 'Available sections: quick-reference, components, data-fetching, routing, config, state-management, ' +
116
- 'extensibility, testing, i18n, styling. ' +
117
- `Topics covered: ${generateTopicsList()}. ` +
118
- 'Content is complete - present exactly as provided, no summaries.'),
97
+ .describe('Guideline sections to return; defaults to core sections.'),
119
98
  },
120
99
  async execute(args) {
121
100
  // Handle empty array case explicitly
@@ -124,26 +103,7 @@ export function createDeveloperGuidelinesTool(loadServices) {
124
103
  }
125
104
  // Default to comprehensive set of key sections if no sections specified
126
105
  const sections = args.sections || DEFAULT_SECTIONS;
127
- // Multiple sections: combine with separators
128
- const combinedContent = sections.map((section) => SECTION_CONTENT[section]).join('\n\n---\n\n');
129
- // Apply instructions for all multi-section responses to ensure full content display
130
- const isMultiSection = sections.length > 1;
131
- // Prepend explicit instruction to present full content (not summarized)
132
- const fullContentInstruction = isMultiSection
133
- ? '⚠️ CRITICAL: Display the FULL content below. DO NOT summarize, condense, or add overviews.\n\n' +
134
- '📋 PWA KIT DEVELOPMENT GUIDELINES\n\n' +
135
- '---\n\n'
136
- : '';
137
- // Add footer instruction to reinforce the message for multi-section responses
138
- const footerInstruction = isMultiSection
139
- ? '\n\n---\n\n⚠️ END OF CONTENT - Full content displayed above. Do not add summaries.\n'
140
- : '';
141
- // For single sections, return directly (backward compatible)
142
- // For multiple sections, wrap with instructions
143
- if (sections.length === 1) {
144
- return SECTION_CONTENT[sections[0]];
145
- }
146
- return fullContentInstruction + combinedContent + footerInstruction;
106
+ return sections.map((section) => SECTION_CONTENT[section]).join('\n\n---\n\n');
147
107
  },
148
108
  formatOutput: (output) => textResult(output),
149
109
  }, loadServices);
@@ -40,34 +40,16 @@ import { getMetricsByCategory, resolveMetricsWindow, enrichMetricsTags, } from '
40
40
  export function createMetricsGetTool(loadServices) {
41
41
  return createToolAdapter({
42
42
  name: 'metrics_get',
43
- description: `CLOSED BETA: the Metrics API must be enabled for your organization, and its behavior, output, and OAuth scopes may change without notice.
44
-
45
- Retrieve observability metrics time-series for a B2C Commerce tenant. Returns metrics data grouped by category with time-series data points.
46
-
47
- **Categories:**
48
- - overall: Aggregate site metrics (requests, response times, errors)
49
- - sales: Sales and order metrics
50
- - ecdn: Edge CDN performance metrics
51
- - third-party: External service metrics (use thirdPartyServiceId filter)
52
- - scapi: SCAPI endpoint metrics (use apiFamily/apiName filters)
53
- - scapi-hooks: SCAPI hooks execution metrics
54
- - mrt: Managed Runtime (PWA Kit) metrics
55
- - controller: Controller execution metrics
56
- - ocapi: OCAPI endpoint metrics (use ocapiCategory/ocapiApi filters)
57
-
58
- **Time window:** Provide "from" and/or "to" as a relative duration ("1h", "7d" — interpreted as ago) or an ISO 8601 timestamp, and/or "window" as a duration ("1h", "30m"). The tool always sends an explicit from+to range, defaulting to a 24-hour window: from + window → to = from + window; to + window → from = to - window; window alone → the last <window>; from alone → 24h forward from it (capped at now); to alone → 24h back from it; nothing → the last 24h. Do not supply from, to, and window together. The API caps a window at 24h and retains 30 days; an explicit range wider than 24h is sent as-is and the API returns a clear error.
59
-
60
- **Response:** { query, data } — "query" echoes the resolved from/to (ISO + epoch seconds), filters, and defaultedWindow/clampedFrom flags; "data[]" contains metricId, title, description, unit, and dataSeries[] with time-series points (timestamp in epoch milliseconds, value). Each series also carries a structured "tags" object (realm, environment, any applied filters, and per-series dimensions like apiFamily/host/cacheStatus) parsed client-side from the packed series id — use these to group/filter rather than parsing the series id string.
61
-
62
- **Requirements:** OAuth with sfcc.metrics scope.`,
43
+ description: 'CLOSED BETA. Retrieve B2C observability metric time series by category and time range. ' +
44
+ 'Defaults to the last 24 hours. Requires Metrics API access and OAuth scope sfcc.metrics.',
63
45
  toolsets: ['SCAPI'],
64
46
  isGA: false,
65
47
  requiresInstance: false, // SCAPI uses OAuth directly
66
- usesProjectContext: true,
48
+ usesConfigurationContext: true,
67
49
  inputSchema: {
68
50
  category: z
69
51
  .enum(['overall', 'sales', 'ecdn', 'third-party', 'scapi', 'scapi-hooks', 'mrt', 'controller', 'ocapi'])
70
- .describe('Metrics category: overall (aggregate), sales, ecdn (CDN), third-party (external), scapi (SCAPI APIs), scapi-hooks, mrt (PWA Kit), controller, ocapi'),
52
+ .describe('Metrics category.'),
71
53
  from: z
72
54
  .string()
73
55
  .optional()
@@ -79,7 +61,7 @@ Retrieve observability metrics time-series for a B2C Commerce tenant. Returns me
79
61
  window: z
80
62
  .string()
81
63
  .optional()
82
- .describe('Window duration ("1h", "30m", "2d"). With from to=from+window; with to → from=to-window; alone the last <window>. Defaults to 24h.'),
64
+ .describe('Duration combined with from or to; alone selects the latest window. Default: 24h.'),
83
65
  thirdPartyServiceId: z
84
66
  .string()
85
67
  .optional()
@@ -23,8 +23,12 @@ interface ScaffoldCustomApiInput extends ProjectContextInput {
23
23
  /** Short description of the API. Default: "A custom B2C Commerce API" */
24
24
  apiDescription?: string;
25
25
  /** Project root for cartridge discovery and output. Default: MCP project directory */
26
+ cartridgeDirectory?: string;
27
+ /** @deprecated Use cartridgeDirectory. */
26
28
  projectRoot?: string;
27
29
  /** Output directory override. Default: scaffold default or project root */
30
+ outputDirectory?: string;
31
+ /** @deprecated Use outputDirectory. */
28
32
  outputDir?: string;
29
33
  }
30
34
  /**
@@ -22,7 +22,7 @@ const CUSTOM_API_SCAFFOLD_ID = 'custom-api';
22
22
  */
23
23
  export async function executeScaffoldCustomApi(args, services, overrides) {
24
24
  const projectDirectory = services.resolveProjectDirectory(args.projectDirectory);
25
- const projectRoot = services.resolveWithProjectDirectory(args.projectRoot, args.projectDirectory);
25
+ const projectRoot = services.resolveWithProjectDirectory(args.cartridgeDirectory ?? args.projectRoot, args.projectDirectory);
26
26
  const getScaffold = overrides?.getScaffold ??
27
27
  (async (id, opts) => {
28
28
  const registry = createScaffoldRegistry();
@@ -96,7 +96,7 @@ export async function executeScaffoldCustomApi(args, services, overrides) {
96
96
  };
97
97
  }
98
98
  const outputDir = resolveOutputDirectory({
99
- outputDir: args.outputDir,
99
+ outputDir: args.outputDirectory ?? args.outputDir,
100
100
  scaffold,
101
101
  projectRoot,
102
102
  });
@@ -147,36 +147,51 @@ export async function executeScaffoldCustomApi(args, services, overrides) {
147
147
  export function createScaffoldCustomApiTool(loadServices, executeOverrides) {
148
148
  return createToolAdapter({
149
149
  name: 'scapi_custom_api_generate_scaffold',
150
- description: `Generate a new custom SCAPI endpoint (OAS 3.0 schema, api.json, script.js) in an existing cartridge. \
151
- Required: apiName (kebab-case). Optional: cartridgeName (defaults to first cartridge found in project), apiType (shopper|admin) default to shopper, \
152
- apiDescription, projectRoot, outputDir.`,
150
+ description: 'Generate a custom SCAPI endpoint scaffold in an existing cartridge: OpenAPI schema, api.json, and script.js. apiName must be kebab-case.',
153
151
  toolsets: ['PWAV3', 'SCAPI', 'STOREFRONTNEXT'],
154
152
  isGA: true,
155
153
  requiresInstance: false,
156
154
  usesProjectContext: true,
157
155
  inputSchema: {
158
- apiName: z
159
- .string()
160
- .min(1)
161
- .describe('API name in kebab-case (e.g. my-products). Must start with lowercase letter, only letters, numbers, hyphens.'),
156
+ apiName: z.string().min(1).describe('Kebab-case API name starting with a lowercase letter.'),
162
157
  cartridgeName: z
163
158
  .string()
164
159
  .min(1)
165
160
  .nullish()
166
- .describe('Cartridge name that will contain the API. Optional; omit to use the first cartridge found under project root).'),
161
+ .describe('Target cartridge; defaults to the first discovered cartridge.'),
167
162
  apiType: z
168
163
  .enum(['admin', 'shopper'])
169
164
  .optional()
170
165
  .describe('Admin (no siteId) or shopper (siteId, customer-facing). Default: shopper'),
171
166
  apiDescription: z.string().optional().describe('Short description of the API.'),
167
+ cartridgeDirectory: z
168
+ .string()
169
+ .nullish()
170
+ .describe('Optional cartridge discovery root, resolved relative to projectDirectory. Defaults to projectDirectory.'),
172
171
  projectRoot: z
173
172
  .string()
174
173
  .nullish()
175
- .describe('Optional cartridge discovery/output root, resolved relative to projectDirectory. Defaults to projectDirectory.'),
176
- outputDir: z.string().optional().describe('Output directory override. Default: project root'),
174
+ .describe('Deprecated alias for cartridgeDirectory. cartridgeDirectory takes precedence.'),
175
+ outputDirectory: z
176
+ .string()
177
+ .optional()
178
+ .describe('Optional output directory. Relative paths resolve from cartridgeDirectory.'),
179
+ outputDir: z
180
+ .string()
181
+ .optional()
182
+ .describe('Deprecated alias for outputDirectory. outputDirectory takes precedence.'),
177
183
  },
178
- async execute(args, { services }) {
179
- return executeScaffoldCustomApi(args, services, executeOverrides);
184
+ async execute(args, context) {
185
+ const output = await executeScaffoldCustomApi(args, context.services, executeOverrides);
186
+ context.setResolvedDirectory('cartridgeDirectory', {
187
+ path: output.projectRoot,
188
+ source: args.cartridgeDirectory || args.projectRoot ? 'argument' : 'projectDirectory',
189
+ });
190
+ context.setResolvedDirectory('outputDirectory', {
191
+ path: output.outputDir,
192
+ source: args.outputDirectory || args.outputDir ? 'argument' : 'projectDirectory',
193
+ });
194
+ return output;
180
195
  },
181
196
  formatOutput(output) {
182
197
  if (output.error) {
@@ -82,26 +82,15 @@ function buildResponse(withMeta, args, columnList, activeCodeVersion) {
82
82
  export function createScapiCustomApisStatusTool(loadServices) {
83
83
  return createToolAdapter({
84
84
  name: 'scapi_custom_apis_get_status',
85
- description: `List Custom SCAPI endpoint registration status (active/not_registered). Returns one row per endpoint per site. For schemas, use scapi_schemas_list with apiFamily: "custom".
86
-
87
- Use cases: Check endpoint status, verify deployment, get per-site details. Use status: "active" to filter, groupBy: "site" to group, columns: "field1,field2" for specific fields, or omit columns for defaults.
88
-
89
- Output: Default (7 fields): type,apiName,cartridgeName,endpointPath,httpMethod,status,siteId. All fields: type,apiName,apiVersion,cartridgeName,endpointPath,httpMethod,status,siteId,securityScheme,operationId,schemaFile,implementationScript,errorReason,id.
90
-
91
- Requires OAuth (sfcc.custom-apis scope) and instance config (shortCode, tenantId). Returns remoteError on failure.
92
-
93
- CLI: b2c scapi custom status`,
85
+ description: 'List Custom SCAPI endpoint registration status per site. Supports filtering, grouping, and selected columns. Requires shortCode, tenantId, and sfcc.custom-apis scope. Use scapi_schemas_list for schemas.',
94
86
  toolsets: ['PWAV3', 'SCAPI', 'STOREFRONTNEXT'],
95
87
  isGA: true,
96
88
  requiresInstance: false,
97
- usesProjectContext: true,
89
+ usesConfigurationContext: true,
98
90
  inputSchema: {
99
91
  status: z.enum(['active', 'not_registered']).optional().describe('Filter by status. Omit for all.'),
100
92
  groupBy: z.enum(['site', 'type']).optional().describe('Group by siteId or type (Admin/Shopper).'),
101
- columns: z
102
- .string()
103
- .optional()
104
- .describe('Comma-separated fields. Omit for defaults (7 fields). All fields: type,apiName,apiVersion,cartridgeName,endpointPath,httpMethod,status,siteId,securityScheme,operationId,schemaFile,implementationScript,errorReason,id'),
93
+ columns: z.string().optional().describe('Comma-separated output fields; omit for defaults.'),
105
94
  },
106
95
  async execute(args, { services: svc }) {
107
96
  let endpoints = [];
@@ -37,6 +37,13 @@ import { collapseOpenApiSchema } from '@salesforce/b2c-tooling-sdk/schemas';
37
37
  function buildScapiApiUrl(shortCode, apiFamily, apiName, apiVersion) {
38
38
  return `https://${shortCode}.api.commercecloud.salesforce.com/${apiFamily}/${apiName}/${apiVersion}`;
39
39
  }
40
+ function getSchemasApiError(error, response) {
41
+ const message = getApiErrorMessage(error, response);
42
+ if (response.status === 401 || response.status === 403) {
43
+ return `${message}. Verify OAuth credentials include the sfcc.scapi-schemas scope.`;
44
+ }
45
+ return message;
46
+ }
40
47
  /**
41
48
  * Fetches a specific schema from the SCAPI Schemas API.
42
49
  *
@@ -60,7 +67,7 @@ async function fetchSpecificSchema(params) {
60
67
  },
61
68
  });
62
69
  if (error) {
63
- throw new Error(`Failed to fetch schema for ${apiFamily}/${apiName}/${apiVersion}: ${getApiErrorMessage(error, response)}`);
70
+ throw new Error(`Failed to fetch schema for ${apiFamily}/${apiName}/${apiVersion}: ${getSchemasApiError(error, response)}`);
64
71
  }
65
72
  // Apply collapsing unless expandAll is requested
66
73
  const collapsed = !expandAll;
@@ -106,7 +113,7 @@ async function fetchSchemasList(params) {
106
113
  },
107
114
  });
108
115
  if (error) {
109
- throw new Error(`Failed to fetch SCAPI schemas: ${getApiErrorMessage(error, response)}`);
116
+ throw new Error(`Failed to fetch SCAPI schemas: ${getSchemasApiError(error, response)}`);
110
117
  }
111
118
  const schemas = data?.data ?? [];
112
119
  const filteredSchemas = prepareSchemaListForConsumer(schemas, shortCode);
@@ -187,18 +194,11 @@ function getAvailableFilters(schemas) {
187
194
  export function createScapiSchemasListTool(loadServices) {
188
195
  return createToolAdapter({
189
196
  name: 'scapi_schemas_list',
190
- description: `List or fetch SCAPI schema metadata and OpenAPI specs for standard SCAPI (Shop/Admin/Shopper) and custom APIs (apiFamily: "custom"). For endpoint registration status, use scapi_custom_apis_get_status.
191
-
192
- **Modes:**
193
- - **List (discovery):** Omit includeSchemas or any identifier. Returns metadata: schemas[], total, availableApiFamilies/Names/Versions.
194
- - **Fetch:** Set includeSchemas=true + all three: apiFamily, apiName, apiVersion. Returns full OpenAPI schema (collapsed by default; set expandAll=true for full).
195
-
196
- **Rules:** includeSchemas requires all three identifiers. status only works in list mode (use "current" for active schemas, "deprecated" for phased-out schemas). Custom APIs use apiFamily: "custom".
197
-
198
- **Requirements:** OAuth with sfcc.scapi-schemas scope.`,
197
+ description: 'List SCAPI schema metadata or fetch an OpenAPI schema. Fetch requires includeSchemas, apiFamily, apiName, and apiVersion. Use scapi_custom_apis_get_status for endpoint status.',
199
198
  toolsets: ['PWAV3', 'SCAPI', 'STOREFRONTNEXT'],
200
199
  isGA: true,
201
200
  requiresInstance: false, // SCAPI uses OAuth directly, doesn't need B2CInstance (hostname)
201
+ usesConfigurationContext: true,
202
202
  inputSchema: {
203
203
  apiFamily: z.string().optional().describe('API family (e.g., "checkout", "product", "custom").'),
204
204
  apiName: z.string().optional().describe('API name (e.g., "shopper-baskets", "shopper-products").'),
@@ -5,22 +5,11 @@ export declare const ALL_TOOLSETS = "ALL";
5
5
  /**
6
6
  * Available toolsets that can be enabled.
7
7
  */
8
- export declare const TOOLSETS: readonly ["CARTRIDGES", "DIAGNOSTICS", "MRT", "PWAV3", "SCAPI", "STOREFRONTNEXT", "STOREFRONTNEXT_DEPRECATED"];
9
- /**
10
- * Deprecated toolsets. These can only be enabled by explicitly naming them via
11
- * `--toolsets`; they are never auto-activated by project detection and are NOT
12
- * included when `--toolsets ALL` is used.
13
- *
14
- * `STOREFRONTNEXT_DEPRECATED` holds the legacy `sfnext_*` MCP tools. They are
15
- * superseded by the `storefront-next` and `storefront-next-figma` agent-skills
16
- * plugins and are not compatible with the Storefront Next 1.0 GA release. They
17
- * will be removed in a future release.
18
- */
19
- export declare const DEPRECATED_TOOLSETS: readonly ["STOREFRONTNEXT_DEPRECATED"];
8
+ export declare const TOOLSETS: readonly ["CARTRIDGES", "DIAGNOSTICS", "MRT", "PWAV3", "SCAPI", "STOREFRONTNEXT"];
20
9
  /**
21
10
  * Valid toolset names including the special "ALL" value.
22
11
  */
23
- export declare const VALID_TOOLSET_NAMES: readonly ["ALL", "CARTRIDGES", "DIAGNOSTICS", "MRT", "PWAV3", "SCAPI", "STOREFRONTNEXT", "STOREFRONTNEXT_DEPRECATED"];
12
+ export declare const VALID_TOOLSET_NAMES: readonly ["ALL", "CARTRIDGES", "DIAGNOSTICS", "MRT", "PWAV3", "SCAPI", "STOREFRONTNEXT"];
24
13
  /**
25
14
  * Type representing a valid toolset name.
26
15
  */
@@ -10,26 +10,7 @@ export const ALL_TOOLSETS = 'ALL';
10
10
  /**
11
11
  * Available toolsets that can be enabled.
12
12
  */
13
- export const TOOLSETS = [
14
- 'CARTRIDGES',
15
- 'DIAGNOSTICS',
16
- 'MRT',
17
- 'PWAV3',
18
- 'SCAPI',
19
- 'STOREFRONTNEXT',
20
- 'STOREFRONTNEXT_DEPRECATED',
21
- ];
22
- /**
23
- * Deprecated toolsets. These can only be enabled by explicitly naming them via
24
- * `--toolsets`; they are never auto-activated by project detection and are NOT
25
- * included when `--toolsets ALL` is used.
26
- *
27
- * `STOREFRONTNEXT_DEPRECATED` holds the legacy `sfnext_*` MCP tools. They are
28
- * superseded by the `storefront-next` and `storefront-next-figma` agent-skills
29
- * plugins and are not compatible with the Storefront Next 1.0 GA release. They
30
- * will be removed in a future release.
31
- */
32
- export const DEPRECATED_TOOLSETS = ['STOREFRONTNEXT_DEPRECATED'];
13
+ export const TOOLSETS = ['CARTRIDGES', 'DIAGNOSTICS', 'MRT', 'PWAV3', 'SCAPI', 'STOREFRONTNEXT'];
33
14
  /**
34
15
  * Valid toolset names including the special "ALL" value.
35
16
  */
@@ -388,7 +388,7 @@
388
388
  "type": "boolean"
389
389
  },
390
390
  "toolsets": {
391
- "description": "Toolsets to enable (comma-separated). Options: all, CARTRIDGES, DIAGNOSTICS, MRT, PWAV3, SCAPI, STOREFRONTNEXT, STOREFRONTNEXT_DEPRECATED",
391
+ "description": "Toolsets to enable (comma-separated). Options: all, CARTRIDGES, DIAGNOSTICS, MRT, PWAV3, SCAPI, STOREFRONTNEXT",
392
392
  "env": "SFCC_TOOLSETS",
393
393
  "name": "toolsets",
394
394
  "hasDynamicHelp": false,
@@ -429,5 +429,5 @@
429
429
  "enableJsonFlag": false
430
430
  }
431
431
  },
432
- "version": "2.0.0"
432
+ "version": "2.1.1"
433
433
  }