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:
pipx install git+https://github.com/mburger89/KiCAD-Buddy
Or with a plain virtualenv
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 and it is
Homebrew's and Debian's default. Use pipx or a venv rather than
--break-system-packages.
Then:
# 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
{
"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
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 for the one-time PyPI setup and how to cut a
release.
Licence
MIT.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file kicad_buddy-0.1.0.tar.gz.
File metadata
- Download URL: kicad_buddy-0.1.0.tar.gz
- Upload date:
- Size: 104.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
59fa3ef221b00d692019cae5480f26f78037f3f6e18bfb4af05940c8dec44345
|
|
| MD5 |
2befe94d13c705a3c4648f92423a8046
|
|
| BLAKE2b-256 |
c2cbb0c1f1a04c16f4eb9aba03461986273a9334c664bc838ea81c6564676a88
|
Provenance
The following attestation bundles were made for kicad_buddy-0.1.0.tar.gz:
Publisher:
publish.yml on mburger89/KiCAD-Buddy
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
kicad_buddy-0.1.0.tar.gz -
Subject digest:
59fa3ef221b00d692019cae5480f26f78037f3f6e18bfb4af05940c8dec44345 - Sigstore transparency entry: 2472830480
- Sigstore integration time:
-
Permalink:
mburger89/KiCAD-Buddy@8fad674b8db8600c83a57da7e9144df337674256 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/mburger89
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@8fad674b8db8600c83a57da7e9144df337674256 -
Trigger Event:
release
-
Statement type:
File details
Details for the file kicad_buddy-0.1.0-py3-none-any.whl.
File metadata
- Download URL: kicad_buddy-0.1.0-py3-none-any.whl
- Upload date:
- Size: 103.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
46778d24750e2be9664ddd770459035569b9f2003d48557e4f09db269efe01a7
|
|
| MD5 |
2fa2ecb854ebce8520de345988c2c66b
|
|
| BLAKE2b-256 |
87f0e31d5abcac10c8a4f267cfb71ef875053891dc04d5b19690748f3db1bf66
|
Provenance
The following attestation bundles were made for kicad_buddy-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on mburger89/KiCAD-Buddy
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
kicad_buddy-0.1.0-py3-none-any.whl -
Subject digest:
46778d24750e2be9664ddd770459035569b9f2003d48557e4f09db269efe01a7 - Sigstore transparency entry: 2472830523
- Sigstore integration time:
-
Permalink:
mburger89/KiCAD-Buddy@8fad674b8db8600c83a57da7e9144df337674256 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/mburger89
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@8fad674b8db8600c83a57da7e9144df337674256 -
Trigger Event:
release
-
Statement type: