deadbringer17/Copperbrain

Model Context Protocol server exposing schematic capture, netlist generation, BOM validation, and PCB toolchain integration to LLM agents.

4

stars

56

commits

Python

primary language

Sep 3, 2026

updated

README

Copperbrain

Copperbrain is a local MCP server for safe KiCad 10 schematic/PCB analysis, deterministic JLCPCB/LCSC sourcing, controlled changes, ERC/DRC validation, typed PCB design rules, and component-only BOM estimates.

See this README for scope and public contracts, docs/INSTALLATION.md for setup, and docs/DEMO.md for the reproducible reference flow.

Installation

Requires Windows, Python 3.11 or newer, uv, and KiCad 10.x (kicad-cli.exe is discovered dynamically). Controlled PCB routing uses a managed KiCadRoutingTools runtime with its platform-specific Rust core; JLCImport and JLCPCB Tools are optional and enable local component sourcing.

git clone https://github.com/deadbringer17/Copperbrain.git
cd Copperbrain
uv sync --all-extras
uv run python scripts/setup_dependencies.py --skip-jlc-plugins
uv run pytest

Start the server with uv run copperbrain. Configure an MCP client to execute uv with arguments run copperbrain and this repository as its working directory. Copperbrain exposes local stdio only and never starts a public network listener. See docs/INSTALLATION.md for the full environment-variable reference and mutation-safety details.

To update a source checkout explicitly from the official origin/main, run:

uv run copperbrain update

The updater accepts only a clean main worktree with the official Copperbrain GitHub origin and applies a Git fast-forward only. It refuses dirty worktrees, detached or different branches, unexpected remotes, and divergent history; it never stashes, resets, rebases, or discards local work. Restart Codex or open a new task after a successful update.

To fetch the pinned, hash-verified KiCadRoutingTools runtime and optional JLCImport/JLCPCB Tools integrations automatically instead of installing them by hand, run:

uv run python scripts/setup_dependencies.py

The script only ever contacts official sources over HTTPS (GitHub, Adoptium, kicad.github.io), verifies a checksum whenever the source publishes one, and asks for confirmation before writing anything — including the JLC plugins, which land in KiCad's own plugin directory, outside this repository. See "Automated dependency setup" in docs/INSTALLATION.md for exactly what it does and does not do.

Installing in Codex CLI

Complete the installation above first. Codex (the codex CLI) reads MCP server definitions from its config.toml~/.codex/config.toml on Linux/macOS, %USERPROFILE%\.codex\config.toml on Windows. Add a [mcp_servers.copperbrain] entry:

[mcp_servers.copperbrain]
command = "uv"
args = ["run", "--directory", "C:\\path\\to\\Copperbrain", "copperbrain"]
enabled = true

Codex launches command directly, without a shell and without setting a working directory of its own, so uv run needs --directory <repo> instead of relying on cd; use the absolute path to where you cloned this repository. To override an environment variable from docs/INSTALLATION.md#configuration for this server only, add it under [mcp_servers.copperbrain.env], the same way other entries in config.toml do. Restart Codex (or start a new session) after editing the file. Copperbrain still exposes local stdio only; registering it this way adds no network exposure.

Development

uv sync --all-extras
uv run pytest
uv run ruff check .
uv run ruff format --check .
uv run mypy src

Run the stdio MCP server with uv run copperbrain.

Run the non-destructive offline demo with uv run python scripts/run_demo.py.

MCP client contract

Every tool publishes a complete JSON Schema for its arguments. Structured requests such as request, rule_set, spec, requirements, and operations expose the underlying Pydantic model — its fields, enumerations, bounds, and defaults — instead of a free-form object, so a client can construct them without guessing. Fixed vocabularies (change_kind, phase, output_format, layer and strategy choices) are enumerations, and quantities and limits carry their real bounds. Schematic operations publish one schema variant per kind; each variant lists the required and accepted fields inside parameters, including their scalar types. Boundary validation failures are returned as stable invalid_input errors with field locations and corrective hints; Copperbrain does not expose Pydantic versions or documentation URLs to MCP callers.

Each tool also publishes a human-readable title and behavior hints: readOnlyHint for the analysis and proposal tools, destructiveHint for the three acceptances and rollback_accepted_phase, idempotentHint, and openWorldHint for tools that reach the JLCPCB/LCSC catalog or download assets. The server advertises the gated workflow in its initialize instructions.

Refusals keep their structure end to end: the stable error code, message, actionable hint, and details all reach the client, so failures never have to be recovered from log text.

Handlers are dispatched onto a worker thread and serialized through a single token, so shared sessions and change-set workspaces are touched by one operation at a time. The stdio loop keeps answering pings for the whole run. Note that a long KiCad CLI run, routing candidate, or catalog download cannot be interrupted once started: the worker thread runs to completion, holds the token, and a cancellation is only observed after it finishes. Size routing batches accordingly — COPPERBRAIN_ROUTING_TIMEOUT_SECONDS (default 900) bounds a single run. get_project_creation_status is the one tool that bypasses the token, so an in-flight project creation stays observable.

