Skip to main content
Glama
Nolex13

viaris-mcp

by Nolex13

viaris-mcp

CI License: MIT Node

An MCP server that puts an Orbis Viaris EV charger within reach of an AI agent: what the house is drawing right now, what the car took last night, and when it should charge next.

It speaks to the charger over your own network. No cloud account, no vendor app, nothing leaves the LAN.

You    "Is the car charging? How much is the house pulling?"
Agent  → get_status
       "Nothing plugged in. The house is drawing 436 W, and the charger is
        allowed up to 4000 W of the household budget."

You    "Only charge between 11pm and 6am."
Agent  → add_charging_schedule  start 23:00  end 06:00
       "Done — 23:00–06:00 is now active on the mennekes connector."

You    "How much did I charge last month?"
Agent  → get_charging_history
       "Eleven sessions, 214 kWh, averaging 3h20m each."

Requirements

  • Node.js 20 or newer

  • An Orbis Viaris charger on the same network as the machine running your agent. The server uses MCP's stdio transport, so it runs as a subprocess of the agent — it cannot reach across networks.

  • The charger's IP address. It does not answer ping, so find it in your router's DHCP list (the MAC begins E8:9F:6D, Espressif) or in the Viaris app.

Verify you can reach it before going further:

curl -s http://<charger-ip>/device

You should get JSON with model and serial. If that works, everything below will.

Related MCP server: IoT Device Management MCP Server

Install

Nothing to install. The configurations below run it with npx, which fetches the package the first time and caches it after.

If you would rather pin a version than take whatever is newest — reasonable for something that can change your household power limit — use viaris-mcp@0.1.0 in place of viaris-mcp everywhere below.

Worth doing if you want to read the code before pointing it at your charger, or if you plan to change it.

git clone https://github.com/Nolex13/viaris-mcp.git
cd viaris-mcp
npm install
npm run build

That produces dist/index.js. Everywhere below, replace

"command": "npx", "args": ["-y", "viaris-mcp"]

with

"command": "node", "args": ["/absolute/path/to/viaris-mcp/dist/index.js"]

Configure

One environment variable, VIARIS_CHARGERS, listing each charger as name=address:

VIARIS_CHARGERS="garage=192.168.1.100"
VIARIS_CHARGERS="garage=192.168.1.100,outdoor=192.168.1.101"

The name is yours to choose — it is how you will refer to the charger when talking to the agent, so garage beats charger1.

With one charger configured, the charger parameter is optional everywhere. With two or more it becomes required for writes, and reads report on all of them — a charger that is switched off shows up as an error in its own entry without spoiling the others.


Wire it into your agent

Edit the config file:

  • macOS — ~/Library/Application Support/Claude/claude_desktop_config.json

  • Windows — %APPDATA%\Claude\claude_desktop_config.json

  • Linux — ~/.config/Claude/claude_desktop_config.json

{
  "mcpServers": {
    "viaris": {
      "command": "npx",
      "args": ["-y", "viaris-mcp"],
      "env": { "VIARIS_CHARGERS": "garage=192.168.1.100" }
    }
  }
}

Restart Claude Desktop. The tools appear under the connectors icon.

claude mcp add viaris \
  --env VIARIS_CHARGERS=garage=192.168.1.100 \
  -- npx -y viaris-mcp

Then /mcp inside a session to confirm it connected.

Open the MCP servers panel → Configure MCP Servers, and add:

{
  "mcpServers": {
    "viaris": {
      "command": "npx",
      "args": ["-y", "viaris-mcp"],
      "env": { "VIARIS_CHARGERS": "garage=192.168.1.100" },
      "disabled": false
    }
  }
}

In ~/.continue/config.yaml:

mcpServers:
  - name: viaris
    command: npx
    args:
      - -y
      - viaris-mcp
    env:
      VIARIS_CHARGERS: garage=192.168.1.100

In your settings.json:

{
  "context_servers": {
    "viaris": {
      "command": {
        "path": "npx",
        "args": ["-y", "viaris-mcp"],
        "env": { "VIARIS_CHARGERS": "garage=192.168.1.100" }
      }
    }
  }
}

The server speaks MCP over stdio. Launch it as a subprocess with VIARIS_CHARGERS in its environment, and speak MCP on its stdin/stdout:

VIARIS_CHARGERS="garage=192.168.1.100" npx -y viaris-mcp

With the official SDK:

import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';

const client = new Client({ name: 'my-agent', version: '1.0.0' });
await client.connect(new StdioClientTransport({
  command: 'npx',
  args: ['-y', 'viaris-mcp'],
  env: { ...process.env, VIARIS_CHARGERS: 'garage=192.168.1.100' },
}));

console.log(await client.listTools());

Check it works without an agent at all:

VIARIS_CHARGERS="garage=192.168.1.100" npx -y viaris-mcp

It should start and sit there waiting for MCP traffic on stdin — that means the configuration parsed and the server is running. Ctrl-C to stop. A configuration mistake exits immediately and says what is wrong.

From a clone, npm run smoke goes further: it completes a real MCP handshake and verifies every tool is exposed as expected. Neither contacts your charger.


Tools

Reading

Tool

Parameters

Returns

get_status

charger?, element?

Charging state, live household and vehicle power, active limits

get_configuration

charger?

Everything readable: device, power, SPL mode, solar, LEDs, clock drift, plus OCPP/Modbus/MQTT under readOnly

get_charging_history

charger?, limit?

Past sessions, newest first: start, end, energy in Wh, duration

get_charging_schedule

charger?, element?

Programmed windows, times as HH:MM

get_status answers with:

{
  "charging": { "connector": "mennekes", "state": "free", "sessionId": 1, "user": null },
  "power":    { "home": 436, "car": 0, "total": 436, "unit": "W" },
  "limits":   { "homeLimit": 4000, "chargerMax": 7360 }
}

States are free, connected, charging, paused, finished, on, off, inoperative.

Writing

Tool

Parameters

Effect

add_charging_schedule

start, end, maxPowerW?, charger?, element?

Adds a window. "23:00""06:00" crossing midnight is handled

remove_charging_schedule

id, charger?, element?

Removes a window by the id get_charging_schedule reports

set_home_power_limit

limitW, charger?

The household power budget, in watts

set_charger_current_limit

amps, charger?

Charger's maximum current, capped at what the device reports

set_solar_config

enabled, priority?, charger?

Solar charging on/off and its priority

set_led_brightness

intensity (0, 50 or 100), charger?

LED brightness

set_device_time

epochSeconds?, timezone?, timezoneCode?, charger?

Clock, and timezone if both fields are given

Things to try

Is the car plugged in?

How much power is the house using right now?

Set the household limit to 6 kW, we upgraded the contract.

Charge only during the cheap night tariff, 11pm to 7am.

How much energy did I use for charging in the last three months?

Turn the charger LEDs down, they light up the bedroom.


Limitations

Everything runs on your LAN. stdio transport means the server is a subprocess of your agent, so the agent's machine must be on the same network as the charger. There is no remote mode, and adding one would mean exposing an unauthenticated device to a wider network.

The device API has no authentication. Anybody on your network can already read and change your charger's settings. This server does not — cannot — fix that; see SECURITY.md for what it does instead.

Mapped from one device. VIARIS UNI, firmware 7.2.53, single-phase, 32 A. Other models in the family share the API surface, and the code reads its limits from the device rather than assuming them, but three-phase behaviour and multi-connector models are untested against real hardware. Reports welcome.

Writes have type and range validation and nothing else. No confirmation step, no read-only mode. Ranges come from what the device reports, so a nonsense value is rejected, but a plausible wrong value is not. If your agent reads untrusted content from the web, consider what a prompt injection could reach.

