wso2-bi-salesforce-mcp-server

wso2-bi-salesforce-mcp-server

Enables AI assistants to set up, run, and manage Ballerina + Salesforce integrations inside a WSO2 Integrator workspace, providing 18 tools for OAuth2 token acquisition, project scaffolding, building, deploying, and stopping the integration service.

Category
Visit Server

README

wso2-bi-salesforce-mcp-server

MCP server that lets AI assistants set up, run, and manage Ballerina + Salesforce integrations inside a WSO2 Integrator (BI) workspace — from zero credentials to a running REST service in one conversation.

Gives AI assistants 18 tools to acquire OAuth2 tokens, validate credentials, discover SObjects, scaffold Ballerina projects, add CDC/Platform Event listeners, build, deploy, and stop the integration service — without exposing a shell command interface.


Prerequisites

Tool Version Purpose
Node.js 18+ Run the MCP server
Ballerina 2201.12.0 (Swan Lake) Build and run Ballerina projects
Git Any Clone the repo
Salesforce org Any edition Developer Edition is free — sign up
Ballerina 2201.12.0 Exact match recommended Scaffolded projects pin this distribution — mismatch will warn at setup

You don't need Salesforce credentials yet. The MCP tools walk you through creating a Connected App and getting a refresh token.

Salesforce org setting (if using username-password flow): Setup → Identity → OAuth and OpenID Connect Settings → enable "Allow OAuth Username-Password Flows". This is a one-time 30-second toggle. Not required if using browser OAuth (Path C).


Installation

1. Clone or locate the project

# If you already have the project directory:
cd /path/to/wso2-bi-salesforce-mcp-server

# Or clone from source:
git clone <repo-url>
cd wso2-bi-salesforce-mcp-server

2. Install dependencies

npm install

3. Build the server

npm run build

This compiles TypeScript to dist/. The entry point is dist/index.js.

4. Verify the build

echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' | node dist/index.js

You should see a JSON response listing all 18 tools.


Default project paths (auto-detected)

Projects are scaffolded into your WSO2 Integrator workspace by default. No configuration required.

Platform Default bi_path
macOS / Linux ~/WSO2Integrator
Windows %USERPROFILE%\WSO2Integrator

If ~/WSO2Integrator doesn't exist, the server will create the project inside it. You can always override the path in any tool that accepts bi_path or project_path.


Adding the MCP to AI clients

Replace /absolute/path/to/wso2-bi-salesforce-mcp-server with the actual path on your machine.

Claude Desktop

  1. Open Claude Desktop → Settings → Developer → Edit Config, or open the config file directly:

    # macOS
    ~/Library/Application Support/Claude/claude_desktop_config.json
    
    # Windows
    %APPDATA%\Claude\claude_desktop_config.json
    
  2. Add the server under mcpServers:

    {
      "mcpServers": {
        "ballerina-salesforce": {
          "command": "node",
          "args": [
            "/absolute/path/to/wso2-bi-salesforce-mcp-server/dist/index.js"
          ]
        }
      }
    }
    
  3. Restart Claude Desktop. The 18 tools will appear automatically.


Claude Code (CLI)

Claude Code uses dedicated MCP config files, not settings.json. MCP servers never go in settings.json.

Recommended — CLI commands (writes the correct file automatically)

# User scope — available in all your projects (recommended for personal use)
claude mcp add --scope user --transport stdio ballerina-salesforce -- \
  node /absolute/path/to/wso2-bi-salesforce-mcp-server/dist/index.js

# Project scope — shared with your team via .mcp.json at the repo root
claude mcp add --scope project --transport stdio ballerina-salesforce -- \
  node /absolute/path/to/wso2-bi-salesforce-mcp-server/dist/index.js

Verify:

claude mcp list

Manual — edit the config files directly

User scope (~/.claude.json — available in all your projects):

{
  "mcpServers": {
    "ballerina-salesforce": {
      "command": "node",
      "args": ["/absolute/path/to/wso2-bi-salesforce-mcp-server/dist/index.js"],
      "type": "stdio"
    }
  }
}

Project scope (.mcp.json at your project root — commit this to share with your team):

{
  "mcpServers": {
    "ballerina-salesforce": {
      "command": "node",
      "args": ["/absolute/path/to/wso2-bi-salesforce-mcp-server/dist/index.js"],
      "type": "stdio"
    }
  }
}

Note: ~/.claude/.mcp.json is not a valid path. User-scope MCP config lives in ~/.claude.json (top-level key). Project-scope config lives in .mcp.json at the project root, not inside .claude/.


Cursor

  1. Open Cursor → Settings → Features → MCP (or Cursor Settings > MCP).
  2. Click Add new MCP server.
  3. Fill in:
    • Name: ballerina-salesforce
    • Type: stdio
    • Command: node
    • Args: /absolute/path/to/wso2-bi-salesforce-mcp-server/dist/index.js