Three acceptance gates

The public MCP exposes exactly three tools that accept a validated mutation:

  1. accept_schematic for the project scaffold or schematic change set.
  2. accept_design_rules for reviewed widths, clearances, vias, netclasses, and assignments.
  3. accept_pcb for one aggregate change set composed from optional layout, placement, grounding, and routing stages, prepared with prepare_pcb_acceptance and rechecked with validate_pcb_acceptance.

Granular PCB prepare/preview/validate/apply/rollback functions are internal and are not MCP tools. They modify only the private aggregate workspace. rollback_accepted_phase is an explicit recovery command, not another acceptance gate.

To start a new design safely, call prepare_project_creation with an existing parent directory and a typed name/layer count plus a caller-selected request_id. Copperbrain persists that idempotency key before long-running work: retrying it with the same inputs resolves to the same change set, while get_project_creation_status remains callable during the operation and reports in_progress, completed, or failed after an ambiguous client timeout. Copperbrain creates the schematic through kicad-sch-api, creates the empty board through KiCad's bundled Python API, validates both files, and publishes only a preview under <new-project>/copperbrain-output/previews/schematic/. accept_schematic applies the validated scaffold; recovery remains hash guarded.

For an opened KiCad project, Copperbrain writes every deliverable artifact below <project>/copperbrain-output/: at most the stable schematic, design-rules, and pcb previews under previews/, plus BOM exports under bom/. Private mutation workspaces, caches, and rollback snapshots are not placed in the project.

Project analysis via MCP

Call detect_kicad to confirm KiCad, CLI, and JLC plugin availability, then open_project to open a project read-only and hash its sources. get_project_summary returns sheets, components, electrical nets, and power symbols; analyze_schematic returns deterministic, evidence-backed observations; trace_net returns every pin KiCad assigns to one exact net name. run_erc and run_drc run KiCad's checks and normalize violations without touching project files. Opened sessions are persisted in Copperbrain's private data directory and can be recovered after an MCP restart; reopening the project remains necessary if the persisted record is unavailable or the source project has changed.

Schematic changes via MCP

prepare_schematic_change stages allowlisted operations in a private workspace and returns a compact summary, risks, counts, and a project-local PDF preview; validate_change revalidates it in place. Summary mode is the default for prepare, validate, and acceptance and never echoes the input operation batch. Pass verbosity="full" only for deliberately small changes, or use get_schematic_change_details to page through operations, semantic differences, validation messages, or ERC violations in bounded groups of at most 20; exceptionally long scalar fields are marked and truncated in the page response. Applying requires the first acceptance gate, accept_schematic, with confirmed=true and editor_closed=true.

rollback_accepted_phase requires the exact change_set_id returned by the accepted phase. Its lock refusal identifies the detected project lock file and tells the caller which KiCad editor to close; editor_closed=true is an attestation, never a bypass. A successful rollback of an existing project returns a fresh session_id because the previous session's source hashes are obsolete.

Before saving a prepared schematic, Copperbrain registers project symbol libraries and preserves connectivity-bearing constructs that the pinned kicad-sch-api cannot round-trip, including global and hierarchical labels and unresolved embedded symbol definitions. The change is refused if a guarded wire, junction, bus, or label would still be lost.

Readability reports distinguish wired, mixed, label_based, and empty schematics. In label_based mode, direct pin labels and the absence of wire endpoints are intentional and do not reduce the score or produce a false readability failure; collision and duplicate-position checks remain active. empty reports readability as not applicable.

Component sourcing via MCP

search_components ranks JLCPCB/LCSC candidates against typed requirements using the installed JLCPCB Tools catalog or a recorded COPPERBRAIN_JLC_CATALOG. get_component_details returns normalized catalog details for one exact LCSC part; compare_components and find_alternatives rank supplied or discovered candidates against the same requirements. estimate_component_cost estimates component-only cost at one requested quantity. import_component_assets installs the resolved symbol/footprint/3D/datasheet assets locally from allowlisted HTTPS sources. For parts without a library symbol, generate_symbol_from_pinout creates a deterministic, parser-validated .kicad_sym scaffold in Copperbrain's private data directory from typed pin numbers, names, electrical types, sides, and standard properties. It accepts no S-expression and does not mutate the project. Review the result and pass it with the matching footprint to import_component_assets, which still enforces exact pin-to-pad number correspondence.

BOM via MCP

generate_bom groups and enriches the schematic BOM and writes JSON/CSV/Markdown under copperbrain-output/bom/. estimate_bom_cost returns component-only estimates at the requested board quantities; suggest_bom_substitutions proposes requirement-motivated alternatives for the first limit sourced BOM lines and reports sourced_line_count, examined_line_count, and truncated so a large BOM cannot turn into an unbounded run of catalog searches. All cost figures explicitly exclude PCB, assembly, stencil, shipping, taxes, and duties.

