@salesforce/b2c-dx-mcp 0.3.2 → 0.4.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.
- package/README.md +47 -27
- package/content/page-designer.md +4 -4
- package/dist/commands/mcp.d.ts +14 -2
- package/dist/commands/mcp.js +21 -9
- package/dist/registry.d.ts +4 -4
- package/dist/registry.js +13 -13
- package/dist/services.d.ts +75 -1
- package/dist/services.js +124 -1
- package/dist/tools/adapter.d.ts +29 -21
- package/dist/tools/adapter.js +34 -24
- package/dist/tools/cartridges/index.d.ts +5 -3
- package/dist/tools/cartridges/index.js +55 -25
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/index.js +1 -0
- package/dist/tools/mrt/index.d.ts +2 -2
- package/dist/tools/mrt/index.js +29 -10
- package/dist/tools/page-designer-decorator/analyzer.d.ts +169 -0
- package/dist/tools/page-designer-decorator/analyzer.js +535 -0
- package/dist/tools/page-designer-decorator/index.d.ts +252 -0
- package/dist/tools/page-designer-decorator/index.js +597 -0
- package/dist/tools/page-designer-decorator/rules/1-mode-selection.d.ts +8 -0
- package/dist/tools/page-designer-decorator/rules/1-mode-selection.js +65 -0
- package/dist/tools/page-designer-decorator/rules/2a-auto-mode.d.ts +13 -0
- package/dist/tools/page-designer-decorator/rules/2a-auto-mode.js +87 -0
- package/dist/tools/page-designer-decorator/rules/2b-0-interactive-overview.d.ts +4 -0
- package/dist/tools/page-designer-decorator/rules/2b-0-interactive-overview.js +55 -0
- package/dist/tools/page-designer-decorator/rules/2b-1-interactive-analyze.d.ts +22 -0
- package/dist/tools/page-designer-decorator/rules/2b-1-interactive-analyze.js +109 -0
- package/dist/tools/page-designer-decorator/rules/2b-2-interactive-select-props.d.ts +21 -0
- package/dist/tools/page-designer-decorator/rules/2b-2-interactive-select-props.js +60 -0
- package/dist/tools/page-designer-decorator/rules/2b-3-interactive-configure-attrs.d.ts +27 -0
- package/dist/tools/page-designer-decorator/rules/2b-3-interactive-configure-attrs.js +68 -0
- package/dist/tools/page-designer-decorator/rules/2b-4-interactive-configure-regions.d.ts +4 -0
- package/dist/tools/page-designer-decorator/rules/2b-4-interactive-configure-regions.js +65 -0
- package/dist/tools/page-designer-decorator/rules/2b-5-interactive-confirm-generation.d.ts +11 -0
- package/dist/tools/page-designer-decorator/rules/2b-5-interactive-confirm-generation.js +92 -0
- package/dist/tools/page-designer-decorator/rules.d.ts +51 -0
- package/dist/tools/page-designer-decorator/rules.js +70 -0
- package/dist/tools/page-designer-decorator/templates/decorator-generator.d.ts +116 -0
- package/dist/tools/page-designer-decorator/templates/decorator-generator.js +350 -0
- package/dist/tools/pwav3/index.d.ts +2 -2
- package/dist/tools/pwav3/index.js +13 -13
- package/dist/tools/scapi/index.d.ts +10 -2
- package/dist/tools/scapi/index.js +5 -56
- package/dist/tools/scapi/scapi-custom-apis-status.d.ts +9 -0
- package/dist/tools/scapi/scapi-custom-apis-status.js +152 -0
- package/dist/tools/scapi/scapi-schemas-list.d.ts +12 -0
- package/dist/tools/scapi/scapi-schemas-list.js +248 -0
- package/dist/tools/storefrontnext/developer-guidelines.d.ts +2 -2
- package/dist/tools/storefrontnext/developer-guidelines.js +3 -3
- package/dist/tools/storefrontnext/index.d.ts +2 -2
- package/dist/tools/storefrontnext/index.js +13 -13
- package/oclif.manifest.json +20 -6
- package/package.json +10 -5
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
|
-
|
|
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
|
package/dist/tools/adapter.d.ts
CHANGED
|
@@ -3,22 +3,22 @@
|
|
|
3
3
|
*
|
|
4
4
|
* This module provides utilities for creating standardized MCP tools that:
|
|
5
5
|
* - Validate input using Zod schemas
|
|
6
|
-
* - Inject
|
|
7
|
-
* - Inject
|
|
6
|
+
* - Inject loaded B2CInstance for WebDAV/OCAPI operations (requiresInstance)
|
|
7
|
+
* - Inject loaded MRT auth for MRT API operations (requiresMrtAuth)
|
|
8
8
|
* - Format output consistently (textResult, jsonResult, errorResult)
|
|
9
9
|
*
|
|
10
10
|
* ## Configuration Resolution
|
|
11
11
|
*
|
|
12
|
-
* Both B2C instance and MRT auth are
|
|
13
|
-
* {@link Services.fromResolvedConfig}
|
|
12
|
+
* Both B2C instance and MRT auth are loaded before each tool call via
|
|
13
|
+
* a loader function that calls {@link Services.fromResolvedConfig}:
|
|
14
14
|
*
|
|
15
|
-
* - **B2CInstance**:
|
|
16
|
-
* - **MRT Auth**:
|
|
15
|
+
* - **B2CInstance**: Loaded from flags + dw.json on each call. Available when `requiresInstance: true`.
|
|
16
|
+
* - **MRT Auth**: Loaded from --api-key → SFCC_MRT_API_KEY → ~/.mobify on each call. Available when `requiresMrtAuth: true`.
|
|
17
17
|
*
|
|
18
|
-
* This "
|
|
19
|
-
* -
|
|
20
|
-
* - Consistent mental model (both
|
|
21
|
-
* -
|
|
18
|
+
* This "load on each call" pattern provides:
|
|
19
|
+
* - Fresh configuration on each tool invocation (picks up changes to config files)
|
|
20
|
+
* - Consistent mental model (both loaded the same way)
|
|
21
|
+
* - Tools can respond to configuration changes without server restart
|
|
22
22
|
*
|
|
23
23
|
* @module tools/adapter
|
|
24
24
|
*
|
|
@@ -42,8 +42,11 @@
|
|
|
42
42
|
*
|
|
43
43
|
* @example MRT tool (MRT API)
|
|
44
44
|
* ```typescript
|
|
45
|
-
* //
|
|
46
|
-
* const
|
|
45
|
+
* // Loader function that loads config and creates Services on each tool call
|
|
46
|
+
* const loadServices = () => {
|
|
47
|
+
* const config = this.loadConfiguration();
|
|
48
|
+
* return Services.fromResolvedConfig(config);
|
|
49
|
+
* };
|
|
47
50
|
*
|
|
48
51
|
* const mrtTool = createToolAdapter({
|
|
49
52
|
* name: 'mrt_bundle_push',
|
|
@@ -53,12 +56,12 @@
|
|
|
53
56
|
* inputSchema: {
|
|
54
57
|
* projectSlug: z.string().describe('MRT project slug'),
|
|
55
58
|
* },
|
|
56
|
-
* execute: async (args, {
|
|
57
|
-
* const result = await pushBundle({ projectSlug: args.projectSlug },
|
|
59
|
+
* execute: async (args, { mrtConfig }) => {
|
|
60
|
+
* const result = await pushBundle({ projectSlug: args.projectSlug }, mrtConfig.auth);
|
|
58
61
|
* return result;
|
|
59
62
|
* },
|
|
60
63
|
* formatOutput: (output) => jsonResult(output),
|
|
61
|
-
* },
|
|
64
|
+
* }, loadServices);
|
|
62
65
|
* ```
|
|
63
66
|
*/
|
|
64
67
|
import { type ZodRawShape } from 'zod';
|
|
@@ -78,7 +81,7 @@ export interface ToolExecutionContext {
|
|
|
78
81
|
b2cInstance?: B2CInstance;
|
|
79
82
|
/**
|
|
80
83
|
* MRT configuration (auth, project, environment, origin).
|
|
81
|
-
*
|
|
84
|
+
* Loaded before each tool call.
|
|
82
85
|
* Only populated when requiresMrtAuth is true.
|
|
83
86
|
*/
|
|
84
87
|
mrtConfig?: MrtConfig;
|
|
@@ -176,7 +179,7 @@ export declare function jsonResult(data: unknown, indent?: number): ToolResult;
|
|
|
176
179
|
* @template TInput - The validated input type (inferred from inputSchema)
|
|
177
180
|
* @template TOutput - The output type from the execute function
|
|
178
181
|
* @param options - Tool adapter configuration
|
|
179
|
-
* @param
|
|
182
|
+
* @param loadServices - Function that loads configuration and returns Services instance
|
|
180
183
|
* @returns An McpTool ready for registration
|
|
181
184
|
*
|
|
182
185
|
* @example
|
|
@@ -184,18 +187,23 @@ export declare function jsonResult(data: unknown, indent?: number): ToolResult;
|
|
|
184
187
|
* import { z } from 'zod';
|
|
185
188
|
* import { createToolAdapter, jsonResult, errorResult } from './adapter.js';
|
|
186
189
|
*
|
|
190
|
+
* const loadServices = () => {
|
|
191
|
+
* const config = this.loadConfiguration();
|
|
192
|
+
* return Services.fromResolvedConfig(config);
|
|
193
|
+
* };
|
|
194
|
+
*
|
|
187
195
|
* const listCodeVersionsTool = createToolAdapter({
|
|
188
196
|
* name: 'code_version_list',
|
|
189
197
|
* description: 'List all code versions on the instance',
|
|
190
198
|
* toolsets: ['CARTRIDGES'],
|
|
191
199
|
* inputSchema: {},
|
|
192
|
-
* execute: async (_args, {
|
|
193
|
-
* const result = await
|
|
200
|
+
* execute: async (_args, { b2cInstance }) => {
|
|
201
|
+
* const result = await b2cInstance.ocapi.GET('/code_versions', {});
|
|
194
202
|
* if (result.error) throw new Error(result.error.message);
|
|
195
203
|
* return result.data;
|
|
196
204
|
* },
|
|
197
205
|
* formatOutput: (data) => jsonResult(data),
|
|
198
|
-
* },
|
|
206
|
+
* }, loadServices);
|
|
199
207
|
* ```
|
|
200
208
|
*/
|
|
201
|
-
export declare function createToolAdapter<TInput, TOutput>(options: ToolAdapterOptions<TInput, TOutput>,
|
|
209
|
+
export declare function createToolAdapter<TInput, TOutput>(options: ToolAdapterOptions<TInput, TOutput>, loadServices: () => Services): McpTool;
|
package/dist/tools/adapter.js
CHANGED
|
@@ -8,22 +8,22 @@
|
|
|
8
8
|
*
|
|
9
9
|
* This module provides utilities for creating standardized MCP tools that:
|
|
10
10
|
* - Validate input using Zod schemas
|
|
11
|
-
* - Inject
|
|
12
|
-
* - Inject
|
|
11
|
+
* - Inject loaded B2CInstance for WebDAV/OCAPI operations (requiresInstance)
|
|
12
|
+
* - Inject loaded MRT auth for MRT API operations (requiresMrtAuth)
|
|
13
13
|
* - Format output consistently (textResult, jsonResult, errorResult)
|
|
14
14
|
*
|
|
15
15
|
* ## Configuration Resolution
|
|
16
16
|
*
|
|
17
|
-
* Both B2C instance and MRT auth are
|
|
18
|
-
* {@link Services.fromResolvedConfig}
|
|
17
|
+
* Both B2C instance and MRT auth are loaded before each tool call via
|
|
18
|
+
* a loader function that calls {@link Services.fromResolvedConfig}:
|
|
19
19
|
*
|
|
20
|
-
* - **B2CInstance**:
|
|
21
|
-
* - **MRT Auth**:
|
|
20
|
+
* - **B2CInstance**: Loaded from flags + dw.json on each call. Available when `requiresInstance: true`.
|
|
21
|
+
* - **MRT Auth**: Loaded from --api-key → SFCC_MRT_API_KEY → ~/.mobify on each call. Available when `requiresMrtAuth: true`.
|
|
22
22
|
*
|
|
23
|
-
* This "
|
|
24
|
-
* -
|
|
25
|
-
* - Consistent mental model (both
|
|
26
|
-
* -
|
|
23
|
+
* This "load on each call" pattern provides:
|
|
24
|
+
* - Fresh configuration on each tool invocation (picks up changes to config files)
|
|
25
|
+
* - Consistent mental model (both loaded the same way)
|
|
26
|
+
* - Tools can respond to configuration changes without server restart
|
|
27
27
|
*
|
|
28
28
|
* @module tools/adapter
|
|
29
29
|
*
|
|
@@ -47,8 +47,11 @@
|
|
|
47
47
|
*
|
|
48
48
|
* @example MRT tool (MRT API)
|
|
49
49
|
* ```typescript
|
|
50
|
-
* //
|
|
51
|
-
* const
|
|
50
|
+
* // Loader function that loads config and creates Services on each tool call
|
|
51
|
+
* const loadServices = () => {
|
|
52
|
+
* const config = this.loadConfiguration();
|
|
53
|
+
* return Services.fromResolvedConfig(config);
|
|
54
|
+
* };
|
|
52
55
|
*
|
|
53
56
|
* const mrtTool = createToolAdapter({
|
|
54
57
|
* name: 'mrt_bundle_push',
|
|
@@ -58,12 +61,12 @@
|
|
|
58
61
|
* inputSchema: {
|
|
59
62
|
* projectSlug: z.string().describe('MRT project slug'),
|
|
60
63
|
* },
|
|
61
|
-
* execute: async (args, {
|
|
62
|
-
* const result = await pushBundle({ projectSlug: args.projectSlug },
|
|
64
|
+
* execute: async (args, { mrtConfig }) => {
|
|
65
|
+
* const result = await pushBundle({ projectSlug: args.projectSlug }, mrtConfig.auth);
|
|
63
66
|
* return result;
|
|
64
67
|
* },
|
|
65
68
|
* formatOutput: (output) => jsonResult(output),
|
|
66
|
-
* },
|
|
69
|
+
* }, loadServices);
|
|
67
70
|
* ```
|
|
68
71
|
*/
|
|
69
72
|
import { z } from 'zod';
|
|
@@ -138,7 +141,7 @@ function formatZodErrors(error) {
|
|
|
138
141
|
* @template TInput - The validated input type (inferred from inputSchema)
|
|
139
142
|
* @template TOutput - The output type from the execute function
|
|
140
143
|
* @param options - Tool adapter configuration
|
|
141
|
-
* @param
|
|
144
|
+
* @param loadServices - Function that loads configuration and returns Services instance
|
|
142
145
|
* @returns An McpTool ready for registration
|
|
143
146
|
*
|
|
144
147
|
* @example
|
|
@@ -146,21 +149,26 @@ function formatZodErrors(error) {
|
|
|
146
149
|
* import { z } from 'zod';
|
|
147
150
|
* import { createToolAdapter, jsonResult, errorResult } from './adapter.js';
|
|
148
151
|
*
|
|
152
|
+
* const loadServices = () => {
|
|
153
|
+
* const config = this.loadConfiguration();
|
|
154
|
+
* return Services.fromResolvedConfig(config);
|
|
155
|
+
* };
|
|
156
|
+
*
|
|
149
157
|
* const listCodeVersionsTool = createToolAdapter({
|
|
150
158
|
* name: 'code_version_list',
|
|
151
159
|
* description: 'List all code versions on the instance',
|
|
152
160
|
* toolsets: ['CARTRIDGES'],
|
|
153
161
|
* inputSchema: {},
|
|
154
|
-
* execute: async (_args, {
|
|
155
|
-
* const result = await
|
|
162
|
+
* execute: async (_args, { b2cInstance }) => {
|
|
163
|
+
* const result = await b2cInstance.ocapi.GET('/code_versions', {});
|
|
156
164
|
* if (result.error) throw new Error(result.error.message);
|
|
157
165
|
* return result.data;
|
|
158
166
|
* },
|
|
159
167
|
* formatOutput: (data) => jsonResult(data),
|
|
160
|
-
* },
|
|
168
|
+
* }, loadServices);
|
|
161
169
|
* ```
|
|
162
170
|
*/
|
|
163
|
-
export function createToolAdapter(options,
|
|
171
|
+
export function createToolAdapter(options, loadServices) {
|
|
164
172
|
const { name, description, inputSchema, toolsets, isGA = true, requiresInstance = false, requiresMrtAuth = false, execute, formatOutput, } = options;
|
|
165
173
|
// Create Zod schema from inputSchema definition
|
|
166
174
|
const zodSchema = z.object(inputSchema);
|
|
@@ -178,7 +186,9 @@ export function createToolAdapter(options, services) {
|
|
|
178
186
|
}
|
|
179
187
|
const args = parseResult.data;
|
|
180
188
|
try {
|
|
181
|
-
// 2.
|
|
189
|
+
// 2. Load Services to get fresh configuration (re-reads config files)
|
|
190
|
+
const services = loadServices();
|
|
191
|
+
// 3. Get B2CInstance if required (loaded on each call)
|
|
182
192
|
let b2cInstance;
|
|
183
193
|
if (requiresInstance) {
|
|
184
194
|
if (!services.b2cInstance) {
|
|
@@ -186,7 +196,7 @@ export function createToolAdapter(options, services) {
|
|
|
186
196
|
}
|
|
187
197
|
b2cInstance = services.b2cInstance;
|
|
188
198
|
}
|
|
189
|
-
//
|
|
199
|
+
// 4. Get MRT config if required (loaded on each call)
|
|
190
200
|
let mrtConfig;
|
|
191
201
|
if (requiresMrtAuth) {
|
|
192
202
|
if (!services.mrtConfig.auth) {
|
|
@@ -199,14 +209,14 @@ export function createToolAdapter(options, services) {
|
|
|
199
209
|
origin: services.mrtConfig.origin,
|
|
200
210
|
};
|
|
201
211
|
}
|
|
202
|
-
//
|
|
212
|
+
// 5. Execute the operation
|
|
203
213
|
const context = {
|
|
204
214
|
b2cInstance,
|
|
205
215
|
mrtConfig,
|
|
206
216
|
services,
|
|
207
217
|
};
|
|
208
218
|
const output = await execute(args, context);
|
|
209
|
-
//
|
|
219
|
+
// 6. Format output
|
|
210
220
|
return formatOutput(output);
|
|
211
221
|
}
|
|
212
222
|
catch (error) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { McpTool } from '../../utils/index.js';
|
|
2
2
|
import type { Services } from '../../services.js';
|
|
3
|
-
import type { DeployResult, DeployOptions } from '@salesforce/b2c-tooling-sdk/operations/code';
|
|
3
|
+
import type { DeployResult, DeployOptions, CodeVersion } from '@salesforce/b2c-tooling-sdk/operations/code';
|
|
4
4
|
import type { B2CInstance } from '@salesforce/b2c-tooling-sdk';
|
|
5
5
|
/**
|
|
6
6
|
* Optional dependency injections for testing.
|
|
@@ -8,13 +8,15 @@ import type { B2CInstance } from '@salesforce/b2c-tooling-sdk';
|
|
|
8
8
|
interface CartridgeToolInjections {
|
|
9
9
|
/** Mock findAndDeployCartridges function for testing */
|
|
10
10
|
findAndDeployCartridges?: (instance: B2CInstance, directory: string, options: DeployOptions) => Promise<DeployResult>;
|
|
11
|
+
/** Mock getActiveCodeVersion function for testing */
|
|
12
|
+
getActiveCodeVersion?: (instance: B2CInstance) => Promise<CodeVersion | undefined>;
|
|
11
13
|
}
|
|
12
14
|
/**
|
|
13
15
|
* Creates all tools for the CARTRIDGES toolset.
|
|
14
16
|
*
|
|
15
|
-
* @param
|
|
17
|
+
* @param loadServices - Function that loads configuration and returns Services instance
|
|
16
18
|
* @param injections - Optional dependency injections for testing
|
|
17
19
|
* @returns Array of MCP tools
|
|
18
20
|
*/
|
|
19
|
-
export declare function createCartridgesTools(
|
|
21
|
+
export declare function createCartridgesTools(loadServices: () => Services, injections?: CartridgeToolInjections): McpTool[];
|
|
20
22
|
export {};
|
|
@@ -10,9 +10,10 @@
|
|
|
10
10
|
*
|
|
11
11
|
* @module tools/cartridges
|
|
12
12
|
*/
|
|
13
|
+
import path from 'node:path';
|
|
13
14
|
import { z } from 'zod';
|
|
14
15
|
import { createToolAdapter, jsonResult } from '../adapter.js';
|
|
15
|
-
import { findAndDeployCartridges } from '@salesforce/b2c-tooling-sdk/operations/code';
|
|
16
|
+
import { findAndDeployCartridges, getActiveCodeVersion } from '@salesforce/b2c-tooling-sdk/operations/code';
|
|
16
17
|
import { getLogger } from '@salesforce/b2c-tooling-sdk/logging';
|
|
17
18
|
/**
|
|
18
19
|
* Creates the cartridge_deploy tool.
|
|
@@ -23,12 +24,13 @@ import { getLogger } from '@salesforce/b2c-tooling-sdk/logging';
|
|
|
23
24
|
* 3. Uploads the zip to WebDAV and triggers server-side unzip
|
|
24
25
|
* 4. Optionally reloads the code version after deploy
|
|
25
26
|
*
|
|
26
|
-
* @param
|
|
27
|
+
* @param loadServices - Function that loads configuration and returns Services instance
|
|
27
28
|
* @param injections - Optional dependency injections for testing
|
|
28
29
|
* @returns The cartridge_deploy tool
|
|
29
30
|
*/
|
|
30
|
-
function createCartridgeDeployTool(
|
|
31
|
+
function createCartridgeDeployTool(loadServices, injections) {
|
|
31
32
|
const findAndDeployCartridgesFn = injections?.findAndDeployCartridges || findAndDeployCartridges;
|
|
33
|
+
const getActiveCodeVersionFn = injections?.getActiveCodeVersion || getActiveCodeVersion;
|
|
32
34
|
return createToolAdapter({
|
|
33
35
|
name: 'cartridge_deploy',
|
|
34
36
|
description: 'Finds and deploys cartridges to a B2C Commerce instance via WebDAV. ' +
|
|
@@ -65,37 +67,65 @@ function createCartridgeDeployTool(services, injections) {
|
|
|
65
67
|
async execute(args, context) {
|
|
66
68
|
// Get instance from context (guaranteed by adapter when requiresInstance is true)
|
|
67
69
|
const instance = context.b2cInstance;
|
|
68
|
-
// Default directory to current directory
|
|
69
|
-
const directory = args.directory || '.';
|
|
70
|
-
// Parse options
|
|
71
|
-
const options = {
|
|
72
|
-
include: args.cartridges,
|
|
73
|
-
exclude: args.exclude,
|
|
74
|
-
reload: args.reload,
|
|
75
|
-
};
|
|
76
|
-
// Log all computed variables before deploying
|
|
77
70
|
const logger = getLogger();
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
71
|
+
try {
|
|
72
|
+
// If no code version specified, get the active one
|
|
73
|
+
let codeVersion = instance.config.codeVersion;
|
|
74
|
+
if (!codeVersion) {
|
|
75
|
+
logger.debug('No code version specified, getting active version...');
|
|
76
|
+
const active = await getActiveCodeVersionFn(instance);
|
|
77
|
+
if (!active?.id) {
|
|
78
|
+
throw new Error('No code version specified and no active code version found. ' +
|
|
79
|
+
'Specify a code version using one of: ' +
|
|
80
|
+
'--code-version flag, SFCC_CODE_VERSION environment variable, ' +
|
|
81
|
+
'or code-version field in dw.json configuration file.');
|
|
82
|
+
}
|
|
83
|
+
codeVersion = active.id;
|
|
84
|
+
instance.config.codeVersion = codeVersion;
|
|
85
|
+
}
|
|
86
|
+
// Resolve directory path: relative paths are resolved relative to working directory, absolute paths are used as-is
|
|
87
|
+
const directory = args.directory
|
|
88
|
+
? path.isAbsolute(args.directory)
|
|
89
|
+
? args.directory
|
|
90
|
+
: path.resolve(context.services.getWorkingDirectory(), args.directory)
|
|
91
|
+
: context.services.getWorkingDirectory();
|
|
92
|
+
// Parse options
|
|
93
|
+
const options = {
|
|
94
|
+
include: args.cartridges,
|
|
95
|
+
exclude: args.exclude,
|
|
96
|
+
reload: args.reload,
|
|
97
|
+
};
|
|
98
|
+
// Log all computed variables before deploying
|
|
99
|
+
logger.debug({
|
|
100
|
+
directory,
|
|
101
|
+
codeVersion,
|
|
102
|
+
include: options.include,
|
|
103
|
+
exclude: options.exclude,
|
|
104
|
+
reload: options.reload,
|
|
105
|
+
}, '[Cartridges] Deploying cartridges with computed options');
|
|
106
|
+
// Deploy cartridges
|
|
107
|
+
const result = await findAndDeployCartridgesFn(instance, directory, options);
|
|
108
|
+
return result;
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
// Handle communication and authentication errors
|
|
112
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
113
|
+
throw new Error(`Failed to communicate with B2C instance. Check your authentication credentials and network connection. ` +
|
|
114
|
+
`If no code version is specified, ensure the instance is accessible and has an active code version. ` +
|
|
115
|
+
`Original error: ${errorMessage}`);
|
|
116
|
+
}
|
|
87
117
|
},
|
|
88
118
|
formatOutput: (output) => jsonResult(output),
|
|
89
|
-
},
|
|
119
|
+
}, loadServices);
|
|
90
120
|
}
|
|
91
121
|
/**
|
|
92
122
|
* Creates all tools for the CARTRIDGES toolset.
|
|
93
123
|
*
|
|
94
|
-
* @param
|
|
124
|
+
* @param loadServices - Function that loads configuration and returns Services instance
|
|
95
125
|
* @param injections - Optional dependency injections for testing
|
|
96
126
|
* @returns Array of MCP tools
|
|
97
127
|
*/
|
|
98
|
-
export function createCartridgesTools(
|
|
99
|
-
return [createCartridgeDeployTool(
|
|
128
|
+
export function createCartridgesTools(loadServices, injections) {
|
|
129
|
+
return [createCartridgeDeployTool(loadServices, injections)];
|
|
100
130
|
}
|
|
101
131
|
//# sourceMappingURL=index.js.map
|
package/dist/tools/index.d.ts
CHANGED
package/dist/tools/index.js
CHANGED
|
@@ -12,9 +12,9 @@ interface MrtToolInjections {
|
|
|
12
12
|
/**
|
|
13
13
|
* Creates all tools for the MRT toolset.
|
|
14
14
|
*
|
|
15
|
-
* @param
|
|
15
|
+
* @param loadServices - Function that loads configuration and returns Services instance
|
|
16
16
|
* @param injections - Optional dependency injections for testing
|
|
17
17
|
* @returns Array of MCP tools
|
|
18
18
|
*/
|
|
19
|
-
export declare function createMrtTools(
|
|
19
|
+
export declare function createMrtTools(loadServices: () => Services, injections?: MrtToolInjections): McpTool[];
|
|
20
20
|
export {};
|