Skip to main content
Glama
Yuri-Fernando

Engineering-CAD-AI MCP Server

README.md
# 📐 Engineering-CAD-AI — de pedido em linguagem natural a revisão CAD verificada, com aprovação humana

### Python · ezdxf · Pydantic · FastAPI · MCP · Claude (opcional) · pytest · GitHub Actions

[![ci](https://github.com/Yuri-Fernando/Engineering-CAD-AI/actions/workflows/ci.yml/badge.svg)](https://github.com/Yuri-Fernando/Engineering-CAD-AI/actions/workflows/ci.yml)
![testes](https://img.shields.io/badge/testes-113%20passam%20%C2%B7%201%20opt--in-0a8a0a)
![readback](https://img.shields.io/badge/readback-9%2F9%20checks-0a8a0a)
![escopo](https://img.shields.io/badge/escopo-DXF%202D-2a78d6)
![versão](https://img.shields.io/badge/vers%C3%A3o-v0.1.0-4a5563) ![license](https://img.shields.io/badge/license-MIT-4a5563)

## 🟡 Status

🟡 **MVP técnico funcional — DXF → Engineering IR → plano tipado → aprovação → revisão nova verificada.**
O fluxo completo roda offline, sem licença de CAD e sem chave de API: 113 testes passam (1 teste opt-in
com o Claude real fica pulado por custo) e a demo grava a revisão B com os 9 checks de releitura em PASS.
AutoCAD, FreeCAD e Creo estão com contrato definido e marcados `CAD_REAL_NOT_RUN` (sem instalação
licenciada); busca híbrida e similaridade ainda não foram iniciadas.

| Área | Estado | Evidência |
|---|---|---|
| Parser DXF + Engineering IR v1 | ✅ implementado e testado | [`test_parser.py`](tests/test_parser.py), golden escrito à mão |
| Plano tipado + validador determinístico | ✅ implementado e testado | [`test_intent_and_validation.py`](tests/test_intent_and_validation.py) |
| Aprovação + copy-on-write + readback | ✅ implementado e testado | [`test_workflow.py`](tests/test_workflow.py), [relatório da demo](docs/evidence/demo_report.md) |
| API, MCP, CLI | ✅ implementado e testado | [`test_api.py`](tests/test_api.py), [`test_mcp_server.py`](tests/test_mcp_server.py) |
| Planner Claude | 🟡 testado com cliente falso | chamada real é opt-in |
| AutoCAD / FreeCAD / Creo | ⛔ `CAD_REAL_NOT_RUN` | [ADR 0002](docs/adr/0002-adaptadores-cad.md) |

---

## Descrição / Contexto

Em engenharia mecânica, boa parte do trabalho repetitivo é alterar desenhos: acrescentar um furo,
mover uma feature, anotar uma revisão. Pedir isso direto a um modelo de linguagem é arriscado — o
modelo erra geometria, não deixa rastro e pode sobrescrever o arquivo errado. OCR sobre o desenho
também é o caminho errado quando o arquivo é vetorial: a geometria exata já está no DXF.

Este repositório implementa a alternativa: **o modelo (opcional) só interpreta a intenção; código
determinístico lê e calcula a geometria; um validador decide; um humano aprova o plano exato; o
adaptador CAD grava uma revisão nova e o resultado é reaberto e conferido.** Tudo com evidência
(`dxf:handle:<H>`), hashes e trilha de auditoria.

Nome: *Engineering Document & CAD Intelligence* (EDCI) é o nome do escopo; o pacote Python é `engcad`.

---

## 🧭 Origem do Projeto

O projeto nasceu de uma pesquisa sobre como ligar agentes de IA a sistemas CAD
([docs/research/integracao-agentes-cad.md](docs/research/integracao-agentes-cad.md)): APIs do AutoCAD
(.NET, AutoLISP/COM, Design Automation), Creo (VB API/J-Link/CREOSON), FreeCAD, CAD-como-código
(ezdxf, CadQuery, build123d) e cerca de vinte servidores MCP comunitários conferidos no GitHub.

Conclusões que definiram o projeto:

1. O padrão que funciona é **plano tipado + execução determinística + verificação**, não "o LLM
   desenha por coordenadas".
2. **CAD-como-código / arquivo neutro** é o caminho mais robusto para começar: headless, versionável,
   testável e sem licença.
3. Vários servidores MCP de CAD expõem `execute_lisp`/`execute_python` — na prática, um shell. As
   anotações MCP são dicas, não controle: a segurança tem de morar no servidor.
4. Texto de desenho (carimbo, notas) é **dado não confiável** e pode conter prompt injection.
5. Integração com CAD comercial só se declara pronta depois de testada na instalação real.

Plano com gates de evidência: F0 base → F1 IR → F3 plano → F4 execução segura (MVP estrito, concluído)
→ F2 conhecimento → F5 similaridade → F8 adaptadores comerciais ([ROADMAP.md](ROADMAP.md)).

---

## 🎯 Objetivo

- Ler DXF sem perder nada: entidades suportadas viram IR tipado; as demais ficam registradas.
- Nunca inventar: unidade desconhecida, campo ausente ou pedido ambíguo resultam em `None`,
  `UNITS_UNKNOWN` ou `NEEDS_CLARIFICATION`.
- Converter pedido → operações de uma allowlist fechada, validadas por geometria determinística.
- Exigir aprovação humana vinculada ao hash do plano e ao SHA da fonte.
- Gravar sempre em arquivo novo e provar por releitura que só mudou o que foi aprovado.
- Expor tudo por CLI, API e MCP sem dar ao agente ferramentas de aprovação ou execução de código.

---

## 🔬 Linha de Pesquisa / Desenvolvimento

- Representação intermediária de desenho técnico com proveniência por entidade.
- Planejamento de alterações CAD por LLM com saída estruturada e abstenção.
- Validação geométrica 2D (ponto-em-polígono, folga ao contorno, colisão de furos).
- Segurança de agentes com ferramentas (MCP fechado, prompt injection em artefatos, aprovação humana).
- Verificação pós-escrita por oráculo independente (readback + invariantes).

---

## 🏗️ Arquitetura

```text
 DXF ─► sniff de formato ─► parser ezdxf ─► Engineering IR v1 ─────────────┐
 PDF/imagem ─► ponte ocr_core (opcional) ─► evidências de carimbo          │
                                                                           ▼
 pedido ─► planner ├─ determinístico (regex pt/en)                 ActionPlan (allowlist)
                   └─ Claude (opcional, desligado por padrão) ──►  plan_hash · base_sha
                                                                           │
                         validador determinístico + invariantes ◄──────────┤
                         simulação ─► diff de entidades ─► preview SVG     │
                                                                           ▼
                         aprovação humana (HMAC local, CLI/API) ─► APPROVED
                                                                           │
                         revalida a fonte (TOCTOU) ─► adaptador CAD ─► arquivo staging
                                                                           │
                         readback independente ─► 9 checks ─► rename atômico
                                                                           ▼
                         manifest.json · report.md · audit.jsonl · nova revisão no workspace
```

| Módulo | Função | Teste |
|---|---|---|
| `parser_dxf.py` | DXF → IR, unidades, carimbo, contorno/furos por regra | `test_parser.py` |
| `ir.py` | contrato Engineering IR v1 (Pydantic + JSON Schema) | `test_parser.py` |
| `intent.py` | pedido → operações ou perguntas | `test_intent_and_validation.py` |
| `plan.py` | ActionPlan, allowlist, `plan_hash` | `test_intent_and_validation.py` |
| `validate.py` | regras geométricas, invariantes, simulação | `test_intent_and_validation.py` |
| `approval.py` | aprovação HMAC vinculada a plano + base | `test_workflow.py` |
| `adapters/` | protocolo, ezdxf, mock, stubs comerciais | `test_adapters_contract.py` |
| `verify.py` | readback e checks | `test_adapters_contract.py` |
| `service.py` | workspace, estados, auditoria, execução | `test_workflow.py` |
| `api.py` · `mcp_server.py` · `cli.py` | interfaces | `test_api.py`, `test_mcp_server.py` |
| `llm.py` · `ocr_bridge.py` | integrações opcionais | `test_llm_and_bridges.py` |

Estados do plano: `PROPOSED → APPROVED → EXECUTING → COMPLETED`, com `NEEDS_CLARIFICATION`,
`REJECTED` e `FAILED` terminais. Transições fora da tabela são recusadas (`INVALID_STATE`).

---

## ⚙️ Funcionamento

1. **Ingestão** — o arquivo é identificado pelo conteúdo, copiado como somente leitura para
   `sources/<rev>/` e convertido em IR (`rev-<sha16>`).
2. **Plano** — o pedido vira operações tipadas; faltando diâmetro, posição, layer ou alvo, o plano
   fica `NEEDS_CLARIFICATION`.
3. **Validação** — contorno com folga de 0,1 mm, colisão com furos existentes e novos, layer existente,
   handle existente, contorno protegido; os invariantes são calculados aqui, não pelo modelo.
4. **Preview** — simulação em memória, diff por handle e SVG (verde = novo, vermelho = removido,
   laranja = movido).
5. **Aprovação** — humano aprova o plano exato; o registro assina `plan_id|plan_hash|base_sha|aprovador|data`.
6. **Execução** — confere aprovação e SHA, re-lê a fonte, revalida, grava em staging pelo adaptador,
   reabre o arquivo e checa os invariantes; só então renomeia para o nome final.
7. **Evidência** — manifest, relatório Markdown e eventos de auditoria ligam fonte, plano, aprovação e saída.

```text
"adicione furo central Ø10 em (60,40)"
  → add_circle{center_mm:(60,40), diameter_mm:10, layer:HOLES}   (layer herdado dos furos existentes)
  → valid: dentro do contorno, sem colisão → invariantes: 11 preservadas, +1, CIRCLE 4→5
  → aprovado por humano → plate_revA__<plan>.dxf → readback 9/9 PASS → fonte com o mesmo SHA
```

---

## 🧠 Verificação / Modelagem

| Camada | O que prova | Resultado |
|---|---|---|
| Golden da peça A | parser lê exatamente a geometria especificada (valores escritos à mão, independentes do parser) | 4 furos Ø10, cota 120 mm, carimbo DEMO-001/SUP-001/A |
| Referência rev B | a saída gerada é geometricamente igual à peça B construída independentemente | só o texto `REV` difere |
| Readback | o arquivo gravado contém só a alteração aprovada | 9/9 checks na demo |
| Oráculos negativos | o verificador detecta saída de outro plano e entidade perdida | testes de contrato falham como esperado |
| Segurança | aprovação adulterada, plano editado, base alterada, nomes maliciosos, injeção | recusados com código estável |

O oráculo de readback é independente do caminho de escrita: o arquivo final é reaberto pelo parser e
comparado com a simulação por **assinatura geométrica** (tipo, layer, geometria arredondada a 1e-6 mm),
não pelo retorno da função que gravou.

---

## 🧪 Desenvolvimento Experimental

```text
pesquisa → ADR → fixtures + golden → parser → plano/validador → execução + readback → interfaces → demo
```

**Achados reais (não plantados)**

| Sintoma | O que se testou | Causa real | Correção |
|---|---|---|---|
| `adicione o texto "REV B — furo central"` pedia "um único tipo de objeto" | pedido com palavras de comando dentro das aspas | a palavra *furo* citada contava como objeto | trecho citado removido antes da detecção; regressão com `"remova o furo em (15,15)"` citado |
| DXF truncado estourava `StopIteration` | fixture `corrupt.dxf` | exceção fora da lista capturada | toda falha de leitura vira `DXF_CORRUPT` |
| furo em polegada lido como 14.999999999999998 mm | fixture em polegada | ponto flutuante de `x/25.4*25.4` | normalização arredondada a 1e-9 mm |
| teste da superfície MCP reprovava | busca da substring "approve" | `cad_apply_approved_plan` contém "approve" | teste checa prefixo de ferramenta de aprovação |

Detalhes em [WORKLOG.md](WORKLOG.md); decisões em [ADR 0001](docs/adr/0001-arquitetura.md).

---

## 🛠️ Tecnologias

**Linguagens:** Python 3.10+
**CAD:** ezdxf 1.4.5 (DXF R12–R2018)
**Contratos:** Pydantic 2 (schemas com `extra=forbid`), JSON Schema exportado
**Interfaces:** FastAPI, SDK `mcp` 2.x (`MCPServer`, stdio), argparse
**IA (opcional):** SDK `anthropic` — planner Claude com saída JSON validada
**Integração:** `ocr_core` do repositório [OCR](https://github.com/Yuri-Fernando/OCR) para PDF/imagem
**Qualidade:** pytest, GitHub Actions (Linux/Windows × 3.10/3.12)

---

## 📊 Resultados

| Medida | Valor | Origem |
|---|---|---|
| Testes | 113 passam, 1 pulado (opt-in com custo) de 114 | `python -m pytest -q`, 2026-10-20, Windows 11 / Python 3.10 |
| Checks de readback na demo | 9/9 PASS | [docs/evidence/demo_report.md](docs/evidence/demo_report.md) |
| Fonte após execução | SHA idêntico ao aprovado | check `source_unchanged` |
| Contagem de círculos | 4 → 5 | [manifest da demo](docs/evidence/demo_manifest.json) |
| Pedidos ambíguos testados | 9/9 viram `NEEDS_CLARIFICATION` | `test_ambiguous_requests_need_clarification` |
| Operações maliciosas no schema | 7/7 rejeitadas | `test_schema_allowlist_rejects_unsafe_operations` |

Limites: são fixtures sintéticas de uma peça simples; não há benchmark de desenhos reais nem medida
de desempenho. Não foi medida taxa de acerto de LLM (EX-04 da pesquisa está planejado).

---

## 🖼️ Evidências

<p align="center">
  <a href="docs/evidence/demo_preview.svg"><img src="docs/evidence/demo_preview.svg" width="560" alt="Preview do plano: placa com quatro furos existentes em cinza e o furo central novo em verde"></a><br>
  <sub>Preview gerado pela demo: geometria existente em cinza, furo central proposto em verde.</sub>
</p>

- [Relatório da demo](docs/evidence/demo_report.md) — pedido, plano, hashes, aprovação e os 9 checks.
- [Manifest da demo](docs/evidence/demo_manifest.json) — mesmo conteúdo em JSON.
- [JSON Schemas](schemas/) — `engineering_ir.schema.json` e `cad_action_plan.schema.json`.

---

## 🚀 Aplicações

- Alterações repetitivas em desenhos 2D de chapas, suportes e gabinetes com trilha de aprovação.
- Camada de ferramentas segura para assistentes (Claude Desktop/Code via MCP) em ambiente de engenharia.
- Base para comparar revisões (`engcad compare`) e auditar o que mudou entre arquivos.
- Ponto de partida para adaptadores de CAD comercial com contrato e testes já definidos.

---

## 🔭 Visão de Longo Prazo

```text
DXF 2D verificado (hoje)
   ↓
code-CAD 3D (build123d/CadQuery → STEP + vistas DXF, checagem de volume/sólido)
   ↓
conhecimento: busca híbrida com citação por source_anchor e filtro de revisão
   ↓
similaridade explicável entre projetos (geometria + texto + regras, com benchmark rotulado)
   ↓
adaptadores licenciados (AutoCAD .NET / APS, Creo, FreeCAD) passando nos mesmos contratos
   ↓
identidade real, RBAC e observabilidade de custo/latência por pedido
```

---

## 🗺️ Roadmap

- **F0 — Base** ✅ Concluída — pacote, CI, ADRs, fixtures e golden.
- **F1 — Parse + IR** ✅ Concluída — `test_parser.py` (14 testes).
- **F3 — Plano** ✅ Concluída — allowlist, validador e intenção (35 testes).
- **F4 — Execução segura** ✅ Concluída — aprovação, copy-on-write, readback (27 + 14 testes).
- **F6 — Agente** 🟡 Parcial — MCP fechado testado; Claude real não executado.
- **F7 — Interface** 🟡 Parcial — API e CLI; sem dashboard web.
- **F2 — Conhecimento** ⏳ Planejada — busca híbrida com citação.
- **F5 — Similaridade** ⏳ Planejada — depende de pares rotulados.
- **F8 — CAD comercial** ⛔ Bloqueada — depende de licença/instalação.

Detalhe em [ROADMAP.md](ROADMAP.md).

---

## 🕓 Histórico e Mudanças

| Versão | Data | O que mudou |
|---|---|---|
| v0.1.0 | 2026-10-20 | MVP: IR v1, parser DXF, plano tipado, validador, aprovação, ezdxf copy-on-write, readback, API, MCP, CLI, ponte OCR |

[CHANGELOG.md](CHANGELOG.md) · [WORKLOG.md](WORKLOG.md)

---

## 🔮 Próximos Passos

**Concluídos nesta versão** ✅ — fluxo DXF ponta a ponta com aprovação e readback; MCP sem ferramentas
de aprovação/execução de código; ponte com o motor documental do OCR.

**Dependem de terceiros** — instalação/licença de AutoCAD ou Creo para os adaptadores reais; chave
de API e autorização de dados para medir o planner Claude real.

**Próximos técnicos (v0.2)** — adaptador build123d para 3D; índice híbrido com citação por
`source_anchor`; benchmark de 100 pedidos (EX-04) comparando determinístico × Claude × modelo local;
dashboard web de revisão/aprovação.

---

## ▶️ Como rodar localmente

Pré-requisitos: Python 3.10+.

```bash
pip install "ezdxf==1.4.5" "pydantic>=2.7,<3" fastapi httpx "mcp>=2.0" pytest   # ou: pip install -e ".[api,mcp,dev]"

python -m pytest -q                                   # 113 passam, 1 opt-in pulado

# demo ponta a ponta (gera a placa, planeja, mostra preview e para pedindo aprovação)
PYTHONPATH=src python -m engcad demo -w demo-ws
PYTHONPATH=src python -m engcad demo -w demo-ws --approve     # aprovação DEMO rotulada

# fluxo manual
PYTHONPATH=src python -m engcad fixtures --out fixtures
PYTHONPATH=src python -m engcad ingest fixtures/plate_revA.dxf -w ws
PYTHONPATH=src python -m engcad plan <revision_id> "adicione furo central Ø10 em (60,40)" -w ws
PYTHONPATH=src python -m engcad preview <plan_id> -w ws
PYTHONPATH=src python -m engcad approve <plan_id> --approver "Seu Nome" --reason "revisado" -w ws
PYTHONPATH=src python -m engcad apply <plan_id> -w ws
PYTHONPATH=src python -m engcad compare fixtures/plate_revA.dxf ws/outputs/<plan_id>/plate_revA__*.dxf

# interfaces
PYTHONPATH=src python -m engcad serve-api -w ws      # http://127.0.0.1:8077/docs
PYTHONPATH=src python -m engcad serve-mcp -w ws      # MCP stdio
```

| Ambiente | Como | Verificado nesta revisão |
|---|---|---|
| Windows 11 (PowerShell) | `$env:PYTHONPATH="src"; python -m engcad demo -w demo-ws --approve` | ✅ testes + demo |
| Linux | comandos acima | via CI (matriz configurada; primeira execução após publicação) |
| Claude Desktop/Code (MCP) | `claude mcp add engcad -- python -m engcad serve-mcp -w <ws>` com `PYTHONPATH=src` | ⚠️ servidor testado in-process; cliente real não verificado |
| Planner Claude | `ENGCAD_ALLOW_CLOUD_LLM=1`, `ANTHROPIC_API_KEY`, `--planner claude` | ⚠️ não executado (opt-in com custo) |
| Ponte OCR | `ENGCAD_OCR_SRC=<caminho>/OCR/src` | ✅ teste de integração com `ocr_core` real |

---

## 📁 Estrutura do repositório

```text
Engineering-CAD-AI/
├── src/engcad/
│   ├── ir.py, parser_dxf.py, units.py, geometry.py   # leitura e contrato do IR
│   ├── plan.py, intent.py, llm.py, validate.py        # planejamento e validação
│   ├── diff.py, render.py, verify.py, report.py       # diff, preview, readback, relatório
│   ├── approval.py, service.py                        # aprovação, estados, workspace, auditoria
│   ├── adapters/ (base, ezdxf, mock, commercial)      # protocolo por capacidade
│   ├── api.py, mcp_server.py, cli.py, ocr_bridge.py   # interfaces e integrações
│   └── fixtures.py                                    # peças sintéticas
├── tests/ (7 arquivos, 114 testes) + fixtures/golden/
├── schemas/                                           # JSON Schema do IR e do plano
├── docs/ adr/ · research/ · evidence/ · TEST_MATRIX.md
├── .github/workflows/ci.yml
└── CHANGELOG.md · ROADMAP.md · WORKLOG.md · LICENSE
```

Não versionado: workspaces (`*-ws/`, `engcad-workspace/`), que contêm fontes, aprovações e a chave
HMAC local do aprovador.

---

## 📚 Documentação

| Documento | Conteúdo |
|---|---|
| [ADR 0001](docs/adr/0001-arquitetura.md) | camadas, garantias impostas pelo código, consequências |
| [ADR 0002](docs/adr/0002-adaptadores-cad.md) | ordem de adaptadores CAD e por quê |
| [Pesquisa agentes↔CAD](docs/research/integracao-agentes-cad.md) | caminhos de integração, repositórios conferidos, técnicas, segurança |
| [Matriz de testes](docs/TEST_MATRIX.md) | o que cada arquivo de teste prova e o que não é testado |
| [Evidências](docs/evidence/) | preview, relatório e manifest da demo |
| [CHANGELOG](CHANGELOG.md) · [ROADMAP](ROADMAP.md) · [WORKLOG](WORKLOG.md) | histórico, fases, diário |

---

## ⚠️ Limitações

- **Somente DXF 2D.** DWG, STEP e feature tree nativa exigem adaptadores licenciados (não executados).
- **Geometria interpretada por regra simples:** contorno = maior LWPOLYLINE fechada sem bulge; furo =
  CIRCLE dentro do contorno. Polilinhas com arcos, blocos (INSERT não é explodido) e espaço de papel não
  entram na validação.
- **Sem GD&T e sem tolerâncias**: o IR registra tolerância como desconhecida; nada é inferido.
- **Aprovação demo** (HMAC com chave local) não é autenticação corporativa; não há RBAC nem multiusuário.
- **Planner Claude** só testado com cliente falso; qualidade real não medida.
- **PDF/imagem**: a ponte só extrai campos de carimbo literais; cotas a partir de raster não existem.
- **Sem validação de engenharia**: saídas são `R&D / NOT FOR MANUFACTURE`.
- Persistência em arquivos JSON no workspace (sem banco, sem fila); adequado a uso local.

---

## Status

🟡 **MVP técnico funcional — v0.1.0.** Fluxo DXF ponta a ponta implementado e testado (113 testes
passam, readback 9/9 na demo); adaptadores de CAD comercial e planner Claude real ainda não executados.

---

## Contexto / Observações

Peça de portfólio e laboratório de P&D, sem afiliação com fornecedores de CAD. Todas as peças são
sintéticas e geradas por código; nenhum desenho industrial real foi usado. Contagens de estrelas na
pesquisa são instantâneos de 2026-10-20. Nenhuma métrica de produção é alegada.

---

## 🔗 Projetos Relacionados

| Projeto | Relação |
|---|---|
| [OCR](https://github.com/Yuri-Fernando/OCR) | motor documental `ocr_core` usado pela ponte para PDF/imagem; o adapter é **opcional** (aponta para `OCR/src` via `ENGCAD_OCR_SRC`) e o fluxo DXF funciona sem ele |
| [OmniMind_AI_OS](https://github.com/Yuri-Fernando/OmniMind_AI_OS) | runtime multiagente candidato a orquestrar este fluxo |
| [AegisLLM](https://github.com/Yuri-Fernando/AegisLLM) | gateway de segurança para LLMs (mesma preocupação com injeção) |
| [Industrial-Control-Lab](https://github.com/Yuri-Fernando/Industrial-Control-Lab) | laboratório de automação industrial sem hardware |
| [SAP-FlowGuard](https://github.com/Yuri-Fernando/SAP-FlowGuard) | mesmo padrão: regras determinísticas, aprovação humana, escrita fail-closed |
| [Pix-Fraud-Decisioning-Lab](https://github.com/Yuri-Fernando/Pix-Fraud-Decisioning-Lab) | mesma disciplina: regras versionadas, trilha de auditoria e IA apenas consultiva, nunca decisória |

---

## 🤖 Autor

**Yuri Fernando Dubbern**

Engenharia Elétrica · Ciência da Computação · Inteligência Artificial ·
Sistemas Embarcados · Projeto de Hardware · Pesquisa e Desenvolvimento

[LinkedIn](https://www.linkedin.com/in/yuridubbern) · [GitHub](https://github.com/Yuri-Fernando) · [Lattes](http://lattes.cnpq.br/7151392692642166) · [Linktree](https://linktr.ee/yuri.f.dubbern)

---

## Licença

MIT — ver [LICENSE](LICENSE).