Excalidraw via MCP
Dizer "use Excalidraw MCP" deve ser suficiente para obter um diagrama complicado, desenhado ao vivo e salvo onde deve estar. Esta skill é o que torna isso realidade.
A única coisa que quebra tudo
O formato de elemento do create_view é um esqueleto, não o esquema de disco. O
label de uma forma é apenas açúcar sintático do esqueleto. O renderizador de tela do Excalidraw não possui ramo de texto para retângulo / elipse / losango — o texto do contêiner é desenhado apenas via
boundElements → containerId. Portanto, colar JSON do create_view em um arquivo .excalidraw
produz caixas vazias, silenciosamente. Esse único fato é a razão de existir do scripts/excalidraw_build.py:
autor uma vez no esqueleto, obtenha tanto a renderização ao vivo quanto um arquivo correto.
Segundo fato: diagramas feitos à mão não degradam gradualmente com o tamanho — eles falham na irregularidade. Medido em uma cena real gerada, elementos produzidos por uma fórmula de layout repetitiva tiveram uma taxa de defeito de 0,00; elementos únicos feitos sob medida tiveram 0,71. Portanto, calcule as posições com uma fórmula e deixe o linter verificar o resultado.
Pré-verificação em uma máquina nova
Instalar esta skill não instala o servidor MCP — mcp-deps é uma declaração que
vskill check verifica, não um instalador. Se as ferramentas mcp__excalidraw__* não
estiverem disponíveis, execute isto primeiro — ele detecta e registra o servidor, em qualquer SO:
python3 scripts/ensure_mcp.py --install
Ele informa onde o servidor foi encontrado, ou executa
claude mcp add --transport http --scope user excalidraw https://mcp.excalidraw.com
e re-verifica. Saída 0 configurado, 1 ausente, 2 não foi possível registrar (sem CLI Claude no
PATH — ele imprime o comando para executar manualmente). O Claude Code precisa ser reiniciado depois para
ativar um servidor recém-adicionado.
Escopos: --scope user (padrão) cobre todos os projetos na máquina via ~/.claude.json;
--scope project escreve ./.mcp.json para que colegas de equipe o obtenham ao clonar; --scope local é
apenas este projeto. Um servidor registrado sob um projeto diferente conta como ausente —
Claude Code não o carregará aqui, e o script informa isso.
Sem o MCP, tudo exceto a renderização ao vivo inline ainda funciona.
excalidraw_build.py e excalidraw_lint.py são Python 3 apenas com biblioteca padrão — sem pacotes, sem
rede. Crie arquivos, faça lint, envie-os. excalidraw_render.py adicionalmente precisa
pip install playwright && playwright install chromium.
Windows
Use py -3 e barras invertidas; python3 no Windows é um stub da Microsoft Store que abre
a Store em vez de executar qualquer coisa.
py -3 scripts\ensure_mcp.py --install
py -3 scripts\excalidraw_build.py scene.json -o out.excalidraw
Todo o resto é portátil: caminhos usam pathlib, saída é escrita com UTF-8 explícito
e quebras de linha \n para que uma execução no Windows não grave CRLF no JSON da cena, e a
pré-verificação resolve claude.cmd / claude.exe além de claude. Se vskill i avisar
que links simbólicos não estão disponíveis, ele volta a copiar — ative o Modo Desenvolvedor para obter
links simbólicos de volta.
Fluxo de trabalho
- Pré-verificação (apenas máquina nova): se as ferramentas
mcp__excalidraw__*estiverem ausentes,python3 scripts/ensure_mcp.py --install(py -3no Windows). - Autor o esqueleto. Um array JSON, o mesmo que
create_viewrecebe. As posições vêm de uma fórmula de layout (vejareferences/layout-recipes.md), nunca de olhômetro. - Fazer lint — offline, sem dependências, detecta overflow/colisão/geometria:
python3 scripts/excalidraw_lint.py scene.json --camera--cameraimprime umcameraUpdatecom enquadramento 4:3 correto para colar no topo. - Renderizar ao vivo com
mcp__excalidraw__create_view, elementos transmitidos em ordem z com movimentos de câmera (vejareferences/mcp-workflow.md). Mantenha ocheckpointIdretornado. - Salvar o arquivo quando o usuário quiser um no disco:
python3 scripts/excalidraw_build.py scene.json -o out.excalidraw python3 scripts/excalidraw_build.py scene.json -o out --obsidian # → out.excalidraw.md python3 scripts/excalidraw_build.py scene.json -o out.excalidraw --dark - Olhe para ele antes de declarar sucesso em algo não trivial. Isso renderiza através
do próprio
exportToSvgdo Excalidraw, então o texto é medido com métricas de fonte reais:
Em seguida, Leia o PNG. Corrija o que você vê; refaça o lint; re-renderize.python3 scripts/excalidraw_render.py out.excalidraw -o /tmp/preview.png
As etapas 2 e 5 são o portão de qualidade. Pulá-las é como rótulos acabam fora de suas caixas e setas acabam apontando para nada.
Folha de dicas do esqueleto
{"type":"rectangle","id":"api","x":100,"y":80,"width":180,"height":80,
"roundness":{"type":3},"backgroundColor":"#a5d8ff","fillStyle":"solid",
"strokeColor":"#4a9eed","label":{"text":"API Gateway","fontSize":18}}
{"type":"arrow","id":"e1","from":"api","to":"db","label":{"text":"SQL"}} // vinculação automática
{"type":"arrow","id":"e2","from":"api","to":"db","route":"ortho"} // formato L
{"type":"arrow","id":"e3","x":300,"y":150,"points":[[0,0],[120,0]]} // manual
{"type":"text","id":"ttl","center":400,"y":20,"text":"Title","fontSize":24} // centralizado automaticamente
{"type":"rectangle","id":"zone","x":40,"y":40,"width":700,"height":420,
"opacity":30,"zoneLabel":"Data layer"} // legenda, não rótulo vinculado
Extensões apenas do builder: from/to (âncoras de perímetro + vinculação bidirecional),
route:"ortho", zoneLabel, center em texto, fixedWidth em uma forma (quebra em vez de
aumentar). Todo o resto é passado inalterado, então o mesmo array ainda funciona
diretamente com create_view.
Nunca coloque um label vinculado em um retângulo de zona de fundo — ele centraliza no meio
da zona e não pode ser pego. Use zoneLabel.
Escolhendo a saída
| Destino | Comando | Notas |
|---|---|---|
| Mostrar ao usuário agora | create_view | animado, guiado por câmera; retorna checkpointId |
| Arquivo em um repositório | excalidraw_build.py -o x.excalidraw | abre em excalidraw.com ou na extensão VS Code |
| Vault Obsidian | ... -o x --obsidian | .excalidraw.md, interpretado pelo plugin, com diff por git |
| Link compartilhável | mcp__excalidraw__export_to_excalidraw | faz upload para excalidraw.com — pergunte primeiro |
O MCP não possui ferramenta de arquivo local. export_to_excalidraw é um upload público, então trate-o como
publicação: confirme com o usuário antes de chamá-lo.
Iterando
create_view retorna um checkpointId. Para continuar a partir dele — incluindo edições do usuário feitas em
tela cheia — comece o próximo array com
{"type":"restoreCheckpoint","id":"<checkpointId>"} e anexe apenas o que é novo. Use
{"type":"delete","ids":"a,b"} para remover elementos; nunca reutilize um id deletado. Mantenha o
arquivo esqueleto no disco sincronizado, pois esse arquivo é o que constrói e faz lint.
Referências
references/file-format.md— o esquema de disco, verificado contra o upstream: códigos de fonte, texto vinculado, geometria de seta, vinculações, o que o Excalidraw recalcula e não recalcula ao abrir. Leia antes de editar manualmente qualquer arquivo.excalidraw.references/mcp-workflow.md— coreografia de câmera, ordem de transmissão, checkpoints, modo escuro e os próprios limites do MCP.references/layout-recipes.md— fórmulas para layouts de fluxo, em camadas, raias, sequência, grade, radial e matriz, além de como manter um diagrama de 60 elementos legível.references/obsidian.md— o wrapper.excalidraw.md, regras de bloco-ref e a armadilha de cena compactada.scripts/ensure_mcp.py— detectar e registrar o servidor MCP do Excalidraw em qualquer SO.scripts/split_excalidraw_library.py— dividir um.excalidrawlib(pacotes de ícones AWS/GCP/K8s de libraries.excalidraw.com) em JSON por ícone mais uma tabela de consulta, para que os dados do ícone nunca entrem no contexto.
Limites que vale a pena declarar em voz alta
- As estimativas de largura são calibradas por caractere, não medidas a partir do binário da fonte; o linter avisa dentro de 10% de overflow. Quando avisar sobre algo importante, renderize.
excalidraw_render.pyprecisa deplaywrightmais acesso à rede para esm.sh. Sem eles, o lint ainda é totalmente offline.- O linter não pode julgar se um diagrama é bom, apenas se é correto. A composição ainda é seu trabalho.
Changelog
- 1.2.0 —
scripts/ensure_mcp.py: pré-verificação multiplataforma que detecta o servidor MCP (incluindo o mapa por projeto de~/.claude.json) e o registra quando ausente. Suporte ao Windows: documentadopy -3, resolução declaude.cmd, UTF-8 explícito e quebras de linha\nem toda escrita. - 1.1.1 — linter não aplica mais as regras de ajuste de caixa (R1/R2) a contêineres de seta; rótulos de seta são dispostos ao longo do caminho e são cobertos por R10.
- 1.1.0 — movido para o monorepo vskill em
skills/excalidraw-mcp/, correspondendo aremotion-best-practicese outras skills no repositório. O repositório independenteanton-abyzov/excalidraw-mcp-skillestá obsoleto. - 1.0.1 — documentar configuração do MCP: instalar a skill não instala o servidor;
adicionado o comando único
claude mcp adde o que ainda funciona sem ele. - 1.0.0 — primeira versão. Substitui a skill
excalidraw-diagram-generatorapenas de arquivo, cujos templates emitiamtextinline em formas e, portanto, abriam como caixas vazias.