All three report catalog_failures: an LCSC identifier the catalog refused is named with its structured reason instead of silently producing an unpriced line, and one refused line no longer aborts a whole substitution report.

PCB design rules via MCP

Use analyze_pcb_constraints to inspect current netclasses and receive evidence-backed net-role suggestions. Pass reviewed fabrication limits and electrical intent to propose_design_rules, then use prepare_pcb_rule_change, validate_pcb_rule_change, and accept_design_rules. Applying requires the second acceptance and a saved, closed KiCad editor; rollback_accepted_phase restores the phase snapshot when explicitly invoked.

ManufacturingProfile covers minimum clearance/track/via dimensions, copper thickness, allowed temperature rise, and internal/external current layer. NetRuleRequirement covers exact net names, role, current, voltage, explicit clearance/width, creepage, maximum routed length, and optional differential geometry/maximum uncoupled length. Raw .kicad_dru text is never accepted through MCP.

High-current rules require a current or reviewed width. High-voltage rules require reviewed clearance. Differential geometry is explicitly marked as not impedance-controlled unless width and gap are supplied from a verified stackup calculation.

Before proposing routing rules, Copperbrain resolves every connected footprint and measures its electrical pads, minimum pitch, and edge-to-edge pad clearance. If a class width or clearance does not fit the package, the generated .kicad_dru applies a narrower track width or reduced clearance only inside that component's courtyard, never below the fabrication profile minimum. The original class remains active outside the package. Missing project-local courtyards can be generated inside the same previewed change set and are validated through KiCad CLI; unresolved footprints or packages narrower than the fabrication minimum produce a safe refusal.

PCB inspection and placement via MCP

Use get_pcb_summary, inspect_pcb_net, and get_footprint_placement for typed board queries. analyze_placement reports conservative courtyard overlaps, footprints outside Edge.Cuts, estimated ratsnest length, occupied envelope, compactness, side counts, and cross-layer nets. propose_component_placement accepts exact references, a typed optional region, spacing/grid and routing-corridor limits, plus deterministic compact or grid, rotation, and layer policies. Compact placement scores pad connectivity and envelope growth, keeps connectors near edges, and allows automatic bottom placement only for small SMD passives.

Pass the returned operations directly to prepare_pcb_acceptance. Placement is applied and validated inside its private aggregate workspace without an intermediate PDF or published copy; no separate placement preview or acceptance is exposed.

The official kicad-python IPC binding is installed and detected dynamically for live board transactions. PCB inspection and safe preview do not require a running editor: the typed file adapter and kicad-cli remain the deterministic offline path. No MCP placement tool accepts raw KiCad S-expressions, and this extension does not route traces or modify zones, keepouts, or the board outline. Un cambio F.Cu/B.Cu viene eseguito soltanto nella copia temporanea attraverso l'API pcbnew inclusa in KiCad, cosi pad, grafica, testi e modelli 3D vengono trasformati insieme. Preview, DRC, conferma esplicita, snapshot e rollback restano obbligatori.

Post-placement PCB grounding

Include the reviewed grounding request in prepare_pcb_acceptance. It targets every pad in one or more reviewed ground domains and derives all zone outlines from the real closed Edge.Cuts, pad geometry, fanouts, and vias. The default is always a two-copper-layer board: PGND owns the main shaped region on F.Cu, while GND owns the main shaped region on B.Cu. Planner-derived local regions on the opposite side are cut out of the main region with explicit clearance and distinct priorities. A four-layer stackup is used only when copper_layers=4 is explicitly requested; that opt-in policy uses PGND -> F.Cu/In2.Cu and GND -> In1.Cu/B.Cu for an unambiguous pair.

The domains remain distinct KiCad nets and are connected only through two-terminal bridges such as a 0-ohm resistor or net tie explicitly named in bridge_references. Pads that do not touch their assigned plane receive typed, clearance-screened pad-to-via fanouts. thermal and solid pad connections are selectable per domain; local shaped regions are solid and power ground commonly uses solid. Via-in-pad is opt-in because it requires a reviewed fabrication process. Existing selected-net zones are replaced only when replace_existing_planes=true is explicitly requested.

The result is validated inside the private aggregate workspace without a grounding preview. The KiCad Project Manager may remain open: only a PCB document lock blocks the final aggregate mutation. rollback_accepted_phase restores the aggregate PCB snapshot. Ambiguous domain roles, overlapping layer assignments, missing/ambiguous bridges, unsafe fanouts, or new DRC errors cause a structured refusal. The workflow does not accept polygons or KiCad expressions from callers, and it does not claim thermal, return-path, EMC, SI/PI, stackup, or DFM certification.

Headless PCB initialization via MCP

For an empty board, prepare_pcb_acceptance accepts an optional layout stage: a typed rectangular outline, one placement for every physical schematic footprint, and optional fixed M3 mounting holes. It synchronizes footprints, builds the unrouted PCB, and runs comparative ERC/DRC inside the aggregate workspace. There is no separate layout preview or acceptance — it is covered by the single PCB gate. Footprint substitutions are a schematic change: send them to prepare_schematic_change as update_property operations before preparing the PCB.

The bounded motor-driver reference helpers demonstrate this flow for a provisional 12 V, 20 A brushed-DC H-bridge using DRV8701, four external 60 V MOSFETs, ATtiny1616, half-duplex RS-485, and four protected 5–24 V digital sensor inputs. Its typed plan uses a compact 120 x 100 mm board, four M3 holes, a star-separated PGND/logic GND, and a 70 um external-copper assumption. It is a review benchmark, not a production-qualified design; high-current zones, thermal/EMC/DFM, motor stall behavior, and the final stackup still require engineering validation.

The typed DRV8311S reference helpers describe an 85 x 50 mm four-layer BLDC driver at a provisional 9--12.6 V, 2 A continuous operating point, with 6-PWM, SPI, three current-sense outputs, fault, Hall signals, input protection, decoupling, grounding intent, thermal-pad fanout, and rule classes. The repository intentionally does not bundle generated benchmark projects. The helpers and their deterministic tests are review evidence, not a production release: power/phase copper, thermal/SOA, EMC, DFM, and final routing still require project-specific engineering validation.

Controlled PCB routing via MCP

After rules and placement/grounding intent are reviewed, use analyze_unrouted_nets to identify the remaining disconnected pad groups. Ground-zone connectivity is included, so the router does not redundantly route pads already joined by an applied plane. Check get_routing_backend_status, then call propose_pcb_routing. KiCadRoutingTools runs locally through its Python CLI and Rust-accelerated A* core. Copperbrain can run at most three isolated ordering strategies: mps, inside_out, and original. One candidate is used by default and a request for a fourth is rejected. Copperbrain ranks candidates by completion, new DRC errors, open connections, vias, and routed length. Only the selected candidate's copper delta becomes typed segments and vias; there is no internal routing fallback. Reviewed planes remain on the private input board as copper obstacles, while their nets are excluded from the explicit signal-routing batch. The selected typed copper is applied to the already-grounded private board, followed by KiCad zone refill and comparative DRC. Fine-pitch escape geometry is opt-in per routing batch. When enabled, Copperbrain derives short typed stubs from pad and courtyard geometry and, for a nearby opposite-side target, a clearance- offset dogbone via with an outside-courtyard approach. It includes these seeds in the private router input and subjects the resulting complete copper delta to the same scope, preservation, connectivity, and DRC gates. When nets is empty, Copperbrain materializes the exact currently-unrouted net set before starting the backend. KiCadRoutingTools receives those exact names through its fixed --nets argument; non-target nets, existing routes, planes, keepouts, pads, and the board outline remain obstacles. Copperbrain never enables the backend option that permits ripping pre-existing routes. Every result is rejected if it removes existing copper or adds copper outside the requested net set.

Pass the reviewed routing requests with placement and grounding to prepare_pcb_acceptance. Copperbrain stops after the bounded candidate comparison, applies only the best candidate to the private prepared PCB, refills zones, rechecks connectivity, and runs comparative DRC inside one private workspace without routing previews. It does not keep retrying to obtain a complete route. Final engineering cleanup and the explicit decision to apply the prepared PCB remain with the user. Only the complete aggregate publishes copperbrain-output/previews/pcb/ and can be applied by accept_pcb with the third acceptance and a closed editor. The KiCad Project Manager may remain open; only a PCB-document lock blocks the aggregate apply/rollback. Boards containing pre-existing copper are rejected by default; explicitly select the preserve policy only for intentional incremental routing. Wall-time and output-stall watchdogs stop the complete router process tree. The typed delta is always applied to the original-precision project copy. Each proposal writes versioned baseline and per-candidate JSON metrics below the private COPPERBRAIN_DATA_DIR/metrics/connectivity/ tree. KiCadRoutingTools attempt records retain bounded queued/routed/failure counts, duration, routed copper, watchdog evidence, and resource data when the backend exposes it. Backend output is bounded and sensitive net names are replaced with hashes. The returned RoutingPlan.metrics_run_id correlates those records with preview, apply, and recovery. Call get_connectivity_metrics with that ID for a bounded, sanitized optimization view including the best observed pass, connection delta, failed-candidate count, stagnation, and watchdog causes. New records use schema 5 while the reader remains compatible with persisted schema-2 records.

For the compact end-to-end surface, call prepare_pcb_acceptance, review its preview, then use validate_pcb_acceptance and accept_pcb. assess_pcb_readiness intentionally keeps production_ready=false when DFM, stackup, thermal, SI/PI, EMC, or impedance checks have not been performed, even if routing/ERC/DRC pass.

The AI may explain and review the structured candidate evidence, but it cannot override connectivity, DRC, confirmation, stale-hash, or editor-state gates. This workflow does not certify impedance, SI/PI/EMC, thermal behavior, or regulatory compliance. Raw KiCad expressions, zones, and keepouts remain unavailable through the routing tools.

Contributors

deadbringer17

54 commits

claude

2 commits

