@salesforce/b2c-dx-mcp 1.2.0 → 1.3.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.
- package/README.md +8 -1
- package/dist/registry.js +10 -3
- package/dist/server-context.d.ts +6 -3
- package/dist/server-context.js +12 -4
- package/dist/tools/diagnostics/index.d.ts +2 -1
- package/dist/tools/diagnostics/index.js +8 -0
- package/dist/tools/diagnostics/mrt-log-watch-registry.d.ts +115 -0
- package/dist/tools/diagnostics/mrt-log-watch-registry.js +0 -0
- package/dist/tools/diagnostics/mrt-logs-watch-list.d.ts +4 -0
- package/dist/tools/diagnostics/mrt-logs-watch-list.js +36 -0
- package/dist/tools/diagnostics/mrt-logs-watch-poll.d.ts +4 -0
- package/dist/tools/diagnostics/mrt-logs-watch-poll.js +59 -0
- package/dist/tools/diagnostics/mrt-logs-watch-start.d.ts +14 -0
- package/dist/tools/diagnostics/mrt-logs-watch-start.js +133 -0
- package/dist/tools/diagnostics/mrt-logs-watch-stop.d.ts +4 -0
- package/dist/tools/diagnostics/mrt-logs-watch-stop.js +37 -0
- package/dist/tools/storefrontnext/figma/figma-to-component/index.js +3 -2
- package/dist/tools/storefrontnext/figma/generate-component/index.js +3 -2
- package/dist/tools/storefrontnext/figma/map-tokens/index.js +3 -2
- package/dist/tools/storefrontnext/index.d.ts +9 -9
- package/dist/tools/storefrontnext/index.js +1 -5
- package/dist/tools/storefrontnext/page-designer-decorator/index.js +3 -2
- package/dist/tools/storefrontnext/sfnext-development-guidelines.js +3 -2
- package/dist/tools/storefrontnext/site-theming/index.js +3 -2
- package/dist/utils/constants.d.ts +13 -2
- package/dist/utils/constants.js +20 -1
- package/oclif.manifest.json +2 -2
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -80,9 +80,12 @@ See the [Configuration Guide](https://salesforcecommercecloud.github.io/b2c-deve
|
|
|
80
80
|
| CARTRIDGES | `cartridge_deploy` | [toolsets#cartridges](https://salesforcecommercecloud.github.io/b2c-developer-tooling/mcp/toolsets#cartridges) |
|
|
81
81
|
| MRT | `mrt_bundle_push` | [toolsets#mrt](https://salesforcecommercecloud.github.io/b2c-developer-tooling/mcp/toolsets#mrt) |
|
|
82
82
|
| SCAPI | `scapi_schemas_list`, `scapi_custom_apis_get_status`, `scapi_custom_api_generate_scaffold` | [toolsets#scapi](https://salesforcecommercecloud.github.io/b2c-developer-tooling/mcp/toolsets#scapi) |
|
|
83
|
-
| STOREFRONTNEXT | `
|
|
83
|
+
| STOREFRONTNEXT | `mrt_bundle_push` + SCAPI tools (auto-enabled for Storefront Next projects) | [toolsets#storefrontnext](https://salesforcecommercecloud.github.io/b2c-developer-tooling/mcp/toolsets#storefrontnext) |
|
|
84
|
+
| STOREFRONTNEXT_DEPRECATED ⛔ | `sfnext_get_guidelines`, `sfnext_add_page_designer_decorator`, `sfnext_configure_theme`, `sfnext_start_figma_workflow`, `sfnext_analyze_component`, `sfnext_match_tokens_to_theme` — **deprecated, see note below** | [toolsets#storefrontnext-deprecated](https://salesforcecommercecloud.github.io/b2c-developer-tooling/mcp/toolsets#storefrontnext-deprecated) |
|
|
84
85
|
| PWAV3 | `pwakit_get_guidelines` + SCAPI tools | [toolsets#pwav3](https://salesforcecommercecloud.github.io/b2c-developer-tooling/mcp/toolsets#pwav3) |
|
|
85
86
|
|
|
87
|
+
> **⛔ `sfnext_*` tools are deprecated.** The Storefront Next MCP tools are **not compatible with the Storefront Next 1.0 GA release** and have been superseded by the [`storefront-next` and `storefront-next-figma` agent-skills plugins](https://salesforcecommercecloud.github.io/b2c-developer-tooling/guide/agent-skills), which stay current with the GA release. They have moved to the `STOREFRONTNEXT_DEPRECATED` toolset, which is **never auto-enabled** and **excluded from `--toolsets all`**; to use them you must request the toolset explicitly (`--toolsets STOREFRONTNEXT_DEPRECATED --allow-non-ga-tools`). They will be removed in a future release.
|
|
88
|
+
|
|
86
89
|
### cartridge_deploy
|
|
87
90
|
|
|
88
91
|
Deploy cartridges to a B2C Commerce instance. [Details](https://salesforcecommercecloud.github.io/b2c-developer-tooling/mcp/tools/cartridge-deploy)
|
|
@@ -118,6 +121,10 @@ Generate new custom SCAPI endpoint in a cartridge. [Details](https://salesforcec
|
|
|
118
121
|
- "Use the MCP tool to scaffold a new custom API named my-products."
|
|
119
122
|
- "Use the MCP tool to create a custom admin API called customer-trips."
|
|
120
123
|
|
|
124
|
+
## Deprecated: Storefront Next (`sfnext_*`) tools
|
|
125
|
+
|
|
126
|
+
> **⛔ Deprecated and not compatible with the Storefront Next 1.0 GA release.** The tools below have been superseded by the [`storefront-next` and `storefront-next-figma` agent-skills plugins](https://salesforcecommercecloud.github.io/b2c-developer-tooling/guide/agent-skills) and will be removed in a future release. They no longer auto-enable for Storefront Next projects and are excluded from `--toolsets all`; to use them, request `--toolsets STOREFRONTNEXT_DEPRECATED --allow-non-ga-tools`. Migrate to the skills plugins.
|
|
127
|
+
|
|
121
128
|
### sfnext_get_guidelines
|
|
122
129
|
|
|
123
130
|
Get Storefront Next guidelines and best practices. [Details](https://salesforcecommercecloud.github.io/b2c-developer-tooling/mcp/tools/sfnext-get-guidelines)
|
package/dist/registry.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { getLogger } from '@salesforce/b2c-tooling-sdk/logging';
|
|
7
7
|
import { detectWorkspaceType } from '@salesforce/b2c-tooling-sdk/discovery';
|
|
8
|
-
import { ALL_TOOLSETS, TOOLSETS, VALID_TOOLSET_NAMES } from './utils/index.js';
|
|
8
|
+
import { ALL_TOOLSETS, DEPRECATED_TOOLSETS, TOOLSETS, VALID_TOOLSET_NAMES } from './utils/index.js';
|
|
9
9
|
import { createCartridgesTools } from './tools/cartridges/index.js';
|
|
10
10
|
import { createDiagnosticsTools } from './tools/diagnostics/index.js';
|
|
11
11
|
import { createDocsTools } from './tools/docs/index.js';
|
|
@@ -27,6 +27,9 @@ const BASE_TOOLSETS = ['SCAPI', 'DIAGNOSTICS'];
|
|
|
27
27
|
const PROJECT_TYPE_TOOLSETS = {
|
|
28
28
|
cartridges: ['CARTRIDGES'],
|
|
29
29
|
'pwa-kit-v3': ['PWAV3', 'MRT'],
|
|
30
|
+
// Note: STOREFRONTNEXT_DEPRECATED is intentionally NOT auto-activated. The
|
|
31
|
+
// legacy sfnext_* tools are superseded by the storefront-next agent-skills
|
|
32
|
+
// plugins and must be explicitly requested via --toolsets.
|
|
30
33
|
'storefront-next': ['STOREFRONTNEXT', 'MRT', 'CARTRIDGES'],
|
|
31
34
|
};
|
|
32
35
|
/**
|
|
@@ -75,6 +78,7 @@ export function createToolRegistry(loadServices, serverContext) {
|
|
|
75
78
|
PWAV3: [],
|
|
76
79
|
SCAPI: [],
|
|
77
80
|
STOREFRONTNEXT: [],
|
|
81
|
+
STOREFRONTNEXT_DEPRECATED: [],
|
|
78
82
|
};
|
|
79
83
|
// Collect all tools from all factories
|
|
80
84
|
const allTools = [
|
|
@@ -174,9 +178,12 @@ export async function registerToolsets(flags, server, loadServices, serverContex
|
|
|
174
178
|
if (invalidToolsets.length > 0) {
|
|
175
179
|
logger.warn({ invalidToolsets, validToolsets: VALID_TOOLSET_NAMES }, `Ignoring invalid toolset(s): "${invalidToolsets.join('", "')}"`);
|
|
176
180
|
}
|
|
177
|
-
// Determine which toolsets to enable
|
|
181
|
+
// Determine which toolsets to enable.
|
|
182
|
+
// `ALL` expands to every toolset EXCEPT deprecated ones — deprecated toolsets
|
|
183
|
+
// must always be named explicitly.
|
|
178
184
|
const validToolsets = toolsets.filter((t) => TOOLSETS.includes(t));
|
|
179
|
-
const
|
|
185
|
+
const allNonDeprecatedToolsets = TOOLSETS.filter((t) => !DEPRECATED_TOOLSETS.includes(t));
|
|
186
|
+
const toolsetsToEnable = new Set(toolsets.includes(ALL_TOOLSETS) ? allNonDeprecatedToolsets : validToolsets);
|
|
180
187
|
// Auto-discovery: If no valid toolsets AND no valid individual tools, detect workspace type.
|
|
181
188
|
// This handles both: (1) no flags provided, and (2) all provided flags are invalid.
|
|
182
189
|
// Auto-discovery enables appropriate toolsets based on workspace type,
|
package/dist/server-context.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { LogWatchRegistry } from './tools/diagnostics/log-watch-registry.js';
|
|
2
|
+
import { MrtLogWatchRegistry } from './tools/diagnostics/mrt-log-watch-registry.js';
|
|
2
3
|
import { DebugSessionRegistry } from './tools/diagnostics/session-registry.js';
|
|
3
4
|
/**
|
|
4
5
|
* Server-scoped persistent state that lives for the lifetime of the MCP
|
|
@@ -17,13 +18,15 @@ import { DebugSessionRegistry } from './tools/diagnostics/session-registry.js';
|
|
|
17
18
|
* client would also share the same context. Tools that mutate registries
|
|
18
19
|
* (like the debug tools) should not assume single-tenant access.
|
|
19
20
|
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* may see each other's
|
|
21
|
+
* The registries dedup on a stable key (host:client_id for debug, hostname for
|
|
22
|
+
* SFCC log watches, project/environment/origin for MRT log watches), so
|
|
23
|
+
* multi-agent use is functional but agents may see each other's
|
|
24
|
+
* sessions/watches via list tools.
|
|
23
25
|
*/
|
|
24
26
|
export declare class ServerContext {
|
|
25
27
|
readonly debugSessions: DebugSessionRegistry;
|
|
26
28
|
readonly logWatches: LogWatchRegistry;
|
|
29
|
+
readonly mrtLogWatches: MrtLogWatchRegistry;
|
|
27
30
|
constructor();
|
|
28
31
|
destroyAll(): Promise<void>;
|
|
29
32
|
}
|
package/dist/server-context.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
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
6
|
import { LogWatchRegistry } from './tools/diagnostics/log-watch-registry.js';
|
|
7
|
+
import { MrtLogWatchRegistry } from './tools/diagnostics/mrt-log-watch-registry.js';
|
|
7
8
|
import { DebugSessionRegistry } from './tools/diagnostics/session-registry.js';
|
|
8
9
|
/**
|
|
9
10
|
* Server-scoped persistent state that lives for the lifetime of the MCP
|
|
@@ -22,19 +23,26 @@ import { DebugSessionRegistry } from './tools/diagnostics/session-registry.js';
|
|
|
22
23
|
* client would also share the same context. Tools that mutate registries
|
|
23
24
|
* (like the debug tools) should not assume single-tenant access.
|
|
24
25
|
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* may see each other's
|
|
26
|
+
* The registries dedup on a stable key (host:client_id for debug, hostname for
|
|
27
|
+
* SFCC log watches, project/environment/origin for MRT log watches), so
|
|
28
|
+
* multi-agent use is functional but agents may see each other's
|
|
29
|
+
* sessions/watches via list tools.
|
|
28
30
|
*/
|
|
29
31
|
export class ServerContext {
|
|
30
32
|
debugSessions;
|
|
31
33
|
logWatches;
|
|
34
|
+
mrtLogWatches;
|
|
32
35
|
constructor() {
|
|
33
36
|
this.debugSessions = new DebugSessionRegistry();
|
|
34
37
|
this.logWatches = new LogWatchRegistry();
|
|
38
|
+
this.mrtLogWatches = new MrtLogWatchRegistry();
|
|
35
39
|
}
|
|
36
40
|
async destroyAll() {
|
|
37
|
-
await Promise.allSettled([
|
|
41
|
+
await Promise.allSettled([
|
|
42
|
+
this.debugSessions.destroyAll(),
|
|
43
|
+
this.logWatches.destroyAll(),
|
|
44
|
+
this.mrtLogWatches.destroyAll(),
|
|
45
|
+
]);
|
|
38
46
|
}
|
|
39
47
|
}
|
|
40
48
|
//# sourceMappingURL=server-context.js.map
|
|
@@ -4,6 +4,7 @@ import type { ServerContext } from '../../server-context.js';
|
|
|
4
4
|
import { type LogsListFilesInjections } from './logs-list-files.js';
|
|
5
5
|
import { type LogsGetRecentInjections } from './logs-get-recent.js';
|
|
6
6
|
import { type LogsWatchStartInjections } from './logs-watch-start.js';
|
|
7
|
-
|
|
7
|
+
import { type MrtLogsWatchStartInjections } from './mrt-logs-watch-start.js';
|
|
8
|
+
export interface DiagnosticsToolInjections extends LogsGetRecentInjections, LogsListFilesInjections, LogsWatchStartInjections, MrtLogsWatchStartInjections {
|
|
8
9
|
}
|
|
9
10
|
export declare function createDiagnosticsTools(loadServices: () => Promise<Services> | Services, serverContext?: ServerContext, injections?: DiagnosticsToolInjections): McpTool[];
|
|
@@ -20,6 +20,10 @@ import { createLogsWatchStartTool } from './logs-watch-start.js';
|
|
|
20
20
|
import { createLogsWatchPollTool } from './logs-watch-poll.js';
|
|
21
21
|
import { createLogsWatchStopTool } from './logs-watch-stop.js';
|
|
22
22
|
import { createLogsWatchListTool } from './logs-watch-list.js';
|
|
23
|
+
import { createMrtLogsWatchStartTool } from './mrt-logs-watch-start.js';
|
|
24
|
+
import { createMrtLogsWatchPollTool } from './mrt-logs-watch-poll.js';
|
|
25
|
+
import { createMrtLogsWatchStopTool } from './mrt-logs-watch-stop.js';
|
|
26
|
+
import { createMrtLogsWatchListTool } from './mrt-logs-watch-list.js';
|
|
23
27
|
export function createDiagnosticsTools(loadServices, serverContext, injections) {
|
|
24
28
|
return [
|
|
25
29
|
createDebugListSessionsTool(loadServices, serverContext),
|
|
@@ -39,6 +43,10 @@ export function createDiagnosticsTools(loadServices, serverContext, injections)
|
|
|
39
43
|
createLogsWatchPollTool(loadServices, serverContext),
|
|
40
44
|
createLogsWatchStopTool(loadServices, serverContext),
|
|
41
45
|
createLogsWatchListTool(loadServices, serverContext),
|
|
46
|
+
createMrtLogsWatchStartTool(loadServices, serverContext, injections),
|
|
47
|
+
createMrtLogsWatchPollTool(loadServices, serverContext),
|
|
48
|
+
createMrtLogsWatchStopTool(loadServices, serverContext),
|
|
49
|
+
createMrtLogsWatchListTool(loadServices, serverContext),
|
|
42
50
|
];
|
|
43
51
|
}
|
|
44
52
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import type { MrtLogEntry, TailMrtLogsResult } from '@salesforce/b2c-tooling-sdk/operations/mrt';
|
|
2
|
+
import type { ToolExecutionContext } from '../adapter.js';
|
|
3
|
+
/** Maximum number of buffered entries before oldest are evicted. */
|
|
4
|
+
export declare const DEFAULT_BUFFER_CAP = 5000;
|
|
5
|
+
/**
|
|
6
|
+
* Maximum cumulative bytes buffered before oldest entries are evicted.
|
|
7
|
+
* Guards against a small number of pathologically large entries (e.g. multi-MB
|
|
8
|
+
* stack traces) blowing past the count cap's intended memory bound.
|
|
9
|
+
*/
|
|
10
|
+
export declare const DEFAULT_BUFFER_BYTES_CAP: number;
|
|
11
|
+
export interface PollWaiter {
|
|
12
|
+
resolve: () => void;
|
|
13
|
+
timer: ReturnType<typeof setTimeout>;
|
|
14
|
+
}
|
|
15
|
+
export interface MrtLogWatchEntry {
|
|
16
|
+
watchId: string;
|
|
17
|
+
/** MRT project slug being tailed. */
|
|
18
|
+
project: string;
|
|
19
|
+
/** MRT environment slug being tailed. */
|
|
20
|
+
environment: string;
|
|
21
|
+
/** MRT API origin URL (used for the logs WebSocket host). */
|
|
22
|
+
origin?: string;
|
|
23
|
+
buffer: MrtLogEntry[];
|
|
24
|
+
/** Running byte size of `buffer` (raw + message), used for the byte cap. */
|
|
25
|
+
bufferBytes: number;
|
|
26
|
+
errors: Array<{
|
|
27
|
+
message: string;
|
|
28
|
+
at: string;
|
|
29
|
+
}>;
|
|
30
|
+
totalEntriesSeen: number;
|
|
31
|
+
droppedEntries: number;
|
|
32
|
+
bufferCap: number;
|
|
33
|
+
bufferBytesCap: number;
|
|
34
|
+
stop: () => void;
|
|
35
|
+
done: Promise<void>;
|
|
36
|
+
pollWaiters: PollWaiter[];
|
|
37
|
+
createdAt: number;
|
|
38
|
+
lastActivityAt: number;
|
|
39
|
+
/**
|
|
40
|
+
* True once the underlying WebSocket has closed — either via stop() or
|
|
41
|
+
* because the server closed/failed the connection on its own. A stopped
|
|
42
|
+
* watch keeps its buffered entries until drained or idle-reaped.
|
|
43
|
+
*/
|
|
44
|
+
stopped: boolean;
|
|
45
|
+
}
|
|
46
|
+
export interface RegisterMrtWatchOptions {
|
|
47
|
+
project: string;
|
|
48
|
+
environment: string;
|
|
49
|
+
origin?: string;
|
|
50
|
+
tailResult: TailMrtLogsResult;
|
|
51
|
+
bufferCap?: number;
|
|
52
|
+
bufferBytesCap?: number;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Stable dedup key for an MRT log watch. A developer may tail several
|
|
56
|
+
* (project, environment, origin) tuples concurrently — unlike the SFCC log
|
|
57
|
+
* watch which keys on hostname — so all three components form the key. A space
|
|
58
|
+
* separator is safe since project/environment slugs are URL-safe (no spaces).
|
|
59
|
+
*/
|
|
60
|
+
export declare function mrtWatchKey(project: string, environment: string, origin?: string): string;
|
|
61
|
+
/**
|
|
62
|
+
* In-memory registry of background MRT log-tail streams.
|
|
63
|
+
*
|
|
64
|
+
* Mirrors `LogWatchRegistry` (SFCC instance logs) but adapted for the MRT
|
|
65
|
+
* logging WebSocket: there are no log files, prefixes, or rotations — just a
|
|
66
|
+
* single live stream per (project, environment, origin). The stream can also
|
|
67
|
+
* close on its own (idle timeout, auth expiry, server restart), which is
|
|
68
|
+
* recorded as `stopped: true` plus a buffered error so a poll can surface it.
|
|
69
|
+
*/
|
|
70
|
+
export declare class MrtLogWatchRegistry {
|
|
71
|
+
private cleanupTimer;
|
|
72
|
+
private readonly watches;
|
|
73
|
+
constructor();
|
|
74
|
+
/**
|
|
75
|
+
* Append a log entry to a watch buffer. Evicts oldest if over cap.
|
|
76
|
+
* Resolves any pending poll waiters.
|
|
77
|
+
*/
|
|
78
|
+
appendEntry(watchId: string, entry: MrtLogEntry): void;
|
|
79
|
+
appendError(watchId: string, err: Error): void;
|
|
80
|
+
destroyAll(): Promise<void>;
|
|
81
|
+
destroyWatch(watchId: string): Promise<void>;
|
|
82
|
+
/**
|
|
83
|
+
* Drain buffered entries (up to maxEntries) and any error events from the
|
|
84
|
+
* watch. Removes drained items from the underlying buffers.
|
|
85
|
+
*/
|
|
86
|
+
drain(watchId: string, maxEntries: number): {
|
|
87
|
+
entries: MrtLogEntry[];
|
|
88
|
+
errors: Array<{
|
|
89
|
+
message: string;
|
|
90
|
+
at: string;
|
|
91
|
+
}>;
|
|
92
|
+
truncated: boolean;
|
|
93
|
+
};
|
|
94
|
+
findByKey(project: string, environment: string, origin?: string): MrtLogWatchEntry | undefined;
|
|
95
|
+
getWatch(watchId: string): MrtLogWatchEntry | undefined;
|
|
96
|
+
getWatchOrThrow(watchId: string): MrtLogWatchEntry;
|
|
97
|
+
listWatches(): MrtLogWatchEntry[];
|
|
98
|
+
/**
|
|
99
|
+
* Mark a watch's stream as closed (the WebSocket ended on its own or via
|
|
100
|
+
* stop). Keeps the entry so buffered entries can still be drained and the
|
|
101
|
+
* `stopped` flag is observable on the next poll; idle cleanup removes it
|
|
102
|
+
* later. Resolves any blocked pollers so they return promptly.
|
|
103
|
+
*/
|
|
104
|
+
markStreamClosed(watchId: string): void;
|
|
105
|
+
registerWatch(opts: RegisterMrtWatchOptions): MrtLogWatchEntry;
|
|
106
|
+
/**
|
|
107
|
+
* Wait until at least one entry is buffered (or an error event arrives, or
|
|
108
|
+
* the stream stops), or until timeout elapses. Returns immediately if there
|
|
109
|
+
* is already activity to report.
|
|
110
|
+
*/
|
|
111
|
+
waitForActivity(watchId: string, timeoutMs: number): Promise<void>;
|
|
112
|
+
private cleanupIdleWatches;
|
|
113
|
+
private flushWaiters;
|
|
114
|
+
}
|
|
115
|
+
export declare function getMrtLogWatchRegistry(context: ToolExecutionContext): MrtLogWatchRegistry;
|
|
Binary file
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { McpTool } from '../../utils/index.js';
|
|
2
|
+
import type { Services } from '../../services.js';
|
|
3
|
+
import type { ServerContext } from '../../server-context.js';
|
|
4
|
+
export declare function createMrtLogsWatchListTool(loadServices: () => Promise<Services> | Services, serverContext?: ServerContext): McpTool;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2025, Salesforce, Inc.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2
|
|
4
|
+
* For full license text, see the license.txt file in the repo root or http://www.apache.org/licenses/LICENSE-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { createToolAdapter, jsonResult } from '../adapter.js';
|
|
7
|
+
import { getMrtLogWatchRegistry } from './mrt-log-watch-registry.js';
|
|
8
|
+
export function createMrtLogsWatchListTool(loadServices, serverContext) {
|
|
9
|
+
return createToolAdapter({
|
|
10
|
+
name: 'mrt_logs_watch_list',
|
|
11
|
+
description: 'List all active MRT log watches with their status. Use this to find an orphaned watch_id (e.g., after a ' +
|
|
12
|
+
'crashed agent run) so you can resume polling or stop it.',
|
|
13
|
+
toolsets: ['DIAGNOSTICS', 'PWAV3', 'STOREFRONTNEXT'],
|
|
14
|
+
inputSchema: {},
|
|
15
|
+
async execute(_args, context) {
|
|
16
|
+
const registry = getMrtLogWatchRegistry(context);
|
|
17
|
+
const entries = registry.listWatches();
|
|
18
|
+
return {
|
|
19
|
+
watches: entries.map((w) => ({
|
|
20
|
+
buffered_entries: w.buffer.length,
|
|
21
|
+
created_at: new Date(w.createdAt).toISOString(),
|
|
22
|
+
dropped_entries: w.droppedEntries,
|
|
23
|
+
environment: w.environment,
|
|
24
|
+
last_activity_at: new Date(w.lastActivityAt).toISOString(),
|
|
25
|
+
origin: w.origin,
|
|
26
|
+
project: w.project,
|
|
27
|
+
stopped: w.stopped,
|
|
28
|
+
total_entries_seen: w.totalEntriesSeen,
|
|
29
|
+
watch_id: w.watchId,
|
|
30
|
+
})),
|
|
31
|
+
};
|
|
32
|
+
},
|
|
33
|
+
formatOutput: (output) => jsonResult(output),
|
|
34
|
+
}, loadServices, serverContext);
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=mrt-logs-watch-list.js.map
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { McpTool } from '../../utils/index.js';
|
|
2
|
+
import type { Services } from '../../services.js';
|
|
3
|
+
import type { ServerContext } from '../../server-context.js';
|
|
4
|
+
export declare function createMrtLogsWatchPollTool(loadServices: () => Promise<Services> | Services, serverContext?: ServerContext): McpTool;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2025, Salesforce, Inc.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2
|
|
4
|
+
* For full license text, see the license.txt file in the repo root or http://www.apache.org/licenses/LICENSE-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
import { createToolAdapter, jsonResult } from '../adapter.js';
|
|
8
|
+
import { getMrtLogWatchRegistry } from './mrt-log-watch-registry.js';
|
|
9
|
+
const DEFAULT_TIMEOUT_MS = 5000;
|
|
10
|
+
const DEFAULT_MAX_ENTRIES = 200;
|
|
11
|
+
export function createMrtLogsWatchPollTool(loadServices, serverContext) {
|
|
12
|
+
return createToolAdapter({
|
|
13
|
+
name: 'mrt_logs_watch_poll',
|
|
14
|
+
description: 'Drain buffered entries from an MRT log watch. If the buffer is empty, blocks up to timeout_ms waiting for ' +
|
|
15
|
+
'new entries. Returns immediately if entries are already buffered or the stream has stopped. Set ' +
|
|
16
|
+
'truncated=true if there are more entries beyond max_entries — call again to get the rest. When ' +
|
|
17
|
+
'stopped=true the underlying WebSocket has closed (stopped, idle-timed-out, or connection lost); check ' +
|
|
18
|
+
'errors for the reason.',
|
|
19
|
+
toolsets: ['DIAGNOSTICS', 'PWAV3', 'STOREFRONTNEXT'],
|
|
20
|
+
inputSchema: {
|
|
21
|
+
watch_id: z.string().describe('Watch id from mrt_logs_watch_start.'),
|
|
22
|
+
timeout_ms: z
|
|
23
|
+
.number()
|
|
24
|
+
.int()
|
|
25
|
+
.min(0)
|
|
26
|
+
.optional()
|
|
27
|
+
.describe('Max time to block waiting for new entries when buffer is empty. Defaults to 5000ms.'),
|
|
28
|
+
max_entries: z
|
|
29
|
+
.number()
|
|
30
|
+
.int()
|
|
31
|
+
.positive()
|
|
32
|
+
.optional()
|
|
33
|
+
.describe('Maximum entries to return per call. Defaults to 200.'),
|
|
34
|
+
},
|
|
35
|
+
async execute(args, context) {
|
|
36
|
+
const registry = getMrtLogWatchRegistry(context);
|
|
37
|
+
const watch = registry.getWatchOrThrow(args.watch_id);
|
|
38
|
+
const timeoutMs = args.timeout_ms ?? DEFAULT_TIMEOUT_MS;
|
|
39
|
+
const maxEntries = args.max_entries ?? DEFAULT_MAX_ENTRIES;
|
|
40
|
+
if (watch.buffer.length === 0 && watch.errors.length === 0 && !watch.stopped && timeoutMs > 0) {
|
|
41
|
+
await registry.waitForActivity(args.watch_id, timeoutMs);
|
|
42
|
+
}
|
|
43
|
+
const drained = registry.drain(args.watch_id, maxEntries);
|
|
44
|
+
const droppedSnapshot = watch.droppedEntries;
|
|
45
|
+
watch.droppedEntries = 0;
|
|
46
|
+
return {
|
|
47
|
+
buffered_remaining: watch.buffer.length,
|
|
48
|
+
dropped_entries: droppedSnapshot,
|
|
49
|
+
entries: drained.entries,
|
|
50
|
+
errors: drained.errors,
|
|
51
|
+
stopped: watch.stopped,
|
|
52
|
+
truncated: drained.truncated,
|
|
53
|
+
watch_id: args.watch_id,
|
|
54
|
+
};
|
|
55
|
+
},
|
|
56
|
+
formatOutput: (output) => jsonResult(output),
|
|
57
|
+
}, loadServices, serverContext);
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=mrt-logs-watch-poll.js.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { TailMrtLogsOptions, TailMrtLogsResult } from '@salesforce/b2c-tooling-sdk/operations/mrt';
|
|
2
|
+
import type { AuthStrategy } from '@salesforce/b2c-tooling-sdk/auth';
|
|
3
|
+
import type { McpTool } from '../../utils/index.js';
|
|
4
|
+
import type { Services } from '../../services.js';
|
|
5
|
+
import type { ServerContext } from '../../server-context.js';
|
|
6
|
+
export interface MrtLogsWatchStartInjections {
|
|
7
|
+
tailMrtLogs?: (options: TailMrtLogsOptions, auth: AuthStrategy) => Promise<TailMrtLogsResult>;
|
|
8
|
+
getProfile?: (options: {
|
|
9
|
+
origin?: string;
|
|
10
|
+
}, auth: AuthStrategy) => Promise<{
|
|
11
|
+
email?: string;
|
|
12
|
+
}>;
|
|
13
|
+
}
|
|
14
|
+
export declare function createMrtLogsWatchStartTool(loadServices: () => Promise<Services> | Services, serverContext?: ServerContext, injections?: MrtLogsWatchStartInjections): McpTool;
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2025, Salesforce, Inc.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2
|
|
4
|
+
* For full license text, see the license.txt file in the repo root or http://www.apache.org/licenses/LICENSE-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
import { getProfile, tailMrtLogs } from '@salesforce/b2c-tooling-sdk/operations/mrt';
|
|
8
|
+
import { createToolAdapter, jsonResult } from '../adapter.js';
|
|
9
|
+
import { getMrtLogWatchRegistry } from './mrt-log-watch-registry.js';
|
|
10
|
+
/**
|
|
11
|
+
* Case-insensitive substring match against an entry's message and raw text.
|
|
12
|
+
* Mirrors the SFCC `matchesSearch` semantics. The CLI `mrt tail-logs` command
|
|
13
|
+
* treats `search` as a regex, but MCP tool consumers get the safer substring
|
|
14
|
+
* filter (no ReDoS surface, predictable behavior).
|
|
15
|
+
*/
|
|
16
|
+
function matchesSearch(entry, search) {
|
|
17
|
+
const lower = search.toLowerCase();
|
|
18
|
+
return entry.message.toLowerCase().includes(lower) || entry.raw.toLowerCase().includes(lower);
|
|
19
|
+
}
|
|
20
|
+
function matchesLevel(entry, levels) {
|
|
21
|
+
return Boolean(entry.level && levels.has(entry.level.toUpperCase()));
|
|
22
|
+
}
|
|
23
|
+
export function createMrtLogsWatchStartTool(loadServices, serverContext, injections) {
|
|
24
|
+
const tailMrtLogsFn = injections?.tailMrtLogs ?? tailMrtLogs;
|
|
25
|
+
const getProfileFn = injections?.getProfile ?? getProfile;
|
|
26
|
+
return createToolAdapter({
|
|
27
|
+
name: 'mrt_logs_watch_start',
|
|
28
|
+
description: "Start a background tail of a Managed Runtime (MRT) environment's application logs over a WebSocket. " +
|
|
29
|
+
'Returns a watch_id immediately. MRT logs are always a live stream — there is no historical fetch — so ' +
|
|
30
|
+
'call mrt_logs_watch_start BEFORE triggering the request/SSR action you want to capture, then call ' +
|
|
31
|
+
'mrt_logs_watch_poll to drain buffered entries (it blocks up to timeout_ms). Always call ' +
|
|
32
|
+
'mrt_logs_watch_stop when done. Requires MRT project + environment (from --project/--environment flags, ' +
|
|
33
|
+
'MRT_PROJECT/MRT_ENVIRONMENT env vars, or dw.json). Only one active watch per project/environment/origin ' +
|
|
34
|
+
'— use mrt_logs_watch_list to find an existing one.',
|
|
35
|
+
toolsets: ['DIAGNOSTICS', 'PWAV3', 'STOREFRONTNEXT'],
|
|
36
|
+
requiresMrtAuth: true,
|
|
37
|
+
inputSchema: {
|
|
38
|
+
level: z
|
|
39
|
+
.array(z.string())
|
|
40
|
+
.optional()
|
|
41
|
+
.describe('Filter by log level (ERROR, WARN, INFO, DEBUG, etc.). Entries not matching are dropped before buffering.'),
|
|
42
|
+
search: z
|
|
43
|
+
.string()
|
|
44
|
+
.optional()
|
|
45
|
+
.describe('Case-insensitive substring filter applied to message and raw text as entries arrive.'),
|
|
46
|
+
},
|
|
47
|
+
async execute(args, context) {
|
|
48
|
+
const registry = getMrtLogWatchRegistry(context);
|
|
49
|
+
const project = context.mrtConfig?.project;
|
|
50
|
+
const environment = context.mrtConfig?.environment;
|
|
51
|
+
const origin = context.mrtConfig?.origin;
|
|
52
|
+
const auth = context.mrtConfig.auth;
|
|
53
|
+
if (!project) {
|
|
54
|
+
throw new Error('MRT project is required. Provide --project flag, set MRT_PROJECT, or set mrtProject in dw.json.');
|
|
55
|
+
}
|
|
56
|
+
if (!environment) {
|
|
57
|
+
throw new Error('MRT environment is required. Provide --environment flag, set MRT_ENVIRONMENT, or set mrtEnvironment in dw.json.');
|
|
58
|
+
}
|
|
59
|
+
// Fail fast on a duplicate before opening a WebSocket.
|
|
60
|
+
const existing = registry.findByKey(project, environment, origin);
|
|
61
|
+
if (existing) {
|
|
62
|
+
throw new Error(`An MRT log watch already exists for ${project}/${environment} (watch_id: "${existing.watchId}"). ` +
|
|
63
|
+
`Stop it with mrt_logs_watch_stop first, or poll the existing watch.`);
|
|
64
|
+
}
|
|
65
|
+
const levelFilter = args.level && args.level.length > 0 ? new Set(args.level.map((l) => l.toUpperCase())) : null;
|
|
66
|
+
const searchFilter = args.search;
|
|
67
|
+
// Best-effort user email for the WebSocket connection (matches the CLI).
|
|
68
|
+
let user;
|
|
69
|
+
try {
|
|
70
|
+
const profile = await getProfileFn({ origin }, auth);
|
|
71
|
+
user = profile.email;
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
// Non-fatal: proceed without user email.
|
|
75
|
+
}
|
|
76
|
+
// The callbacks need the watchId, but it is only minted by registerWatch
|
|
77
|
+
// (which itself needs the tailResult). Close over a mutable holder filled
|
|
78
|
+
// in after registration.
|
|
79
|
+
const ref = {};
|
|
80
|
+
const tailResult = await tailMrtLogsFn({
|
|
81
|
+
projectSlug: project,
|
|
82
|
+
environmentSlug: environment,
|
|
83
|
+
origin,
|
|
84
|
+
user,
|
|
85
|
+
onEntry(entry) {
|
|
86
|
+
if (!ref.id)
|
|
87
|
+
return;
|
|
88
|
+
if (levelFilter && !matchesLevel(entry, levelFilter))
|
|
89
|
+
return;
|
|
90
|
+
if (searchFilter && !matchesSearch(entry, searchFilter))
|
|
91
|
+
return;
|
|
92
|
+
registry.appendEntry(ref.id, entry);
|
|
93
|
+
},
|
|
94
|
+
onError(err) {
|
|
95
|
+
if (!ref.id)
|
|
96
|
+
return;
|
|
97
|
+
registry.appendError(ref.id, err);
|
|
98
|
+
},
|
|
99
|
+
onClose() {
|
|
100
|
+
if (!ref.id)
|
|
101
|
+
return;
|
|
102
|
+
registry.markStreamClosed(ref.id);
|
|
103
|
+
},
|
|
104
|
+
}, auth);
|
|
105
|
+
// tailMrtLogs rejects `done` on a non-clean WebSocket close. Attach a
|
|
106
|
+
// no-op catch up front so neither the registration-failure path below
|
|
107
|
+
// nor a later connection drop produces an unhandled rejection.
|
|
108
|
+
// destroyWatch awaits the same promise for real cleanup.
|
|
109
|
+
tailResult.done.catch(() => { });
|
|
110
|
+
// registerWatch re-checks the dedup key and throws on a duplicate. If two
|
|
111
|
+
// starts race past findByKey above, the loser's WebSocket is already open
|
|
112
|
+
// — stop it so it isn't orphaned (it would otherwise stream until process
|
|
113
|
+
// exit).
|
|
114
|
+
let entry;
|
|
115
|
+
try {
|
|
116
|
+
entry = registry.registerWatch({ project, environment, origin, tailResult });
|
|
117
|
+
}
|
|
118
|
+
catch (error) {
|
|
119
|
+
tailResult.stop();
|
|
120
|
+
throw error;
|
|
121
|
+
}
|
|
122
|
+
ref.id = entry.watchId;
|
|
123
|
+
return {
|
|
124
|
+
environment,
|
|
125
|
+
project,
|
|
126
|
+
started_at: new Date(entry.createdAt).toISOString(),
|
|
127
|
+
watch_id: entry.watchId,
|
|
128
|
+
};
|
|
129
|
+
},
|
|
130
|
+
formatOutput: (output) => jsonResult(output),
|
|
131
|
+
}, loadServices, serverContext);
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=mrt-logs-watch-start.js.map
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { McpTool } from '../../utils/index.js';
|
|
2
|
+
import type { Services } from '../../services.js';
|
|
3
|
+
import type { ServerContext } from '../../server-context.js';
|
|
4
|
+
export declare function createMrtLogsWatchStopTool(loadServices: () => Promise<Services> | Services, serverContext?: ServerContext): McpTool;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2025, Salesforce, Inc.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2
|
|
4
|
+
* For full license text, see the license.txt file in the repo root or http://www.apache.org/licenses/LICENSE-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
import { createToolAdapter, jsonResult } from '../adapter.js';
|
|
8
|
+
import { getMrtLogWatchRegistry } from './mrt-log-watch-registry.js';
|
|
9
|
+
export function createMrtLogsWatchStopTool(loadServices, serverContext) {
|
|
10
|
+
return createToolAdapter({
|
|
11
|
+
name: 'mrt_logs_watch_stop',
|
|
12
|
+
description: 'Stop an MRT log watch and close its WebSocket. Idempotent on already-stopped watches (returns success ' +
|
|
13
|
+
'with stopped_at). Always pair with mrt_logs_watch_start so streaming connections do not accumulate on ' +
|
|
14
|
+
'the server.',
|
|
15
|
+
toolsets: ['DIAGNOSTICS', 'PWAV3', 'STOREFRONTNEXT'],
|
|
16
|
+
inputSchema: {
|
|
17
|
+
watch_id: z.string().describe('Watch id from mrt_logs_watch_start.'),
|
|
18
|
+
},
|
|
19
|
+
async execute(args, context) {
|
|
20
|
+
const registry = getMrtLogWatchRegistry(context);
|
|
21
|
+
// Idempotent: a watch that was already stopped (and removed) returns a
|
|
22
|
+
// success response rather than throwing, so retry/cleanup paths are safe.
|
|
23
|
+
const watch = registry.getWatch(args.watch_id);
|
|
24
|
+
const totalSeen = watch?.totalEntriesSeen ?? 0;
|
|
25
|
+
if (watch) {
|
|
26
|
+
await registry.destroyWatch(args.watch_id);
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
stopped_at: new Date().toISOString(),
|
|
30
|
+
total_entries_seen: totalSeen,
|
|
31
|
+
watch_id: args.watch_id,
|
|
32
|
+
};
|
|
33
|
+
},
|
|
34
|
+
formatOutput: (output) => jsonResult(output),
|
|
35
|
+
}, loadServices, serverContext);
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=mrt-logs-watch-stop.js.map
|
|
@@ -305,14 +305,15 @@ export function generateWorkflowResponse(figmaUrl, workflowFilePath) {
|
|
|
305
305
|
export function createFigmaToComponentTool(loadServices) {
|
|
306
306
|
return createToolAdapter({
|
|
307
307
|
name: 'sfnext_start_figma_workflow',
|
|
308
|
-
description: '
|
|
308
|
+
description: '[DEPRECATED] Superseded by the storefront-next and storefront-next-figma agent-skills plugins and NOT compatible with the Storefront Next 1.0 GA release. Will be removed in a future release. ' +
|
|
309
|
+
'WORKFLOW ORCHESTRATOR: Call this tool FIRST when converting Figma designs. ' +
|
|
309
310
|
'Parses Figma URL to extract fileKey and nodeId, returns step-by-step workflow instructions ' +
|
|
310
311
|
'and parameters for subsequent tool calls. ' +
|
|
311
312
|
'CRITICAL: This is only the FIRST step. After calling this tool, you MUST continue executing ' +
|
|
312
313
|
'the complete workflow: 1) Call Figma MCP tools, 2) Discover similar components, ' +
|
|
313
314
|
'3) Call sfnext_analyze_component tool, 4) Call sfnext_match_tokens_to_theme tool, ' +
|
|
314
315
|
'5) Show both outputs to the user then implement the recommended approach.',
|
|
315
|
-
toolsets: ['
|
|
316
|
+
toolsets: ['STOREFRONTNEXT_DEPRECATED'],
|
|
316
317
|
isGA: false,
|
|
317
318
|
requiresInstance: false,
|
|
318
319
|
inputSchema: figmaToComponentSchema.shape,
|
|
@@ -76,13 +76,14 @@ export function generateComponentRecommendation(input) {
|
|
|
76
76
|
export function createGenerateComponentTool(loadServices) {
|
|
77
77
|
return createToolAdapter({
|
|
78
78
|
name: 'sfnext_analyze_component',
|
|
79
|
-
description: '
|
|
79
|
+
description: '[DEPRECATED] Superseded by the storefront-next and storefront-next-figma agent-skills plugins and NOT compatible with the Storefront Next 1.0 GA release. Will be removed in a future release. ' +
|
|
80
|
+
'Analyzes Figma design and discovered components to recommend component generation strategy. ' +
|
|
80
81
|
'Workflow: 1) Discover similar components using Glob/Grep/Read tools, ' +
|
|
81
82
|
'2) Call this tool with the discoveredComponents parameter, ' +
|
|
82
83
|
'3) Tool analyzes differences and recommends REUSE/EXTEND/CREATE action, ' +
|
|
83
84
|
'4) Tool provides formatted recommendation with code examples and workflow steps. ' +
|
|
84
85
|
'Call this tool AFTER retrieving Figma design data and discovering similar components.',
|
|
85
|
-
toolsets: ['
|
|
86
|
+
toolsets: ['STOREFRONTNEXT_DEPRECATED'],
|
|
86
87
|
isGA: false,
|
|
87
88
|
requiresInstance: false,
|
|
88
89
|
inputSchema: generateComponentSchema.shape,
|
|
@@ -216,12 +216,13 @@ export function mapFigmaTokensToTheme(args, workspaceRoot) {
|
|
|
216
216
|
export function createMapTokensToThemeTool(loadServices) {
|
|
217
217
|
return createToolAdapter({
|
|
218
218
|
name: 'sfnext_match_tokens_to_theme',
|
|
219
|
-
description: '
|
|
219
|
+
description: '[DEPRECATED] Superseded by the storefront-next and storefront-next-figma agent-skills plugins and NOT compatible with the Storefront Next 1.0 GA release. Will be removed in a future release. ' +
|
|
220
|
+
'Maps Figma design tokens to existing StorefrontNext theme tokens in app.css. ' +
|
|
220
221
|
'Analyzes Figma design tokens (colors, spacing, radius, etc.) and finds exact matches, ' +
|
|
221
222
|
'provides fuzzy matches with confidence scores, suggests new token names for unmatched values, ' +
|
|
222
223
|
'and recommends where to add new tokens in the CSS file. ' +
|
|
223
224
|
'Use this tool after retrieving design variables from Figma MCP to ensure components use theme tokens instead of hardcoded values.',
|
|
224
|
-
toolsets: ['
|
|
225
|
+
toolsets: ['STOREFRONTNEXT_DEPRECATED'],
|
|
225
226
|
isGA: false,
|
|
226
227
|
requiresInstance: false,
|
|
227
228
|
inputSchema: mapTokensToThemeSchema.shape,
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Storefront Next toolset for B2C Commerce.
|
|
2
|
+
* Storefront Next (deprecated) toolset for B2C Commerce.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* **DEPRECATED:** These `sfnext_*` tools are superseded by the `storefront-next`
|
|
5
|
+
* and `storefront-next-figma` agent-skills plugins and are NOT compatible with
|
|
6
|
+
* the Storefront Next 1.0 GA release. They now live in the
|
|
7
|
+
* `STOREFRONTNEXT_DEPRECATED` toolset, which is never auto-activated by project
|
|
8
|
+
* detection and is excluded from `--toolsets ALL`. To use them you must request
|
|
9
|
+
* the toolset explicitly (`--toolsets STOREFRONTNEXT_DEPRECATED`). They will be
|
|
10
|
+
* removed in a future release.
|
|
5
11
|
*
|
|
6
12
|
* **Implemented Tools:**
|
|
7
13
|
* - `sfnext_get_guidelines` - Get development guidelines and best practices
|
|
@@ -11,18 +17,12 @@
|
|
|
11
17
|
* - `sfnext_analyze_component` - Analyze design and recommend REUSE/EXTEND/CREATE
|
|
12
18
|
* - `sfnext_match_tokens_to_theme` - Match design tokens to theme
|
|
13
19
|
*
|
|
14
|
-
* Note: mrt_bundle_push is defined in the MRT toolset and appears in STOREFRONTNEXT.
|
|
15
|
-
*
|
|
16
20
|
* @module tools/storefrontnext
|
|
17
21
|
*/
|
|
18
22
|
import type { McpTool } from '../../utils/index.js';
|
|
19
23
|
import type { Services } from '../../services.js';
|
|
20
24
|
/**
|
|
21
|
-
* Creates all tools for the
|
|
22
|
-
*
|
|
23
|
-
* Note: mrt_bundle_push is defined in the MRT toolset with
|
|
24
|
-
* toolsets: ["MRT", "PWAV3", "STOREFRONTNEXT"] and will
|
|
25
|
-
* automatically appear in STOREFRONTNEXT.
|
|
25
|
+
* Creates all tools for the deprecated STOREFRONTNEXT_DEPRECATED toolset.
|
|
26
26
|
*
|
|
27
27
|
* @param loadServices - Function that loads configuration and returns Services instance
|
|
28
28
|
* @returns Array of MCP tools
|
|
@@ -10,11 +10,7 @@ import { createFigmaToComponentTool } from './figma/figma-to-component/index.js'
|
|
|
10
10
|
import { createGenerateComponentTool } from './figma/generate-component/index.js';
|
|
11
11
|
import { createMapTokensToThemeTool } from './figma/map-tokens/index.js';
|
|
12
12
|
/**
|
|
13
|
-
* Creates all tools for the
|
|
14
|
-
*
|
|
15
|
-
* Note: mrt_bundle_push is defined in the MRT toolset with
|
|
16
|
-
* toolsets: ["MRT", "PWAV3", "STOREFRONTNEXT"] and will
|
|
17
|
-
* automatically appear in STOREFRONTNEXT.
|
|
13
|
+
* Creates all tools for the deprecated STOREFRONTNEXT_DEPRECATED toolset.
|
|
18
14
|
*
|
|
19
15
|
* @param loadServices - Function that loads configuration and returns Services instance
|
|
20
16
|
* @returns Array of MCP tools
|
|
@@ -528,13 +528,14 @@ function handleAutoMode(args, workspaceRoot) {
|
|
|
528
528
|
export function createPageDesignerDecoratorTool(loadServices) {
|
|
529
529
|
return {
|
|
530
530
|
name: 'sfnext_add_page_designer_decorator',
|
|
531
|
-
description: '
|
|
531
|
+
description: '[DEPRECATED] Superseded by the storefront-next and storefront-next-figma agent-skills plugins and NOT compatible with the Storefront Next 1.0 GA release. Will be removed in a future release. ' +
|
|
532
|
+
'Adds Page Designer decorators (@Component, @AttributeDefinition, @RegionDefinition) to React components. ' +
|
|
532
533
|
'Two modes: autoMode=true for quick setup with defaults, or interactive mode via conversationContext.step. ' +
|
|
533
534
|
'Component discovery uses --project-directory flag or SFCC_PROJECT_DIRECTORY env var. ' +
|
|
534
535
|
'Auto mode: selects suitable props, infers types, generates code immediately. ' +
|
|
535
536
|
'Interactive mode: multi-step workflow (analyze → select_props → configure_attrs → configure_regions → confirm_generation).',
|
|
536
537
|
inputSchema: pageDesignerDecoratorSchema.shape,
|
|
537
|
-
toolsets: ['
|
|
538
|
+
toolsets: ['STOREFRONTNEXT_DEPRECATED'],
|
|
538
539
|
isGA: false,
|
|
539
540
|
async handler(args) {
|
|
540
541
|
try {
|
|
@@ -83,13 +83,14 @@ const DEFAULT_SECTIONS = ['quick-reference', 'data-fetching', 'components', 'tes
|
|
|
83
83
|
export function createDeveloperGuidelinesTool(loadServices) {
|
|
84
84
|
return createToolAdapter({
|
|
85
85
|
name: 'sfnext_get_guidelines',
|
|
86
|
-
description: '
|
|
86
|
+
description: '[DEPRECATED] Superseded by the storefront-next and storefront-next-figma agent-skills plugins and NOT compatible with the Storefront Next 1.0 GA release. Will be removed in a future release. ' +
|
|
87
|
+
'ESSENTIAL FIRST STEP for Storefront Next development. Returns critical architecture rules, coding standards, and best practices. ' +
|
|
87
88
|
'Use this tool FIRST before writing any Storefront Next code to understand non-negotiable patterns for React Server Components, ' +
|
|
88
89
|
'data loading, and framework constraints. Returns comprehensive guidelines by default (quick-reference + key sections); ' +
|
|
89
90
|
'supports retrieving specific topic sections. ' +
|
|
90
91
|
'CRITICAL INSTRUCTION: ALWAYS present ALL returned content in FULL - DO NOT SUMMARIZE, DO NOT ADD SUMMARIES, ' +
|
|
91
92
|
'DO NOT ADD OVERVIEWS. The returned content IS the complete answer - display it exactly as provided.',
|
|
92
|
-
toolsets: ['
|
|
93
|
+
toolsets: ['STOREFRONTNEXT_DEPRECATED'],
|
|
93
94
|
isGA: false,
|
|
94
95
|
requiresInstance: false,
|
|
95
96
|
inputSchema: {
|
|
@@ -29,7 +29,8 @@ import { generateResponse } from './response-builder.js';
|
|
|
29
29
|
export function createSiteThemingTool(loadServices) {
|
|
30
30
|
return createToolAdapter({
|
|
31
31
|
name: 'sfnext_configure_theme',
|
|
32
|
-
description: '
|
|
32
|
+
description: '[DEPRECATED] Superseded by the storefront-next and storefront-next-figma agent-skills plugins and NOT compatible with the Storefront Next 1.0 GA release. Will be removed in a future release. ' +
|
|
33
|
+
'⚠️ MANDATORY: Call this tool FIRST before implementing any theming changes. ' +
|
|
33
34
|
'Provides theming guidelines, questions, and automatic validation. ' +
|
|
34
35
|
'CRITICAL RULES: Call immediately when user requests theming (even if colors/fonts provided). ' +
|
|
35
36
|
'NEVER implement without calling this tool first. NEVER skip question-answer workflow. ' +
|
|
@@ -38,7 +39,7 @@ export function createSiteThemingTool(loadServices) {
|
|
|
38
39
|
'DEFAULT FILES: theming-questions, theming-validation, theming-accessibility. ' +
|
|
39
40
|
'Use fileKeys to add custom files. ' +
|
|
40
41
|
'WORKFLOW: Call tool → Ask questions → Call with colorMapping (validation) → Present findings → Wait confirmation → Implement',
|
|
41
|
-
toolsets: ['
|
|
42
|
+
toolsets: ['STOREFRONTNEXT_DEPRECATED'],
|
|
42
43
|
isGA: false,
|
|
43
44
|
requiresInstance: false,
|
|
44
45
|
inputSchema: {
|
|
@@ -5,11 +5,22 @@ 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"];
|
|
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"];
|
|
9
20
|
/**
|
|
10
21
|
* Valid toolset names including the special "ALL" value.
|
|
11
22
|
*/
|
|
12
|
-
export declare const VALID_TOOLSET_NAMES: readonly ["ALL", "CARTRIDGES", "DIAGNOSTICS", "MRT", "PWAV3", "SCAPI", "STOREFRONTNEXT"];
|
|
23
|
+
export declare const VALID_TOOLSET_NAMES: readonly ["ALL", "CARTRIDGES", "DIAGNOSTICS", "MRT", "PWAV3", "SCAPI", "STOREFRONTNEXT", "STOREFRONTNEXT_DEPRECATED"];
|
|
13
24
|
/**
|
|
14
25
|
* Type representing a valid toolset name.
|
|
15
26
|
*/
|
package/dist/utils/constants.js
CHANGED
|
@@ -10,7 +10,26 @@ export const ALL_TOOLSETS = 'ALL';
|
|
|
10
10
|
/**
|
|
11
11
|
* Available toolsets that can be enabled.
|
|
12
12
|
*/
|
|
13
|
-
export const TOOLSETS = [
|
|
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'];
|
|
14
33
|
/**
|
|
15
34
|
* Valid toolset names including the special "ALL" value.
|
|
16
35
|
*/
|
package/oclif.manifest.json
CHANGED
|
@@ -387,7 +387,7 @@
|
|
|
387
387
|
"type": "boolean"
|
|
388
388
|
},
|
|
389
389
|
"toolsets": {
|
|
390
|
-
"description": "Toolsets to enable (comma-separated). Options: all, CARTRIDGES, DIAGNOSTICS, MRT, PWAV3, SCAPI, STOREFRONTNEXT",
|
|
390
|
+
"description": "Toolsets to enable (comma-separated). Options: all, CARTRIDGES, DIAGNOSTICS, MRT, PWAV3, SCAPI, STOREFRONTNEXT, STOREFRONTNEXT_DEPRECATED",
|
|
391
391
|
"env": "SFCC_TOOLSETS",
|
|
392
392
|
"name": "toolsets",
|
|
393
393
|
"hasDynamicHelp": false,
|
|
@@ -420,5 +420,5 @@
|
|
|
420
420
|
"enableJsonFlag": false
|
|
421
421
|
}
|
|
422
422
|
},
|
|
423
|
-
"version": "1.
|
|
423
|
+
"version": "1.3.0"
|
|
424
424
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforce/b2c-dx-mcp",
|
|
3
3
|
"description": "MCP server for B2C Commerce developer experience tools",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.3.0",
|
|
5
5
|
"author": "Salesforce",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"repository": "SalesforceCommerceCloud/b2c-developer-tooling",
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
"yaml": "2.8.1",
|
|
81
81
|
"postcss": "8.5.6",
|
|
82
82
|
"zod": "3.25.76",
|
|
83
|
-
"@salesforce/b2c-tooling-sdk": "1.
|
|
83
|
+
"@salesforce/b2c-tooling-sdk": "1.14.0"
|
|
84
84
|
},
|
|
85
85
|
"devDependencies": {
|
|
86
86
|
"@eslint/compat": "^1",
|
|
@@ -99,7 +99,7 @@
|
|
|
99
99
|
"eslint-config-prettier": "^10",
|
|
100
100
|
"eslint-plugin-header": "^3.1.1",
|
|
101
101
|
"eslint-plugin-prettier": "^5.5.5",
|
|
102
|
-
"mocha": "^
|
|
102
|
+
"mocha": "^11",
|
|
103
103
|
"oclif": "^4",
|
|
104
104
|
"prettier": "^3.8.3",
|
|
105
105
|
"shx": "^0.3.3",
|
|
@@ -125,6 +125,7 @@
|
|
|
125
125
|
"pretest": "tsc --noEmit -p test",
|
|
126
126
|
"test": "c8 mocha --forbid-only --ignore 'test/e2e/**' \"test/**/*.test.ts\"",
|
|
127
127
|
"test:ci": "c8 mocha --forbid-only --reporter json --reporter-option output=test-results.json --ignore 'test/e2e/**' \"test/**/*.test.ts\"",
|
|
128
|
+
"test:ci:win": "c8 --check-coverage=false mocha --forbid-only --reporter json --reporter-option output=test-results.json --ignore 'test/e2e/**' \"test/**/*.test.ts\"",
|
|
128
129
|
"test:agent": "mocha --forbid-only --reporter min --ignore 'test/e2e/**' \"test/**/*.test.ts\"",
|
|
129
130
|
"test:e2e": "mocha --forbid-only \"test/e2e/**/*.test.ts\"",
|
|
130
131
|
"test:e2e:ci": "mocha --forbid-only --reporter json --reporter-option output=test-results-e2e.json \"test/e2e/**/*.test.ts\"",
|