About
Sfdcmcpsrv — Model Context Protocol server
README
A Spring Boot MCP (Model Context Protocol) server that exposes Salesforce REST API operations to AI clients such as Claude Desktop. It communicates over stdin/stdout — there is no HTTP port. AI clients send tool calls over the MCP protocol and receive JSON responses, while the server handles all Salesforce OAuth and REST API plumbing transparently.
Architecture
graph LR
subgraph client["AI Client"]
ai["Claude Desktop\n/ AI Agent"]
end
subgraph server["MCP Server · this project"]
direction TB
stdio["stdio Transport\n(Spring AI MCP)"]
tools["SalesforceMcpTools\ndescribe_sobject · create_record · soql_query"]
rest["SalesforceRestService\nHTTP calls · 401 retry"]
auth["UserImpersonationService\nJWT Bearer · per-user token cache"]
key[("server.key\nRSA-2048 private key")]
end
subgraph sfdc["Salesforce"]
oauth["OAuth 2.0\n/services/oauth2/token"]
api["REST API\n/services/data/v63.0/…"]
end
ai <-->|"MCP protocol (stdin / stdout)"| stdio
stdio --> tools
tools --> rest
rest --> auth
key --> auth
auth -->|"RS256 JWT (sub = targetUsername)"| oauth
oauth -->|"access_token + instance_url"| auth
rest -->|"Bearer token"| api
api -->|"JSON response"| rest
Request Flow
Every MCP tool call goes through this sequence. The token cache means Salesforce is only contacted for a new token once per user per ~110 minutes.
sequenceDiagram
participant AI as AI Client
participant MCP as MCP Server
participant Auth as UserImpersonationService
participant Tok as Salesforce OAuth
participant API as Salesforce REST API
AI ->> MCP : tool call (targetUsername, objectName, …)
MCP ->> Auth : getAccessTokenForUser(targetUsername)
alt Token cached and valid (within 110-minute TTL)
Auth -->> MCP : cached access_token + instance_url
else Cache miss or token expired
Auth ->> Tok : POST /services/oauth2/token<br/>JWT iss=clientId · sub=targetUsername · exp=+3 min · sig=RS256
Tok -->> Auth : access_token + instance_url
Note over Auth : stored in ConcurrentHashMap<br/>with 110-minute TTL
Auth -->> MCP : access_token + instance_url
end
MCP ->> API : GET / POST Authorization: Bearer <access_token>
alt Salesforce returns 401 (token revoked mid-session)
API -->> MCP : 401 Unauthorized
MCP ->> Auth : invalidateToken(targetUsername)
MCP ->> Auth : getAccessTokenForUser(targetUsername)
Auth ->> Tok : fresh JWT exchange
Tok -->> Auth : new access_token
MCP ->> API : retry original request
end
API -->> MCP : JSON payload
MCP -->> AI : tool result (JSON string)
MCP Tools
| Tool | Parameters | Description |
|---|---|---|
describe_sobject |
targetUsername, objectName |
Returns the full schema of a Salesforce SObject — field names, types, createable/updateable flags. |
create_record |
targetUsername, objectName, fieldsJson (JSON object) |
Validates fields against the describe result, then creates a new record. Returns the new record ID. |
soql_query |
targetUsername, objectName, fieldsJson (JSON array of field names) |
Runs SELECT <fields> FROM <object> and returns all matching records. |
targetUsername is the Salesforce user the integration account impersonates for each call.
The server signs a fresh JWT with sub = targetUsername, exchanges it for an access token, and executes the REST call as that user.
Salesforce Org Prerequisites
Complete these steps once in your Salesforce org before running the server.
1 — Generate an RSA key pair
# Generate a 2048-bit private key
openssl genrsa -out server.key 2048
# Generate the self-signed public certificate (valid 10 years)
openssl req -new -x509 -key server.key -out server.crt -days 3650 \
-subj "/CN=sfdc-mcp-server"
Place server.key at the path configured by salesforce.private-key-path in application.properties.
Keep the private key out of version control.
2 — Create a Connected App
- Go to Setup → Apps → App Manager → New Connected App.
- Fill in Connected App Name and Contact Email.
- Under API (Enable OAuth Settings):
- Check Enable OAuth Settings.
- Set Callback URL to
https://login.salesforce.com/services/oauth2/success(not used, but required). - Add OAuth scopes: Manage user data via APIs (api) and Perform requests at any time (refresh_token, offline_access).
- Check Use digital signatures and upload
server.crt.
- Save. Salesforce may take 2–10 minutes to activate the new Connected App.
3 — Configure the Connected App policy
After the Connected App is saved:
- Go to Setup → Apps → App Manager, find the app, click Manage.
- Click Edit Policies.
- Set Permitted Users to
Admin approved users are pre-authorized. - Save.
This setting is required for the JWT Bearer OAuth flow.
4 — Authorize users for impersonation
Each Salesforce user the MCP server will impersonate (i.e. every value ever passed as targetUsername) must be pre-authorized:
- On the Connected App's Manage page, scroll to the Profiles section.
- Click Manage Profiles.
- Add the Profile assigned to each user that will be impersonated.
- Save.
Tip: Assign users to a single shared profile (e.g. a dedicated "MCP Users" profile) to keep this list manageable.
5 — Note the Consumer Key
- Go to Setup → Apps → App Manager, find the app, click View.
- Copy the Consumer Key value.
- Set it as
salesforce.client-idinapplication.properties.
Configuration
All settings live in src/main/resources/application.properties:
salesforce.org-url=https://<your-org>.my.salesforce.com
salesforce.client-id=<Consumer Key from Connected App>
salesforce.integration-username=<[email protected]>
salesforce.private-key-path=/absolute/path/to/server.key
salesforce.api-version=v63.0
salesforce.integration-username identifies the Connected App owner in Salesforce audit logs.
It is not the user executing API calls — that is determined per tool call via targetUsername.
Building and Running
# Build
./mvnw clean package
# Run (MCP server connects via stdio — attach to an AI client, not a terminal)
./mvnw spring-boot:run
Console logging is suppressed so it does not corrupt the stdio MCP stream.
All logs go to ./logs/mcp-server.log.
Connecting to Claude Desktop
Add the following to your Claude Desktop claude_desktop_config.json:
{
"mcpServers": {
"salesforce": {
"command": "java",
"args": ["-jar", "/path/to/sfdcmcpsrv-0.0.1-SNAPSHOT.jar"]
}
}
}
Testing
Smoke test (no Salesforce connection required)
./mvnw test
Verifies the Spring context loads and all beans wire up correctly.
Integration tests (live Salesforce org)
- Open
src/test/resources/application-test.properties. - Set
salesforce.test-usernameto a Salesforce user whose profile is pre-authorized on the Connected App (see Step 4 above). - Run:
# All integration tests
./mvnw test -Dspring.profiles.active=test
# Single entity
./mvnw test -Dtest=AccountMcpToolsIntegrationTest -Dspring.profiles.active=test
./mvnw test -Dtest=ContactMcpToolsIntegrationTest -Dspring.profiles.active=test
Tests auto-skip (reported as skipped, not failed) when salesforce.test-username is blank.
Note: Each integration test run creates real records in Salesforce. Periodically delete records whose
Namestarts withMCPin your test org.
Stack
| Layer | Technology |
|---|---|
| Language | Java 25 |
| Framework | Spring Boot 4.1.0 |
| MCP transport | Spring AI 2.0.0 (spring-ai-starter-mcp-server) |
| Salesforce auth | JWT Bearer OAuth 2.0 (JJWT 0.11.5, RS256) |
| HTTP client | java.net.http.HttpClient (JDK built-in) |
| JSON | Jackson 2.15 |
Installing Sfdcmcpsrv
This server has no published package — it is built from source. Open the repository and follow its README.
▸ github.com/monchrome/sfdcmcpsrvFAQ
Is Sfdcmcpsrv MCP free?
Yes, Sfdcmcpsrv MCP is free — one-click install via Unyly at no cost.
Does Sfdcmcpsrv need an API key?
No, Sfdcmcpsrv runs without API keys or environment variables.
Is Sfdcmcpsrv hosted or self-hosted?
Self-hosted: the server runs locally on your machine via the install command above.
How do I install Sfdcmcpsrv in Claude Desktop, Claude Code or Cursor?
Open Sfdcmcpsrv on unyly.org, pick your client tab (Claude Desktop, Claude Code, Cursor) and press Install — the config is generated automatically, no JSON editing.
Related MCPs
Fetch
Web content fetching and conversion for efficient LLM usage.
AWS KB Retrieval
Retrieval from AWS Knowledge Base using Bedrock Agent Runtime.
by modelcontextprotocolSpring AI MCP Server
Provides auto-configuration for setting up an MCP server in Spring Boot applications.
llm-analysis-assistant
A very streamlined mcp client that supports calling and monitoring stdio/sse/streamableHttp, and can also view request responses through the /logs page. It also
by xuzexin-hzCompare Sfdcmcpsrv with
Not sure what to pick?
Find your stack in 60 seconds
Author?
Embed badge for your README
Browse similar
All ai MCPs
