Skip to content

Autorouting

The routing tools take an unrouted (or partially routed) PCB and lay copper for the remaining nets automatically. The whole pipeline is headless and needs no display, no running KiCad GUI, and no Java runtime by default, which makes it usable in CI, containers, and from an MCP client.

Routing runs through freeroute, a native-Python port of the FreeRouting engine, with the original FreeRouting JAR available as an optional fallback for dense boards.

  • KiCad with its bundled pcbnew Python module (used for DSN export and the native SES applier)

  • freeroute installed and on your PATH:

    Terminal window
    uv tool install freeroute
    # or: pip install freeroute

freeroute is pure Python standard library with no dependencies. mckicad auto-discovers the freeroute command; if it is installed off-PATH, set FREEROUTE_CLI to the executable in your .env. Confirm your setup before routing:

Check whether automated routing is available for my board

The check_routing_capability tool reports which router it found (freeroute, the JAR, or both) and whether the board is ready to route.

When you route a board, mckicad runs a fully headless sequence:

  1. Export to DSN. The board is exported to a Specctra DSN file using KiCad’s bundled pcbnew Python. KiCad 10’s kicad-cli dropped the DSN export and SES import subcommands, so mckicad does this itself rather than shelling out to the CLI.
  2. Route. freeroute reads the DSN, routes the nets, and writes a Specctra SES file. No Java, no GUI.
  3. Apply the SES natively. A native, headless SES applier writes the routed copper straight back into the .kicad_pcb file. There is no GUI import step and no display required.
  4. Validate. Run a DRC check and inspect the routing result to confirm the board is clean.

To run it:

Automatically route my PCB at /path/to/project.kicad_pcb

The route_pcb_automatically tool orchestrates the whole pipeline and returns routing statistics along with the path to the updated board.

freeroute ships three engines. mckicad defaults to room with channel packing enabled, which is a good all-round starting point. Select an engine through the routing_config argument (see Configuration).

EngineWhat it doesReach for it when
roomContinuous free-space router with channel packing and shove. DRC-clean output.Default. Best general-purpose choice for most boards.
exactOrthogonal router whose output is verified exactly DRC-clean. Supports shove and 45-degree / diagonal shortening.You want provably clean, predictable orthogonal routing.
gridFast maze router, grid-quantised.Quick first passes and simpler boards where speed matters more than density.

The relevant routing_config keys are:

  • freeroute_engineroom (default), exact, or grid
  • freeroute_pack — enable channel packing for tighter routing (default true)
  • freeroute_shove — allow shoving existing traces to make room
  • freeroute_diagonal — allow 45-degree / diagonal trace shortening

freeroute is built to never emit a design rule violation. Every engine produces DRC-clean copper, and exact verifies its output as exactly clean. The trade-off is deliberate: when the router cannot place a net without breaking clearance, it drops the net rather than route it into a violation. You get a board that passes DRC with some nets still unrouted, not a fully connected board that fails DRC.

After routing, verify the result:

Analyze the routing quality of my board

analyze_routing_quality reports on trace characteristics, via usage, and potential issues. To see how many nets actually got connected:

Check the routing connectivity of my PCB

check_connectivity reports total nets, routed vs unrouted counts, and the routing completion percentage. Any nets freeroute dropped show up here as unrouted, so you can decide whether to reroute with different settings, route them by hand, or reach for the JAR fallback.

If freeroute is not installed, or it cannot route a particular board, mckicad falls back to the original FreeRouting JAR. This path requires a Java runtime and the JAR on disk (see Installation). The JAR reaches higher net completion on dense commercial boards, at the cost of pulling Java back into the pipeline.

mckicad picks the router for you: freeroute when it is available and can route the board, the JAR otherwise. You do not have to choose manually, but you can keep both installed so the fallback is there when you need it.

freeroute is Alpha. Being honest about its scope saves surprises:

What it does today: routes real KiCad boards across multiple layers with vias, rip-up and retry, channel packing, and 45-degree shortening, and it produces DRC-clean output.

What it does not do yet: it is not at FreeRouting/JAR density parity on dense commercial boards. Because it drops a net rather than emit a DRC violation, it completes fewer nets than the JAR on a hard board.

Recommendation: use freeroute for headless, JVM-free routing — CI, containers, and MCP-driven workflows where you cannot or do not want to run Java. Keep the FreeRouting JAR as a fallback when you need maximum net completion on a dense board.

ToolDescription
check_routing_capabilityCheck whether automated routing is available and which router was found
route_pcb_automaticallyRun the full headless routing pipeline (freeroute, JAR fallback)
analyze_routing_qualityAnalyze the routed board for quality and potential issues
check_connectivityReport routed vs unrouted nets and completion percentage
  1. Confirm freeroute is installed: freeroute --version
  2. If it is installed off-PATH, set FREEROUTE_CLI to the executable path
  3. Run check_routing_capability to see what mckicad detected
  4. As a fallback, install the FreeRouting JAR and a Java runtime (see Installation)
  1. This is expected behaviour: freeroute drops nets it cannot route cleanly rather than create DRC violations
  2. Try a different engine (exact or grid) or adjust freeroute_pack / freeroute_shove / freeroute_diagonal
  3. Route the remaining nets by hand in KiCad
  4. For a dense board, install the FreeRouting JAR and let mckicad fall back to it for higher completion
  1. Ensure KiCad’s bundled pcbnew Python module is available to the server
  2. Verify the .kicad_pcb file opens cleanly in KiCad
  3. Check the server logs (mckicad.log) for the exact failure