Install AI Tools

B2C Commerce tools, documentation, and skills for your assistant.

Claude

Install the plugin Recommended

bash
claude plugin marketplace add SalesforceCommerceCloud/b2c-developer-tooling
claude plugin install b2c-dx-mcp@b2c-developer-tooling

Start a new Claude Code session. To install for the current project only, run it from your project directory with --scope project.

Manual MCP setup
bash
claude mcp add --transport stdio --scope user b2c-dx-mcp -- npx -y @salesforce/b2c-dx-mcp@latest

Start a new session. To configure the current project only, run it from your project directory with --scope project. See Claude Code MCP setup.

Claude Desktop setup

Codex

Install the plugin Recommended

bash
codex plugin marketplace add SalesforceCommerceCloud/b2c-developer-tooling
codex plugin add b2c-dx-mcp@b2c-developer-tooling

Start a new Codex session in your project. This setup also works with the Codex IDE extension and the ChatGPT Work desktop app.

Manual MCP setup
bash
codex mcp add b2c-dx-mcp -- npx -y @salesforce/b2c-dx-mcp@latest

Or add this to ~/.codex/config.toml (or $CODEX_HOME/config.toml if customized):

toml
[mcp_servers.b2c-dx-mcp]
command = "npx"
args = ["-y", "@salesforce/b2c-dx-mcp@latest"]

Start a new session. See Codex MCP configuration.

ChatGPT online setup

VS Code

Install the plugin Recommended

  1. Open the Command Palette (Cmd/Ctrl+Shift+P) and run Chat: Install Plugin from Source.
  2. Enter SalesforceCommerceCloud/b2c-developer-tooling.
  3. Select b2c-dx-mcp and follow the installation prompts.
  4. Start a new chat in GitHub Copilot.
Manual MCP setup

Add this to .vscode/mcp.json in your workspace:

json
{
  "servers": {
    "b2c-dx-mcp": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@salesforce/b2c-dx-mcp@latest"]
    }
  }
}

See VS Code MCP setup.

Copilot CLI setup

Cursor

Reload the MCP server in Cursor after installation.

Manual MCP setup

Add this to .cursor/mcp.json in your project:

json
{
  "mcpServers": {
    "b2c-dx-mcp": {
      "command": "npx",
      "args": ["-y", "@salesforce/b2c-dx-mcp@latest"]
    }
  }
}

For all projects, use ~/.cursor/mcp.json instead.

See Cursor's MCP documentation.

OpenCode

Add this to opencode.json in your project:

json
{
  "mcp": {
    "b2c-dx-mcp": {
      "type": "local",
      "command": ["npx", "-y", "@salesforce/b2c-dx-mcp@latest"],
      "enabled": true
    }
  }
}

Restart OpenCode. For all projects, use ~/.config/opencode/opencode.json. See OpenCode MCP setup.

Gemini

Run:

bash
gemini mcp add --scope user b2c-dx-mcp -- npx -y @salesforce/b2c-dx-mcp@latest

Start a new Gemini CLI session. To configure the current project only, run it from your project directory with --scope project. See Gemini CLI MCP setup.

No separate skills plugins needed.

Other clients and manual setup →
Skip to content
View as Markdown
View as Markdown

Debug Commands ​

Commands for connecting to the B2C Commerce Script Debugger API (SDAPI) to set breakpoints, inspect variables, and step through server-side code.

  • b2c debug — Debug Adapter Protocol (DAP) adapter for IDE integrations (VS Code, JetBrains, etc.).
  • b2c debug cli — interactive terminal REPL, or JSONL-over-stdio RPC mode for headless scripts and agents.

Authentication ​

The script debugger uses Basic auth (Business Manager username and password). OAuth credentials are not sufficient. Provide credentials via any of:

  • --username / --password flags
  • SFCC_USERNAME / SFCC_PASSWORD environment variables
  • username / password fields in dw.json

The script debugger must also be enabled on the instance: Business Manager > Administration > Development Configuration > Script Debugger > Enable.

See the Authentication Guide for details.


b2c debug ​

The b2c debug command launches a Debug Adapter Protocol (DAP) adapter that bridges your IDE to the B2C Commerce script debugger. It's designed to be invoked by an IDE over stdio, not run directly in a shell.

Usage ​

bash
b2c debug [--cartridge-path <PATH>] [--client-id <ID>]

Flags ​

FlagDescriptionDefault
--cartridge-pathPath to your cartridges directory. The adapter recursively discovers cartridges under this path and maps them to the running instance..
--client-idClient ID reported to the B2C script debugger API. Useful when multiple debug sessions share an instance.b2c-cli

Inherits the global instance and authentication flags (--server, --username, --password, etc.).

Examples ​

bash
# Run from a project root with cartridges in ./cartridges or ./
b2c debug

# Point at an explicit cartridges directory
b2c debug --cartridge-path ./cartridges

# Use a non-default debugger client ID
b2c debug --client-id my-debugger

IDE Integration ​

Most IDEs spawn DAP adapters automatically based on a launch configuration. The adapter speaks DAP over stdin/stdout, so direct shell invocation will appear to hang — that's expected. Configure your IDE's debug launcher to invoke b2c debug and supply the appropriate environment.

Notes ​

  • A warning is emitted if no cartridges are found at --cartridge-path.
  • Source maps are derived from the discovered cartridge layout; ensure your local cartridge tree matches what's deployed to the instance, otherwise breakpoints may not bind.
  • The adapter exits when its stdin stream closes.

