Skip to content

Commit c045eec

Browse files
Feature/mcp cartridge deploy implementation (#114)
* feat(mcp): implement Cartridge Deploy MCP Tool * add patrick to code owners * remove delete option from MCP tool cartridge deploy * update readme earl access * update mcp tool description text
1 parent 0d29262 commit c045eec

File tree

4 files changed

+446
-51
lines changed

4 files changed

+446
-51
lines changed

.github/CODEOWNERS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
#GUSINFO:CC Cosmos,B2C CLI and Developer Tools
22
* @clavery
3-
/packages/b2c-dx-mcp/ @yhsieh1
3+
/packages/b2c-dx-mcp/ @yhsieh1 @patricksullivansf

packages/b2c-dx-mcp/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -237,15 +237,15 @@ Use `--toolsets all` to enable all toolsets, or select specific ones with `--too
237237
238238
#### CARTRIDGES
239239
Cartridge development, deployment, and code version management.
240-
- **Status:** 🚧 Placeholder
240+
- **Status:** 🚧 Early Access
241241

242242
| Tool | Description |
243243
|------|-------------|
244244
| `cartridge_deploy` | Deploy cartridges to a B2C Commerce instance |
245245

246246
#### MRT
247247
Managed Runtime operations for PWA Kit and Storefront Next deployments.
248-
- **Status:** 🚧 Placeholder
248+
- **Status:** 🚧 Early Access
249249

250250
| Tool | Description |
251251
|------|-------------|

packages/b2c-dx-mcp/src/tools/cartridges/index.ts

Lines changed: 72 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,16 @@
99
*
1010
* This toolset provides MCP tools for cartridge and code version management.
1111
*
12-
* > ⚠️ **PLACEHOLDER - ACTIVE DEVELOPMENT**
13-
* > This tool is a placeholder implementation that returns mock responses.
14-
* > Actual implementation is coming soon. Use `--allow-non-ga-tools` flag to enable.
15-
*
1612
* @module tools/cartridges
1713
*/
1814

1915
import {z} from 'zod';
2016
import type {McpTool} from '../../utils/index.js';
2117
import type {Services} from '../../services.js';
2218
import {createToolAdapter, jsonResult} from '../adapter.js';
19+
import {findAndDeployCartridges} from '@salesforce/b2c-tooling-sdk/operations/code';
20+
import type {DeployResult, DeployOptions} from '@salesforce/b2c-tooling-sdk/operations/code';
21+
import type {B2CInstance} from '@salesforce/b2c-tooling-sdk';
2322
import {getLogger} from '@salesforce/b2c-tooling-sdk/logging';
2423

2524
/**
@@ -32,21 +31,16 @@ interface CartridgeDeployInput {
3231
cartridges?: string[];
3332
/** Exclude these cartridge names */
3433
exclude?: string[];
35-
/** Delete existing cartridges before upload */
36-
delete?: boolean;
3734
/** Reload code version after deploy */
3835
reload?: boolean;
3936
}
4037

4138
/**
42-
* Output type for cartridge_deploy tool (placeholder).
39+
* Optional dependency injections for testing.
4340
*/
44-
interface CartridgeDeployOutput {
45-
tool: string;
46-
status: string;
47-
message: string;
48-
input: CartridgeDeployInput;
49-
timestamp: string;
41+
interface CartridgeToolInjections {
42+
/** Mock findAndDeployCartridges function for testing */
43+
findAndDeployCartridges?: (instance: B2CInstance, directory: string, options: DeployOptions) => Promise<DeployResult>;
5044
}
5145

5246
/**
@@ -56,58 +50,87 @@ interface CartridgeDeployOutput {
5650
* 1. Finds cartridges by `.project` files in the specified directory
5751
* 2. Creates a zip archive of all cartridge directories
5852
* 3. Uploads the zip to WebDAV and triggers server-side unzip
59-
* 4. Optionally deletes existing cartridges before upload
60-
* 5. Optionally reloads the code version after deploy
53+
* 4. Optionally reloads the code version after deploy
6154
*
6255
* @param services - MCP services
56+
* @param injections - Optional dependency injections for testing
6357
* @returns The cartridge_deploy tool
6458
*/
65-
function createCartridgeDeployTool(services: Services): McpTool {
66-
return createToolAdapter<CartridgeDeployInput, CartridgeDeployOutput>(
59+
function createCartridgeDeployTool(services: Services, injections?: CartridgeToolInjections): McpTool {
60+
const findAndDeployCartridgesFn = injections?.findAndDeployCartridges || findAndDeployCartridges;
61+
return createToolAdapter<CartridgeDeployInput, DeployResult>(
6762
{
6863
name: 'cartridge_deploy',
69-
description: '[PLACEHOLDER] Deploy cartridges to a B2C Commerce instance',
64+
description:
65+
'Finds and deploys cartridges to a B2C Commerce instance via WebDAV. ' +
66+
'Searches the directory for cartridges (by .project files), applies include/exclude filters, ' +
67+
'creates a zip archive, uploads via WebDAV, and optionally reloads the code version. ' +
68+
'Use this tool to deploy custom code cartridges for SFRA or other B2C Commerce code. ' +
69+
'Requires the instance to have a code version configured.',
7070
toolsets: ['CARTRIDGES'],
7171
isGA: false,
7272
requiresInstance: true,
7373
inputSchema: {
7474
directory: z
7575
.string()
7676
.optional()
77-
.describe('Path to directory containing cartridges (default: current directory)'),
78-
cartridges: z.array(z.string()).optional().describe('Only deploy these cartridge names'),
79-
exclude: z.array(z.string()).optional().describe('Exclude these cartridge names'),
80-
delete: z.boolean().optional().describe('Delete existing cartridges before upload'),
81-
reload: z.boolean().optional().describe('Reload code version after deploy'),
77+
.describe(
78+
'Path to directory to search for cartridges. Defaults to current working directory if not specified. ' +
79+
'The tool will recursively search this directory for .project files to identify cartridges.',
80+
),
81+
cartridges: z
82+
.array(z.string())
83+
.optional()
84+
.describe(
85+
'Array of cartridge names to include in the deployment. If not specified, all cartridges found in the directory are deployed. ' +
86+
'Use this to selectively deploy specific cartridges when you have multiple cartridges but only want to update some.',
87+
),
88+
exclude: z
89+
.array(z.string())
90+
.optional()
91+
.describe(
92+
'Array of cartridge names to exclude from the deployment. Use this to skip deploying certain cartridges, ' +
93+
'such as third-party or unchanged cartridges. Applied after the include filter.',
94+
),
95+
reload: z
96+
.boolean()
97+
.optional()
98+
.describe(
99+
'Whether to reload (re-activate) the code version after deployment. ' +
100+
'Set to true to make the deployed code immediately active on the instance. ' +
101+
'Defaults to false. Use this when you want changes to take effect right away.',
102+
),
82103
},
83104
async execute(args, context) {
84-
// Placeholder implementation
85-
const timestamp = new Date().toISOString();
105+
// Get instance from context (guaranteed by adapter when requiresInstance is true)
106+
const instance = context.b2cInstance!;
86107

87-
// TODO: Remove this log when implementing
108+
// Default directory to current directory
109+
const directory = args.directory || '.';
110+
111+
// Parse options
112+
const options: DeployOptions = {
113+
include: args.cartridges,
114+
exclude: args.exclude,
115+
reload: args.reload,
116+
};
117+
118+
// Log all computed variables before deploying
88119
const logger = getLogger();
89-
logger.debug({context}, 'cartridge_deploy context');
120+
logger.debug(
121+
{
122+
directory,
123+
include: options.include,
124+
exclude: options.exclude,
125+
reload: options.reload,
126+
},
127+
'[Cartridges] Deploying cartridges with computed options',
128+
);
90129

91-
// TODO: When implementing, use context.b2cInstance:
92-
// import { findAndDeployCartridges } from '@salesforce/b2c-tooling-sdk/operations/code';
93-
//
94-
// const directory = args.directory || '.';
95-
// const result = await findAndDeployCartridges(context.b2cInstance!, directory, {
96-
// include: args.cartridges,
97-
// exclude: args.exclude,
98-
// delete: args.delete,
99-
// reload: args.reload,
100-
// });
101-
// return result;
130+
// Deploy cartridges
131+
const result = await findAndDeployCartridgesFn(instance, directory, options);
102132

103-
return {
104-
tool: 'cartridge_deploy',
105-
status: 'placeholder',
106-
message:
107-
"This is a placeholder implementation for 'cartridge_deploy'. The actual implementation is coming soon.",
108-
input: args,
109-
timestamp,
110-
};
133+
return result;
111134
},
112135
formatOutput: (output) => jsonResult(output),
113136
},
@@ -119,8 +142,9 @@ function createCartridgeDeployTool(services: Services): McpTool {
119142
* Creates all tools for the CARTRIDGES toolset.
120143
*
121144
* @param services - MCP services
145+
* @param injections - Optional dependency injections for testing
122146
* @returns Array of MCP tools
123147
*/
124-
export function createCartridgesTools(services: Services): McpTool[] {
125-
return [createCartridgeDeployTool(services)];
148+
export function createCartridgesTools(services: Services, injections?: CartridgeToolInjections): McpTool[] {
149+
return [createCartridgeDeployTool(services, injections)];
126150
}

0 commit comments

Comments
 (0)