AutoCAD MCP Pro
AutoCAD MCP Pro
Production-grade AutoCAD automation for AI agents. Live through COM on Windows, or headless through ezdxf anywhere — one typed contract, two engines.
Install · Tools · Engines · Evidence · Limits · Config · Changelog
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.
v1.5 release snapshot: 154 tools · 6 resources · 5 prompt templates · 1369 collected tests. 154 is the registered count; a default install advertises 149 over
tools/list, becauseENABLE_3Dis unset.system_aboutis the runtime authority.
Why this exists
A big MCP server is expensive to be connected to. The full catalog costs a client 40,305 tokens before it has asked for anything. Discovery mode replaces it with two tools and costs 356.
A drafter searches for FILLET, not entity_fillet. Those command names appeared in no tool name or description — df = 0 against a stock index, not badly ranked but absent. The fix was data: an authored corpus of 158 AutoCAD command names and 672 synonym phrases covering all 154 tools. A test refuses to let a tool exist without one.
Advertised surface | Tools seen | Idle cost |
| 149 | 40,305 tokens |
| 47 | 12,131 tokens |
| 2 | 356 tokens |
Offline ratio estimates, not tokenizer counts, and theuncached ratio — prompt caching amortises the idle term. benchmarks/token_suite.py --tokenizer anthropic counts for real.
Install
pip install autocad-mcp-pro # or: uvx autocad-mcp-pro
autocad-mcp # stdio MCP server, backend auto-selectedAUTOCAD_MCP_BACKEND=ezdxf autocad-mcp # portable DXF engine, no AutoCAD needed
AUTOCAD_MCP_BACKEND=com autocad-mcp # live AutoCAD (needs the [com] extra)Extra | Pulls in | For |
(none) |
| Headless DXF on any OS — no rendering |
|
| Live AutoCAD control + window capture |
|
| PDF export and headless PNG, any platform |
| everything above | Development and CI |
The bare installcannot draw pixels — ezdxf.addons.drawing imports Pillow unconditionally, so every render path needs it. Add [pdf] for images on Linux or macOS.
{
"mcpServers": {
"autocad": {
"command": "autocad-mcp",
"env": {
"AUTOCAD_MCP_BACKEND": "auto",
"ALLOWED_PATHS": "C:\\Users\\you\\Documents\\AutoCAD",
"TOOL_PROFILE": "full",
"DISCOVERY_MODE": "off"
}
}
}
}Claude Desktop, Cursor, or any stdio MCP host. For HTTP: autocad-mcp --transport http --port 8000 — loopback only unless remote HTTP is explicitly enabled and a bearer token is set.
What you get
Area | What it does |
Drawing lifecycle | create, open, save, export DXF/PDF, audit (repairs), purge, undo/redo |
Geometry | lines, arcs, polylines, splines, hatches, trim/extend/fillet/chamfer, handle-preserving edits |
Annotation | ISO 129 toleranced dimensions, ISO 286 fits ( |
Engineering generators | involute gears (front + section A-A), DIN 6885 keyed bores, ISO A3 title block |
Discovery |
|
Batching |
|
Paper space | tab lifecycle, viewports, |
Selection | window vs crossing stated back to the caller; a polygon tested against its own shape, not its bounding box |
Boundaries |
|
Measurement |
|
Hatch depth | gradients, in-place edits, typed edge boundaries (headless), island styles |
Annotation objects | WIPEOUT, REVCLOUD, MTEXT background masks (headless), text find/replace |
3D solids |
|
Quality loop |
|
Delivery |
|
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.
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 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 | ✅ | ✅ |
Paper-space layouts + viewports | ✅ | ✅ |
Viewport model-content rendering | ✅ | ✅ ᵐ (no borders) |
Selection window / crossing / polygon | ✅ | ✅ |
Entity area by handle | ActiveX | Analytic, bulges included |
HATCH filled area (islands subtracted) | AutoCAD's own number | Loops walked, |
REGION / 3DSOLID area | ✅ | — ACIS is opaque to ezdxf |
3D solids | ✅ with | — |
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 — |
TABLE and MLEADER | Native | Portable composite |
Screenshots and PDF | Window capture | Matplotlib ᵐ |
ᵐ Needs matplotlib ([pdf]/[full]); without it png, pdf, viewport_render and handle_overlay report unsupported headlessly. ᶜ Headless CHSPACE carries four named restrictions in its capability reason: top-view untwisted viewports only, dimensions refused unless frozen, ACIS/proxy/table refused, viewport clipping reported rather than applied.
Every COM path added in v1.5 was executed against alive AutoCAD 2026. That run found four defects reading could not — the largest being that AcadPViewport has no ViewCenter member, so the line setting it had been silently swallowed by a bare except since v1.4.
Evidence
Self-measurement, produced by scripts in benchmarks/.
Correctness — every release re-proves itself
26 deterministic headless checks against the previous tag and the current tree, each in its own subprocess so a hard crash counts as a miss rather than killing the run.
Version | Checks passing | Pass rate | Fixed | Regressed |
v1.5.0 (baseline) | 24 / 26 | 92.3 % | — | — |
v1.5.1 (this release) | 26 / 26 | 100 % | 2 | 0 |
Against the older v1.4.0 baseline the same suite reports 21 / 26 → 26 / 26, five fixed, zero regressed. Three of the five are new capability (miss → pass); two are repaired defects (fail → pass) — the diameter and radius callouts, which measured the leader as geometry and dimensioned a 40 mm bore as 60 at default settings.
The task matrix — five tasks that can fail
An earlier matrix scored this server 10/10, which carried no information: every task in it exercised something the server was built around. Five were added because they can fail, and three did while being written.
Task | Verified against |
| six AutoCAD command names, each ranking #1 |
| 40,305 → 356 tokens, against a ceiling fixed in advance |
| 300 filled with the island, 400 ignoring it |
| window 1, crossing 2, bounding box 3, polygon 1 |
| 139.2699 against the 100.0 a vertex shoelace gives |
Headless performance
Workloads call the same backend methods the MCP tools call, so server-side overhead is included. Numbers move with hardware; the report records the machine fingerprint. Read the next section before quoting them — this release is slower than v1.4.0 at creating entities, on purpose.
What this release is bad at
A page that only lists strengths is a page that has not been measured.
Entity creation is slower than v1.4.0. Median of three runs on one machine and interpreter: 2,000 lines 1.4× slower, the 10,000-line roundtrip 2.3× slower. Attributed — setting EZDXF_CALL_TIMEOUT=0 returns creation to v1.4.0's numbers. The cost is the per-call asyncio.wait_for wrapped around every headless call so one hung call can no longer wedge a server whose document lock is a single asyncio.Lock. Deliberate trade, documented knob, on the 1.6 roadmap. The premium quality pass went the other way — 3.7× faster.
Wave A shipped 13 tools of a planned 39. Every cut is backed by a measurement. The REGION and 2D-boolean family went because add_region() produces a REGION with zero ACIS bytes, and the greiner_hormann substitute loses 28.2% of the area on a square with one semicircular edge.
system_run_command / system_run_lisp are a guardrail, not a security boundary — the rejection message says so in those words. A 36-verb denylist refuses the obvious cases, but AutoCAD accepts hundreds of commands and DANGEROUS_COMMANDS_ENABLED=true switches it off entirely.
Path validation is per-tool, and unscoped until you scope it. With ALLOWED_PATHS empty — the default — the only positive bound is a ten-entry system-directory denylist that does not include C:/Users, /home, /root or /var. Set ALLOWED_PATHS.
Non-AutoCAD ProgIDs are unverified. CAD_PROGID changes which COM application the backend attaches to; nothing beyond the connection has been tested against BricsCAD, ZWCAD or GstarCAD.
Configuration
Nothing loads a .env file — export these, or set them in your MCP client's env block.
Variable | Default | Purpose |
|
|
|
|
| COM ProgID the live backend attaches to |
|
|
|
|
|
|
|
| Expose the opt-in |
|
| Python logging level |
| (empty) | Comma-separated absolute paths the server may access |
|
| Maximum retained undo snapshots |
|
| Headless undo history depth; |
|
| Reject larger DXF input; |
|
| Bound list/selection response sizes |
|
| Per-call live AutoCAD timeout (s); |
|
| Per-call headless timeout (s); |
|
| Allow blocked commands/LISP; reported as unsafe mode |
|
| Permit a non-loopback HTTP bind |
| (empty) | Bearer token required for remote HTTP |
Architecture
flowchart LR
A[MCP host / AI agent] --> B[FastMCP 3 server]
B --> C[Error · audit · timing · logging · capability-refusal middleware]
C --> D[Typed contract · 19 modules · 27 capabilities]
D --> E[COM backend<br/>single-STA thread]
D --> F[ezdxf backend<br/>asyncio.to_thread]
E --> G[Live AutoCAD]
F --> H[Headless DXF]
E --> I[Engineering · critique · scoring · delivery]
F --> IThe sequence in scripts/render_readme_showcase.py, which produced the hero sheet:
drawing_new() ISO linetypes + layers bootstrapped
drawing_apply_iso_layers("mech") ISO 128 lineweights per layer
drawing_settings({units: "mm", linear_precision: 2})
gear_draw_spur_front_view( involute flanks, not a decorated circle
module=6, teeth=24, center=[135, 172],
bore_diameter=40, keyway_width=12, keyway_depth=3.3)
gear_draw_section_aa(x_offset=300, face_width=46)
dimension_linear(...) ISO 129
dimension_diameter(..., fit="H7") deviations from authored ISO 286 tables
titleblock_apply_iso_a3(title="SPUR GEAR m6 z24", material="C45E", ...)
drawing_critique(focus=None) -> [] must be empty before finalize
view_screenshot() -> PNGThe full production loop adds drawing_preflight and drawing_plan at the front, drawing_refine after the critique, and layout_create + viewport_create + drawing_deliver at the end.
Development
uv sync --locked --all-extras
uv run pytest
uv run ruff check . && uv run ruff format --check .uv.lock pins the whole transitive graph, so this reproduces CI exactly. CI runs Linux (3.11 / 3.12), Windows (mocked-COM), plus package, Docker and MCP-registry jobs; the release gate runs the same three test lanes before anything reaches PyPI. Releases are tag-driven: git tag vX.Y.Z && git push origin vX.Y.Z.
Roadmap (1.6)
Give back the creation throughput the per-call timeout costs — arm it only for calls that can actually block. ISO 286 interference shafts r/s/t/u. HATCH boundary geometry in entity_get (1.5 measures a hatch's filled area but does not hand back its loops). REGION/3DSOLID area headlessly, which needs a modelling kernel ezdxf does not have. An allowlist of permitted AutoLISP heads, replacing the denylist — enumerating dangerous symbols does not terminate. ezdxf.recover as a fallback on drawing_open.
Features ship when their contracts and limitations are testable — not when they make a longer checklist.
Star History
Author
Umutcan Edizsalan · Mechanical engineering work at Anka-Makine · GitHub @U-C4N
Built from production drawing work, then made model-agnostic through MCP.
License
mcp-name: io.github.u-c4n/autocad-mcp
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/U-C4N/Autocad-MCP'
If you have feedback or need assistance with the MCP directory API, please join our Discord server