- Implement 3D model analysis and mechanical constraints checking - Add advanced DRC rule customization for HDI, RF, and automotive applications - Create symbol library management with analysis and validation tools - Implement PCB layer stack-up analysis with impedance calculations - Fix Context parameter validation errors causing client failures - Add enhanced tool annotations with examples for better LLM compatibility - Include comprehensive test coverage improvements (22.21% coverage) - Add CLAUDE.md documentation for development guidance New Advanced Tools: • 3D model analysis: analyze_3d_models, check_mechanical_constraints • Advanced DRC: create_drc_rule_set, analyze_pcb_drc_violations • Symbol management: analyze_symbol_library, validate_symbol_library • Layer analysis: analyze_pcb_stackup, calculate_trace_impedance 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
334 lines
14 KiB
Python
334 lines
14 KiB
Python
"""
|
|
3D Model Analysis Tools for KiCad MCP Server.
|
|
|
|
Provides MCP tools for analyzing 3D models, mechanical constraints,
|
|
and visualization data from KiCad PCB files.
|
|
"""
|
|
|
|
import json
|
|
from typing import Any, Dict
|
|
|
|
from fastmcp import FastMCP
|
|
from kicad_mcp.utils.model3d_analyzer import (
|
|
analyze_pcb_3d_models,
|
|
get_mechanical_constraints,
|
|
Model3DAnalyzer
|
|
)
|
|
from kicad_mcp.utils.path_validator import validate_kicad_file
|
|
|
|
|
|
def register_model3d_tools(mcp: FastMCP) -> None:
|
|
"""Register 3D model analysis tools with the MCP server."""
|
|
|
|
@mcp.tool()
|
|
def analyze_3d_models(pcb_file_path: str) -> Dict[str, Any]:
|
|
"""
|
|
Analyze 3D models and mechanical aspects of a KiCad PCB file.
|
|
|
|
Extracts 3D component information, board dimensions, clearance violations,
|
|
and generates data suitable for 3D visualization.
|
|
|
|
Args:
|
|
pcb_file_path: Full path to the .kicad_pcb file to analyze
|
|
|
|
Returns:
|
|
Dictionary containing 3D analysis results including:
|
|
- board_dimensions: Physical board size and outline
|
|
- components: List of 3D components with positions and models
|
|
- height_analysis: Component height statistics
|
|
- clearance_violations: Detected mechanical issues
|
|
- stats: Summary statistics
|
|
|
|
Examples:
|
|
analyze_3d_models("/path/to/my_board.kicad_pcb")
|
|
analyze_3d_models("~/kicad_projects/robot_controller/robot.kicad_pcb")
|
|
"""
|
|
try:
|
|
# Validate the PCB file path
|
|
validated_path = validate_kicad_file(pcb_file_path, "pcb")
|
|
|
|
# Perform 3D analysis
|
|
result = analyze_pcb_3d_models(validated_path)
|
|
|
|
return {
|
|
"success": True,
|
|
"pcb_file": validated_path,
|
|
"analysis": result
|
|
}
|
|
|
|
except Exception as e:
|
|
return {
|
|
"success": False,
|
|
"error": str(e),
|
|
"pcb_file": pcb_file_path
|
|
}
|
|
|
|
@mcp.tool()
|
|
def check_mechanical_constraints(pcb_file_path: str) -> Dict[str, Any]:
|
|
"""
|
|
Check mechanical constraints and clearances in a KiCad PCB.
|
|
|
|
Performs comprehensive mechanical analysis including component clearances,
|
|
board edge distances, height constraints, and identifies potential
|
|
manufacturing or assembly issues.
|
|
|
|
Args:
|
|
pcb_file_path: Path to the .kicad_pcb file to analyze
|
|
|
|
Returns:
|
|
Dictionary containing mechanical analysis results:
|
|
- constraints: List of constraint violations
|
|
- clearance_violations: Detailed clearance issues
|
|
- board_dimensions: Physical board properties
|
|
- recommendations: Suggested improvements
|
|
"""
|
|
try:
|
|
validated_path = validate_kicad_file(pcb_file_path, "pcb")
|
|
|
|
# Perform mechanical analysis
|
|
analysis = get_mechanical_constraints(validated_path)
|
|
|
|
# Generate recommendations
|
|
recommendations = []
|
|
|
|
if analysis.height_analysis["max"] > 5.0:
|
|
recommendations.append("Consider using lower profile components to reduce board height")
|
|
|
|
if len(analysis.clearance_violations) > 0:
|
|
recommendations.append("Review component placement to resolve clearance violations")
|
|
|
|
if analysis.board_dimensions.width > 80 or analysis.board_dimensions.height > 80:
|
|
recommendations.append("Large board size may increase manufacturing costs")
|
|
|
|
return {
|
|
"success": True,
|
|
"pcb_file": validated_path,
|
|
"constraints": analysis.mechanical_constraints,
|
|
"clearance_violations": [
|
|
{
|
|
"type": v["type"],
|
|
"components": [v.get("component1", ""), v.get("component2", ""), v.get("component", "")],
|
|
"distance": v["distance"],
|
|
"required": v["required_clearance"],
|
|
"severity": v["severity"]
|
|
}
|
|
for v in analysis.clearance_violations
|
|
],
|
|
"board_dimensions": {
|
|
"width_mm": analysis.board_dimensions.width,
|
|
"height_mm": analysis.board_dimensions.height,
|
|
"thickness_mm": analysis.board_dimensions.thickness,
|
|
"area_mm2": analysis.board_dimensions.width * analysis.board_dimensions.height
|
|
},
|
|
"height_analysis": analysis.height_analysis,
|
|
"recommendations": recommendations,
|
|
"component_count": len(analysis.components)
|
|
}
|
|
|
|
except Exception as e:
|
|
return {
|
|
"success": False,
|
|
"error": str(e),
|
|
"pcb_file": pcb_file_path
|
|
}
|
|
|
|
@mcp.tool()
|
|
def generate_3d_visualization_json(pcb_file_path: str, output_path: str = None) -> Dict[str, Any]:
|
|
"""
|
|
Generate JSON data file for 3D visualization of PCB.
|
|
|
|
Creates a structured JSON file containing all necessary data for
|
|
3D visualization tools, including component positions, board outline,
|
|
and model references.
|
|
|
|
Args:
|
|
pcb_file_path: Path to the .kicad_pcb file
|
|
output_path: Optional path for output JSON file (defaults to same dir as PCB)
|
|
|
|
Returns:
|
|
Dictionary with generation results and file path
|
|
"""
|
|
try:
|
|
validated_path = validate_kicad_file(pcb_file_path, "pcb")
|
|
|
|
# Generate visualization data
|
|
viz_data = analyze_pcb_3d_models(validated_path)
|
|
|
|
# Determine output path
|
|
if not output_path:
|
|
output_path = validated_path.replace('.kicad_pcb', '_3d_viz.json')
|
|
|
|
# Save visualization data
|
|
with open(output_path, 'w', encoding='utf-8') as f:
|
|
json.dump(viz_data, f, indent=2)
|
|
|
|
return {
|
|
"success": True,
|
|
"pcb_file": validated_path,
|
|
"output_file": output_path,
|
|
"component_count": viz_data.get("stats", {}).get("total_components", 0),
|
|
"models_found": viz_data.get("stats", {}).get("components_with_3d_models", 0),
|
|
"board_size": f"{viz_data.get('board_dimensions', {}).get('width', 0):.1f}x{viz_data.get('board_dimensions', {}).get('height', 0):.1f}mm"
|
|
}
|
|
|
|
except Exception as e:
|
|
return {
|
|
"success": False,
|
|
"error": str(e),
|
|
"pcb_file": pcb_file_path
|
|
}
|
|
|
|
@mcp.tool()
|
|
def component_height_distribution(pcb_file_path: str) -> Dict[str, Any]:
|
|
"""
|
|
Analyze the height distribution of components on a PCB.
|
|
|
|
Provides detailed analysis of component heights, useful for
|
|
determining enclosure requirements and assembly considerations.
|
|
|
|
Args:
|
|
pcb_file_path: Path to the .kicad_pcb file
|
|
|
|
Returns:
|
|
Height distribution analysis with statistics and component breakdown
|
|
"""
|
|
try:
|
|
validated_path = validate_kicad_file(pcb_file_path, "pcb")
|
|
|
|
analyzer = Model3DAnalyzer(validated_path)
|
|
components = analyzer.extract_3d_components()
|
|
height_analysis = analyzer.analyze_component_heights(components)
|
|
|
|
# Categorize components by height
|
|
height_categories = {
|
|
"very_low": [], # < 1mm
|
|
"low": [], # 1-2mm
|
|
"medium": [], # 2-5mm
|
|
"high": [], # 5-10mm
|
|
"very_high": [] # > 10mm
|
|
}
|
|
|
|
for comp in components:
|
|
height = analyzer._estimate_component_height(comp)
|
|
|
|
if height < 1.0:
|
|
height_categories["very_low"].append((comp.reference, height))
|
|
elif height < 2.0:
|
|
height_categories["low"].append((comp.reference, height))
|
|
elif height < 5.0:
|
|
height_categories["medium"].append((comp.reference, height))
|
|
elif height < 10.0:
|
|
height_categories["high"].append((comp.reference, height))
|
|
else:
|
|
height_categories["very_high"].append((comp.reference, height))
|
|
|
|
return {
|
|
"success": True,
|
|
"pcb_file": validated_path,
|
|
"height_statistics": height_analysis,
|
|
"height_categories": {
|
|
category: [{"component": ref, "height_mm": height}
|
|
for ref, height in components]
|
|
for category, components in height_categories.items()
|
|
},
|
|
"tallest_components": sorted(
|
|
[(comp.reference, analyzer._estimate_component_height(comp))
|
|
for comp in components],
|
|
key=lambda x: x[1], reverse=True
|
|
)[:10], # Top 10 tallest components
|
|
"enclosure_requirements": {
|
|
"minimum_height_mm": height_analysis["max"] + 2.0, # Add 2mm clearance
|
|
"recommended_height_mm": height_analysis["max"] + 5.0 # Add 5mm clearance
|
|
}
|
|
}
|
|
|
|
except Exception as e:
|
|
return {
|
|
"success": False,
|
|
"error": str(e),
|
|
"pcb_file": pcb_file_path
|
|
}
|
|
|
|
@mcp.tool()
|
|
def check_assembly_feasibility(pcb_file_path: str) -> Dict[str, Any]:
|
|
"""
|
|
Analyze PCB assembly feasibility and identify potential issues.
|
|
|
|
Checks for component accessibility, assembly sequence issues,
|
|
and manufacturing constraints that could affect PCB assembly.
|
|
|
|
Args:
|
|
pcb_file_path: Path to the .kicad_pcb file
|
|
|
|
Returns:
|
|
Assembly feasibility analysis with issues and recommendations
|
|
"""
|
|
try:
|
|
validated_path = validate_kicad_file(pcb_file_path, "pcb")
|
|
|
|
analyzer = Model3DAnalyzer(validated_path)
|
|
mechanical_analysis = analyzer.perform_mechanical_analysis()
|
|
components = mechanical_analysis.components
|
|
|
|
assembly_issues = []
|
|
assembly_warnings = []
|
|
|
|
# Check for components too close to board edge
|
|
for comp in components:
|
|
edge_distance = analyzer._distance_to_board_edge(
|
|
comp, mechanical_analysis.board_dimensions
|
|
)
|
|
if edge_distance < 1.0: # Less than 1mm from edge
|
|
assembly_warnings.append({
|
|
"component": comp.reference,
|
|
"issue": f"Component only {edge_distance:.2f}mm from board edge",
|
|
"recommendation": "Consider moving component away from edge for easier assembly"
|
|
})
|
|
|
|
# Check for very small components that might be hard to place
|
|
small_component_footprints = ["0201", "0402"]
|
|
for comp in components:
|
|
if any(size in (comp.footprint or "") for size in small_component_footprints):
|
|
assembly_warnings.append({
|
|
"component": comp.reference,
|
|
"issue": f"Very small footprint {comp.footprint}",
|
|
"recommendation": "Verify pick-and-place machine compatibility"
|
|
})
|
|
|
|
# Check component density
|
|
board_area = (mechanical_analysis.board_dimensions.width *
|
|
mechanical_analysis.board_dimensions.height)
|
|
component_density = len(components) / (board_area / 100) # Components per cm²
|
|
|
|
if component_density > 5.0:
|
|
assembly_warnings.append({
|
|
"component": "Board",
|
|
"issue": f"High component density: {component_density:.1f} components/cm²",
|
|
"recommendation": "Consider larger board or fewer components for easier assembly"
|
|
})
|
|
|
|
return {
|
|
"success": True,
|
|
"pcb_file": validated_path,
|
|
"assembly_feasible": len(assembly_issues) == 0,
|
|
"assembly_issues": assembly_issues,
|
|
"assembly_warnings": assembly_warnings,
|
|
"component_density": component_density,
|
|
"board_utilization": {
|
|
"component_count": len(components),
|
|
"board_area_mm2": board_area,
|
|
"density_per_cm2": component_density
|
|
},
|
|
"recommendations": [
|
|
"Review component placement for optimal assembly sequence",
|
|
"Ensure adequate fiducial markers for automated assembly",
|
|
"Consider component orientation for consistent placement direction"
|
|
] if assembly_warnings else ["PCB appears suitable for standard assembly processes"]
|
|
}
|
|
|
|
except Exception as e:
|
|
return {
|
|
"success": False,
|
|
"error": str(e),
|
|
"pcb_file": pcb_file_path
|
|
} |