style: revert Prettier formatting in TS files

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Eugene Mikhantyev
2026-03-29 12:28:30 +01:00
parent 7d53272cb1
commit 8b0ed30ee3
2 changed files with 370 additions and 484 deletions

View File

@@ -1,307 +1,308 @@
/**
* Tool Registry for KiCAD MCP Server
*
* Centralizes all tool definitions and provides lookup/search functionality
*/
import { z } from "zod";
export interface ToolDefinition {
name: string;
description: string;
inputSchema: z.ZodObject<any> | z.ZodType<any>;
// Handler will be registered separately in the existing tool files
}
export interface ToolCategory {
name: string;
description: string;
tools: string[]; // Tool names in this category
}
/**
* Tool category definitions
* Each category groups related tools for better organization
*/
export const toolCategories: ToolCategory[] = [
{
name: "board",
description:
"Board configuration: layers, mounting holes, zones, visualization",
tools: [
"add_layer",
"set_active_layer",
"get_layer_list",
"add_mounting_hole",
"add_board_text",
"add_zone",
"get_board_extents",
"get_board_2d_view",
"launch_kicad_ui",
],
},
{
name: "component",
description:
"Advanced component operations: edit, delete, search, group, annotate",
tools: [
"rotate_component",
"delete_component",
"edit_component",
"find_component",
"get_component_properties",
"add_component_annotation",
"group_components",
"replace_component",
],
},
{
name: "export",
description:
"File export for fabrication and documentation: Gerber, PDF, BOM, 3D models",
tools: [
"export_gerber",
"export_pdf",
"export_svg",
"export_3d",
"export_bom",
"export_netlist",
"export_position_file",
"export_vrml",
],
},
{
name: "drc",
description:
"Design rule checking and electrical validation: DRC, net classes, clearances",
tools: [
"set_design_rules",
"get_design_rules",
"run_drc",
"add_net_class",
"assign_net_to_class",
"set_layer_constraints",
"check_clearance",
"get_drc_violations",
],
},
{
name: "schematic",
description:
"Schematic operations: create, inspect, add/edit/delete components, wire connections, netlists, annotation",
tools: [
"create_schematic",
"add_schematic_component",
"list_schematic_components",
"move_schematic_component",
"rotate_schematic_component",
"annotate_schematic",
"add_schematic_wire",
"delete_schematic_wire",
"add_schematic_junction",
"add_schematic_net_label",
"delete_schematic_net_label",
"connect_to_net",
"connect_passthrough",
"get_net_connections",
"list_schematic_nets",
"list_schematic_wires",
"list_schematic_labels",
"get_wire_connections",
"generate_netlist",
"sync_schematic_to_board",
"get_schematic_view",
"export_schematic_svg",
"export_schematic_pdf",
],
},
{
name: "library",
description:
"Footprint library access: search, browse, get footprint information",
tools: [
"list_libraries",
"search_footprints",
"list_library_footprints",
"get_footprint_info",
],
},
{
name: "routing",
description: "Advanced routing operations: vias, copper pours",
tools: ["add_via", "add_copper_pour"],
},
{
name: "autoroute",
description:
"Freerouting autorouter: automatic PCB routing via Specctra DSN/SES",
tools: ["autoroute", "export_dsn", "import_ses", "check_freerouting"],
},
];
/**
* Direct tools that are always visible (not routed)
* These are the most frequently used tools
*/
export const directToolNames = [
// Project lifecycle
"create_project",
"open_project",
"save_project",
"snapshot_project",
"get_project_info",
// Core PCB operations
"place_component",
"move_component",
"add_net",
"route_trace",
"get_board_info",
"set_board_size",
// Board setup
"add_board_outline",
// Schematic essentials (always visible so AI uses them correctly)
"add_schematic_component",
"list_schematic_components",
"annotate_schematic",
"connect_passthrough",
"connect_to_net",
"add_schematic_net_label",
// Schematic <-> PCB sync (F8 equivalent)
"sync_schematic_to_board",
// UI management
"check_kicad_ui",
];
// Build lookup maps at module load time
const categoryMap = new Map<string, ToolCategory>();
const toolCategoryMap = new Map<string, string>();
export function initializeRegistry() {
// Build category map
for (const category of toolCategories) {
categoryMap.set(category.name, category);
// Build tool -> category map
for (const toolName of category.tools) {
toolCategoryMap.set(toolName, category.name);
}
}
}
/**
* Get a category by name
*/
export function getCategory(name: string): ToolCategory | undefined {
return categoryMap.get(name);
}
/**
* Get the category name for a tool
*/
export function getToolCategory(toolName: string): string | undefined {
return toolCategoryMap.get(toolName);
}
/**
* Get all categories
*/
export function getAllCategories(): ToolCategory[] {
return toolCategories;
}
/**
* Get all routed tool names (excludes direct tools)
*/
export function getRoutedToolNames(): string[] {
const allRoutedTools: string[] = [];
for (const category of toolCategories) {
allRoutedTools.push(...category.tools);
}
return allRoutedTools;
}
/**
* Check if a tool is a direct tool
*/
export function isDirectTool(toolName: string): boolean {
return directToolNames.includes(toolName);
}
/**
* Check if a tool is a routed tool
*/
export function isRoutedTool(toolName: string): boolean {
return toolCategoryMap.has(toolName);
}
/**
* Search for tools by keyword
* Searches tool names, descriptions, and category names
*/
export interface SearchResult {
category: string;
tool: string;
description: string;
}
export function searchTools(query: string): SearchResult[] {
const q = query.toLowerCase();
const matches: SearchResult[] = [];
// Search direct tools first
for (const toolName of directToolNames) {
if (toolName.toLowerCase().includes(q)) {
matches.push({
category: "direct",
tool: toolName,
description: `${toolName} (direct tool — call directly, no execute_tool needed)`,
});
}
}
// Search routed tools by name and category
for (const category of toolCategories) {
const categoryMatch =
category.name.toLowerCase().includes(q) ||
category.description.toLowerCase().includes(q);
for (const toolName of category.tools) {
if (toolName.toLowerCase().includes(q) || categoryMatch) {
matches.push({
category: category.name,
tool: toolName,
description: `${toolName} (${category.name})`,
});
}
}
}
return matches.slice(0, 20); // Limit results
}
/**
* Get statistics about the tool registry
*/
export function getRegistryStats() {
const routedToolCount = getRoutedToolNames().length;
const directToolCount = directToolNames.length;
return {
total_categories: toolCategories.length,
total_routed_tools: routedToolCount,
total_direct_tools: directToolCount,
total_tools: routedToolCount + directToolCount,
categories: toolCategories.map((c) => ({
name: c.name,
tool_count: c.tools.length,
})),
};
}
// Initialize on module load
initializeRegistry();
/**
* Tool Registry for KiCAD MCP Server
*
* Centralizes all tool definitions and provides lookup/search functionality
*/
import { z } from 'zod';
export interface ToolDefinition {
name: string;
description: string;
inputSchema: z.ZodObject<any> | z.ZodType<any>;
// Handler will be registered separately in the existing tool files
}
export interface ToolCategory {
name: string;
description: string;
tools: string[]; // Tool names in this category
}
/**
* Tool category definitions
* Each category groups related tools for better organization
*/
export const toolCategories: ToolCategory[] = [
{
name: "board",
description: "Board configuration: layers, mounting holes, zones, visualization",
tools: [
"add_layer",
"set_active_layer",
"get_layer_list",
"add_mounting_hole",
"add_board_text",
"add_zone",
"get_board_extents",
"get_board_2d_view",
"launch_kicad_ui"
]
},
{
name: "component",
description: "Advanced component operations: edit, delete, search, group, annotate",
tools: [
"rotate_component",
"delete_component",
"edit_component",
"find_component",
"get_component_properties",
"add_component_annotation",
"group_components",
"replace_component"
]
},
{
name: "export",
description: "File export for fabrication and documentation: Gerber, PDF, BOM, 3D models",
tools: [
"export_gerber",
"export_pdf",
"export_svg",
"export_3d",
"export_bom",
"export_netlist",
"export_position_file",
"export_vrml"
]
},
{
name: "drc",
description: "Design rule checking and electrical validation: DRC, net classes, clearances",
tools: [
"set_design_rules",
"get_design_rules",
"run_drc",
"add_net_class",
"assign_net_to_class",
"set_layer_constraints",
"check_clearance",
"get_drc_violations"
]
},
{
name: "schematic",
description: "Schematic operations: create, inspect, add/edit/delete components, wire connections, netlists, annotation",
tools: [
"create_schematic",
"add_schematic_component",
"list_schematic_components",
"move_schematic_component",
"rotate_schematic_component",
"annotate_schematic",
"add_schematic_wire",
"delete_schematic_wire",
"add_schematic_junction",
"add_schematic_net_label",
"delete_schematic_net_label",
"connect_to_net",
"connect_passthrough",
"get_net_connections",
"list_schematic_nets",
"list_schematic_wires",
"list_schematic_labels",
"get_wire_connections",
"generate_netlist",
"sync_schematic_to_board",
"get_schematic_view",
"export_schematic_svg",
"export_schematic_pdf"
]
},
{
name: "library",
description: "Footprint library access: search, browse, get footprint information",
tools: [
"list_libraries",
"search_footprints",
"list_library_footprints",
"get_footprint_info"
]
},
{
name: "routing",
description: "Advanced routing operations: vias, copper pours",
tools: [
"add_via",
"add_copper_pour"
]
},
{
name: "autoroute",
description: "Freerouting autorouter: automatic PCB routing via Specctra DSN/SES",
tools: [
"autoroute",
"export_dsn",
"import_ses",
"check_freerouting"
]
}
];
/**
* Direct tools that are always visible (not routed)
* These are the most frequently used tools
*/
export const directToolNames = [
// Project lifecycle
"create_project",
"open_project",
"save_project",
"snapshot_project",
"get_project_info",
// Core PCB operations
"place_component",
"move_component",
"add_net",
"route_trace",
"get_board_info",
"set_board_size",
// Board setup
"add_board_outline",
// Schematic essentials (always visible so AI uses them correctly)
"add_schematic_component",
"list_schematic_components",
"annotate_schematic",
"connect_passthrough",
"connect_to_net",
"add_schematic_net_label",
// Schematic <-> PCB sync (F8 equivalent)
"sync_schematic_to_board",
// UI management
"check_kicad_ui"
];
// Build lookup maps at module load time
const categoryMap = new Map<string, ToolCategory>();
const toolCategoryMap = new Map<string, string>();
export function initializeRegistry() {
// Build category map
for (const category of toolCategories) {
categoryMap.set(category.name, category);
// Build tool -> category map
for (const toolName of category.tools) {
toolCategoryMap.set(toolName, category.name);
}
}
}
/**
* Get a category by name
*/
export function getCategory(name: string): ToolCategory | undefined {
return categoryMap.get(name);
}
/**
* Get the category name for a tool
*/
export function getToolCategory(toolName: string): string | undefined {
return toolCategoryMap.get(toolName);
}
/**
* Get all categories
*/
export function getAllCategories(): ToolCategory[] {
return toolCategories;
}
/**
* Get all routed tool names (excludes direct tools)
*/
export function getRoutedToolNames(): string[] {
const allRoutedTools: string[] = [];
for (const category of toolCategories) {
allRoutedTools.push(...category.tools);
}
return allRoutedTools;
}
/**
* Check if a tool is a direct tool
*/
export function isDirectTool(toolName: string): boolean {
return directToolNames.includes(toolName);
}
/**
* Check if a tool is a routed tool
*/
export function isRoutedTool(toolName: string): boolean {
return toolCategoryMap.has(toolName);
}
/**
* Search for tools by keyword
* Searches tool names, descriptions, and category names
*/
export interface SearchResult {
category: string;
tool: string;
description: string;
}
export function searchTools(query: string): SearchResult[] {
const q = query.toLowerCase();
const matches: SearchResult[] = [];
// Search direct tools first
for (const toolName of directToolNames) {
if (toolName.toLowerCase().includes(q)) {
matches.push({
category: "direct",
tool: toolName,
description: `${toolName} (direct tool — call directly, no execute_tool needed)`
});
}
}
// Search routed tools by name and category
for (const category of toolCategories) {
const categoryMatch =
category.name.toLowerCase().includes(q) ||
category.description.toLowerCase().includes(q);
for (const toolName of category.tools) {
if (toolName.toLowerCase().includes(q) || categoryMatch) {
matches.push({
category: category.name,
tool: toolName,
description: `${toolName} (${category.name})`
});
}
}
}
return matches.slice(0, 20); // Limit results
}
/**
* Get statistics about the tool registry
*/
export function getRegistryStats() {
const routedToolCount = getRoutedToolNames().length;
const directToolCount = directToolNames.length;
return {
total_categories: toolCategories.length,
total_routed_tools: routedToolCount,
total_direct_tools: directToolCount,
total_tools: routedToolCount + directToolCount,
categories: toolCategories.map(c => ({
name: c.name,
tool_count: c.tools.length
}))
};
}
// Initialize on module load
initializeRegistry();

