Metadata-Version: 2.4
Name: kicad-buddy
Version: 0.1.0
Summary: MCP server exposing KiCad's PCB, schematic, export and library tooling to AI assistants
Author-email: Max Burger <mburger89@me.com>
License-Expression: MIT
Project-URL: Homepage, https://github.com/mburger89/KiCAD-Buddy
Project-URL: Repository, https://github.com/mburger89/KiCAD-Buddy
Project-URL: Issues, https://github.com/mburger89/KiCAD-Buddy/issues
Keywords: kicad,mcp,eda,pcb,schematic,electronics,model-context-protocol
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Manufacturing
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)
Classifier: Topic :: Software Development :: Embedded Systems
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: mcp>=1.2
Requires-Dist: kicad-python>=0.7.0
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == "dev"
Dynamic: license-file

# KiCad Buddy

An MCP server plus a companion in-KiCad plugin that put as much of KiCad as
possible in reach of an AI assistant: PCB layout, schematics, every export
format, libraries — and an escape hatch to fire any KiCad command by name.

**62 tools.** Built for KiCad 9 and 10.

---

## Why it's built this way

KiCad exposes itself through three different doors, and no single one covers
the whole application. This bridge uses all three and picks the right one per task.

| Door | What it reaches | Needs KiCad running? |
|---|---|---|
| **IPC API** (protobuf/nng, via `kicad-python`) | Live board editing: footprints, tracks, vias, zones, nets, selection, commits/undo | Yes |
| **`kicad-cli`** (headless) | DRC, ERC, gerbers, drill, pick-and-place, BOM, netlist, STEP/GLB, PDF/SVG/DXF, IPC-2581, ODB++, renders, jobsets | No |
| **Direct file access** (S-expressions) | Schematic editing, symbol/footprint libraries, library tables | No |

And the escape hatch: KiCad names every menu item, tool and command internally as
a `TOOL_ACTION`, and the IPC API can fire any of them by name. The bridge ships a
catalogue of **850 actions for KiCad 10** (and 775 for KiCad 9) extracted from
KiCad's own source, each with its real menu label and tooltip — so you search in
plain language and get the exact name:

```
kicad_list_actions("fill all zones")
  → pcbnew.ZoneFiller.zoneFillAll   "Fill All Zones"

kicad_list_actions("differential pair", app="pcbnew")
  → pcbnew.InteractiveRouter.DiffPair   "Route Differential Pair"
  → pcbnew.LengthTuner.TuneDiffPairSkew "Tune Skew of a Differential Pair"
```

Guess a name wrong and `kicad_run_action` returns `RAS_INVALID` **with close
matches**, rather than failing silently. The catalogue is version-aware: 122
actions were added and 47 removed between 9.0 and 10.0, which is exactly why
hand-written guesses don't hold. It's also topped up from your machine's hotkey
configuration, so anything specific to your build is covered too.

**The one honest gap:** KiCad 10's IPC API ships schematic *types* but no schematic
*commands* — there is no live schematic editing endpoint yet. So schematic tools
edit `.kicad_sch` files directly. They write a `.bak` first and warn you when the
file is open in the editor. Follow them with `kicad_refresh_editor` so KiCad reloads
rather than overwriting your change.

---

## Install

Needs **Python 3.10+** and **KiCad 9 or 10**.

`pipx` is the least painful route, because it handles the virtualenv for you and
still puts `kicad-buddy` on your `PATH` where your MCP client can find it:

```bash
pipx install git+https://github.com/mburger89/KiCAD-Buddy
```

<details>
<summary>Or with a plain virtualenv</summary>

```bash
python3 -m venv ~/.venvs/kicad-buddy
~/.venvs/kicad-buddy/bin/pip install git+https://github.com/mburger89/KiCAD-Buddy
# then point your MCP client at ~/.venvs/kicad-buddy/bin/kicad-buddy
```

