38 KiB
MCP Server Management Reference
Register, configure, and manage Model Context Protocol (MCP) servers in the
Salesforce API Catalog using the sf agent mcp CLI commands. This reference
backs the Manage MCP Servers task domain in SKILL.md.
MCP servers expose assets — tools, prompts, and resources — that become available as agent actions once whitelisted. This reference covers server registration, lifecycle management, and interactive asset whitelisting.
Requires: sf CLI with the agent mcp plugin installed. Verify with
sf help agent mcp. If the command is missing, check sf version, run
sf update, and confirm plugin availability with sf plugins.
Developer preview: Every sf agent mcp command is currently in developer
preview. Each response includes a warnings array containing a preview notice
("This command is currently in developer preview..."). Parse result as usual
and ignore the warning for automation, but be aware flag/output shapes may change.
ID formats (observed): Server IDs use the 0Le prefix (e.g. 0LeSB000000JoFd),
and asset IDs use the 1XO prefix (e.g. 1XOSB0000008riJ). The 0XSxx…/0YSxx…
placeholders in older examples are illustrative only.
Core Principles
- Always
--json— Include--jsonon everysf agent mcpcommand to get structured output. (Consistent with Rule 1 inSKILL.md.) - Verify target org — Before any operation, confirm a target org is set with
sf config get target-org --json. If none, ask the user to runsf config set target-org <alias>. (Consistent with Rule 2.) - Interactive approval — When whitelisting tools, display metadata for each tool individually and wait for user approval before activating.
- Security first — For OAuth servers, handle client secrets securely (stdin piping) and warn about credential exposure. Flag destructive or broadly-scoped tools before activation.
Task Workflows
1. Register a New MCP Server
When the user wants to register/create/add an MCP server:
Required Information
Gather from the user (ask if not provided):
- Server name (
-n, --name) — Unique identifier - Server URL (
--server-url) — Endpoint URL - Target org (
-o, --target-org) — Org alias or username - Label (optional,
--label) — Human-readable display name - Description (optional,
--description) — Server purpose - Authentication type (
--auth-type) —NO_AUTH(default) orOAUTH
If --auth-type OAUTH, also gather:
- Identity provider (
--identity-provider) - Client ID (
--client-id) - Client secret (
--client-secret) — Handle securely via stdin - Scope (
--scope)
Execution Steps
-
Verify target org is set
sf config get target-org --jsonIf no target org, ask user to set one with
sf config set target-org <alias> -
Gather required information — Ask for any missing required fields
-
Create the server
NO_AUTH example:
sf agent mcp create -n MyServer --server-url https://mcp.example.com/mcp -o myOrg --jsonOAUTH example (secure client secret handling):
echo "secret-value" | sf agent mcp create -n MyServer --server-url https://mcp.example.com/mcp --auth-type OAUTH --identity-provider MyIdp --client-id abc123 --client-secret - --scope "read write" -o myOrg --json -
Extract server ID — Parse the JSON response and extract
result.server.id(format:0LeSB000000Jp5F). Note the ID is underresult.server, notresultdirectly. This ID is required for all subsequent operations. The response also includesresult.assets(discovered but not yet registered — they haveid: nullandstatus: "NOT_REGISTERED"until you activate them). -
Display confirmation — Show the user:
- Server name
- Server ID
- Server URL
- Connection status
-
Offer next steps
- "Would you like to fetch and whitelist tools from this server now?"
- If yes, proceed to Fetch and Whitelist Assets workflow
2. List MCP Servers
When the user wants to see all registered MCP servers:
-
Verify target org
sf config get target-org --json -
List servers
sf agent mcp list -o myOrg --jsonOptional filters:
- By status:
--status ACTIVEor--status DISCONNECTED - By type:
--type EXTERNAL - By label:
--label "My Server"
- By status:
-
Display results — The server array is under
result.mcpServers. Show a table or list with: Server name, Server ID, Status (ACTIVE/DISCONNECTED), Server URL, Label. Auth type is under each server'sauthorization.authType. -
Offer actions — Ask if the user wants to get details on a specific server, fetch assets, or update/delete a server
3. Get Server Details
When the user wants details on a specific server:
-
Verify target org
sf config get target-org --json -
Get server details
sf agent mcp get -i 0XSxx0000000001 -o myOrg --json -
Display details — Name, label, description, server URL, status, authentication type (
authorization.authType), and created/modified timestamps. Audit fields are IDs only (createdById/lastModifiedById) — there are no user-name objects. For OAUTH servers,authorization.scopeandauthorization.identityProvider(a token endpoint URL) are also present.
4. Fetch and Whitelist Assets (Interactive Tool Approval)
This is the core whitelisting workflow with interactive tool-by-tool approval.
-
Verify target org
sf config get target-org --json -
Fetch live assets from the server
sf agent mcp fetch -i 0XSxx0000000001 -o myOrg --json -
Parse the response — Extract the list of assets from
result.assets. Each asset includes:id,name(e.g.,McpTool__getTickets),label,kind(MCP_TOOL/MCP_PROMPT/MCP_RESOURCE),active(boolean),availableAsAgentAction(boolean),description, andstatus(IN_SYNC/NOT_REGISTERED). Note:inputSchema,outputSchema, andannotationsare NOT guaranteed to be present (the live server did not return them) — handle their absence gracefully. -
Interactive tool review — For EACH tool in the list:
a. Display tool metadata clearly (only render schema/annotations fields if the server actually returned them — they are often absent):
Tool: <name> (<label>) Kind: <kind> Description: <description> Input Schema: <formatted JSON inputSchema> (or "Not specified") Output Schema: <formatted JSON outputSchema> (or "Not specified") Annotations: <formatted JSON annotations> (or "None") Current Status: <active ? "ACTIVE" : "INACTIVE">b. Ask for approval:
Do you want to ACTIVATE this tool? (yes/no/skip) - yes: Add to allowlist - no: Exclude from allowlist (deactivate if currently active) - skip: Keep current status unchangedc. Record the user's choice — Build an array of approved assets
-
Build the asset allowlist — Create a JSON payload with the approved assets:
{ "assets": [ { "name": "McpTool__add", "active": true }, { "name": "McpTool__subtract", "active": false } ] } -
Replace the server's asset allowlist — Pass the payload inline via
--assets, or pipe it through stdin with--assets -. No temp file needed.Inline (small payloads):
sf agent mcp asset replace -i 0XSxx0000000001 \ --assets '{"assets":[{"name":"McpTool__add","active":true},{"name":"McpTool__subtract","active":false}]}' \ -o myOrg --jsonVia stdin (larger payloads):
echo '<json payload>' | sf agent mcp asset replace -i 0XSxx0000000001 --assets - -o myOrg --json -
Confirm results — The replace response returns the full resulting asset set under
result.assets(noassetsUpdatedcount field). Derive counts by inspecting each asset'sactiveflag in the response, e.g.:Asset Allowlist Updated: - Active: <count of active:true> tools - Inactive: <count of active:false> tools
Notes on Asset Replacement
- Full replacement semantics —
sf agent mcp asset replaceis a FULL replacement, not a merge. Assets not in the payload are removed/deactivated. - Always include the full desired state — If a tool should remain active,
include it in the payload with
"active": true. - Read current state first — Use
sf agent mcp fetchorsf agent mcp asset listto see current assets before replacement.
5. List Assets for a Server
When the user wants to see the current asset allowlist:
-
Verify target org
sf config get target-org --json -
List assets
sf agent mcp asset list -i 0XSxx0000000001 -o myOrg --json -
Display results — Show each asset with: Name, Kind (MCP_TOOL, MCP_PROMPT, MCP_RESOURCE), Active status, Available as agent action
6. Update MCP Server
When the user wants to modify server configuration:
Updatable Fields
--label— New display label ⚠️ (observed not to persist — see command note)--description— New description (persists)--server-url— New endpoint URL ⚠️ (observed not to persist — see command note)--auth-type— Change authentication (requires full OAuth params if switching to OAUTH)
⚠️ In live preview-CLI testing, only --description persisted; --label and
--server-url returned success but were silently ignored. Always confirm with a
follow-up get. See the sf agent mcp update command reference below for details.
Execution Steps
-
Verify target org
sf config get target-org --json -
Gather update fields — Ask which fields to change
-
Update the server
sf agent mcp update -i 0XSxx0000000001 --label "New Label" --description "Updated description" -o myOrg --jsonSwitching to OAuth:
echo "secret" | sf agent mcp update -i 0XSxx0000000001 --auth-type OAUTH --identity-provider MyIdp --client-id abc --client-secret - --scope "read write" -o myOrg --json -
Confirm results — Display updated server details
7. Delete MCP Server
When the user wants to remove a server registration:
-
Verify target org
sf config get target-org --json -
Get server details first — Show what will be deleted
sf agent mcp get -i 0XSxx0000000001 -o myOrg --json -
Confirm deletion — Ask user:
Are you sure you want to delete this MCP server? - Name: <name> - URL: <url> - This action is PERMANENT and cannot be undone. Confirm deletion? (yes/no) -
Delete the server
sf agent mcp delete -i 0XSxx0000000001 -o myOrg --no-prompt --json -
Confirm deletion — Display success message
Command Reference
sf agent mcp create
Purpose: Register a new MCP server in the API Catalog
Required Parameters:
-n, --name <value>— Unique server name. It cannot contain spaces, has to start with a letter and can only contain alphanumeric characters.-o, --target-org <value>— Target org alias/username--server-url <value>— MCP server endpoint URL
Optional Parameters:
--label <value>— Human-readable display name--description <value>— Server description--auth-type <OAUTH|NO_AUTH>— Default:NO_AUTH--identity-provider <value>— OAuth IdP (required withOAUTH)--client-id <value>— OAuth client ID (required withOAUTH)--client-secret <value>— OAuth secret (use-for stdin)--scope <value>— OAuth scope (required withOAUTH)--api-version <value>— API version override--json— JSON output (ALWAYS use this)
Response Structure:
create returns BOTH the discovered assets and the newly created server
object (result keys: assets, server). Each asset item has exactly these
keys: active, availableAsAgentAction, description, id, kind, label,
name, status. On creation the assets are discovered but not yet registered,
so each asset's id is null and its status is NOT_REGISTERED (activate
them with agent mcp asset replace). The server's audit fields (createdById,
createdDate, lastModifiedById, lastModifiedDate) also come back null in
the immediate create response.
{
"status": 0,
"result": {
"assets": [
{
"active": false,
"availableAsAgentAction": false,
"description": "Gets all tickets for driver...",
"id": null,
"kind": "MCP_TOOL",
"label": "getTickets",
"name": "McpTool__getTickets",
"status": "NOT_REGISTERED"
}
],
"server": {
"authorization": {
"authType": "NO_AUTH",
"identityProvider": null,
"scope": null
},
"createdById": null,
"createdDate": null,
"description": "temp server for output reconciliation",
"id": "0LeSB000000Jp5F",
"label": "Recon Test",
"lastModifiedById": null,
"lastModifiedDate": null,
"name": "reconTestServer",
"serverUrl": "https://mcp.example.com/mcp",
"status": "ACTIVE",
"type": "EXTERNAL"
}
},
"warnings": ["This command is currently in developer preview..."]
}
To extract the server ID after create, read result.server.id (NOT result.id).
Error Response:
Errors are emitted with a non-zero status/exitCode (e.g. 4) and include
name, message, context, stack, cause, code, and commandName fields:
{
"name": "GetMcpServerFailed",
"message": "Failed to get MCP server: MCP server not found",
"exitCode": 4,
"context": "ApiCatalogMcpServerGet",
"code": "GetMcpServerFailed",
"status": 4,
"commandName": "ApiCatalogMcpServerGet",
"warnings": ["This command is currently in developer preview..."]
}
sf agent mcp list
Purpose: List all registered MCP servers
Required Parameters:
-o, --target-org <value>— Target org
Optional Parameters:
--label <value>— Filter by label--type <EXTERNAL>— Filter by type--status <ACTIVE|DISCONNECTED>— Filter by status--json— JSON output
Response Structure:
The server array is nested under result.mcpServers (NOT directly under
result). Each server carries a nested authorization object and bare
createdById/lastModifiedById string IDs.
{
"status": 0,
"result": {
"mcpServers": [
{
"authorization": {
"authType": "NO_AUTH",
"identityProvider": null,
"scope": null
},
"createdById": "005SB00000iwVrhYAE",
"createdDate": "2026-07-22T21:07:55Z",
"description": null,
"id": "0LeSB000000JoFd",
"label": "ticketsMCP",
"lastModifiedById": "005SB00000iwVrhYAE",
"lastModifiedDate": "2026-07-22T21:09:22Z",
"name": "ticketsMCP",
"serverUrl": "https://mcp.example.com/tickets/mcp",
"status": "ACTIVE",
"type": "EXTERNAL"
}
]
},
"warnings": ["This command is currently in developer preview..."]
}
sf agent mcp get
Purpose: Get details on a specific MCP server
Required Parameters:
-i, --mcp-server-id <value>— Server ID-o, --target-org <value>— Target org
Optional Parameters:
--json— JSON output
Response Structure:
Auth details are nested under authorization (authType, identityProvider,
scope). For OAUTH servers identityProvider holds the token endpoint URL. There
is NO clientId field in the response, and audit info is exposed as bare
createdById/lastModifiedById string IDs (not createdBy objects with names).
{
"status": 0,
"result": {
"authorization": {
"authType": "OAUTH",
"identityProvider": "https://mcp.example.com/auth/token",
"scope": "read"
},
"createdById": "005SB00000iwVrhYAE",
"createdDate": "2026-07-15T23:38:04Z",
"description": null,
"id": "0LeSB000000Jk0j",
"label": "TestHKWithAuth",
"lastModifiedById": "005SB00000iwVrhYAE",
"lastModifiedDate": "2026-07-15T23:40:43Z",
"name": "TestHKWithAuth",
"serverUrl": "https://mcp.example.com/test/mcp",
"status": "ACTIVE",
"type": "EXTERNAL"
},
"warnings": ["This command is currently in developer preview..."]
}
sf agent mcp update
Purpose: Update an existing MCP server
Required Parameters:
-i, --mcp-server-id <value>— Server ID-o, --target-org <value>— Target org- At least one of
--label,--description,--server-url, or--auth-type. Supplying none errors withNoFields(exit code 1): "No fields to update. Provide at least one of --label, --description, --server-url, or --auth-type."
Optional Parameters:
--label <value>— New label--description <value>— New description--server-url <value>— New URL--auth-type <OAUTH|NO_AUTH>— New auth type--identity-provider <value>— OAuth IdP--client-id <value>— OAuth client ID--client-secret <value>— OAuth secret (use-)--scope <value>— OAuth scope--json— JSON output
Response Structure:
update returns the FULL server object (same shape as get), not a partial
subset.
⚠️ Observed preview-stage bug — not all updatable fields persist: In live
testing against the preview CLI (sf 2.144.6, plugin-agent), only
--description actually persisted. --label and --server-url updates
returned status: 0 (apparent success) but the value was silently ignored —
a follow-up get showed the old value unchanged, and the label in the update
response echoed the server name rather than the requested label. Always verify
update results with a follow-up get, and do not rely on --label or
--server-url taking effect until this is fixed. (--auth-type was not
re-verified in this pass.)
{
"status": 0,
"result": {
"authorization": {
"authType": "NO_AUTH",
"identityProvider": null,
"scope": null
},
"createdById": "005SB00000iwVrhYAE",
"createdDate": "2026-07-23T21:16:03Z",
"description": "updated desc",
"id": "0LeSB000000Jp5F",
"label": "reconTestServer",
"lastModifiedById": "005SB00000iwVrhYAE",
"lastModifiedDate": "2026-07-23T21:16:17Z",
"name": "reconTestServer",
"serverUrl": "https://mcp.example.com/tickets/mcp",
"status": "ACTIVE",
"type": "EXTERNAL"
},
"warnings": ["This command is currently in developer preview..."]
}
sf agent mcp delete
Purpose: Delete an MCP server
Required Parameters:
-i, --mcp-server-id <value>— Server ID-o, --target-org <value>— Target org
Optional Parameters:
--no-prompt— Skip confirmation--json— JSON output
Response Structure:
Returns only id and deleted — there is NO name field.
{
"status": 0,
"result": { "id": "0LeSB000000Jp5F", "deleted": true },
"warnings": ["This command is currently in developer preview..."]
}
sf agent mcp fetch
Purpose: Fetch live assets from an MCP server
Required Parameters:
-i, --mcp-server-id <value>— Server ID-o, --target-org <value>— Target org
Optional Parameters:
--json— JSON output
Response Structure:
Assets are returned directly under result.assets — there is NO serverId or
serverName field. Each asset carries active, availableAsAgentAction,
description, id, kind, label, name, and a status field
(IN_SYNC for registered assets, NOT_REGISTERED for freshly discovered ones).
Observed assets do NOT include inputSchema, outputSchema, or annotations —
those fields were not returned by the live server. Do not rely on them being
present. Descriptions may contain HTML entities (e.g. ' for ').
{
"status": 0,
"result": {
"assets": [
{
"active": true,
"availableAsAgentAction": true,
"description": "Gets all tickets for driver using their driver's license id...",
"id": "1XOSB0000008riJ",
"kind": "MCP_TOOL",
"label": "getTickets",
"name": "McpTool__getTickets",
"status": "IN_SYNC"
},
{
"active": true,
"availableAsAgentAction": true,
"description": "Evaluates whether a ticket should be waived based on a reason...",
"id": "1XOSB0000008riI",
"kind": "MCP_TOOL",
"label": "disputeTicket",
"name": "McpTool__disputeTicket",
"status": "IN_SYNC"
}
]
},
"warnings": ["This command is currently in developer preview..."]
}
sf agent mcp asset list
Purpose: List the current asset allowlist for a server
Required Parameters:
-i, --mcp-server-id <value>— Server ID-o, --target-org <value>— Target org
Optional Parameters:
--json— JSON output
Response Structure:
Assets are returned directly under result.assets — there is NO serverId
field. Each asset has exactly these keys: active, availableAsAgentAction,
description, id, kind, label, name. Note: unlike fetch, asset list
does NOT include a status field on each asset.
Important: asset list reflects only registered assets. Immediately after
create, before any asset replace, this returns an empty set
("assets": []) even though the server advertises assets — because the assets
are discovered but not yet registered. Use fetch to see advertised (but
unregistered) assets, and asset replace to register/activate them.
{
"status": 0,
"result": {
"assets": [
{
"active": true,
"availableAsAgentAction": true,
"description": "Evaluates whether a ticket should be waived...",
"id": "1XOSB0000008riI",
"kind": "MCP_TOOL",
"label": "disputeTicket",
"name": "McpTool__disputeTicket"
},
{
"active": true,
"availableAsAgentAction": true,
"description": "Gets all tickets for driver...",
"id": "1XOSB0000008riJ",
"kind": "MCP_TOOL",
"label": "getTickets",
"name": "McpTool__getTickets"
}
]
},
"warnings": ["This command is currently in developer preview..."]
}
sf agent mcp asset replace
Purpose: Replace the full asset allowlist for a server
Required Parameters:
-i, --mcp-server-id <value>— Server ID-o, --target-org <value>— Target org- Either
--assets <value>OR--assets-file <value>
Optional Parameters:
--assets <value>— JSON string or-for stdin. Mutually exclusive with--assets-file(supplying both errors with exit code 2).--assets-file <value>— Path to JSON file. Mutually exclusive with--assets. A missing file path errors with exit code 2 before any API call.--json— JSON output
Asset Payload Format:
Each asset item may include id, name, label, description, active, and
kind (per the command help). In practice name + active is sufficient to set
the allowlist; the other fields are optional. The payload accepts either an array
or an object with an assets key, supplied inline via --assets, from stdin via
--assets -, or from a file via --assets-file.
Array format:
[
{ "name": "McpTool__add", "active": true },
{ "name": "McpTool__subtract", "active": false }
]
Object format:
{
"assets": [{ "name": "McpTool__add", "active": true }]
}
Response Structure:
Returns the full resulting asset set under result.assets (same shape as
asset list) — there is NO serverId or assetsUpdated field. Each asset in
the response is a full asset object (active, availableAsAgentAction,
description, id, kind, label, name), not just the {name, active} pairs
sent in the request payload.
The response lists ALL of the server's assets, not only those in your payload.
Any advertised asset omitted from the payload is returned with active: false
(this is the "full replacement" semantics — omission = deactivation). For example,
sending a payload with just getTickets: true against a 3-asset server returns
all three assets: getTickets active, and the two omitted ones as active: false.
After a replace, previously-unregistered assets now have real (non-null) ids.
{
"status": 0,
"result": {
"assets": [
{
"active": false,
"availableAsAgentAction": false,
"description": "Evaluates whether a ticket should be waived...",
"id": "1XOSB0000008rok",
"kind": "MCP_TOOL",
"label": "disputeTicket",
"name": "McpTool__disputeTicket"
},
{
"active": true,
"availableAsAgentAction": true,
"description": "Gets all tickets for driver...",
"id": "1XOSB0000008rol",
"kind": "MCP_TOOL",
"label": "getTickets",
"name": "McpTool__getTickets"
}
]
},
"warnings": ["This command is currently in developer preview..."]
}
Concepts
Asset Kinds
| Kind | Description | Use Case |
|---|---|---|
MCP_TOOL |
Executable function/action | Agent can invoke tools to perform operations |
MCP_PROMPT |
Reusable prompt template | Agent can use prompts for structured generation |
MCP_RESOURCE |
Data source or endpoint | Agent can read resources for context |
Server Status
| Status | Meaning | Action |
|---|---|---|
ACTIVE |
Server is reachable and responding | Normal operation |
DISCONNECTED |
Server is unreachable or not responding | Check URL, auth, network |
Asset Activation States
| State | Meaning | Visibility |
|---|---|---|
active: true |
Asset is whitelisted and available | Available to agents |
active: false |
Asset is fetched but not whitelisted | Not available to agents |
| Not in allowlist | Asset exists on server but not tracked | Not available to agents |
The availableAsAgentAction boolean mirrors whether an active asset is exposed as
an agent action.
Asset Sync Status (fetch only)
The fetch command returns a status field on each asset (the asset list
command does NOT):
| Status | Meaning |
|---|---|
IN_SYNC |
Asset is registered in the catalog and matches the live server |
NOT_REGISTERED |
Asset was discovered on the server but is not yet registered (its id is null) — e.g. immediately after create before an asset replace |
Authentication Types
NO_AUTH — No authentication required. The MCP server is publicly accessible or uses a different auth mechanism (e.g., IP allowlisting, API gateway).
sf agent mcp create -n PublicServer --server-url https://public.mcp.example.com/mcp --auth-type NO_AUTH -o myOrg --json
OAUTH — OAuth 2.0 client credentials flow. Requires identity provider, client ID, client secret, and scope.
echo "my-secret" | sf agent mcp create \
-n SecureServer \
--server-url https://secure.mcp.example.com/mcp \
--auth-type OAUTH \
--identity-provider MyIdentityProvider \
--client-id abc123xyz \
--client-secret - \
--scope "read write execute" \
-o myOrg \
--json
OAuth parameters: --identity-provider (named credential or external IdP),
--client-id, --client-secret (use - for stdin), --scope (space-separated).
Tool Metadata Fields
Required: name (e.g., McpTool__add), kind, description.
Optional: inputSchema (JSON Schema for inputs), outputSchema (JSON Schema
for outputs), annotations (custom metadata). Common annotations: category,
rateLimit, cost, latency, destructive, requiresAuth.
Security Best Practices
Client Secret Handling
- NEVER pass
--client-secretdirectly on the command line (visible in shell history):# ❌ NEVER sf agent mcp create -n Server --server-url https://mcp.example.com --auth-type OAUTH --client-secret "my-secret" -o myOrg - ALWAYS use stdin piping:
# ✅ stdin echo "my-secret" | sf agent mcp create -n Server --server-url https://mcp.example.com --auth-type OAUTH --client-secret - -o myOrg --json # ✅ file piping cat /secure/location/secret.txt | sf agent mcp create -n Server --server-url https://mcp.example.com --auth-type OAUTH --client-secret - -o myOrg --json
Credential Storage
- Warn users that credentials are stored in the Salesforce org.
- Recommend org-specific service accounts, not personal credentials.
Server URL Validation
- Verify HTTPS for production servers.
- Warn if using HTTP for non-local development.
Tool Review Checklist
Before activating a tool, review:
- Destructive operations — Does it delete, update, or modify data? Execute code/commands? Have file system access?
- Data exposure — Does it access sensitive data (PII, credentials)? Query databases directly? Have broad read permissions?
- Rate limits — Are there rate limit annotations? Could it cause DoS if overused? Cost implications?
- Authentication — Does it require additional auth? Impersonate users? Have elevated privileges?
- Scope — Is the tool's purpose clear? Narrowly scoped or overly broad? Does it align with agent use cases?
Recommended Warnings
Production org deployment:
⚠️ WARNING: You are deploying to a PRODUCTION org.
This will activate MCP tools in a live environment.
Ensure all tools have been reviewed and tested.
Continue? (yes/no)
Destructive tool activation:
⚠️ CAUTION: This tool has destructive capabilities.
Tool: McpTool__deleteRecord
Description: Delete records from the database
Annotations: {"destructive": true, "scope": "all_records"}
Are you sure you want to activate this tool? (yes/no)
Broad permissions:
⚠️ NOTICE: This tool has broad data access.
Tool: McpResource__customerData
Description: Access to all customer records
Consider limiting scope or using field-level security.
Activate anyway? (yes/no)
Error Handling
| Error | Likely message | Resolution |
|---|---|---|
| No target org set | No default org found |
Ask user to run sf config set target-org <alias> |
| Server not found | MCP server not found |
Verify server ID with sf agent mcp list |
| Connection refused | Failed to connect to <url>: Connection refused |
Verify URL, network connectivity, ensure server is running |
| Invalid OAuth credentials | OAuth authentication failed: Invalid client credentials |
Verify client ID, secret, identity provider, scope |
| Duplicate name | Failed to create MCP server: API Catalog External service registration with name: <name> already exists. Use a new name or edit the existing one (name CreateMcpServerFailed, exit code 4) |
Use a unique name or update the existing server |
| Unparseable asset JSON | The assets input does not contain valid JSON. (name InvalidJson, exit code 1) |
Fix the JSON syntax of the --assets/stdin payload |
| Wrong asset JSON shape | The assets input must be a JSON array of asset items or an object with an "assets" array. (name InvalidShape, exit code 1) |
Use an array of asset items or { "assets": [...] } |
| Asset not found | Failed to replace MCP server assets: API Catalog DataSource MCP DataSource Asset <name> not found on server <id> (name ReplaceMcpServerAssetsFailed, exit code 4) |
Fetch fresh assets with sf agent mcp fetch |
| Server disconnected | Cannot update assets: Server is DISCONNECTED |
Check server status, verify URL and auth |
| Deactivating an exposed Agent Action | Failed to replace MCP server assets: Cannot deactivate asset(s) [<name>]: each is currently exposed as an Agent Action and must remain active for the lifetime of the server. Delete the Agent Action first, or delete the server with DELETE /mcp-servers/{id}. (name ReplaceMcpServerAssetsFailed, exit code 4) |
Delete the Agent Action referencing the tool first, or delete the server |
Edge Cases
Empty asset list ("assets": []) — The server exposes nothing, is newly
registered and not yet indexed, or fetch errored. Offer to check server status,
retry fetch, or update server config.
All tools declined/skipped — No assets will be activated. Offer to review the tools again, fetch fresh assets, or cancel and keep current state.
Partial OAuth configuration — If some but not all OAuth params are provided,
list the required set (--identity-provider, --client-id, --client-secret,
--scope) and which are missing.
Server ID ambiguity — If the user refers to a server by name, resolve to an ID
via sf agent mcp list. If multiple names match, present the matches and ask which
ID to use.
Windows Compatibility
- Python command: Use
pythoninstead ofpython3. - Stdin piping (PowerShell):
"secret" | sf agent mcp create ... --client-secret -
PowerShell — pass assets inline or via stdin:
$assets = @{
assets = @(
@{ name = "McpTool__add"; active = $true },
@{ name = "McpTool__subtract"; active = $false }
)
} | ConvertTo-Json -Depth 10 -Compress
$assets | sf agent mcp asset replace -i 0XSxx0000000001 --assets - -o myOrg --json
cmd — create server (no auth):
sf agent mcp create ^
-n MyServer ^
--server-url https://mcp.example.com/mcp ^
-o myOrg ^
--json
For OAuth with a client secret, use PowerShell or Git Bash for stdin piping.
Complete Workflow Example
Scenario: Register and whitelist a weather MCP server
# 1. Verify target org
sf config get target-org --json
# 2. Create MCP server (no auth)
sf agent mcp create \
-n WeatherServer \
--server-url https://weather.mcp.example.com/mcp \
--label "Weather MCP Server" \
--description "Provides current weather and forecasts" \
-o myOrg \
--json
# Extract server ID from response: 0XSxx0000000123
# 3. Fetch available tools
sf agent mcp fetch -i 0XSxx0000000123 -o myOrg --json
# 4. Review each tool interactively (handled by Claude — see Workflow 4)
# Tool getCurrentWeather → yes, Tool getForecast → yes
# 5. Build allowlist and replace it (pipe payload via stdin — no temp file)
echo '{
"assets": [
{"name": "McpTool__getCurrentWeather", "active": true},
{"name": "McpTool__getForecast", "active": true}
]
}' | sf agent mcp asset replace -i 0XSxx0000000123 --assets - -o myOrg --json
# 6. Verify activation
sf agent mcp asset list -i 0XSxx0000000123 -o myOrg --json
Scenario: Register an OAuth-authenticated server
# Store client secret securely, then pipe via stdin
echo "my-oauth-secret" | sf agent mcp create \
-n OAuthServer \
--server-url https://secure.mcp.example.com/mcp \
--auth-type OAUTH \
--identity-provider MyIdentityProvider \
--client-id abc123xyz \
--client-secret - \
--scope "read write execute" \
-o myOrg \
--json
Quick Reference
| Command | Purpose |
|---|---|
sf agent mcp create |
Register a new MCP server |
sf agent mcp list |
List all registered servers |
sf agent mcp get |
Get details on a specific server |
sf agent mcp update |
Update server configuration |
sf agent mcp delete |
Remove server registration |
sf agent mcp fetch |
Fetch live assets from server |
sf agent mcp asset list |
List current asset allowlist |
sf agent mcp asset replace |
Update asset allowlist (full replacement) |
Troubleshooting
Server shows DISCONNECTED status
- Check server URL is accessible:
curl -v <server-url> - Verify authentication credentials (if OAuth)
- Check server logs for connection errors
- Try updating the server URL:
sf agent mcp update -i <id> --server-url <new-url>
Tools not appearing after whitelisting
- Verify asset activation:
sf agent mcp asset list -i <id> - Check tools are marked
active: true - Fetch fresh assets:
sf agent mcp fetch -i <id> - Verify server is ACTIVE:
sf agent mcp get -i <id>
"Command not found: agent mcp"
- The
sf agent mcpplugin may not be installed - Check SF CLI version:
sf version; update withsf update - Verify plugin availability:
sf plugins