View File

@@ -161,37 +161,15 @@ preserves the component's position and UUID.
Note: operates on .kicad_sch files only. To modify a PCB footprint use edit_component.`,
{
schematicPath: z.string().describe("Path to the .kicad_sch file"),
reference: z
.string()
.describe(
"Current reference designator of the component (e.g. R1, U3)",
),
footprint: z
.string()
.optional()
.describe(
"New KiCAD footprint string (e.g. Resistor_SMD:R_0603_1608Metric)",
),
value: z
.string()
.optional()
.describe("New value string (e.g. 10k, 100nF)"),
newReference: z
.string()
.optional()
.describe("Rename the reference designator (e.g. R1 → R10)"),
fieldPositions: z
.record(
z.object({
x: z.number(),
y: z.number(),
angle: z.number().optional().default(0),
}),
)
.optional()
.describe(
'Reposition field labels: map of field name to {x, y, angle} (e.g. {"Reference": {"x": 12.5, "y": 17.0}})',
),
reference: z.string().describe("Current reference designator of the component (e.g. R1, U3)"),
footprint: z.string().optional().describe("New KiCAD footprint string (e.g. Resistor_SMD:R_0603_1608Metric)"),
value: z.string().optional().describe("New value string (e.g. 10k, 100nF)"),
newReference: z.string().optional().describe("Rename the reference designator (e.g. R1 → R10)"),
fieldPositions: z.record(z.object({
x: z.number(),
y: z.number(),
angle: z.number().optional().default(0),
})).optional().describe("Reposition field labels: map of field name to {x, y, angle} (e.g. {\"Reference\": {\"x\": 12.5, \"y\": 17.0}})"),
},
async (args: {
schematicPath: string;
@@ -232,9 +210,7 @@ Note: operates on .kicad_sch files only. To modify a PCB footprint use edit_comp
"Get full component info from a schematic: position, field values, and each field's label position (at x/y/angle). Use this to inspect or prepare repositioning of Reference/Value labels.",
{
schematicPath: z.string().describe("Path to the .kicad_sch file"),
reference: z
.string()
.describe("Component reference designator (e.g. R1, U1)"),
reference: z.string().describe("Component reference designator (e.g. R1, U1)"),
},
async (args: { schematicPath: string; reference: string }) => {
const result = await callKicadScript("get_schematic_component", args);
@@ -244,24 +220,20 @@ Note: operates on .kicad_sch files only. To modify a PCB footprint use edit_comp
: "unknown";
const fieldLines = Object.entries(result.fields ?? {}).map(
([name, f]: [string, any]) =>
` ${name}: "${f.value}" @ (${f.x}, ${f.y}, angle=${f.angle}°)`,
` ${name}: "${f.value}" @ (${f.x}, ${f.y}, angle=${f.angle}°)`
);
return {
content: [
{
type: "text",
text: `Component ${result.reference} at ${pos}\nFields:\n${fieldLines.join("\n")}`,
},
],
content: [{
type: "text",
text: `Component ${result.reference} at ${pos}\nFields:\n${fieldLines.join("\n")}`,
}],
};
}
return {
content: [
{
type: "text",
text: `Failed to get component: ${result.message || "Unknown error"}`,
},
],
content: [{
type: "text",
text: `Failed to get component: ${result.message || "Unknown error"}`,
}],
};
},
);
@@ -608,14 +580,8 @@ Note: operates on .kicad_sch files only. To modify a PCB footprint use edit_comp
schematicPath: z.string().describe("Path to the .kicad_sch file"),
filter: z
.object({
libId: z
.string()
.optional()
.describe("Filter by library ID (e.g., 'Device:R')"),
referencePrefix: z
.string()
.optional()
.describe("Filter by reference prefix (e.g., 'R', 'C', 'U')"),
libId: z.string().optional().describe("Filter by library ID (e.g., 'Device:R')"),
referencePrefix: z.string().optional().describe("Filter by reference prefix (e.g., 'R', 'C', 'U')"),
})
.optional()
.describe("Optional filters"),
@@ -629,9 +595,7 @@ Note: operates on .kicad_sch files only. To modify a PCB footprint use edit_comp
const comps = result.components || [];
if (comps.length === 0) {
return {
content: [
{ type: "text", text: "No components found in schematic." },
],
content: [{ type: "text", text: "No components found in schematic." }],
};
}
const lines = comps.map(
@@ -692,10 +656,7 @@ Note: operates on .kicad_sch files only. To modify a PCB footprint use edit_comp
}
return {
content: [
{
type: "text",
text: `Failed to list nets: ${result.message || "Unknown error"}`,
},
{ type: "text", text: `Failed to list nets: ${result.message || "Unknown error"}` },
],
isError: true,
};
@@ -733,10 +694,7 @@ Note: operates on .kicad_sch files only. To modify a PCB footprint use edit_comp
}
return {
content: [
{
type: "text",
text: `Failed to list wires: ${result.message || "Unknown error"}`,
},
{ type: "text", text: `Failed to list wires: ${result.message || "Unknown error"}` },
],
isError: true,
};
@@ -774,10 +732,7 @@ Note: operates on .kicad_sch files only. To modify a PCB footprint use edit_comp
}
return {
content: [
{
type: "text",
text: `Failed to list labels: ${result.message || "Unknown error"}`,
},
{ type: "text", text: `Failed to list labels: ${result.message || "Unknown error"}` },
],
isError: true,
};
@@ -834,7 +789,10 @@ Note: operates on .kicad_sch files only. To modify a PCB footprint use edit_comp
schematicPath: z.string().describe("Path to the .kicad_sch file"),
reference: z.string().describe("Reference designator (e.g., R1, U1)"),
angle: z.number().describe("Rotation angle in degrees (0, 90, 180, 270)"),
mirror: z.enum(["x", "y"]).optional().describe("Optional mirror axis"),
mirror: z
.enum(["x", "y"])
.optional()
.describe("Optional mirror axis"),
},
async (args: {
schematicPath: string;
@@ -1078,14 +1036,8 @@ Note: operates on .kicad_sch files only. To modify a PCB footprint use edit_comp
.enum(["png", "svg"])
.optional()
.describe("Output format (default: png)"),
width: z
.number()
.optional()
.describe("Image width in pixels (default: 1200)"),
height: z
.number()
.optional()
.describe("Image height in pixels (default: 900)"),
width: z.number().optional().describe("Image width in pixels (default: 1200)"),
height: z.number().optional().describe("Image height in pixels (default: 900)"),
},
async (args: {
schematicPath: string;
@@ -1255,35 +1207,19 @@ Note: operates on .kicad_sch files only. To modify a PCB footprint use edit_comp
"get_schematic_view_region",
"Export a cropped region of the schematic as an image (PNG or SVG). Specify bounding box coordinates in schematic mm. Useful for zooming into a specific area to inspect wiring or layout.",
{
schematicPath: z
.string()
.describe("Path to the .kicad_sch schematic file"),
schematicPath: z.string().describe("Path to the .kicad_sch schematic file"),
x1: z.number().describe("Left X coordinate of the region in mm"),
y1: z.number().describe("Top Y coordinate of the region in mm"),
x2: z.number().describe("Right X coordinate of the region in mm"),
y2: z.number().describe("Bottom Y coordinate of the region in mm"),
format: z
.enum(["png", "svg"])
.optional()
.describe("Output image format (default: png)"),
width: z
.number()
.optional()
.describe("Output image width in pixels (default: 800)"),
height: z
.number()
.optional()
.describe("Output image height in pixels (default: 600)"),
format: z.enum(["png", "svg"]).optional().describe("Output image format (default: png)"),
width: z.number().optional().describe("Output image width in pixels (default: 800)"),
height: z.number().optional().describe("Output image height in pixels (default: 600)"),
},
async (args: {
schematicPath: string;
x1: number;
y1: number;
x2: number;
y2: number;
format?: string;
width?: number;
height?: number;
x1: number; y1: number; x2: number; y2: number;
format?: string; width?: number; height?: number;
}) => {
const result = await callKicadScript("get_schematic_view_region", args);
if (result.success && result.imageData) {
@@ -1291,40 +1227,27 @@ Note: operates on .kicad_sch files only. To modify a PCB footprint use edit_comp
return { content: [{ type: "text", text: result.imageData }] };
}
return {
content: [
{
type: "image",
data: result.imageData,
mimeType: "image/png",
},
],
content: [{
type: "image",
data: result.imageData,
mimeType: "image/png",
}],
};
}
return {
content: [
{
type: "text",
text: `Failed: ${result.message || "Unknown error"}`,
},
],
content: [{ type: "text", text: `Failed: ${result.message || "Unknown error"}` }],
};
},
);
// Find overlapping elements
server.tool(
"find_overlapping_elements",
"Detect spatially overlapping symbols, wires, and labels in the schematic. Finds duplicate power symbols at the same position, collinear overlapping wires, and labels stacked on top of each other.",
{
schematicPath: z
.string()
.describe("Path to the .kicad_sch schematic file"),
tolerance: z
.number()
.optional()
.describe(
"Distance threshold in mm for label proximity and wire collinearity checks. Symbol overlap uses bounding-box intersection. (default: 0.5)",
),
schematicPath: z.string().describe("Path to the .kicad_sch schematic file"),
tolerance: z.number().optional().describe("Distance threshold in mm for label proximity and wire collinearity checks. Symbol overlap uses bounding-box intersection. (default: 0.5)"),
},
async (args: { schematicPath: string; tolerance?: number }) => {
const result = await callKicadScript("find_overlapping_elements", args);
@@ -1336,36 +1259,25 @@ Note: operates on .kicad_sch files only. To modify a PCB footprint use edit_comp
if (syms.length) {
lines.push(`\nOverlapping symbols (${syms.length}):`);
syms.slice(0, 20).forEach((o: any) => {
lines.push(
` ${o.element1.reference}${o.element2.reference} (${o.distance}mm) [${o.type}]`,
);
lines.push(` ${o.element1.reference}${o.element2.reference} (${o.distance}mm) [${o.type}]`);
});
}
if (lbls.length) {
lines.push(`\nOverlapping labels (${lbls.length}):`);
lbls.slice(0, 20).forEach((o: any) => {
lines.push(
` "${o.element1.name}" ↔ "${o.element2.name}" (${o.distance}mm)`,
);
lines.push(` "${o.element1.name}" ↔ "${o.element2.name}" (${o.distance}mm)`);
});
}
if (wires.length) {
lines.push(`\nOverlapping wires (${wires.length}):`);
wires.slice(0, 20).forEach((o: any) => {
lines.push(
` wire @ (${o.wire1.start.x},${o.wire1.start.y})→(${o.wire1.end.x},${o.wire1.end.y}) overlaps with another`,
);
lines.push(` wire @ (${o.wire1.start.x},${o.wire1.start.y})→(${o.wire1.end.x},${o.wire1.end.y}) overlaps with another`);
});
}
return { content: [{ type: "text", text: lines.join("\n") }] };
}
return {
content: [
{
type: "text",
text: `Failed: ${result.message || "Unknown error"}`,
},
],
content: [{ type: "text", text: `Failed: ${result.message || "Unknown error"}` }],
};
},
);
@@ -1375,9 +1287,7 @@ Note: operates on .kicad_sch files only. To modify a PCB footprint use edit_comp
"get_elements_in_region",
"List all symbols, wires, and labels within a rectangular region of the schematic. Useful for understanding what is in a specific area before modifying it.",
{
schematicPath: z
.string()
.describe("Path to the .kicad_sch schematic file"),
schematicPath: z.string().describe("Path to the .kicad_sch schematic file"),
x1: z.number().describe("Left X coordinate of the region in mm"),
y1: z.number().describe("Top Y coordinate of the region in mm"),
x2: z.number().describe("Right X coordinate of the region in mm"),
@@ -1385,56 +1295,39 @@ Note: operates on .kicad_sch files only. To modify a PCB footprint use edit_comp
},
async (args: {
schematicPath: string;
x1: number;
y1: number;
x2: number;
y2: number;
x1: number; y1: number; x2: number; y2: number;
}) => {
const result = await callKicadScript("get_elements_in_region", args);
if (result.success) {
const c = result.counts;
const lines = [
`Region (${args.x1},${args.y1})→(${args.x2},${args.y2}): ${c.symbols} symbols, ${c.wires} wires, ${c.labels} labels`,
];
const lines = [`Region (${args.x1},${args.y1})→(${args.x2},${args.y2}): ${c.symbols} symbols, ${c.wires} wires, ${c.labels} labels`];
const syms: any[] = result.symbols || [];
if (syms.length) {
lines.push("\nSymbols:");
syms.forEach((s: any) => {
const pinCount = s.pins ? Object.keys(s.pins).length : 0;
lines.push(
` ${s.reference} (${s.libId}) @ (${s.position.x}, ${s.position.y}) [${pinCount} pins]`,
);
lines.push(` ${s.reference} (${s.libId}) @ (${s.position.x}, ${s.position.y}) [${pinCount} pins]`);
});
}
const wires: any[] = result.wires || [];
if (wires.length) {
lines.push(`\nWires (${wires.length}):`);
wires.slice(0, 30).forEach((w: any) => {
lines.push(
` (${w.start.x},${w.start.y}) → (${w.end.x},${w.end.y})`,
);
lines.push(` (${w.start.x},${w.start.y}) → (${w.end.x},${w.end.y})`);
});
if (wires.length > 30)
lines.push(` ... and ${wires.length - 30} more`);
if (wires.length > 30) lines.push(` ... and ${wires.length - 30} more`);
}
const labels: any[] = result.labels || [];
if (labels.length) {
lines.push(`\nLabels (${labels.length}):`);
labels.forEach((l: any) => {
lines.push(
` "${l.name}" [${l.type}] @ (${l.position.x}, ${l.position.y})`,
);
lines.push(` "${l.name}" [${l.type}] @ (${l.position.x}, ${l.position.y})`);
});
}
return { content: [{ type: "text", text: lines.join("\n") }] };
}
return {
content: [
{
type: "text",
text: `Failed: ${result.message || "Unknown error"}`,
},
],
content: [{ type: "text", text: `Failed: ${result.message || "Unknown error"}` }],
};
},
);
@@ -1444,9 +1337,7 @@ Note: operates on .kicad_sch files only. To modify a PCB footprint use edit_comp
"find_wires_crossing_symbols",
"Find all wires that cross over component symbol bodies. Wires passing over symbols are unacceptable in schematics — they indicate routing mistakes where a wire was drawn across a component instead of around it.",
{
schematicPath: z
.string()
.describe("Path to the .kicad_sch schematic file"),
schematicPath: z.string().describe("Path to the .kicad_sch schematic file"),
},
async (args: { schematicPath: string }) => {
const result = await callKicadScript("find_wires_crossing_symbols", args);
@@ -1455,20 +1346,14 @@ Note: operates on .kicad_sch files only. To modify a PCB footprint use edit_comp
const lines = [`Found ${collisions.length} wire(s) crossing symbols:`];
collisions.slice(0, 30).forEach((c: any, i: number) => {
lines.push(
` ${i + 1}. Wire (${c.wire.start.x},${c.wire.start.y})→(${c.wire.end.x},${c.wire.end.y}) crosses ${c.component.reference} (${c.component.libId})`,
` ${i + 1}. Wire (${c.wire.start.x},${c.wire.start.y})→(${c.wire.end.x},${c.wire.end.y}) crosses ${c.component.reference} (${c.component.libId})`
);
});
if (collisions.length > 30)
lines.push(` ... and ${collisions.length - 30} more`);
if (collisions.length > 30) lines.push(` ... and ${collisions.length - 30} more`);
return { content: [{ type: "text", text: lines.join("\n") }] };
}
return {
content: [
{
type: "text",
text: `Failed: ${result.message || "Unknown error"}`,
},
],
content: [{ type: "text", text: `Failed: ${result.message || "Unknown error"}` }],
};
},
);