feat(schematic): hierarchical sheet insertion and subsheet scaffolding

Adds add_hierarchical_sheet (insert a sheet symbol referencing a child
.kicad_sch, with sheet_instances + fixed component instance paths) and
create_hierarchical_subsheet (create the child file + wire it into the parent
in one call). Upstream has add_sheet_pin / add_schematic_hierarchical_label
but no way to create a sheet or stand up a child sheet, so hierarchical
designs can't be built through the MCP server today.

- python/commands/schematic_hierarchy.py: SchematicHierarchyCommands
- src/tools/schematic-hierarchy.ts + registry 'schematic_hierarchy' category
- python/kicad_interface.py: import + instantiate + dispatch routes
- tests/test_schematic_hierarchy.py: 5 unit/integration tests on real .kicad_sch

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Ravi
2026-06-02 19:41:45 -07:00
committed by mixelpixx
parent df82ff5c56
commit a9d7af5edf
6 changed files with 445 additions and 0 deletions

View File

@@ -20,6 +20,7 @@ import { registerExportTools } from "./tools/export.js";
import { registerSchematicTools } from "./tools/schematic.js";
import { registerLibraryTools } from "./tools/library.js";
import { registerSymbolLibraryTools } from "./tools/library-symbol.js";
import { registerSchematicHierarchyTools } from "./tools/schematic-hierarchy.js";
import { registerJLCPCBApiTools } from "./tools/jlcpcb-api.js";
import { registerDatasheetTools } from "./tools/datasheet.js";
import { registerFootprintTools } from "./tools/footprint.js";
@@ -296,6 +297,7 @@ export class KiCADMcpServer {
registerSchematicTools(this.server, this.callKicadScript.bind(this));
registerLibraryTools(this.server, this.callKicadScript.bind(this));
registerSymbolLibraryTools(this.server, this.callKicadScript.bind(this));
registerSchematicHierarchyTools(this.server, this.callKicadScript.bind(this));
registerJLCPCBApiTools(this.server, this.callKicadScript.bind(this));
registerDatasheetTools(this.server, this.callKicadScript.bind(this));
registerFootprintTools(this.server, this.callKicadScript.bind(this));

View File

@@ -123,6 +123,11 @@ export const toolCategories: ToolCategory[] = [
description: "Read a symbol's pins straight from the library (no schematic needed)",
tools: ["list_symbol_pins", "batch_list_symbol_pins"],
},
{
name: "schematic_hierarchy",
description: "Hierarchical schematic sheets: insert a sheet, scaffold a sub-sheet",
tools: ["add_hierarchical_sheet", "create_hierarchical_subsheet"],
},
{
name: "routing",
description: "Advanced routing operations: vias, copper pours",

View File

@@ -0,0 +1,64 @@
/**
* Schematic hierarchy tools: insert a hierarchical sheet, scaffold a sub-sheet.
*/
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
export function registerSchematicHierarchyTools(server: McpServer, callKicadScript: Function) {
// Link an existing sub-sheet into a parent
server.tool(
"add_hierarchical_sheet",
"Insert a hierarchical-sheet reference block into a parent schematic, pointing at an existing sub-sheet file. Adds the sheet box, name/file fields, a sheet_instances path entry on the next page number, and fixes sub-sheet component instance paths so ERC resolves references.",
{
schematicPath: z.string().describe("Path to the parent .kicad_sch"),
subsheetPath: z.string().describe("Path to the existing sub-sheet .kicad_sch to reference"),
sheetName: z.string().optional().default("Sheet").describe("Display name for the sheet"),
position: z
.object({ x: z.number(), y: z.number() })
.optional()
.describe("Top-left of the sheet box in mm (default 50,50)"),
size: z
.object({ width: z.number(), height: z.number() })
.optional()
.describe("Sheet box size in mm (default 80x50)"),
},
async (args: any) => {
const r = await callKicadScript("add_hierarchical_sheet", args);
if (!r.success)
return { content: [{ type: "text", text: `Failed: ${r.message || "Unknown error"}` }] };
return {
content: [
{
type: "text",
text: `Added sheet '${r.sheet_name}' -> ${r.subsheet_path} (page ${r.page})`,
},
],
};
},
);
// Create a sub-sheet file AND link it in one call
server.tool(
"create_hierarchical_subsheet",
"Create a new sub-sheet .kicad_sch file and link it into a parent schematic in a single call (create_schematic + add_hierarchical_sheet). The fastest way to grow a hierarchical design.",
{
parentSchematicPath: z.string().describe("Path to the parent .kicad_sch"),
subsheetPath: z.string().describe("Path for the new sub-sheet .kicad_sch to create"),
sheetName: z.string().optional().default("Sheet").describe("Display name for the sheet"),
position: z.object({ x: z.number(), y: z.number() }).optional(),
size: z.object({ width: z.number(), height: z.number() }).optional(),
metadata: z
.record(z.string(), z.any())
.optional()
.describe("Optional metadata for the new sub-sheet (title, etc.)"),
},
async (args: any) => {
const r = await callKicadScript("create_hierarchical_subsheet", args);
return {
content: [
{ type: "text", text: r.success ? r.message : `Failed: ${r.message || "Unknown error"}` },
],
};
},
);
}