Metadata-Version: 2.5
Name: openinverter-mcp
Version: 0.1.0
Summary: MCP server for openinverter / EV-CAN work: parameter DB inspection, CAN frame decode, DBC operations, and recorded-log analysis
Author: Jesse Sapirstein
License: MIT
License-File: LICENSE
Keywords: can,canbus,dbc,ev,mcp,openinverter
Classifier: Development Status :: 3 - Alpha
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Scientific/Engineering
Requires-Python: >=3.10
Requires-Dist: cantools<45,>=44.0.0
Requires-Dist: mcp<3,>=2.2.0
Requires-Dist: openinverter-can-tool<0.6,>=0.5.1
Requires-Dist: python-can<5,>=4.6.1
Provides-Extra: dev
Requires-Dist: pytest>=8; extra == 'dev'
Description-Content-Type: text/markdown

# openinverter-mcp

MCP server for [openinverter](https://openinverter.org/) / EV-CAN work: inspect openinverter
parameter databases, decode and encode CAN frames via DBC files, and analyze recorded CAN
logs — from Claude Code, Claude Desktop, or any MCP client.

Built for DIY EV builders (Leaf/Tesla drive units, stm32-sine firmware). **No CAN hardware
required**: the DBC, log, and param-DB lanes are fully usable standalone on files. Live
device access exists but is deliberately locked behind a feature flag (see Safety).

## Install

Requires Python 3.10+.

```sh
pip install openinverter-mcp        # once published; from a clone:
git clone <this repo> && cd openinverter-mcp
uv sync                             # or: pip install -e .
```

## Register with Claude Code

From a clone (project-scoped `.mcp.json` in this repo already does this):

```sh
claude mcp add openinverter -- uv run --directory C:/path/to/openinverter-mcp openinverter-mcp
```

Once on PyPI, no clone needed:

```sh
claude mcp add openinverter -- uvx openinverter-mcp
```

Then in a session: "load assets/sample.dbc and decode 0x156 701C2D2ED40D4A00".

## Tools

Handles (`dbc:1`, `log:1`, `paramdb:1`) are returned by the load tools; every tool that
takes a handle also accepts a file path directly.

| Tool | What it does |
|---|---|
| `server_info` | Version, device-lane status, loaded handles. Smoke test. |
| `dbc_load` | Load a DBC file → handle + message/node summary. |
| `dbc_info` | List messages (with `search` over message/signal names) or full signal detail for one message. |
| `decode_frame` | One raw frame (id + hex data) → named signal values. |
| `encode_message` | Signal values → frame bytes (hex + candump form), range-checked. |
| `log_open` | Open a recorded log: candump `.log`, Vector `.blf`, python-can `.csv`, `.asc`, `.trc`. |
| `log_stats` | Bus overview: per-id counts, rates (Hz), time span, DLC profile. |
| `log_decode` | Decode a log through a DBC; id filter + pagination; unknown ids summarized. |
| `param_db_load` | Load an openinverter param DB (oic-format JSON, NUL-tolerant). |
| `param_list` | Parameters/spot values: id, unit, range, default, enum/bitfield labels; filter by category/search. |
| `param_read` | Parameter definition from file; live value only with a connected `device=`. |
| `param_write` | Write to a LIVE inverter — refuses without `device` + `confirm:true` (see Safety). |
| `device_scan` / `device_connect` | Live bus access — feature-flagged. |

SavvyCAN users: export captures as candump (`.log`) for `log_open`.

## Safety model

Writing parameters can command a physical inverter, so `param_write` is safe **by
construction** — three independent latches:

1. The server must be started with `OPENINVERTER_MCP_ENABLE_DEVICE=1` before any
   physical CAN interface can be opened at all (the `virtual` interface is always allowed).
2. `param_write` requires an explicit `device` handle from `device_connect`.
3. `param_write` requires `confirm: true`, and its refusal text instructs the model to
   obtain the human's explicit confirmation of the exact write first.

Everything is validated (writability, range, enum/bitfield labels) before any bus traffic.
Firmware `save`/`reset`/`start`/`stop` commands are not exposed at all. Values written go
to RAM only.

## Bundled sample assets

`assets/` ships a synthetic, MIT-licensed trio (regenerate with `python assets/generate.py`):
`sample.dbc` (EV-style messages), `sample-candump.log` (10 s synthetic drive, 405 frames),
`sample-paramdb.json` (openinverter param DB with real stm32-sine parameter facts).
See `ATTRIBUTION.md` for licensing of dependencies and asset provenance.

## Development

```sh
uv sync --extra dev
uv run pytest          # 33 tests incl. a real stdio MCP end-to-end drive
```

Design: `specs/DESIGN.md`. Research notes: `specs/api-research.md`. License: MIT.