Or add directly to ~/.cursor/mcp.json:

{
  "mcpServers": {
    "ballerina-salesforce": {
      "command": "node",
      "args": [
        "/absolute/path/to/wso2-bi-salesforce-mcp-server/dist/index.js"
      ]
    }
  }
}

Restart Cursor after saving.


Windsurf

Add to ~/.codeium/windsurf/mcp_config.json:

{
  "mcpServers": {
    "ballerina-salesforce": {
      "command": "node",
      "args": [
        "/absolute/path/to/wso2-bi-salesforce-mcp-server/dist/index.js"
      ]
    }
  }
}

Restart Windsurf after saving.


VS Code

Continue.dev — add to ~/.continue/config.json:

{
  "mcpServers": [
    {
      "name": "ballerina-salesforce",
      "command": "node",
      "args": [
        "/absolute/path/to/wso2-bi-salesforce-mcp-server/dist/index.js"
      ]
    }
  ]
}

GitHub Copilot (VS Code MCP support) — add to VS Code settings.json:

{
  "github.copilot.mcp.servers": {
    "ballerina-salesforce": {
      "command": "node",
      "args": [
        "/absolute/path/to/wso2-bi-salesforce-mcp-server/dist/index.js"
      ],
      "type": "stdio"
    }
  }
}

Zed

Add to ~/.config/zed/settings.json:

{
  "context_servers": {
    "ballerina-salesforce": {
      "command": {
        "path": "node",
        "args": [
          "/absolute/path/to/wso2-bi-salesforce-mcp-server/dist/index.js"
        ]
      }
    }
  }
}

HTTP mode (any agent)

Run the server as an HTTP endpoint — useful for remote agents, containers, or any client that supports HTTP-based MCP.

TRANSPORT=http PORT=3001 SF_MCP_HTTP_TOKEN=your-secret-token node dist/index.js
  • MCP endpoint: http://127.0.0.1:3001/mcp
  • Auth header: Authorization: Bearer your-secret-token
  • Health check: http://127.0.0.1:3001/healthz

⚠️ Always set SF_MCP_HTTP_TOKEN in HTTP mode. The server warns on startup if it is missing.

Any MCP-compatible client (generic)

The server uses stdio transport — the standard for local MCP servers.

  • Command: node
  • Args: ["/absolute/path/to/wso2-bi-salesforce-mcp-server/dist/index.js"]
  • Transport: stdio
  • Protocol: JSON-RPC 2.0 over stdin/stdout

Usage guide

Once configured, interact with the tools through your AI assistant using natural language. The assistant calls the correct tools automatically.

Quick start (one command)

The fastest path if you already have a Salesforce refresh token:

"Set up a Ballerina Salesforce integration. Client ID: 3MVG9..., Secret: ..., Refresh token: 5Aep..., Base URL: https://myorg.my.salesforce.com"

This single phrase triggers sf_quickstart, which:

  1. Validates your credentials with a live Salesforce API call
  2. Auto-detects sandbox vs production from the URL
  3. Scaffolds a complete Ballerina project at ~/WSO2Integrator/salesforce_integration/
  4. Writes Config.toml with mode 0600 (owner read/write only)
  5. Returns the project path and ready-to-run instructions

Say "Also compile it" to add build: true and verify the project compiles immediately.


Starting from zero (full walkthrough)

If you don't have credentials yet, the assistant walks you through the full setup.

Step 1 — Get the setup guide:

"Show me the Salesforce setup guide"
"I'm new to Salesforce — where do I start?"
"What do I need to set up a Ballerina Salesforce integration?"

Step 2 — Create a Connected App (3 min, manual in Salesforce):

The guide returned by sf_setup_guide gives you the exact steps. In short:

  1. Salesforce → Setup → App Manager → New Connected App
  2. Enable OAuth: scopes api + refresh_token (offline_access), callback https://login.salesforce.com/services/oauth2/success
  3. Save → copy Consumer Key and Consumer Secret
  4. Wait 2–10 min for the app to activate

Step 3 — Check prerequisites:

"Check if Ballerina is installed"
"Are my prerequisites met?"

Step 4 — Get an OAuth refresh token:

"Get me an OAuth URL for client ID 3MVG9..."

Open the returned URL in a browser, approve access, copy the ?code= value from the redirect URL, then:

"Exchange this OAuth code: aPrx..."

Save the returned refresh_token and instance_url.

Step 5 — Scaffold and run:

"Set up a Salesforce integration for my org. Client ID: 3MVG9..., Secret: ..., Refresh token: 5Aep..., Base URL: https://myorg.my.salesforce.com"

Step 6 — Deploy:

"Start the integration service"
"Deploy the Salesforce project"

Step 7 — Stop when done:

"Stop the integration service"

Example prompts

