Update repository with project files and documentation

- Added comprehensive documentation (BUILD_AND_TEST, CLIENT_CONFIG, KNOWN_ISSUES, ROADMAP, etc.)
- Updated core functionality for board outline, size, and utilities
- Added new tools for project, routing, schematic, and UI management
- Included TypeScript SDK with full MCP implementation
- Updated configuration examples for all platforms
- Added changelog and status tracking
- Improved Python utilities with KiCAD process management
- Enhanced resource helpers and server capabilities

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
KiCAD MCP Bot
2025-11-01 19:30:39 -04:00
parent e4c7119c51
commit 89247fffe0
194 changed files with 52486 additions and 77 deletions

View File

@@ -107,11 +107,11 @@ export function registerLibraryResources(server: McpServer, callKicadScript: Com
);
// ------------------------------------------------------
// Component Details Resource
// Library Component Details Resource
// ------------------------------------------------------
server.resource(
"component_details",
new ResourceTemplate("kicad://component/{componentId}/{library?}", {
"library_component_details",
new ResourceTemplate("kicad://library/component/{componentId}/{library?}", {
list: undefined
}),
async (uri, params) => {

View File

@@ -7,6 +7,7 @@ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
import express from 'express';
import { spawn, ChildProcess } from 'child_process';
import { existsSync } from 'fs';
import { join, dirname } from 'path';
import { logger } from './logger.js';
// Import tool registration functions
@@ -16,6 +17,7 @@ import { registerComponentTools } from './tools/component.js';
import { registerRoutingTools } from './tools/routing.js';
import { registerDesignRuleTools } from './tools/design-rules.js';
import { registerExportTools } from './tools/export.js';
import { registerUITools } from './tools/ui.js';
// Import resource registration functions
import { registerProjectResources } from './resources/project.js';
@@ -28,6 +30,46 @@ import { registerComponentPrompts } from './prompts/component.js';
import { registerRoutingPrompts } from './prompts/routing.js';
import { registerDesignPrompts } from './prompts/design.js';
/**
* Find the Python executable to use
* Prioritizes virtual environment if available, falls back to system Python
*/
function findPythonExecutable(scriptPath: string): string {
const isWindows = process.platform === 'win32';
// Get the project root (parent of the python/ directory)
const projectRoot = dirname(dirname(scriptPath));
// Check for virtual environment
const venvPaths = [
join(projectRoot, 'venv', isWindows ? 'Scripts' : 'bin', isWindows ? 'python.exe' : 'python'),
join(projectRoot, '.venv', isWindows ? 'Scripts' : 'bin', isWindows ? 'python.exe' : 'python'),
];
for (const venvPath of venvPaths) {
if (existsSync(venvPath)) {
logger.info(`Found virtual environment Python at: ${venvPath}`);
return venvPath;
}
}
// Fall back to system Python or environment-specified Python
if (isWindows && process.env.KICAD_PYTHON) {
// Allow override via KICAD_PYTHON environment variable
return process.env.KICAD_PYTHON;
} else if (isWindows && process.env.PYTHONPATH?.includes('KiCad')) {
// Windows: Try KiCAD's bundled Python
const kicadPython = 'C:\\Program Files\\KiCad\\9.0\\bin\\python.exe';
if (existsSync(kicadPython)) {
return kicadPython;
}
}
// Default to system Python
logger.info('Using system Python (no venv found)');
return isWindows ? 'python.exe' : 'python3';
}
/**
* KiCAD MCP Server class
*/
@@ -85,6 +127,7 @@ export class KiCADMcpServer {
registerRoutingTools(this.server, this.callKicadScript.bind(this));
registerDesignRuleTools(this.server, this.callKicadScript.bind(this));
registerExportTools(this.server, this.callKicadScript.bind(this));
registerUITools(this.server, this.callKicadScript.bind(this));
// Register all resources
registerProjectResources(this.server, this.callKicadScript.bind(this));
@@ -109,9 +152,8 @@ export class KiCADMcpServer {
// Start the Python process for KiCAD scripting
logger.info(`Starting Python process with script: ${this.kicadScriptPath}`);
const pythonExe = process.env.PYTHONPATH ?
'C:\\Program Files\\KiCad\\9.0\\bin\\python.exe' : 'python';
const pythonExe = findPythonExecutable(this.kicadScriptPath);
logger.info(`Using Python executable: ${pythonExe}`);
this.pythonProcess = spawn(pythonExe, [this.kicadScriptPath], {
stdio: ['pipe', 'pipe', 'pipe'],

View File

@@ -167,11 +167,15 @@ export function registerBoardTools(server: McpServer, callKicadScript: CommandFu
},
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;
const result = await callKicadScript("add_board_outline", {
shape,
params
centerX: x,
centerY: y,
...otherParams
});
return {
content: [{
type: "text",

79
src/tools/project.ts Normal file
View File

@@ -0,0 +1,79 @@
/**
* Project management tools for KiCAD MCP server
*/
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { z } from 'zod';
export function registerProjectTools(server: McpServer, callKicadScript: Function) {
// Create project tool
server.tool(
"create_project",
"Create a new KiCAD project",
{
path: z.string().describe("Project directory path"),
name: z.string().describe("Project name"),
},
async (args: { path: string; name: string }) => {
const result = await callKicadScript("create_project", args);
return {
content: [{
type: "text",
text: JSON.stringify(result, null, 2)
}]
};
}
);
// Open project tool
server.tool(
"open_project",
"Open an existing KiCAD project",
{
filename: z.string().describe("Path to .kicad_pro or .kicad_pcb file"),
},
async (args: { filename: string }) => {
const result = await callKicadScript("open_project", args);
return {
content: [{
type: "text",
text: JSON.stringify(result, null, 2)
}]
};
}
);
// Save project tool
server.tool(
"save_project",
"Save the current KiCAD project",
{
path: z.string().optional().describe("Optional new path to save to"),
},
async (args: { path?: string }) => {
const result = await callKicadScript("save_project", args);
return {
content: [{
type: "text",
text: JSON.stringify(result, null, 2)
}]
};
}
);
// Get project info tool
server.tool(
"get_project_info",
"Get information about the current KiCAD project",
{},
async () => {
const result = await callKicadScript("get_project_info", {});
return {
content: [{
type: "text",
text: JSON.stringify(result, null, 2)
}]
};
}
);
}

101
src/tools/routing.ts Normal file
View File

@@ -0,0 +1,101 @@
/**
* Routing tools for KiCAD MCP server
*/
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { z } from 'zod';
export function registerRoutingTools(server: McpServer, callKicadScript: Function) {
// Add net tool
server.tool(
"add_net",
"Create a new net on the PCB",
{
name: z.string().describe("Net name"),
netClass: z.string().optional().describe("Net class name"),
},
async (args: { name: string; netClass?: string }) => {
const result = await callKicadScript("add_net", args);
return {
content: [{
type: "text",
text: JSON.stringify(result, null, 2)
}]
};
}
);
// Route trace tool
server.tool(
"route_trace",
"Route a trace between two points",
{
start: z.object({
x: z.number(),
y: z.number(),
unit: z.string().optional()
}).describe("Start position"),
end: z.object({
x: z.number(),
y: z.number(),
unit: z.string().optional()
}).describe("End position"),
layer: z.string().describe("PCB layer"),
width: z.number().describe("Trace width in mm"),
net: z.string().describe("Net name"),
},
async (args: any) => {
const result = await callKicadScript("route_trace", args);
return {
content: [{
type: "text",
text: JSON.stringify(result, null, 2)
}]
};
}
);
// Add via tool
server.tool(
"add_via",
"Add a via to the PCB",
{
position: z.object({
x: z.number(),
y: z.number(),
unit: z.string().optional()
}).describe("Via position"),
net: z.string().describe("Net name"),
viaType: z.string().optional().describe("Via type (through, blind, buried)"),
},
async (args: any) => {
const result = await callKicadScript("add_via", args);
return {
content: [{
type: "text",
text: JSON.stringify(result, null, 2)
}]
};
}
);
// Add copper pour tool
server.tool(
"add_copper_pour",
"Add a copper pour (ground/power plane) to the PCB",
{
layer: z.string().describe("PCB layer"),
net: z.string().describe("Net name"),
clearance: z.number().optional().describe("Clearance in mm"),
},
async (args: any) => {
const result = await callKicadScript("add_copper_pour", args);
return {
content: [{
type: "text",
text: JSON.stringify(result, null, 2)
}]
};
}
);
}

76
src/tools/schematic.ts Normal file
View File

@@ -0,0 +1,76 @@
/**
* Schematic tools for KiCAD MCP server
*/
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { z } from 'zod';
export function registerSchematicTools(server: McpServer, callKicadScript: Function) {
// Create schematic tool
server.tool(
"create_schematic",
"Create a new schematic",
{
name: z.string().describe("Schematic name"),
path: z.string().optional().describe("Optional path"),
},
async (args: { name: string; path?: string }) => {
const result = await callKicadScript("create_schematic", args);
return {
content: [{
type: "text",
text: JSON.stringify(result, null, 2)
}]
};
}
);
// Add component to schematic
server.tool(
"add_schematic_component",
"Add a component to the schematic",
{
symbol: z.string().describe("Symbol library reference"),
reference: z.string().describe("Component reference (e.g., R1, U1)"),
value: z.string().optional().describe("Component value"),
position: z.object({
x: z.number(),
y: z.number()
}).optional().describe("Position on schematic"),
},
async (args: any) => {
const result = await callKicadScript("add_schematic_component", args);
return {
content: [{
type: "text",
text: JSON.stringify(result, null, 2)
}]
};
}
);
// Connect components with wire
server.tool(
"add_wire",
"Add a wire connection in the schematic",
{
start: z.object({
x: z.number(),
y: z.number()
}).describe("Start position"),
end: z.object({
x: z.number(),
y: z.number()
}).describe("End position"),
},
async (args: any) => {
const result = await callKicadScript("add_wire", args);
return {
content: [{
type: "text",
text: JSON.stringify(result, null, 2)
}]
};
}
);
}

48
src/tools/ui.ts Normal file
View File

@@ -0,0 +1,48 @@
/**
* UI/Process management tools for KiCAD MCP server
*/
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { z } from 'zod';
import { logger } from '../logger.js';
export function registerUITools(server: McpServer, callKicadScript: Function) {
// Check if KiCAD UI is running
server.tool(
"check_kicad_ui",
"Check if KiCAD UI is currently running",
{},
async () => {
logger.info('Checking KiCAD UI status');
const result = await callKicadScript("check_kicad_ui", {});
return {
content: [{
type: "text",
text: JSON.stringify(result, null, 2)
}]
};
}
);
// Launch KiCAD UI
server.tool(
"launch_kicad_ui",
"Launch KiCAD UI, optionally with a project file",
{
projectPath: z.string().optional().describe("Optional path to .kicad_pcb file to open"),
autoLaunch: z.boolean().optional().describe("Whether to launch KiCAD if not running (default: true)")
},
async (args: { projectPath?: string; autoLaunch?: boolean }) => {
logger.info(`Launching KiCAD UI${args.projectPath ? ' with project: ' + args.projectPath : ''}`);
const result = await callKicadScript("launch_kicad_ui", args);
return {
content: [{
type: "text",
text: JSON.stringify(result, null, 2)
}]
};
}
);
logger.info('UI management tools registered');
}

View File

@@ -0,0 +1,61 @@
/**
* Resource helper utilities for MCP resources
*/
/**
* Create a JSON response for MCP resources
*
* @param data Data to serialize as JSON
* @param uri Optional URI for the resource
* @returns MCP resource response object
*/
export function createJsonResponse(data: any, uri?: string) {
return {
contents: [{
uri: uri || "data:application/json",
mimeType: "application/json",
text: JSON.stringify(data, null, 2)
}]
};
}
/**
* Create a binary response for MCP resources
*
* @param data Binary data (Buffer or base64 string)
* @param mimeType MIME type of the binary data
* @param uri Optional URI for the resource
* @returns MCP resource response object
*/
export function createBinaryResponse(data: Buffer | string, mimeType: string, uri?: string) {
const blob = typeof data === 'string' ? data : data.toString('base64');
return {
contents: [{
uri: uri || `data:${mimeType}`,
mimeType: mimeType,
blob: blob
}]
};
}
/**
* Create an error response for MCP resources
*
* @param error Error message
* @param details Optional error details
* @param uri Optional URI for the resource
* @returns MCP resource error response
*/
export function createErrorResponse(error: string, details?: string, uri?: string) {
return {
contents: [{
uri: uri || "data:application/json",
mimeType: "application/json",
text: JSON.stringify({
error,
details
}, null, 2)
}]
};
}