deadbringer17/Copperbrain

Model Context Protocol server exposing schematic capture, netlist generation, BOM validation, and PCB toolchain integration to LLM agents.

4

stars

56

commits

Python

primary language

Sep 3, 2026

updated

README

Copperbrain

Copperbrain is a local MCP server for safe KiCad 10 schematic/PCB analysis, deterministic JLCPCB/LCSC sourcing, controlled changes, ERC/DRC validation, typed PCB design rules, and component-only BOM estimates.

See this README for scope and public contracts, docs/INSTALLATION.md for setup, and docs/DEMO.md for the reproducible reference flow.

Installation

Requires Windows, Python 3.11 or newer, uv, and KiCad 10.x (kicad-cli.exe is discovered dynamically). Controlled PCB routing uses a managed KiCadRoutingTools runtime with its platform-specific Rust core; JLCImport and JLCPCB Tools are optional and enable local component sourcing.

git clone https://github.com/deadbringer17/Copperbrain.git
cd Copperbrain
uv sync --all-extras
uv run python scripts/setup_dependencies.py --skip-jlc-plugins
uv run pytest

Start the server with uv run copperbrain. Configure an MCP client to execute uv with arguments run copperbrain and this repository as its working directory. Copperbrain exposes local stdio only and never starts a public network listener. See docs/INSTALLATION.md for the full environment-variable reference and mutation-safety details.

To update a source checkout explicitly from the official origin/main, run:

uv run copperbrain update

The updater accepts only a clean main worktree with the official Copperbrain GitHub origin and applies a Git fast-forward only. It refuses dirty worktrees, detached or different branches, unexpected remotes, and divergent history; it never stashes, resets, rebases, or discards local work. Restart Codex or open a new task after a successful update.

To fetch the pinned, hash-verified KiCadRoutingTools runtime and optional JLCImport/JLCPCB Tools integrations automatically instead of installing them by hand, run:

uv run python scripts/setup_dependencies.py

The script only ever contacts official sources over HTTPS (GitHub, Adoptium, kicad.github.io), verifies a checksum whenever the source publishes one, and asks for confirmation before writing anything — including the JLC plugins, which land in KiCad's own plugin directory, outside this repository. See "Automated dependency setup" in docs/INSTALLATION.md for exactly what it does and does not do.

Installing in Codex CLI

Complete the installation above first. Codex (the codex CLI) reads MCP server definitions from its config.toml~/.codex/config.toml on Linux/macOS, %USERPROFILE%\.codex\config.toml on Windows. Add a [mcp_servers.copperbrain] entry:

[mcp_servers.copperbrain]
command = "uv"
args = ["run", "--directory", "C:\\path\\to\\Copperbrain", "copperbrain"]
enabled = true

Codex launches command directly, without a shell and without setting a working directory of its own, so uv run needs --directory <repo> instead of relying on cd; use the absolute path to where you cloned this repository. To override an environment variable from docs/INSTALLATION.md#configuration for this server only, add it under [mcp_servers.copperbrain.env], the same way other entries in config.toml do. Restart Codex (or start a new session) after editing the file. Copperbrain still exposes local stdio only; registering it this way adds no network exposure.

Development

uv sync --all-extras
uv run pytest
uv run ruff check .
uv run ruff format --check .
uv run mypy src

Run the stdio MCP server with uv run copperbrain.

Run the non-destructive offline demo with uv run python scripts/run_demo.py.

MCP client contract

Every tool publishes a complete JSON Schema for its arguments. Structured requests such as request, rule_set, spec, requirements, and operations expose the underlying Pydantic model — its fields, enumerations, bounds, and defaults — instead of a free-form object, so a client can construct them without guessing. Fixed vocabularies (change_kind, phase, output_format, layer and strategy choices) are enumerations, and quantities and limits carry their real bounds. Schematic operations publish one schema variant per kind; each variant lists the required and accepted fields inside parameters, including their scalar types. Boundary validation failures are returned as stable invalid_input errors with field locations and corrective hints; Copperbrain does not expose Pydantic versions or documentation URLs to MCP callers.

Each tool also publishes a human-readable title and behavior hints: readOnlyHint for the analysis and proposal tools, destructiveHint for the three acceptances and rollback_accepted_phase, idempotentHint, and openWorldHint for tools that reach the JLCPCB/LCSC catalog or download assets. The server advertises the gated workflow in its initialize instructions.

Refusals keep their structure end to end: the stable error code, message, actionable hint, and details all reach the client, so failures never have to be recovered from log text.

Handlers are dispatched onto a worker thread and serialized through a single token, so shared sessions and change-set workspaces are touched by one operation at a time. The stdio loop keeps answering pings for the whole run. Note that a long KiCad CLI run, routing candidate, or catalog download cannot be interrupted once started: the worker thread runs to completion, holds the token, and a cancellation is only observed after it finishes. Size routing batches accordingly — COPPERBRAIN_ROUTING_TIMEOUT_SECONDS (default 900) bounds a single run. get_project_creation_status is the one tool that bypasses the token, so an in-flight project creation stays observable.

