Connecting an AI Assistant¶
OpenZEV can answer questions about your own data through an AI assistant — Claude Code, Claude Desktop, Cursor, n8n, or any other client that speaks the Model Context Protocol (MCP). Instead of clicking through the readiness cockpit, invoice detail, import logs and audit log yourself, you ask in plain language: "Is Q2 ready to bill for ZEV Sonnenhof?", "Why is this invoice higher than last quarter?", "What went wrong in yesterday's import?"
The assistant sees exactly what your account can see in the API — nothing more — and every question it asks OpenZEV is recorded in the audit log.
Privacy note¶
Enabling this feature lets the signed-in user send OpenZEV data — participant names, consumption figures, invoice amounts, audit history — to whichever LLM provider the assistant uses, which is very likely a third party outside Switzerland. Only enable it if that is acceptable for your community, and only give a key to an assistant you trust with that data.
The MCP endpoint is read-only in this release: no tool can create, change, approve, send or delete anything.
Enabling it¶
An administrator must turn the feature on first — it is off by default:
- Open Platform → Settings → Functions.
- Enable
mcp_server_enabled.
While the flag is off, the MCP endpoint does not exist as far as any caller
can tell (404, whether or not they are signed in).
Creating a key for the assistant¶
The assistant authenticates the same way a script does — see API Keys for the full picture. For an assistant:
- Open Account → Tokens & keys.
- Choose New API key.
- Give it a name that says what it's for —
claude-code-mcpbeatskey 3. - Tick Read-only key. Every tool in this release only reads, so a read-only key loses nothing and keeps the credential's blast radius small if it ever leaks.
- Choose Create key and copy the value shown — it is not shown again.
Only admins and accounts that manage or view a community can use the MCP
endpoint. A participant's key is refused with 403.
Connecting a client¶
The endpoint is https://<your-openzev-host>/api/v1/mcp/, speaking MCP's
Streamable HTTP transport. Send the key as a bearer token.
Claude Code¶
claude mcp add --transport http openzev \
https://your-openzev.example.com/api/v1/mcp/ \
--header "Authorization: Bearer ozv_3f9a1c04b7e2_kR8vN2pQ..."
Generic MCP client configuration¶
Most desktop clients (Claude Desktop via a local HTTP-to-stdio bridge, Cursor, …) take a JSON block naming the server:
{
"mcpServers": {
"openzev": {
"url": "https://your-openzev.example.com/api/v1/mcp/",
"headers": {
"Authorization": "Bearer ozv_3f9a1c04b7e2_kR8vN2pQ..."
}
}
}
}
n8n¶
Add an MCP Client node, set its Endpoint to
https://your-openzev.example.com/api/v1/mcp/, and set Authentication to
a header credential: Authorization: Bearer ozv_3f9a1c04b7e2_kR8vN2pQ....
What you can ask¶
Once connected, the assistant has eleven tools. You do not need to know their names — asking a normal question is enough — but knowing what exists helps you phrase a better question:
| Tool | Answers |
|---|---|
list_zevs |
Which ZEVs can I see? (call this first to get a ZEV's id) |
list_participants |
Who is in this ZEV, since when, and which metering points are they assigned to? (names and dates only — no email, phone, address or IBAN) |
period_readiness |
Can this billing period be invoiced, and what is blocking it? |
find_invoices |
Which invoices match this participant / period / status? |
explain_invoice |
Break one invoice down into its line items, and compare it with the participant's previous invoice |
import_triage |
What happened in recent metering imports, and what went wrong? |
consumption_summary |
Consumption, production and self-consumption over a date range, by month, day or hour (hour for up to a week); for the whole ZEV it also shows each participant's consumption and how much of it came from the ZEV |
consumption_profile |
A participant's average day: how much they use in each hour, and how much of it comes from the ZEV's own solar |
data_gaps |
Which metering points are missing readings, and where? |
live_energy |
What the ZEV produces and uses right now, how much is spare, which metering points report, and when production is expected to peak (only when live energy data is switched on; indicative, never billing) |
audit_query |
Who did what, and when? |
Example questions:
- "List the ZEVs I have access to."
- "Is the current period ready to bill for ZEV Sonnenhof?"
- "Who are the current participants of ZEV Sonnenhof, and which meters do they have?"
- "Find Anna Muster's invoices from this year."
- "Explain invoice OZV-00013 — why did it go up from last quarter?"
- "What errors came up in yesterday's metering import?"
- "How much energy did ZEV Sonnenhof self-consume in August, by day?"
- "Which participants used the most electricity last quarter, and how much of it was solar?"
- "When in the day does Anna Muster use the most electricity, and how much of that is covered by solar?"
- "Which metering points have gaps in the last 30 days?"
- "How much is ZEV Sonnenhof producing right now, and is anything spare?"
- "When is production expected to peak tomorrow?"
- "Who approved invoices for ZEV Sonnenhof last week?"
Limits¶
- Read-only. No tool changes anything. A future release may add write tools (approving or sending invoices) with an explicit confirmation step.
- No raw meter data. Consumption is aggregated into monthly, daily or (for up to a week) hourly buckets; the underlying 15-minute readings are not exposed through MCP.
- Scoped to your account. An assistant connected with a manager's key sees only that manager's ZEVs — the same tenant isolation that protects the REST API protects MCP, because MCP tools call the same REST endpoints internally.
- Bearer-token clients only, for now. The endpoint accepts a static API key, not an OAuth login. Connectors that only support OAuth (such as claude.ai's custom connectors) cannot connect yet.
- Lists are capped. A question that would return hundreds of rows comes back truncated with a note saying so — narrow the question (a shorter date range, a specific participant) rather than asking for everything at once.
Revoking access¶
Revoke the key the same way you would revoke any other API key: Account → API keys → Revoke. It takes effect on the assistant's next request. See Revoking a key for the full picture, including how an administrator can revoke it on your behalf.
Audit trail¶
Every tool call the assistant makes is recorded in the audit log as an
mcp.tool.call event, naming the tool, the arguments, the key that was used
(by its prefix), and the ZEV it concerned (when the question named one you can
see). The event is named Abfrage durch KI-Assistent (AI assistant query) and its details show the source KI-Assistent (mcp). To see exactly what an assistant
looked at, open the platform audit log's Technical filters and enter the action code mcp.tool.call — or ask the
assistant itself, since audit_query can answer that question too.
Troubleshooting¶
| Symptom | Cause |
|---|---|
404 on the endpoint |
mcp_server_enabled is off — ask an administrator to enable it. The endpoint answers 404 to everyone while the flag is off, so this is the first thing to check. |
401 |
Missing, wrong, revoked or expired key. Same causes as any other API key — see API Keys → Troubleshooting. |
403 |
Your key's account manages or views no community (for example, it is only a participant), or its access was removed. Only admins, managers and viewers can use MCP. |
| The assistant says a tool failed with "Permission denied" or "not found" | You (or the assistant) named a ZEV or invoice your account cannot see. This is the same scoping the REST API enforces — it is not a bug. |
| Answers feel stale | Ask the assistant to call the tool again — MCP calls always read live data, there is no caching layer of its own. |