Content
# Vibe CAD
[](https://github.com/wangtao9090/VibeCAD/actions/workflows/ci.yml) [](https://pypi.org/project/vibecad/) [](LICENSE) [](https://www.python.org)
**AI-native conversational CAD — an open-source MCP connector for FreeCAD (chat-native, zero-install).**
## Tool List
## Quick Start (User)
**Claude Desktop / Cowork (Recommended)**: Download the latest version of [`VibeCAD.mcpb`](https://github.com/wangtao9090/VibeCAD/releases/latest) from [Releases](https://github.com/wangtao9090/VibeCAD/releases/latest) and **double-click to install**. After installation, Claude Desktop will pop up an installation window, click install to proceed. Zero terminal, zero configuration file, no need to pre-install uv/Python (the host automatically prepares an isolated Python environment). After installation, tell the AI "Help me prepare the CAD environment". For a step-by-step guide, see the **[User Guide](docs/USER_GUIDE.md)**.
> For other clients (Claude Code / Cursor, etc.), use the stdio method: Install [uv](https://docs.astral.sh/uv/) and then run `claude mcp add --transport stdio vibecad -- uvx vibecad` (published on [PyPI](https://pypi.org/project/vibecad/)). For details, see Appendix A of the User Guide.
## First Release: Chat-native Zero Installation
Users do not need to install FreeCAD — the MCP server automatically downloads the headless FreeCAD runtime (micromamba) on the first run.
Each step returns text diagnostics + soft rendering images + interactive glTF preview. Installing FreeCAD unlocks Live mode as an upgrade, not a threshold.
## Architecture (Scheme B: In-process)
- **MCP Framework**: Python official MCP SDK (FastMCP), starting with stdio
- **Geometry Engine**: conda-forge FreeCAD 1.1+ in-process `import`
- **Runtime Distribution**: micromamba automatic installation (full platform matrix)
- **Tool Interface**: Pure semantic tools (`add_hole`/`fillet_edges`/`assemble`/`fasten`), each tool transaction + geometric assertions + rule checks
- **Feedback Tiers**: glTF artifact (main) / soft rendering image / pure text diagnostics
## Development
```bash
uv sync # Install server dependencies (excluding FreeCAD)
uv run vibecad # Start MCP server (stdio, run pure stdlib launcher first)
uv run pytest # Run unit tests (slow integration tests are skipped by default)
uv run ruff check # Static check
```
### FreeCAD Runtime (First Use)
The server starts and handshake; the FreeCAD runtime (about 2-3GB) is downloaded on demand in the background without blocking the handshake:
1. Call `ensure_runtime` — if not ready, start background installation (micromamba → conda env `python=3.12 freecad=1.1.0` → pip install server → smoke test), return `started` immediately.
2. Poll `get_runtime_status` until `phase=ready`; if `needs_reconnect=true`, the runtime is ready but the current session is still guiding the interpreter, **please reconnect to this MCP server**.
3. After reconnection, call `smoke_cad` — create a 10×10×10 Box in-process, export STEP, and return volume/bounding box (verify A1/A3).
Environment variables:
- `VIBECAD_HOME` — root directory of the runtime (default platform data directory)
- `VIBECAD_AUTO_INSTALL=1` — server starts and automatically installs in the background (default requires explicit `ensure_runtime`)
- `VIBECAD_FREECAD_ENV=<conda env path>` — reuse an existing FreeCAD env (only verify, do not build)
- `VIBECAD_PIP_SPEC=<local source/package name>` — point to a local repository source during the pre-release period
- Integration test: `VIBECAD_RUN_INTEGRATION=1 uv run pytest -m slow` (actually download 2-3GB)
> Expired installation lock: If the installation is abnormally interrupted, manually delete `<VIBECAD_HOME>/.install.lock`.
> The FreeCAD runtime is obtained on-demand by `vibecad.runtime` (D4) and isolated from this venv.
## Semantic Modeling Tools (Round 2)
After the runtime is ready and reconnected, use the following semantic tools to complete "natural language → parametric single part → manufacturable file":
| Tool | Function |
|---|---|
| `new_document(name)` | Create a new single-part working document |
| `add_box(length, width, height, position=[x,y,z])` | Parametric cuboid (Part::Box, mm); `position` placement position (default origin) |
| `add_cylinder(radius, height, position=[x,y,z], axis="z")` | Parametric cylinder (Part::Cylinder, mm); `position` placement position, `axis=x\|y\|z` axis direction (can penetrate different faces, cooperate with centered position to punch holes) |
| `boolean_cut(base_name, tool_name)` | Boolean difference (Part::Cut): subtract tool from base |
| `export_part(output_dir, fmt="both")` | Export manufacturable file STEP/STL (fmt: step\|stl\|gltf\|both\|all; all includes glTF) |
| `describe_part()` | Text diagnostics: volume/bounding box/centroid/number of solids/validity |
| `render_part(view="iso", annotate=None, edges_of=None)` | **PNG preview image** (view: iso\|front\|top\|right\|back\|**multi**). `view="multi"` outputs **engineering drawing tri-view拼图** (wireframe + hidden line + dimensions + ⌀ + center line + annotation iso grid); `annotate="faces"` outputs **face annotation图** (A/B/C labels + dimension lines) + label table; `annotate="edges"` outputs edge annotation图 (E1…, `edges_of="A"` only draw edges of A) |
| `add_hole(face, diameter, depth=None, offset=[u,v], pattern=None)` | **Punch a round hole on the specified face** (face=face label); depth omitted = through hole; offset face inner offset; `pattern={"type":"linear","count":4,"spacing":10}` or `{"type":"circular","count":6,"radius":12}` **hole array** (all or nothing) |
| `fillet_edges(edges, radius)` | **Fillet** (edges=edge label list, e.g., `["E1","E2"]`) |
| `chamfer_edges(edges, size)` | **Chamfer** (edge label list) |
| `move_part(name, position)` | **Move the part** to an absolute position (hole tool/base; features recalculate with dependencies, destroying hole integrity/closed cavity movement sounds loud) |
| `rotate_part(name, axis, angle)` | **Rotate the part** (around its own bounding box center; applies to objects without features, overall rotation leaves assembly wheel) |
| `extrude_profile(profile, height, face, offset, operation)` | **Free profile extrusion**: profile DSL (rect/circle/polygon/slot) pad material/pocket groove on the specified face; volume bilateral calculation (punching through/overlapping loud refusal) |
| `new_part(name)` | **Create a new assembly part** and set it as the active part (existing tools default to the active part; the first part is automatically named Part1) |
| `place_part(part, position, rotation_axis, angle)` | **Part-level pose**: move/rotate the entire part (including all features) - holes follow the part |
| `align_parts(moving_part, moving_face, target_part, target_face, offset, gap, allow_interference)` | **Face-to-face alignment** (跨零件面标签指代); after assembly, **automatic interference check**, overlapping loud report interference amount and rollback (`allow_interference` explicitly exempted press fit) |
| `modify_part(name, parameter, value)` | **Parameter modification** (e.g., `("Box","length",45)`, `("HoleTool","radius",5)`) — FreeCAD dependency chain automatically recalculates, engineering drawing dimensions update on-site; modifiable objects and parameters see the `parts` field returned by each step; with drift/hole integrity/single entity geometric assertions, dangerous modifications (swallowing/hole becomes a gap/cutting two halves) loudly refuse and rollback |
Each tool = parameter verification → document transaction → parametric object → recompute → **geometric assertion** ( `recompute()` return value is unreliable, geometric assertion is the only credible success criterion) → structured return. All tools guard "runtime ready + reconnected to conda interpreter".
## Visual Feedback (Round 3)
- `render_part` returns **PNG soft rendering image** (matplotlib Agg, no GPU), as MCP `ImageContent` **inline visible** in Claude Desktop and other clients - users iterate and draw accordingly.
- `export_part(fmt="gltf"/"all")` exports **glTF (.glb) artifact** (face-by-face primitive + face-level extras) for future glTF-enabled apps/clients to interactively rotate and pick.
## References
- **[User Guide](docs/USER_GUIDE.md)** — Installation, Claude Cowork configuration, scenario-based usage, and troubleshooting
- **[Acceptance Test Plan](docs/ACCEPTANCE_TESTS.md)** — 12 conversation scenario checklist + Windows manual verification
## License
[MIT](LICENSE)