Five of the eighteen history columns are unidentified. They are constant across a full buffer, so their meaning cannot be deduced by observation. They are omitted rather than guessed at.

No live streaming. The charger has a WebSocket that pushes power updates, but every tool here polls on demand. There is no background process and no stored history beyond the ~100 sessions the device keeps.

Reset, firmware upload and network configuration are deliberately absent. They can leave a charger unreachable. Use the web interface.

Possible improvements

Roughly in order of how much they would add:

  • A charging_summary tool that aggregates history into the answer people actually want — energy per month, cost given a tariff, average session — so the agent does not have to do arithmetic over a hundred rows.

  • WebSocket streaming for live power, exposed as an MCP resource that updates rather than a tool that polls.

  • Tariff awareness: given a time-of-use tariff, let the agent propose a charging window rather than only setting one it was told.

  • A read-only mode behind an environment variable, for people who want the monitoring without the ability to change anything.

  • Three-phase and multi-connector coverage, which needs someone with the hardware more than it needs code.

  • Solar-aware scheduling: the device already knows PV production; charging windows could follow it.

  • Identify the remaining CSV columns, most likely by correlating a session recorded while watching the web interface.

If one of these is what you came for, say so in an issue — it is useful to know which ones matter to someone.


Troubleshooting

ping says the charger is down. It is not. The device does not answer ICMP even when perfectly healthy. Use curl -s http://<charger-ip>/device instead.

I don't know the charger's IP. Look in your router's DHCP client list for a MAC starting E8:9F:6D (Espressif — the controller is an ESP32), or read it from the Viaris app. Give it a DHCP reservation while you are there: the configuration hardcodes the address.

The agent doesn't list any Viaris tools. Run the command from your config by hand — VIARIS_CHARGERS="garage=192.168.1.100" npx -y viaris-mcp — and read what it prints. Most failures are visible in one line there and invisible inside an MCP client, which tends to report only that the server did not start.

Running from source instead? Check the path in your config is absolute, that it points at dist/index.js rather than src/index.ts, and that you ran npm run build.

"no charger configured". VIARIS_CHARGERS did not reach the process. Most MCP clients do not inherit your shell environment, so the variable has to be in the env block of the client's config, not in your .bashrc.

"expected name=address". The value needs a name for each charger: garage=192.168.1.100, not just the address.

"several chargers are configured: specify..." You configured more than one in VIARIS_CHARGERS, so writes need to say which. Tell the agent the name: "set the garage charger to 6 kW".

First start is slow, or fails with no network. npx fetches the package the first time and caches it after. An MCP client that gives up quickly may time out on that first run: start it once by hand to warm the cache.

Everything times out. Check the machine running the agent is on the same network as the charger — stdio transport means the server is a subprocess there, not somewhere else. A VPN capturing all traffic will also do this.

A tool returns "the device did not declare the expected maximum". Your firmware answers GET /device without a field this server needs. Please open an issue with your firmware version and the response — that is exactly the kind of difference worth knowing about.

Something worked in the web interface but not here. The web interface may use an endpoint that is deliberately not exposed (reset, firmware, network) or one that was never mapped. docs/api.md lists what is known.


Development

npm install
npm test            # no charger required
npm run test:watch
npm run typecheck
npm run lint
npm run build
npm run smoke       # MCP handshake against the built server

Tests never touch a real charger: device/ runs against fixtures recorded from real hardware, transport/ against a local HTTP server, tools/ against fakes.

To re-record fixtures from your own charger:

VIARIS_CHARGERS="garage=192.168.1.100" npm run record-fixtures

Note that this writes your serial, MAC and charging history into tests/fixtures/ — anonymise before committing.

Architecture and the reasoning behind it: docs/design.md. Guidance for coding agents working here: CLAUDE.md.

Contributing

Bug reports from other Viaris models are especially useful — see CONTRIBUTING.md.

Documentation

License

MIT. Not affiliated with Orbis.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

No tool schema history has been recorded yet.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Nolex13/viaris-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server