wso2-bi-salesforce-mcp-server
Provides tools for setting up, building, and managing Salesforce integrations using Ballerina within a WSO2 Integrator environment, including credential management, project scaffolding, and deployment.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@wso2-bi-salesforce-mcp-serverCreate a new Ballerina Salesforce integration project"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
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 |
18+ | Run the MCP server | |
2201.12.0 (Swan Lake) | Build and run Ballerina projects | |
Any | Clone the repo | |
Salesforce org | Any edition | Developer Edition is free — sign up |
Ballerina | 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-server2. Install dependencies
npm install3. Build the server
npm run buildThis 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.jsYou 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 |
macOS / Linux |
|
Windows |
|
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
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.jsonAdd the server under
mcpServers:{ "mcpServers": { "ballerina-salesforce": { "command": "node", "args": [ "/absolute/path/to/wso2-bi-salesforce-mcp-server/dist/index.js" ] } } }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.jsVerify:
claude mcp listManual — 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.jsonis not a valid path. User-scope MCP config lives in~/.claude.json(top-level key). Project-scope config lives in.mcp.jsonat the project root, not inside.claude/.
Cursor
Open Cursor → Settings → Features → MCP (or
Cursor Settings > MCP).Click Add new MCP server.
Fill in:
Name:
ballerina-salesforceType:
stdioCommand:
nodeArgs:
/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.jsMCP endpoint:
http://127.0.0.1:3001/mcpAuth header:
Authorization: Bearer your-secret-tokenHealth check:
http://127.0.0.1:3001/healthz
⚠️ Always set
SF_MCP_HTTP_TOKENin 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:
nodeArgs:
["/absolute/path/to/wso2-bi-salesforce-mcp-server/dist/index.js"]Transport:
stdioProtocol: 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:
Validates your credentials with a live Salesforce API call
Auto-detects sandbox vs production from the URL
Scaffolds a complete Ballerina project at
~/WSO2Integrator/salesforce_integration/Writes
Config.tomlwith mode 0600 (owner read/write only)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_guidegives you the exact steps. In short:
Salesforce → Setup → App Manager → New Connected App
Enable OAuth: scopes
api+refresh_token (offline_access), callbackhttps://login.salesforce.com/services/oauth2/successSave → copy Consumer Key and Consumer Secret
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.jsonfile. 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 serviceStep-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 doneFastest 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 doneStarting 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 doneStarting 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 doneOr 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 doneTool 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 |
| boolean |
| 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 |
| string | required | Consumer Key from your Connected App |
| string |
| Must match your Connected App |
| boolean |
| Use |
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_tokenis intentionally masked in output — it's shown asaccess_token_previewonly. 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 |
| string | required | Consumer Key |
| string | required | Consumer Secret |
| string | required | The |
| string | success URL | Same URI used in |
| boolean |
| 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-runsf_get_oauth_auth_urlAUTH_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 |
| string | Consumer Key |
| string | Consumer Secret |
| string | Refresh token |
| string | e.g. |
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 |
| boolean |
| Include |
| string | — | Substring filter on name or label |
| integer |
| Max results (1–200) |
| integer |
| 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 |
| string | SObject API name, e.g. |
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 |
| string | required | Consumer Key |
| string | required | Consumer Secret |
| string | required | Refresh token |
| string | required | e.g. |
| string |
| Ballerina package name |
| string |
| Ballerina org name in |
| string |
| WSO2 BI workspace root |
| string[] |
| SObject API names to scaffold CRUD for |
| array | — | CDC / Platform Event listeners to add (see below) |
| boolean |
| Run |
| boolean | auto-detected | Override sandbox detection (detected from URL by default) |
cdc_listeners entry — specify exactly one of:
Field | Type | Channel generated |
| string |
|
| boolean |
|
| string (ends |
|
| string[] | Which callbacks: |
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 |
| 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>.balreferencing the pre-built type fromballerinax/salesforce.types— nodescribeAPI call needed.Custom (
__c) objects: describes the schema live, appends a typed record totypes.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 |
| string | Path to the existing project |
credentials | — | Required only for custom ( |
| string | SObject API name, e.g. |
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 |
| string | Path to the existing project |
| string | SObject name → channel |
| boolean | All objects → channel |
| string (ends | Platform event → channel |
| string[] | CDC callbacks to scaffold (default: all four) |
Specify exactly one of
sobject,all_changes, orplatform_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 |
| 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 |
| string | required | Path to the project |
| integer |
| HTTP listener port |
Returns: pid (save this for sf_stop_project), started, service_url, health_check, output, message.
Endpoints once running:
Method | Path | Description |
|
| Health check — returns |
|
| Query all records (SOQL, LIMIT 200) |
|
| Get a single record by Salesforce ID |
|
| Create a record |
|
| Update a record |
|
| 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 |
| integer | PID returned by |
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_credentialsin 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 |
| string | required | Consumer Key from the Connected App |
| string | required | Consumer Secret |
| string | required | e.g. |
| string | required | Salesforce username (email) |
| string | required | Password (append security token if required: |
| string |
| Redirect URI registered in your Connected App |
| string |
| Display name for the Postman collection |
| string |
| 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 |
| string | required | Absolute or |
| boolean |
| 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 |
|
Request body (urlencoded) |
|
Request URL (query params) |
|
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 |
| string | Consumer Key from the Connected App |
| string | Consumer Secret |
| string | Salesforce username (email) |
| string | Password. If your org uses a security token, append it directly: |
| string | e.g. |
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 |
| Wrong password or missing security token | Append security token to password |
| Wrong | Check the Connected App's Consumer Key/Secret |
| Username-password flow not enabled | Enable it in Setup → Identity → OAuth and OpenID Connect Settings |
No | Connected App missing | 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 docsStandard vs custom SObjects
SObject type | Record type source | Describe API call? | Entry in types.bal? |
Standard ( |
| ❌ No | ❌ No |
Custom ( | 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 |
|
Docker / WSO2 BI runtime |
|
CI | Mix — |
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, troubleshootingPublishing flow — POST /accounts → sfClient->create(), GET /accounts/{id} → sfClient->getById(), etc.
Consuming flow — salesforce: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 runMCP 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.mdConfiguration
Environment variables for the MCP server
Variable | Default | Description |
|
|
|
|
| HTTP listener port (HTTP mode only) |
| — | Bearer token required on all |
|
| Absolute path to the |
Development
# Rebuild after changes
npm run build
# Watch mode (recompiles on save)
npm run dev
# Clean and rebuild
rm -rf dist && npm run buildTo add a new tool:
Add the Zod schema to
src/schemas/tools.tsAdd the handler in the appropriate file under
src/tools/Register it with
server.registerTool(...)in that file's register functionRun
npm run build
Security
Credential protection
Hostname allow-list:
sf_base_urlis validated against*.salesforce.com,*.force.com,*.cloudforce.com, and*.salesforce-setup.combefore any credential is sent. Arbitrary URLs are rejected — prevents SSRF and credential exfiltration.Config.tomlwritten with mode0600: Only the owning user can read it. Enforced on every write including credential rotation.Token masking:
sf_exchange_oauth_codemasks the short-livedaccess_tokenin its output. Only therefresh_tokenis 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$HOMEor$TMPDIR. Path traversal attempts (../../etc/passwd) throwPATH_TRAVERSALimmediately.
Process safety
sf_deploy_projectregisters spawned PIDs in-process.sf_stop_projectonly terminates PIDs it started — it refuses to kill arbitrary system processes.
HTTP transport
Binds to
127.0.0.1only — no external exposure by default.Set
SF_MCP_HTTP_TOKENto requireAuthorization: Bearer <token>on every/mcprequest./healthzis 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 |
| Refresh token revoked or wrong endpoint (production vs sandbox) |
| New Connected App still activating — wait 2–10 min |
| Wrong Consumer Key or Secret |
|
|
| Path resolves outside allowed roots |
| Project directory or file not found |
| Project or module file already exists |
|
|
| Compilation failed — see |
| Required file missing (e.g. |
| Network error — check connectivity and retry |
| Validation error (e.g. invalid SObject name format) |
| 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.jsFirst 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
Enable CDC for the object: Salesforce Setup → Integrations → Change Data Capture → select your object → Save.
CDC requires Enterprise, Unlimited, Performance, or Developer Edition.
Ensure OAuth scopes include
apiandrefresh_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.jsToken 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.
Maintenance
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