Content
AutoCAD MCP Server — Production README
========================================
## Architecture
A Model Context Protocol (MCP) server that connects an LLM (Gemini CLI, Claude Desktop)
directly to a running AutoCAD instance via COM automation. The AI can read the drawing state,
draw architectural elements, annotate, dimension, manage files, and undo its own mistakes.
```
LLM Agent (Gemini/Claude)
↕ JSON-RPC (stdio)
FastMCP Server (server.py)
↕
AutoCAD COM Client (autocad_client.py)
↕ win32com VARIANT SafeArrays
AutoCAD 2022-2025 (Windows)
↕
Mock CAD Engine (fallback for macOS/offline)
```
## Quick Start
### macOS / Linux (Development Mode)
```bash
# Install dependencies
pip3 install mcp pyyaml pytest
# Run in mock/simulation mode
AUTOCAD_MOCK=1 python server.py
```
### Windows (Live AutoCAD)
```bash
# Install Windows COM dependencies
pip install pywin32 mcp pyyaml
# Run — will auto-connect to running AutoCAD
python server.py
```
### Gemini CLI Configuration
Add to `~/.gemini/config.yaml`:
```yaml
mcpServers:
autocad:
command: python
args:
- /path/to/autocad_mcp_server/server.py
env:
AUTOCAD_MOCK: "0" # "1" for offline testing
```
## Available Tools (40 Total)
### Context & Query
| Tool | Description |
|------|-------------|
| `get_drawing_summary` | Drawing layers, entity count, extents, unit info |
| `get_drawing_units` | Current unit system (mm/inches/feet) and conversion factors |
| `query_entities` | Read model space entities with layer/type filtering |
| `query_entities_fast` | High-performance SelectionSet query for large drawings |
| `get_spatial_summary` | Bird's-eye grid map of drawing for LLM spatial reasoning |
### Drawing Primitives
| Tool | Description |
|------|-------------|
| `draw_line` | Single line entity |
| `draw_polyline` | Multi-vertex polyline |
| `draw_circle` | Circle by center + radius |
| `draw_arc` | Arc by center, radius, start/end angles |
| `draw_rectangle` | Axis-aligned rectangle (closed polyline) |
### Semantic Architecture
| Tool | Description |
|------|-------------|
| `draw_wall` | Double-line wall (center axis + thickness) |
| `create_room` | Complete room: 4 walls + doors + windows + label |
| `cleanup_wall_junctions` | Fix overlapping wall corners (L/T/cross junctions) |
| `calculate_room_area` | Floor area in m² and ft² |
| `label_room` | Place room name + area at centroid |
| `apply_architectural_template` | Configure AIA standard layers |
### Block Management
| Tool | Description |
|------|-------------|
| `insert_architectural_block` | Insert door/window/column/furniture block |
| `snap_block_to_grid` | Snap to structural grid then insert block |
| `align_block_to_wall_segment` | Place door/window along wall axis |
| `list_available_blocks` | See all blocks in library and drawing |
| `load_block_from_file` | Import block from external .dwg file |
### Modification
| Tool | Description |
|------|-------------|
| `modify_entity` | Move/scale/rotate/delete/reLLayer by handle |
| `copy_entity` | Copy by displacement vector |
| `array_entity_rectangular` | Create rectangular array of copies |
| `mirror_entity` | Mirror across a line |
### Annotation
| Tool | Description |
|------|-------------|
| `add_text` | Single-line text entity |
| `add_mtext` | Multi-line text with word wrap |
| `add_linear_dimension` | Linear H/V dimension |
| `add_aligned_dimension` | Aligned dimension (follows angle) |
| `add_hatch` | Hatch fill (ANSI31, AR-CONC, etc.) |
### Layer & Style
| Tool | Description |
|------|-------------|
| `set_layer_properties` | Color (ACI), linetype, lineweight, frozen/locked |
| `load_linetype` | Load DASHED/CENTER/HIDDEN from acad.lin |
### File I/O
| Tool | Description |
|------|-------------|
| `save_drawing` | Save active document |
| `save_drawing_as` | Save to new path (dwg/dxf/dwt) |
| `open_drawing` | Open .dwg file |
| `new_drawing` | Create new drawing (optional template) |
| `export_to_pdf` | Export to PDF |
### Undo/Redo
| Tool | Description |
|------|-------------|
| `undo_last_action` | Undo the last AI tool call atomically |
| `redo_last_action` | Redo the previously undone action |
### Maintenance
| Tool | Description |
|------|-------------|
| `purge_drawing` | Purge unused drawing definitions |
## Configuration
Edit `config.yaml` in the server directory:
```yaml
units:
preferred_input: "mm" # Unit LLM should use for dimensions
fallback_drawing_unit: "mm" # If INSUNITS=0 (unitless drawing)
architecture:
default_wall_thickness: 200.0 # mm
default_door_width: 900.0
default_window_width: 1200.0
block_library:
search_paths:
- "./blocks/" # Local block library directory
- "${AUTOCAD_BLOCK_LIB}" # Optional env var path
```
## Standard Layers (AIA Convention)
| Layer | Color | Purpose |
|-------|-------|---------|
| `A-WALL` | Yellow (2) | Architectural walls |
| `A-DOOR` | Cyan (4) | Doors |
| `A-GLAZ` | Green (3) | Windows/glazing |
| `S-COLS` | Red (1) | Structural columns |
| `S-GRID` | Gray (8) | Structural grid lines |
| `A-ANNO-DIMS` | Magenta (6) | Dimensions |
| `A-ANNO-TEXT` | White (7) | Text and labels |
| `A-WALL-PATT` | Gray (9) | Wall hatch patterns |
| `I-FURN` | Blue (5) | Interior furniture |
## Running Tests
```bash
# Unit tests (no AutoCAD required)
AUTOCAD_MOCK=1 python -m pytest tests/ -v
# Specific test files
python -m pytest tests/test_coordinate_utils.py -v
python -m pytest tests/test_unit_engine.py -v
python -m pytest tests/test_wall_solver.py -v
python -m pytest tests/test_tools_mock.py -v
# With coverage report
AUTOCAD_MOCK=1 python -m pytest tests/ -v --cov=. --cov-report=html
```
## File Structure
```
autocad_mcp_server/
├── server.py — MCP tool definitions (~40 tools)
├── autocad_client.py — COM client + Mock CAD Engine
├── com_helpers.py — VARIANT type conversion + thread lock
├── coordinate_utils.py — Geometry math, snapping, wall corners
├── unit_engine.py — Unit detection and conversion
├── block_library.py — Block file discovery and import
├── wall_solver.py — Wall junction cleanup algorithms
├── undo_manager.py — Undo/redo group manager
├── config.py — YAML config loader
├── config.yaml — Default configuration
├── blocks/ — Block .dwg file library
├── tests/
│ ├── test_coordinate_utils.py
│ ├── test_unit_engine.py
│ ├── test_wall_solver.py
│ └── test_tools_mock.py
└── requirements.txt
```
## Critical Bug Fixes Applied (vs. v1.0)
| Bug | File | Fix |
|-----|------|-----|
| B1: `math` not imported | `server.py` | Added `import math` |
| B2: `math.to_degrees` monkey-patch | `coordinate_utils.py` | Fixed chained assignment |
| B3: COM VARIANT type mismatch | `autocad_client.py` | All coord args use `to_variant_point()` |
| B4: Missing `functools.wraps` | `autocad_client.py` | Added `@functools.wraps(func)` |
| B5: Redundant `CoInitialize` | `autocad_client.py` | COM init once in `connect()` |
## Known Limitations
- PDF export via SendCommand may require user interaction on some AutoCAD versions.
Alternative: Use `save_drawing_as` with DXF format for contractor exchange.
- Hatch pattern AppendOuterLoop has version-specific behavior in AutoCAD 2022+.
In production, verify with AutoCAD 2024 on Windows.
- Arc/circle snap modes are not implemented in `snap_to_entities` for endpoint/quadrant snapping.