feat: add mil unit support across position/coordinate commands (#162)
* feat(units): add mil unit support across all position/coordinate commands KiCad natively supports mils, so the MCP server should too. Added "mil" as a valid unit option in tool schemas and updated all unit-to-nanometer scale conversions across component, routing, outline, view, and IPC handler code paths. 1 mil = 25400 nm (0.0254 mm). Also fixes a pre-existing mypy overload error in pin_locator.py (str cast on dict.get key) that was blocking pre-commit on any Python file change. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(units): add mil to TypeScript tool schemas The Python-side mil support was added but the actual input validation happens in the TypeScript/Zod schemas. Updated all z.enum(["mm", "inch"]) to include "mil" across board, component, routing, design-rules, and export tool definitions. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(tools): replace CP-1252 mojibake with correct Unicode in board.ts Replace U+00C3 U+00D7 (×) with U+00D7 (×) in add_logo size output string. Character was mangled when file was saved as CP-1252 instead of UTF-8. * fix: restore em-dash and fix pre-commit mypy in component/routing component.py: replace CP-1252 mojibake (â€") with correct Unicode em-dash (—) in the 'Add to board first' comment. Addresses maintainer review on PR #162. routing.py: annotate ex/ey as float at first assignment site in _point_to_segment_distance_nm so mypy pre-commit hook passes cleanly on this branch. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -29,7 +29,7 @@ export function registerBoardTools(server: McpServer, callKicadScript: CommandFu
|
||||
{
|
||||
width: z.number().describe("Board width"),
|
||||
height: z.number().describe("Board height"),
|
||||
unit: z.enum(["mm", "inch"]).describe("Unit of measurement"),
|
||||
unit: z.enum(["mm", "mil", "inch"]).describe("Unit of measurement"),
|
||||
},
|
||||
async ({ width, height, unit }) => {
|
||||
logger.debug(`Setting board size to ${width}x${height} ${unit}`);
|
||||
@@ -181,7 +181,7 @@ export function registerBoardTools(server: McpServer, callKicadScript: CommandFu
|
||||
// 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"),
|
||||
unit: z.enum(["mm", "mil", "inch"]).describe("Unit of measurement"),
|
||||
})
|
||||
.describe("Parameters for the outline shape"),
|
||||
},
|
||||
@@ -216,7 +216,7 @@ export function registerBoardTools(server: McpServer, callKicadScript: CommandFu
|
||||
.object({
|
||||
x: z.number().describe("X coordinate"),
|
||||
y: z.number().describe("Y coordinate"),
|
||||
unit: z.enum(["mm", "inch"]).describe("Unit of measurement"),
|
||||
unit: z.enum(["mm", "mil", "inch"]).describe("Unit of measurement"),
|
||||
})
|
||||
.describe("Position of the mounting hole"),
|
||||
diameter: z.number().describe("Diameter of the hole"),
|
||||
@@ -253,7 +253,7 @@ export function registerBoardTools(server: McpServer, callKicadScript: CommandFu
|
||||
.object({
|
||||
x: z.number().describe("X coordinate"),
|
||||
y: z.number().describe("Y coordinate"),
|
||||
unit: z.enum(["mm", "inch"]).describe("Unit of measurement"),
|
||||
unit: z.enum(["mm", "mil", "inch"]).describe("Unit of measurement"),
|
||||
})
|
||||
.describe("Position of the text"),
|
||||
layer: z.string().describe("Layer to place the text on"),
|
||||
@@ -302,7 +302,7 @@ export function registerBoardTools(server: McpServer, callKicadScript: CommandFu
|
||||
}),
|
||||
)
|
||||
.describe("Points defining the zone outline"),
|
||||
unit: z.enum(["mm", "inch"]).describe("Unit of measurement"),
|
||||
unit: z.enum(["mm", "mil", "inch"]).describe("Unit of measurement"),
|
||||
clearance: z.number().optional().describe("Clearance value"),
|
||||
minWidth: z.number().optional().describe("Minimum width"),
|
||||
padConnection: z
|
||||
@@ -340,7 +340,7 @@ export function registerBoardTools(server: McpServer, callKicadScript: CommandFu
|
||||
"get_board_extents",
|
||||
"Return the bounding box (min/max X and Y) of all objects on the current PCB board.",
|
||||
{
|
||||
unit: z.enum(["mm", "inch"]).optional().describe("Unit of measurement for the result"),
|
||||
unit: z.enum(["mm", "mil", "inch"]).optional().describe("Unit of measurement for the result"),
|
||||
},
|
||||
async ({ unit }) => {
|
||||
logger.debug("Getting board extents");
|
||||
|
||||
@@ -32,7 +32,7 @@ export function registerComponentTools(server: McpServer, callKicadScript: Comma
|
||||
.object({
|
||||
x: z.number().describe("X coordinate"),
|
||||
y: z.number().describe("Y coordinate"),
|
||||
unit: z.enum(["mm", "inch"]).describe("Unit of measurement"),
|
||||
unit: z.enum(["mm", "inch", "mil"]).describe("Unit of measurement"),
|
||||
})
|
||||
.describe("Position coordinates and unit"),
|
||||
reference: z.string().optional().describe("Optional desired reference (e.g., 'R5')"),
|
||||
@@ -85,7 +85,7 @@ export function registerComponentTools(server: McpServer, callKicadScript: Comma
|
||||
.object({
|
||||
x: z.number().describe("X coordinate"),
|
||||
y: z.number().describe("Y coordinate"),
|
||||
unit: z.enum(["mm", "inch"]).describe("Unit of measurement"),
|
||||
unit: z.enum(["mm", "inch", "mil"]).describe("Unit of measurement"),
|
||||
})
|
||||
.describe("New position coordinates and unit"),
|
||||
rotation: z.number().optional().describe("Optional new rotation in degrees"),
|
||||
@@ -359,7 +359,7 @@ export function registerComponentTools(server: McpServer, callKicadScript: Comma
|
||||
"Return all pads of a PCB component with their positions, net assignments and sizes.",
|
||||
{
|
||||
reference: z.string().describe("Reference designator of the component (e.g., 'U1')"),
|
||||
unit: z.enum(["mm", "inch"]).optional().describe("Unit for coordinates (default: mm)"),
|
||||
unit: z.enum(["mm", "mil", "inch"]).optional().describe("Unit for coordinates (default: mm)"),
|
||||
},
|
||||
async ({ reference, unit }) => {
|
||||
logger.debug(`Getting pads for component: ${reference}`);
|
||||
@@ -393,11 +393,11 @@ export function registerComponentTools(server: McpServer, callKicadScript: Comma
|
||||
y1: z.number(),
|
||||
x2: z.number(),
|
||||
y2: z.number(),
|
||||
unit: z.enum(["mm", "inch"]).optional(),
|
||||
unit: z.enum(["mm", "inch", "mil"]).optional(),
|
||||
})
|
||||
.optional()
|
||||
.describe("Filter by bounding box region"),
|
||||
unit: z.enum(["mm", "inch"]).optional().describe("Unit for coordinates (default: mm)"),
|
||||
unit: z.enum(["mm", "mil", "inch"]).optional().describe("Unit for coordinates (default: mm)"),
|
||||
},
|
||||
async ({ layer, boundingBox, unit }) => {
|
||||
logger.debug("Getting component list");
|
||||
@@ -427,7 +427,7 @@ export function registerComponentTools(server: McpServer, callKicadScript: Comma
|
||||
{
|
||||
reference: z.string().describe("Component reference designator (e.g., 'U1')"),
|
||||
pad: z.string().describe("Pad number or name (e.g., '1', 'A1')"),
|
||||
unit: z.enum(["mm", "inch"]).optional().describe("Unit for coordinates (default: mm)"),
|
||||
unit: z.enum(["mm", "mil", "inch"]).optional().describe("Unit for coordinates (default: mm)"),
|
||||
},
|
||||
async ({ reference, pad, unit }) => {
|
||||
logger.debug(`Getting pad position for ${reference} pad ${pad}`);
|
||||
@@ -460,7 +460,7 @@ export function registerComponentTools(server: McpServer, callKicadScript: Comma
|
||||
.object({
|
||||
x: z.number(),
|
||||
y: z.number(),
|
||||
unit: z.enum(["mm", "inch"]),
|
||||
unit: z.enum(["mm", "inch", "mil"]),
|
||||
})
|
||||
.describe("Starting position"),
|
||||
rows: z.number().describe("Number of rows"),
|
||||
@@ -617,7 +617,7 @@ export function registerComponentTools(server: McpServer, callKicadScript: Comma
|
||||
.object({
|
||||
x: z.number(),
|
||||
y: z.number(),
|
||||
unit: z.enum(["mm", "inch"]).optional(),
|
||||
unit: z.enum(["mm", "inch", "mil"]).optional(),
|
||||
})
|
||||
.describe("Offset from original position"),
|
||||
newReference: z.string().optional().describe("New reference designator"),
|
||||
|
||||
@@ -253,7 +253,7 @@ export function registerDesignRuleTools(server: McpServer, callKicadScript: Comm
|
||||
.object({
|
||||
x: z.number().optional(),
|
||||
y: z.number().optional(),
|
||||
unit: z.enum(["mm", "inch"]).optional(),
|
||||
unit: z.enum(["mm", "mil", "inch"]).optional(),
|
||||
})
|
||||
.optional()
|
||||
.describe("Position to check (if ID not provided)"),
|
||||
@@ -270,7 +270,7 @@ export function registerDesignRuleTools(server: McpServer, callKicadScript: Comm
|
||||
.object({
|
||||
x: z.number().optional(),
|
||||
y: z.number().optional(),
|
||||
unit: z.enum(["mm", "inch"]).optional(),
|
||||
unit: z.enum(["mm", "mil", "inch"]).optional(),
|
||||
})
|
||||
.optional()
|
||||
.describe("Position to check (if ID not provided)"),
|
||||
|
||||
@@ -264,7 +264,7 @@ export function registerExportTools(server: McpServer, callKicadScript: CommandF
|
||||
{
|
||||
outputPath: z.string().describe("Path to save the position file"),
|
||||
format: z.enum(["CSV", "ASCII"]).optional().describe("File format (default: CSV)"),
|
||||
units: z.enum(["mm", "inch"]).optional().describe("Units to use (default: mm)"),
|
||||
units: z.enum(["mm", "mil", "inch"]).optional().describe("Units to use (default: mm)"),
|
||||
side: z
|
||||
.enum(["top", "bottom", "both"])
|
||||
.optional()
|
||||
|
||||
@@ -172,7 +172,7 @@ export function registerRoutingTools(server: McpServer, callKicadScript: Functio
|
||||
.object({
|
||||
x: z.number(),
|
||||
y: z.number(),
|
||||
unit: z.enum(["mm", "inch"]).optional(),
|
||||
unit: z.enum(["mm", "inch", "mil"]).optional(),
|
||||
})
|
||||
.optional()
|
||||
.describe("Delete trace nearest to this position"),
|
||||
@@ -206,11 +206,11 @@ export function registerRoutingTools(server: McpServer, callKicadScript: Functio
|
||||
y1: z.number(),
|
||||
x2: z.number(),
|
||||
y2: z.number(),
|
||||
unit: z.enum(["mm", "inch"]).optional(),
|
||||
unit: z.enum(["mm", "inch", "mil"]).optional(),
|
||||
})
|
||||
.optional()
|
||||
.describe("Filter by bounding box region"),
|
||||
unit: z.enum(["mm", "inch"]).optional().describe("Unit for coordinates"),
|
||||
unit: z.enum(["mm", "inch", "mil"]).optional().describe("Unit for coordinates"),
|
||||
},
|
||||
async (args: any) => {
|
||||
const result = await callKicadScript("query_traces", args);
|
||||
@@ -358,7 +358,7 @@ export function registerRoutingTools(server: McpServer, callKicadScript: Functio
|
||||
.boolean()
|
||||
.optional()
|
||||
.describe("Include statistics (track count, total length, etc.)"),
|
||||
unit: z.enum(["mm", "inch"]).optional().describe("Unit for length measurements"),
|
||||
unit: z.enum(["mm", "mil", "inch"]).optional().describe("Unit for length measurements"),
|
||||
},
|
||||
async (args: any) => {
|
||||
const result = await callKicadScript("get_nets_list", args);
|
||||
|
||||
Reference in New Issue
Block a user