Damecek/salesforce-mcp-lib
GitHub: Damecek/salesforce-mcp-lib
一个通过 JSON-RPC 2.0 和 OAuth 2.0 将 AI 代理连接至 Salesforce 的本地桥接库,解决令牌生命周期与安全边界问题。
Stars: 12 | Forks: 3
# Salesforce MCP 库
[](https://www.npmjs.com/package/salesforce-mcp-lib)
[](LICENSE)
通过 [Model Context Protocol](https://modelcontextprotocol.io/) 将 AI 代理连接到 Salesforce 的开源桥梁。

两个包,零外部依赖:
| 包 | 功能 | 安装 |
|----|------|------|
| **Apex 框架**(2GP 解锁) | JSON-RPC 2.0 核心 + 在您的 Salesforce org 中本地运行的 MCP 服务器 | `sf package install` |
| **npm stdio 代理** | OAuth 2.0 生命周期 + stdio 到 HTTPS 桥接 — 配置一次,永运行。消费者已处理 Salesforce 令牌时可选项 | `npx salesforce-mcp-lib` |
## 工作原理
1. **MCP 客户端**(Claude、ChatGPT、任意 MCP 主机)通过 **stdio** 发送 JSON-RPC 2.0 消息
2. **npm 代理**通过 OAuth 2.0(客户端凭据或每用户登录)认证请求,经 HTTPS 转发并自动处理令牌刷新
3. **Apex MCP 服务器**将请求分派到您注册的 **工具**、**资源** 和 **提示** —— 全部在 Salesforce 内部运行,享受完整的平台安全
步骤 1–2 在使用 npm 代理时适用。如果 MCP 主机可通过有效 Bearer 令牌直接通过 HTTPS 访问 Apex 端点,则仅需步骤 3。
Apex 服务器是 **无状态** 的 — 每个请求都会重建处理程序链。无会话清理、无状态错误、无跨请求数据泄漏。
### 何时需要代理(以及何时不需要)
Apex `@RestResource` 端点 **就是** MCP 服务器 — 它实现了 JSON-RPC 2.0、功能协商以及所有工具/资源/提示的分发。TypeScript 代理是认证与传输桥接,而非协议逻辑。大多数 MCP 客户端同时支持 stdio 和 HTTP,因此代理的主要价值不在于传输 — 而在于 **OAuth 令牌生命周期管理**:获取令牌、缓存、到期刷新、401 时重新认证。配置一次,永运行。
**当您的 MCP 主机无法自行管理 Salesforce OAuth 令牌时,您需要代理。** 这涵盖了大多数桌面客户端(Claude Desktop、Cursor、VS Code 扩展)以及任何没有内置 Salesforce 凭据存储的集成。
**当消费者已处理 Salesforce OAuth 时,您可以跳过代理。** — 例如具有原生 Salesforce 连接器的云平台(如 n8n)、自动化服务,或自定义代理编排层(自行获取令牌、触发 MCP 代理、路由响应并重复)。Apex 端点是无状态的,因此调用之间无需维护会话。
有关两种路径及直接连接要求的深入讨论,请参阅 [docs/architecture.md](docs/architecture.md)。
### 安全 — 4 层,其中 3 层自动生效
| 层 | 执行方 |
|----|--------|
| OAuth 2.0 作用域 | 外部客户端应用配置 |
| 配置文件权限 | Salesforce 平台 |
| 权限集 | Salesforce 平台 |
| 共享规则 | Salesforce 平台 |
## 为何使用外部客户端应用
本库使用 OAuth 2.0 `client_credentials` 流程,对发出凭证的 Salesforce 容器运行时无关。项目文档有意标准化为 **外部客户端应用(ECA)**,以使设置指引领先于 Salesforce 平台方向。
## 快速开始
### 1. 安装 Apex 框架
```
sf package install --package 04tdL000000So9xQAC --target-org YOUR_ORG --wait 10
```
### 2. 创建您的 MCP 端点(2 个 Apex 类)
**端点** — 将能力串联的 `@RestResource`。在该解锁包中,框架 API 保持 `public`;端点本身为 `global`,因为 Apex REST 入口点需要此修饰符:
```
@RestResource(urlMapping='/mcp/minimal')
global inherited sharing class MinimalMcpEndpoint {
@HttpPost
global static void handlePost() {
McpServer server = new McpServer();
server.registerTool(new MinimalTool());
server.handleRequest(RestContext.request, RestContext.response);
}
}
```
**工具** — 扩展包的 `public` `McpToolDefinition` 基类并实现 `inputSchema()`、`validate()`、`execute()`:
```
public inherited sharing class MinimalTool extends McpToolDefinition {
public MinimalTool() {
this.name = 'echo';
this.description = 'Echoes the provided message back to the caller';
}
public override Map inputSchema() {
return new Map{
'type' => 'object',
'properties' => new Map{
'message' => new Map{
'type' => 'string',
'description' => 'The message to echo'
}
},
'required' => new List{ 'message' }
};
}
public override void validate(Map arguments) {
if (!arguments.containsKey('message')) {
throw new McpInvalidParamsException('message is required');
}
}
public override McpToolResult execute(Map arguments) {
String msg = (String) arguments.get('message');
McpToolResult result = new McpToolResult();
result.content = new List{ new McpTextContent(msg) };
return result;
}
}
```
### 3. 配置外部客户端应用
**选项 A — 客户端凭据**(服务账户,无需用户交互):
创建使用 **OAuth 2.0 客户端凭据** 流程的外部客户端应用。记下 `client_id` 与 `client_secret`。
**选项 B — 每用户认证**(个人身份,推荐):
创建使用 **授权码 + PKCE** 流程的外部客户端应用。回调 URL:`http://localhost:13338/oauth/callback`。作用域:`api`、`refresh_token`。详见 [每用户认证设置指南](specs/003-per-user-auth/quickstart.md)。
### 4. 连接 AI 代理
**每用户认证**(个人身份 — 推荐用于 Claude Code):
```
# 终端一次性登录
npx salesforce-mcp-lib login \
--instance-url https://your-org.my.salesforce.com \
--client-id YOUR_CLIENT_ID
```
然后通过 `/mcp` → 添加服务器,或编辑 `~/.claude.json` 添加:
```
{
"mcpServers": {
"salesforce": {
"command": "npx",
"args": [
"-y", "salesforce-mcp-lib",
"--instance-url", "https://your-org.my.salesforce.com",
"--client-id", "YOUR_CLIENT_ID",
"--endpoint", "/services/apexrest/mcp/minimal"
]
}
}
}
```
**客户端凭据**(服务账户 — 现有行为):
```
{
"mcpServers": {
"salesforce": {
"command": "npx",
"args": [
"-y", "salesforce-mcp-lib",
"--instance-url", "https://your-org.my.salesforce.com",
"--client-id", "YOUR_CLIENT_ID",
"--client-secret", "YOUR_CLIENT_SECRET",
"--endpoint", "/services/apexrest/mcp/minimal"
]
}
}
}
```
认证模式自动检测:存在 `--client-secret` → 客户端凭据流程;否则 → 每用户认证(需先执行 `login`)。
至此,代理即可发现并调用您的 Salesforce 工具。
`inherited sharing` 和 `with sharing` 有助于强制执行记录级访问默认设置,但它们本身不会强制实施 CRUD/FLS。当工具读取或写入受保护字段或对象时,请使用显式安全检查。
## 三种 MCP 能力
在单个端点注册工具、资源与提示:
```
@RestResource(urlMapping='/mcp/e2e')
global inherited sharing class E2eHttpEndpoint {
@HttpPost
global static void handlePost() {
McpServer server = new McpServer();
server.registerTool(new ExampleQueryTool());
server.registerResource(new ExampleOrgResource());
server.registerPrompt(new ExampleSummarizePrompt());
server.handleRequest(RestContext.request, RestContext.response);
}
}
```
| 能力 | 扩展类 | 覆盖方法 |
|------|--------|----------|
| **工具** | `McpToolDefinition` | `inputSchema()`、`validate()`、`execute()` |
| **资源** | `McpResourceDefinition` | `read()` |
| **资源模板** | `McpResourceTemplateDefinition` | `read(arguments)` |
| **提示** | `McpPromptDefinition` | `get(arguments)` |
请参阅 [`examples/`](examples/) 获取完整可运行代码。
## CLI 参考
### MCP 服务器模式
```
salesforce-mcp-lib [options]
```
| 选项 | 环境变量 | 必填 | 描述 |
|------|----------|------|------|
| `--instance-url` | `SF_INSTANCE_URL` | 是 | Salesforce 组织 URL |
| `--client-id` | `SF_CLIENT_ID` | 是 | 外部客户端应用消费者密钥 |
| `--client-secret` | `SF_CLIENT_SECRET` | 否* | 外部客户端应用消费者密钥 |
| `--endpoint` | `SF_ENDPOINT` | 是 | Apex REST 端点路径 |
| `--callback-port` | `SF_CALLBACK_PORT` | 否 | 本地 OAuth 回调端口(默认:`13338`) |
| `--log-level` | `SF_LOG_LEVEL` | 否 | `debug` / `info` / `warn` / `error`(默认:`info`) |
\* 提供 `--client-secret` → 客户端凭据流程;省略 → 每用户认证(需先执行 `login`)。
### 登录子命令(每用户认证)
```
salesforce-mcp-lib login [options]
```
| 选项 | 环境变量 | 必填 | 描述 |
|------|----------|------|------|
| `--instance-url` | `SF_INSTANCE_URL` | 是 | Salesforce 组织 URL |
| `--client-id` | `SF_CLIENT_ID` | 是 | 外部客户端应用消费者密钥 |
| `--headless` | `SF_HEADLESS` | 否 | 打印认证 URL 而非打开浏览器 |
| `--callback-port` | `SF_CALLBACK_PORT` | 否 | 本地 OAuth 回调端口(默认:`13338`) |
## 技术栈
- **Apex**:Salesforce API 65.0 — 54 个类,零外部依赖
- **TypeScript**:ES2022,Node.js >= 20 — 10 个模块,零 npm 生产依赖
- **协议**:MCP `2025-11-25`,JSON-RPC 2.0 — 全部 11 种 MCP 方法均已实现
- **打包**:Salesforce 2GP 解锁包(无命名空间)
## 项目结构
```
force-app/main/
json-rpc/classes/ # JSON-RPC 2.0 core (14 classes)
mcp/classes/ # MCP server framework (40 classes)
packages/salesforce-mcp-lib/
src/ # TypeScript stdio proxy (10 modules)
tests/ # Unit tests
examples/
minimal/ # Single-tool echo example
e2e-http-endpoint/ # Tools + resources + prompts
scripts/ # Build, deploy, and release scripts
```
## 许可证
[MIT](LICENSE)
标签:2GP解锁, AI代理集成, Apex, JSON-RPC 2.0, MCP, MITM代理, Model Context Protocol, npm包, OAuth 2.0, OAuth令牌刷新, REST资源, Salesforce, 令牌生命周期管理, 传输代理, 协议代理, 客户端凭证, 工具调度, 开发效率, 提示词调度, 搜索关键词, 无外部依赖, 无状态服务, 机器学习, 标准输入输出桥接, 桥接代理, 生产就绪, 网络可观测性, 自动化攻击, 自动重试, 资源调度, 跨请求数据隔离, 身份验证代理, 集成方案