"Show me the Salesforce integration setup guide."

"Check if Ballerina is installed and ready."

"Get me an OAuth authorization URL for client ID 3MVG9... — this is a sandbox org."

"Exchange this code: aPrxQ7... and give me the refresh token."

"Validate my Salesforce connection — client ID 3MVG9..., secret ..., token 5Aep..., URL https://myorg.my.salesforce.com"

"List all custom objects in my Salesforce org."

"Describe the Invoice__c object fields."

"Set up a Ballerina Salesforce integration project with my credentials."

"Set up the project and also include Account CDC listeners so I get notified of Account changes."

"Add a listener for the OrderConfirmed__e platform event to my existing project."

"Add the Product2 object to my existing Salesforce integration project."

"Add the My_Custom__c object to my project — here are my credentials."

"Build my Salesforce integration project and show me any errors."

"Start the Salesforce service on port 8080."

"Update Config.toml in my project with these new credentials — my token was rotated."

"Stop the Salesforce integration service."

Quick Start Prompts

Copy one of these into your AI agent (Claude Desktop, Claude Code, Cursor, etc.) to go from zero to a running integration in one conversation.

⚠️ One-time Salesforce admin step required for Path A and Path B (takes 30 seconds): Paths A and B use the Salesforce username-password OAuth flow, which is disabled by default since Salesforce Spring '22. Before running either path, enable it once in your org: Salesforce Setup → Identity → OAuth and OpenID Connect Settings → ✅ Allow OAuth Username-Password Flows

If you cannot enable this (enterprise org policy), use Path C (browser OAuth) instead — it has no such restriction.


🆕 Path A — First-time setup

Use this when you have Salesforce credentials but no existing Postman collection. The agent will generate a credential wallet, scaffold the Ballerina project, and start the service.

Set up a complete Ballerina + Salesforce integration for me.

My Salesforce details:
- Client ID: <consumer_key>
- Client Secret: <consumer_secret>
- Base URL: https://myorg.my.salesforce.com
- Username: me@myorg.com
- Password: myPasswordSecurityToken
  (if your org uses a security token, append it to the password: myPasswordABC123)

Steps I want you to do:
1. Check prerequisites (bal CLI installed and version matches)
2. Generate a Postman collection and save it as my credential wallet
3. Use the returned credentials to run sf_quickstart (scaffold + build the project)
4. Deploy the service and tell me the PID and port

💡 After step 2 you'll have a ~/WSO2Integrator/Salesforce Integration.postman_collection.json file. Keep it — it's your credential wallet for future sessions. You can also import it into the Postman app to get fresh access tokens at any time.


🔁 Path B — Returning user (credential wallet already exists)

Use this in any future session after Path A. No credentials to type — the agent reads everything from the saved file.

Set up my Ballerina + Salesforce integration.
My credential wallet is at ~/WSO2Integrator/Salesforce Integration.postman_collection.json

Steps:
1. Import credentials from that Postman file
2. Run sf_quickstart with the extracted credentials
3. Deploy the service and give me the PID and port

🌐 Path C — Browser OAuth (no password flow)

Use this if your org has the username-password flow disabled (common in enterprise orgs).

Set up my Ballerina + Salesforce integration using browser OAuth.

My Salesforce details:
- Client ID: <consumer_key>
- Client Secret: <consumer_secret>
- Base URL: https://myorg.my.salesforce.com

Steps:
1. Check prerequisites
2. Give me the OAuth authorization URL to open in my browser
3. After I paste back the auth code, exchange it for a refresh token
4. Run sf_quickstart to scaffold and build the project
5. Deploy the service

Step-by-step workflow

Fastest path — generate a Postman collection (first-time setup):

