""" CadQuery MCP Server Ermöglicht Claude, CadQuery-Python-Code auszuführen und STL-Dateien zu erzeugen. """ import os import sys import tempfile import base64 import traceback from pathlib import Path from mcp.server.fastmcp import FastMCP import cadquery as cq from cadquery import exporters _default_output = Path(__file__).parent / "models" OUTPUT_DIR = Path(os.environ.get("CADQUERY_OUTPUT_DIR", _default_output)) OUTPUT_DIR.mkdir(parents=True, exist_ok=True) mcp = FastMCP("cadquery") def _run_cadquery(code: str) -> cq.Workplane: """Führt CadQuery-Code aus und gibt das Ergebnis zurück.""" captured = {} def show_object(obj, name="result", options=None): captured["result"] = obj def show(obj, name="result", options=None): captured["result"] = obj namespace = { "cq": cq, "cadquery": cq, "show_object": show_object, "show": show, } exec(code, namespace) # noqa: S102 if "result" in captured: return captured["result"] # Letzte Variable suchen, die ein Workplane oder Shape ist for val in reversed(list(namespace.values())): if isinstance(val, (cq.Workplane, cq.Shape, cq.Assembly)): return val raise ValueError( "Kein CadQuery-Objekt gefunden. " "Bitte 'show_object(result)' am Ende des Codes aufrufen " "oder das Ergebnis in eine Variable namens 'result' speichern." ) @mcp.tool() def render_stl(code: str, filename: str = "model.stl") -> str: """ Rendert CadQuery-Python-Code als STL-Datei für den 3D-Drucker. Args: code: Gültiger CadQuery-Python-Code filename: Dateiname für die STL-Ausgabe (z.B. "halter.stl") Returns: Pfad zur erzeugten STL-Datei oder Fehlermeldung """ if not filename.endswith(".stl"): filename += ".stl" output_path = OUTPUT_DIR / filename try: result = _run_cadquery(code) exporters.export(result, str(output_path)) size_kb = output_path.stat().st_size // 1024 return f"STL erfolgreich erstellt: {output_path}\nDateigröße: {size_kb} KB" except Exception as e: return f"Fehler beim Rendern:\n{traceback.format_exc()}\nBitte CadQuery-Code prüfen." @mcp.tool() def preview_png(code: str, filename: str = "preview.png") -> str: """ Rendert eine PNG-Vorschau des CadQuery-Modells. Args: code: Gültiger CadQuery-Python-Code filename: Dateiname für die PNG-Ausgabe Returns: Base64-kodiertes PNG-Bild oder Fehlermeldung """ if not filename.endswith(".png"): filename += ".png" svg_path = OUTPUT_DIR / filename.replace(".png", ".svg") output_path = OUTPUT_DIR / filename try: result = _run_cadquery(code) exporters.export(result, str(svg_path)) size_bytes = svg_path.stat().st_size return f"SVG-Vorschau erstellt: {svg_path} ({size_bytes} Bytes)\n(PNG-Konvertierung erfordert zusätzliche Abhängigkeiten)" except Exception as e: return f"Fehler beim Rendern der Vorschau:\n{traceback.format_exc()}" @mcp.tool() def list_models() -> str: """Listet alle bisher erstellten 3D-Modelle im Output-Verzeichnis.""" files = list(OUTPUT_DIR.glob("*.stl")) if not files: return f"Keine STL-Dateien in {OUTPUT_DIR}" lines = [f"Modelle in {OUTPUT_DIR}:"] for f in sorted(files): size_kb = f.stat().st_size // 1024 lines.append(f" {f.name} ({size_kb} KB)") return "\n".join(lines) if __name__ == "__main__": mcp.run()