内容
# Victron VRM MCP 服务器
Victron Energy 的 VRM 云 API 的 MCP 服务器。向 Streamable HTTP 公开 52 种 VRM 工具 - 适用于 Anthropic MCP Connector API 和任何支持 HTTP 的 MCP 客户端。
> 52 个工具 | 流式 HTTP | 安全性优先 | 208 项测试 | MCP Connector 兼容
---
## 我需要哪个软件包?
这是**云/远程**部分的配对。本地/LAN 部分是 **[`victron-tcp`](https://github.com/lubosstrejcek/victron-tcp)**。
| | **[`victron-tcp`](https://github.com/lubosstrejcek/victron-tcp)** | **`victron-vrm-mcp`** (此仓库) |
|---|---|---|
| 传输 | stdio(本地子进程) | 流式 HTTP(远程) |
| 数据源 | Modbus TCP + 您 LAN 上的 MQTT | VRM 云 API |
| 需要访问您 LAN 上的 GX 设备 | **是** | 否 |
| 在远离船/房屋时是否有效 | 否 | **是** |
| 在互联网关闭时是否有效 | **是** | 否 |
| 延迟 | 实时(~50 毫秒) | ~15 分钟(VRM 采样) |
| 原始寄存器访问 | **是**(900+ 个寄存器) | 否 |
| 写覆盖 | 今日仅只读;通过 MQTT 计划写入 | 24 个破坏性工具,均有 `confirm` 门控 |
| MCP Connector API 兼容 | 否(stdio) | **是**(HTTPS) |
| 客户端 | Claude Code、Claude Desktop、Cursor、Windsurf | Anthropic Messages API + 任何通过 HTTP 讲 MCP 的客户端 |
| 认证 | 本地无(信任 LAN) | 每个请求的 VRM 个人访问令牌 |
**使用 `victron-tcp` 时:** 您与 GX 设备在同一 LAN 上,并希望实时访问原始寄存器支持。
**使用 `victron-vrm-mcp` 时:** 您需要远程访问,正在通过 MCP Connector 构建 API 支持的应用,或者不想在 LAN 上暴露任何内容。
您可以同时使用**两者** - 它们服务于不同的用例。
---
## 安装
与 `victron-tcp` 不同,该软件包是您**自行托管**的服务器,而不是您的客户端生成的进程。您运行一次,在它前面添加 HTTPS,然后将 MCP 客户端连接到其 URL。
### 从 npm 运行(推荐)
```bash
# 一次性(无需安装)
npx victron-vrm-mcp
# 或全局安装
npm install -g victron-vrm-mcp
victron-vrm-mcp
# 或固定在项目中
npm install victron-vrm-mcp
npx victron-vrm-mcp
```
默认监听 `http://127.0.0.1:3000/mcp`。使用环境变量配置(`PORT`、`HOST`、`ALLOWED_ORIGINS`、`VRM_ALLOWED_SITES`、`VRM_AUTH_SCHEME`)- 请参阅 `.env.example`。
### 从源码运行(开发)
```bash
git clone https://github.com/lubosstrejcek/victron-vrm-mcp.git
cd victron-vrm-mcp
npm install
npm run build
npm start
```
相同的默认绑定(`http://127.0.0.1:3000/mcp`)。
### Docker
路线图上有 Dockerfile。目前,可以适应一个最小的单行命令:
```bash
docker run --rm -it -p 3000:3000 -e HOST=0.0.0.0 \
-e ALLOWED_ORIGINS="https://claude.ai" \
node:22-alpine sh -c "npx -y victron-vrm-mcp"
```
### 公共 HTTPS(推荐)
对于远程客户端,您需要真正的 TLS。最简单的路径,无需打开防火墙端口: **[Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/)**。
```bash
cloudflared tunnel create vrm
cloudflared tunnel route dns vrm victron-vrm.example.com
cloudflared tunnel run --url http://127.0.0.1:3000 vrm
```
现在 `https://victron-vrm.example.com/mcp` 可以使用真正的证书和没有打开的端口访问。替代方案:nginx/Caddy 反向代理,Fly.io,Cloudflare Workers 适配器(路线图)。
### Anthropic Messages API(MCP Connector)
```json
{
"mcp_servers": [{
"type": "url",
"url": "https://victron-vrm.example.com/mcp",
"name": "victron-vrm",
"authorization_token": "<your-vrm-personal-access-token>"
}],
"tools": [{ "type": "mcp_toolset", "mcp_server_name": "victron-vrm" }]
}
```
### Claude Code / Cursor / Windsurf(HTTP 传输)
```bash
claude mcp add-json victron-vrm '{"type":"http","url":"https://victron-vrm.example.com/mcp","headers":{"Authorization":"Bearer YOUR_VRM_TOKEN"}}'
```
### 不知道您的 VRM 令牌?
在 [VRM → 首选项 → 集成 → 访问令牌](https://vrm.victronenergy.com/)(端点:`POST /users/{idUser}/accesstokens/create`)创建一个**个人访问令牌**。访问令牌是长期有效的、可撤销的,并且是**支持**的未来第三方身份验证方法。
> ⚠️ **VRM Bearer 令牌(`/auth/login`,`/auth/loginAsDemo`)自 2026-06-01 起已弃用**(现在在官方 OpenAPI 规范中)。该服务器仍然通过 `x-vrm-auth-scheme: Bearer` 支持它们进行测试,但新的集成**必须**使用访问令牌。使用 `/auth/loginAsDemo` 令牌返回的短期 Bearer 令牌进行快速烟雾测试。
### 不知道您的 idSite?
首先调用 `vrm_list_installations` - 它返回令牌可以访问的每个站点。或者,如果您有 12 个字符的门户 ID,请调用 `vrm_get_site_id` 来解析它。
### 要求
- **Node.js 18+**
- **VRM 个人访问令牌**(或用于测试的 demo-login Bearer)
- **公共 HTTPS** 如果您希望 MCP Connector API 访问它
---
## 工具
52 个工具,涵盖 88 个 VRM 操作(52 个直接 + 35+ 个小部件端点通过通用 `vrm_widget` 分派器)。每个破坏性工具都有 `confirm: true` 门控;每个工具都声明 `inputSchema`、`outputSchema` 和 MCP 注解。
<details>
<summary><strong>发现和查找(4 个工具)</strong></summary>
| 工具 | 描述 |
|------|-------------|
| `vrm_list_installations` | 列出令牌可以访问的所有站点(支持 `limit` 进行 markdown 截断) |
| `vrm_search_sites` | 按站点 ID、电子邮件、用户名、序列号、站点标识符或电子邮件域搜索 |
| `vrm_get_site_id` | 将 12 个字符的门户 ID 解析为数字 `idSite` |
| `vrm_list_invites` | 列出用户发出/接收的邀请 |
</details>
<details>
<summary><strong>监控 - 读取(11 个工具)</strong></summary>
| 工具 | 描述 |
|------|-------------|
| `vrm_get_system_overview` | 站点的连接设备 + 角色 |
| `vrm_get_diagnostics` | 每个设备的最后已知属性值 |
| `vrm_get_stats` | 时间序列统计数据(15 分钟/小时/天/周/月/年) |
| `vrm_get_overallstats` | 生命周期汇总统计数据 |
| `vrm_get_alarms` | 配置的报警、设备、通知用户、可用属性 |
| `vrm_get_site_users` | 站点的用户 + 邀请 + 访问请求 + 组链接 |
| `vrm_get_tags` | 按源分组的标签(用户/团队/组/预定义) |
| `vrm_get_dynamic_ess_settings` | 当前动态 ESS 配置 |
| `vrm_get_gps_download` | GPS 位置历史 |
| `vrm_get_forecasts_last_reset` | 上次预测重置的时间戳(如果未重置,则为 0) |
| `vrm_get_custom_widgets` | 站点上配置的自定义小部件 |
</details>
<details>
<summary><strong>小部件(3 个工具 - 涵盖 35+ 个小部件端点)</strong></summary>
| 工具 | 描述 |
|------|-------------|
| `vrm_widget` | 任何 VRM 小部件名称的通用调度器(BatterySummary、SolarChargerSummary、TankSummary、VeBusState、MPPTState、InputState、InverterState、PVInverterStatus、MotorSummary、GlobalLinkSummary、MeteorologicalSensorOverview、Status、HoursOfAc、LithiumBMS、DCMeter、FuelCellState、BatteryRelayState、ChargerRelayState、GatewayRelayState、SolarChargerRelayState、BatteryMonitorWarningsAndAlarms、VeBusWarningsAndAlarms、InverterChargerState、InverterChargerWarningsAndAlarms、EssBatteryLifeState、IOExtenderInOut、BMSDiagnostics、HistoricData、TempSummaryAndGraph、TempAirQuality、EvChargerSummary 等) |
| `vrm_widget_graph` | 带有 `attributeCodes[]` / `attributeIds[]`、`start`/`end`、`useMinMax` 的时间序列图表 |
| `vrm_widget_generator_state` | 发电机状态变化时间线 |
</details>
<details>
<summary><strong>写入 - 低风险(4 个工具,确认门控)</strong></summary>
| 工具 | 描述 |
|------|-------------|
| `vrm_set_favorite` | 标记/取消标记站点为收藏夹 |
| `vrm_tags_add` | 将标签附加到站点 |
| `vrm_tags_remove` | 从站点分离标签 |
| `vrm_clear_alarm` | 确认活动报警 |
</details>
<details>
<summary><strong>写入 - 中等风险(5 个工具,确认门控)</strong></summary>
| 工具 | 描述 |
|------|-------------|
| `vrm_add_alarm` | 创建报警(浮点或枚举阈值变体) |
| `vrm_edit_alarm` | 修改现有报警 |
| `vrm_delete_alarm` | 删除报警定义 |
| `vrm_reset_forecasts` | 重置站点的预测基线 |
| `vrm_set_site_settings` | 更新站点名称/备注/地理围栏/报警监控/Node-RED 限制等。 |
</details>
<details>
<summary><strong>写入 - 高影响(1 个工具,确认门控)</strong></summary>
| 工具 | 描述 |
|------|-------------|
| `vrm_set_dynamic_ess_settings` | 写入动态 ESS 配置(计划、b2g、priceSchedule、batteryKwh 等) |
</details>
<details>
<summary><strong>访问管理(8 个工具,确认门控)</strong></summary>
| 工具 | 描述 |
|------|-------------|
| `vrm_invite_user` | 通过电子邮件邀请用户并设置访问级别(0=监控,1=管理员,2=技术人员) |
| `vrm_unlink_user` | 从站点删除用户 |
| `vrm_unlink_installation` | 从站点删除当前用户(自我删除) |
| `vrm_set_user_rights` | 批量更新每个用户的访问级别 |
| `vrm_set_invite_rights` | 批量更新待处理邀请的访问级别 |
| `vrm_link_user_groups` | 将用户组与访问级别链接 |
| `vrm_set_user_group_access_level` | 更改或删除用户组的访问级别 |
| `vrm_add_site` | 向用户帐户添加安装 |
</details>
<details>
<summary><strong>访问令牌(2 个工具,确认门控)</strong></summary>
| 工具 | 描述 |
|------|-------------|
| `vrm_create_access_token` | 创建长期有效的个人访问令牌 |
| `vrm_delete_access_token` | 撤销一个令牌 ID 或全部使用 `"*"` - **可以自我锁定** |
</details>
<details>
<summary><strong>身份验证(3 个工具 - Bearer 流,已弃用 2026-06-01)</strong></summary>
| 工具 | 描述 |
|------|-------------|
| `vrm_auth_login_as_demo` | 为演示租户获取短期 Bearer(只读) |
| `vrm_auth_login` | 登录电子邮件+密码(已弃用,安全隐患 - 使用访问令牌) |
| `vrm_auth_logout` | 使当前 Bearer 会话失效 |
</details>
<details>
<summary><strong>自定义小部件 CRUD(4 个工具)</strong></summary>
| 工具 | 描述 |
|------|-------------|
| `vrm_get_custom_widgets` | 列出站点上的自定义小部件 |
| `vrm_create_custom_widget` | 创建(确认门控) |
| `vrm_patch_custom_widget` | 更新(确认门控) |
| `vrm_delete_custom_widget` | 删除(确认门控) |
</details>
<details>
<summary><strong>数据属性(2 个工具)</strong></summary>
| 工具 | 描述 |
|------|-------------|
| `vrm_find_by_data_attributes` | 按属性条件搜索用户的安装(`bs>=50,au=(1,2)`);服务器端 `page`/`count` 分页 |
| `vrm_list_data_attributes` | 所有 VRM 属性定义的目录 |
</details>
<details>
<summary><strong>管理员 / 集合(6 个工具 - 大多数需要管理员权限)</strong></summary>
| 工具 | 描述 |
|------|-------------|
| `vrm_admin_list_devices` | 系统的所有设备 |
| `vrm_admin_data_attributes_count` | 按数据属性条件计算安装 |
| `vrm_admin_search_download` | 批量搜索导出 |
| `vrm_list_firmwares` | 固件目录(需要 `feedChannel` + `victronConnectVersion`) |
| `vrm_add_system` | 注册新系统(确认门控) |
| `vrm_installation_overview_download` | 批量概览导出(返回二进制有效载体为 base64) |
</details>
### 资源
| URI | 内容 |
|-----|---------|
| `docs/vrm-api-openapi.yaml` | 捆绑的 VRM OpenAPI 3.1 规范(78 个端点,更新于 2026-04)用于参考 |
---
## 配置
### 环境变量
| 变量 | 默认值 | 描述 |
|----------|---------|-------------|
| `PORT` | `3000` | HTTP 端口 |
| `HOST` | `127.0.0.1` | 绑定地址 |
| `MCP_PATH` | `/mcp` | 端点路径 |
| `VRM_AUTH_SCHEME` | `Token` | 转发到 VRM 的默认方案。使用 `Token`(访问令牌)。`Bearer` 自 2026-06-01 起由 VRM 弃用。每个请求覆盖:`x-vrm-auth-scheme` 头。 |
| `VRM_ALLOWED_SITES` | _(unset)_ | 以逗号分隔的 `idSite` 允许列表。如果未设置,令牌可以访问的任何站点都允许。 |
| `ALLOWED_ORIGINS` | _(unset)_ | 以逗号分隔的允许 `Origin` 头值列表。如果未设置,仅允许同源 + 环回接受。 |
### 本地 `.env`(可选)
复制 `.env.example` 到 `.env` 并调整。Node 20.6+ 直接加载它:
```bash
node --env-file=.env dist/index.js
```
`.env` 被 gitignore。**永远不要在 `.env` 中放置 VRM 令牌** - 它们在每个请求中通过 `Authorization` 头传递。
### 每个请求的头部
| 头部 | 用途 |
|--------|---------|
| `Authorization: Bearer <vrm-token>` | **必填**。转发的 VRM 令牌。 |
| `x-vrm-auth-scheme: Token\|Bearer` | 可选。覆盖此请求的 `VRM_AUTH_SCHEME`。对于 `/auth/loginAsDemo` 令牌,请使用 `Bearer`。 |
| `x-vrm-skip-confirms: 1` | 可选。跳过破坏性工具上的 `confirm: true` 门控。**仅限自动化** - 交互式会话绝不使用。记录为 `skip_confirms_enabled` 警告。 |
| `Origin` | 针对 `ALLOWED_ORIGINS`(或本地开发的同源)进行 DNS 绑定保护。 |
| `mcp-protocol-version` | 验证支持的版本 (`2025-06-18`, `2025-03-26`). |
---
## 安全模型
| 层 | 它做什么 |
|---|---|
| **来源头部验证** | 拒绝跨源请求,除非 `Origin` 位于 `ALLOWED_ORIGINS`(或本地开发的匹配主机)。防御 DNS 绑定。 |
| **严格的 Accept + Content-Type** | POST 必须发送 `Content-Type: application/json` 和 `Accept` 包括 `application/json` 和 `text/event-stream`。还杀死了简单的 POST CSRF。 |
| **MCP-Protocol-Version 白名单** | 仅接受服务器支持的版本;未知版本 → 400。 |
| **需要 Bearer 令牌** | 拒绝任何 VRM 调用之前,拒绝不匹配或过短的令牌。 |
| **令牌从不存储 / 从不记录** | 令牌仅存在于转发它们的 fetch 调用中。记录器自动剥离任何包含 `token` 或 `authorization` 的密钥。 |
| **Zod 输入验证** | 每个工具参数都经过模式验证。`idSite`/`idUser` 必须是正整数;小部件名称必须匹配严格的 PascalCase 正则表达式;请求正文根据工具进行模式验证。 |
| **URL 安全路径构造** | 路径参数通过 `encodeURIComponent` 进行 URL 编码。没有字符串模板化为 URL。 |
| **VRM 基 URL 主机固定** | 客户端拒绝调用除 `vrmapi.victronenergy.com` 之外的任何 HTTPS。 |
| **破坏操作门控** | 写入/删除的工具需要 `{ confirm: true }` 或 `x-vrm-skip-confirms: 1` 头部(自动化选择加入)。服务器端拒绝发生在 MCP 客户端之前。MCP 注解 (`destructiveHint`, `idempotentHint`, `readOnlyHint`) 已设置,以便客户端可以强制执行 UX 确认。 |
| **可选站点允许列表** | `VRM_ALLOWED_SITES=123,456` 将服务器限制为一组固定的站点。在 VRM 之前拒绝。 |
| **速率限制感知** | 429 响应显示并带有 `Retry-After`。没有静默重试。 |
| **错误正文编辑** | VRM 错误正文减少为 `error_code: errors-text`,截断为 256 个字符。原始响应正文绝不流向客户端。 |
| **无状态每个请求** | 新鲜的 `McpServer` + `StreamableHTTPServerTransport` 每个请求 - 没有跨请求状态,没有会话身份验证。 |
| **结构化 JSON stderr 日志** | 所有操作事件都是单行 JSON;令牌/授权密钥被剥离。 |
---
## 工作原理
```
┌──────────────────────────┐ HTTPS + Bearer 令牌 ┌──────────────────────┐
│ MCP 客户端 │ ────────────────────────────────▶ │ victron-vrm-mcp │
│ (Connector API, Claude │ │ (流式 HTTP) │
│ Code, Cursor, 等) │ └──────────┬───────────┘
└──────────────────────────┘ │
│ x-authorization: Token …
▼
https://vrmapi.victronenergy.com/v2
```
服务器是**无状态**的 - 每个 MCP 请求都携带自己的 VRM 令牌。新的 `McpServer` + `StreamableHTTPServerTransport` 为每个请求构造,转发身份验证信息通过 SDK 的 `RequestHandlerExtra.authInfo` 通道。
---
## 调试
[MCP Inspector](https://modelcontextprotocol.io/docs/tools/inspector) 是交互式调试服务器的最快方法。
```bash
# 终端 1 - 启动服务器
npm run build && npm start
# (或:PORT=3000 npx victron-vrm-mcp)
# 终端 2 - 启动 Inspector UI
npm run inspect
# 然后在 UI 中:
# 传输: 流式 HTTP
# URL: http://127.0.0.1:3000/mcp
# 头部: Authorization: Bearer <您的 VRM 令牌>
# x-vrm-auth-scheme: Token (或 Bearer 用于 /auth/loginAsDemo 令牌)
```
## 测试
8个文件共208个测试,大约2秒运行完成:
```bash
npm test # 构建并运行所有测试
npm run test:unit # 仅运行单元测试(不启动服务器)
```
| 文件 | 覆盖率 |
|------|----------|
| `tests/helpers.test.ts` | zod模式、`sitePath`/`userPath`编码、`requireConfirm` + 跳过绕过、`resolveAuth`令牌保护、`formatVrmError`编辑 |
| `tests/client.test.ts` | 令牌长度保护、方案转发、数组查询编码、主机固定、4xx → `VrmApiError`、429 重试后、 二进制下载往返 |
| `tests/logger.test.ts` | 自动编辑 `token`/`authorization` 键(不区分大小写) |
| `tests/http.test.ts` | 端到端HTTP:404/405/401/403/406/415/400/200、源验证、确认门、跳过头 |
| `tests/tools.coverage.test.ts` | 52种工具的每一种都有正确的形状 + 注释;每种破坏性工具在没有确认的情况下拒绝,并带有跳过头 |
| `tests/outputSchema.test.ts` | 每个工具都声明 `outputSchema` 且至少有一个属性;描述卫生(长度、端点提及、无注入标记、破坏性工具命名危险) |
| `tests/regressions.test.ts` | 特定错误锁定:跳过确认绕过、固件所需参数、 二进制下载、路径遍历拒绝、 小部件名称正则表达式、限制边界 |
| `tests/fuzz.test.ts` | 格式错误的JSON、1MB正文、 unicode/控制字符/XSS/SQL注入字符串、数组长度限制、内容类型边缘情况、令牌泄漏哨兵 |
持续集成:`.github/workflows/ci.yml` 在 Node 18 / 20 / 22 上运行完整的测试套件,每次推送和拉取请求,以及令牌泄漏哨兵grep和 `npm audit`。
### 评估
`evals/*.xml` — 12个多工具场景评估(非持续集成,手动评估对抗LLM客户端)。涵盖发现 + 概述、电池最近一小时、报警分类、按SOC查找、用户邀请、访问令牌轮换、标签管理、安全拒绝、站点ID查找、每日健康检查、ESS配置更改、自动夜间作业。
---
## 路线图
已完成:
- [x] 52种工具,涵盖88种VRM操作
- [x] 可流式HTTP传输 + MCP连接器API支持
- [x] 安全强化(源/接受/内容类型/协议版本、令牌编辑、确认门、站点允许列表、基准URL固定)
- [x] 每个工具的 `outputSchema`
- [x] 208个测试 + Node 18/20/22上的持续集成
- [x] 12个场景评估
计划中:
- [ ] Cloudflare Workers适配器(无状态友好部署)
- [ ] Docker镜像
- [ ] 匹配VRM的200窗口/3 req/s的令牌桶速率限制器
- [ ] 记录的固定装置测试(离线VRM响应快照)
- [ ] 当VRM添加时,以cursor样式分页 `vrm_list_data_attributes`
---
## 参考
- [VRM API文档](https://vrmapi.victronenergy.com/v2/docs)
- [VRM API实时文档(试用)](https://vrm-api-docs.victronenergy.com/)
- [Anthropic MCP连接器API](https://platform.claude.com/docs/en/agents-and-tools/mcp-connector)
- [模型上下文协议规范](https://modelcontextprotocol.io)
- [与维可隆能源产品的数据通信](https://www.victronenergy.com/upload/documents/Technical-Information-Data-communication-with-Victron-Energy-products_EN.pdf) (白皮书)
## 许可证
MIT
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器