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

b2c_tooling_sdk.operations.ods ​

ODS (On-Demand Sandbox) operations.

Mirrors src/operations/ods/index.ts.

Classes ​

BuildSandboxSettingsOptions ​

python
class BuildSandboxSettingsOptions

Options for build_sandbox_settings.

Fields

NameTypeDefault
client_idstr | NoneNone
ocapi_settingslist[dict[str, Any]] | NoneNone
webdav_settingslist[dict[str, Any]] | NoneNone

CloneBatchFailedError ​

python
class CloneBatchFailedError(Exception)

Raised when one or more clones in a batch enter the FAILED state.

All clones in the batch reached a terminal state, but at least one of them failed.

CloneBatchMemberStatus ​

python
class CloneBatchMemberStatus

Status of a single clone within a batch, as observed on one poll tick.

Fields

NameTypeDefault
clone_idstr
statusCloneState
progress_percentageint | NoneNone

CloneBatchPollingError ​

python
class CloneBatchPollingError(Exception)

Raised when an API request to fetch the status of a clone in a batch fails.

CloneBatchPollingTimeoutError ​

python
class CloneBatchPollingTimeoutError(Exception)

Raised when a batch of sandbox clones does not all reach a terminal state within the timeout.

CloneFailedError ​

python
class CloneFailedError(Exception)

Raised when a sandbox clone operation enters the FAILED state.

ClonePollingError ​

python
class ClonePollingError(Exception)

Raised when an API request to fetch clone status fails.

ClonePollingTimeoutError ​

python
class ClonePollingTimeoutError(Exception)

Raised when a sandbox clone operation does not complete within the configured timeout while polling.

SandboxNotFoundError ​

python
class SandboxNotFoundError(Exception)

Raised when a sandbox cannot be found by its friendly identifier.

SandboxPollingError ​

python
class SandboxPollingError(Exception)

Raised when fetching sandbox status fails during polling.

SandboxPollingTimeoutError ​

python
class SandboxPollingTimeoutError(Exception)

Raised when a sandbox does not reach its target state within the specified timeout period.

SandboxTerminalStateError ​

python
class SandboxTerminalStateError(Exception)

Raised when a sandbox reaches a terminal error state (failed or deleted) during polling.

WaitForCloneOptions ​

python
class WaitForCloneOptions

Configuration options for wait_for_clone polling behavior.

Fields

NameTypeDefault
sandbox_idstr
clone_idstr
poll_interval_secondsfloat
timeout_secondsfloat
on_pollCallable[[WaitForClonePollInfo], None] | NoneNone
sleepCallable[[float], Awaitable[None]]_default_sleep

WaitForClonePollInfo ​

python
class WaitForClonePollInfo

Information passed to the on_poll callback on each clone status poll.

Fields

NameTypeDefault
sandbox_idstr
clone_idstr
elapsed_secondsfloat
statusCloneState
progress_percentageint | NoneNone

WaitForClonesOptions ​

python
class WaitForClonesOptions

Configuration options for wait_for_clones batch polling behavior.

Fields

NameTypeDefault
sandbox_idstr
clone_idslist[str]
poll_interval_secondsfloat
timeout_secondsfloat
on_pollCallable[[WaitForClonesPollInfo], None] | NoneNone
sleepCallable[[float], Awaitable[None]]_default_sleep

WaitForClonesPollInfo ​

python
class WaitForClonesPollInfo

Information passed to the on_poll callback on each poll tick while waiting for a batch of clones.

Fields

NameType
sandbox_idstr
elapsed_secondsfloat
completedint
totalint
cloneslist[CloneBatchMemberStatus]

WaitForSandboxOptions ​

python
class WaitForSandboxOptions

Configuration options for wait_for_sandbox sandbox state polling.

Fields

NameTypeDefault
sandbox_idstr
target_stateSandboxState
poll_interval_secondsfloat
timeout_secondsfloat
on_pollCallable[[WaitForSandboxPollInfo], None] | NoneNone
sleepCallable[[float], Awaitable[None]]_default_sleep

WaitForSandboxPollInfo ​

python
class WaitForSandboxPollInfo

Information provided to the on_poll callback on each poll during sandbox state monitoring.

Fields

NameType
sandbox_idstr
elapsed_secondsfloat
stateSandboxState

Functions ​

build_sandbox_settings ​

python
def build_sandbox_settings(options: BuildSandboxSettingsOptions) -> dict[str, Any] | None

Build the sandbox settings object granting OCAPI and WebDAV permissions to a client ID.

New sandboxes have no API permissions by default, so the client used to create the sandbox (e.g. for code deployment) must be granted access explicitly or subsequent operations will fail with authorization errors.

When ocapi_settings/webdav_settings are provided they fully replace the defaults. Otherwise, when a client_id is provided, the client is granted the default resources/permissions.

:example:

python
>>> settings = build_sandbox_settings(BuildSandboxSettingsOptions(client_id=config.values.client_id))
>>> await ods_client.post("/sandboxes", {"body": {"realm": realm, "ttl": ttl, "settings": settings}})

Parameters

NameTypeDescription
optionsBuildSandboxSettingsOptionsThe settings to build.

Returns: The settings dict, or None when there is nothing to set (no client ID and no custom settings).

is_friendly_sandbox_id ​

python
def is_friendly_sandbox_id(value: str) -> bool

Check if a string matches the friendly sandbox ID format (realm-instance or realm_instance).

Parameters

NameTypeDescription
valuestrThe string to check.

Returns: True if the value matches the friendly format.

is_uuid ​

python
def is_uuid(value: str) -> bool

Check if a string is a valid UUID.

Parameters

NameTypeDescription
valuestrThe string to check.

Returns: True if the value is a valid UUID.

parse_friendly_sandbox_id ​

python
def parse_friendly_sandbox_id(value: str) -> ParsedFriendlySandboxId | None

Parse a friendly sandbox ID into its realm and instance components.

Parameters

NameTypeDescription
valuestrThe friendly ID to parse (e.g., "abcd-123" or "abcd_123").

Returns: The parsed realm/instance, or None if not a valid friendly ID.

resolve_sandbox_id ​

python
async def resolve_sandbox_id(client: OdsClient, identifier: str) -> str

Resolve a sandbox identifier to a UUID.

If the identifier is already a UUID, it is returned directly without making an API call. If the identifier is a friendly format (realm-instance), it queries the ODS API to find the matching sandbox and returns its UUID.

:example:

python
>>> # UUID is returned directly
>>> await resolve_sandbox_id(client, "abc12345-1234-1234-1234-abc123456789")
'abc12345-1234-1234-1234-abc123456789'
>>> # Friendly ID is looked up
>>> await resolve_sandbox_id(client, "zzzv-123")
'abc12345-1234-1234-1234-abc123456789'  # actual UUID from API

Parameters

NameTypeDescription
clientOdsClientThe ODS API client.
identifierstrSandbox identifier (UUID or friendly format like "abcd-123").

Returns: The sandbox UUID.

Raises

Attributes ​

DEFAULT_OCAPI_RESOURCES ​

python
DEFAULT_OCAPI_RESOURCES: list[dict[str, Any]] = ...

DEFAULT_WEBDAV_PERMISSIONS ​

python
DEFAULT_WEBDAV_PERMISSIONS: list[dict[str, Any]] = [{'path': '/impex', 'operations': ['read_write']}, {'path': '/cartridges', 'operations': ['read_write']}, {'path': '/static', 'operations': ['read_write']}]

CloneState ​

python
CloneState = str

SandboxState ​

python
SandboxState = str