MCP协议主机服务

一个Node.js应用程序,作为MCP(Model Context Protocol)主机,通过REST API桥接Salesforce(Apex/Flow)与远程MCP服务器。

  • by SalesforceDiariesBySanket
  • Apex
  • 本地部署
  • 更新于
在 GitHub 查看 SalesforceDiariesBySanket/mcp-router

使用说明

Heroku MCP主机

Node.js应用程序,充当MCP(模型上下文协议)主机,通过REST API将Salesforce(Apex/Flow)与远程MCP服务器桥接。

概述

┌─────────────────┐         ┌──────────────────┐         ┌─────────────────┐
│   Salesforce    │         │  Heroku MCP Host │         │  Remote MCP     │
│  (Apex / Flow)  │◄───────►│   (REST API)     │◄───────►│    Servers      │
│                 │  HTTPS  │                  │   SSE   │                 │
└─────────────────┘         └──────────────────┘         └─────────────────┘

由于Salesforce不能直接与MCP服务器(使用SSE/StreamableHTTP协议)通信,因此此应用程序通过以下方式充当桥梁:

  1. 公开Salesforce可以调用的REST API
  2. 使用MCP协议连接到远程MCP服务器
  3. 将REST请求转换为MCP命令,反之亦然

特性

  • 🔌 同时连接到多个MCP服务器
  • 🔧 从Salesforce Apex/Flow调用MCP工具
  • 📚 阅读MCP资源
  • 💬 获取MCP提示
  • 🔐 API密钥验证
  • 📊 健康监测端点
  • 🚀 Heroku就绪部署

快速开始

地方发展

  1. 克隆存储库

  2. 安装依赖项:

    npm install
    
  3. 创建 .env 文件:

    cp .env.example .env
    
  4. 在中配置MCP服务器 .env:

    API_KEY=your-secure-api-key
    MCP_SERVERS={"myserver": {"url": "https://mcp-server.example.com/sse", "transport": "sse"}}
    
  5. 启动服务器:

    npm start
    

部署到Heroku

  1. 创建Heroku应用程序:

    heroku create your-app-name
    
  2. 设置环境变量:

    heroku config:set API_KEY=your-secure-api-key
    heroku config:set MCP_SERVERS='{"myserver": {"url": "https://mcp-server.example.com/sse", "transport": "sse"}}'
    
  3. 部署:

    git push heroku main
    

API 参考

认证

所有API端点(除 /health)需要通过以下方式进行身份验证:

  • X-API-Key 标题,或
  • Authorization: Bearer <api-key> 头球

端点

健康检查

GET /health

返回服务器运行状况。无需身份验证。

列出服务器

GET /api/v1/servers

返回已注册MCP服务器的列表。

注册服务器

POST /api/v1/servers
Content-Type: application/json

{
  "name": "myserver",
  "url": "https://mcp-server.example.com/sse",
  "transport": "sse",
  "headers": {},
  "timeout": 30000
}

列出工具

GET /api/v1/mcp/:serverName/tools

返回MCP服务器上可用工具的列表。

呼叫工具

POST /api/v1/mcp/:serverName/tools/call
Content-Type: application/json

{
  "tool": "toolName",
  "arguments": {
    "arg1": "value1"
  }
}

调用MCP服务器上的工具并返回结果。

列出资源

GET /api/v1/mcp/:serverName/resources

读取资源

POST /api/v1/mcp/:serverName/resources/read
Content-Type: application/json

{
  "uri": "resource://example/resource"
}

列表提示

GET /api/v1/mcp/:serverName/prompts

获取提示

POST /api/v1/mcp/:serverName/prompts/get
Content-Type: application/json

{
  "prompt": "promptName",
  "arguments": {
    "arg1": "value1"
  }
}

Salesforce集成

Apex示例

public class MCPHostService {
    private static final String MCP_HOST_URL = 'https://your-heroku-app.herokuapp.com';
    private static final String API_KEY = 'your-api-key';
    
    /**
     * Call an MCP tool
     */
    public static Map<String, Object> callTool(String serverName, String toolName, Map<String, Object> arguments) {
        HttpRequest req = new HttpRequest();
        req.setEndpoint(MCP_HOST_URL + '/api/v1/mcp/' + serverName + '/tools/call');
        req.setMethod('POST');
        req.setHeader('Content-Type', 'application/json');
        req.setHeader('X-API-Key', API_KEY);
        req.setTimeout(60000);
        
        Map<String, Object> body = new Map<String, Object>{
            'tool' => toolName,
            'arguments' => arguments
        };
        req.setBody(JSON.serialize(body));
        
        Http http = new Http();
        HttpResponse res = http.send(req);
        
        if (res.getStatusCode() == 200) {
            return (Map<String, Object>) JSON.deserializeUntyped(res.getBody());
        } else {
            throw new MCPException('MCP call failed: ' + res.getBody());
        }
    }
    
    /**
     * List available tools
     */
    public static List<Object> listTools(String serverName) {
        HttpRequest req = new HttpRequest();
        req.setEndpoint(MCP_HOST_URL + '/api/v1/mcp/' + serverName + '/tools');
        req.setMethod('GET');
        req.setHeader('X-API-Key', API_KEY);
        req.setTimeout(30000);
        
        Http http = new Http();
        HttpResponse res = http.send(req);
        
        if (res.getStatusCode() == 200) {
            Map<String, Object> result = (Map<String, Object>) JSON.deserializeUntyped(res.getBody());
            return (List<Object>) result.get('tools');
        } else {
            throw new MCPException('Failed to list tools: ' + res.getBody());
        }
    }
    
    public class MCPException extends Exception {}
}

流量集成

  1. 为Heroku MCP主机URL创建命名凭据
  2. 使用Apex动作调用 MCPHostService.callTool()
  3. 在Flow中解析JSON响应

远程站点设置

别忘了在Salesforce设置中将Heroku应用程序URL添加到远程站点设置中:

  • 远程站点URL: https://your-heroku-app.herokuapp.com

配置

环境变量

变量 描述 默认值
PORT 服务器端口 3000
HOST 绑定主机 0.0.0.0
API_KEY 用于身份验证的API密钥 (必需)
LOG_LEVEL 日志记录级别 info
MCP_SERVERS MCP服务器的JSON配置 {}
MCP_TIMEOUT 默认超时时间(毫秒) 30000
CORS_ORIGINS CORS允许的来源 *

MCP服务器配置格式

{
  "serverName": {
    "url": "https://mcp-server.example.com/sse",
    "transport": "sse",
    "headers": {
      "Authorization": "Bearer token"
    },
    "timeout": 30000
  }
}

安全注意事项

  1. 始终使用https 生产中
  2. 旋转API键 定期
  3. 限制CORS来源 转到您的Salesforce组织域
  4. 使用命名凭据 在Salesforce中用于凭证存储
  5. 监控日志 可疑活动

故障排除

连接问题

  • 验证MCP服务器URL是否可以从Heroku访问
  • 检查MCP服务器是否需要身份验证标头
  • 查看Heroku日志: heroku logs --tail

超时错误

  • 增加 MCP_TIMEOUT 用于慢速操作
  • 增加顶点 setTimeout() 匹配

身份验证失败

  • 验证在Heroku和Salesforce中是否正确设置了API密钥
  • 检查授权标头格式

许可证

麻省理工学院