Three acceptance gates

The public MCP exposes exactly three tools that accept a validated mutation:

  1. accept_schematic for the project scaffold or schematic change set.
  2. accept_design_rules for reviewed widths, clearances, vias, netclasses, and assignments.
  3. accept_pcb for one aggregate change set composed from optional layout, placement, grounding, and routing stages, prepared with prepare_pcb_acceptance and rechecked with validate_pcb_acceptance.

Granular PCB prepare/preview/validate/apply/rollback functions are internal and are not MCP tools. They modify only the private aggregate workspace. rollback_accepted_phase is an explicit recovery command, not another acceptance gate.

To start a new design safely, call prepare_project_creation with an existing parent directory and a typed name/layer count plus a caller-selected request_id. Copperbrain persists that idempotency key before long-running work: retrying it with the same inputs resolves to the same change set, while get_project_creation_status remains callable during the operation and reports in_progress, completed, or failed after an ambiguous client timeout. Copperbrain creates the schematic through kicad-sch-api, creates the empty board through KiCad's bundled Python API, validates both files, and publishes only a preview under <new-project>/copperbrain-output/previews/schematic/. accept_schematic applies the validated scaffold; recovery remains hash guarded.

For an opened KiCad project, Copperbrain writes every deliverable artifact below <project>/copperbrain-output/: at most the stable schematic, design-rules, and pcb previews under previews/, plus BOM exports under bom/. Private mutation workspaces, caches, and rollback snapshots are not placed in the project.

Project analysis via MCP

Call detect_kicad to confirm KiCad, CLI, and JLC plugin availability, then open_project to open a project read-only and hash its sources. get_project_summary returns sheets, components, electrical nets, and power symbols; analyze_schematic returns deterministic, evidence-backed observations; trace_net returns every pin KiCad assigns to one exact net name. run_erc and run_drc run KiCad's checks and normalize violations without touching project files. Opened sessions are persisted in Copperbrain's private data directory and can be recovered after an MCP restart; reopening the project remains necessary if the persisted record is unavailable or the source project has changed.

Schematic changes via MCP

prepare_schematic_change stages allowlisted operations in a private workspace and returns a compact summary, risks, counts, and a project-local PDF preview; validate_change revalidates it in place. Summary mode is the default for prepare, validate, and acceptance and never echoes the input operation batch. Pass verbosity="full" only for deliberately small changes, or use get_schematic_change_details to page through operations, semantic differences, validation messages, or ERC violations in bounded groups of at most 20; exceptionally long scalar fields are marked and truncated in the page response. Applying requires the first acceptance gate, accept_schematic, with confirmed=true and editor_closed=true.

rollback_accepted_phase requires the exact change_set_id returned by the accepted phase. Its lock refusal identifies the detected project lock file and tells the caller which KiCad editor to close; editor_closed=true is an attestation, never a bypass. A successful rollback of an existing project returns a fresh session_id because the previous session's source hashes are obsolete.

Before saving a prepared schematic, Copperbrain registers project symbol libraries and preserves connectivity-bearing constructs that the pinned kicad-sch-api cannot round-trip, including global and hierarchical labels and unresolved embedded symbol definitions. The change is refused if a guarded wire, junction, bus, or label would still be lost.

Readability reports distinguish wired, mixed, label_based, and empty schematics. In label_based mode, direct pin labels and the absence of wire endpoints are intentional and do not reduce the score or produce a false readability failure; collision and duplicate-position checks remain active. empty reports readability as not applicable.

Component sourcing via MCP

search_components ranks JLCPCB/LCSC candidates against typed requirements using the installed JLCPCB Tools catalog or a recorded COPPERBRAIN_JLC_CATALOG. get_component_details returns normalized catalog details for one exact LCSC part; compare_components and find_alternatives rank supplied or discovered candidates against the same requirements. estimate_component_cost estimates component-only cost at one requested quantity. import_component_assets installs the resolved symbol/footprint/3D/datasheet assets locally from allowlisted HTTPS sources. For parts without a library symbol, generate_symbol_from_pinout creates a deterministic, parser-validated .kicad_sym scaffold in Copperbrain's private data directory from typed pin numbers, names, electrical types, sides, and standard properties. It accepts no S-expression and does not mutate the project. Review the result and pass it with the matching footprint to import_component_assets, which still enforces exact pin-to-pad number correspondence.

BOM via MCP

generate_bom groups and enriches the schematic BOM and writes JSON/CSV/Markdown under copperbrain-output/bom/. estimate_bom_cost returns component-only estimates at the requested board quantities; suggest_bom_substitutions proposes requirement-motivated alternatives for the first limit sourced BOM lines and reports sourced_line_count, examined_line_count, and truncated so a large BOM cannot turn into an unbounded run of catalog searches. All cost figures explicitly exclude PCB, assembly, stencil, shipping, taxes, and duties.

