mcp server
solar-manager-mcp
MCP server for Solar Manager (solar-manager.ch) — cloud API and local gateway API for AI assistants
Set up
Runs on your computer. Pick your agent and operating system.
This project does not publish an install method we can turn into a config. Follow the README instead.
README
synced Oct 23, 2026solar-manager-mcp
An MCP server for Solar Manager, the Swiss PV energy management system. It lets an AI assistant read your plant's live and historical data — and, if you explicitly allow it, control your devices.
Both of Solar Manager's APIs are covered:
- Cloud API (
cloud.solar-manager.ch) — history, forecast, tariffs, statistics, device control. Needs an internet connection and a Cloud API key. - Local API (the gateway on your own network) — live values every few seconds, no internet, no cloud round-trip. Needs a local API key from the gateway UI.
One file, no build step, no framework. uv pulls the single dependency on first run.
Works with Claude over stdio and with ChatGPT
over HTTP.
Not affiliated with or endorsed by Solar Manager AG. Built against the public External API.
Tools
| Tool | What it does |
|---|---|
list_endpoints(search) | Lists the ~50 cloud endpoints, filtered by substring ("battery", "forecast", "tariff"). Deprecated ones are marked. |
describe_endpoint(path, method) | Parameters and response schema for one endpoint, $refs inlined. |
request(method, path, query, body) | Calls a cloud endpoint. Writes are blocked by default. |
local_live() | Live values from the gateway on your LAN, with device names resolved. |
Why four tools instead of fifty
Generating one tool per endpoint would put ~50 tool definitions into the model's context and would need regenerating whenever Solar Manager ships a new API version. Instead the OpenAPI spec is fetched at runtime and searched on demand, so the server stays current on its own and costs almost no context. The assistant looks up what it needs, then calls it.
Setup
1. Get your keys
Cloud API key — in the Solar Manager portal: Profil bearbeiten → Cloud-API-Schlüssel → API Schlüssel hinzufügen. Pick the scopes you want:
| Scope | Needed for |
|---|---|
read | All GET endpoints — data, forecast, devices, tariffs |
externalOverride:read | Reading the external-override (control) state |
write | Configuration, e.g. PUT /v1/configure/sensor-priority |
externalOverride:write | The PUT /v1/control/* endpoints that actually switch hardware |
Read-only (read + externalOverride:read) is the sane default. If the menu entry is
missing, Solar Manager support has to enable the feature for your account.
Local API key — in the gateway UI: Einstellungen → Lokale API → API Schlüssel hinzufügen. Make sure the HTTP or HTTPS toggle is on. This is a different key from the cloud one and only works against the gateway itself.
Copy either key immediately — neither is shown again after creation.
2. Find your gateway's IP
The gateway answers on /v2/point. From a machine on the same network:
for i in $(seq 1 254); do (curl -sk -m 2 -o /dev/null -w "%{http_code} 192.168.1.$i\n" "https://192.168.1.$i/v2/point" &); done | grep 401
The host replying 401 (unauthorized, because no key was sent) is your gateway. Adjust the
subnet to yours. Giving it a DHCP reservation saves you doing this again.
3. Register with your client
- Claude — Claude Desktop and Claude Code, local, no tunnel needed
- ChatGPT — needs developer mode and an HTTPS endpoint, so the server runs in HTTP mode behind a tunnel
The short version for Claude Desktop, keys inline in the config:
{
"mcpServers": {
"solar-manager": {
"command": "uv",
"args": ["run", "--script", "/absolute/path/to/solar-manager-mcp/server.py"],
"env": {
"SOLAR_MANAGER_API_KEY": "sm_...",
"SOLAR_MANAGER_LOCAL_URL": "https://192.168.1.42",
"SOLAR_MANAGER_LOCAL_API_KEY": "..."
}
}
}
}
Every key is optional: cloud key only → cloud tools work; local key only → local_live()
works; both → everything.
If you'd rather not have credentials in the config file — because it's synced, shared, or
you juggle several clients — copy secrets.example.json to secrets.json next to
server.py, chmod 600 it, and leave the env block out. Environment variables win over
secrets.json when both are present.
4. Verify
uv run --script server.py --check
Offline self-check of the parts that can break silently. For an end-to-end test, ask your assistant "what is my solar plant doing right now?".
Usage notes
Most cloud endpoints are keyed by smId, the plant identifier. Get it from
GET /v1/users (field sm_id). Typical calls:
GET /v1/overview today / week / month / year totals
GET /v1/users account info, sm_id
GET /v3/users/{smId}/data/range?from&to&interval history (interval 300, 900 or 3600 s)
GET /v3/users/{smId}/data/stream latest values via the cloud
GET /v3/users/{smId}/data/forecast PV forecast, 15-minute steps
GET /v3/users/{smId}/devices devices incl. IP, MAC, priority
GET /v3/users/{smId}/tariffs tariff configuration
Reading the data
Field names are terse and shared across both APIs:
| Field | Meaning |
|---|---|
pW / pWh | PV production, power in W / energy in Wh per interval |
cW / cWh | Consumption, power / energy |
bcW / bcWh | Battery charging, power / energy |
bdW / bdWh | Battery discharging, power / energy |
soc | Battery state of charge in % |
eWh / iWh | Per device: energy exported / imported over the interval |
scWh / cPvWh | Self-consumption including / excluding battery charging |
cOtherW | Residual consumption of unmetered devices |
power | Per device power in W (negative = feeding in, e.g. a discharging battery) |
activeDevice | 1 on/charging, 0 off, −1 discharging |
t / iv | Timestamp / interval in seconds the Wh values accumulate over |
Device control
The PUT /v1/control/* endpoints physically switch batteries, car chargers, heat pumps and
water heaters. They are blocked unless you set SOLAR_MANAGER_ALLOW_CONTROL=1. The safer
route is not to grant the write scopes to your API key in the first place — then control is
impossible rather than merely disabled.
The local API is read-only by nature: it exposes only /v2/point and /v2/devices. No
history, no forecast, no control.
Gotchas
- Never send your API key to
POST /v3/auth/refresh. That endpoint treats it as a refresh token and rotates it, invalidating the key in your config. This server only ever sendsx-api-key, which does not rotate. /v2/customerstimes out server-side. Use/v1/usersinstead.- The local gateway uses a self-signed certificate, so TLS verification is disabled for
that host only. Don't point
SOLAR_MANAGER_LOCAL_URLat anything internet-facing. - Email/password auth (
SOLAR_MANAGER_EMAIL+SOLAR_MANAGER_PASSWORD) still works as a fallback via the deprecated/v1/oauth/login, which Solar Manager removes in June 2027. Use an API key.
Requirements
uv and Python 3.10+. The only dependency is the MCP SDK,
which uv installs on first run from the inline script metadata — nothing else to set up.
server.py --http serves the same tools over Streamable HTTP on 127.0.0.1:8000/mcp for
clients that can't spawn a local process; see the ChatGPT guide.
License
MIT