1. sf_generate_postman_collection → give credentials once, auto-obtain token, save to ~/WSO2Integrator/*.postman_collection.json
2. sf_quickstart                  → validate + scaffold + (optional) build (ready_for_quickstart returned above)
3. sf_deploy_project              → start the service
4. sf_stop_project                → stop the service when done

Fastest path — already have a Postman collection?

1. sf_import_postman_credentials  → extract all credentials from .postman_collection.json
   (if token expired) sf_get_token_password_flow → get fresh token, no browser needed
2. sf_quickstart                  → validate + scaffold + (optional) build
3. sf_deploy_project              → start the service
4. sf_stop_project                → stop the service when done

Starting from scratch (browser OAuth):

1. sf_setup_guide          → first-time guide: Connected App setup, credential steps
2. sf_check_prerequisites  → verify bal CLI version + platform info
3. sf_get_oauth_auth_url   → generate authorization URL (open in browser)
4. sf_exchange_oauth_code  → trade the ?code= for a refresh_token
5. sf_quickstart           → validate + scaffold + (optional) build  ← one call does it all
6. sf_deploy_project       → start the service in the background
7. sf_stop_project         → stop the service when done

Starting from scratch (no browser — username + password):

1. sf_check_prerequisites       → verify Ballerina is installed
2. sf_get_token_password_flow   → username+password → refresh_token (no browser)
3. sf_quickstart                → validate + scaffold + build
4. sf_deploy_project            → start the service
5. sf_stop_project              → stop the service when done

Or broken out manually:

1. sf_setup_guide          → read the setup instructions
2. sf_check_prerequisites  → verify Ballerina is installed
3. sf_get_oauth_auth_url   → get the auth URL
4. sf_exchange_oauth_code  → exchange code → refresh_token
5. sf_validate_connection  → confirm credentials work
6. sf_list_sobjects        → discover SObjects in the org
7. sf_describe_sobject     → inspect field metadata for a specific object
8. sf_scaffold_project     → generate the Ballerina project
9. sf_build_project        → compile with bal build
10. sf_deploy_project      → start the service
11. sf_stop_project        → stop the service when done

Tool reference

Onboarding

sf_setup_guide

Returns a step-by-step guide for first-time users: how to create a Salesforce Connected App, obtain credentials, and which tools to call in order. Call this at the start of any Salesforce integration session.

"Show me the Salesforce setup guide"
"I've never set up a Salesforce Connected App — walk me through it"
"What scopes do I need for the Connected App?"
Parameter Type Default Description
sandbox boolean false Show sandbox (test.salesforce.com) variant

sf_check_prerequisites

Verifies the bal CLI is installed and reports its version vs. the expected Ballerina distribution.

"Check if Ballerina is installed"
"Are my prerequisites met for the Salesforce integration?"
"What version of Ballerina do I have?"

No parameters. Returns: bal_cli.available, bal_cli.version, platform, recommended_action.


OAuth2 authentication

sf_get_oauth_auth_url

Generates a Salesforce OAuth2 authorization URL. Open it in a browser to approve access — you receive a ?code= query parameter in the redirect URL.

"Get me an OAuth URL for client ID 3MVG9..."
"Generate a Salesforce authorization URL — this is a sandbox"
Parameter Type Default Description
sf_client_id string required Consumer Key from your Connected App
redirect_uri string https://login.salesforce.com/services/oauth2/success Must match your Connected App
sandbox boolean false Use test.salesforce.com instead of login.salesforce.com

Returns: auth_url (open this in a browser), next_step.


sf_exchange_oauth_code

Exchanges the ?code= from the redirect URL for a long-lived refresh token.

The short-lived access_token is intentionally masked in output — it's shown as access_token_preview only. You never need it directly; the other tools refresh automatically on demand.

"Exchange this OAuth code: aPrxQ7..."
"I got the code from the redirect URL — exchange it for a refresh token"
Parameter Type Default Description
sf_client_id string required Consumer Key
sf_client_secret string required Consumer Secret
code string required The ?code= value from the redirect URL
redirect_uri string success URL Same URI used in sf_get_oauth_auth_url
sandbox boolean false Must match where the code was obtained

Returns: refresh_token (save this!), instance_url (use as sf_base_url in all other tools).

Common errors:

  • AUTH_INVALID_GRANT — code expired or already used; re-run sf_get_oauth_auth_url
  • AUTH_CONNECTED_APP_NOT_READY — wait 2–10 min after creating the Connected App

Validation & discovery

sf_validate_connection

Makes a live Salesforce API call to confirm credentials work before writing any files to disk.

"Validate my Salesforce connection"
"Test that my credentials work"
Parameter Type Description
sf_client_id string Consumer Key
sf_client_secret string Consumer Secret
sf_refresh_token string Refresh token
sf_base_url string e.g. https://myorg.my.salesforce.com

Returns: connected, org_id, username, instance_url, is_sandbox.


sf_list_sobjects

Lists all SObjects in your org. Supports filtering and pagination.

"List all custom objects in my Salesforce org"
"Show me all Account-related SObjects"
"What objects are available in my org?"
Parameter Type Default Description
credentials required All 4 credential fields
include_custom boolean true Include __c objects
filter string Substring filter on name or label
limit integer 50 Max results (1–200)
offset integer 0 Pagination offset

Returns: total, count, has_more, next_offset, sobjects[].


sf_describe_sobject

Returns full field metadata for a specific SObject — field names, types, nullability, and relationship references.

"Describe the Invoice__c object"
"What fields does the Account object have?"
"Show me the schema for My_Custom__c"
Parameter Type Description
credentials All 4 credential fields
object_name string SObject API name, e.g. Account or My_Custom__c

Returns: name, label, field_count, fields[] with full type info.


Project scaffolding

sf_quickstart ⭐ Start here

One-shot setup: validates credentials → auto-detects sandbox → scaffolds the Ballerina project → (optional) compiles.

This is the recommended entry point. Most users only need this one tool after exchanging their OAuth code.

"Set up a Ballerina Salesforce project with my credentials"
"Scaffold the Salesforce integration and compile it to check for errors"
"Set up the integration and also add Account and Contact CDC listeners"
Parameter Type Default Description
sf_client_id string required Consumer Key
sf_client_secret string required Consumer Secret
sf_refresh_token string required Refresh token
sf_base_url string required e.g. https://myorg.my.salesforce.com
project_name string salesforce_integration Ballerina package name
org_name string wso2bi Ballerina org name in Ballerina.toml
bi_path string ~/WSO2Integrator WSO2 BI workspace root
target_objects string[] ["Account","Contact","Lead","Opportunity"] SObject API names to scaffold CRUD for
cdc_listeners array CDC / Platform Event listeners to add (see below)
build boolean false Run bal build after scaffolding
sandbox boolean auto-detected Override sandbox detection (detected from URL by default)

cdc_listeners entry — specify exactly one of:

Field Type Channel generated
sobject string /data/<SObject>ChangeEvent
all_changes boolean true /data/ChangeEvents
platform_event string (ends __e) /event/<Name>__e
events string[] Which callbacks: onCreate, onUpdate, onDelete, onRestore (default: all four)

Returns: status, connection, project_path, files_created, standard_sobjects, custom_sobjects, cdc_channels, ballerina_version, next_steps.


sf_scaffold_project

Granular alternative to sf_quickstart — scaffolds without the live credential validation step. Accepts the same parameters as sf_quickstart except build.

"Scaffold a Salesforce project — I've already validated my credentials"
"Create the project files for Account, Contact, and Invoice__c"

Project management

sf_write_config_toml

Overwrites Config.toml in an existing project with new credentials. Use this after token rotation without re-scaffolding the whole project.

Written with mode 0600 (owner read/write only). Sandbox is auto-detected from sf_base_url.

"Update the credentials in my existing project — my token was rotated"
"Rewrite Config.toml with these new values"
Parameter Type Description
project_path string Path to the existing Ballerina project
credentials All 4 credential fields

sf_add_custom_object

Adds a new SObject to an already-scaffolded project without re-scaffolding everything.

  • Standard SObjects: creates <object>.bal referencing the pre-built type from ballerinax/salesforce.types — no describe API call needed.
  • Custom (__c) objects: describes the schema live, appends a typed record to types.bal, and creates <object>.bal.

Returns: files_updated[], manual_step (route snippet to paste into main.bal).

"Add the Product2 object to my existing project"
"Add Invoice__c to the project — here are my credentials"
"I need to support Asset in addition to what's already scaffolded"
Parameter Type Description
project_path string Path to the existing project
credentials Required only for custom (__c) objects
object_name string SObject API name, e.g. Invoice__c

sf_add_cdc_listener

Adds an event-driven listener file to an existing project. Generates a .bal file with handler stubs using the same OAuth2 credentials already in main.bal — no extra Config.toml entries needed.

"Add a CDC listener for Account changes to my project"
"Listen for all CDC-enabled object changes"
"Add a platform event listener for OrderConfirmed__e"
"Add an Account listener but only scaffold onCreate and onUpdate"
Parameter Type Description
project_path string Path to the existing project
listener.sobject string SObject name → channel /data/<SObject>ChangeEvent
listener.all_changes boolean All objects → channel /data/ChangeEvents
listener.platform_event string (ends __e) Platform event → channel /event/<Name>__e
listener.events string[] CDC callbacks to scaffold (default: all four)

Specify exactly one of sobject, all_changes, or platform_event.

⚠️ CDC requires a Salesforce admin step: Setup → Integrations → Change Data Capture → enable objects. The MCP server generates the Ballerina code but cannot enable CDC in Salesforce itself.


Build & run

sf_build_project

Runs bal build in the project directory. Takes 30–90s on first build (downloads the connector from Ballerina Central). Reports the full compiler output.

"Build my Salesforce project"
"Compile the integration and show me any errors"
"Run bal build and check if everything is OK"
Parameter Type Description
project_path string Path to the Ballerina project

Returns: success, output (full compiler output), project_path.


sf_deploy_project

Starts the Ballerina service in the background via bal run. Waits up to 20 seconds for the HTTP listener banner. Ports are passed as configurable overrides so the reported service_url always matches the actual listener.

"Start the Salesforce integration service"
"Deploy the project on port 8080"
"Run the Ballerina service and give me the PID"
Parameter Type Default Description
project_path string required Path to the project
port integer 9090 HTTP listener port

Returns: pid (save this for sf_stop_project), started, service_url, health_check, output, message.

Endpoints once running:

Method Path Description
GET /health Health check — returns { status: "UP" }
GET /<object>s Query all records (SOQL, LIMIT 200)
GET /<object>/{id} Get a single record by Salesforce ID
POST /<object> Create a record
PUT /<object>/{id} Update a record
DELETE /<object>/{id} Delete a record

sf_stop_project

Stops a service started by sf_deploy_project. Only PIDs registered by this MCP server session can be stopped — it will not kill arbitrary system processes.

"Stop the Salesforce service"
"Kill the integration process with PID 12345"
Parameter Type Description
pid integer PID returned by sf_deploy_project

Postman & password-flow (no browser needed)

sf_generate_postman_collection ⭐ Generate a credential wallet

Takes your Salesforce credentials once, auto-obtains a refresh token via the password flow, and saves a ready-to-import Postman Collection v2.1 to disk. That single file becomes your reusable credential wallet:

  • Use in Postman — import and click "Get New Access Token" at any time, no configuration needed.
  • Use with this MCP — pass the saved file to sf_import_postman_credentials in any future session. No copy-pasting, no browser flows, no repeated auth setup.

The generated collection includes three folders:

  • 🔐 Authentication — Password Flow (no browser), Step 1-2 auth-code flow, and Token Refresh requests with auto-save test scripts
  • 🔍 Salesforce REST API — Validate Connection, List SObjects, Describe Account, SOQL Query, Create Account
  • 🔗 Ballerina Integration Service — Health Check, List/Create Accounts via the local Ballerina service
"Generate a Postman collection for my Salesforce org"
"Create a Salesforce Postman collection and save my credentials"
"Set up Postman for my Salesforce integration — username is me@myorg.com"
Parameter Type Default Description
sf_client_id string required Consumer Key from the Connected App
sf_client_secret string required Consumer Secret
sf_base_url string required e.g. https://myorg.my.salesforce.com
username string required Salesforce username (email)
password string required Password (append security token if required: myPasswordABC123)
redirect_uri string https://login.salesforce.com/services/oauth2/success Redirect URI registered in your Connected App
collection_name string Salesforce Integration Display name for the Postman collection
output_path string ~/WSO2Integrator/<collection_name>.postman_collection.json Where to save the file

Returns: collection_saved_to (file path), ready_for_quickstart (use directly with sf_quickstart), refresh_token_obtained (true/false).

One-time Salesforce Setup requirement (same as sf_get_token_password_flow):

Setup → Identity → OAuth and OpenID Connect Settings → enable "Allow OAuth Username-Password Flows"


sf_import_postman_credentials ⭐ Fastest onboarding

Reads a .postman_collection.json file and extracts every Salesforce credential it can find — clientId, clientSecret, refreshToken, instanceUrl, username, password — from the collection-level OAuth2 block and individual request bodies. No copy-pasting required.

Returns a ready_for_quickstart block you can pass directly to sf_quickstart. If the refresh token is expired, it tells you exactly which tool to call next (sf_get_token_password_flow).

"Import credentials from my Postman collection at ~/Documents/MCP-servers/wso2-bi-salesforce-mcp-server/_BalSFConnector.postman_collection.json"
"Read my Postman collection and set up the integration"
"Extract Salesforce credentials from ~/Downloads/MyOrg.postman_collection.json and validate them"
Parameter Type Default Description
postman_file string required Absolute or ~-relative path to the .postman_collection.json file
validate boolean true Make a live Salesforce API call to confirm extracted credentials work

Returns: credentials_found (secrets masked), ready_for_quickstart block, password_flow_args (if username+password present but no refresh token), next_action guidance.

What it extracts from the Postman file:

Postman location Fields extracted
Collection auth.oauth2 clientId, clientSecret, username, password, instanceUrl, redirectUri
Request body (urlencoded) refresh_token, client_id, client_secret
Request URL (query params) client_id, client_secret, redirect_uri

sf_get_token_password_flow

Gets a Salesforce OAuth2 refresh token using username + password only — no browser, no auth code redirect.

"Get a Salesforce refresh token using my username and password — no browser"
"Use the username/password from my Postman collection to get a refresh token"
Parameter Type Description
sf_client_id string Consumer Key from the Connected App
sf_client_secret string Consumer Secret
username string Salesforce username (email)
password string Password. If your org uses a security token, append it directly: myPassword + ABC123myPasswordABC123
sf_base_url string e.g. https://myorg.my.salesforce.com

Returns: refresh_token, instance_url, ready_for_quickstart block.

One-time Salesforce Setup requirement (30 seconds):

Setup → Identity → OAuth and OpenID Connect Settings → enable "Allow OAuth Username-Password Flows"

Common errors:

Error Cause Fix
authentication failure Wrong password or missing security token Append security token to password
invalid_client_credentials Wrong client_id or client_secret Check the Connected App's Consumer Key/Secret
unsupported_grant_type Username-password flow not enabled Enable it in Setup → Identity → OAuth and OpenID Connect Settings
No refresh_token returned Connected App missing offline_access scope Add "Perform requests at any time (refresh_token, offline_access)" scope

Generated project structure

~/WSO2Integrator/salesforce_integration/
├── Ballerina.toml          # Package: ballerinax/salesforce@8.7.0, dist 2201.12.0
├── Config.toml             # Mode 0600, gitignored — credentials + port
├── .gitignore              # Excludes Config.toml, target/, .ballerina/, Dependencies.toml
├── main.bal                # HTTP service + salesforce:Client + configurable vars
├── types.bal               # Custom __c typed records (empty if no custom objects)
├── account.bal             # Account CRUD: query, getById, create, update, delete
├── contact.bal             # Contact CRUD
├── lead.bal                # Lead CRUD
├── opportunity.bal         # Opportunity CRUD
├── cdc_account.bal         # (if requested) CDC listener for Account changes
├── event_order__e.bal      # (if requested) Platform event listener for Order__e
└── README.md               # Auto-generated project usage docs

Standard vs custom SObjects

SObject type Record type source Describe API call? Entry in types.bal?
Standard (Account, Contact, …) ballerinax/salesforce.types pre-built ❌ No ❌ No
Custom (My_Object__c) Generated from live describe ✅ Yes ✅ Yes

Using pre-built types means standard SObjects need zero describe calls during scaffolding — the project generates in seconds regardless of how many standard objects you include.

Environment variable fallbacks

main.bal uses Ballerina configurable for all credentials with os:getEnv() fallbacks. The same project runs in all environments without code changes:

Environment How credentials are supplied
Local dev Config.toml in project root
Docker / WSO2 BI runtime SF_CLIENT_ID, SF_CLIENT_SECRET, SF_REFRESH_TOKEN, SF_REFRESH_URL, SF_BASE_URL env vars
CI Mix — Config.toml wins when present

Sample project

A complete, runnable reference project is included at examples/sample_salesforce_integration/. It demonstrates both integration flows with production-quality error handling:

examples/sample_salesforce_integration/
├── Ballerina.toml             # connector v8.7.0, dist 2201.12.0
├── Config.toml.example        # copy to Config.toml and fill in your credentials
├── .gitignore
├── main.bal                   # HTTP service + shared salesforce:Client
├── account.bal                # Account CRUD with error classification + retry
├── cdc_account.bal            # CDC consumer flow (/data/AccountChangeEvent)
├── event_sample.bal           # Platform event consumer flow (/event/Sample_Event__e)
├── errors.bal                 # Typed errors, retry helper, HTTP status mapping
└── README.md                  # Run instructions, curl examples, troubleshooting

Publishing flowPOST /accountssfClient->create(), GET /accounts/{id}sfClient->getById(), etc.

Consuming flowsalesforce:Listener on /data/AccountChangeEvent with onCreate, onUpdate, onDelete, onRestore stubs, and a separate listener on /event/Sample_Event__e with onMessage.

Error handling — typed errors (RecordNotFound, ValidationFailed, DuplicateRecord, AuthFailed), HTTP status mapping (404/400/409/502/500), withRetry with exponential back-off for transient Salesforce errors (REQUEST_LIMIT_EXCEEDED, etc.).

cd examples/sample_salesforce_integration
cp Config.toml.example Config.toml
# fill in credentials
bal run

MCP server project structure

wso2-bi-salesforce-mcp-server/
├── src/
│   ├── index.ts                   # Entry point — server factory, stdio + HTTP transports
│   ├── types.ts                   # Shared TypeScript types, ToolError, error codes, maskSecret
│   ├── constants.ts               # SF constants, URL validation, sandbox detection, versions
│   ├── schemas/
│   │   └── tools.ts               # Zod schemas for all 15 tool inputs
│   ├── services/
│   │   ├── salesforce.ts          # Token management, SObject describe/list, validateConnection
│   │   ├── filesystem.ts          # writeFile, balBuild, balRun, checkBalCli, expandPath
│   │   └── generator.ts           # Ballerina code generators (main.bal, types.bal, CDC listeners)
│   └── tools/
│       ├── oauth.ts               # sf_get_oauth_auth_url, sf_exchange_oauth_code
│       ├── salesforce.ts          # sf_setup_guide, sf_check_prerequisites, sf_validate_connection,
│       │                          #   sf_list_sobjects, sf_describe_sobject
│       ├── ballerina.ts           # sf_quickstart, sf_scaffold_project, sf_write_config_toml,
│       │                          #   sf_add_custom_object, sf_add_cdc_listener,
│       │                          #   sf_build_project, sf_deploy_project, sf_stop_project
│       └── postman.ts             # sf_generate_postman_collection, sf_import_postman_credentials, sf_get_token_password_flow
├── examples/
│   └── sample_salesforce_integration/   # Complete runnable reference project
├── dist/                          # Compiled JavaScript (git-ignored)
├── package.json
├── tsconfig.json
└── README.md

Configuration

Environment variables for the MCP server

Variable Default Description
TRANSPORT stdio stdio or http
PORT 3001 HTTP listener port (HTTP mode only)
SF_MCP_HTTP_TOKEN Bearer token required on all /mcp requests (HTTP mode). Strongly recommended.
BAL_BIN bal Absolute path to the bal binary — useful when bal is installed but not on PATH.

Development

# Rebuild after changes
npm run build

# Watch mode (recompiles on save)
npm run dev

# Clean and rebuild
rm -rf dist && npm run build

To add a new tool:

  1. Add the Zod schema to src/schemas/tools.ts
  2. Add the handler in the appropriate file under src/tools/
  3. Register it with server.registerTool(...) in that file's register function
  4. Run npm run build

Security

Credential protection

  • Hostname allow-list: sf_base_url is validated against *.salesforce.com, *.force.com, *.cloudforce.com, and *.salesforce-setup.com before any credential is sent. Arbitrary URLs are rejected — prevents SSRF and credential exfiltration.
  • Config.toml written with mode 0600: Only the owning user can read it. Enforced on every write including credential rotation.
  • Token masking: sf_exchange_oauth_code masks the short-lived access_token in its output. Only the refresh_token is shown (it's the one you need to save).

Path safety

  • All user-supplied paths (project_path, bi_path) are resolved and verified to lie under $HOME or $TMPDIR. Path traversal attempts (../../etc/passwd) throw PATH_TRAVERSAL immediately.

Process safety

  • sf_deploy_project registers spawned PIDs in-process. sf_stop_project only terminates PIDs it started — it refuses to kill arbitrary system processes.

HTTP transport

  • Binds to 127.0.0.1 only — no external exposure by default.
  • Set SF_MCP_HTTP_TOKEN to require Authorization: Bearer <token> on every /mcp request.
  • /healthz is always unauthenticated (returns server name and version only).

Structured error codes

Every tool error returns a machine-readable code field so agents can handle failures precisely:

Code Meaning
AUTH_INVALID_GRANT Refresh token revoked or wrong endpoint (production vs sandbox)
AUTH_CONNECTED_APP_NOT_READY New Connected App still activating — wait 2–10 min
AUTH_INVALID_CLIENT Wrong Consumer Key or Secret
INVALID_URL sf_base_url failed hostname allow-list check
PATH_TRAVERSAL Path resolves outside allowed roots
NOT_FOUND Project directory or file not found
ALREADY_EXISTS Project or module file already exists
BAL_CLI_MISSING bal not on PATH — check BAL_BIN env var
BAL_BUILD_FAILED Compilation failed — see output field
PRECONDITION_FAILED Required file missing (e.g. Config.toml before deploy)
TRANSIENT Network error — check connectivity and retry
INVALID_INPUT Validation error (e.g. invalid SObject name format)
UNKNOWN Unexpected error

Troubleshooting

AUTH_CONNECTED_APP_NOT_READY on first use

Salesforce Connected Apps take 2–10 minutes to activate after creation. Wait and retry sf_exchange_oauth_code or sf_validate_connection.

bal not found

which bal      # should print a path like /usr/local/bin/bal
bal version    # should print Ballerina 2201.12.0 (Swan Lake)

If missing, install from ballerina.io/downloads. If bal is installed but not on PATH:

BAL_BIN=/path/to/bal node dist/index.js

First bal build is slow

The first build downloads ballerinax/salesforce@8.7.0 from Ballerina Central. Ensure you have internet access and allow up to 3 minutes. Subsequent builds use the local cache.

CDC events not arriving

  1. Enable CDC for the object: Salesforce Setup → Integrations → Change Data Capture → select your object → Save.
  2. CDC requires Enterprise, Unlimited, Performance, or Developer Edition.
  3. Ensure OAuth scopes include api and refresh_token.

Platform event listener fails to start

The channel /event/YourEvent__e must exist in your org before the listener can attach. Create the Platform Event in Salesforce Setup → Platform Events.

Service starts but /health returns connection refused

The 20-second startup window elapsed before the listener banner was detected. The service may still be starting — wait a few seconds and retry. Check the output field in the sf_deploy_project result for error messages.

PATH_TRAVERSAL error

Your project_path or bi_path resolves outside $HOME or $TMPDIR. Use a path inside your home directory, or run with extra roots:

SF_MCP_ALLOWED_ROOTS=/data/projects node dist/index.js

Token expired mid-session

Access tokens are short-lived (~2 hours). The connector refreshes them automatically using the stored refresh_token. If you see INVALID_SESSION_ID errors, the refresh token itself may have been revoked — re-run sf_get_oauth_auth_url and sf_exchange_oauth_code to get a new one, then call sf_write_config_toml to update the project without re-scaffolding.

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured