Sponsored by Deepsite.site

Victron Vrm Mcp — Mcp Server

Created By
lubosstrejceka month ago
Overview

Victron VRM MCP — MCP Server

MCP server for Victron Energy's VRM cloud API. Exposes 52 VRM tools over Streamable HTTP — ready for the Anthropic MCP Connector API and any HTTP-capable MCP client.

52 tools | Streamable HTTP | Security-first | 208 tests | MCP Connector compatible


Which package do I want?

This is the cloud / remote half of a pair. The local / LAN half is victron-tcp.

victron-tcpvictron-vrm-mcp (this repo)
Transportstdio (local subprocess)Streamable HTTP (remote)
Data sourceModbus TCP + MQTT on your LANVRM cloud API
Needs access to the GX on your LANYesNo
Works when you're away from the boat / houseNoYes
Works when the internet is downYesNo
LatencyReal-time (~50 ms)~15 min (VRM sampling)
Raw register accessYes (900+ registers)No
Write coverageRead-only today; writes via MQTT planned24 destructive tools, all confirm-gated
MCP Connector API compatibleNo (stdio)Yes (HTTPS)
ClientsClaude Code, Claude Desktop, Cursor, WindsurfAnthropic Messages API + anything that speaks MCP over HTTP
AuthNone locally (trusts LAN)Per-request VRM personal access token

Use victron-tcp when: you're on the same LAN as a GX device and want real-time access with raw register support. Use victron-vrm-mcp when: you need remote access, you're building an API-backed app via the MCP Connector, or you don't want to expose anything on your LAN.

You can use both simultaneously — they serve different use cases.


Installation

Unlike victron-tcp, this package is a server you self-host, not a process your client spawns. You run it once, put HTTPS in front of it, and connect MCP clients to its URL.

# one-off (no install)
npx victron-vrm-mcp

# or install globally
npm install -g victron-vrm-mcp
victron-vrm-mcp

# or pin in a project
npm install victron-vrm-mcp
npx victron-vrm-mcp

Listens on http://127.0.0.1:3000/mcp by default. Configure with env vars (PORT, HOST, ALLOWED_ORIGINS, VRM_ALLOWED_SITES, VRM_AUTH_SCHEME) — see .env.example.

Run from source (development)

git clone https://github.com/lubosstrejcek/victron-vrm-mcp.git
cd victron-vrm-mcp
npm install
npm run build
npm start

Same default bind (http://127.0.0.1:3000/mcp).

Docker

A Dockerfile is on the roadmap. For now, a minimal one-liner you can adapt:

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"

For remote clients you need real TLS. Easiest path without opening firewall ports: Cloudflare Tunnel.

cloudflared tunnel create vrm
cloudflared tunnel route dns vrm victron-vrm.example.com
cloudflared tunnel run --url http://127.0.0.1:3000 vrm

Now https://victron-vrm.example.com/mcp is reachable with a real cert and no open ports. Alternatives: nginx/Caddy reverse proxy, Fly.io, Cloudflare Workers adapter (roadmap).

Anthropic Messages API (MCP Connector)

{
  "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 transport)

claude mcp add-json victron-vrm '{"type":"http","url":"https://victron-vrm.example.com/mcp","headers":{"Authorization":"Bearer YOUR_VRM_TOKEN"}}'

Don't know your VRM token?

Create a personal access token at VRM → Preferences → Integrations → Access tokens (endpoint: POST /users/{idUser}/accesstokens/create). Access tokens are long-lived, revocable, and the supported third-party auth method going forward.

⚠️ VRM Bearer tokens (/auth/login, /auth/loginAsDemo) are deprecated from 2026-06-01 (now in the official OpenAPI spec). This server still supports them via x-vrm-auth-scheme: Bearer for testing, but new integrations must use access tokens. A warning is logged whenever the Bearer scheme is used.

For quick smoke testing before you have an access token, GET https://vrmapi.victronenergy.com/v2/auth/loginAsDemo returns a short-lived Bearer token against the Victron demo tenant.

Don't know your idSite?

Call vrm_list_installations first — it returns every site the token can access. Or if you have a 12-char portal ID, call vrm_get_site_id to resolve it.

Requirements

  • Node.js 18+
  • A VRM personal access token (or a demo-login Bearer for testing)
  • Public HTTPS if you want the MCP Connector API to reach it

Tools

52 tools covering 88 VRM operations (52 direct + 35+ widget endpoints via the generic vrm_widget dispatcher). Every destructive tool is confirm: true gated; every tool declares inputSchema, outputSchema, and MCP annotations.

Discovery & Lookup (4 tools)
ToolDescription
vrm_list_installationsList all sites the token can access (supports limit for markdown truncation)
vrm_search_sitesSearch by site ID, email, username, serial number, site identifier, or email domain
vrm_get_site_idResolve a 12-char portal ID to a numeric idSite
vrm_list_invitesList invitations issued/received by the user
Monitoring — reads (11 tools)
ToolDescription
vrm_get_system_overviewConnected devices + roles for a site
vrm_get_diagnosticsPer-device last-known attribute values
vrm_get_statsTime-series stats (15min/hours/days/weeks/months/years)
vrm_get_overallstatsLifetime aggregate stats
vrm_get_alarmsConfigured alarms, devices, notification users, available attributes
vrm_get_site_usersUsers + invites + access requests + group links on a site
vrm_get_tagsTags grouped by source (user/team/group/predefined)
vrm_get_dynamic_ess_settingsCurrent Dynamic ESS configuration
vrm_get_gps_downloadGPS position history
vrm_get_forecasts_last_resetTimestamp of the last forecasts reset (0 if never)
vrm_get_custom_widgetsCustom widgets configured on a site
Widgets (3 tools — 35+ widget endpoints covered)
ToolDescription
vrm_widgetGeneric dispatcher for any VRM widget name (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, etc.)
vrm_widget_graphTime-series graph with attributeCodes[] / attributeIds[], start/end, useMinMax
vrm_widget_generator_stateGenerator state-change timeline
Writes — low-risk (4 tools, confirm-gated)
ToolDescription
vrm_set_favoriteMark/unmark a site as favorite
vrm_tags_addAttach a tag to a site
vrm_tags_removeDetach a tag from a site
vrm_clear_alarmAcknowledge an active alarm
Writes — medium-risk (5 tools, confirm-gated)
ToolDescription
vrm_add_alarmCreate alarm (float or enum threshold variant)
vrm_edit_alarmModify existing alarm
vrm_delete_alarmDelete alarm definition
vrm_reset_forecastsReset forecasting baseline for a site
vrm_set_site_settingsUpdate site name/notes/geofence/alarm-monitoring/Node-RED restrictions/etc.
Writes — high-impact (1 tool, confirm-gated)
ToolDescription
vrm_set_dynamic_ess_settingsWrite Dynamic ESS configuration (schedule, b2g, priceSchedule, batteryKwh, etc.)
Access management (8 tools, confirm-gated)
ToolDescription
vrm_invite_userInvite a user by email with access level (0=monitoring, 1=admin, 2=technician)
vrm_unlink_userRemove a user from a site
vrm_unlink_installationRemove the current user from a site (self-unlink)
vrm_set_user_rightsBulk-update per-user access levels
vrm_set_invite_rightsBulk-update pending-invite access levels
vrm_link_user_groupsLink user groups with access levels
vrm_set_user_group_access_levelChange or remove a user group's access level
vrm_add_siteAdd an installation to a user account
Access tokens (2 tools, confirm-gated)
ToolDescription
vrm_create_access_tokenCreate a long-lived personal access token
vrm_delete_access_tokenRevoke one token by id or ALL with "*"can self-lockout
Auth (3 tools — Bearer flow, deprecated 2026-06-01)
ToolDescription
vrm_auth_login_as_demoFetch a short-lived Bearer for the demo tenant (read-only)
vrm_auth_loginLog in with email+password (DEPRECATED, security hazard — use access tokens)
vrm_auth_logoutInvalidate the current Bearer session
Custom widgets CRUD (4 tools)
ToolDescription
vrm_get_custom_widgetsList custom widgets on a site
vrm_create_custom_widgetCreate (confirm-gated)
vrm_patch_custom_widgetUpdate (confirm-gated)
vrm_delete_custom_widgetDelete (confirm-gated)
Data attributes (2 tools)
ToolDescription
vrm_find_by_data_attributesSearch user's installations by attribute conditions (bs>=50,au=(1,2)); server-side page/count pagination
vrm_list_data_attributesCatalog of all VRM attribute definitions
Admin / collection (6 tools — most require admin privileges)
ToolDescription
vrm_admin_list_devicesAll devices across the system
vrm_admin_data_attributes_countCount installations by data-attribute condition
vrm_admin_search_downloadBulk search export
vrm_list_firmwaresFirmware catalog (requires feedChannel + victronConnectVersion)
vrm_add_systemRegister a new system (confirm-gated)
vrm_installation_overview_downloadBulk overview export (returns binary payload as base64)

Resources

URIContent
docs/vrm-api-openapi.yamlBundled VRM OpenAPI 3.1 spec (78 endpoints, updated 2026-04) used for reference

Configuration

Environment variables

VariableDefaultDescription
PORT3000HTTP port
HOST127.0.0.1Bind address
MCP_PATH/mcpEndpoint path
VRM_AUTH_SCHEMETokenDefault scheme for forwarding to VRM. Use Token (access tokens). Bearer is deprecated by VRM on 2026-06-01. Per-request override: x-vrm-auth-scheme header.
VRM_ALLOWED_SITES(unset)Comma-separated idSite allowlist. If unset, any site the token can access is allowed.
ALLOWED_ORIGINS(unset)Comma-separated list of allowed Origin header values. If unset, only same-origin + loopback accepted.

Local .env (optional)

Copy .env.example to .env and adjust. Node 20.6+ loads it directly:

node --env-file=.env dist/index.js

.env is gitignored. VRM tokens never go in .env — they're passed per-request in the Authorization header.

Per-request headers

HeaderPurpose
Authorization: Bearer <vrm-token>Required. The VRM token to forward.
x-vrm-auth-scheme: Token|BearerOptional. Overrides VRM_AUTH_SCHEME for this request. Use Bearer for /auth/loginAsDemo tokens.
x-vrm-skip-confirms: 1Optional. Bypasses the confirm: true gate on destructive tools. Automation only — never for interactive sessions. Logged as a skip_confirms_enabled warning.
OriginValidated against ALLOWED_ORIGINS (or same-origin) for DNS-rebinding defense.
mcp-protocol-versionValidated against supported versions (2025-06-18, 2025-03-26).

Security model

LayerWhat it does
Origin header validationRejects cross-origin requests unless Origin is in ALLOWED_ORIGINS (or matches the host for local dev). Defense against DNS rebinding.
Strict Accept + Content-TypePOST must send Content-Type: application/json and Accept including both application/json and text/event-stream. Also kills simple-POST CSRF.
MCP-Protocol-Version whitelistOnly accepts versions this server supports; unknown versions → 400.
Bearer token requiredMissing or implausibly short tokens rejected before any VRM call.
Token never stored / never loggedTokens live only in the fetch call that forwards them. Logger auto-strips any key containing token or authorization.
Zod input validationEvery tool argument is schema-validated. idSite/idUser must be positive integers; widget names must match a strict PascalCase regex; request bodies are schema-validated per tool.
URL-safe path constructionPath parameters are URL-encoded via encodeURIComponent in shared sitePath() / userPath() helpers. No string templating into URLs.
VRM base-URL host pinClient refuses to call anything other than vrmapi.victronenergy.com over HTTPS.
Destructive-op gatingTools that write/delete require { confirm: true } OR the x-vrm-skip-confirms: 1 header (automation opt-in). Refusals happen server-side, not just at the MCP client. MCP annotations (destructiveHint, idempotentHint, readOnlyHint) are set so clients can enforce UX confirmation.
Optional site allowlistVRM_ALLOWED_SITES=123,456 constrains the server to a fixed set of sites. Refused before hitting VRM.
Rate-limit awareness429 responses surface with Retry-After. No silent retries.
Error body redactionVRM error bodies are reduced to error_code: errors-text, truncated to 256 chars. Raw response bodies never flow to the client.
Stateless per-requestFresh McpServer + StreamableHTTPServerTransport per request — no cross-request state, no session auth.
Structured JSON stderr logsAll operational events are one-line JSON; token/authorization keys stripped.
DELETE returns 405Server is stateless; no session to delete.

How it works

┌──────────────────────────┐       HTTPS + Bearer token        ┌──────────────────────┐
│  MCP client              │ ────────────────────────────────▶ │  victron-vrm-mcp     │
│  (Connector API, Claude  │                                    │  (Streamable HTTP)   │
│   Code, Cursor, etc.)    │                                    └──────────┬───────────┘
└──────────────────────────┘                                               │
                                                                           │ x-authorization: Token …
                                                        https://vrmapi.victronenergy.com/v2

The server is stateless — each MCP request carries its own VRM token. A fresh McpServer + StreamableHTTPServerTransport is constructed per request, forwarding auth through the SDK's RequestHandlerExtra.authInfo channel.


Debugging

The MCP Inspector is the fastest way to poke at the server interactively.

# Terminal 1 — start the server
npm run build && npm start
# (or: PORT=3000 npx victron-vrm-mcp)

# Terminal 2 — launch the Inspector UI
npm run inspect
# Then in the UI:
#   Transport:  Streamable HTTP
#   URL:        http://127.0.0.1:3000/mcp
#   Headers:    Authorization: Bearer <your-vrm-token>
#               x-vrm-auth-scheme: Token   (or Bearer for /auth/loginAsDemo tokens)

Logs go to stderr as one-line JSON (the Streamable HTTP transport doesn't capture stderr through to clients — see the spec's debugging guide). For client-visible diagnostics, the spec offers notifications/message (planned for a future release).

Testing

208 tests across 8 files, runs in ~2 seconds:

npm test           # build + run all tests
npm run test:unit  # unit tests only (no server spawn)
FileCoverage
tests/helpers.test.tszod schemas, sitePath/userPath encoding, requireConfirm + skip bypass, resolveAuth token guards, formatVrmError redaction
tests/client.test.tsToken-length guard, scheme forwarding, array query encoding, host pin, 4xx → VrmApiError, 429 Retry-After, binary download round-trip
tests/logger.test.tsAuto-redaction of token/authorization keys (case-insensitive)
tests/http.test.tsEnd-to-end HTTP: 404/405/401/403/406/415/400/200, Origin validation, confirm gate, skip header
tests/tools.coverage.test.tsEvery one of the 52 tools has correct shape + annotations; every destructive tool refuses without confirm AND passes with skip header
tests/outputSchema.test.tsEvery tool declares outputSchema with ≥1 property; description hygiene (length, endpoint mention, no injection markers, destructive tools name the hazard)
tests/regressions.test.tsSpecific bug locks: skip-confirms bypass, firmwares required params, binary download, path traversal rejection, widget-name regex, limit bounds
tests/fuzz.test.tsMalformed JSON, 1 MB body, unicode/control-char/XSS/SQL-injection strings, array length limits, content-type edge cases, token-leak sentinel

CI: .github/workflows/ci.yml runs the full suite on Node 18 / 20 / 22 for every push + PR, plus a token-leak sentinel grep and npm audit.

Evals

evals/*.xml — 12 multi-tool scenario evaluations (not CI, graded manually against an LLM client). Cover discovery + overview, battery-last-hour, alarm triage, find-by-SOC, user invite, access-token rotation, tag management, safety refusal, site-id lookup, daily health check, ESS config change, automated nightly job.


Roadmap

Shipped:

  • 52 tools covering 88 VRM operations
  • Streamable HTTP transport + MCP Connector API support
  • Security hardening (Origin/Accept/Content-Type/Protocol-Version, token redaction, confirm gates, site allowlist, base-URL pin)
  • outputSchema on every tool
  • 208 tests + CI on Node 18/20/22
  • 12 scenario evals

Planned:

  • Cloudflare Workers adapter (stateless-friendly deployment)
  • Docker image
  • Token-bucket rate limiter matching VRM's 200-window / 3 req/s
  • Recorded-fixture tests (offline VRM response snapshots)
  • Paginate vrm_list_data_attributes cursor-style when VRM adds it

References

License

MIT

Server Config

{
  "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"
    }
  ]
}
Recommend Servers
TraeBuild with Free GPT-4.1 & Claude 3.7. Fully MCP-Ready.
Visual Studio Code - Open Source ("Code - OSS")Visual Studio Code
Baidu Map百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Amap Maps高德地图官方 MCP Server
Y GuiA web-based graphical interface for AI chat interactions with support for multiple AI models and MCP (Model Context Protocol) servers.
ChatWiseThe second fastest AI chatbot™
WindsurfThe new purpose-built IDE to harness magic
RedisA Model Context Protocol server that provides access to Redis databases. This server enables LLMs to interact with Redis key-value stores through a set of standardized tools.
Jina AI MCP ToolsA Model Context Protocol (MCP) server that integrates with Jina AI Search Foundation APIs.
Howtocook Mcp基于Anduin2017 / HowToCook (程序员在家做饭指南)的mcp server,帮你推荐菜谱、规划膳食,解决“今天吃什么“的世纪难题; Based on Anduin2017/HowToCook (Programmer's Guide to Cooking at Home), MCP Server helps you recommend recipes, plan meals, and solve the century old problem of "what to eat today"
MCP AdvisorMCP Advisor & Installation - Use the right MCP server for your needs
CursorThe AI Code Editor
Zhipu Web SearchZhipu Web Search MCP Server is a search engine specifically designed for large models. It integrates four search engines, allowing users to flexibly compare and switch between them. Building upon the web crawling and ranking capabilities of traditional search engines, it enhances intent recognition capabilities, returning results more suitable for large model processing (such as webpage titles, URLs, summaries, site names, site icons, etc.). This helps AI applications achieve "dynamic knowledge acquisition" and "precise scenario adaptation" capabilities.
DeepChatYour AI Partner on Desktop
MiniMax MCPOfficial MiniMax Model Context Protocol (MCP) server that enables interaction with powerful Text to Speech, image generation and video generation APIs.
Serper MCP ServerA Serper MCP Server
AiimagemultistyleA Model Context Protocol (MCP) server for image generation and manipulation using fal.ai's Stable Diffusion model.
EdgeOne Pages MCPAn MCP service designed for deploying HTML content to EdgeOne Pages and obtaining an accessible public URL.
BlenderBlenderMCP connects Blender to Claude AI through the Model Context Protocol (MCP), allowing Claude to directly interact with and control Blender. This integration enables prompt assisted 3D modeling, scene creation, and manipulation.
Playwright McpPlaywright MCP server
Tavily Mcp