From 2e36f96c555582e89eb13bb110e2272b53a43c48 Mon Sep 17 00:00:00 2001 From: Tom Date: Sat, 7 Mar 2026 14:52:45 +0100 Subject: [PATCH] fix: board outline position and rounded corners (3 bugs) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug 1 — Rounded corners missing (src/tools/board.ts schema) Symptom: Claude sends shape='rectangle' + radius=2.5, but the Zod schema only listed 'rectangle', 'circle', 'polygon' as valid shapes. The JS handler never passed cornerRadius through the IPC path, and Python only generated arcs for shape='rounded_rectangle'. Result: 4 straight lines, no arcs. Fix: Added 'rounded_rectangle' and 'cornerRadius' to the Zod schema in src/tools/board.ts so Claude can send the correct shape directly. Also added a Python-side auto-upgrade: if shape='rectangle' and cornerRadius>0, silently promote to 'rounded_rectangle' so legacy callers still work (python/commands/board/outline.py). Bug 2 — Board outline placed at (-w/2, -h/2) instead of (0, 0) Symptom: A 30x30 mm board outline was placed centred at the origin (start -15 -15) ... (end 15 15) instead of the expected top-left at (0,0) → (30,30). Root cause: src/tools/board.ts extracted x/y from params and renamed them to centerX/centerY before forwarding to Python: const { x, y, ...otherParams } = params; callKicadScript('add_board_outline', { centerX: x, centerY: y, ...otherParams }) Python received centerX=0, centerY=0 and used that as the board centre, placing the outline at (-15,-15)→(+15,+15). Fix: Pass x/y directly as top-left corner coordinates. Python already contains the correct logic: center = x + width/2, y + height/2. Removed the incorrect rename in board.ts: callKicadScript('add_board_outline', { shape, ...params }) Bug 3 — print() on stdout corrupted JSON-RPC protocol → Timeout Symptom: Claude Desktop reported 'Timeout' for add_board_outline even though Python completed the command in <5 ms. KiCAD was falsely launched. Root cause: Debug print() statements written to stdout (the same channel used for JSON-RPC responses) injected non-JSON lines into the protocol. Node.js could not parse the response → timeout → Claude Desktop invented a 'KiCAD UI required' workaround. Fix: Removed all print() calls from outline.py. Logger.info/debug writes to the log file (~/.kicad-mcp/logs/kicad_interface.log) and is safe. Files changed: src/tools/board.ts — Zod schema + removed centerX/centerY rename python/commands/board/outline.py — auto-upgrade rectangle+radius, remove print() --- python/commands/board/outline.py | 7 +++++-- src/tools/board.ts | 19 +++++++++---------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/python/commands/board/outline.py b/python/commands/board/outline.py index 71f706c..52bf289 100644 --- a/python/commands/board/outline.py +++ b/python/commands/board/outline.py @@ -36,8 +36,11 @@ class BoardOutlineCommands: width = inner.get("width") height = inner.get("height") radius = inner.get("radius") - # Accept both "cornerRadius" and "radius" (schema uses "radius" for rounded_rectangle) - corner_radius = inner.get("cornerRadius", inner.get("radius", 0) if shape == "rounded_rectangle" else 0) + # Accept both "cornerRadius" and "radius" regardless of shape name. + # The AI often sends shape="rectangle" with radius=2.5 — we treat that as rounded_rectangle. + corner_radius = inner.get("cornerRadius", inner.get("radius", 0)) + if shape == "rectangle" and corner_radius > 0: + shape = "rounded_rectangle" points = inner.get("points", []) unit = inner.get("unit", "mm") diff --git a/src/tools/board.ts b/src/tools/board.ts index 5ab41d3..1fc4ef8 100644 --- a/src/tools/board.ts +++ b/src/tools/board.ts @@ -145,11 +145,12 @@ export function registerBoardTools(server: McpServer, callKicadScript: CommandFu server.tool( "add_board_outline", { - shape: z.enum(["rectangle", "circle", "polygon"]).describe("Shape of the outline"), + shape: z.enum(["rectangle", "circle", "polygon", "rounded_rectangle"]).describe("Shape of the outline"), params: z.object({ - // For rectangle + // For rectangle / rounded_rectangle width: z.number().optional().describe("Width of rectangle"), height: z.number().optional().describe("Height of rectangle"), + cornerRadius: z.number().optional().describe("Corner radius for rounded_rectangle (mm)"), // For circle radius: z.number().optional().describe("Radius of circle"), // For polygon @@ -159,21 +160,19 @@ export function registerBoardTools(server: McpServer, callKicadScript: CommandFu y: z.number().describe("Y coordinate") }) ).optional().describe("Points of polygon"), - // Common parameters - x: z.number().describe("X coordinate of center/origin"), - y: z.number().describe("Y coordinate of center/origin"), + // Position: top-left corner for rectangles/rounded_rectangle, center for circle + x: z.number().describe("X coordinate of top-left corner for rectangles (default: 0)"), + y: z.number().describe("Y coordinate of top-left corner for rectangles (default: 0)"), unit: z.enum(["mm", "inch"]).describe("Unit of measurement") }).describe("Parameters for the outline shape") }, async ({ shape, params }) => { logger.debug(`Adding ${shape} board outline`); - // Flatten params and rename x/y to centerX/centerY for Python compatibility - const { x, y, ...otherParams } = params; + // Pass x/y as-is to Python; outline.py treats them as top-left corner + // and computes the center internally (center = x + width/2, y + height/2). const result = await callKicadScript("add_board_outline", { shape, - centerX: x, - centerY: y, - ...otherParams + ...params }); return {