Install
$ agentstack add mcp-gchen19-ankusdrive ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ● Filesystem access Used
- ● Shell / process execution Used
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
AnkusDrive
A CLI + MCP server that drives FreeCAD through its Python API so LLMs (and humans at a terminal) can design mechanical parts and run FEM simulations without clicking through the GUI.
Why
FreeCAD exposes almost everything it does through a Python API — create documents, build sketches, extrude solids, mesh them, run CalculiX/Elmer FEM solves, read back stress/displacement fields. But that API lives inside FreeCAD's embedded Python (freecadcmd), which is awkward to call from anywhere else. AnkusDrive wraps it behind two surfaces:
- CLI — one-shot commands (
ankusdrive run script.py,ankusdrive box --w 10 --d 20 --h 5 -o part.FCStd) for scripts, CI, and quick iteration. - MCP server — 280+ structured tools (
new_document,add_primitive,boolean_op,pad,add_gear,fem_new_analysis,fem_run,fem_results) so an LLM agent can model, inspect, and simulate iteratively. Beyond core CAD/FEM this now spans a broad simulation surface (thermal, CFD/CHT, EM, acoustics, FSI, injection molding, granular/DEM, optics, multibody) and a design-control layer (item/part numbers, recipes, variant families, lifecycle/revision, ECO change orders, versioned interfaces). - Multi-agent orchestration — a host-side reference layer that lets a team of agents partition one product into components, build them in parallel, and merge the pieces back together with the joints actually fitting (see [Multi-agent design](#multi-agent-design)).
Target environment
- FreeCAD 1.1.x. The
freecadcmdbinary is auto-discovered per-OS (macOS.appbundle, Linux/usr/binetc., WindowsC:\Program Files\FreeCAD 1.1\bin\freecadcmd.exe— version-globbed); override via$ANKUSDRIVE_FREECADCMDor rely on PATH. Runankusdrive doctorto see exactly what resolved. - Bundled Python,
ccx(CalculiX), andgmshalready ship inside every FreeCAD install — the macOS.app, the Linux package, and the Windowsbin\— so core CAD + structural FEM work on all three with no extra install. - Host-side rendering needs
Pillowandnumpy; both are installed by AnkusDrive as regular pip deps. - One optional exception: drawing PDF/SVG export (
export_drawing) renders inside FreeCAD's bundled Python, so it needsreportlab+svglibinstalled there — see [Drawing export (PDF/SVG)](#drawing-export-pdfsvg). DXF export and everything else leave FreeCAD's Python untouched.
Setup
AnkusDrive is a pip-installable package; FreeCAD itself is the only thing you install separately. The host-side dependencies (mcp, Pillow, numpy) come along with the install. freecadcmd is launched as a subprocess and uses its own bundled Python — AnkusDrive doesn't touch it.
# 1. Install FreeCAD 1.1.x from https://www.freecad.org/
# (macOS: drag to /Applications; Linux: distro package or AppImage;
# Windows: run the installer — default C:\Program Files\FreeCAD 1.1)
# 2. Install AnkusDrive. Pick one:
pipx install ankusdrive # from PyPI — isolated app, `ankusdrive` on PATH
pip install ankusdrive # or into an env you manage yourself
# unreleased main, or for development from a clone:
pipx install git+https://github.com/gchen19/AnkusDrive.git
git clone https://github.com/gchen19/AnkusDrive.git && cd AnkusDrive
python3 -m venv .venv && .venv/bin/pip install -e . # `.venv/bin/ankusdrive`
# 3. Smoke-test that the worker can reach FreeCAD, and see the full setup report
ankusdrive ping # → ping=pong freecad=1.1.1
ankusdrive doctor # per-item FreeCAD + solver checklist with the exact fix each
> On Windows, don't follow the block above by hand — there is one scripted path > that does all of it including the MCP registration: > [Windows quickstart (PowerShell)](#windows-quickstart-powershell).
AnkusDrive is published on PyPI at pypi.org/project/ankusdrive; the distribution roadmap beyond it (marketplace listings, hosted transport) is tracked in epic #303; the original phase plan is kept as a design record at docs/archive/PUBLISHING_PLAN.md.
Windows quickstart (PowerShell)
Windows is a first-class target (core CAD + CalculiX FEM run natively against a stock FreeCAD 1.1 install), and the whole core install is one script — venv, pinned dependencies, doctor, and the MCP registration line with resolved absolute paths:
# 1. Install FreeCAD 1.1.x from https://www.freecad.org/ (default C:\Program Files\FreeCAD 1.1).
# Nothing needs to go on PATH — AnkusDrive globs the versioned install dir itself.
# 2. Clone and run the core installer. Windows PowerShell 5.1 is enough; no admin needed.
git clone https://github.com/gchen19/AnkusDrive.git
cd AnkusDrive
powershell -ExecutionPolicy Bypass -File scripts\install-core.ps1
That creates .venv, installs AnkusDrive with the pins that matter (notably `mcp /tmp/fcprefix.py FREECADPREFIX="$(freecadcmd /tmp/fcprefix.py 2>/dev/null | sed -n 's/^DPREFIX=//p')" FREECADPY="$FREECADPREFIX/bin/python" # some builds: $FREECADPREFIX/bin/python3
Pin svglib pycairo, a native build we
don't use (our drawings are line art, no gradients).
"$FREECAD_PY" -m pip install reportlab "svglib/.local/bin/ankusdrive (pipx default) or /absolute/path/to/AnkusDrive/.venv/bin/ankusdrive` (clone+venv).
Claude Desktop, one click — download ankusdrive-.mcpb from the latest release and open it. Claude Desktop sets up its Python environment with uv, so no pipx step is needed — FreeCAD 1.1 still is. The install dialog has one optional field, the FreeCAD command path, for a FreeCAD that auto-discovery cannot find.
Claude Code — register once:
claude mcp add ankusdrive -- ankusdrive mcp
Other hosts (Cursor, Continue, custom MCP clients) — same shape: stdio transport, command = ankusdrive, args = ["mcp"].
After restarting the host, you should see 280+ ankusdrive__* tools become available. If startup hangs or the host reports a closed connection, run ankusdrive ping directly — that exercises the same worker boot path with cleaner error messages.
Tool families (toolsets). Every tool definition takes up the client's context, and all 283 come to roughly 114k tokens. Tools are grouped into families you can switch on and off: core (always on), drawings, fem, components, sheet_metal, assembly, intent, manufacturing, hand_calcs, simulation, plm, rendering.
- pip / pipx / uvx / clone: every family is on unless you set
ANKUSDRIVE_TOOLSETS, e.g. ANKUSDRIVE_TOOLSETS=drawings,fem,simulation, or toolsets = "..." in config.toml.
- Claude Desktop extension:
core,drawingsandfemare on by default
(~31k tokens); turn others on in the extension's settings.
setup_status lists the families that are off and exactly how to enable each one.
run_script executes Python the agent writes, with full access to your files and processes. It's controlled by ANKUSDRIVE_ALLOW_RUN_SCRIPT (env, or allow_run_script in config.toml):
- pip / pipx / uvx / clone: allowed unless set to
false. - Claude Desktop extension: off by default; turn it on in the extension's
settings.
When it's off, the tool isn't offered at all, and setup_status says how to enable it.
Simulation solvers & review-video demos
The base install (FreeCAD + pip install ankusdrive) covers geometry, the analytic oracles, and the MCP surface. The heavy simulation families each shell out to an external solver, discovered at runtime by ankusdrive/solvers.py ($ANKUSDRIVE__PATH → PATH → standard install dirs). A family whose solver is absent degrades to a clean {ok: false, reason, install} dict instead of crashing — check what currently resolves with ankusdrive doctor (cross-platform, no server boot needed), the solve_capabilities MCP tool, or the install script's list. The install script installs the pip-wheel solvers and provisions the native ones — scripts/install-solvers.sh on Linux/macOS (apt/conda + source builds), and scripts/install-solvers.ps1 on Windows (pip extras + portable SU2/Elmer/PrusaSlicer downloads; CalculiX auto-detected from FreeCAD's bundle).
Persistent config: every ANKUSDRIVE_* path can instead live in ~/.config/ankusdrive/config.toml (%APPDATA%\ankusdrive\config.toml on Windows; ANKUSDRIVE_CONFIG overrides): freecadcmd = "..." at top level, one lowercased key per solver var under [solvers] (su2_path, elmer_path, openfoam_bashrc, ...). Env vars still win when set; the file is the layer that survives an MCP host's minimal launch environment. ankusdrive doctor reports the file and which layer resolved each value.
Platform note: the solver discovery layer is fully cross-platform (per-OS install dirs, Windows PATHEXT/.exe, env overrides), so ankusdrive doctor gives an honest report on macOS/Linux/Windows. The pip-wheel families (MBD, topology, optics, fluids) install identically everywhere. The native-binary families differ by OS — CalculiX ships inside every FreeCAD install; SU2 and PrusaSlicer have good Windows/macOS binaries; Elmer has a portable Windows zip but no macOS binaries; the OpenFOAM-backed families (CFD, FSI, injection molding) still rely on a Linux shell + linker glue and are Linux/WSL/Docker for now. See docs/WINDOWS.md and docs/MACOS.md for the full per-solver reality and setup on each OS.
The review-video demos under scratch/ turn a solver result into a GIF a human can watch — the real exported geometry in motion with the matching oracle overlaid on the frame (written to artifacts/). Each needs its family's solver plus matplotlib, and the CFD one needs meshio (on top of the base numpy/Pillow):
pip install matplotlib meshio # frame rendering + reading OpenFOAM's VTK output
| Review-video demo (scratch/…) | Solver it drives | Install | |---|---|---| | dog_clutch_cad_sim.py — rigid-body contact via p.vhacd | PyBullet (pip wheel) | pip install 'ankusdrive[mbd]' | | meshing_gears_video.py — MBD gear train | PyBullet (pip wheel) | pip install 'ankusdrive[mbd]' | | modal_shape_video.py — FEM modal shapes | CalculiX ccx (FreeCAD FEM) | apt install calculix-ccx (Linux); FreeCAD finds ccx on PATH | | thermal_field_video.py — transient thermal field | Elmer | apt install elmerfem-csc; ensure ElmerSolver on PATH (or set ANKUSDRIVE_ELMER_PATH) | | cfd_field_video.py — CFD field (lid-driven cavity) | OpenFOAM + meshio | OpenFOAM via apt/conda, then source /etc/bashrc (or set ANKUSDRIVE_OPENFOAM_BASHRC); pip install meshio |
All of them also use FreeCAD for the geometry/meshing, so run each with the same interpreter that launches the worker — e.g. .venv/bin/python3 scratch/cfd_field_video.py.
Optics
Two optics engines sit behind the MCP surface, in two licensing/runtime lanes:
| Lane | Tools | Engine | Install | |---|---|---|---| | Sequential — lens design + optimization | optics_lens_design, optics_lens_optimize, optics_raytrace | optiland / rayoptics (MIT/BSD, in-process) | pip install 'ankusdrive[optics]' — or scripts/install-solvers.sh optics | | Non-sequential — tracing through STL solids | optics_solid_trace | KrakenOS (GPL-3.0, out-of-process only) | pip install 'ankusdrive[optics_gpl]' — or scripts/install-solvers.sh optics_gpl |
The sequential engines import in-process, so install the optics extra into the same interpreter that launches the worker (like the other wheels). The non-sequential engine is GPL-3.0 and is therefore never imported by AnkusDrive — it runs in a separate subprocess (ankusdrive/optics_gpl_runner.py), the same arm's-length boundary used for the GPL Elmer/OpenFOAM binaries. The worker locates a Python that can import KrakenOS automatically (from where the wheel is installed); override with ANKUSDRIVE_OPTICS_GPL_PYTHON=/path/to/python. Because of that isolation the GPL extra is opt-in: the no-argument install-solvers.sh run installs only the permissive extras and prints how to add optics_gpl. Rendered examples for both lanes (lens layout, spot diagram, optimization, prism TIR, and a ball-lens spherical-aberration study) live in examples/optics_gallery/ — regenerate with .venv/bin/python examples/optics_gallery.py (and …_3d.py, optics_ball_lens.py), or bootstrap everything in one shot (installs both lanes, then renders every figure):
scripts/install-solvers.sh --optics-gallery
Architecture sketch
┌────────────┐ ┌────────────┐ ┌──────────────────────┐
│ MCP host │ ───► │ AnkusDrive │ ───► │ freecadcmd worker │
│ (Claude) │ │ (Python) │ IPC │ (long-lived Python) │
└────────────┘ └────────────┘ └──────────────────────┘
▲ ▲ │
│ │ ▼
└── CLI user ────────┘ .FCStd / .inp / .vtk
Key decision: long-lived worker with JSON-over-stdin/stdout, not subprocess-per-call. FreeCAD startup is ~1–2s; re-paying that per tool call is unacceptable for an interactive agent. The worker is a small Python loop launched under freecadcmd, reading commands, dispatching to handlers, returning structured results (including object IDs so follow-up calls can reference created geometry).
FreeCAD API surface we care about
Notes gathered from the scripting docs and the FEM Python tutorial:
Core (App):
App.newDocument(name)/App.ActiveDocument/doc.recompute()/doc.save(path)doc.addObject("Part::Box", "name")— typed object creation; properties set after (box.Height = 5)doc.supportedTypes()for introspection;obj.TypeId,obj.isDerivedFrom("Part::Feature")
Modeling:
Part—makeBox,makeCylinder,makeSphere, booleancut/common/fuse, fillets, lofts (OpenCASCADE under the hood)Draft— 2D primitives,move, arraysSketcher+PartDesign— parametric sketch-driven solids (most "real" mechanical design happens here)FreeCAD.Vector,Placementfor positioning
FEM (ObjectsFem + femtools):
ObjectsFem.makeAnalysis(doc, "Analysis")— containermakeSolverCalculixCcxTools/makeSolverElmer— solver objects with tunables (GeometricalNonlinearity,ThermoMechSteadyState, …)makeMaterialSolid— assignYoungsModulus,PoissonRatio,Density- Constraints:
makeConstraintFixed,makeConstraintForce,makeConstraintPressure,makeConstraintDisplacement, contact/tie/spring, thermal - Mesh:
makeMeshGmsh+femmesh.gmshtools.GmshTools(...).create_mesh()(or Netgen) - Run:
femtools.ccxtools.FemToolsCcx().run() - Results: iterate
analysis.GroupforFem::FemResultObject; read.DisplacementVectors, stress fields
Headless invocation:
freecadcmd script.py— runs script then exitsfreecadcmdwith no args — interactive Python REPL (what the worker will drive)--console,-M,-P,--pass,FreeCAD.ConfigGet(...)for env info- `FreeCADG
…
Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: gchen19
- Source: gchen19/AnkusDrive
- License: Apache-2.0
- Homepage: https://pypi.org/project/ankusdrive/
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.