Skip to main content
Glama
Power CAD MCP

Power CAD MCP

by khs0927

Power CAD MCP

AI 어시스턴트(Claude Desktop, Claude Code 등 MCP 클라이언트)가 AutoCAD 2027 도면을 읽고, 수정하고, 검증하도록 해 주는 Model Context Protocol 서버 모음입니다.

구성

위치

용도

power-cad-server + AutoCAD 2027 플러그인 (C#/.NET 10, 주력)

dotnet/

실도면 수정. AutoCAD 내부에서 트랜잭션으로 실행하고, 수정 직전 대상 확인·수정 직후 자동 검증·실패 시 롤백

power-cad-mcp (Python)

src/power_cad_mcp

COM 폴백 작도 및 파일 인벤토리(42개 도구)와 AutoCAD 없는 DXF/PNG/PDF 작도·미리보기, Ontology 건물 데이터 조회·도면 대조·블록 대조·인벤토리 대조·Graph RAG 질의응답(11개 도구)

best-cad-mcp (외부, 선택)

uvx --from best-cad-mcp cad-mcp

도면 의미·객체 관계 분석 — 별도 MCP 서버로 함께 연결

주력: power-cad-server (C#)

Claude ─stdio─▶ power-cad-server ─Named Pipe(토큰)─▶ PowerCad.Plugin.A27 (AutoCAD 2027 내부) ─▶ 도면 DB

도구 65개 (C# 0.5.0 preview):

분류

도구

프레임워크

cad_get_document_identity, cad_bind_document, cad_extract_snapshot, cad_query_page, cad_review_snapshot, cad_plan_create, cad_plan_get, cad_plan_execute

의미 컨텍스트

cad_context_query, cad_context_select, cad_context_actions, cad_context_action_select

Ontology (읽기 전용)

ontology_catalog, ontology_find_elements, ontology_blocks, ontology_drawings, ontology_element_context, ontology_search, ontology_ask, ontology_auto_context, ontology_locate, ontology_block_candidates — Python 서버와 같은 이름·인자·결과 형태(AutoCAD에 도면이 열려 있으면 in_open_drawing 표시, ontology_locate는 cad_* 편집 도구용 fingerprint도 함께 반환). POWERCAD_ONTOLOGY_URL을 설정해야 동작하며, 없으면 [ONTOLOGY_NOT_CONFIGURED] 오류를 돌려줍니다

연결

cad_status, cad_list_targets, cad_select_target

조회

cad_query(필터·group_by 집계·compact·within_mode·xdata 태그 필터), cad_get(XData 포함), cad_xdata_get(핸들별 XData 원문과 key→value tags), cad_inspect(단위·현재값·문자/치수 스타일·선종류·블록·범위), cad_layers

인벤토리

cad_inventory — 이름을 몰라도 모든 레이아웃(탭 순서·플롯 장치/용지·뷰포트/객체 수), 블록 정의(동적 블록 실제 이름·익명/레이아웃/XREF 여부·속성 정의·객체 종류별 개수·중첩 블록·레이아웃별 삽입 수), 레이아웃별 블록 참조(핸들·위치·회전·축척·레이어·속성값, 중첩 참조는 max_depth(기본 2)까지 경로 표시), XREF(경로·찾음/미해결 상태·부착/오버레이·중첩 그래프)를 읽기 전용으로 나열. XREF 파일은 열지 않으며 max_blocks·max_references·전송 크기 한도를 넘으면 *_truncated로 표시

작성

cad_create — line, polyline, circle, arc, text(justify·style·width_factor), mtext, insert, point, dimension(rotated/aligned, 스타일·문자 재지정), hatch(SOLID·ANSI31 등), 공통 color/linetype/lineweight · cad_create_many — 작도 계획 전체(최대 5000개)를 한 트랜잭션으로: 없는 레이어·문자 스타일·치수 스타일만 생성(기존 것은 변경하지 않음), insert.attributes, 객체별 hs 태그를 XData로 저장(기본 앱 HS-STEEL), offset, skip_missing_blocks, 생성 핸들 전부 재검증·실패 시 전체 롤백, dry_run 지원

수정

cad_replace_text, cad_move, cad_modify_opening, cad_set_properties(레이어·색·선종류·선가중치·문자 높이/회전/스타일/정렬), cad_copy(배열 복사), cad_transform(회전·축척·대칭, 문자는 읽히는 방향 유지), cad_offset(선·직선 폴리선·원·호 간격띄우기, count로 여러 줄), cad_delete

레이어

cad_set_layer(생성·색·선종류·선가중치·켜기/동결/플롯·현재 레이어, 잠금 해제는 사용자 확인 필요)

블록·패턴 자산

cad_block_library, cad_export_block, cad_import_block, cad_export_hatch_pattern(해치 패턴을 .pat로 내보내기)

측정

cad_measure(길이·둘레·면적(호 구간 포함)·경로 거리, mm 도면은 m² 병기 — 실면적표용)

화면

cad_zoom, cad_snapshot(모델 뷰를 PNG로 반환해 결과를 눈으로 확인)

묶음

cad_batch(최대 20단계를 한 트랜잭션으로, 위 수정 명령 모두 사용 가능)

HS-STEEL 자산

cad_hs_registry_status, cad_hs_assets, cad_hs_asset_get, cad_hs_section_info(읽기 전용) · cad_hs_styles_apply, cad_hs_block_place, cad_hs_section_draw, cad_hs_grid, cad_hs_members_place(작도, 바인딩·검증·롤백 동일) · cad_hs_member_list(XData 물량, 읽기 전용) · cad_hs_steel_prepare, cad_hs_steel_catalog_prepare. 설정: POWER_CAD_HS_REGISTRY 또는 POWER_CAD_HS_STEEL_ROOT(hs-steel-cad 레지스트리), HS_STEEL_ASSET_ROOT(PC별 원본 자산 루트, 예 C:\cad\HSSTEEL·C:\HS-STEEL), POWERCAD_ASSET_DB(공유 자산 DB 폴더, powercad.asset.card/v1). 없으면 내장 HS 표준(HS-* 레이어 15개, HS-KOR)으로 동작. 사용 지침: HS_STEEL_DRAWING_PLAYBOOK

저장

cad_save — 기본 copy: 열린 도면은 그대로 두고 DWG/DXF 사본 저장(기존 파일은 overwrite 필요) · save: 열린 도면 자체 저장(user_confirmed 필요)

시각 검증 (보조, 읽기 전용)

cad_visual_inspect, cad_visual_verify — 현재 뷰를 NVIDIA Cosmos Reason2로 확인. NVIDIA_COSMOS_ENDPOINT를 설정해야 동작하며, 결과는 참고용이라 수정을 승인하지 않습니다 (워크플로)

HS 강재 핸드오프 (읽기 전용)

cad_hs_steel_catalog_prepare(hs-steel-section-catalog/1 검증), cad_hs_steel_prepare(hs-steel-draw-plan/1 → cad_plan_create 단계로 변환, CAD는 수정하지 않음)

서버 옵션: power-cad-server [--simulate] [--target <autocad-2027-PID|PID>] [--read-only] [--home <dir>]. 같은 값을 환경 변수 POWER_CAD_SIMULATE, POWER_CAD_TARGET, POWER_CAD_READ_ONLY, POWER_CAD_HOME(검색 폴더, 기본 %LOCALAPPDATA%\PowerCad)으로도 줄 수 있고 CLI 플래그가 우선합니다. 블록 라이브러리 폴더는 기본 Documents\PowerCad\blocks이며 POWER_CAD_BLOCK_LIBRARY로 바꿉니다.

AutoCAD가 명령·대화상자로 바쁘면 20초 안에 CAD_BUSY로 답합니다(POWER_CAD_BUSY_TIMEOUT, 초 단위로 변경).

모든 수정은 같은 절차를 거칩니다: 지문으로 대상 확인 → 한 트랜잭션에서 변경 → 변경된 대상만 재검증 → 실패 시 전체 롤백 → before/after 보고. dry_run: true로 실제와 같은 조건의 미리보기를 받을 수 있습니다.

설치 (Windows, AutoCAD 2027)

git clone https://github.com/khs0927/power-cad-mcp
cd power-cad-mcp
powershell -ExecutionPolicy Bypass -File scripts\install_autocad_plugin.ps1

.NET 10 SDK가 없으면 winget으로 설치한 뒤 플러그인과 서버를 빌드하고, AutoCAD 번들을 %APPDATA%\Autodesk\ApplicationPlugins\PowerCad.bundle에 설치하고, Claude Desktop에 power-cad를 등록합니다. AutoCAD를 재시작한 뒤 명령줄에서 POWERCAD_STATUS로 확인하세요. 빌드 없이 쓰려면 Releases에서 PowerCad-<버전>-win-x64.zip을 받아 압축을 풀고, 그 폴더에서 powershell -ExecutionPolicy Bypass -File scripts\install_autocad_plugin.ps1 -SkipBuild를 실행합니다.

AutoCAD 없이 먼저 써 보기: power-cad-server --simulate (샘플 평면도: 벽, 실명, 동적 문, 창, 잠긴 레이어).

개발

./scripts/build_dotnet.sh          # restore → build(플러그인 포함) → 전체 테스트 → dist/PowerCad.bundle, dist/server/win-x64
dotnet test dotnet/PowerCad.Tests

Related MCP server: autocad-mcp

Codex 연결

OpenAI Docs의 MCP 등록 안내에 따라 빌드된 서버를 등록합니다.

powershell -ExecutionPolicy Bypass -File scripts\register_codex.ps1

개발용 시뮬레이터는 -Name power-cad-dev -Simulate로 별도 등록할 수 있습니다. 등록 전에 새 플러그인도 설치해야 실제 도면에서 새 계약을 사용할 수 있습니다.

새 서버에서는 cad_get_document_identity로 현재 도면 ID를 읽고 cad_bind_document로 고정한 뒤 수정합니다. document_id는 도면 DB의 FingerprintGuid에 묶여 있어 같은 세션에서 다시 조회해도 바뀌지 않습니다(database_fingerprint로도 확인 가능). 자세한 개발 상태·사용 순서·인수 조건은 프레임워크 운영 문서를 참조하세요.

보조: power-cad-mcp (Python)

  • AutoCAD 백엔드 (Windows) — 실행 중인 AutoCAD에 COM으로 붙어 실시간으로 그립니다.

  • Headless DXF 백엔드 (모든 OS) — AutoCAD 없이 ezdxf로 도면을 만들고 DXF/PNG/PDF/SVG로 저장합니다.

두 백엔드는 같은 42개 도구를 제공합니다.

demo

도구 목록 (Python)

분류

도구

세션/파일

drawing_census, cad_status, new_drawing, open_drawing, save_drawing, get_drawing_info, export_drawing, render_preview

레이어

list_layers, create_layer, update_layer, set_current_layer, delete_layer

작도

draw_line, draw_polyline, draw_rectangle, draw_polygon, draw_circle, draw_arc, draw_ellipse, draw_point, add_text, add_mtext, add_dimension, add_hatch, draw_batch

블록

list_blocks, create_block, insert_block

조회/편집

list_entities, get_entity, delete_entities, move_entities, copy_entities, rotate_entities, scale_entities, mirror_entities, offset_entity, set_entity_properties

화면/기타

zoom_extents, zoom_window, run_command

Ontology (읽기 전용)

ontology_catalog, ontology_find_elements, ontology_blocks, ontology_drawings, ontology_element_context, ontology_search, ontology_ask, ontology_auto_context, ontology_locate, ontology_block_candidates, ontology_census_check

save_drawing(path=...)·export_drawing은 열려 있는 도면 자신이 아닌 기존 파일을 덮어쓰지 않습니다. 교체하려면 overwrite=true를 명시하세요 (자동 승인되는 WRITE 도구가 도면 텍스트의 프롬프트 주입으로 사용자 파일을 덮어쓰는 것을 방지).

규칙:

  • 좌표는 [x, y] 또는 [x, y, z](도면 단위), 각도는 도(degree), +X 기준 반시계 방향입니다.

  • 생성된 모든 객체는 handle(16진 문자열)과 함께 반환되며, 이후 편집은 handle로 합니다.

  • 색상은 ACI 번호(0–256) 또는 이름(red, yellow, green, cyan, blue, magenta, white, bylayer …).

  • 많은 객체를 그릴 때는 draw_batch 한 번으로 처리하면 훨씬 빠릅니다 (AutoCAD 왕복 횟수 감소).

  • 상대 경로는 POWER_CAD_WORKSPACE(기본: 현재 폴더) 기준으로 해석되며, 확장자가 없으면 자동으로 붙습니다.

설치 (Python, Windows + AutoCAD 2027)

사전 조건: Windows 10/11, AutoCAD 2027 실행 중, Python 3.10+ (없으면 스크립트가 uv로 설치).

git clone https://github.com/khs0927/power-cad-mcp
cd power-cad-mcp
powershell -ExecutionPolicy Bypass -File scripts\setup_windows.ps1

스크립트가 하는 일: .venv 생성 → 패키지 설치 → AutoCAD 연결 확인(--check) → %APPDATA%\Claude\claude_desktop_config.json에 power-cad-py 서버 등록(기존 파일은 .bak으로 백업). 주력 C# 서버(power-cad, install_autocad_plugin.ps1이 등록)와 이름이 겹치지 않아 둘을 함께 쓸 수 있습니다. 다른 이름은 -Name으로 지정합니다. 끝나면 Claude Desktop을 재시작하세요.

수동 등록

Claude Desktop (%APPDATA%\Claude\claude_desktop_config.json):

{
  "mcpServers": {
    "power-cad-py": {
      "command": "uvx",
      "args": ["--from", "git+https://github.com/khs0927/power-cad-mcp", "power-cad-mcp"],
      "env": { "POWER_CAD_BACKEND": "autocad" }
    }
  }
}

Claude Code:

claude mcp add power-cad-py -e POWER_CAD_BACKEND=autocad -- uvx --from git+https://github.com/khs0927/power-cad-mcp power-cad-mcp

연결 확인

.venv\Scripts\power-cad-mcp.exe --backend autocad --check   # 상태 JSON 출력, 연결 실패 시 exit 1
python scripts\smoke_test_autocad.py                         # 새 도면에 테스트 도형을 그림

설정 (환경 변수)

변수

기본값

설명

POWER_CAD_BACKEND

auto

autocad / dxf / auto(Windows면 AutoCAD, 아니면 DXF)

POWER_CAD_PROGID

–

COM ProgID 지정(쉼표 구분). 기본 순서: AutoCAD.Application, .26(2027), .25, .24

POWER_CAD_LAUNCH

0

1이면 AutoCAD가 꺼져 있을 때 직접 실행

POWER_CAD_WORKSPACE

현재 폴더

상대 경로 기준 폴더

POWER_CAD_DXF_PATH

–

DXF 백엔드에서 시작 시 열/저장할 파일

POWER_CAD_ALLOW_COMMANDS

1

0이면 run_command 비활성화(차단 명령·보호 시스템 변수는 1이어도 항상 거부)

POWER_CAD_ALLOW_LISP

0

1이면 run_command에서 AutoLISP 식 허용(위험 함수는 계속 차단)

POWER_CAD_ONTOLOGY_ROOT

–

khs0927/Ontology 로컬 checkout 경로. 설정 시 C# 주력 서버에서 CAIR context 도구 활성화

POWER_CAD_ONTOLOGY_COMMAND

aec-mcp

Ontology MCP 실행 명령. ROOT가 설정된 경우 기본값 사용

POWER_CAD_ONTOLOGY_TIMEOUT

20

.NET 서버 전용: aec-mcp stdio 호출 제한시간(초, 1–120). Python REST 도구에는 POWERCAD_ONTOLOGY_TIMEOUT을 씁니다

POWER_CAD_BUSY_TIMEOUT

20

.NET AutoCAD 플러그인: AutoCAD가 명령·대화상자로 바쁠 때 CAD_BUSY로 답하기까지 기다리는 시간(초, 3–300)

POWER_CAD_SION_URL

–

Sion Ontology Platform의 HTTP base URL. 설정 시 Sion AEC federation을 우선 사용

POWER_CAD_SION_TIMEOUT

20

Sion AEC HTTP 호출 제한시간(초, 1–120)

POWER_CAD_SION_TOKEN

–

원격 Sion 호출용 Bearer token. loopback이 아닌 Sion URL에는 필수

POWERCAD_ONTOLOGY_URL

Python: http://127.0.0.1:58000 · C#: –

ontology_* 도구가 읽는 Ontology REST API 주소 (POWER_CAD_ONTOLOGY_URL도 인식). C# 서버는 설정하지 않으면 ontology_* 도구가 [ONTOLOGY_NOT_CONFIGURED]로 답합니다

POWERCAD_ONTOLOGY_TIMEOUT

10

Python·C# 서버: Ontology REST 호출 제한시간(초, 1–120). .NET aec-mcp용 POWER_CAD_ONTOLOGY_TIMEOUT과는 별개입니다

POWERCAD_ONTOLOGY_ASK_TIMEOUT

120

Python·C# 서버: ontology_ask(POST /v1/ask, 로컬 LLM 답변 생성) 전용 제한시간(초, 5–600). 일반 REST 제한시간보다 짧게 적용하지 않습니다

POWERCAD_ONTOLOGY_TOKEN

–

Python·C# 서버가 Ontology REST에 보내는 Bearer token. Ontology 서버의 AEC_API_TOKEN과 같은 값. Ontology의 scripts/ops/init-env.ps1 -SetUserEnv가 생성·설정 (보안 메모)

POWERCAD_ONTOLOGY_AUTO_CONTEXT

0

Python 서버: 1이면 draw_batch에 task가 있을 때 ontology_auto_context를 먼저 실행

POWERCAD_ONTOLOGY_LIVE_URL

–

테스트 전용: 설정하면 tests/test_ontology_live.py가 이 주소의 실제 Ontology API로 계약 검사를 실행(없으면 skip)

CLI 옵션: power-cad-mcp [--backend auto|autocad|dxf] [--workspace DIR] [--dxf-path FILE] [--launch] [--transport stdio|streamable-http|sse --host 127.0.0.1 --port 8765] [--check] [--version]

Sion / Ontology / CAIR 컨텍스트 연결

C#/.NET 10 주력 서버는 두 개의 읽기 전용 의미 컨텍스트 경로를 지원합니다.

  • POWER_CAD_SION_URL이 설정되어 있으면 Sion Ontology Platform의 /api/v1/aec/query를 우선 사용합니다.

  • Sion URL이 없으면 기존 POWER_CAD_ONTOLOGY_ROOT + aec-mcp 직접 연결을 사용합니다.

Sion 경로에서는 응답이 반드시 canonical=false, read_only=true여야 합니다. 이 계약을 만족하지 않으면 Power CAD가 컨텍스트를 거부합니다.

  1. cad_context_query가 Sion 또는 Ontology에서 CAIR global memory를 검색합니다.

  2. CAD 형식의 geometry_ref에서 handle 후보만 추출합니다.

  3. 후보마다 현재 AutoCAD에 cad_get을 호출해 실제 존재와 fingerprint를 검증합니다.

  4. 결과는 1, 2, 3… 번호가 붙은 context_id candidate space로 반환됩니다.

  5. cad_context_select(context_id, choice)가 선택 시점에 fingerprint를 다시 검증합니다.

  6. cad_context_actions(context_id, candidate_choice)가 현재 live entity에 허용되는 작업만 번호형 action-space로 반환합니다.

  7. cad_context_action_select(..., action_choice)가 번호를 실제 cad_get / cad_move / cad_replace_text / cad_modify_opening 중 하나로 해석하면서 fingerprint를 다시 검증합니다.

  8. 후보 선택과 action 선택 모두 may_execute_mutation=false입니다. 실제 수정은 기존 edit tool의 expect_fingerprint와 transaction/rollback 경계를 그대로 거쳐야 합니다.

골든 경로는 Ontology → Sion AEC federation → Power CAD live verification → AutoCAD transaction/rollback입니다. Ontology/GraphRAG/Sion 결과가 직접 AutoCAD를 수정할 수 없고, 오래된 지식이나 잘못된 매핑은 live CAD 재검증 단계에서 차단됩니다.

Ontology 건물 데이터 자동 조회 (Python·C# 서버)

Google Drive의 모든 DWG/DXF를 파싱해 둔 Ontology(aec_intelligence, Postgres + AGE + pgvector)를 읽기 전용 REST API로 조회합니다. 자동화를 시작할 때 문·창·벽·실, 상세도, CAD 블록을 사용자가 일일이 나열하지 않아도 관련 항목을 스스로 모아 옵니다.

설정:

  1. Ontology 쪽에서 REST API를 띄웁니다(Ontology docker compose up api 기본 http://127.0.0.1:58000).

  2. 다른 주소라면 POWERCAD_ONTOLOGY_URL을 지정합니다. 예: claude mcp add power-cad -e POWERCAD_ONTOLOGY_URL=http://127.0.0.1:58000 -- power-cad-mcp C# 주력 서버(power-cad-server)는 기본 주소가 없으므로 항상 지정합니다. 예: claude mcp add power-cad -e POWERCAD_ONTOLOGY_URL=http://127.0.0.1:58000 -- power-cad-server (C# 서버의 ontology_* 도구는 아래 표와 같은 이름·인자·결과를 돌려주며, 오류 문구 앞에 [ONTOLOGY_UNAVAILABLE]/[ONTOLOGY_FAILED] 같은 코드가 붙습니다. draw_batch 연결과 open_drawing 표시는 Python 서버에만 있습니다.)

  3. 서비스가 꺼져 있으면 각 도구는 Ontology service is not reachable at … 오류를 돌려주고, 작도 도구는 영향을 받지 않습니다.

도구

REST

용도

ontology_catalog

GET /v1/catalog

종류별 객체 수(한글 별칭 포함), 도면 분류, 레이어, 블록, 층, 프로젝트

ontology_find_elements

GET /v1/elements?kind=

Door/Window/Wall/Space/Column/Beam… 또는 문/창호/벽체; drawing_category·layer·block_name(와일드카드)·text·bbox 필터, next_cursor 페이지. 층·시트는 클라이언트에서 거릅니다 (2F=2층). Python 서버는 층을 storey=2층 파라미터로도 보내 두어, 서버 측 층 필터를 지원하는 API에서는 그대로 쓰입니다(현재 API는 무시)

ontology_blocks

GET /v1/blocks?name_like=

블록 정의, 사용 횟수, 속성 태그, 레이어, 예시 파일. category(Door, 창호…)는 인스턴스 분류로 거릅니다

ontology_drawings

GET /v1/drawings?category=

plan/detail/section/elevation/structural/schedule 또는 평면도/상세도/창호도…; 시트별 도면번호·도면명·축척

ontology_element_context

GET /v1/elements/{id}/context?hops=

객체와 1–2 hop 그래프 이웃(층·실·호스트 벽·시트·블록 정의)

ontology_search

POST /v1/search

어휘 + 벡터 + 그래프 하이브리드 검색 (top_k, kind, storey)

ontology_ask (Python·C#)

POST /v1/ask

Graph RAG 질의응답: 서버가 질문을 키워드/벡터/지식그래프 탐색/프로젝트 요약으로 라우팅하고, 로컬 LLM(Ollama)이 그 근거만으로 한국어 답을 만듭니다. 모든 답은 [C#] 인용(문서·레이아웃/시트·객체 id·bbox)을 달고, 근거가 없으면 refused: true. question, project_id?, top_k=12(1–30), generate=true를 두 서버에서 동일하게 사용합니다. generate=false면 LLM 없이 검색+발췌 답만. 인용된 object_ids는 ontology_locate로 열린 도면에서 찾습니다. 제한시간 POWERCAD_ONTOLOGY_ASK_TIMEOUT(초, 5–600, 기본 120)

ontology_auto_context

위 조합

작업 문장 하나로 필요한 자료 묶음을 한 번에 반환 (project_id, 검색 결과 수 k 지정 가능)

ontology_locate

GET /v1/elements/{id}/context + 열린 도면

Ontology 객체 id → 현재 열린 도면의 실제 handle 확인(읽기 전용)

ontology_block_candidates (Python·C#)

GET /v1/blocks + list_blocks

Ontology 블록 중 열린 도면에 정의가 있어 insert_block에 바로 쓸 수 있는 것 / 다른 파일에만 있는 것 구분(읽기 전용)

ontology_census_check (Python)

GET /v1/drawings + GET /v1/elements?document_id= + drawing_census

도면 파일의 census와 Ontology가 가진 같은 파일의 행 대조: 수집 여부, 핸들 차이, 레이어별 객체 수, 클래스별 수(ZIUM 레이어 포함). 맞대어 볼 수 없는 것은 not_comparable(읽기 전용, 파일을 쓰지 않음)

ontology_auto_context(task, drawing?, project_id?, k?)는 작업 문장(한국어/영어)에서 키워드로 대상을 추론합니다. project_id를 주면 객체·도면·블록·검색 호출 모두 그 프로젝트로 한정합니다.

  • 문/도어/door → Door, 창/창문/window → Window, 창호 → Window+Door, 벽/벽체/wall → Wall, 실/방/room → Space

  • 기둥 → Column, 보 → Beam, 철골/H-형강 → SteelSection+구조도, 계단·슬래브

  • 평면/상세/단면/입면/구조/리스트·일람표 → 도면 분류, 블록/심볼 → 블록 목록

  • 2층/2F/지하1층/B1F/옥상 → 층, AW-02 같은 부호 → 검색어

예: "2층 평면도 문 리스트 갱신" → 2F의 Door 객체, 평면도·일람표 시트, Door 블록, 검색 결과를 한 번에 받습니다. 층/시트/부호 필터로 결과가 없으면 해당 클래스 전체로 넓히고 warnings에 이유를 남깁니다. 검색은 추론한 클래스(하나일 때)와 층을 kind/storey 필터로 함께 보냅니다. API는 층을 정확히 일치로 비교하고 층 정보가 없는 도면도 많으므로, 층 필터로 결과가 없으면 층 없이 다시 찾습니다. API가 질의 전체를 한 구절로 비교하기 때문에 작업 문장으로 결과가 없으면 부호·도면·클래스 단어로 다시 검색하는데, 클래스 단어는 그 클래스를 kind로 묶어 보내므로 창이 창고, 실이 화장실에 걸리지 않습니다. 이때 warnings에는 실제로 보낸 키워드만 남깁니다. 도면이 열려 있으면 묶음의 검색 결과·객체마다 in_open_drawing(원본 파일이 지금 열린 도면인지)이 붙고, open_drawing과 counts.in_open_drawing이 함께 옵니다. 열린 도면을 알 수 없으면(예: AutoCAD 미실행) 이 표시는 조용히 생략됩니다.

Ontology 객체 → 도면 handle (ontology_locate)

Ontology 객체에는 handle, document_id, source_file이 있지만 handle은 도면 하나 안에서만 고유합니다. 다른 도면의 handle을 그대로 move_entities에 넘기면 엉뚱한 객체가 바뀔 수 있으므로, 편집 전에 ontology_locate(element_ids)로 확인합니다.

  • 객체마다 /v1/elements/{id}/context로 행을 받아 source_file과 열린 도면(get_drawing_info의 name/path)을 비교합니다. 양쪽 모두 폴더가 있으면 전체 경로(구분자 \=/, 겹친 / 정리, 대소문자 무시, .dwg/.dxf/.dwt/.dws 확장자 무시)를 비교하고, 한쪽이 파일 이름뿐이면 파일 이름만 비교합니다(A-201.dwg = a-201.DXF). 이름이 같아도 열린 도면이 저장되지 않았거나(경로 없음) 기본 이름(Drawing1 등)이면 같은 파일이라고 증명할 수 없으므로 other_drawing("open drawing is unsaved/default-named; cannot prove it is the source file")입니다.

  • 같은 도면이면 모델 공간에서만 handle을 찾고(레이어 레코드·블록 정의 안·종이 공간 객체는 "없음"), 엔티티 종류·레이어·블록 이름이 객체 클래스에 맞는지 봅니다 (예: 블록 DOOR_SINGLE인 문인데 LINE이면 불일치, 문인데 DIMENSION/TEXT면 불일치, 실(Space)은 TEXT 허용). matched에는 긍정 근거가 하나 이상 필요합니다: 알려진 클래스(문·창·벽·기둥·실·주석 등), 같은 레이어, 또는 같은 블록 이름(익명 *U… 참조 포함).

  • 결과 status: matched(편집 가능) · unverified(반대 근거도 긍정 근거도 없음 — 편집에 쓰지 않음) · mismatch(handle은 있으나 대상이 달라 보임, reasons) · handle_missing(같은 도면 모델 공간에 없음, 다른 배치 탭 등) · other_drawing(다른 파일, 열린 도면 없음, 미저장/기본 이름 — handle을 조회조차 하지 않음) · not_found(Ontology에 없는 id, 또는 API가 다른 객체를 돌려줌 — error: "API returned element …"). ./.. 같은 id는 오류로 거부합니다.

  • 각 결과에 element_id, handle, source_file, open_drawing, entity(종류·레이어·블록 이름·위치 요약)가 있고, matched_handles에 편집 가능한 handle만 모읍니다.

  • 도면을 절대 수정하지 않습니다.

권장 흐름:

  1. ontology_auto_context(task) — 대상 후보를 모으고 in_open_drawing으로 지금 도면의 것인지 확인

  2. 필요하면 해당 도면을 open_drawing으로 연 뒤 ontology_locate(element_ids) — status="matched"인 handle만 고름

  3. get_entity / move_entities / delete_entities / set_entity_properties 등 편집 도구에 그 handle을 넘김

자동화 진입점 연결: draw_batch(operations, task="…", auto_context=true)로 호출하거나 POWERCAD_ONTOLOGY_AUTO_CONTEXT=1을 켜면 작도 전에 ontology_auto_context(task)가 실행되어 결과의 ontology_context에 붙습니다. 서비스가 꺼져 있어도 작도는 그대로 진행되고 ontology_context.available=false와 오류 문구만 남습니다. 조회가 성공하면 ontology_targets도 붙습니다: 묶음 안의 객체를 추가 Ontology 호출 없이 ontology_locate와 같은 규칙으로 열린 도면에 대조해, matched인 객체의 element_id·class·name·handle·엔티티 종류와 상태별 개수(counts)를 요약합니다. 작도 작업 자체는 바뀌지 않습니다. Ontology 결과는 참고 정보이므로, 실제 수정에는 matched handle만 쓰세요.

Ontology 블록 → insert_block (ontology_block_candidates)

insert_block은 열린 도면에 정의된 블록 이름만 받습니다. ontology_block_candidates(name_or_task, project_id?, limit?)는 Ontology 블록 카탈로그(/v1/blocks)와 열린 도면의 블록 정의(list_blocks)를 대조합니다. 도면을 수정하지 않고, 다른 파일에서 정의를 가져오지도 않습니다.

  • name_or_task: 블록 이름/와일드카드(DOOR* → name_like) 또는 작업 문장("문 블록 배치" → 인스턴스가 Door로 분류된 블록). 공백 없는 단어(문, door)는 이름과 분류 두 가지로 찾습니다.

  • 이름 비교는 대소문자를 무시하고 블록의 effective_names도 봅니다(동적 블록은 *U12 같은 익명 이름으로 저장되기 때문).

  • insertable: 열린 도면에 정의가 있음 → insert_name을 그대로 insert_block(name=…)에 넘깁니다(base_point, entity_count 포함). 이름 질의에 맞지만 Ontology에 없는 도면 내 블록도 note와 함께 여기에 나옵니다.

  • other_files: 다른 도면에만 있음 → example_files에 있는 파일을 열어 작업하거나, 사용자가 블록을 직접 가져와야 합니다. Ontology가 이 도면에서 읽었다고 하는데 지금 정의가 없으면(purge/이름 변경) note로 알려 줍니다.

  • not_insertable: XREF(Ontology 쪽이든 열린 도면의 같은 이름 정의든), effective name 없는 익명 블록. 블록 테이블을 읽지 못하면 unverified에 두고 warnings에 이유를 남깁니다.

도면 인벤토리 ↔ Ontology (ontology_census_check, Python 서버)

drawing_census(로컬, 파일의 모든 객체)와 Ontology(수집된 건물 데이터)는 따로 만든 인벤토리입니다. ontology_census_check(path, census_json?, project_id?, standard?)는 같은 파일을 두고 둘을 대조합니다. 파일도 도면도 바꾸지 않습니다.

  • 문서 찾기: /v1/drawings의 name/source_key를 파일명으로 비교(대소문자 무시, .dwg = .dxf). 여러 개면 project_id → 높은 리비전 → 최근 수집 순으로 고르고 나머지는 other_documents.

  • handles: handle이 있는 Ontology 요소를 census의 entity_index에서 찾습니다. only_in_ontology는 수집 후 파일이 바뀐 것(또는 다른 리비전), only_in_census_*는 Ontology가 요소로 만들지 않은 레이아웃 객체(치수·일반 선 등 — 결함 아님). 블록 정의 내부와 ATTRIB은 제외합니다.

  • layers: Ontology Layer 행의 entity_count/block_entity_count와 census의 레이아웃/블록 정의 객체 수 → equal/differs/not_in_ontology.

  • classes: 클래스별 Ontology 요소 수 옆에 같은 레이어의 census 객체 수와 ZIUM 표준 레이어(문 DOOR, 창 WIN·WINBAR, 벽 WAL1~3, 계단 STAIR, 실 실명)의 객체 수. 객체 수 ≠ 요소 수이므로 일치 판정은 하지 않습니다. 정확한 대조는 handles입니다.

  • not_comparable: handle 없는 Ontology 행(문서·레이어·뷰), 블록 내부, 기둥·구조벽이 섞인 ZIUM COL, 표준 없이 만든 census 등 — 이유와 함께.

  • 파일이 수집 시각 이후 수정됐거나 census_json이 다른 파일의 것이면 warnings에 남깁니다. entity_index가 없는 예전 census.json은 drawing_census를 다시 돌리세요.

COM 편집 플랜에서 Ontology id 쓰기 (scripts/com_plan_runner.py)

com_plan_runner.py의 플랜(docs/playbooks/*.plan.json)은 대상을 handle + 예상 형상으로 고정합니다. op마다 elements를 두면 handle 대신(또는 함께) Ontology 객체 id로 대상을 지정할 수 있습니다.

{"id": "D1", "op": "delete", "elements": {"@door": "obs_18a…", "AA4": "obs_33b…"},
 "expect": {"@door": "AcDbBlockReference", "AA4": "AcDbPolyline"}}
  • @로 시작하는 키는 자리표시자로, 그 op의 expect 키·handles·handle에서 확인된 handle로 바뀝니다.

  • 그 밖의 키는 플랜에 이미 적힌 handle이며, 객체가 정확히 그 handle로 확인되어야 합니다.

  • 검증 전에 Ontology REST API(--ontology-url, 없으면 POWERCAD_ONTOLOGY_URL, 기본 http://127.0.0.1:58000)에서 객체를 받아 ontology_locate와 같은 규칙(원본 파일 = 열린 도면, handle 존재, 엔티티 타당성)으로 대조합니다. 하나라도 matched가 아니거나 쓰이지 않는 키·같은 handle로 겹치는 대상이 있으면 {"ok": false, "stage": "resolve"}로 플랜 전체를 거부합니다(unverified도 거부, 해석 중 예외도 traceback 없이 stage:"resolve").

  • elements가 없어도 한 op 안에서 같은 handle을 두 번 적으면(aa4와 AA4처럼 대소문자만 달라도) 검증 단계에서 거부합니다.

  • 그 뒤 기존 예상 형상 검사가 확인된 handle에 그대로 실행되고, 결과에 resolved(키 → id → handle)가 붙습니다. elements가 없는 플랜은 Ontology에 접속하지 않습니다.

보안

run_command는 AutoCAD 명령줄에 그대로 입력을 보냅니다. 도면 속 텍스트가 프롬프트에 섞여 들어올 수 있으므로 AutoCAD 밖으로 나갈 수 있는 명령(SHELL, START, SCRIPT, APPLOAD, NETLOAD, VBARUN, QUIT 등)은 항상 차단되고, 보안 관련 시스템 변수(SECURELOAD, TRUSTEDPATHS, MTEXTED 등 PROTECTED_SYSVARS)는 어떤 형태로도 바꿀 수 없고, AutoLISP는 기본적으로 꺼져 있습니다. 필요 없다면 POWER_CAD_ALLOW_COMMANDS=0으로 완전히 끌 수 있습니다.

POWER_CAD_ALLOW_COMMANDS 기본값을 1로 유지하는 이유: run_command는 MCP destructive 주석이 붙어 있어 클라이언트가 실행 전 사용자 승인을 받고, OS·코드 로딩으로 나가는 경로(차단 명령, 보호 시스템 변수, LISP)는 기본값에서도 막혀 있습니다. 남는 위험은 열린 도면 안의 편집(되돌리기 가능)뿐인데, 끄면 FILLET/OFFSET 옵션처럼 전용 도구가 없는 작업을 전혀 할 수 없습니다. 도면을 무인으로 일괄 처리하거나 신뢰할 수 없는 도면 텍스트를 다룰 때는 0으로 두세요.

구조

src/power_cad_mcp/
  server.py            MCP 도구 정의 (MCPServer, mcp SDK 2.x)
  backends/base.py     백엔드 인터페이스 (handle 기반, 각도=도)
  backends/com_backend.py   AutoCAD COM: 전용 STA 스레드, busy 재시도(IMessageFilter), 오류 변환
  backends/dxf_backend.py   ezdxf headless 백엔드 + 렌더링
  safety.py            run_command 필터
  ontology.py          Ontology REST 클라이언트(urllib), 작업 문장 키워드 추론, auto_context 묶음, 객체→도면 handle 대조(locate)
  census.py            drawing_census: 파일의 모든 객체 인벤토리(census.json)
  census_check.py      census ↔ Ontology 대조(ontology_census_check)
  source_binding_acceptance.py  Ontology 핸드오프 → 실행 전 준비 상태 검증(실행 권한은 부여하지 않음)
  config.py · errors.py · geometry.py · colors.py   설정, 오류 변환, 기하 계산, 색 이름
tests/
  fake_acad.py         AutoCAD COM 객체 모델 모사 → COM 백엔드를 Linux CI에서도 검증
  test_live_autocad.py 실제 AutoCAD 대상 테스트 (옵트인)

COM 객체는 스레드(아파트먼트)에 묶여 있고 MCP 런타임은 동기 도구를 임의의 워커 스레드에서 실행하므로, 모든 AutoCAD 호출은 하나의 전용 STA 스레드로 모아서 실행합니다. AutoCAD가 바쁠 때(RPC_E_CALL_REJECTED)는 COM 메시지 필터가 자동으로 재시도하며, 도형을 만드는 호출은 중복 생성을 막기 위해 통째로 재실행하지 않습니다.

개발

uv venv && uv pip install -e ".[dev]"
pytest                     # DXF end-to-end, 가짜 AutoCAD COM, stdio 프로세스, Ontology 계약, 유닛 (실기 AutoCAD·실제 Ontology API 테스트는 옵트인)
ruff check . && ruff format --check .
python -m build            # dist/*.whl, dist/*.tar.gz
python examples/demo_floor_plan.py            # headless 데모 → examples/out/
python examples/demo_floor_plan.py --backend autocad   # 실행 중인 AutoCAD에 그리기

실제 AutoCAD 테스트 (Windows):

$env:POWER_CAD_LIVE_TESTS = "1"; pytest -m autocad -v

실제 Ontology API와의 계약 테스트 (도면이 하나 이상 적재된 API가 필요, 읽기 전용):

POWERCAD_ONTOLOGY_LIVE_URL=http://127.0.0.1:58000 pytest tests/test_ontology_live.py -v

문제 해결

  • Could not attach to a running AutoCAD — AutoCAD가 실행 중이고 도면 하나가 열려 있는지 확인하세요. AutoCAD와 MCP 서버는 같은 사용자, 같은 권한 수준이어야 합니다(한쪽만 "관리자 권한으로 실행"이면 COM 연결 실패).

  • AutoCAD stayed busy — 명령 실행 중이거나 대화상자가 열려 있습니다. AutoCAD에서 Esc를 누르고 다시 시도하세요.

  • PDF 내보내기 — DWG To PDF.pc3 플로터를 사용해 도면 범위를 용지에 맞춰 출력합니다.

  • DXF로 내보내기(AutoCAD) — AutoCAD의 SaveAs를 사용하므로, 원래 DWG가 있다면 다시 원래 파일로 저장해 활성 문서를 되돌립니다.

License

MIT

Available Tools

41 tools
add_dimensionC

Dimension the distance between p1 and p2 (aligned, or linear/horizontal/vertical).

Inputs: p1 (required), p2 (required), location (required), kind, +4 more. Returns: object

add_hatchC

Fill a closed boundary with a hatch pattern or solid fill.

Inputs: boundary (required), angle, color, layer, +2 more. Returns: object

add_mtextB

Add multiline text (MTEXT) with its top-left corner at the insertion point.

Inputs: text (required), insert (required), color, layer, +2 more. Returns: object

add_textB

Add single-line text at the insertion point (left baseline).

Inputs: text (required), insert (required), color, layer, +2 more. Returns: object

cad_statusA
Read-onlyIdempotent

Report the active backend (AutoCAD over COM, or headless DXF), connection and open drawing.

Inputs: no named parameters. Returns: object

copy_entitiesB

Copy entities, offsetting the copies by a displacement vector. Returns the new entities.

Inputs: handles (required), displacement (required). Returns: result

create_blockC

Define a new block from existing model-space entities.

Inputs: name (required), handles (required), base_point (required), delete_source. Returns: object

create_layerB

Create a layer (or update it if it exists) and optionally make it current.

Inputs: name (required), color, linetype, lineweight, +1 more. Returns: object

delete_entitiesC
Destructive

Erase entities.

Inputs: handles (required). Returns: object

delete_layerC
Destructive

Delete an unused layer.

Inputs: name (required). Returns: object

draw_arcB

Draw a circular arc counter-clockwise from start_angle to end_angle.

Inputs: center (required), radius (required), end_angle (required), start_angle (required), +3 more. Returns: object

draw_batchB

Create many entities in one call. Returns the created entity (or error) for every operation.

Inputs: operations (required), stop_on_error. Returns: object

draw_circleC

Draw a circle.

Inputs: center (required), radius (required), color, layer, +1 more. Returns: object

draw_ellipseC

Draw a full ellipse.

Inputs: ratio (required), center (required), major_axis (required), color, +2 more. Returns: object

draw_lineC

Draw a straight line segment.

Inputs: end (required), start (required), color, layer, +1 more. Returns: object

draw_pointC

Place a POINT entity.

Inputs: location (required), color, layer. Returns: object

draw_polygonA

Draw a regular polygon as a closed polyline.

Inputs: sides (required), center (required), radius (required), color, +3 more. Returns: object

draw_polylineB

Draw a polyline through the points (2D lightweight polyline; 3D if Z varies).

Inputs: points (required), color, layer, closed, +1 more. Returns: object

draw_rectangleA

Draw an axis-aligned rectangle (closed polyline) from two opposite corners.

Inputs: corner1 (required), corner2 (required), color, layer, +1 more. Returns: object

export_drawingB

Export the drawing: AutoCAD → pdf/dwg/dxf/png/bmp/wmf; headless → dxf/png/pdf/svg.

Inputs: path (required), format. Returns: object

get_drawing_infoB
Read-onlyIdempotent

Name, path, units, current layer, entity count and extents of the active drawing.

Inputs: no named parameters. Returns: object

get_entityB
Read-onlyIdempotent

Get one entity's type, layer, color and geometry by handle.

Inputs: handle (required). Returns: object

insert_blockC

Insert a block reference.

Inputs: name (required), insert (required), color, layer, +2 more. Returns: object

list_blocksA
Read-onlyIdempotent

List block definitions available for insert_block.

Inputs: no named parameters. Returns: result

list_entitiesB
Read-onlyIdempotent

List model-space entities with their geometry (filtered, up to limit).

Inputs: layer, limit, entity_type. Returns: object

list_layersA
Read-onlyIdempotent

List layers with color, linetype and on/frozen/locked/current state.

Inputs: no named parameters. Returns: result

mirror_entitiesA

Mirror entities across the line p1-p2 (keeps the originals unless delete_source).

Inputs: p1 (required), p2 (required), handles (required), delete_source. Returns: result

move_entitiesB

Move entities by a displacement vector [dx, dy(, dz)].

Inputs: handles (required), displacement (required). Returns: result

new_drawingA

Create a new, empty drawing and make it active.

Inputs: template. Returns: object

offset_entityB

Create a parallel copy (OFFSET) of a line, arc, circle or polyline.

Inputs: handle (required), distance (required). Returns: result

open_drawingB

Open an existing drawing and make it active.

Inputs: path (required). Returns: object

render_previewA
Read-onlyIdempotent

Render the current drawing to a PNG image so you can check the result visually.

Inputs: no named parameters.

rotate_entitiesB

Rotate entities about a base point.

Inputs: angle (required), handles (required), base_point (required). Returns: result

run_commandA
Destructive

Send raw input to the AutoCAD command line (AutoCAD backend only). Shell/script/loader commands are blocked; AutoLISP needs POWER_CAD_ALLOW_LISP=1.

Inputs: command (required). Returns: object

save_drawingA

Save the active drawing (optionally under a new name).

Inputs: path. Returns: object

scale_entitiesB

Scale entities uniformly about a base point.

Inputs: factor (required), handles (required), base_point (required). Returns: result

set_current_layerA

Make a layer current; new entities without an explicit layer go there.

Inputs: name (required). Returns: object

set_entity_propertiesB

Change an entity's layer, color, linetype or lineweight.

Inputs: handle (required), color, layer, linetype, +1 more. Returns: object

update_layerA

Change a layer's color/linetype, turn it on/off, freeze/thaw, lock/unlock or rename it.

Inputs: name (required), on, color, frozen, +3 more. Returns: object

zoom_extentsB

Zoom the view to show the whole drawing.

Inputs: no named parameters. Returns: object

zoom_windowA

Zoom the view to the window spanned by two corners.

Inputs: p1 (required), p2 (required). Returns: object

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    B3.1/5.0

    Scored across 41 tools

    Disambiguation4/5

    Each tool targets a distinct action+resource: drawing primitives, entity edits (move/copy/rotate/scale/mirror), and layer operations are cleanly separated. Minor overlap between create_layer (which also updates) and update_layer, and draw_batch vs individual draw_* tools, but boundaries remain readable.

    Naming Consistency4/5

    Overwhelmingly consistent verb_noun pattern (draw_line, list_entities, create_layer, zoom_extents). Only minor deviations like cad_status (noun-first) and get_drawing_info break the otherwise predictable scheme.

    Tool Count3/5

    41 tools is heavy for a single server, though CAD genuinely spans drawing, layers, blocks, entity editing, views and export so most tools earn their place. Still, the surface could be trimmed or further consolidated (e.g. more batch variants).

    Completeness4/5

    Strong lifecycle coverage: drawing setup, primitives, layer management, blocks, entity CRUD and transforms, viewing and export. Gaps like trim/extend/fillet and undo are notable but not blocking for core workflows.

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      A
      quality
      D
      maintenance
      Enables reading, analyzing, and editing CAD files (DXF and DWG) via natural language, including entity queries, layer management, and safe copy-based edits.
      17
      1
      MIT
    • A
      license
      A
      quality
      B
      maintenance
      Enables an AI assistant to conversationally control Autodesk AutoCAD, drawing, inspecting, and editing plans, and includes a cross-platform DXF engine that runs without AutoCAD on macOS and Linux. It exposes tools for rendering views as images, batching geometry, blocks, and structures, measuring and checking plans, and undoing whole batches.
      12
      MIT