Files
Thorsten 77eb5379d2 Initial commit: OpenSCAD MCP server for Claude Code
MCP server that lets Claude generate and render OpenSCAD models to STL files.
Includes setup documentation and installation guide.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 16:00:24 +01:00

8.6 KiB

OpenSCAD MCP Server — Installationsanleitung

LLM-gestützte 3D-Modell-Erstellung: Claude generiert OpenSCAD-Code und rendert ihn direkt zu STL-Dateien für den 3D-Drucker.


Voraussetzungen

  • Windows 10/11
  • Claude Code Desktop App installiert
  • Python (Microsoft Store) — bereits installiert auf diesem System

Schritt 1: OpenSCAD installieren

  1. https://openscad.org/downloads.html aufrufen
  2. Windows Installer herunterladen und ausführen
  3. Standardpfad bestätigen: C:\Program Files\OpenSCAD\

Verifizieren:

"C:\Program Files\OpenSCAD\openscad.exe" --version

Erwartete Ausgabe: OpenSCAD version 2021.01 (oder neuer)


Schritt 2: Projektverzeichnis anlegen

mkdir C:\Users\<USERNAME>\Documents\Claude\openscad-mcp

Schritt 3: Python Virtual Environment erstellen

Wichtig: Den Microsoft Store Python verwenden (python3.13.exe in WindowsApps). Das python.exe aus C:\Users\...\AppData\Local\Programs\Python\Python313\ ist ein eingebettetes Python ohne pip und funktioniert nicht. Die WindowsApps\python3.13.exe ist ein App Execution Alias — funktioniert nur in interaktiven Shells, nicht als Subprocess von Claude Code. Lösung: Virtual Environment erstellen — das .venv\Scripts\python.exe ist eine echte Executable ohne diese Einschränkung.

cd C:\Users\<USERNAME>\Documents\Claude\openscad-mcp

"C:\Users\<USERNAME>\AppData\Local\Microsoft\WindowsApps\python3.13.exe" -m venv .venv

.venv\Scripts\pip install mcp

Verifizieren:

.venv\Scripts\python.exe -c "from mcp.server.fastmcp import FastMCP; print('OK')"

Schritt 4: MCP-Server erstellen

Datei C:\Users\<USERNAME>\Documents\Claude\openscad-mcp\server.py:

"""
OpenSCAD MCP Server
Ermöglicht Claude, OpenSCAD-Code zu rendern und STL-Dateien zu erzeugen.
"""

import subprocess
import tempfile
import os
import base64
from pathlib import Path
from mcp.server.fastmcp import FastMCP

OPENSCAD_PATH = os.environ.get(
    "OPENSCAD_PATH",
    r"C:\Program Files\OpenSCAD\openscad.exe"
)

OUTPUT_DIR = Path(os.environ.get("OPENSCAD_OUTPUT_DIR", Path.home() / "3d-models"))
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)

mcp = FastMCP("openscad")


def _run_openscad(scad_code: str, output_path: Path, extra_args: list = None) -> tuple[bool, str]:
    with tempfile.NamedTemporaryFile(suffix=".scad", mode="w", delete=False, encoding="utf-8") as f:
        f.write(scad_code)
        scad_file = f.name
    try:
        cmd = [OPENSCAD_PATH, "-o", str(output_path)] + (extra_args or []) + [scad_file]
        result = subprocess.run(cmd, capture_output=True, text=True, timeout=60)
        output = (result.stdout + result.stderr).strip()
        success = result.returncode == 0 and output_path.exists()
        return success, output
    finally:
        os.unlink(scad_file)


@mcp.tool()
def render_stl(code: str, filename: str = "model.stl") -> str:
    """Rendert OpenSCAD-Code als STL-Datei für den 3D-Drucker."""
    if not filename.endswith(".stl"):
        filename += ".stl"
    output_path = OUTPUT_DIR / filename
    success, output = _run_openscad(code, output_path)
    if success:
        size_kb = output_path.stat().st_size // 1024
        return f"STL erfolgreich erstellt: {output_path}\nDateigröße: {size_kb} KB\nOpenSCAD-Output: {output or '(kein Output)'}"
    else:
        return f"Fehler beim Rendern:\n{output}"


@mcp.tool()
def preview_png(code: str, filename: str = "preview.png") -> str:
    """Rendert eine PNG-Vorschau des OpenSCAD-Modells."""
    if not filename.endswith(".png"):
        filename += ".png"
    output_path = OUTPUT_DIR / filename
    extra = ["--camera=0,0,0,55,0,25,140", "--imgsize=800,600", "--colorscheme=DeepOcean"]
    success, output = _run_openscad(code, output_path, extra_args=extra)
    if success:
        with open(output_path, "rb") as f:
            img_b64 = base64.b64encode(f.read()).decode()
        return f"data:image/png;base64,{img_b64}"
    else:
        return f"Fehler beim Rendern der Vorschau:\n{output}"