b2c debug cli ​

Start an interactive CLI debug session with a REPL interface. Provides a terminal-based debugging experience without requiring a DAP client. Add --rpc to switch to JSONL-over-stdio mode for headless scripts and agents.

Usage ​

bash
b2c debug cli [--cartridge-path <PATH>] [--client-id <ID>] [--rpc]

Flags ​

FlagDescriptionDefault
--cartridge-pathPath to directory containing cartridges.
--client-idClient ID for the debugger APIb2c-cli
--rpcRun in RPC mode (JSONL over stdin/stdout)false

Inherits the global instance and authentication flags.

REPL Commands ​

CommandAliasDescription
break <file>:<line> [if <cond>]bSet breakpoint
breakpointsblList active breakpoints
delete <id>dDelete breakpoint
continuecResume current thread
stepsStep over
stepinsiStep into
stepoutsoStep out
stackbtShow call stack
frame <n>fSelect stack frame
varsvShow variables in current frame
members <path>mExpand object members
eval <expr>eEvaluate expression
threadstList known threads
thread <id>Switch to thread
helphShow commands
quitqDisconnect and exit

Examples ​

bash
# Start interactive debugger
b2c debug cli

# Specify cartridge directory
b2c debug cli --cartridge-path ./cartridges

# Use a custom client ID (for concurrent sessions)
b2c debug cli --client-id my-session

# Start in RPC mode for headless scripts
b2c debug cli --rpc

Interactive Session Example ​

debug> break Cart.js:42
Breakpoint #1 set at ./cartridges/app_storefront/cartridge/controllers/Cart.js:42

debug> break Checkout.js:100 if basket.totalGrossPrice > 100
Breakpoint #2 set at ./cartridges/app_storefront/cartridge/controllers/Checkout.js:100

● Thread 5 halted at ./cartridges/app_storefront/cartridge/controllers/Cart.js:42 in show()

debug> vars
  request: dw.system.Request = [object Request] [local]
  basket: dw.order.Basket = [object Basket] [local]

debug> eval basket.productLineItems.length
3

debug> stack
  → #0  show  ./cartridges/app_storefront/cartridge/controllers/Cart.js:42
    #1  execute  /app_storefront/cartridge/controllers/Cart.js:1

debug> continue
Thread 5 resumed.

RPC Mode ​

When started with --rpc, the debug CLI runs as a JSONL-over-stdio RPC server. This enables headless scripts, agents, and other tools to drive the debugger programmatically.

Protocol ​

  • Input (stdin): One JSON object per line (JSONL)
  • Output (stdout): One JSON object per line — either a response or an async event

Request Format ​

json
{"id": 1, "command": "set_breakpoints", "args": {"breakpoints": [{"file": "Cart.js", "line": 42}]}}
FieldTypeDescription
idnumber or stringOptional. Echoed back in the response for correlation.
commandstringRequired. The command to execute.
argsobjectOptional. Command-specific arguments.

Response Format ​

json
{"id": 1, "result": {"breakpoints": [{"id": 1, "file": "Cart.js", "line": 42, "script_path": "/app_storefront/cartridge/controllers/Cart.js"}]}}

On error:

json
{"id": 1, "error": "No thread selected. Wait for a thread_stopped event."}

Event Format ​

Events are emitted asynchronously (not in response to a command):

json
{"event": "ready", "data": {}}
{"event": "thread_stopped", "data": {"thread_id": 5, "location": {"file": "Cart.js", "line": 42, "function_name": "show", "script_path": "/app_storefront/cartridge/controllers/Cart.js"}}}

Available Commands ​

CommandArgsDescription
set_breakpointsbreakpoints: [{file, line, condition?}]Replace all breakpoints
list_breakpointsList current breakpoints
continuethread_id?Resume a halted thread
step_overthread_id?Step to next line
step_intothread_id?Step into function call
step_outthread_id?Step out of function
get_stackthread_id?Get call stack frames
get_variablesthread_id?, frame_index?, scope?, object_path?Get variables
evaluateexpression, thread_id?, frame_index?Evaluate expression
list_threadsList known threads
select_threadthread_idSwitch current thread
select_frameindexSwitch current frame

When thread_id is omitted, the last thread that halted is used.

Events ​

EventDescription
readyEmitted once after connection is established
thread_stoppedA thread hit a breakpoint or step completed

Example Session (Python) ​

python
import subprocess, json

proc = subprocess.Popen(
    ["b2c", "debug", "cli", "--rpc"],
    stdin=subprocess.PIPE, stdout=subprocess.PIPE,
    text=True, bufsize=1
)

def send(cmd, args=None, id=None):
    msg = {"command": cmd}
    if args: msg["args"] = args
    if id is not None: msg["id"] = id
    proc.stdin.write(json.dumps(msg) + "\n")
    proc.stdin.flush()

def recv():
    return json.loads(proc.stdout.readline())

# Wait for ready
assert recv()["event"] == "ready"

# Set a breakpoint
send("set_breakpoints", {"breakpoints": [{"file": "Cart.js", "line": 42}]}, id=1)
response = recv()  # {"id": 1, "result": {...}}

# Wait for breakpoint hit (trigger a request on the instance)
event = recv()  # {"event": "thread_stopped", "data": {...}}

# Inspect state
send("get_stack", id=2)
stack = recv()

send("get_variables", id=3)
variables = recv()

# Continue execution
send("continue", id=4)
recv()

See Also ​