使用说明
用于Copilot Studio的Salesforce MCP服务器
一个具有流式HTTP传输的自托管Salesforce MCP(模型上下文协议)服务器,旨在连接到Microsoft Copilot Studio。
⚠️ 免责声明
此项目仅用于测试、开发和教育目的。
- 这是 非 Salesforce、微软或任何附属公司的官方产品。
- 这个项目是 非 由Salesforce或Microsoft认可、支持或维护。
- 作者接受 无责任 因使用本软件而导致的任何数据丢失、安全事件、服务中断或其他损害。
- 请勿在生产中使用 而无需执行自己的安全审查、渗透测试和合规性评估。
- 您全权负责保护您的Salesforce凭据、Azure资源以及通过此服务器处理的任何数据。
- Salesforce®是Salesforce,股份有限公司的注册商标,Microsoft®和Copilot Studio®是Microsoft Corporation的注册商标。所有商标均归其各自所有者所有。
- 使用本软件须遵守 MIT许可证 --按“原样”提供,不提供任何形式的保证。
概述
这个项目囊括了优秀的 tsmztech/mcp服务器销售团队 (MIT许可证) 流式HTTP传输层,使其能够与 微软复制品工作室 作为定制MCP连接器。
为什么存在
| 方法 | 有效吗? | 限制 |
|---|---|---|
Salesforce托管MCP (api.salesforce.com) |
否 | 返回401“无效令牌”--需要未记录的JWT格式,测试版不稳定 |
| 微软的原生Salesforce连接器 | 是 | 只有7个工具:GetAccounts、GetOpportunity、GetLeads、GetCases、PostCase、PatchCase、ExecuteSOSLQuery |
| 此自托管MCP服务器 | 是 | 15工具 --完整的SOQL、任何对象上的CRUD、Apex、模式管理 |
建筑
Microsoft Copilot Studio
→ Custom MCP Connector (Streamable HTTP)
→ Azure App Service / Container App
→ This MCP Server (HTTP transport)
→ Salesforce REST API (via jsforce)
可用工具(15)
| 工具 | 说明 |
|---|---|
salesforce_search_objects |
按名称模式搜索Salesforce对象 |
salesforce_describe_object |
获取任何对象的完整架构元数据 |
salesforce_query_records |
使用关系支持执行SOQL查询 |
salesforce_aggregate_query |
GROUP BY、COUNT、SUM、AVG查询 |
salesforce_dml_records |
在任何对象上插入、更新、删除、插入 |
salesforce_manage_object |
创建/修改自定义对象 |
salesforce_manage_field |
创建/修改自定义字段 |
salesforce_manage_field_permissions |
管理现场级安全 |
salesforce_search_all |
SOSL跨对象搜索 |
salesforce_read_apex |
阅读Apex类源代码 |
salesforce_write_apex |
创建/更新Apex类 |
salesforce_read_apex_trigger |
读取触发器源代码 |
salesforce_write_apex_trigger |
创建/更新触发器 |
salesforce_execute_anonymous |
执行匿名Apex |
salesforce_manage_debug_logs |
启用/禁用/检索调试日志 |
先决条件
- Node.js 18+
- Salesforce组织 具有API访问权限(开发人员、企业版、无限版)
- Azure订阅 (用于托管)
- 微软复制品工作室 许可证
快速入门(本地)
1.克隆并安装
git clone <this-repo>
cd mcp-server-salesforce
npm install
2.配置Salesforce凭据
复制示例环境文件并填写您的凭据:
cp .env.example .env
编辑 .env:
SALESFORCE_CONNECTION_TYPE=User_Password
SALESFORCE_USERNAME=your-username@salesforce.com
SALESFORCE_PASSWORD=your-password
SALESFORCE_TOKEN=your-security-token
SALESFORCE_INSTANCE_URL=https://login.salesforce.com
PORT=3000
安全说明: 对于生产环境,请使用OAuth 2.0客户端凭据流,而不是用户名/密码。集
SALESFORCE_CONNECTION_TYPE=OAuth_2_0_Client_Credentials并提供SALESFORCE_CLIENT_ID和SALESFORCE_CLIENT_SECRET.
3.构建和运行
npm run build
node dist/http-server.js
4.测试
# Health check
curl http://localhost:3000/health
# Initialize MCP session
curl -X POST http://localhost:3000/ \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}'
部署到Azure
选项A:Azure应用服务
# Login to Azure
az login
# Create resource group
az group create --name rg-sf-mcp --location uksouth
# Create App Service plan
az appservice plan create --name plan-sf-mcp --resource-group rg-sf-mcp --sku B1 --is-linux
# Create web app
az webapp create --name sf-mcp-server --resource-group rg-sf-mcp --plan plan-sf-mcp --runtime "NODE:18-lts"
# Configure environment variables
az webapp config appsettings set --name sf-mcp-server --resource-group rg-sf-mcp --settings \
SALESFORCE_CONNECTION_TYPE=User_Password \
SALESFORCE_USERNAME=your-username@salesforce.com \
SALESFORCE_PASSWORD=your-password \
SALESFORCE_TOKEN=your-security-token \
SALESFORCE_INSTANCE_URL=https://login.salesforce.com \
PORT=8080
# Deploy
az webapp deploy --name sf-mcp-server --resource-group rg-sf-mcp --src-path ./deploy.zip
选项B:Azure容器应用程序
看 部署.md 用于具有托管身份的容器应用程序部署。
连接到Copilot工作室
使用MCP板载向导(推荐)
- 在Copilot工作室→ 代理人→ 工具 → 添加工具 → 新工具 → 模型上下文协议
- 填写:
- 服务器名称:
Salesforce CRM - 服务器描述:
Query and manage Salesforce data — SOQL, CRUD, schema, Apex - 服务器URL:
https://your-app-name.azurewebsites.net/
- 服务器名称:
- 身份验证: 无 (如果使用API密钥)或 OAuth 2.0 (如果使用Entra ID)
- 点击 创建 → 创建连接 → 添加到代理
使用自定义连接器(替代方案)
- 在Power Apps中→ 自定义连接器→ 导入OpenAPI文件
- 使用提供的 swagger.yaml
- 在“安全”选项卡上配置安全性
- 将连接器添加到您的Copilot Studio代理
故障排除
了解两个身份验证层
身份验证错误分为两个独立层之一。在排除故障之前,确定哪一个出现故障:
| 层 | 谁进行身份验证 | 凭据 | 失败时的症状 |
|---|---|---|---|
| 副驾驶工作室→ MCP服务器 | 调用Azure终结点的连接器 | 可选 X-API-Key 标题(仅当 API_KEY 已设置) |
HTTP 401 Unauthorized 从服务器 |
| MCP服务器→ 赛富时 | 每次工具调用时登录Salesforce的服务器 | SALESFORCE_USERNAME + SALESFORCE_PASSWORD + SALESFORCE_TOKEN (或OAuth) |
工具调用返回 isError: true Salesforce消息,例如 INVALID_LOGIN |
健康检查是不够的。
GET /health回报200即使Salesforce凭据错误,因为服务器仅在以下情况下向Salesforce进行身份验证 工具 被调用——不是在启动时。绿色健康检查告诉您应用程序正在运行,而不是Salesforce验证有效。
INVALID_LOGIN: Invalid username, password, security token; or user locked out
这是最常见的错误,总是意味着 服务器→ 赛富时 凭据被拒绝。要检查的事项,按顺序:
- 存储的凭据已过时。 Azure应用程序设置中的值可能比您在web上使用的值旧。能够登录Salesforce网站只能证明您知道 当前的 密码——确实如此 不 证明Azure中存储了相同的值。
- 在Salesforce中重置安全令牌不会更新Azure。 令牌重置只会向您的电子邮件发送一个新令牌。直到你将新令牌粘贴到
SALESFORCE_TOKEN,Azure仍然保留旧的(现已失效)版本。在不更新Azure的情况下重置令牌会使问题变得更糟,而不是更好。 - 密码和令牌必须是匹配的一对。 更改Salesforce密码 使现有安全令牌无效。始终更新
SALESFORCE_PASSWORD和SALESFORCE_TOKEN一起. - 令牌区分大小写 并由服务器直接附加到密码上——不要添加空格或分隔符。
修复--同时更新这两个值。 在PowerShell中,将每个设置包装在 单引号 所以像这样的角色 !, $,或backticks按字面意思存储,不由shell解释:
az webapp config appsettings set --name <your-app-name> --resource-group <your-rg> --settings 'SALESFORCE_PASSWORD=<current-password>' 'SALESFORCE_TOKEN=<new-token>'
设置应用程序设置会自动重新启动应用程序。MCP会话存储在内存中,因此Copilot Studio在下次请求时会重新初始化。
如何重现Salesforce的真实错误
因为健康端点隐藏了身份验证失败,所以调用一个实际的工具来显示真正的Salesforce消息。这将驱动完整的MCP握手并调用查询工具:
$base = 'https://<your-app-name>.azurewebsites.net/'
$h = @{ 'Content-Type' = 'application/json'; 'Accept' = 'application/json, text/event-stream' }
$init = Invoke-WebRequest -Uri $base -Method Post -Headers $h -UseBasicParsing -Body '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"diag","version":"1.0"}}}'
$sid = $init.Headers['Mcp-Session-Id']
$h2 = $h + @{ 'Mcp-Session-Id' = "$sid" }
Invoke-WebRequest -Uri $base -Method Post -Headers $h2 -UseBasicParsing -Body '{"jsonrpc":"2.0","method":"notifications/initialized"}' | Out-Null
$call = Invoke-WebRequest -Uri $base -Method Post -Headers $h2 -UseBasicParsing -Body '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"salesforce_query_records","arguments":{"objectName":"Account","fields":["Id","Name"],"limit":3}}}'
$call.Content
成功的响应包含 "isError":false 并返回记录。失败会在中返回准确的Salesforce消息 text 现场。
试用、开发和代理组织
较新的试用版、开发者版和 代理商 组织越来越强制执行 多因素认证 并且可以完全阻止传统用户名-密码API登录-即使使用正确的密码和令牌。如果凭据确实正确,但登录仍然失败,请切换到 OAuth 2.0客户端凭据 流(已支持):
- 使用以下工具在Salesforce中创建连接的应用程序/外部客户端应用程序 客户端凭据 流已启用,并按照用户分配的方式运行。
- 设置这些应用程序设置,而不是密码/令牌对:对于客户端凭据,
az webapp config appsettings set --name <your-app-name> --resource-group <your-rg> --settings 'SALESFORCE_CONNECTION_TYPE=OAuth_2.0_Client_Credentials' 'SALESFORCE_CLIENT_ID=<consumer-key>' 'SALESFORCE_CLIENT_SECRET=<consumer-secret>' 'SALESFORCE_INSTANCE_URL=https://<your-domain>.my.salesforce.com'SALESFORCE_INSTANCE_URL必须是你的组织 我的域 URL,不是login.salesforce.com.
其他常见问题
| 症状 | 原因 | 修复 |
|---|---|---|
401 Unauthorized 从服务器(而不是Salesforce) |
API_KEY 已设置,但请求丢失或错误 X-API-Key header |
确保Copilot Studio连接发送准确的 X-API-Key 价值;标头名称区分大小写 |
| 仅从Azure登录失败,在本地工作 | 启用“将会话锁定到其来源的IP地址”,或登录IP范围排除Azure | 禁用中的IP锁定 设置→ 会话设置,或在用户配置文件上分配Azure出站IP |
OAUTH_APPROVAL_ERROR_GENERIC |
组织范围内的PKCE要求,或缺少“批准未安装的已连接应用程序”权限 | 禁用流的PKCE,或授予用户配置文件的权限 |
| Copilot Studio中未显示任何工具 | 应用程序未运行或端口错误 | 确认 GET /health 回报 200;确保 PORT=8080 和 WEBSITES_PORT=8080 已设置 |
| 沙盒登录失败 | 登录主机错误 | 设置 SALESFORCE_INSTANCE_URL=https://test.salesforce.com 用于沙盒 |
| Auth以前工作过,突然中断 | Salesforce密码已更改/过期,令牌无效 | 重置令牌,然后更新 两者 SALESFORCE_PASSWORD 和 SALESFORCE_TOKEN 在Azure中 |
查看实时服务器日志
az webapp log tail --name <your-app-name> --resource-group <your-rg>
服务器将其选择的连接类型和Salesforce错误记录到日志流中显示的stderr中。
安全考虑
当前状态
重要提示: 该项目目前适合 开发、演示和内部概念验证 使用。它需要对企业生产部署进行额外的强化。请参阅下面的路线图。
| 区域 | 当前状态 | 企业准备好了吗? |
|---|---|---|
| Salesforce身份验证 | 应用程序设置中的用户名+密码+安全令牌 | 否--使用OAuth客户端凭据或JWT承载 |
| MCP端点身份验证 | 可选API密钥(X-API-Key header) |
部分--为企业添加Entra ID |
| 传输中的数据 | Azure应用服务强制执行HTTPS | 是 |
| 秘密管理 | Azure应用程序设置(静态加密) | 部分--移动到密钥库 |
| 网络接入 | 向互联网开放 | 否--添加IP分配列表或VNET |
| 审计日志 | 无 | 否--添加应用程序洞察 |
| 代币轮换 | 手动 | 否--需要自动刷新 |
身份验证选项
| 方法 | 用例 | 设置 |
|---|---|---|
| API密钥 (header) | 简单部署,内部使用 | 设置 API_KEY env var,传入 X-API-Key 头球 |
| Entra ID OAuth | 生产、多租户 | 配置应用注册+应用服务上的轻松认证 |
| 网络限制 | 深度防御 | Azure VNET+专用端点 |
生产检查表
- []使用OAuth 2.0客户端凭据进行Salesforce身份验证(不是用户名/密码)
- []将机密存储在Azure密钥库中,而不是应用程序设置中
- []仅启用HTTPS
- []添加API密钥或Entra ID身份验证
- []限制网络访问(IP分配列表或VNET)
- []启用Azure监视器/应用程序洞察
- []设置令牌刷新错误警报
- []检查要公开哪些MCP工具(如果不需要,请禁用Apex/模式工具)
路线图
安全强化(优先级)
| 项目 | 状态 | 描述 |
|---|---|---|
| 启用API密钥身份验证 | 就绪 | 设置 API_KEY env-var——已内置于服务器中 |
| 切换到OAuth 2.0客户端凭据 | 计划 | 用已连接的应用程序客户端凭据替换用户名/密码。服务器已通过支持此功能 SALESFORCE_CONNECTION_TYPE=OAuth_2_0_Client_Credentials |
| 切换到JWT承载身份验证 | 计划 | 基于证书的身份验证——不存储秘密,最安全的选项 |
| Azure密钥库集成 | 计划 | 将所有Salesforce凭据从应用程序设置移动到密钥库引用 |
| 端点上的Entra ID身份验证 | 已计划 | 添加Azure应用服务轻松授权,以便只有您的租户可以访问MCP服务器 |
| 应用程序洞察日志记录 | 计划 | 记录所有MCP工具调用、Salesforce查询和错误,以进行审计跟踪 |
| VNET+专用端点 | 计划 | 限制网络访问,以便只有Power Platform可以访问MCP服务器 |
| 工具级访问控制 | 计划 | 配置暴露哪些MCP工具(例如,禁用只读代理的写/Pex工具) |
| 自动秘密轮换 | 计划 | 自动提醒和轮换Salesforce令牌 |
特性
| 项目 | 状态 | 描述 |
|---|---|---|
| 可流式HTTP传输 | 完成 | 启用Copilot Studio MCP集成 |
| 文档搜索、列表、下载 | 完成 | 自定义 salesforce_get_documents 具有4个动作的工具 |
| 接受标头修复 | 完成 | Power Platform API集线器兼容性 |
| API密钥验证 | 完成 | 可选 X-API-Key 标头验证 |
| SharePoint代理流集成 | 完成 | 下载Salesforce文件→ 带有可点击链接的SharePoint |
| 从文档中提取文本 | 计划 | 从Word/PDF中提取可读文本用于LLM推理 |
| 持续会话 | 计划 | 用Redis替换内存中的会话存储,以实现多实例扩展 |
| 集装箱化部署 | 计划 | Docker+Azure容器应用支持 |
项目结构
├── src/
│ ├── index.ts # Original STDIO MCP server (from tsmztech)
│ ├── http-server.ts # Streamable HTTP wrapper (added for Copilot Studio)
│ ├── tools/ # Tool implementations
│ │ ├── query.ts # SOQL queries
│ │ ├── dml.ts # Insert/Update/Delete/Upsert
│ │ ├── search.ts # Object search
│ │ ├── searchAll.ts # SOSL search
│ │ ├── describe.ts # Schema metadata
│ │ ├── aggregateQuery.ts # Aggregate queries
│ │ ├── manageObject.ts # Custom object management
│ │ ├── manageField.ts # Custom field management
│ │ ├── readApex.ts # Read Apex source
│ │ ├── writeApex.ts # Write Apex source
│ │ └── ...
│ ├── types/ # TypeScript type definitions
│ └── utils/
│ └── connection.ts # Salesforce connection factory
├── .env.example # Example environment config
├── package.json
├── tsconfig.json
└── swagger.yaml # OpenAPI spec for custom connector
鸣谢
该项目建立在 tsmztech/mcp服务器销售团队 (MIT许可证)。HTTP传输包装器(http-server.ts)该项目增加了Copilot Studio集成。
许可证
麻省理工学院——见 许可证