All three report catalog_failures: an LCSC identifier the catalog refused is named with its structured reason instead of silently producing an unpriced line, and one refused line no longer aborts a whole substitution report.

PCB design rules via MCP

Use analyze_pcb_constraints to inspect current netclasses and receive evidence-backed net-role suggestions. Pass reviewed fabrication limits and electrical intent to propose_design_rules, then use prepare_pcb_rule_change, validate_pcb_rule_change, and accept_design_rules. Applying requires the second acceptance and a saved, closed KiCad editor; rollback_accepted_phase restores the phase snapshot when explicitly invoked.

ManufacturingProfile covers minimum clearance/track/via dimensions, copper thickness, allowed temperature rise, and internal/external current layer. NetRuleRequirement covers exact net names, role, current, voltage, explicit clearance/width, creepage, maximum routed length, and optional differential geometry/maximum uncoupled length. Raw .kicad_dru text is never accepted through MCP.

High-current rules require a current or reviewed width. High-voltage rules require reviewed clearance. Differential geometry is explicitly marked as not impedance-controlled unless width and gap are supplied from a verified stackup calculation.

Before proposing routing rules, Copperbrain resolves every connected footprint and measures its electrical pads, minimum pitch, and edge-to-edge pad clearance. If a class width or clearance does not fit the package, the generated .kicad_dru applies a narrower track width or reduced clearance only inside that component's courtyard, never below the fabrication profile minimum. The original class remains active outside the package. Missing project-local courtyards can be generated inside the same previewed change set and are validated through KiCad CLI; unresolved footprints or packages narrower than the fabrication minimum produce a safe refusal.

PCB inspection and placement via MCP

Use get_pcb_summary, inspect_pcb_net, and get_footprint_placement for typed board queries. analyze_placement reports conservative courtyard overlaps, footprints outside Edge.Cuts, estimated ratsnest length, occupied envelope, compactness, side counts, and cross-layer nets. propose_component_placement accepts exact references, a typed optional region, spacing/grid and routing-corridor limits, plus deterministic compact or grid, rotation, and layer policies. Compact placement scores pad connectivity and envelope growth, keeps connectors near edges, and allows automatic bottom placement only for small SMD passives.

Pass the returned operations directly to prepare_pcb_acceptance. Placement is applied and validated inside its private aggregate workspace without an intermediate PDF or published copy; no separate placement preview or acceptance is exposed.

The official kicad-python IPC binding is installed and detected dynamically for live board transactions. PCB inspection and safe preview do not require a running editor: the typed file adapter and kicad-cli remain the deterministic offline path. No MCP placement tool accepts raw KiCad S-expressions, and this extension does not route traces or modify zones, keepouts, or the board outline. Un cambio F.Cu/B.Cu viene eseguito soltanto nella copia temporanea attraverso l'API pcbnew inclusa in KiCad, cosi pad, grafica, testi e modelli 3D vengono trasformati insieme. Preview, DRC, conferma esplicita, snapshot e rollback restano obbligatori.

Post-placement PCB grounding

Include the reviewed grounding request in prepare_pcb_acceptance. It targets every pad in one or more reviewed ground domains and derives all zone outlines from the real closed Edge.Cuts, pad geometry, fanouts, and vias. The default is always a two-copper-layer board: PGND owns the main shaped region on F.Cu, while GND owns the main shaped region on B.Cu. Planner-derived local regions on the opposite side are cut out of the main region with explicit clearance and distinct priorities. A four-layer stackup is used only when copper_layers=4 is explicitly requested; that opt-in policy uses PGND -> F.Cu/In2.Cu and GND -> In1.Cu/B.Cu for an unambiguous pair.

The domains remain distinct KiCad nets and are connected only through two-terminal bridges such as a 0-ohm resistor or net tie explicitly named in bridge_references. Pads that do not touch their assigned plane receive typed, clearance-screened pad-to-via fanouts. thermal and solid pad connections are selectable per domain; local shaped regions are solid and power ground commonly uses solid. Via-in-pad is opt-in because it requires a reviewed fabrication process. Existing selected-net zones are replaced only when replace_existing_planes=true is explicitly requested.

The result is validated inside the private aggregate workspace without a grounding preview. The KiCad Project Manager may remain open: only a PCB document lock blocks the final aggregate mutation. rollback_accepted_phase restores the aggregate PCB snapshot. Ambiguous domain roles, overlapping layer assignments, missing/ambiguous bridges, unsafe fanouts, or new DRC errors cause a structured refusal. The workflow does not accept polygons or KiCad expressions from callers, and it does not claim thermal, return-path, EMC, SI/PI, stackup, or DFM certification.

Headless PCB initialization via MCP

For an empty board, prepare_pcb_acceptance accepts an optional layout stage: a typed rectangular outline, one placement for every physical schematic footprint, and optional fixed M3 mounting holes. It synchronizes footprints, builds the unrouted PCB, and runs comparative ERC/DRC inside the aggregate workspace. There is no separate layout preview or acceptance — it is covered by the single PCB gate. Footprint substitutions are a schematic change: send them to prepare_schematic_change as update_property operations before preparing the PCB.

