@salesforce/b2c-dx-mcp 0.3.2 → 0.4.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 (54) hide show
  1. package/README.md +47 -27
  2. package/content/page-designer.md +4 -4
  3. package/dist/commands/mcp.d.ts +12 -0
  4. package/dist/commands/mcp.js +16 -4
  5. package/dist/registry.d.ts +4 -4
  6. package/dist/registry.js +10 -10
  7. package/dist/services.d.ts +75 -1
  8. package/dist/services.js +124 -1
  9. package/dist/tools/adapter.d.ts +29 -21
  10. package/dist/tools/adapter.js +34 -24
  11. package/dist/tools/cartridges/index.d.ts +5 -3
  12. package/dist/tools/cartridges/index.js +55 -25
  13. package/dist/tools/index.d.ts +1 -0
  14. package/dist/tools/index.js +1 -0
  15. package/dist/tools/mrt/index.d.ts +2 -2
  16. package/dist/tools/mrt/index.js +29 -10
  17. package/dist/tools/page-designer-decorator/analyzer.d.ts +169 -0
  18. package/dist/tools/page-designer-decorator/analyzer.js +535 -0
  19. package/dist/tools/page-designer-decorator/index.d.ts +252 -0
  20. package/dist/tools/page-designer-decorator/index.js +597 -0
  21. package/dist/tools/page-designer-decorator/rules/1-mode-selection.d.ts +8 -0
  22. package/dist/tools/page-designer-decorator/rules/1-mode-selection.js +65 -0
  23. package/dist/tools/page-designer-decorator/rules/2a-auto-mode.d.ts +13 -0
  24. package/dist/tools/page-designer-decorator/rules/2a-auto-mode.js +87 -0
  25. package/dist/tools/page-designer-decorator/rules/2b-0-interactive-overview.d.ts +4 -0
  26. package/dist/tools/page-designer-decorator/rules/2b-0-interactive-overview.js +55 -0
  27. package/dist/tools/page-designer-decorator/rules/2b-1-interactive-analyze.d.ts +22 -0
  28. package/dist/tools/page-designer-decorator/rules/2b-1-interactive-analyze.js +109 -0
  29. package/dist/tools/page-designer-decorator/rules/2b-2-interactive-select-props.d.ts +21 -0
  30. package/dist/tools/page-designer-decorator/rules/2b-2-interactive-select-props.js +60 -0
  31. package/dist/tools/page-designer-decorator/rules/2b-3-interactive-configure-attrs.d.ts +27 -0
  32. package/dist/tools/page-designer-decorator/rules/2b-3-interactive-configure-attrs.js +68 -0
  33. package/dist/tools/page-designer-decorator/rules/2b-4-interactive-configure-regions.d.ts +4 -0
  34. package/dist/tools/page-designer-decorator/rules/2b-4-interactive-configure-regions.js +65 -0
  35. package/dist/tools/page-designer-decorator/rules/2b-5-interactive-confirm-generation.d.ts +11 -0
  36. package/dist/tools/page-designer-decorator/rules/2b-5-interactive-confirm-generation.js +92 -0
  37. package/dist/tools/page-designer-decorator/rules.d.ts +51 -0
  38. package/dist/tools/page-designer-decorator/rules.js +70 -0
  39. package/dist/tools/page-designer-decorator/templates/decorator-generator.d.ts +116 -0
  40. package/dist/tools/page-designer-decorator/templates/decorator-generator.js +350 -0
  41. package/dist/tools/pwav3/index.d.ts +2 -2
  42. package/dist/tools/pwav3/index.js +13 -13
  43. package/dist/tools/scapi/index.d.ts +10 -2
  44. package/dist/tools/scapi/index.js +5 -56
  45. package/dist/tools/scapi/scapi-custom-apis-status.d.ts +9 -0
  46. package/dist/tools/scapi/scapi-custom-apis-status.js +152 -0
  47. package/dist/tools/scapi/scapi-schemas-list.d.ts +12 -0
  48. package/dist/tools/scapi/scapi-schemas-list.js +248 -0
  49. package/dist/tools/storefrontnext/developer-guidelines.d.ts +2 -2
  50. package/dist/tools/storefrontnext/developer-guidelines.js +3 -3
  51. package/dist/tools/storefrontnext/index.d.ts +2 -2
  52. package/dist/tools/storefrontnext/index.js +13 -13
  53. package/oclif.manifest.json +13 -2
  54. package/package.json +10 -5
