fix: add pin-snapping and coordinate feedback to net label tools

add_schematic_net_label now accepts optional componentRef + pinNumber to
snap the label directly to the exact pin endpoint via PinLocator, removing
all approximation risk.  The response always includes actual_position and,
when snapping was used, snapped_to_pin — so the caller gets confirmation
of exactly where the label landed.

connect_to_net return type changed from bool to Dict, returning
pin_location, label_location, and wire_stub on success so agents no
longer need a separate verification call to confirm placement.

connect_passthrough updated to check result.get("success") against the
new dict return.  tool_schemas.py and schematic.ts updated to match
(position is now optional, componentRef/pinNumber/labelType/orientation
added, connect_to_net schema field names corrected).

17 new unit tests in tests/test_net_label_pin_snapping.py.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Eugene Mikhantyev
2026-04-12 14:12:11 +01:00
parent 0bf73674da
commit 94125eda7f
5 changed files with 481 additions and 55 deletions

View File

@@ -325,20 +325,55 @@ Note: operates on .kicad_sch files only. To modify a PCB footprint use edit_comp
// Add net label
server.tool(
"add_schematic_net_label",
"Add a net label to the schematic",
"Add a net label to the schematic. " +
"PREFERRED: supply componentRef + pinNumber to snap the label to the exact pin endpoint — " +
"this guarantees an electrical connection. " +
"Alternatively supply position [x, y], but the coordinates must match the pin endpoint exactly " +
"(even a 0.01 mm offset breaks the connection). " +
"The response includes actual_position (coordinates actually used) and snapped_to_pin " +
"(present when a pin reference was resolved).",
{
schematicPath: z.string().describe("Path to the schematic file"),
netName: z.string().describe("Name of the net (e.g., VCC, GND, SIGNAL_1)"),
position: z.array(z.number()).length(2).describe("Position [x, y] for the label"),
position: z
.array(z.number())
.length(2)
.optional()
.describe(
"Position [x, y] for the label. Required when componentRef/pinNumber are not given.",
),
componentRef: z
.string()
.optional()
.describe("Component reference to snap label to (e.g. U1, R1). Use with pinNumber."),
pinNumber: z
.union([z.string(), z.number()])
.optional()
.describe(
"Pin number or name on componentRef to snap label to (e.g. '1', 'GND'). Use with componentRef.",
),
labelType: z
.enum(["label", "global_label", "hierarchical_label"])
.optional()
.describe("Label type (default: label)"),
orientation: z.number().optional().describe("Rotation angle 0/90/180/270 (default: 0)"),
},
async (args: { schematicPath: string; netName: string; position: number[] }) => {
async (args: {
schematicPath: string;
netName: string;
position?: number[];
componentRef?: string;
pinNumber?: string | number;
labelType?: string;
orientation?: number;
}) => {
const result = await callKicadScript("add_schematic_net_label", args);
if (result.success) {
return {
content: [
{
type: "text",
text: `Successfully added net label '${args.netName}' at position [${args.position}]`,
text: JSON.stringify(result, null, 2),
},
],
};
@@ -358,7 +393,9 @@ Note: operates on .kicad_sch files only. To modify a PCB footprint use edit_comp
// Connect pin to net
server.tool(
"connect_to_net",
"Connect a component pin to a named net",
"Connect a component pin to a named net by adding a wire stub and net label at the exact pin endpoint. " +
"The response includes pin_location (exact pin coords), label_location (where the label was placed), " +
"and wire_stub (the wire segment added) so you can confirm the placement.",
{
schematicPath: z.string().describe("Path to the schematic file"),
componentRef: z.string().describe("Component reference (e.g., U1, R1)"),
@@ -377,7 +414,7 @@ Note: operates on .kicad_sch files only. To modify a PCB footprint use edit_comp
content: [
{
type: "text",
text: `Successfully connected ${args.componentRef}/${args.pinName} to net '${args.netName}'`,
text: JSON.stringify(result, null, 2),
},
],
};