Install AI Tools

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

Claude

Using Claude Desktop? See Claude Desktop (Cowork) setup.

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.

Codex/ChatGPT

Using the ChatGPT desktop app (ChatGPT Work)? See ChatGPT Work setup.

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. Codex plugins also work in ChatGPT Work.

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.

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 ​