@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()

Schritt 5: MCP-Server testen

echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}' | .venv\Scripts\python.exe server.py

Erwartete Ausgabe: JSON-Antwort mit "name":"openscad" — Server funktioniert.


Schritt 6: Claude Code Desktop konfigurieren

Wichtig: Es gibt zwei Settings-Dateien. Nur eine davon wird von der Desktop App gelesen:

Datei Gelesen von
C:\Users\<USERNAME>\.claude\settings.json Claude Code CLI (Terminal)
C:\Users\<USERNAME>\AppData\Roaming\Claude\claude_desktop_config.json Claude Code Desktop App

Da die Desktop App verwendet wird, muss der Eintrag in claude_desktop_config.json.

Datei öffnen: C:\Users\<USERNAME>\AppData\Roaming\Claude\claude_desktop_config.json

Den mcpServers-Block hinzufügen (Backslashes im Pfad beachten):

{
  "mcpServers": {
    "openscad": {
      "command": "C:\\Users\\<USERNAME>\\Documents\\Claude\\openscad-mcp\\.venv\\Scripts\\python.exe",
      "args": ["C:\\Users\\<USERNAME>\\Documents\\Claude\\openscad-mcp\\server.py"]
    }
  },
  "preferences": {
    ...vorhandene Einstellungen beibehalten...
  }
}

Schritt 7: Claude Code neu starten

Vollständig beenden — nicht nur neues Chat-Fenster öffnen:

  • Rechtsklick auf Claude-Icon im Systemtray → Quit/Beenden
  • Alternativ: Task-Manager → claude.exe beenden

Dann Claude Code neu starten und einen neuen Chat öffnen.


Verifikation

In einem neuen Chat eingeben:

"Erstelle einen einfachen Würfel 20x20x20mm als test.stl"

Claude sollte automatisch das Tool render_stl aufrufen und eine STL-Datei in C:\Users\<USERNAME>\3d-models\test.stl erzeugen.


Beispiel-Prompts

Erstelle einen Filamentrollenhalter für 200mm Außendurchmesser, 30mm Achse, als filamenthalter.stl
Erstelle einen Wandhalter für ein 32mm Rohr, Wandstärke 3mm, 2 Schraubenlöcher M4, als rohrhalter.stl
Erstelle eine Box 80x50x30mm mit Deckel und Scharnier, Wandstärke 2mm, als box.stl

Troubleshooting

Server wird nicht geladen (Tools nicht sichtbar)

  • Prüfen ob Eintrag in claude_desktop_config.json ist (nicht in settings.json)
  • Claude Code vollständig neu starten (Systemtray → Quit)
  • Debug-Log prüfen: C:\Users\<USERNAME>\.claude\debug\ — neueste Datei nach openscad durchsuchen

STL-Render schlägt fehl

  • OpenSCAD-Pfad prüfen: "C:\Program Files\OpenSCAD\openscad.exe" --version
  • Output-Verzeichnis prüfen: C:\Users\<USERNAME>\3d-models\ muss existieren (wird automatisch erstellt)

Python/mcp Import-Fehler

  • Virtual Environment neu erstellen (Schritt 3)
  • Prüfen: .venv\Scripts\python.exe -c "from mcp.server.fastmcp import FastMCP; print('OK')"

Dateistruktur

C:\Users\<USERNAME>\
├── AppData\Roaming\Claude\
│   └── claude_desktop_config.json          ← MCP-Server Registrierung
├── .claude\
│   └── settings.json                        ← Claude Code CLI-Settings (nicht relevant)
├── Documents\Claude\openscad-mcp\
│   ├── .venv\                               ← Python Virtual Environment
│   │   └── Scripts\python.exe               ← Echter Python-Interpreter
│   └── server.py                            ← MCP-Server Code
└── 3d-models\                               ← Ausgabeverzeichnis für STL-Dateien
    ├── filamenthalter.stl
    └── ...

Hintergrund: Warum so kompliziert?

  1. Zwei Config-Dateien: Claude Code Desktop liest claude_desktop_config.json, nicht ~/.claude/settings.json. Letzteres ist nur für den CLI-Modus.

  2. Windows App Execution Aliases: WindowsApps\python3.13.exe ist ein Stub der nur aus interaktiven Shells funktioniert. Als Subprocess von Claude Code schlägt er ohne Fehlermeldung fehl. Ein Virtual Environment erstellt eine echte python.exe ohne diese Einschränkung.

  3. Eingebettetes Python: C:\...\Programs\Python\Python313\python.exe (das vom py-Launcher verwendete) hat kein pip und kann nicht für MCP verwendet werden.