Modern CAD CLI + MCP Server system (2D/3D drawing, editing, measurement, rendering, JSON-driven)
Reason this release was yanked:
Renamed to tianshangcad. Use pip install tianshangcad instead.
Project description
TianshangCAD (cad-mcp-server)
A modern CAD CLI + MCP Server system. 2D/3D drawing, editing, measurement, validation and JSON-driven workflows are available both from the command line and as standardized tools callable by any MCP client (AI agent).
Status: Phases 1–7 complete (v0.7.0 assembly + engineering drawings), plus the v0.6.0 sprint, the v0.8.0 Task A/B (parametric features + simulation interface) and the v0.9.0 Task A (real-time collaboration). 907 tests passing, ~87% coverage (measured with optional extras installed),
ruffandmypyclean.
中文文档: readme/README.zh-CN.md
Changelog · Migration guide v0.6.0 → v0.9.0
Features
- CAD CLI —
file,draw,edit,view,measure,layer,batchcommand groups with short aliases (l=draw line,c=draw circle, ...) - MCP Server — 103 JSON-RPC tools over stdio, streamable HTTP or WebSocket (collaboration), callable from Claude, Cursor and other MCP clients
- 3D views — JSON-defined
View3DDefinitionwith spherical camera pose, named views (iso / top / front / side / back / bottom), perspective / orthographic projection, plane sections (XY / YZ / XZ), exploded views and orbit GIF animation; incremental WebGL delta sync for browser clients - Batch automation — schedule one-off / cron / dependency-chained jobs, sandboxed Python / SCR / batch script execution, webhook notifications, SQLite persistence and reusable Jinja2 command templates
- Geometry validation — self-intersection, degenerate-face and
non-manifold-edge checks with structured
type/location/fix_suggestiondiagnostics; box-box interference volumes; topology metrics - Rendering — 2D orthographic PNG (top / front / side, DPI 72–300), shaded 3D preview and Three.js WebGL export with a bundled browser viewer
- Versioning — full document snapshots with
deepdiff-based save / list / diff / restore - Natural language —
cad_nlp_commandmaps English / Chinese requests to tool calls with ambiguity handling - JSON-driven — scenes and geometry defined and validated with Pydantic schemas; full import/export round-trip
- Pluggable kernel — analytic (default, no native deps) / OCC
(
cadquery) / FreeCAD - File IO — JSON, DXF, STL (STEP via the OCC backend)
- Production hardening — Docker image with healthcheck, Prometheus
metrics (
/metrics), API-key authentication (401/403), sliding-window rate limiting (429) and a/healthendpoint - Quality gates —
mypystrict typing,rufflinting,pytestwith a 80% coverage floor; GitHub Actions CI runs lint + tests on every push. The reported ~87% coverage assumes the optional extras (boolean,solver,occ,collab,sim) are installed; the basepip install -e .suite measures lower.
Install
python -m venv .venv
# Windows
.venv\Scripts\activate
# Linux / macOS
source .venv/bin/activate
pip install -e ".[dev]"
Self-contained Debian package (Linux amd64, bundles all runtime wheels — no network access needed at install time):
wget <release>/cad-mcp-server_<version>_amd64.deb
sudo dpkg -i cad-mcp-server_<version>_amd64.deb
Optional OCC kernel:
pip install -e ".[occ]"
CLI Usage
cad-cli --version
cad-cli file new design.json --unit mm
cad-cli draw line 0,0 100,0
cad-cli draw circle 50,50 --radius 25
cad-cli draw box 0,0,0 --dimensions 100,50,30
cad-cli edit move line_1 --dx 50
cad-cli view zoom --extents
cad-cli measure distance 0,0 100,100
Short aliases are expanded automatically:
cad-cli l 0,0 100,0 equals cad-cli draw line 0,0 100,0.
cad-cli --version prints the current version (e.g. cad-cli 0.9.0).
Command groups
| Group | Commands |
|---|---|
file |
new, open, save, close, list, info, export, import |
draw |
line, circle, arc, rectangle, polygon, polyline, box, cylinder, sphere |
edit |
move, copy, rotate, scale, erase, list, undo, redo |
view |
zoom, pan, list |
measure |
distance, area, list |
layer |
create, list, set, on, off, delete |
render |
view, 3d, webgl, view3d, section, explode, gif, views, status |
batch |
schedule, run-script, list, status, cancel, templates, logs |
MCP Server
Run the server and connect any MCP client to it.
stdio (local agents)
python -m cad_mcp_server --transport stdio
Streamable HTTP
python -m cad_mcp_server --transport http --host 127.0.0.1 --port 8081
The server then serves MCP at http://127.0.0.1:8081/mcp, exposes a health
check at /health and Prometheus metrics at /metrics.
When an API key is configured (via the CAD_API_KEYS env var, comma-separated),
HTTP requests must send it as x-api-key or Authorization: Bearer <key>:
missing keys get 401, invalid keys get 403. Requests are also subject to a
sliding-window rate limit (default 100 requests / 60 s, configurable via
CAD_RATE_LIMIT_MAX and CAD_RATE_LIMIT_WINDOW); exceeding it returns 429.
/health and /metrics are always public. stdio mode is unaffected.
Tools (103 total)
| Group | Tools |
|---|---|
| Files | cad_file_create, cad_file_open, cad_file_save, cad_file_close, cad_file_list, cad_file_export, cad_file_import |
| Objects | cad_object_create, cad_object_read, cad_object_update, cad_object_delete, cad_object_list |
| Boolean | cad_boolean_union, cad_boolean_subtract, cad_boolean_intersect, cad_object_boolean |
| Variables | cad_variable_set, cad_variable_list |
| Layers | cad_layer_create, cad_layer_read, cad_layer_update, cad_layer_delete, cad_layer_list |
| JSON | cad_json_load, cad_json_parse, cad_json_validate, cad_json_import_geometry, cad_json_export_geometry, cad_json_import_scene, cad_json_export_scene, cad_json_save |
| Status | cad_status_check, cad_status_file, cad_status_object, cad_status_layer, cad_status_health, cad_logs_get, cad_logs_clear |
| Validation | cad_validate_geometry, cad_validate_interference, cad_validate_topology, cad_metrics_get |
| Render | cad_render_view |
| 3D Views | cad_view_3d_create, cad_view_3d_read, cad_view_3d_list, cad_view_3d_update, cad_view_3d_delete, cad_view_3d_render, cad_view_section, cad_view_explode, cad_view_animation, cad_webgl_sync |
| Version | cad_version_save, cad_version_list, cad_version_diff, cad_version_restore |
| NLP | cad_nlp_command, cad_nlp_chat |
| Batch | cad_batch_execute, cad_batch_schedule, cad_batch_status, cad_batch_cancel, cad_batch_list, cad_batch_templates, cad_batch_run_script |
| Constraints | cad_constraint_add, cad_constraint_remove, cad_constraint_list, cad_constraint_solve |
| Assembly | cad_assembly_create, cad_assembly_add_part, cad_assembly_add_subasm, cad_assembly_add_mate, cad_assembly_solve, cad_assembly_bom, cad_assembly_explode |
| Drawing | cad_drawing_create, cad_drawing_add_view, cad_drawing_add_section, cad_drawing_add_dimension, cad_drawing_add_tolerance, cad_drawing_export |
| Features | cad_feature_sweep, cad_feature_loft, cad_feature_fillet, cad_feature_chamfer, cad_feature_pattern_linear, cad_feature_pattern_circular, cad_feature_pattern_mirror |
| Simulation | cad_sim_mesh, cad_sim_setup, cad_sim_run, cad_sim_result, cad_sim_list |
| Collaboration | cad_collab_session, cad_collab_branch, cad_collab_annotation, cad_collab_presence, cad_collab_history, cad_collab_resolve, cad_collab_permission, cad_collab_sync |
Validation, rendering, 3D views & NLP
Validate geometry with structured diagnostics, render orthographic views, snapshot and restore document versions, drive tools from natural language, and create named 3D views with camera, section, explode and animation:
# Render a 300 DPI top view PNG
cad-cli render view --view top --dpi 300 --output preview.png
cad-cli render 3d --output preview3d.png
cad-cli render webgl --output viewer_data.json --viewer examples/threejs_viewer.html
# 3D views
cad-cli render view3d iso --output iso.png
cad-cli render section XY --offset 0 --output section.png
cad-cli render explode --scale 1.5 --output explode.png
cad-cli render gif --frames 48 --output orbit.gif
cad-cli render views
# NLP examples (via the MCP tool cad_nlp_command)
"new file design.dwg" -> cad_file_create {filename: design.dwg}
"draw a line from 0,0 to 10,10" -> cad_object_create (line)
"render the side view" -> cad_render_view {view: side}
"save a version" -> cad_version_save
cad_nlp_chat adds multi-turn dialogue with anaphora resolution: each
session_id remembers the last created object so later turns can refer to
it with pronouns or descriptions. Create intents are executed against the
current document, so "it" / "它" resolves to the real object id.
# Turn 1: draw a circle (creates the object, records it in the session)
"draw a circle at 5,5 radius 3" -> cad_object_create, object_id tracked
# Turn 2: move the referenced circle (same session_id)
"move it to 10,10" -> cad_object_update {object_id, params}
"move the circle I just drew to 3,3" -> same, explicit anaphora
"把它移到 4,4" -> same, Chinese pronoun
Version diffing uses deepdiff and reports changed fields, added/removed
items and the raw result. The WebGL export writes Three.js BufferGeometry
JSON consumable by examples/threejs_viewer.html. View definitions
(camera pose, projection, section/explode parameters) are persisted with the
document and are also exposed as MCP tools (cad_view_3d_*,
cad_view_section, cad_view_explode, cad_view_animation,
cad_webgl_sync).
Real-time collaboration
Phase 9 collaboration builds on the LWW-Map CRDT: a session holds the shared document state as keyed registers (geometry / layers / variables / constraints / assembly), with 4-role × 4-scope RBAC (viewer / editor / admin / owner over document / scene / assembly / settings). Sessions support presence, annotations, document branches (fork / edit / merge with explicit conflict resolution) and a transport-agnostic sync primitive:
# Optional dependency for the WebSocket hub
pip install -e ".[collab]"
cad-cli collab create --name review # seed a session over the current doc
cad-cli collab list
cad-cli collab annotate <session_id> "check the hole"
cad-cli collab perm <session_id> bob --role editor
# WebSocket transport (default port 8082)
python -m cad_mcp_server --transport ws --port 8082
MCP clients use cad_collab_session, cad_collab_branch,
cad_collab_annotation, cad_collab_presence, cad_collab_history,
cad_collab_resolve, cad_collab_permission and cad_collab_sync.
WebSocket clients speak a small JSON envelope (subscribe / op / sync /
ping) that maps onto the sync tool. A multi-client hub fans an applied
op out as a deltas broadcast to every subscriber of the same session
(excluding the origin sender, which already received its live response).
Batch & automation
Schedule jobs with a standard 5-field cron expression, dependency chains and webhook notifications; run scripts through a sandboxed engine; persist job state to SQLite:
# One-off job
cad-cli batch schedule commands.json --name report
# Cron job (daily at 02:00) using a built-in template
cad-cli batch schedule commands.json --cron "0 2 * * *"
# Run a sandboxed Python script
cad-cli batch run-script script.py --type python --timeout 30
# Inspect results
cad-cli batch list
cad-cli batch status <job_id>
cad-cli batch logs --source batch --job-id <job_id>
Scripts run in an isolated subprocess (python -I) with an import whitelist
(os, subprocess, socket, ... are blocked), a runtime sys.modules
guard and a hard timeout.
Docker
A multi-stage image (< 500 MB, python:3.11-slim) is provided in
docker/ for headless deployment:
docker compose -f docker/docker-compose.yml up -d
The container runs the MCP server over streamable HTTP on port 8081 with a
/health healthcheck, and mounts data/ + config/ volumes. Environment
overrides: CAD_RUNTIME, CAD_HEADLESS, CAD_TEMP_DIR, CAD_API_KEYS,
CAD_LOG_LEVEL, CAD_RATE_LIMIT_MAX, CAD_RATE_LIMIT_WINDOW.
Example MCP client configuration (Claude Desktop ~/.config/claude/mcp.json):
{
"mcpServers": {
"cad-server": {
"command": "python",
"args": ["-m", "cad_mcp_server", "--transport", "stdio"],
"autoApprove": [
"cad_object_read",
"cad_object_list",
"cad_status_check",
"cad_json_load",
"cad_json_validate",
"cad_validate_geometry",
"cad_metrics_get"
]
}
}
}
Development
bash scripts/setup_dev.sh # venv + editable install + stubs
bash scripts/run_tests.sh # ruff + mypy + pytest (coverage gate >= 80%)
bash scripts/build_docs.sh
Or run each gate directly:
ruff check . # lint
mypy src # type check
pytest # tests (coverage gate >= 80%)
Project Layout
src/cad_mcp_server/
|-- cli/ # typer CLI: commands + alias expansion
|-- mcp/ # MCP server, transports, security and tool registry
| |-- server.py # MCPServer wiring (103 tools)
| |-- transport.py # stdio / streamable HTTP (+ auth, rate limiting)
| |-- security.py # tool permission whitelist
| |-- auth.py # API-key authentication
| |-- rate_limit.py # sliding-window rate limiter
| `-- tools/ # crud, json_ops, status, validate, batch, boolean,
| # file_io, variables, render, versioning, nlp, view3d,
| # features, simulation
|-- core/ # document, entity, layer, kernel, session, history,
| # variables, scheduler, script_runner, batch_templates,
| # validation, versioning, view_manager, features, simulation,
| # assembly, drawing, constraint
|-- io/ # JSON / DXF / STL importers and exporters
|-- schemas/ # Pydantic geometry, scene and view3d schemas
|-- render/ # 2D / 3D PNG rendering, WebGL export, section, explode,
| # animation
`-- utils/ # logger, config, errors, validators, units, metrics
examples/
`-- threejs_viewer.html # browser viewer for WebGL exports
docker/
|-- Dockerfile # multi-stage image (python:3.11-slim)
|-- docker-compose.yml # service definition with healthcheck
`-- entrypoint.sh
tests/
|-- unit/ # CLI, core, IO, MCP tool unit tests
`-- integration/ # MCP e2e, batch, JSON workflow and performance tests
Documentation
readme/README.zh-CN.md— Chinese README
Continuous Integration
.github/workflows/ci.yml runs ruff + mypy on every push / PR,
pytest with the 80% coverage gate on Python 3.11 and 3.12, and a separate
stress job for the concurrency / soak suite. Pushing a v* tag triggers
.github/workflows/release.yml, which builds the Windows executables
(cad-cli.exe, cad-mcp-server.exe via PyInstaller) and the self-contained
Debian package (scripts/build_deb.py, bundles runtime wheels for Linux
amd64) and publishes them to a GitHub Release.
License
Apache License 2.0 — see LICENSE.
Community guidelines: Code of Conduct · Security: SECURITY.md · Contributing via pull requests is welcome.
Third-party runtime dependencies are all permissive-licensed (MIT / BSD /
Apache-2.0 / ISC / PSF, plus MPL-2.0 for certifi); the full inventory is in
THIRD_PARTY_LICENSES.md.
Optional backends: cadquery (Apache-2.0) is compatible. The optional
FreeCAD / OpenCASCADE backends are LGPL-2.1 and are not bundled; if you
enable them you must comply with the LGPL (retain notices, keep the library
re-linkable). The default AnalyticKernel is self-authored and fully
Apache-2.0.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cad_mcp_server-0.10.0.tar.gz.
File metadata
- Download URL: cad_mcp_server-0.10.0.tar.gz
- Upload date:
- Size: 190.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
737131a7c0e43b47e94aac0c6736cf3e5d28ae70ba9e2fede42c3e2d93c2020b
|
|
| MD5 |
fa9a93a0e2239f0f3a0fc65ae97ede93
|
|
| BLAKE2b-256 |
0914ff26afca125fea1c677c7a208d059710bc42bc99939f5f8b5e97692f2f97
|
Provenance
The following attestation bundles were made for cad_mcp_server-0.10.0.tar.gz:
Publisher:
release.yml on Tianshang301/TianshangCAD
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cad_mcp_server-0.10.0.tar.gz -
Subject digest:
737131a7c0e43b47e94aac0c6736cf3e5d28ae70ba9e2fede42c3e2d93c2020b - Sigstore transparency entry: 2341167770
- Sigstore integration time:
-
Permalink:
Tianshang301/TianshangCAD@46230b730ea987e40f424e76045719a8d410a2d0 -
Branch / Tag:
refs/tags/v0.10.0 - Owner: https://github.com/Tianshang301
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@46230b730ea987e40f424e76045719a8d410a2d0 -
Trigger Event:
push
-
Statement type:
File details
Details for the file cad_mcp_server-0.10.0-py3-none-any.whl.
File metadata
- Download URL: cad_mcp_server-0.10.0-py3-none-any.whl
- Upload date:
- Size: 233.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fc087cdeab83a379304ae5af2ac343067e71e14dd94aed455cd401a32f136fc1
|
|
| MD5 |
8f7c12314b41efb441a15614ecf7362e
|
|
| BLAKE2b-256 |
bc6a52554d61bb13e5df036d2aeff8ba512737afca3b0420a76d24d8789a262e
|
Provenance
The following attestation bundles were made for cad_mcp_server-0.10.0-py3-none-any.whl:
Publisher:
release.yml on Tianshang301/TianshangCAD
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cad_mcp_server-0.10.0-py3-none-any.whl -
Subject digest:
fc087cdeab83a379304ae5af2ac343067e71e14dd94aed455cd401a32f136fc1 - Sigstore transparency entry: 2341167780
- Sigstore integration time:
-
Permalink:
Tianshang301/TianshangCAD@46230b730ea987e40f424e76045719a8d410a2d0 -
Branch / Tag:
refs/tags/v0.10.0 - Owner: https://github.com/Tianshang301
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@46230b730ea987e40f424e76045719a8d410a2d0 -
Trigger Event:
push
-
Statement type: