@mindstone/mcp-server-salesforce 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +116 -3
- package/dist/client.js +9 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,13 +1,117 @@
|
|
|
1
1
|
# @mindstone/mcp-server-salesforce
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/@mindstone/mcp-server-salesforce)
|
|
4
|
+
[](./LICENSE)
|
|
5
|
+
|
|
3
6
|
Salesforce CRM MCP server — accounts, contacts, opportunities, leads, tasks, users, and custom objects via the Salesforce API.
|
|
4
7
|
|
|
5
|
-
|
|
8
|
+
*Best when an MCP host needs a local, install-and-run CRM connector for everyday sales work rather than a Salesforce-hosted endpoint.*
|
|
9
|
+
|
|
10
|
+
## Status
|
|
11
|
+
|
|
12
|
+
- **Version:** [0.1.2](./CHANGELOG.md) · [npm](https://www.npmjs.com/package/@mindstone/mcp-server-salesforce)
|
|
13
|
+
- **Auth:** OAuth (local 127.0.0.1 callback) or static access token ([`SALESFORCE_CLIENT_SECRET`](./server.json), [`SALESFORCE_ACCESS_TOKEN`](./server.json))
|
|
14
|
+
- **Tools:** [26](./src/tools/) (accounts, contacts, opportunities, leads, tasks, query)
|
|
15
|
+
- **Surface:** cloud-api
|
|
16
|
+
- **Machine-readable:** [`STATUS.json`](./STATUS.json)
|
|
17
|
+
|
|
18
|
+
## Why this exists
|
|
19
|
+
|
|
20
|
+
Salesforce's own MCP options are the right starting point for many teams. This package is for teams that want a normal npm MCP server they can run locally in any stdio host.
|
|
21
|
+
|
|
22
|
+
It gives an assistant focused access to the CRM work people actually ask for: finding accounts and contacts, updating leads, creating opportunities and tasks, running CRM searches, and working with custom objects. The benefit is a short path from a natural-language sales request to the right Salesforce records, with write actions kept visible to the host.
|
|
23
|
+
|
|
24
|
+
## Example interaction
|
|
25
|
+
|
|
26
|
+
> "Find Acme Corp in Salesforce, create a Q3 expansion opportunity for $75,000, and add a follow-up task for next Friday."
|
|
27
|
+
|
|
28
|
+
Tools the host calls:
|
|
29
|
+
1. `salesforce_get_accounts` — searches accounts by name and returns the matching account ID.
|
|
30
|
+
2. `salesforce_create_opportunity` — creates the opportunity against that account.
|
|
31
|
+
3. `salesforce_create_task` — adds a follow-up task related to the new opportunity.
|
|
32
|
+
|
|
33
|
+
Response (trimmed):
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
{
|
|
37
|
+
"account": { "id": "001xx000003DGbYAAW", "name": "Acme Corp" },
|
|
38
|
+
"opportunity": {
|
|
39
|
+
"id": "006xx000004TmiYAAS",
|
|
40
|
+
"name": "Q3 expansion",
|
|
41
|
+
"amount": 75000,
|
|
42
|
+
"stage": "Prospecting"
|
|
43
|
+
},
|
|
44
|
+
"task": {
|
|
45
|
+
"id": "00Txx000006rYxDEAU",
|
|
46
|
+
"subject": "Follow up on Q3 expansion"
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Requirements
|
|
52
|
+
|
|
53
|
+
- Node.js 20+
|
|
54
|
+
- npm
|
|
55
|
+
- A Salesforce Connected App for the OAuth path, or a valid access token plus instance URL for manual-token mode.
|
|
56
|
+
|
|
57
|
+
<!-- BEGIN INSTALL_LINKS: do not edit by hand; regenerated by scripts/gen-install-links.mjs -->
|
|
58
|
+
## One-click install
|
|
59
|
+
|
|
60
|
+
[](cursor://anysphere.cursor-deeplink/mcp/install?name=Salesforce&config=eyJ0eXBlIjoic3RkaW8iLCJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBtaW5kc3RvbmUvbWNwLXNlcnZlci1zYWxlc2ZvcmNlIl0sImVudiI6eyJTQUxFU0ZPUkNFX0NMSUVOVF9JRCI6IiIsIlNBTEVTRk9SQ0VfQ0xJRU5UX1NFQ1JFVCI6IiIsIlNBTEVTRk9SQ0VfQUNDRVNTX1RPS0VOIjoiIiwiU0FMRVNGT1JDRV9DT05GSUdfRElSIjoifi8ubWNwL3NhbGVzZm9yY2UiLCJTQUxFU0ZPUkNFX09BVVRIX1BPUlQiOiIwIn19)
|
|
61
|
+
[](vscode:mcp/install?%7B%22name%22%3A%22Salesforce%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40mindstone%2Fmcp-server-salesforce%22%5D%2C%22env%22%3A%7B%22SALESFORCE_CLIENT_ID%22%3A%22%22%2C%22SALESFORCE_CLIENT_SECRET%22%3A%22%22%2C%22SALESFORCE_ACCESS_TOKEN%22%3A%22%22%2C%22SALESFORCE_CONFIG_DIR%22%3A%22%7E%2F.mcp%2Fsalesforce%22%2C%22SALESFORCE_OAUTH_PORT%22%3A%220%22%7D%7D)
|
|
62
|
+
[](vscode-insiders:mcp/install?%7B%22name%22%3A%22Salesforce%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40mindstone%2Fmcp-server-salesforce%22%5D%2C%22env%22%3A%7B%22SALESFORCE_CLIENT_ID%22%3A%22%22%2C%22SALESFORCE_CLIENT_SECRET%22%3A%22%22%2C%22SALESFORCE_ACCESS_TOKEN%22%3A%22%22%2C%22SALESFORCE_CONFIG_DIR%22%3A%22%7E%2F.mcp%2Fsalesforce%22%2C%22SALESFORCE_OAUTH_PORT%22%3A%220%22%7D%7D)
|
|
63
|
+
|
|
64
|
+
After clicking the button, your host will prompt you to fill: `SALESFORCE_CLIENT_ID`, `SALESFORCE_CLIENT_SECRET`, `SALESFORCE_ACCESS_TOKEN`, `SALESFORCE_CONFIG_DIR`, `SALESFORCE_OAUTH_PORT`.
|
|
65
|
+
|
|
66
|
+
<details>
|
|
67
|
+
<summary>Manual config for Claude Desktop / Claude Code / Goose / Continue.dev (Salesforce)</summary>
|
|
68
|
+
|
|
69
|
+
```json
|
|
70
|
+
{
|
|
71
|
+
"mcpServers": {
|
|
72
|
+
"Salesforce": {
|
|
73
|
+
"command": "npx",
|
|
74
|
+
"args": [
|
|
75
|
+
"-y",
|
|
76
|
+
"@mindstone/mcp-server-salesforce"
|
|
77
|
+
],
|
|
78
|
+
"env": {
|
|
79
|
+
"SALESFORCE_CLIENT_ID": "",
|
|
80
|
+
"SALESFORCE_CLIENT_SECRET": "",
|
|
81
|
+
"SALESFORCE_ACCESS_TOKEN": "",
|
|
82
|
+
"SALESFORCE_CONFIG_DIR": "~/.mcp/salesforce",
|
|
83
|
+
"SALESFORCE_OAUTH_PORT": "0"
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
</details>
|
|
91
|
+
<!-- END INSTALL_LINKS -->
|
|
92
|
+
|
|
93
|
+
## Quick Start
|
|
94
|
+
|
|
95
|
+
### Install & build
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
cd <path-to-repo>/connectors/salesforce
|
|
99
|
+
npm install
|
|
100
|
+
npm run build
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### npx
|
|
6
104
|
|
|
7
105
|
```bash
|
|
8
106
|
npx -y @mindstone/mcp-server-salesforce
|
|
9
107
|
```
|
|
10
108
|
|
|
109
|
+
### Local
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
node dist/index.js
|
|
113
|
+
```
|
|
114
|
+
|
|
11
115
|
## Configuration
|
|
12
116
|
|
|
13
117
|
### OAuth (Recommended)
|
|
@@ -28,6 +132,8 @@ Then call `salesforce_connect_account` to start the OAuth flow.
|
|
|
28
132
|
### Additional Options
|
|
29
133
|
|
|
30
134
|
- `SALESFORCE_CONFIG_DIR` — Custom config directory (default: `~/.mcp/salesforce`)
|
|
135
|
+
- `SALESFORCE_OAUTH_PORT` — OAuth callback port (`0` = OS-assigned; default: `0`)
|
|
136
|
+
- `SALESFORCE_OAUTH_SCOPES` — Space-separated OAuth scopes. Leave unset to use the connector default.
|
|
31
137
|
|
|
32
138
|
## Available Tools (26)
|
|
33
139
|
|
|
@@ -75,6 +181,13 @@ Then call `salesforce_connect_account` to start the OAuth flow.
|
|
|
75
181
|
- `salesforce_update_record` — Update any Salesforce record
|
|
76
182
|
- `salesforce_get_records` — Query any Salesforce object
|
|
77
183
|
|
|
78
|
-
##
|
|
184
|
+
## Security notes
|
|
185
|
+
|
|
186
|
+
- The standalone OAuth callback server binds to `127.0.0.1`; it does not honour environment overrides that would expose the callback beyond loopback.
|
|
187
|
+
- OAuth credentials are stored under `SALESFORCE_CONFIG_DIR` (default `~/.mcp/salesforce`) with restrictive directory and file permissions.
|
|
188
|
+
- Write and disconnect tools are marked so capable hosts can ask for confirmation before changing Salesforce data.
|
|
189
|
+
- SOQL helper paths escape string and `LIKE` values, strip comments quote-safely before applying the query limit cap, and enforce a maximum of 200 records for raw SOQL queries.
|
|
190
|
+
|
|
191
|
+
## Licence
|
|
79
192
|
|
|
80
|
-
FSL-1.1-MIT
|
|
193
|
+
[FSL-1.1-MIT](./LICENSE) — Functional Source License, Version 1.1, with MIT future licence. The software converts to MIT licence on 2030-04-08.
|
package/dist/client.js
CHANGED
|
@@ -44,10 +44,18 @@ export async function getConnection(accountId) {
|
|
|
44
44
|
const connectionConfig = {
|
|
45
45
|
instanceUrl: tokenData.instance_url,
|
|
46
46
|
accessToken: tokenData.access_token,
|
|
47
|
-
refreshToken: tokenData.refresh_token,
|
|
48
47
|
};
|
|
48
|
+
// Only hand jsforce a refresh token when we can also give it a way to USE
|
|
49
|
+
// that token — i.e. the OAuth2 client info to build a refresh delegate.
|
|
50
|
+
// jsforce throws synchronously at construction otherwise:
|
|
51
|
+
// "Refresh token is specified without oauth2 client information or refresh function".
|
|
52
|
+
// This is the bridge-mode case: the host app owns OAuth and does not pass
|
|
53
|
+
// SALESFORCE_CLIENT_ID/SECRET into the connector, so we operate on the access
|
|
54
|
+
// token alone and surface SESSION_EXPIRED (-> reconnect) on expiry rather than
|
|
55
|
+
// crashing every tool call. (See docs/plans/260612_fix-salesforce-bridge-refresh-token/.)
|
|
49
56
|
if (clientId && clientSecret && tokenData.refresh_token) {
|
|
50
57
|
connectionConfig.oauth2 = { clientId, clientSecret, loginUrl };
|
|
58
|
+
connectionConfig.refreshToken = tokenData.refresh_token;
|
|
51
59
|
}
|
|
52
60
|
const conn = new jsforce.Connection(connectionConfig);
|
|
53
61
|
conn.on('refresh', async (accessToken) => {
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mindstone/mcp-server-salesforce",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"mcpName": "io.github.mindstone/mcp-server-salesforce",
|
|
5
|
-
"description": "Salesforce CRM MCP server
|
|
5
|
+
"description": "Salesforce CRM MCP server — accounts, contacts, opportunities, leads, tasks, and custom objects via Salesforce API",
|
|
6
6
|
"license": "FSL-1.1-MIT",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"bin": {
|