The bounded motor-driver reference helpers demonstrate this flow for a provisional 12 V, 20 A brushed-DC H-bridge using DRV8701, four external 60 V MOSFETs, ATtiny1616, half-duplex RS-485, and four protected 5–24 V digital sensor inputs. Its typed plan uses a compact 120 x 100 mm board, four M3 holes, a star-separated PGND/logic GND, and a 70 um external-copper assumption. It is a review benchmark, not a production-qualified design; high-current zones, thermal/EMC/DFM, motor stall behavior, and the final stackup still require engineering validation.

The typed DRV8311S reference helpers describe an 85 x 50 mm four-layer BLDC driver at a provisional 9--12.6 V, 2 A continuous operating point, with 6-PWM, SPI, three current-sense outputs, fault, Hall signals, input protection, decoupling, grounding intent, thermal-pad fanout, and rule classes. The repository intentionally does not bundle generated benchmark projects. The helpers and their deterministic tests are review evidence, not a production release: power/phase copper, thermal/SOA, EMC, DFM, and final routing still require project-specific engineering validation.

Controlled PCB routing via MCP

After rules and placement/grounding intent are reviewed, use analyze_unrouted_nets to identify the remaining disconnected pad groups. Ground-zone connectivity is included, so the router does not redundantly route pads already joined by an applied plane. Check get_routing_backend_status, then call propose_pcb_routing. KiCadRoutingTools runs locally through its Python CLI and Rust-accelerated A* core. Copperbrain can run at most three isolated ordering strategies: mps, inside_out, and original. One candidate is used by default and a request for a fourth is rejected. Copperbrain ranks candidates by completion, new DRC errors, open connections, vias, and routed length. Only the selected candidate's copper delta becomes typed segments and vias; there is no internal routing fallback. Reviewed planes remain on the private input board as copper obstacles, while their nets are excluded from the explicit signal-routing batch. The selected typed copper is applied to the already-grounded private board, followed by KiCad zone refill and comparative DRC. Fine-pitch escape geometry is opt-in per routing batch. When enabled, Copperbrain derives short typed stubs from pad and courtyard geometry and, for a nearby opposite-side target, a clearance- offset dogbone via with an outside-courtyard approach. It includes these seeds in the private router input and subjects the resulting complete copper delta to the same scope, preservation, connectivity, and DRC gates. When nets is empty, Copperbrain materializes the exact currently-unrouted net set before starting the backend. KiCadRoutingTools receives those exact names through its fixed --nets argument; non-target nets, existing routes, planes, keepouts, pads, and the board outline remain obstacles. Copperbrain never enables the backend option that permits ripping pre-existing routes. Every result is rejected if it removes existing copper or adds copper outside the requested net set.

Pass the reviewed routing requests with placement and grounding to prepare_pcb_acceptance. Copperbrain stops after the bounded candidate comparison, applies only the best candidate to the private prepared PCB, refills zones, rechecks connectivity, and runs comparative DRC inside one private workspace without routing previews. It does not keep retrying to obtain a complete route. Final engineering cleanup and the explicit decision to apply the prepared PCB remain with the user. Only the complete aggregate publishes copperbrain-output/previews/pcb/ and can be applied by accept_pcb with the third acceptance and a closed editor. The KiCad Project Manager may remain open; only a PCB-document lock blocks the aggregate apply/rollback. Boards containing pre-existing copper are rejected by default; explicitly select the preserve policy only for intentional incremental routing. Wall-time and output-stall watchdogs stop the complete router process tree. The typed delta is always applied to the original-precision project copy. Each proposal writes versioned baseline and per-candidate JSON metrics below the private COPPERBRAIN_DATA_DIR/metrics/connectivity/ tree. KiCadRoutingTools attempt records retain bounded queued/routed/failure counts, duration, routed copper, watchdog evidence, and resource data when the backend exposes it. Backend output is bounded and sensitive net names are replaced with hashes. The returned RoutingPlan.metrics_run_id correlates those records with preview, apply, and recovery. Call get_connectivity_metrics with that ID for a bounded, sanitized optimization view including the best observed pass, connection delta, failed-candidate count, stagnation, and watchdog causes. New records use schema 5 while the reader remains compatible with persisted schema-2 records.

For the compact end-to-end surface, call prepare_pcb_acceptance, review its preview, then use validate_pcb_acceptance and accept_pcb. assess_pcb_readiness intentionally keeps production_ready=false when DFM, stackup, thermal, SI/PI, EMC, or impedance checks have not been performed, even if routing/ERC/DRC pass.

The AI may explain and review the structured candidate evidence, but it cannot override connectivity, DRC, confirmation, stale-hash, or editor-state gates. This workflow does not certify impedance, SI/PI/EMC, thermal behavior, or regulatory compliance. Raw KiCad expressions, zones, and keepouts remain unavailable through the routing tools.

Contributors

deadbringer17

54 commits

claude

2 commits

Languages

Python

100.0%