package/README.md CHANGED
@@ -22,16 +22,14 @@ The most important flag is **`--working-directory`** (or env var `SFCC_WORKING_D
22
22
 
23
23
  > **Important:** MCP clients like Cursor and Claude Desktop spawn servers from the home directory (`~`), not your project. Always set `--working-directory`.
24
24
 
25
- <!-- TODO: Update command to use npx once published to npm -->
26
-
27
25
  **Cursor** (supports `${workspaceFolder}`):
28
26
 
29
27
  ```json
30
28
  {
31
29
  "mcpServers": {
32
30
  "b2c-dx": {
33
- "command": "node",
34
- "args": ["/path/to/packages/b2c-dx-mcp/bin/dev.js", "--working-directory", "${workspaceFolder}", "--allow-non-ga-tools"]
31
+ "command": "npx",
32
+ "args": ["-y", "@salesforce/b2c-dx-mcp", "--working-directory", "${workspaceFolder}", "--allow-non-ga-tools"]
35
33
  }
36
34
  }
37
35
  }
@@ -43,8 +41,8 @@ The most important flag is **`--working-directory`** (or env var `SFCC_WORKING_D
43
41
  {
44
42
  "mcpServers": {
45
43
  "b2c-dx": {
46
- "command": "node",
47
- "args": ["/path/to/packages/b2c-dx-mcp/bin/dev.js", "--working-directory", "/path/to/your/project", "--allow-non-ga-tools"]
44
+ "command": "npx",
45
+ "args": ["-y", "@salesforce/b2c-dx-mcp", "--working-directory", "/path/to/your/project", "--allow-non-ga-tools"]
48
46
  }
49
47
  }
50
48
  }
@@ -57,7 +55,7 @@ The server analyzes your working directory and enables toolsets based on what it
57
55
  | Project Type | Detection | Toolsets Enabled |
58
56
  |--------------|-----------|------------------|
59
57
  | **PWA Kit v3** | `@salesforce/pwa-kit-*`, `@salesforce/retail-react-app`, or `ccExtensibility` in package.json | PWAV3, MRT, SCAPI |
60
- | **Storefront Next** | `@salesforce/storefront-next-*` in package.json | STOREFRONTNEXT, MRT, SCAPI |
58
+ | **Storefront Next** | Root or a workspace package has `@salesforce/storefront-next*` dependency, or package name starting with `storefront-next`. | STOREFRONTNEXT, MRT, CARTRIDGES, SCAPI |
61
59
  | **Cartridges** | `.project` file in cartridge directory | CARTRIDGES, SCAPI |
62
60
  | **No project detected** | No B2C markers found | SCAPI (base toolset only) |
63
61
 
@@ -120,15 +118,38 @@ The `storefront_next_development_guidelines` tool provides critical architecture
120
118
  - ✅ "I'm starting a new PWA Kit project. Use the MCP tool to get the development guidelines."
121
119
  - ✅ "Use the MCP tool to create a new product listing page component in my PWA Kit project."
122
120
  - ✅ "Use the MCP tool to recommend React hooks for fetching product data in PWA Kit."
123
- - ✅ "Use the MCP tool to explore the SCAPI Shop API endpoints available for my PWA Kit storefront."
124
121
 
125
122
  ##### SCAPI Discovery
126
123
 
127
- **Good prompts:**
128
- - ✅ "Use the MCP tool to discover what SCAPI endpoints are available for product data."
129
- - "Use the MCP tool to discover custom SCAPI APIs in my B2C instance."
130
- - ✅ "Use the MCP tool to show me all available SCAPI endpoints and their capabilities."
131
- - "Use the MCP tool to scaffold a new custom SCAPI API for order management."
124
+ Use **scapi_schemas_list** for both standard SCAPI (Shop, Admin, Shopper APIs) and custom APIs. Use **scapi_custom_apis_status** for endpoint-level registration status (active/not_registered).
125
+
126
+ **SCAPI Schemas (tool: `scapi_schemas_list`):**
127
+
128
+ Discover schema metadata and fetch OpenAPI specs for both standard and custom SCAPI:
129
+
130
+ **Standard SCAPI:**
131
+ - ✅ "Use the MCP tool to list all available SCAPI schemas." → list mode (no includeSchemas).
132
+ - ✅ "Use the MCP tool to show me what checkout APIs exist." → list with apiFamily: checkout.
133
+ - ✅ "Use the MCP tool to discover SCAPI product endpoints." → list with apiFamily: product.
134
+ - ✅ "Use the MCP tool to get the OpenAPI schema for shopper-baskets v1." → fetch with apiFamily, apiName, apiVersion, includeSchemas: true.
135
+ - ✅ "Use the MCP tool to show me the full OpenAPI spec for shopper-products v1." → fetch with includeSchemas: true, expandAll: true.
136
+
137
+ **Custom APIs (use apiFamily: "custom"):**
138
+ - ✅ "Use the MCP tool to list custom API definitions." → list with apiFamily: custom.
139
+ - ✅ "Use the MCP tool to show me the loyalty-points custom API schema." → apiFamily: custom, apiName: loyalty-points, apiVersion: v1, includeSchemas: true.
140
+
141
+ **Custom API Endpoint Status (tool: `scapi_custom_apis_status`):**
142
+
143
+ Get registration status of custom API endpoints deployed on the instance (remote only). Returns individual HTTP endpoints (e.g., GET /hello, POST /items/{id}) with registration status (active/not_registered), one row per endpoint per site. Requires OAuth with `sfcc.custom-apis` scope.
144
+
145
+ - ✅ "Use the MCP tool to list custom SCAPI endpoints on my instance."
146
+ - ✅ "Use the MCP tool to show which custom APIs are active vs not registered."
147
+ - ✅ "Use the MCP tool to list custom API endpoints grouped by site." → groupBy: site
148
+ - ✅ "Use the MCP tool to list custom API endpoints grouped by type." → groupBy: type
149
+ - ✅ "Use the MCP tool to list only active custom API endpoints." → status: active
150
+ - ✅ "Use the MCP tool to find custom API endpoints that failed to register." → status: not_registered
151
+ - ✅ "Use the MCP tool to show endpoint details with all fields." → extended: true
152
+ - ✅ "Use the MCP tool to show only apiName and status for active endpoints." → status: active, columns: "apiName,status"
132
153
 
133
154
  ##### Cartridge Deployment
134
155
 
@@ -142,7 +163,7 @@ The `storefront_next_development_guidelines` tool provides critical architecture
142
163
  **Good prompts:**
143
164
  - ✅ "Use the MCP tool to build and push my Storefront Next bundle to staging."
144
165
  - ✅ "Use the MCP tool to push the bundle from ./build directory to Managed Runtime."
145
- - ✅ "Use the MCP tool to deploy my PWA Kit bundle to production with a deployment message."
166
+ - ✅ "Use the MCP tool to deploy my PWA Kit or Storefront Next bundle to production with a deployment message."
146
167
 
147
168
  #### Tips for Better Results
148
169
 
@@ -157,7 +178,7 @@ Credentials can be provided via **config files** (recommended), **environment va
157
178
 
158
179
  | Toolset | Required Credentials |
159
180
  |---------|---------------------|
160
- | **SCAPI** | `hostname` + `client-id` + `client-secret` |
181
+ | **SCAPI** | `hostname` + `client-id` + `client-secret` (for `scapi_custom_apis_status`: requires `sfcc.custom-apis` scope) |
161
182
  | **CARTRIDGES** | `hostname` + `username` + `password` (or OAuth) |
162
183
  | **MRT** | `api-key` + `project` (optionally `environment`) |
163
184
  | **PWAV3** | `--working-directory` only (+ MRT config for deployments) |
@@ -264,20 +285,19 @@ PWA Kit v3 development tools for building headless storefronts.
264
285
  | `pwakit_recommend_hooks` | Recommend appropriate React hooks for PWA Kit use cases |
265
286
  | `pwakit_run_site_test` | Run site tests for PWA Kit project |
266
287
  | `pwakit_install_agent_rules` | Install AI agent rules for PWA Kit development |
267
- | `pwakit_explore_scapi_shop_api` | Explore SCAPI Shop API endpoints and capabilities |
268
- | `scapi_discovery` | Discover available SCAPI endpoints and capabilities |
269
- | `scapi_custom_api_discovery` | Discover custom SCAPI API endpoints |
288
+ | `scapi_schemas_list` | List or fetch SCAPI schemas (standard and custom). Use apiFamily: "custom" for custom APIs. |
289
+ | `scapi_custom_apis_status` | Get registration status of custom API endpoints (active/not_registered). Remote only, requires OAuth. |
270
290
  | `mrt_bundle_push` | Build, push bundle (optionally deploy) |
271
291
 
272
292
  #### SCAPI
273
293
  Salesforce Commerce API discovery and exploration.
274
- - **Status:** 🚧 Placeholder
294
+ - **Status:** 🚧 Early Access
275
295
 
276
296
  | Tool | Description |
277
297
  |------|-------------|
278
- | `scapi_discovery` | Discover available SCAPI endpoints and capabilities |
279
- | `scapi_customapi_scaffold` | Scaffold a new custom SCAPI API |
280
- | `scapi_custom_api_discovery` | Discover custom SCAPI API endpoints |
298
+ | `scapi_schemas_list` | List or fetch SCAPI schemas (standard and custom). Use apiFamily: "custom" for custom APIs. |
299
+ | `scapi_custom_apis_status` | Get registration status of custom API endpoints (active/not_registered). Remote only, requires OAuth. |
300
+ | `scapi_customapi_scaffold` | Scaffold a new custom SCAPI API (not yet implemented) |
281
301
 
282
302
  #### STOREFRONTNEXT
283
303
  Storefront Next development tools for building modern storefronts.
@@ -290,13 +310,13 @@ Storefront Next development tools for building modern storefronts.
290
310
  | `storefront_next_figma_to_component_workflow` | Convert Figma designs to Storefront Next components |
291
311
  | `storefront_next_generate_component` | Generate a new Storefront Next component |
292
312
  | `storefront_next_map_tokens_to_theme` | Map design tokens to Storefront Next theme configuration |
293
- | `storefront_next_design_decorator` | Apply design decorators to Storefront Next components |
313
+ | `storefront_next_page_designer_decorator` | Add Page Designer decorators to Storefront Next components |
294
314
  | `storefront_next_generate_page_designer_metadata` | Generate Page Designer metadata for Storefront Next components |
295
- | `scapi_discovery` | Discover available SCAPI endpoints and capabilities |
296
- | `scapi_custom_api_discovery` | Discover custom SCAPI API endpoints |
315
+ | `scapi_schemas_list` | List or fetch SCAPI schemas (standard and custom). Use apiFamily: "custom" for custom APIs. |
316
+ | `scapi_custom_apis_status` | Get registration status of custom API endpoints (active/not_registered). Remote only, requires OAuth. |
297
317
  | `mrt_bundle_push` | Build, push bundle (optionally deploy) |
298
318
 
299
- > **Note:** Some tools appear in multiple toolsets (e.g., `mrt_bundle_push`, `scapi_discovery`). When using multiple toolsets, tools are automatically deduplicated.
319
+ > **Note:** Some tools appear in multiple toolsets (e.g., `mrt_bundle_push`, `scapi_schemas_list`, `scapi_custom_apis_status`). When using multiple toolsets, tools are automatically deduplicated.
300
320
 
301
321
  ## Telemetry
302
322
 
@@ -393,7 +413,7 @@ npx mcp-inspector --cli node bin/dev.js --toolsets all --allow-non-ga-tools --me
393
413
  # Call a specific tool
394
414
  npx mcp-inspector --cli node bin/dev.js --toolsets all --allow-non-ga-tools \
395
415
  --method tools/call \
396
- --tool-name storefront_next_design_decorator
416
+ --tool-name storefront_next_page_designer_decorator
397
417
  ```
398
418
 
399
419
  #### 2. IDE Integration
@@ -35,7 +35,7 @@ To add a new content page: define a page type and ID in Commerce Cloud, then in
35
35
 
36
36
  - **Add a metadata class** with `@Component('typeId', { name, description })` and `@AttributeDefinition()` (and optionally `@AttributeDefinition({ type: 'image' })`, `type: 'url'`, etc.) for each prop you want editable in Page Designer. Use `@RegionDefinition([...])` if the component has nested regions (e.g. a grid with slots).
37
37
  - **Implement the React component** so it accepts those props (and strips Page Designer–only props like `component`, `page`, `componentData`, `designMetadata` before spreading to the DOM). If the component needs server data (e.g. products for a carousel), export a `loader({ componentData, context })` and optionally a `fallback` component; the registry calls the loader during `collectComponentDataPromises` and passes resolved data as the `data` prop.
38
- - **Use the MCP tool `storefront_next_design_decorator`** to generate decorators instead of writing them by hand. Example components: `components/hero/index.tsx`, `components/content-card/index.tsx`, `components/product-carousel/index.tsx`.
38
+ - **Use the MCP tool `storefront_next_page_designer_decorator`** to generate decorators instead of writing them by hand. Example components: `components/hero/index.tsx`, `components/content-card/index.tsx`, `components/product-carousel/index.tsx`.
39
39
 
40
40
  ### After changes
41
41
 
@@ -50,7 +50,7 @@ To add a new content page: define a page type and ID in Commerce Cloud, then in
50
50
 
51
51
  Use the **B2C DX MCP server** for Page Designer work instead of hand-writing decorators and metadata. Configure the B2C DX MCP server in your IDE (e.g. in MCP settings) so these tools are available.
52
52
 
53
- ### 1. `storefront_next_design_decorator` (STOREFRONTNEXT toolset)
53
+ ### 1. `storefront_next_page_designer_decorator` (STOREFRONTNEXT toolset)
54
54
 
55
55
  Adds Page Designer decorators to an existing React component so it can be used in Business Manager. The tool analyzes the component, picks suitable props, infers types (e.g. `*Url`/`*Link` → url, `*Image` → image, `is*`/`show*` → boolean), and generates `@Component('typeId', { name, description })`, `@AttributeDefinition()` on a metadata class, and optionally `@RegionDefinition([...])` for nested regions. It skips complex or UI-only props (e.g. className, style, callbacks).
56
56
 
@@ -71,7 +71,7 @@ Packages the cartridge, uploads it to Commerce Cloud via WebDAV, and unpacks it
71
71
 
72
72
  ### Typical workflow
73
73
 
74
- 1. **`storefront_next_design_decorator`** — Add decorators to the component (use autoMode for a quick first pass).
74
+ 1. **`storefront_next_page_designer_decorator`** — Add decorators to the component (use autoMode for a quick first pass).
75
75
  2. **`storefront_next_generate_page_designer_metadata`** — Generate metadata JSON so the component and regions appear in Page Designer.
76
76
  3. **`cartridge_deploy`** — Deploy to Commerce Cloud so merchants can use the component in Business Manager.
77
77
 
@@ -81,6 +81,6 @@ Packages the cartridge, uploads it to Commerce Cloud via WebDAV, and unpacks it
81
81
  2. **Use registry for components**: Register all Page Designer components with proper `typeId`
82
82
  3. **Handle design mode**: Adapt UI when `pageDesignerMode` is `'EDIT'` or `'PREVIEW'`
83
83
  4. **Rebuild after registry changes**: Static registry is generated at build time
84
- 5. **Use MCP tools**: Leverage `storefront_next_design_decorator` and `storefront_next_generate_page_designer_metadata` for faster development
84
+ 5. **Use MCP tools**: Leverage `storefront_next_page_designer_decorator` and `storefront_next_generate_page_designer_metadata` for faster development
85
85
 
86
86
  **Reference:** See README.md for complete Page Designer documentation and MCP tool setup.
@@ -1,5 +1,6 @@
1
1
  import { BaseCommand } from '@salesforce/b2c-tooling-sdk/cli';
2
2
  import type { ResolvedB2CConfig } from '@salesforce/b2c-tooling-sdk/config';
3
+ import { Services } from '../services.js';
3
4
  /**
4
5
  * oclif Command that starts the B2C DX MCP server.
5
6
  *
@@ -41,6 +42,7 @@ export default class McpServerCommand extends BaseCommand<typeof McpServerComman
41
42
  'log-level': import("@oclif/core/interfaces").OptionFlag<"trace" | "debug" | "info" | "warn" | "error" | "silent" | undefined, import("@oclif/core/interfaces").CustomOptions>;
42
43
  debug: import("@oclif/core/interfaces").BooleanFlag<boolean>;
43
44
  json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
45
+ jsonl: import("@oclif/core/interfaces").BooleanFlag<boolean>;
44
46
  lang: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
45
47
  config: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
46
48
  instance: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
@@ -80,6 +82,16 @@ export default class McpServerCommand extends BaseCommand<typeof McpServerComman
80
82
  * 4. ~/.mobify file (for MRT API key)
81
83
  */
82
84
  protected loadConfiguration(): ResolvedB2CConfig;
85
+ /**
86
+ * Loads configuration and creates a new Services instance.
87
+ *
88
+ * This method loads configuration files (dw.json, ~/.mobify) on each call,
89
+ * allowing tools to pick up changes to configuration between invocations.
90
+ * Flags remain the same (parsed once at startup).
91
+ *
92
+ * @returns A new Services instance with loaded configuration
93
+ */
94
+ protected loadServices(): Services;
83
95
  /**
84
96
  * Main entry point - starts the MCP server.
85
97
  *
@@ -249,6 +249,19 @@ export default class McpServerCommand extends BaseCommand {
249
249
  };
250
250
  return loadConfig(flagConfig, options);
251
251
  }
252
+ /**
253
+ * Loads configuration and creates a new Services instance.
254
+ *
255
+ * This method loads configuration files (dw.json, ~/.mobify) on each call,
256
+ * allowing tools to pick up changes to configuration between invocations.
257
+ * Flags remain the same (parsed once at startup).
258
+ *
259
+ * @returns A new Services instance with loaded configuration
260
+ */
261
+ loadServices() {
262
+ const config = this.loadConfiguration();
263
+ return Services.fromResolvedConfig(config);
264
+ }
252
265
  /**
253
266
  * Main entry point - starts the MCP server.
254
267
  *
@@ -302,10 +315,9 @@ export default class McpServerCommand extends BaseCommand {
302
315
  },
303
316
  telemetry: this.telemetry,
304
317
  });
305
- // Create services from already-resolved config (BaseCommand.init() already resolved it)
306
- const services = Services.fromResolvedConfig(this.resolvedConfig);
307
- // Register toolsets
308
- await registerToolsets(startupFlags, server, services);
318
+ // Register toolsets with loader function that loads config and creates Services on each tool call
319
+ // This allows tools to pick up changes to config files (dw.json, ~/.mobify) between invocations
320
+ await registerToolsets(startupFlags, server, this.loadServices.bind(this));
309
321
  // Connect to stdio transport
310
322
  const transport = new StdioServerTransport();
311
323
  await server.connect(transport);
@@ -11,10 +11,10 @@ export type ToolRegistry = Record<Toolset, McpTool[]>;
11
11
  * Tools are organized by their declared `toolsets` array, allowing
12
12
  * a single tool to appear in multiple toolsets.
13
13
  *
14
- * @param services - Services instance for dependency injection
14
+ * @param loadServices - Function that loads configuration and returns Services instance
15
15
  * @returns Complete tool registry
16
16
  */
17
- export declare function createToolRegistry(services: Services): ToolRegistry;
17
+ export declare function createToolRegistry(loadServices: () => Services): ToolRegistry;
18
18
  /**
19
19
  * Register tools with the MCP server based on startup flags.
20
20
  *
@@ -32,6 +32,6 @@ export declare function createToolRegistry(services: Services): ToolRegistry;
32
32
  *
33
33
  * @param flags - Startup flags from CLI
34
34
  * @param server - B2CDxMcpServer instance
35
- * @param services - Services instance
35
+ * @param loadServices - Function that loads configuration and returns Services instance
36
36
  */
37
- export declare function registerToolsets(flags: StartupFlags, server: B2CDxMcpServer, services: Services): Promise<void>;
37
+ export declare function registerToolsets(flags: StartupFlags, server: B2CDxMcpServer, loadServices: () => Services): Promise<void>;
package/dist/registry.js CHANGED
@@ -58,10 +58,10 @@ function getToolsetsForProjectTypes(projectTypes) {
58
58
  * Tools are organized by their declared `toolsets` array, allowing
59
59
  * a single tool to appear in multiple toolsets.
60
60
  *
61
- * @param services - Services instance for dependency injection
61
+ * @param loadServices - Function that loads configuration and returns Services instance
62
62
  * @returns Complete tool registry
63
63
  */
64
- export function createToolRegistry(services) {
64
+ export function createToolRegistry(loadServices) {
65
65
  const registry = {
66
66
  CARTRIDGES: [],
67
67
  MRT: [],
@@ -71,11 +71,11 @@ export function createToolRegistry(services) {
71
71
  };
72
72
  // Collect all tools from all factories
73
73
  const allTools = [
74
- ...createCartridgesTools(services),
75
- ...createMrtTools(services),
76
- ...createPwav3Tools(services),
77
- ...createScapiTools(services),
78
- ...createStorefrontNextTools(services),
74
+ ...createCartridgesTools(loadServices),
75
+ ...createMrtTools(loadServices),
76
+ ...createPwav3Tools(loadServices),
77
+ ...createScapiTools(loadServices),
78
+ ...createStorefrontNextTools(loadServices),
79
79
  ];
80
80
  // Organize tools by their declared toolsets (supports multi-toolset)
81
81
  for (const tool of allTools) {
@@ -132,15 +132,15 @@ async function performAutoDiscovery(flags, reason) {
132
132
  *
133
133
  * @param flags - Startup flags from CLI
134
134
  * @param server - B2CDxMcpServer instance
135
- * @param services - Services instance
135
+ * @param loadServices - Function that loads configuration and returns Services instance
136
136
  */
137
- export async function registerToolsets(flags, server, services) {
137
+ export async function registerToolsets(flags, server, loadServices) {
138
138
  const toolsets = flags.toolsets ?? [];
139
139
  const individualTools = flags.tools ?? [];
140
140
  const allowNonGaTools = flags.allowNonGaTools ?? false;
141
141
  const logger = getLogger();
142
142
  // Create the tool registry (all available tools)
143
- const toolRegistry = createToolRegistry(services);
143
+ const toolRegistry = createToolRegistry(loadServices);
144
144
  // Build flat list of all tools for lookup
145
145
  const allTools = Object.values(toolRegistry).flat();
146
146
  const allToolsByName = new Map(allTools.map((tool) => [tool.name, tool]));
@@ -40,6 +40,7 @@ import fs from 'node:fs';
40
40
  import type { B2CInstance } from '@salesforce/b2c-tooling-sdk';
41
41
  import type { AuthStrategy } from '@salesforce/b2c-tooling-sdk/auth';
42
42
  import type { ResolvedB2CConfig } from '@salesforce/b2c-tooling-sdk/config';
43
+ import { WebDavClient, type CustomApisClient, type ScapiSchemasClient } from '@salesforce/b2c-tooling-sdk/clients';
43
44
  /**
44
45
  * MRT (Managed Runtime) configuration.
45
46
  * Groups auth, project, environment, and origin settings.
@@ -62,6 +63,8 @@ export interface ServicesOptions {
62
63
  b2cInstance?: B2CInstance;
63
64
  /** Pre-resolved MRT configuration (auth, project, environment) */
64
65
  mrtConfig?: MrtConfig;
66
+ /** Resolved configuration for access to SCAPI settings */
67
+ resolvedConfig: ResolvedB2CConfig;
65
68
  }
66
69
  /**
67
70
  * Services class that provides utilities for MCP tools.
@@ -92,7 +95,13 @@ export declare class Services {
92
95
  * Resolved once at server startup from MrtCommand flags and ~/.mobify.
93
96
  */
94
97
  readonly mrtConfig: MrtConfig;
95
- constructor(opts?: ServicesOptions);
98
+ /**
99
+ * Resolved configuration for accessing SCAPI settings.
100
+ * Provides access to shortCode, tenantId, and OAuth credentials.
101
+ * @private
102
+ */
103
+ private readonly resolvedConfig;
104
+ constructor(opts: ServicesOptions);
96
105
  /**
97
106
  * Creates a Services instance from an already-resolved configuration.
98
107
  *
@@ -113,6 +122,14 @@ export declare class Services {
113
122
  * @returns True if exists, false otherwise
114
123
  */
115
124
  exists(targetPath: string): boolean;
125
+ /**
126
+ * Get Custom APIs client for managing custom SCAPI endpoints.
127
+ * Requires shortCode, tenantId, and OAuth credentials to be configured.
128
+ *
129
+ * @throws Error if shortCode, tenantId, or OAuth credentials are missing
130
+ * @returns Typed Custom APIs client
131
+ */
132
+ getCustomApisClient(): CustomApisClient;
116
133
  /**
117
134
  * Get the current working directory.
118
135
  */
@@ -121,14 +138,62 @@ export declare class Services {
121
138
  * Get the user's home directory.
122
139
  */
123
140
  getHomeDir(): string;
141
+ /**
142
+ * Get organization ID for SCAPI API calls.
143
+ * Ensures the tenant ID has the required f_ecom_ prefix.
144
+ *
145
+ * @throws Error if tenantId is not configured
146
+ * @returns Organization ID with f_ecom_ prefix
147
+ */
148
+ getOrganizationId(): string;
124
149
  /**
125
150
  * Get OS platform information.
126
151
  */
127
152
  getPlatform(): NodeJS.Platform;
153
+ /**
154
+ * Get SCAPI Schemas client for discovering available SCAPI APIs.
155
+ * Requires shortCode, tenantId, and OAuth credentials to be configured.
156
+ *
157
+ * @throws Error if shortCode, tenantId, or OAuth credentials are missing
158
+ * @returns Typed SCAPI Schemas client
159
+ */
160
+ getScapiSchemasClient(): ScapiSchemasClient;
161
+ /**
162
+ * Get SCAPI shortCode from configuration.
163
+ * Returns undefined if not configured.
164
+ *
165
+ * @returns shortCode or undefined
166
+ */
167
+ getShortCode(): string | undefined;
168
+ /**
169
+ * Get tenant ID from configuration.
170
+ * Returns undefined if not configured.
171
+ *
172
+ * @returns tenantId or undefined
173
+ */
174
+ getTenantId(): string | undefined;
128
175
  /**
129
176
  * Get system temporary directory.
130
177
  */
131
178
  getTmpDir(): string;
179
+ /**
180
+ * Get WebDAV client for file operations on B2C instances.
181
+ * Requires hostname and WebDAV credentials to be configured.
182
+ *
183
+ * @throws Error if hostname or B2C instance is missing
184
+ * @returns WebDAV client instance
185
+ */
186
+ getWebDavClient(): WebDavClient;
187
+ /**
188
+ * Get the project working directory.
189
+ * Falls back to process.cwd() if not explicitly set.
190
+ *
191
+ * This is the directory where the project is located, which may differ from process.cwd()
192
+ * when MCP clients spawn servers from a different location (e.g., home directory).
193
+ *
194
+ * @returns Project working directory path
195
+ */
196
+ getWorkingDirectory(): string;
132
197
  /**
133
198
  * Join path segments.
134
199
  *
@@ -165,4 +230,13 @@ export declare class Services {
165
230
  * @returns File stats object
166
231
  */
167
232
  stat(targetPath: string): fs.Stats;
233
+ /**
234
+ * Get OAuth strategy from resolved configuration.
235
+ * Mirrors the pattern from OAuthCommand.getOAuthStrategy().
236
+ *
237
+ * @throws Error if OAuth credentials are not configured
238
+ * @returns OAuth auth strategy
239
+ * @private
240
+ */
241
+ private getOAuthStrategy;
168
242
  }
package/dist/services.js CHANGED
@@ -44,6 +44,7 @@
44
44
  import fs from 'node:fs';
45
45
  import path from 'node:path';
46
46
  import os from 'node:os';
47
+ import { createCustomApisClient, createScapiSchemasClient, toOrganizationId, WebDavClient, } from '@salesforce/b2c-tooling-sdk/clients';
47
48
  /**
48
49
  * Services class that provides utilities for MCP tools.
49
50
  *
@@ -73,9 +74,16 @@ export class Services {
73
74
  * Resolved once at server startup from MrtCommand flags and ~/.mobify.
74
75
  */
75
76
  mrtConfig;
76
- constructor(opts = {}) {
77
+ /**
78
+ * Resolved configuration for accessing SCAPI settings.
79
+ * Provides access to shortCode, tenantId, and OAuth credentials.
80
+ * @private
81
+ */
82
+ resolvedConfig;
83
+ constructor(opts) {
77
84
  this.b2cInstance = opts.b2cInstance;
78
85
  this.mrtConfig = opts.mrtConfig ?? {};
86
+ this.resolvedConfig = opts.resolvedConfig;
79
87
  }
80
88
  /**
81
89
  * Creates a Services instance from an already-resolved configuration.
@@ -102,6 +110,7 @@ export class Services {
102
110
  return new Services({
103
111
  b2cInstance,
104
112
  mrtConfig,
113
+ resolvedConfig: config,
105
114
  });
106
115
  }
107
116
  // ============================================
@@ -117,6 +126,25 @@ export class Services {
117
126
  exists(targetPath) {
118
127
  return fs.existsSync(targetPath);
119
128
  }
129
+ /**
130
+ * Get Custom APIs client for managing custom SCAPI endpoints.
131
+ * Requires shortCode, tenantId, and OAuth credentials to be configured.
132
+ *
133
+ * @throws Error if shortCode, tenantId, or OAuth credentials are missing
134
+ * @returns Typed Custom APIs client
135
+ */
136
+ getCustomApisClient() {
137
+ const { shortCode, tenantId } = this.resolvedConfig.values;
138
+ if (!shortCode) {
139
+ throw new Error('SCAPI short code required. Provide --short-code, set SFCC_SHORTCODE, or configure short-code in dw.json.');
140
+ }
141
+ if (!tenantId) {
142
+ throw new Error('Tenant ID required. Provide --tenant-id, set SFCC_TENANT_ID, or configure tenant-id in dw.json.');
143
+ }
144
+ // This will throw if OAuth credentials are missing
145
+ const oauthStrategy = this.getOAuthStrategy();
146
+ return createCustomApisClient({ shortCode, tenantId }, oauthStrategy);
147
+ }
120
148
  /**
121
149
  * Get the current working directory.
122
150
  */
@@ -129,18 +157,94 @@ export class Services {
129
157
  getHomeDir() {
130
158
  return os.homedir();
131
159
  }
160
+ /**
161
+ * Get organization ID for SCAPI API calls.
162
+ * Ensures the tenant ID has the required f_ecom_ prefix.
163
+ *
164
+ * @throws Error if tenantId is not configured
165
+ * @returns Organization ID with f_ecom_ prefix
166
+ */
167
+ getOrganizationId() {
168
+ const { tenantId } = this.resolvedConfig.values;
169
+ if (!tenantId) {
170
+ throw new Error('Tenant ID required. Provide --tenant-id, set SFCC_TENANT_ID, or configure tenant-id in dw.json.');
171
+ }
172
+ return toOrganizationId(tenantId);
173
+ }
132
174
  /**
133
175
  * Get OS platform information.
134
176
  */
135
177
  getPlatform() {
136
178
  return os.platform();
137
179
  }
180
+ /**
181
+ * Get SCAPI Schemas client for discovering available SCAPI APIs.
182
+ * Requires shortCode, tenantId, and OAuth credentials to be configured.
183
+ *
184
+ * @throws Error if shortCode, tenantId, or OAuth credentials are missing
185
+ * @returns Typed SCAPI Schemas client
186
+ */
187
+ getScapiSchemasClient() {
188
+ const { shortCode, tenantId } = this.resolvedConfig.values;
189
+ if (!shortCode) {
190
+ throw new Error('SCAPI short code required. Provide --short-code, set SFCC_SHORTCODE, or configure short-code in dw.json.');
191
+ }
192
+ if (!tenantId) {
193
+ throw new Error('Tenant ID required. Provide --tenant-id, set SFCC_TENANT_ID, or configure tenant-id in dw.json.');
194
+ }
195
+ // This will throw if OAuth credentials are missing
196
+ const oauthStrategy = this.getOAuthStrategy();
197
+ return createScapiSchemasClient({ shortCode, tenantId }, oauthStrategy);
198
+ }
199
+ /**
200
+ * Get SCAPI shortCode from configuration.
201
+ * Returns undefined if not configured.
202
+ *
203
+ * @returns shortCode or undefined
204
+ */
205
+ getShortCode() {
206
+ return this.resolvedConfig.values.shortCode;
207
+ }
208
+ /**
209
+ * Get tenant ID from configuration.
210
+ * Returns undefined if not configured.
211
+ *
212
+ * @returns tenantId or undefined
213
+ */
214
+ getTenantId() {
215
+ return this.resolvedConfig.values.tenantId;
216
+ }
138
217
  /**
139
218
  * Get system temporary directory.
140
219
  */
141
220
  getTmpDir() {
142
221
  return os.tmpdir();
143
222
  }
223
+ /**
224
+ * Get WebDAV client for file operations on B2C instances.
225
+ * Requires hostname and WebDAV credentials to be configured.
226
+ *
227
+ * @throws Error if hostname or B2C instance is missing
228
+ * @returns WebDAV client instance
229
+ */
230
+ getWebDavClient() {
231
+ if (!this.b2cInstance) {
232
+ throw new Error('B2C instance required for WebDAV operations. Configure hostname and authentication in dw.json.');
233
+ }
234
+ return this.b2cInstance.webdav;
235
+ }
236
+ /**
237
+ * Get the project working directory.
238
+ * Falls back to process.cwd() if not explicitly set.
239
+ *
240
+ * This is the directory where the project is located, which may differ from process.cwd()
241
+ * when MCP clients spawn servers from a different location (e.g., home directory).
242
+ *
243
+ * @returns Project working directory path
244
+ */
245
+ getWorkingDirectory() {
246
+ return this.resolvedConfig.values.workingDirectory ?? process.cwd();
247
+ }
144
248
  /**
145
249
  * Join path segments.
146
250
  *
@@ -159,6 +263,9 @@ export class Services {
159
263
  listDirectory(dirPath) {
160
264
  return fs.readdirSync(dirPath, { withFileTypes: true });
161
265
  }
266
+ // ============================================
267
+ // SCAPI Helper Methods
268
+ // ============================================
162
269
  /**
163
270
  * Read a file from the filesystem.
164
271
  *
@@ -187,5 +294,21 @@ export class Services {
187
294
  stat(targetPath) {
188
295
  return fs.statSync(targetPath);
189
296
  }
297
+ /**
298
+ * Get OAuth strategy from resolved configuration.
299
+ * Mirrors the pattern from OAuthCommand.getOAuthStrategy().
300
+ *
301
+ * @throws Error if OAuth credentials are not configured
302
+ * @returns OAuth auth strategy
303
+ * @private
304
+ */
305
+ getOAuthStrategy() {
306
+ if (!this.resolvedConfig.hasOAuthConfig()) {
307
+ throw new Error('OAuth client ID required. Provide --client-id, set SFCC_CLIENT_ID, or configure in dw.json.');
308
+ }
309
+ // Use resolvedConfig factory to create OAuth strategy
310
+ // This handles client-credentials vs implicit flow automatically
311
+ return this.resolvedConfig.createOAuth();
312
+ }
190
313
  }
191
314
  //# sourceMappingURL=services.js.map