A bare `pip install` into your system Python will usually fail with
`error: externally-managed-environment` — that is [PEP 668][pep668] and it is
Homebrew's and Debian's default. Use pipx or a venv rather than
`--break-system-packages`.

[pep668]: https://peps.python.org/pep-0668/
</details>

Then:

```bash
# install the companion plugin into KiCad's plugin folder
kicad-buddy --install-plugin

# sanity check: finds kicad-cli, connects to KiCad, loads the action catalogue
kicad-buddy --check
```

Finally, in KiCad: **Preferences → Plugins → Enable KiCad API server** (off by
default — nothing live works without it), then restart KiCad.

`--check` should report `"ipc_connected": true`. If it doesn't, KiCad either
isn't running or the API server is still off.

### Wire it to your MCP client

```json
{
  "mcpServers": {
    "kicad": {
      "command": "kicad-buddy",
      "env": {
        "KICAD_CLI": "/Applications/KiCad/KiCad.app/Contents/MacOS/kicad-cli"
      }
    }
  }
}
```

`KICAD_CLI` is only needed if `kicad-cli` isn't on your `PATH` — the bridge looks
in the usual install locations on macOS, Windows and Linux first.

### The toolbar button

The companion plugin adds a **KiCad Buddy** button to the PCB editor toolbar.
Click it with a board open and it records which project you're working on, so you
never have to paste a path. It's installed in two forms — a modern IPC API plugin
(`plugin.json`, validated against KiCad's official manifest schema) and a classic
SWIG action plugin — and whichever one your KiCad accepts writes the same
handshake file.

Verified end to end on **KiCad 10.0.5 / macOS**: the button appears in the PCB
editor's top toolbar and clicking it registers the open project. KiCad builds the
plugin its own virtualenv from `requirements.txt` and runs it under its bundled
Python, so nothing extra is needed from you. The SWIG fallback and the earlier
KiCad versions it exists for have not been re-tested recently.

If the button doesn't appear, look at **Preferences → Plugins** — a rejected
manifest is reported there and nowhere else. Note that panel *appends* to a log,
so restart KiCad before trusting what it says.

You can skip the plugin entirely: `kicad_set_active_project("/path/to/project")`
or the `KICAD_BUDDY_PROJECT` environment variable do the same job.

---

## What it can do

### Session & escape hatch (8)
`kicad_status` · `kicad_set_active_project` · `kicad_list_actions` ·
`kicad_run_action` · `kicad_run_actions` · `kicad_refresh_editor` ·
`kicad_reconnect` · `kicad_install_plugin`

### PCB layout (25)
Inspect: `pcb_summary` · `pcb_list_footprints` · `pcb_get_footprint` ·
`pcb_list_nets` · `pcb_net_report` · `pcb_list_tracks` · `pcb_list_zones` ·
`pcb_stackup` · `pcb_layers` · `pcb_get_selection` · `pcb_export_as_text`

Edit: `pcb_place_footprints` · `pcb_add_tracks` · `pcb_add_vias` · `pcb_add_text` ·
`pcb_add_graphics` · `pcb_align_footprints` · `pcb_delete_items` ·
`pcb_paste_kicad_text` · `pcb_refill_zones` · `pcb_select` ·
`pcb_set_active_layer` · `pcb_set_title_block` · `pcb_save` · `pcb_revert`

Every edit runs inside a KiCad commit, so it lands as one undoable step.

### Schematic (12)
`sch_summary` · `sch_list_symbols` · `sch_get_symbol` · `sch_set_properties` ·
`sch_add_symbol` · `sch_add_wires` · `sch_add_labels` · `sch_add_junctions` ·
`sch_delete_item` · `sch_run_erc` · `sch_netlist` · `sch_bom`

`sch_summary` walks the full sheet hierarchy and flags what's wrong: parts with no
footprint, unannotated references, DNP parts. `sch_add_symbol` copies the symbol's
definition out of its library into the schematic's cache, so the part renders
properly instead of showing up as a broken box.

### Validation & manufacturing (7)
`pcb_run_drc` · `pcb_export` · `sch_export` · `pcb_render` ·
`pcb_fabrication_package` · `kicad_run_jobset` · `kicad_list_export_formats`

DRC and ERC come back **parsed** — counts by severity and readable violations, not
a path to a file. `pcb_fabrication_package` builds gerbers, drill, pick-and-place,
BOM and a PDF into one zip, and refuses to build if DRC finds errors unless you
explicitly override it.

### Libraries (10)
`lib_list_tables` · `lib_search_symbols` · `lib_search_footprints` ·
`lib_get_symbol` · `lib_list_symbols` · `lib_add_table_entry` ·
`lib_create_symbol_library` · `lib_copy_symbol` · `fp_export_svg` · `lib_upgrade`

`lib_list_tables` resolves `${KIPRJMOD}` and friends and tells you which libraries
point at paths that don't exist — the usual cause of missing parts.

---

## Things worth knowing

**Units.** Everything user-facing is millimetres and degrees. KiCad's internal
nanometres never surface.

**Schematic grid.** Schematic coordinates are millimetres on a 1.27 mm grid. Place
symbols and wire endpoints on that grid or KiCad won't consider them connected.

**`pcb_add_tracks` is not an autorouter.** It draws exactly the segments you give
it and checks nothing. Run `pcb_run_drc` afterwards. For real routing, arm KiCad's
own router with `kicad_run_action("pcbnew.InteractiveRouter.SingleTrack")` and
drive it by hand — or use FreeRouting via a DSN export.

**Action names are unstable.** KiCad explicitly does not guarantee them across
versions, which is why the catalogue is per-branch and why the bridge reads your
hotkey config as well. `kicad_run_action` reports `RAS_OK`, `RAS_INVALID` (no such
action, with suggestions) or `RAS_FRAME_NOT_OPEN` (wrong editor open). Some actions
open modal dialogs that wait for a human; some arm an interactive tool rather than
completing immediately.

**Backups.** Every file-level edit writes a `.bak` next to the file it changes.
There is no undo for file edits the way there is for IPC edits.

---

## Development

```bash
python3 -m venv .venv
.venv/bin/pip install -e ".[dev]"
.venv/bin/python -m pytest tests/ -q     # 27 tests, no KiCad needed
```

The test suite covers the S-expression codec, schematic editing, library-table
resolution, project discovery and the action catalogue — the parts that have to be
correct on their own.
Anything touching the live IPC API needs a running KiCad and is exercised by
`kicad_status`.

### Layout

```
src/kicad_buddy/
  config.py     kicad-cli discovery, config dirs, session handshake
  ipc.py        live IPC connection, units, item serialisation
  kcli.py       kicad-cli wrapper
  sexpr.py      S-expression reader/writer
  schdoc.py     .kicad_sch document model
  libs.py       library tables and symbol lookup
  actions.py    TOOL_ACTION catalogue, search and dispatch
  data/         per-version action catalogues extracted from KiCad source
  tools/        the 62 MCP tools
  plugin/       the in-KiCad companion plugin (IPC + SWIG)
```

### Regenerating the action catalogue

The catalogues in `src/kicad_buddy/data/` are extracted from the `TOOL_ACTION`
definitions in KiCad's source (`common/tool/actions.cpp`,
`pcbnew/tools/pcb_actions.cpp`, `eeschema/tools/sch_actions.cpp` and the
gerbview / pl_editor / 3d-viewer equivalents). Rebuild them for a new KiCad
release by re-running that extraction against the matching release branch.

### Releasing

Publishing to PyPI runs on Trusted Publishing from `.github/workflows/publish.yml`.
See [RELEASING.md](RELEASING.md) for the one-time PyPI setup and how to cut a
release.

## Licence

MIT.
