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 --scope project

Start a new Claude Code session in your project. Use --scope user instead for all projects.

Manual MCP setup

From your project directory:

bash
claude mcp add --transport stdio --scope project b2c-dx-mcp -- npx -y @salesforce/b2c-dx-mcp@latest

Start a new session. Use --scope user instead for all projects. 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

From your project directory, run:

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

Start a new Gemini CLI session. Use --scope user instead for all projects. 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