salesforce-remote-mcp-cloudflare
A remote MCP server for Salesforce deployed on Cloudflare Workers, enabling Claude to query and manage Salesforce data through SOQL, SOSL, DML, and Apex with per-user OAuth.
README
salesforce-remote-mcp-cloudflare
A remote MCP (Model Context Protocol) server for Salesforce, deployable on
Cloudflare Workers as a Claude custom connector. It exposes the same 15
Salesforce tools as the local stdio package
@tsmztech/mcp-server-salesforce —
SOQL/SOSL queries, DML, object/field/metadata management, Apex read/write/execute,
debug logs — over Streamable HTTP with full per-user OAuth.
This is a self-hosted template, not a hosted service. You (the setup admin) create a Salesforce Connected App in your org, deploy your own Worker with your own credentials, and register your Worker's URL in Claude. Nothing is shared with anyone else, and no credentials ever leave your Cloudflare account and your Salesforce org.
How it works
Claude (web/desktop/mobile)
│ OAuth 2.1 ─ handled automatically (Dynamic Client Registration, PKCE)
▼
Your Cloudflare Worker ← this repo
│ "Login with Salesforce" ─ your Connected App (OAuth Web Server flow + PKCE)
▼
Your Salesforce org
There are two separate OAuth relationships:
- Claude ↔ Worker — handled entirely by
@cloudflare/workers-oauth-provider. You configure nothing for this; Claude registers itself automatically. - Worker ↔ Salesforce — your Connected App. Its consumer key/secret live only in Worker secrets.
When a user clicks Connect in Claude, they are redirected to your org's Salesforce
login page. Their Salesforce tokens are stored encrypted inside the OAuth grant and are
never visible to Claude or to other users. Every tool call runs as the connected
user — their profile, permissions, and field-level security apply. Expired access
tokens are refreshed automatically (proactively when Claude refreshes its own token,
and reactively on INVALID_SESSION_ID).
One deployment = one Salesforce org. The org (production, sandbox, or a My Domain) is fixed by your configuration. End users don't pick an org — they just log in with their own identity in that org. To serve a second org, deploy a second Worker.
Prerequisites
- A Cloudflare account (free tier works) — sign up
- Node.js 18+ and npm
- A Salesforce org you administer (production, Developer Edition, or sandbox)
- A Claude plan that supports custom connectors (Pro, Max, Team, or Enterprise)
Step 1 — Deploy the Worker
Deploy first: you need your Worker's URL before you can create the Connected App (its OAuth callback points at the Worker).
git clone <this-repo>
cd salesforce-remote-mcp-cloudflare
npm install --legacy-peer-deps
npx wrangler login
Create the KV namespace the OAuth provider stores its (encrypted) state in:
npx wrangler kv namespace create OAUTH_KV
Copy the printed id into wrangler.jsonc:
"kv_namespaces": [{ "binding": "OAUTH_KV", "id": "<your-id-here>" }],
In the same file, set your org's login host — this pins the deployment to your org:
// production / Developer Edition: login.salesforce.com
// sandbox: test.salesforce.com
// My Domain (recommended): yourcompany.my.salesforce.com
"vars": { "SALESFORCE_LOGIN_HOST": "login.salesforce.com" }
Set the state-encryption key (any long random value; you never need it again):
openssl rand -base64 32 | npx wrangler secret put COOKIE_ENCRYPTION_KEY
Deploy:
npx wrangler deploy
Note the URL wrangler prints, e.g.
https://salesforce-remote-mcp-cloudflare.<your-subdomain>.workers.dev.
That is your Worker URL — you'll use it in Steps 2 and 4. (The server won't work
yet; it still needs the Connected App credentials from the next step.)
Step 2 — Create the Connected App in Salesforce
Connected Apps can only be created through the Setup UI — the Metadata API blocks programmatic creation, so there is no CLI shortcut for this step.
- In your org: Setup → App Manager → New Connected App (in some orgs: New Connected App → Create a Connected App).
- Fill in the basics: any name (e.g.
Claude MCP), your email. - Check Enable OAuth Settings and configure:
- Callback URL:
https://<your-worker-url>/sf/callback(e.g.https://salesforce-remote-mcp-cloudflare.acme.workers.dev/sf/callback) - Selected OAuth Scopes — add exactly these two:
- Manage user data via APIs (api)
- Perform requests at any time (refresh_token, offline_access)
- Require Proof Key for Code Exchange (PKCE): leave enabled (the server uses PKCE).
- Require Secret for Web Server Flow: leave enabled.
- Callback URL:
- Save. Salesforce warns changes can take up to 10 minutes to take effect.
- Open the app's detail page → Manage Consumer Details (email verification may be required) and copy the Consumer Key and Consumer Secret.
Optional hardening (Setup → Connected Apps → Manage → Edit Policies): set Permitted Users to Admin approved users are pre-authorized to allowlist which profiles/permission sets may use the connector at all.
Step 3 — Give the Worker its Salesforce credentials
npx wrangler secret put SALESFORCE_CLIENT_ID # paste the Consumer Key
npx wrangler secret put SALESFORCE_CLIENT_SECRET # paste the Consumer Secret
Secrets are stored by Cloudflare, never in code or git. That's the whole server-side setup — no redeploy needed after setting secrets.
Step 4 — Add the connector in Claude
- Team / Enterprise: an org owner/admin adds it once for everyone — Admin settings → Connectors → Add custom connector.
- Pro / Max: add it for yourself — Settings → Connectors → Add custom connector.
In the dialog:
- Name: anything, e.g.
Salesforce - Remote MCP server URL:
https://<your-worker-url>/mcp— note the/mcppath - Advanced settings → OAuth Client ID / Client Secret: LEAVE BLANK. Those fields are a fallback for servers that can't register clients automatically; this server supports Dynamic Client Registration, so Claude configures itself. Your Connected App's key/secret belong only in Worker secrets (Step 3) — never paste them into Claude.
Step 5 — Connect (end users)
- In Claude, find the connector and click Connect.
- You're redirected to your company's Salesforce login — log in and click Allow.
- Done. Ask Claude to
pingthe Salesforce connector to confirm: it replies with the Salesforce username the session is bound to.
Each user connects individually and gets their own permissions — what a user can't see or edit in Salesforce, they can't see or edit through Claude.
The tools
| Category | Tools |
|---|---|
| Discovery | salesforce_search_objects, salesforce_describe_object |
| Query | salesforce_query_records, salesforce_aggregate_query, salesforce_search_all (SOSL) |
| Data | salesforce_dml_records (insert/update/delete/upsert) |
| Schema | salesforce_manage_object, salesforce_manage_field, salesforce_manage_field_permissions |
| Apex | salesforce_read_apex, salesforce_write_apex, salesforce_read_apex_trigger, salesforce_write_apex_trigger, salesforce_execute_anonymous |
| Debug | salesforce_manage_debug_logs |
| Health | ping (no Salesforce call; shows the bound user) |
Tool behavior matches the local @tsmztech/mcp-server-salesforce package. Large
results are truncated at ~140k characters (Claude's connector limit is ~150k) with a
notice asking to narrow the query.
Troubleshooting
| Symptom | Likely cause / fix |
|---|---|
| Claude: "could not reach server" when adding the connector | URL must end in /mcp. The Worker must be deployed (npx wrangler deploy). |
Salesforce error page during Connect: redirect_uri_mismatch |
Connected App callback URL doesn't exactly match https://<worker-url>/sf/callback. Remember changes take up to 10 min. |
invalid_client_id / invalid_client during Connect |
SALESFORCE_CLIENT_ID/SECRET secrets missing or wrong (re-run Step 3), or the Connected App hasn't propagated yet. |
| Login page is the wrong org type (prod vs sandbox) | Fix SALESFORCE_LOGIN_HOST in wrangler.jsonc and redeploy. |
| Tool calls fail with "reconnect" message | The refresh token was revoked or expired (e.g. admin revoked OAuth usage, or org token policies). Disconnect and reconnect the connector. |
INVALID_SESSION_ID errors surfacing to the user |
Shouldn't happen — the server auto-refreshes once and retries. If persistent, check the Connected App's refresh-token policy (Refresh token is valid until revoked is the friendliest). |
| Worker logs | npx wrangler tail streams live logs (no tokens are ever logged). |
| Corporate IP allowlisting | Claude's egress range is 160.79.104.0/21 — relevant if your org enforces login IP ranges on the Connected App. |
Security notes
- Per-user identity: every Salesforce call uses the connected user's own token; org permissions and FLS always apply. There is no service account.
- No token passthrough: Claude's token and Salesforce's tokens are separate; neither is ever forwarded to the other side.
- Storage: Salesforce tokens are stored encrypted at rest inside the OAuth grant
(Cloudflare KV, encrypted by
workers-oauth-provider); the interim login state is AES-GCM sealed withCOOKIE_ENCRYPTION_KEY. - Secrets: only ever via
wrangler secret put— never in code, config, or git. - Revocation: a Salesforce admin can cut any user (or the whole app) off at any time — Setup → Connected Apps OAuth Usage → Revoke. Users can also disconnect from Claude's connector settings.
- See SECURITY.md for reporting vulnerabilities.
Local development
cp .dev.vars.example .dev.vars # fill in your Connected App creds (gitignored)
npx wrangler dev # http://localhost:8787
npm run typecheck
npm test
Note: connecting from claude.ai requires a public HTTPS URL, so end-to-end connector
testing happens against a deployed Worker; wrangler dev is for the OAuth endpoints
and unit-testable logic.
License
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。