Skip to main content
Glama
PasinduGunarathne

wso2-bi-salesforce-mcp-server

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).


Related MCP server: MCP Salesforce Lite

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.

# 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.

Install Server
F
license - not found
A
quality
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/PasinduGunarathne/wso2-bi-salesforce-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server