mcp-venus-os
This server lets you monitor and control a Victron Venus OS system over MQTT, with read telemetry tools and confirmation-gated writes.
Read battery state of charge and related battery telemetry.
Read PV/solar charger power, voltage, current, and yields.
Read grid/AC power, voltage, current, and frequency.
Read inverter mode, state, AC/DC power, and temperature.
List discovered Victron devices.
Set VE.Bus inverter mode (
on,off,charger_only,inverter_only) with confirmation.Set maximum charge current limit in Amps with confirmation.
Set battery SoC limit percentage with confirmation.
Connect to and disconnect from the MQTT broker for real-time data.
Use
instance=0to read all devices of a type, orinstance=Nfor a single device.mqtt_subscribeis present but not implemented; it returns an error.
Provides real-time data streaming from Venus OS via MQTT, including tools to connect, disconnect, and subscribe to MQTT topics for device data.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-venus-os what's the current battery SoC and PV power?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
MCP Venus OS
Venus OS deployment notes
Prefer the MQTT backend on a NAS, server, or workstation. It keeps the MCP/HTTP
runtime off a constrained GX while using the existing Venus MQTT gateway.
The Cerbo audit on 2026-09-12 found no native mcp-venus-os service; the documented
Synology deployment is a separate host and must be checked there.
For an off-device HTTP deployment, configure an operator-owned HTTPS endpoint and bearer authentication. Start with device writes disabled and no Cerbo SSH credentials. Keep the deployment manifest, image pin, credentials, verification record and rollback plan with the operator's deployment configuration. The deployment matrix, HTTP authentication setup and HTTP session lifecycle describe the supported transports and client configuration.
SSH package refresh downloads into a temporary /data staging directory and
validates that setup exists before copying into the installed tree. It retains
files absent from the release, including virtualenvs and local configuration,
and calls setup install without interactive stdin. Package-owned uninstall
handles service removal; there is no recursive-delete fallback. A release can
still replace same-named tracked files, so keep local secrets in the package's
documented external configuration files and retain a backup before upgrades.
MCP (Model Context Protocol) server for Victron Venus OS management. Primary transport is the Venus OS MQTT gateway (N/<portalId>/… reads, W/<portalId>/… writes) so the server can run off-device; direct D-Bus remains available for on-device installs.
Project decisions and participation are described in Governance, Contributing, the Code of conduct, and the roadmap. The security assurance case and quality evidence explain the checks and their limits. The OpenSSF evidence index separates verified evidence from criteria that remain open, including repository access continuity. The container repeatability procedure explains full-image comparison and preservation of original build provenance.
Related MCP server: Victron VRM MCP Server
Release process
See the release strategy for validation, nightly, beta, RC and stable promotion rules, and the operator runbook for local commands.
Features
MQTT read path: subscribes to discovery markers and the exact telemetry paths consumed by tools and configured hardware contracts, then serves a stale-guarded cache (
stale,age_secondsper reading)Write tools over
W/topics: inverter mode, charge-current limit, SoC limit — exact hardware contracts and fresh read-back are required; no automatic rollback is providedSafety constraints: confirmation gate + hard limits enforced before any publish
Two server transports: stdio (Claude Code launches the process) or streamable HTTP with optional bearer-token auth (Synology Docker / shared use)
Optional D-Bus backend: unchanged behavior for installs running directly on the Cerbo
Quick Start
Installation
The supported release channel is GitHub Releases.
There is no mcp-venus-os distribution on PyPI as of 2 November 2026. The signed
stable release below is v0.2.21.
Use Python 3.11+, Git, the GitHub CLI, and
Cosign 3.1.3 or newer. Review the pinned
source revision
and release verification
before trusting its verifier. Run these commands in a new directory:
set -e
git clone --no-checkout https://github.com/4alvit/mcp-venus-os.git release-verifier
git -C release-verifier checkout --detach cb2df16965cf2032a593e7f76063f49ee130d448
gh release download v0.2.21 --repo 4alvit/mcp-venus-os --dir release-v0.2.21
python3 release-verifier/scripts/release_signing.py verify release-v0.2.21 \
--source-sha cb2df16965cf2032a593e7f76063f49ee130d448
python3 -m venv .venv
source .venv/bin/activate
python -m pip install ./release-v0.2.21/mcp_venus_os-0.2.21-py3-none-any.whlDownload the complete asset set, including the OCI archive and its provenance
sidecar, even when installing only the wheel: verification requires the complete
signed inventory. The verified wheel SHA-256 is
2ff82b7fab40b67187109ebe1066a3641dbfb8f00e126ca88374c1870c8d436c.
The publication verification
confirmed that all 13 public assets match the qualified RC bytes.
Historical v0.2.11 remains unsigned, and nightly/beta/RC releases remain
prereleases. The final build uses the accepted RC's source and recipe with its
own final version and signed inventory. Installing the default Git branch selects
development code. GitHub release publication does not publish to PyPI, update a
GHCR tag, or deploy a running server.
Or for development:
git clone https://github.com/4alvit/mcp-venus-os
cd mcp-venus-os
uv sync --locked --extra devPython installations use the selected virtual environment; pip also supports
its normal --prefix and --target installation locations. To remove an
installation, run python -m pip uninstall mcp-venus-os with that environment's
interpreter, or remove the dedicated virtual environment after stopping the
service. Keep deployment secrets outside the environment. For contributor tests
and build-tool installation, follow Contributing.
Prerequisites (Cerbo GX)
Settings → Services → MQTT Gateway, mode = Local network (listens on LAN :1883)
Note the portal ID shown on the MQTT Gateway page (also
com.victronenergy.system/Serial)Verify:
mosquitto_sub -h <cerbo-ip> -t 'N/<portalId>/system/#' -vreturns telemetry
Configuration
Create a .env file from .env.sample or set environment variables:
TRANSPORT_BACKEND=mqtt # mqtt (default) | dbus (on-device only)
SERVER_TRANSPORT=stdio # stdio (default) | http
# MQTT — Venus OS gateway on the Cerbo
MQTT_HOST=<cerbo-ip>
MQTT_PORT=1883
MQTT_PORTAL_ID=<venus-portal-id>
MQTT_STALE_AFTER_SECONDS=60
# Safety
SAFETY_REQUIRE_CONFIRMATION=true
SAFETY_MAX_CHARGE_CURRENT=100
SAFETY_MAX_DISCHARGE_CURRENT=100
SAFETY_MIN_SOC_LIMIT=10
SAFETY_MAX_SOC_LIMIT=100
SAFETY_ALLOWED_MODES=on,off,charger_only,inverter_only,eco
SAFETY_ENABLE_WRITES=false # MUST be true to enable any write/control tools
# HTTP mode extras
SERVER_HOST=127.0.0.1 # 0.0.0.0 inside containers
SERVER_PORT=8000
SERVER_AUTH_TOKEN= # optional bearer token for HTTP modeRunning the Server
uv run mcp-venus-os # stdio (Claude Code launches this)
uv run mcp-venus-os --transport http # or SERVER_TRANSPORT=httpDeployment Matrix
Target | Transport backend | Server transport | Notes |
MP Kubernetes (shared) |
| HTTPS |
|
Synology Docker (alternative) |
|
| saved deployment layout; verify host availability |
macOS (fallback) |
|
| local process via |
On-device (Cerbo) |
|
| legacy mode, no gateway needed |
Docker:
cp .env.sample .env # fill in cerbo IP + portal id (+ token if exposing beyond LAN)
docker compose up -d # healthcheck hits GET /mcp until the MCP endpoint answersHTTP Auth Token
HTTP mode is protected by a static bearer token (SERVER_AUTH_TOKEN). Without it the
server runs unauthenticated — only sensible on a trusted home LAN.
Generate and apply:
openssl rand -hex 24 # generate once
echo 'SERVER_AUTH_TOKEN=<hex>' >> .env # add to the deployment .env
docker compose up -d # restart so the container picks it upClients then send Authorization: Bearer <token> on every request. Unauthenticated or
wrong-token requests get 401. For Claude Code:
claude mcp add --scope user --transport http venus-os \
https://venus-os.k3s.2560801.xyz/mcp \
--header "Authorization: Bearer <token>"Or via the project-level .mcp.json, which reads the token from the
VENUS_MCP_TOKEN environment variable (export VENUS_MCP_TOKEN=<hex> before launching
Claude Code):
{
"mcpServers": {
"venus-os": {
"type": "http",
"url": "https://venus-os.k3s.2560801.xyz/mcp",
"headers": { "Authorization": "Bearer ${VENUS_MCP_TOKEN}" }
}
}
}Claude Code Registration
Primary (shared MP HTTPS endpoint — see above). Fallback: launch the server locally so it works even when the NAS is down:
claude mcp add --scope user venus-os \
-e TRANSPORT_BACKEND=mqtt -e MQTT_HOST=<cerbo-ip> -e MQTT_PORTAL_ID=<id> \
-- uv --directory /path/to/mcp-venus-os run mcp-venus-osDSM notes (deployed at /volume1/docker/mcp-venus-os/):
The 2026-09-12 audit found this directory still present, but no MCP container in the NAS Docker inventory, including stopped containers. Treat the instructions below as the saved deployment layout, not evidence of a currently running endpoint. Verify the existing configuration and host before enabling it again.
Plain
docker compose(full path/usr/local/bin/docker) works fine; Container Manager is not required.Host port 8000 is taken by Portainer on typical DSM installs — remap in the compose
ports:(e.g."8080:8000").SFTP/scp may be disabled; copy files via
ssh ... 'cat > file'.The
.env(portal id, token) lives only on the NAS, mode 600.
Container Images
The reviewed publication mapping is ghcr.io/4alvit/mcp-venus-os. The published 0.2.21 image contains Linux AMD64 and ARM64 variants at immutable index digest sha256:6cf7e9b88a1e77ab6eea17e393f4e225d9e6a152f393488738bda020c64ecd48. Candidate builds produce an OCI archive; approved stable bytes are promoted separately to the registry without rebuilding. Follow the operator runbook for the versioned tag and optional latest update. The former main/tag-triggered GHCR and Docker Hub publishers are retired.
Available Tools
Read Tools
Tool | Description |
| Battery SoC, voltage, current, power, temperature (+ |
| PV/solar charger power, voltage, current, yields (power falls back to V×I) |
| Grid power, voltage, current, frequency from the |
| Inverter mode, state, AC/DC power, temperature |
| Devices discovered from received MQTT topics |
Write Tools (Requires Confirmation)
Tool | Writes to | Notes |
|
| mode name → enum code via per-device table; unknown combos rejected before publishing |
|
| Amps |
|
| % — confirm exact BMS path on target battery |
MQTT Tools
Tool | Description |
| Connect to the Cerbo gateway and prime the read cache |
| Disconnect; previously accepted control values are not automatically undone |
| Stub — reports "not yet implemented" rather than pretending success |
Conditional Tool Groups (context-friendly)
Tools are registered only when their service is present, so installations without them never pay tool-schema context:
Group | Detected via | Tools |
|
|
|
|
|
|
|
| Cerbo management toolkit (below) |
Multi-instance reads: instance=0 → {"readings": [...], "total_power": …} for
every device of the type; explicit instance=N → single dict.
Cerbo SSH Management
When SSH credentials are configured, these register alongside the broker-detected groups; 🔒 = confirmation-gated:
Tool | Purpose |
| reachability, firmware version, addresses |
| firmware dry run |
🔒 | download + apply firmware |
🔒 | set root password (stdin→chpasswd) |
| SetupHelper + installed packages |
🔒 | SetupHelper package lifecycle |
🔒 | arbitrary command, output capped |
# .env (local/stdio runs)
SSH_HOST= # defaults to MQTT_HOST
SSH_USER=root
SSH_KEY_PATH=~/.ssh/id_ed25519 # preferred…
# SSH_PASSWORD= # …or password
CERBO_ROOT_PASSWORD= # used by cerbo_enable_ssh when not passedDocker deployments mount the key instead of passing secrets through .env:
mkdir keys && cp ~/.ssh/<cerbo-key> keys/cerbo_rsa
chown 999:999 keys/cerbo_rsa # uid of the container's app user
chmod 600 keys/cerbo_rsa # compose already mounts ./keys:/app/keys:ro
# compose sets SSH_KEY_PATH=/app/keys/cerbo_rsa; remove those lines to use
# SSH_PASSWORD from .env instead
docker compose up -dTo bootstrap access on a fresh Cerbo: GUI → Settings → General → set the root
password once (cerbo_enable_ssh automates it from then on).
Clients can discover the live surface at runtime via the MCP resource
venus-os://capabilities (also summarized in server instructions); full
reference in docs/CAPABILITIES.md.
MQTT Topic Map
The server speaks the Venus OS MQTT-Gateway protocol:
N/<portalId>/<type>/<instance>/<Path> reads (published by Venus)
W/<portalId>/<type>/<instance>/<Path> writes (published by us)
R/<portalId>/<type>/<instance>/<Path> request one current value
R/<portalId>/keepalive maintain notification publication
inverter/state inverter-control aggregate
tank/<n>/Level dbus-pump tank levelReads: broker subscriptions include shallow service items and
Mgmtmetadata, small discovery markers for internal services, and all telemetry fallback paths consumed by tools. Configured hardware contract targets and identity paths, companion capability topics, and explicit caller subscriptions are preserved. Unused nested settings and history stay off the receive socket. Explicit broad caller subscriptions can opt back into that additional traffic.Tank discovery:
get_tank_level()accepts exacttank/<n>/Leveltopics, where<n>is a nonnegative ASCII decimal integer with no sign or leading zeroes (except0). Malformed names and additional path segments are ignored. An explicit positive instance reads its own cached topic without discovering unrelated tanks. Discovery remains numerically sorted and preserves the existing single-tank and multiple-tank response shapes.Freshness: cache entries use actual notification receipt times; tool output carries
stale+age_seconds(thresholdMQTT_STALE_AFTER_SECONDS, default 60). Each connection requests the initial tree once, then renews Venus publication every 30 seconds with{"keepalive-options":["suppress-republish"]}. The owned decoder worker also requests exact observed tool/contract values every 30 seconds, at most eight reads per 250 ms and 512 per cycle, rotating larger catalogs. Discovery-only metadata is not periodically republished. Missing replies remain stale; sending a read or keepalive never changes an item's age. No wildcard read requests or automatic control writes are used.FlashMQ Serial identity:
system/0/Serialis also a legacy keepalive alias. When a contract or explicit subscriber requires it, the exact read uses the same suppression payload, avoiding a full-tree republish. A retained Serial replay only establishes that the item exists; a live notification is required before it can provide fresh identity evidence. This follows the FlashMQ gateway protocol. The suppression behavior is for FlashMQ; compatibility with the retired Pythondbus-mqttgateway is not claimed.Reconnects: concurrent reads share one MQTT connection and its background recovery loop. A connection wait times out after five seconds without creating a competing client or refreshing cached timestamps. Shutdown waits are bounded; a worker still stopping prevents a replacement from using the same client ID. Paho owns the network thread and wake-up socket so publications from other threads are queued; only the network thread writes MQTT packets. This prevents maintenance requests from interleaving with a partially sent packet.
Disconnect diagnostics: each warning includes bounded
mqtt_diagnosticsJSON containing the connection epoch, callback ordinal, queue depth/drop count, and monotonic ages/counts for notification receipt, PINGREQ attempts and decoded PINGRESPs, socket generation and network-thread liveness. A socket generation advances on socket open, including connections that never receive CONNACK. A ring of at most 12 transport events stays in memory until a disconnect; repeated callbacks omit the ring unless a new event has arrived. Public socket callbacks capture metadata before closure, when the passed socket is still open even thoughclient.socket()is already empty. The public log callback observes only Paho's two fixed ping events. Other log strings, topics, payloads, addresses and credentials are never retained or forwarded by these diagnostics; debug logging is not enabled. On Linux, events include best-effortTCP_INFOcounters/timers and kernel receive and send queue byte counts. Missing measurements have a fixed status and are omitted, never reported as zero. The send queue includes unsent and unacknowledged bytes; TLS buffers are not included. These sequential measurements are not an atomic snapshot. No socket reads, peeks, option changes or packet captures occur. Sampling happens only at socket open/close and ping-related events, never per telemetry message; no background sampler or second socket writer is introduced.pingreq_attemptprecedes Paho enqueueing the packet. The guardedoutput_drained_after_pingreqevent means Paho's output queue subsequently drained on the same live socket; closing the socket cannot generate this event. Neither proves delivery to the broker.pingresp_decodedrecords parser progress, not wire arrival, and thread liveness is not a network-loop heartbeat. These observations help distinguish client/TCP backlogs from a missing response but cannot establish the cause of a timeout on their own. Paho 2.1 can invoke the disconnect callback twice for one keepalive failure;disconnect_callbackandduplicate_in_epochidentify repeated callbacks in one epoch, not necessarily the same outage. An epoch advances only after a successful CONNACK, so failed reconnect attempts can also share it. Timers, freshness limits, subscriptions and reconnect behavior are unchanged.Writes: a value is published as JSON only to its hardware-qualified
W/…path. There are no periodic writes to additional paths and no automatic rollback on disconnect/shutdown. Persistence is device-specific.Verification: after each write the matching
N/…topic is polled for up to 5s (WRITE_VERIFY_TIMEOUT_S); timeout → explicit error, never silent success. A timeout does not prove rejection or undo a command that reached the device. The gateway keep-alive controls notification publication, not the lifetime of arbitrary control values.
Safety Model
Defense runs in order, before any publish:
Confirmation gate (
SAFETY_REQUIRE_CONFIRMATION=true): first call withoutconfirmed=truereturns a confirmation prompt instead of writing.Hard limits: charge/discharge current ≤ configured maxima; SoC limits clamped to
[SAFETY_MIN_SOC_LIMIT, SAFETY_MAX_SOC_LIMIT]; inverter modes restricted toSAFETY_ALLOWED_MODES.Mode enum mapping: only modes with a known device-type enum code reach the wire; anything else is rejected pre-publish.
Reviewed hardware contract binds the exact path and allowed semantics to fresh firmware, target and BMS identities; missing contracts deny writes.
Read-back verification closes the loop — an unacknowledged write is reported as failed.
VE.Bus /Mode uses 1 = charger only, 2 = inverter only, 3 = on, 4 = off;
3 is not Eco. The separate inverter service uses 5 for Low Power/Eco, while
solarcharger uses 1 for on and 4 for off. These mappings follow
Victron's D-Bus specification.
Existing hardware contracts with conflicting codes fail closed and require
review; the server does not rewrite them automatically.
Known caveats: the exact SoC-limit path depends on the battery
BMS. Also note that acceptance ≠ persistence: when another service owns a
path (e.g. a BMS driver continuously asserting /Dc/0/MaxChargeCurrent), Venus
acknowledges and echoes the written value but re-applies its own within seconds —
verified live, where a 45 A write to a BMS-owned 52 A limit echoed successfully
and snapped back ~3 s later. The tool reports acceptance;
whether the value sticks depends on which service owns the item.
Configuration options:
SAFETY_REQUIRE_CONFIRMATION- Require confirmation for write operations (default: true)SAFETY_MAX_CHARGE_CURRENT- Maximum allowed charge current in Amps (default: 100)SAFETY_MAX_DISCHARGE_CURRENT- Maximum allowed discharge current in Amps (default: 100)SAFETY_MIN_SOC_LIMIT- Minimum allowed SoC limit % (default: 10)SAFETY_MAX_SOC_LIMIT- Maximum allowed SoC limit % (default: 100)SAFETY_ALLOWED_MODES- Comma-separated list of allowed inverter modes
Architecture
graph TD
subgraph "Venus OS Hardware"
VOS[Venus OS / Cerbo GX]
DBUS[(D-Bus System Bus)]
MQTT_BROKER[(MQTT Broker)]
end
subgraph "MCP Server (mcp-venus-os)"
MCP[FastMCP Server]
DBUS_CLIENT[D-Bus Client]
MQTT_CLIENT[MQTT Client]
SAFETY[Safety Validator]
TOOLS[MCP Tools]
end
subgraph "Clients"
CLAUDE[Claude Desktop]
OTHER[Other MCP Clients]
end
VOS --> DBUS
VOS --> MQTT_BROKER
DBUS --> DBUS_CLIENT
MQTT_BROKER --> MQTT_CLIENT
DBUS_CLIENT --> TOOLS
MQTT_CLIENT --> TOOLS
SAFETY --> TOOLS
TOOLS --> MCP
MCP -.->|stdio/JSON-RPC| CLAUDE
MCP -.->|stdio/JSON-RPC| OTHERDevelopment
# Install dev dependencies
uv sync --dev
# Run linter
uv run ruff check src/
# Run type checker
uv run mypy src/
# Run tests
uv run pytestLicense
MIT License - see LICENSE file for details.
Contributing and security
See CONTRIBUTING.md for development, bug reports and proposals, SECURITY.md for confidential vulnerability reports and deployment boundaries, and the OpenSSF evidence index for assessment scope and verification.
Verify the SSH host key before upgrading
SSH management now verifies the Cerbo host key. Without SSH_KNOWN_HOSTS,
the client reads the standard ~/.ssh/known_hosts trust file. You can set an
explicit verified file path; the Compose example mounts keys/known_hosts at
/app/keys/known_hosts. Compare the device's SSH host-key fingerprint through
an independently trusted console or administrator before accepting it. A key
observed by ssh-keyscan alone is not proof of identity.
Unknown or changed host keys now fail closed. After a genuine firmware reflash, verify the new key independently before replacing the trusted record. Never disable host-key verification to work around a mismatch. The MCP API does not provide an insecure bypass. SSH access still uses its configured credentials, and write operations still require the existing safety gates.
SSH negotiation requires SHA-2/Ed25519/ECDSA authentication and ephemeral key exchange. Use trusted Ed25519/ECDSA host keys or RSA keys of at least 2048 bits. Legacy servers limited to SHA-1 must be updated before connecting.
Both server host keys and the private key selected by SSH_KEY_PATH must use
RSA of at least 2048 bits, NIST P-256/P-384/P-521, Ed25519 or Ed448. Weak host keys
are removed from the trusted set without changing hostname, port, hashed-host,
wildcard or revocation matching. A trust file containing only weak keys therefore
refuses the connection, including a later key exchange on an existing connection.
The selected client key is checked before connecting; failure does not fall back
to a password. No private-key content is included in the error.
The supported authentication inputs are an ordinary private-key file at
SSH_KEY_PATH and/or SSH_PASSWORD. SSH agents, default identity files,
PKCS#11 tokens, host-based/GSS authentication and SSH/X.509 certificates are not
used. This makes the key policy independent of ambient credentials. If an
installation relied on one of those previously implicit AsyncSSH behaviors,
configure an explicit supported key before upgrading. For a custom host trust
file use SSH_KNOWN_HOSTS; UserKnownHostsFile in an ambient SSH config does not
replace it. The client never disables host verification for an empty trust file.
To keep SSH management disabled, leave both SSH_KEY_PATH and SSH_PASSWORD
unset and restart the MCP server. The SSH tools are not registered in this mode;
the MQTT telemetry tools remain available. This does not disable or weaken MQTT
TLS or its independent credentials.
MQTT certificate policy
When MQTT_TLS=true, the owned Paho connection verifies the broker's certificate
and hostname, then checks every certificate in the verified chain, including its
selected trust anchor, before sending MQTT CONNECT or credentials. RSA keys must
have an actual modulus of at least 2048 bits; EC keys require at least 224 bits,
DSA requires a 2048-bit group and 224-bit subgroup, and Ed25519/Ed448 are supported.
OpenSSL can impose stronger restrictions. TLS is at least 1.2; stricter defaults
and the existing cipher selection remain intact.
This closes a boundary where OpenSSL security level 2 alone accepts a 2047-bit RSA
key. Reissue a weak broker or CA certificate instead of disabling verification.
The client keeps the same system trust and SSL_CERT_FILE/SSL_CERT_DIR behavior
as Paho's default tls_set(). MQTT protocol 3.1.1, connection ownership, retries,
subscriptions and the plaintext mode are unchanged. This does not secure the
plain MQTT mode or certify an external broker's configuration.
The supported runtime is CPython 3.11 or later with the project's existing
cryptography dependency. The guard uses the public verified-chain API when
available, and CPython's internal SSL-object API on 3.11/3.12. A runtime that
cannot supply its verified chain fails closed. The configuration does not expose
MQTT client-certificate or proxy settings; this change adds neither feature.
No system-wide SSL defaults or CA stores are modified.
tests/test_mqtt_tls.py exercises the actual application/Paho path with disposable
local brokers: trusted RSA 1024/2047 leaf, intermediate and root rejection,
strong RSA/EC acceptance, invalid issuer/hostname controls and zero MQTT credential
bytes on rejection. Separate low-security fixture clients validate each test
chain with normal CA/hostname verification. No physical device is contacted.
The helper is adapted under MIT from the reviewed
inverter-dashboard TLS policy
and FastAPI MQTT policy.
Release-candidate fuzzing
The target validates the production hardware-contract schema, serializes accepted contracts, and checks that invalid numeric values and missing identity evidence are denied. Identity readings are synthetic values. It creates no D-Bus, MQTT or SSH client, and it never authorizes or sends a real write. The package namespace bypasses client-export initialization; the actual hardware_contracts module is imported and instrumented.
RC-only fuzzing policy, local reproduction and failure handling.
Available Tools
11 toolsget_battery_socA
Get battery state of charge.
instance=0 returns every discovered battery as readings; instance=N
a single device dict.
Inputs: instance. Returns: object
get_grid_statusA
Get grid/AC status.
instance=0 returns every discovered grid meter as readings;
instance=N a single device dict.
Inputs: instance. Returns: object
get_inverter_statusA
Get inverter mode and state.
instance=0 returns every discovered vebus unit as readings;
instance=N a single device dict.
Inputs: instance. Returns: object
get_pv_powerA
Get PV/solar charger power data.
instance=0 returns every discovered solarcharger/pvinverter as
readings plus total_power; instance=N a single device dict.
Inputs: instance. Returns: object
list_devicesA
List all Victron devices visible to the server.
Inputs: no named parameters. Returns: result
mqtt_connectB
Connect to MQTT broker for real-time data.
Inputs: no named parameters. Returns: object
mqtt_disconnectA
Disconnect from MQTT broker.
Inputs: no named parameters. Returns: object
mqtt_subscribeA
Subscribe to MQTT topic pattern.
Not yet implemented - returns an error.
Inputs: topic_pattern (required). Returns: object
set_charge_current_limitA
Set maximum charge current limit in Amps.
Requires confirmation for write operations.
Inputs: current (required), instance, confirmed. Returns: object
set_inverter_modeB
Set VE.Bus inverter mode (on, off, charger_only, inverter_only).
Requires confirmation for write operations.
Inputs: mode (required), instance, confirmed. Returns: object
set_soc_limitB
Set battery SoC limit percentage.
Requires confirmation for write operations.
Inputs: soc_limit (required), instance, confirmed. Returns: object
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 11 tools
Each tool has a clearly distinct purpose: setting inverter mode, charge current, SoC limit, MQTT operations, and device-specific data retrieval. No overlapping functionality that could cause confusion.
Consistent verb_noun pattern: set_inverter_mode, list_devices, get_battery_soc, mqtt_connect, etc. All names follow snake_case with clear action prefixes.
11 tools for a Venus OS MQTT server is well-scoped, covering the key operations (device listing, data retrieval, setpoints, MQTT management) without bloat.
Core read/write functionality is covered, but mqtt_subscribe is marked as not yet implemented, and there is no explicit tool to read real-time data from the broker despite MQTT tools. Minor gap: no tool for general MQTT publish or unsubscribe.
Maintenance
Related MCP Connectors
MCP server wrapping the Tesla Fleet API and TeslaMate API
An MCP server giving access to Grafana dashboards, data and more.
MCP server with quote and live cryptocurrency price tools, local and cloud-deployed transports.
Hosted MCP server for MT4 and MT5: read accounts, prices and candles, and place or close orders.
Related MCP Servers
- AlicenseAqualityBmaintenanceConnect AI assistants to Victron Energy systems to read real-time solar, battery, grid, and inverter data from your local network via Modbus TCP or MQTT.32134 npm7MIT
- AlicenseBqualityDmaintenanceRead-only MCP server integrating with the Victron VRM API to monitor solar systems, batteries, alarms, and more.4139 npm6MIT
- AlicenseNot gradedqualityDmaintenanceA powerful MCP server that enables AI assistants like Claude to access, analyze, and optimize solar energy data from FoxESS inverters.3MIT
- AlicenseNot gradedqualityDmaintenanceMCP server for Solplanet ASW5-T inverter, enabling natural language queries about solar energy system status and control.MIT