diff --git a/README.md b/README.md index dab5a32..9500230 100644 --- a/README.md +++ b/README.md @@ -3,80 +3,65 @@ # AutoCAD MCP Pro **Production-grade AutoCAD automation for AI agents.** -Live through COM on Windows, or headless through ezdxf on any platform — one typed contract, two engines. +Live through COM on Windows, or headless through ezdxf anywhere — one typed contract, two engines. [](https://github.com/U-C4N/Autocad-MCP/actions/workflows/ci.yml) [](https://pypi.org/project/autocad-mcp-pro/) [](https://pypi.org/project/autocad-mcp-pro/) [](https://github.com/U-C4N/Autocad-MCP/blob/main/pyproject.toml) -[](https://github.com/jlowin/fastmcp) [](https://github.com/U-C4N/Autocad-MCP/blob/main/LICENSE) -[](https://github.com/U-C4N/Autocad-MCP/stargazers) -[Install](https://github.com/U-C4N/Autocad-MCP#install-in-10-seconds) · [Evidence](https://github.com/U-C4N/Autocad-MCP#evidence) · [Two engines](https://github.com/U-C4N/Autocad-MCP#the-two-engines) · [Limits](https://github.com/U-C4N/Autocad-MCP#what-this-release-is-bad-at) · [Config](https://github.com/U-C4N/Autocad-MCP#configuration) · [Changelog](https://github.com/U-C4N/Autocad-MCP/blob/main/CHANGELOG.md) +[Install](#install) · [Tools](#what-you-get) · [Engines](#the-two-engines) · [Evidence](#evidence) · [Limits](#what-this-release-is-bad-at) · [Config](#configuration) · [Changelog](https://github.com/U-C4N/Autocad-MCP/blob/main/CHANGELOG.md) - - ---- - -
+
Not a mockup. Every line on this sheet was drawn by the tools this server exposes — ISO layers, involute gear geometry, DIN 6885 keyway, section A-A, ISO 129 dimensions, an ISO 286 H7 bore fit, ISO 7200 title block — then rendered headlessly by view_screenshot. drawing_critique returns 0 issues on it. Rebuild it with python scripts/render_readme_showcase.py.
| Area | What it does |
|---|---|
| Drawing lifecycle | create, open, save, export DXF/PDF, audit (now repairs), purge; undo/redo live on COM and opt-in headless via EZDXF_UNDO_DEPTH |
| Geometry | lines, arcs, polylines, splines, hatches, trim/extend/fillet/chamfer, handle-preserving edits |
| Annotation | ISO 129 toleranced dimensions, ISO 286 fits (fit="H7"), TABLE, MLEADER, GD&T frames and datums (ISO 1101) |
| Engineering generators | involute gears (front + section A-A), DIN 6885 keyed bores, ISO A3 title block |
| Discovery ✨ | search_tools ranked over an AutoCAD command and synonym corpus — FILLET, BPOLY, QSELECT, WBLOCK, OVERKILL, CHSPACE each rank #1 of the 154-tool registry |
| Batching ✨ | cad_batch runs a whole step list in one round trip; fields= projects the response on 11 result-heavy tools (a closed, gated list) |
| Paper space ✨ | 8 of the 12 layout tools are new — layout_delete/rename/copy, viewport_list/set_scale/lock/delete, entity_change_space (CHSPACE, headless only); layout listing, creation and activation, viewport_create and drawing_export_pdf(layout=...) shipped in v1.4.0, which wrongly declared headless viewport rendering impossible |
| Selection ✨ | window vs crossing stated back to the caller; the polygon is tested as a shape, not as its bounding box — the entity side is still its bounding box, on both engines |
| Boundaries ✨ | boundary_trace (BOUNDARY/BPOLY) chains loose edges into one closed polyline; ARC edges keep their exact bulges, while a bulged polyline segment or any other curved edge is chained as its chord — headless engine only |
| Measurement ✨ | analysis_measure_entity measures what is in the drawing, by handle |
| Hatch depth ✨ | gradients, in-place edits and island styles on both; typed edge boundaries headless only |
| Annotation objects ✨ | WIPEOUT, REVCLOUD, MTEXT background masks — headless only, ActiveX exposes no member — plus text find/replace on both |
| 3D solids | solid_box/cylinder/extrude/revolve/boolean on live AutoCAD (ENABLE_3D=true) — unverified against a live seat: they shipped in v1.4.0, and the v1.5.0 live run covered only what that release added |
| Quality loop | drawing_preflight → drawing_plan → drawing_critique → drawing_refine → drawing_finalize (0–100 score) |
| Delivery | drawing_deliver: DXF/PDF/PNG + SHA-256 manifest + reopen-parity checks |
entity_creation 18, entity_modification 15, layers 14, analysis 12, layouts 12, premium 12, drawing 11, engineering 10, blocks 8, entity_query 8, system 7, dimensions 5, solids 5, corner_ops 4, view 4, batch 3, transactions 3, templates 2, validation 1.
+154 tools in 19 groups. Plus 6 resources that cost nothing in the tool budget (autocad://drawing/info, layers, blocks, entities/stats, entities/{layer_name}, system/status) and 5 prompt templates.
-Alongside the tools, **6 MCP resources** cost nothing in the tool budget and are browsable at any time — `autocad://drawing/info`, `autocad://layers`, `autocad://blocks`, `autocad://entities/stats`, `autocad://entities/{layer_name}`, `autocad://system/status` — plus **5 prompt templates** (`prompt_mechanical_drawing`, `prompt_floor_plan`, `prompt_electrical_schematic`, `prompt_pid_diagram`, `prompt_quick_drawing`).
-
-### Two rules worth knowing before you draw
-
-**Coordinates come out in WCS, and the exceptions are declared rather than hidden.** DXF stores CIRCLE / ARC / LWPOLYLINE / TEXT / INSERT geometry in a per-entity frame, and before v1.5.0 the word `extrusion` appeared nowhere in this codebase, so a mirrored or rotated entity reported coordinates that were quietly wrong. An entity in a plane tilted out of WCS XY now reports `plane_normal` and omits the fields xy cannot express, rather than answering with a number that looks fine.
-
-Three things stay in the entity frame on purpose, and `system_capabilities`' `ocs_normalized` reason string is the live list: **TEXT `rotation`** (a mirrored TEXT is mirror-imaged, and no single scalar angle expresses that), **z components**, and **HATCH boundary geometry**. On the live backend that same reason string also records `2d_polyline_coordinates_not_verified_against_live_autocad` — read it at runtime rather than trusting this paragraph.
-
-**Never read vertices back and shoelace them.** That loses **28.2%** of the area on a semicircular edge, silently. `analysis_measure_entity(handle)` reads the real geometry and states its own accuracy: `exact`, `flatten_tolerance`, `assumed_closed`, `self_intersecting`.
+**Two rules worth knowing.** Every coordinate in and out of a tool is WCS on both engines — the one exception is TEXT `rotation`, which stays in the entity frame because a mirrored TEXT is mirror-imaged and no scalar angle expresses that. And never read vertices back and shoelace them: that loses **28.2%** of the area on a semicircular edge, silently. `analysis_measure_entity(handle)` reads the real geometry and states its own accuracy.
## The two engines
-One contract, split across 19 modules in `backends/contracts/`. Most are ABCs; `gdt.py` and `settings.py` are concrete shared mixins rather than interfaces. Optional methods are declarative — `@capability(key, reason=...)` supplies a default that *refuses* — and a test holds the two backends' capability key sets equal, so a key cannot exist on one engine and be forgotten on the other.
-
-There are **27 capability keys**. `system_capabilities` returns the live map, and you should read it at runtime rather than trusting the table below, because five of the 27 depend on how the machine is set up:
+One contract across 19 modules in `backends/contracts/`. `@capability(key, reason=…)` supplies a default that *refuses*, and a test holds both backends' capability key sets equal. There are **27 capability keys**; read `system_capabilities` at runtime rather than trusting the table — five of them depend on how the machine is set up.
| Capability | COM (live AutoCAD) | ezdxf (headless) |
|---|:---:|:---:|
| Live document control | ✅ | — |
| Cross-platform, no AutoCAD | — | ✅ |
-| Transactions and rollback | ✅ *undo mark; rollback sends `_UNDO B` and AutoCAD never confirms it landed — best-effort, not atomic* | ✅ *full DXF snapshot, restored synchronously* |
+| Transactions and rollback | ✅ | ✅ |
| Paper-space layouts + viewports | ✅ | ✅ |
-| Viewport model-content rendering | ✅ | ✅ ᵐ *(no viewport borders)* |
+| Viewport model-content rendering | ✅ | ✅ ᵐ *(no borders)* |
| Selection window / crossing / polygon | ✅ | ✅ |
| Entity area by handle | ActiveX `.Area` | Analytic, bulges included |
-| HATCH filled area (islands subtracted) | AutoCAD's own number — *measured: a r20 hatch with an r10 island returns 942.478, so the island is subtracted* | Loops walked, `hatch_style` reported |
-| REGION area | ✅ *`.Area` + `.Perimeter`, verified on a seat* | — *ACIS is opaque to ezdxf* |
-| 3DSOLID **surface** area | — *ActiveX exposes `.Volume` only; use MASSPROP* | — |
-| 3D solids | ✅ *only with `ENABLE_3D=true`* | — *no headless ACIS* |
-| DWG write | ✅ | — *no DWG writer* |
-| WIPEOUT | — *`AddWipeout` verified absent, AutoCAD 2026* | ✅ |
-| MTEXT background colour | — *`BackgroundFillColor` verified absent, AutoCAD 2026* | ✅ |
-| REVCLOUD, BPOLY / boundary tracing | — *no ActiveX member; command-line only* | ✅ |
-| CHSPACE (`entity_change_space`) | — *unverified against a live seat* | ✅ ᶜ |
-| Undo history | ✅ | opt-in — `EZDXF_UNDO_DEPTH` defaults to `0` |
+| HATCH filled area (islands subtracted) | AutoCAD's own number | Loops walked, `hatch_style` reported |
+| REGION / 3DSOLID area | ✅ | — *ACIS is opaque to ezdxf* |
+| 3D solids | ✅ *with `ENABLE_3D=true`* | — |
+| DWG write | ✅ | — |
+| WIPEOUT · MTEXT background colour | — *verified absent, AutoCAD 2026* | ✅ |
+| REVCLOUD · BPOLY · typed hatch edges | — *no ActiveX member* | ✅ |
+| CHSPACE | — *unverified on a live seat* | ✅ ᶜ |
+| Undo history | ✅ | opt-in — `EZDXF_UNDO_DEPTH` |
| TABLE and MLEADER | Native | Portable composite |
-| Raw commands / AutoLISP | ✅ *on by default, denylist-sanitized — `DANGEROUS_COMMANDS_ENABLED=true` removes the denylist* | — *no live command line* |
-| Screenshots and PDF export | AutoCAD window capture | Matplotlib render ᵐ |
+| Screenshots and PDF | Window capture | Matplotlib ᵐ |
-ᵐ Needs matplotlib — the `[pdf]` or `[full]` extra. Without it `png`, `pdf`, `viewport_render` and `handle_overlay` all report unsupported on the headless engine.[pdf]/[full]); without it png, pdf, viewport_render and handle_overlay report unsupported headlessly.