
Tengo un diagrama de la arquitectura de mi asistente aparcado en una nota de Obsidian que da un poco de vergüenza. Lo dibujé hace meses, con sus cajas de colores y sus flechas bien alineadas, y era verdad entonces. Hoy le faltan dos servicios, le sobra una cola que ya no existe y sigue señalando un broker por el que hace tres refactors que no pasa nadie. Nadie lo ha tocado. Nadie lo va a tocar. Ese es el problema del que te quiero hablar hoy, y también la solución que le he encontrado, porque he conectado un MCP de Excalidraw a mi agente para que sea él quien dibuje, mire lo que ha dibujado y lo corrija. Así el diagrama deja de ser una foto muerta y pasa a ser un fichero más del repositorio, con su historial y sus diferencias.
El diagrama que miente
Pasa en cualquier proyecto que lleve un año vivo. Abres la carpeta de documentación, encuentras el diagrama que hiciste con tanto cariño y te das cuenta de que estás mirando una pieza de museo. Está impecable, colgado en la pared, y cuenta una historia que ya no es cierta. Hay una caja que ya no existe, un servicio que se partió en dos y una flecha que apunta a un sitio por el que ya no pasa nadie.
Y no es un problema exclusivo del software. Sirve igual para la estructura de una tesis doctoral, para la jerarquía de un departamento o para la línea temporal de las distribuciones de Linux desde 1993 hasta hoy. Todos esos diagramas tienen una cosa en común, y es que no son estáticos. Al principio son cuatro cajas y tres flechas. Según avanza el trabajo se van metiendo ramas, subapartados, excepciones y matices, hasta que el dibujo sencillo del principio se convierte en algo que da pereza mirar.
Dibujar es hasta divertido el primer día. El problema llega cuando el diagrama tiene que seguir el ritmo de lo que representa, y entonces entras en un bucle de abrir la herramienta, arrastrar una caja, recolocar seis flechas, mover la leyenda y volver a exportar. Cada vez. Para siempre.
El coste que nadie factura
Fíjate en el detalle que se nos escapa siempre. Ese diagrama no vive junto al código. Vive en una carpeta aparte, en un fichero que nadie mira, en una herramienta que no sabe absolutamente nada de tu repositorio. El código y el dibujo están divorciados, y de ese divorcio sale todo lo demás.
Porque cuando refactorizas, el diagrama no se entera. Cambias un servicio, entras a la herramienta, mueves cajas, recolocas flechas y vuelves a exportar la imagen. Y como nadie factura ese tiempo, nadie lo ve. Es mantenimiento invisible. No aparece en ningún issue, no queda registrado en ningún commit, no se puede automatizar y no se puede diferenciar con un git diff. Simplemente lo haces tú, una y otra vez, y cada vez que lo dejas el reloj vuelve a empezar.
En documentación esto tiene nombre y todo, doc rot, la documentación que se pudre por abandono. Un diagrama que envejece lejos de su fuente de verdad es el caso más visual de ese fenómeno, porque no solo se queda viejo, sino que se queda viejo con una sonrisa. Sigue pareciendo correcto. Y ahí está la trampa, en que un dibujo desactualizado es peor que no tener dibujo, porque te hace confiar en una información que ya no es cierta.
Anuncios parroquiales: de llm-gateway a la poda de los AGENTS.md
Antes de entrar en harina, lo de todas las semanas, que estos cuatro días han dado de sí. Han sido 141 contribuciones repartidas en una docena de repositorios, y once releases, así que te lo resumo por encima y dejo los detalles para otros episodios.
llm-gateway, el proxy de LLM con failover, ha subido a la 0.2.0. Esta semana le he metido métricas de Prometheus, logs correlacionados y una cabecera x-request-id, que parece una tontería y no lo es, porque ahora puedo seguir una petición de punta a punta sin adivinar por dónde ha pasado. oximeal, la aplicación de comidas, ha llegado a la 0.3.0 con un endurecimiento serio de SQLite a base de BEGIN IMMEDIATE, restricciones CHECK y ON DELETE RESTRICT, y con autenticación OIDC contra Pocket ID. Y mkdr ha ido de la 0.6.2 a la 0.6.5 en tres días, entre arreglos del --no-colour y un detector de bumps que se empeñaba en leer cambios donde no los había.
oxidav, el calendario CalDAV, está en la 0.8.0 con recurrencia RRULE, EXDATE, RDATE, zonas horarias y SEQUENCE en el diálogo de eventos, que era la pieza que le faltaba para no pelearse con otros clientes. valet-ai va por la 0.25.0 y ya expone render_widget y su guía en todos los turnos, no solo cuando le apetece. crypta, en la 0.3.2, trae la bandera --remote en init y arranca con rama main en vez de master.
En el blog, atareao.es, la 1.19.0 ha sido una semana de fontanería. El arreglo del transporte MCP, que es justo lo que conecta a los agentes con el blog, llevaba unos días dando guerra con la negociación de la era del protocolo y por fin está resuelto. Y el pipeline por lotes de transcripciones SubRip, que ya enlaza cada transcripción con su episodio del feed. podtrack ha llegado a la 0.6.1 con autocompletado de shell para bash, zsh y fish, y id3cli, qctl, dotfiles y self-hosted-podman han tenido mantenimiento, con SonarQube dentro del CI, dependencias al día y algo de pulido en los dotfiles.
Y una cosa que me hacía ilusión, la poda de los AGENTS.md. En media docena de repos, anacleto, apimail, centinela, lazymd y populatrs entre ellos, he recortado ese fichero un setenta por ciento y he sacado todo el detalle a docs/, estrenando ahí la sección de Git Flow. Menos ruido para el agente, más foco. Y ahora sí, al tema.
Mermaid cumplió la promesa del texto
Si has pensado alguna vez en resolver esto con texto, ya conoces la respuesta, porque se llama Mermaid y hay que reconocerle el mérito. Mermaid dijo una cosa muy sencilla, diagramas como texto. En vez de arrastrar cajas, escribes unas cuantas líneas con una sintaxis tipo Markdown y el motor te lo pinta.
flowchart LR
cliente[Navegador] --> api[API]
api --> db[(PostgreSQL)]
api --> cache[(Redis)]
Con eso ganas lo importante. El diagrama es reproducible, es diferenciable y es versionable. Tu diagrama es un bloque dentro de un .md que se versiona con git igual que tu código, y en una revisión ves que has añadido un nodo o que has cambiado una arista. El motor va por la versión 12.2.0, lleva años funcionando en serio y la sintaxis se aprende en un rato. No necesitas instalar ninguna aplicación gráfica, ni siquiera abrir el navegador si lo renderizas en tu pipeline. En ese sentido, Mermaid cumplió lo que prometió, y cumplió a lo grande.
De hecho, para un diagrama de flujo dentro de un README o para una nota técnica de cuatro nodos, sigue siendo mi primera opción. Es rápido, es barato y cualquiera puede editarlo con un editor de texto.
La grieta de Mermaid
Pero hay una grieta, y la notaste tú en cuanto intentaste tocar una sola caja. Mermaid no es editable a mano. No hay lienzo. No arrastras nada. Escribes texto y el motor decide dónde va cada cosa. Tú no pintas, describes, y el motor interpreta.
Y el motor coloca los elementos como le parece. El layout lo decide él, es rígido y, seamos sinceros, plano. Queda correcto, pero queda correcto de manual. Si quieres mover una caja dos píxeles a la derecha, no la mueves, editas la sintaxis. Y si quieres cambiar un color, un grosor o un margen, te toca pelear con la sintaxis o meterte directamente en CSS, que es como arreglar una persiana con una espada.
Ponlo al lado de un Excalidraw y se ve la diferencia de filosofía. Uno es texto que se renderiza, el otro es un lienzo que manipulas. Ninguno es mejor en abstracto, pero resuelven cosas distintas. El problema es cuando le pides a la IA lo que ninguno de los dos te da por sí solo.
La IA dibuja a ciegas
Si le pides un diagrama a un modelo de lenguaje sin más, ¿qué pasa? Que te devuelve una imagen. Y esa imagen es bonita, muy bonita, pero está muerta. No la puedes editar, no la puedes mover, no la puedes versionar como estructura. Es un póster. El día que quieras cambiar una caja, vuelves a empezar con otro prompt y rezas para que no te cambie también las otras cinco.
Pero hay algo más profundo, y es lo que de verdad me hizo entender el problema. Sin un lienzo real, la IA no ve lo que hace. No tiene forma de mirar el resultado y decir «uy, esa flecha cruza por encima de una caja» o «esa etiqueta se ha cortado». Dibuja a ciegas, y claro, dibuja regular.
El síntoma más claro es el solapamiento. Le pides siete cajas con sus flechas, las coloca, y hay dos que se pisan, una etiqueta que se monta encima de otra y una conexión que pasa por debajo de un nodo. Es el equivalente a esos memes de la IA dibujando texto en las manos. La intención está, la ejecución falla. Y falla porque le falta exactamente una cosa, ver.
El giro: un MCP con lienzo, no un generador
Llega el giro del episodio, y es de esos que te cambian el modelo mental. Lo que vamos a montar no es un generador de imágenes. Es un MCP que le da a tu agente un lienzo Excalidraw de verdad, vivo y editable. Si vienes del episodio en el que te conté cómo se le dan manos a una IA, esto es la misma idea aplicada a un dominio muy concreto, el dibujo técnico.
La diferencia es enorme. Ya no hay una captura final, hay control elemento a elemento. El agente crea las cajas, crea las flechas, les pone etiquetas, y todo eso vive en un lienzo real, no en una imagen exportada. Y cuando termina, tú puedes seguir editándolo a mano exactamente como cualquier Excalidraw, porque es un Excalidraw.
Piensa en el antes y el después. Prompt que produce imagen muerta, frente a prompt que produce lienzo vivo. El resultado deja de ser un póster y pasa a ser un artefacto con el que puedes seguir trabajando. Y eso, en un proyecto que va a durar años, cambia por completo la economía de la cosa.
El bucle que lo cambia todo
El detalle que lo cambia todo es que el agente se mira a sí mismo, y esto no es marketing mío, está documentado y es literal. El MCP expone dos herramientas para que el modelo se vea. Una es describe_scene, que le devuelve un resumen estructurado en texto con los identificadores, las posiciones, las etiquetas y las conexiones. La otra es get_canvas_screenshot, que le devuelve un PNG renderizado del lienzo.
Con esas dos, el agente tiene algo parecido a ojos. Recibe un texto parecido a este, con la geometría de lo que acaba de dibujar,
elementos: 9 (3 rectángulos, 2 rombos, 4 flechas)
api rect x=120 y=140 w=180 h=90 label="API"
db rect x=420 y=140 w=180 h=90 label="PostgreSQL"
cache rect x=420 y=300 w=180 h=90 label="Redis"
a1 arrow api -> db label="SQL"
a2 arrow api -> cache label="GET/SET"
avisos: 2 elementos solapados, 1 etiqueta recortada
y a partir de ahí decide. Detecta dos flechas cruzadas, una etiqueta cortada o dos cajas que se pisan, y no se queda ahí, corrige elemento a elemento con update_element, align_elements y distribute_elements, y vuelve a mirar. Es un ciclo, dibuja, mira, corrige y vuelve a mirar. Y ese ciclo es lo que separa «la IA me dibuja regular» de «la IA me dibuja y se da cuenta de que está mal».
El toolkit completo son 26 herramientas, que suenan a muchas y luego resulta que son las justas. Te las agrupo,
| Categoría | Herramientas |
|---|---|
| Elementos | create_element, get_element, update_element, delete_element, query_elements, batch_create_elements, duplicate_elements |
| Layout | align_elements, distribute_elements, group_elements, ungroup_elements, lock_elements, unlock_elements |
| Conciencia de escena | describe_scene, get_canvas_screenshot |
| Ficheros | export_scene, import_scene, export_to_image, export_to_excalidraw_url, create_from_mermaid |
| Estado | clear_canvas, snapshot_scene, restore_snapshot |
| Vista | set_viewport, get_resource |
| Guía | read_diagram_guide |
Fíjate en read_diagram_guide. Lo que hace es dejar que el modelo consulte las reglas de diagramación antes de empezar, en lugar de improvisar. Traducido a lenguaje humano, le estás dando un manual de estilo antes que un lápiz. Y eso se nota mucho en el resultado.
Qué pasa por debajo cuando el agente dibuja
Merece la pena pararse un momento en la fontanería, porque entenderla te ahorra la mitad de los problemas de configuración. El toolkit son dos procesos que funcionan como un solo producto: el canvas server, que es la interfaz web de Excalidraw más una API REST y un canal de WebSocket para la sincronización en tiempo real, y un front-end fino que puede ser el CLI, un servidor MCP por stdio o HTTP puro, y que conduce siempre el mismo lienzo.
Cuando OpenCode arranca, habla con el servidor MCP por stdio con JSON-RPC, el mecanismo de siempre. Primero pide tools/list, se trae el catálogo de las 26 herramientas con sus esquemas, y a partir de ahí decide. Cuando quiere dibujar, emite una llamada a batch_create_elements con los argumentos, y el servidor MCP la traduce a peticiones REST contra el canvas. El modelo nunca toca el lienzo directamente, se lo pide a alguien que sí lo toca.
Ese detalle explica un error de configuración muy común, y es confundir la URL del canvas con un endpoint MCP. http://127.0.0.1:3000 es la API del lienzo, no el servidor MCP. El MCP va por stdio, y si le pones esa URL a OpenCode como si fuera un servidor remoto, no conecta. Para clientes que solo hablan HTTP, como Open WebUI, hace falta un puente de stdio a HTTP aparte, y eso ya es otro montaje.
También explica por qué el orden de preferencia del autor es CLI, luego MCP y luego REST. El CLI no necesita negociar nada con nadie, ejecuta y ya está. Por eso la vía de la skill funciona incluso cuando la configuración del MCP está regular, y por eso te la recomiendo como plan A.
Dos MCP de Excalidraw, y no son lo mismo
Aquí conviene no confundirse, porque hay dos y se parecen en el nombre. El MCP oficial, el de excalidraw/excalidraw-mcp, ronda las cinco mil seiscientas estrellas y funciona en remoto, en mcp.excalidraw.com. El toolkit de yctimlin, en cambio, se llama mcp-excalidraw en GitHub y mcp-excalidraw-server en npm, va por la versión 2.1.2, tiene licencia MIT, ronda las dos mil seiscientas estrellas y expone esas 26 herramientas.
| MCP oficial | Toolkit de yctimlin | |
|---|---|---|
| Enfoque | widget de un solo tiro | control programático elemento a elemento |
| Herramientas | 2 | 26 |
| Estado | puntos de control en el chat | lienzo vivo con sincronización |
| La IA ve el lienzo | no | sí, describe y screenshot |
| Refinar | regenerar desde el punto de control | dibujar, mirar, ajustar, mirar |
| Layout | no | alinear, distribuir, agrupar |
| Export a fichero | no | .excalidraw, .excalidraw.md, PNG, SVG |
| Funciona sin MCP | no | sí, CLI, skill y REST |
El oficial es cómodo para una demo rápida. Le pides un diagrama, te lo dibuja dentro del chat y se acabó. Pero la IA no ve el lienzo, no exporta a un fichero y para refinar tienes que volver a generarlo desde un punto de control. Está bien para ver un resultado, pero no para trabajar sobre él.
El de yctimlin sí es un banco de trabajo, y lo dice su propio README. Tiene lienzo vivo, sincronización en tiempo real entre el agente y tú, herramientas de layout y exportaciones de verdad. Es con este con el que voy a montar la demo, y es el que te recomiendo.
Montaje en OpenCode
La demo va en OpenCode, que es mi agente de código de cabecera desde hace meses, y si no lo conoces, en el blog tienes un buen capítulo sobre qué es OpenCode y de dónde viene. Aquí el toolkit brilla, porque está pensado justo para esto, para agentes de código como Claude Code, Codex CLI, Cursor u OpenCode.
El único prerrequisito es tener Node en la versión 20 o superior. Nada más. No hace falta cuenta, no hace falta API key, no hace falta clonar ningún repositorio. Todo corre local y todo es MIT. Son de esos montajes que no te piden sangre a cambio.
Con eso cumplido, hay dos caminos. El primero, y el que recomienda el propio autor para agentes de código, es instalar la skill por línea de comandos,
npx -y mcp-excalidraw-server install-skill --dir ~/.config/opencode/skills
Eso deja la skill excalidraw-skill en el directorio global de skills de OpenCode. Y ojo, que una skill aquí no es un adorno. Lo que hace es enseñarle al agente el flujo completo, cómo planificar el layout antes de dibujar, cómo usar el bucle de screenshot y corrección, cómo enrutar las flechas para que no se crucen y qué anti-patrones evitar. Es el manual de estilo del que te hablaba antes, pero escrito en un formato que el agente lee cuando le conviene. OpenCode busca estas skills en .opencode/skills/<nombre>/SKILL.md a nivel de proyecto y en ~/.config/opencode/skills/<nombre>/SKILL.md a nivel global, así que con ese --dir la dejas disponible en todos tus proyectos.
Si además quieres verlo dibujar en directo, arrancas el canvas,
npx -y mcp-excalidraw-server start
xdg-open http://127.0.0.1:3000
Ahí lo tienes escuchando en 127.0.0.1:3000, con la interfaz de Excalidraw servida en local. Y desde la versión 1.1 el canvas se autoarranca, de manera que cualquier comando que dibuje lo levanta solo si no hay nada escuchando en el puerto. Si eso te molesta, se desactiva con EXCALIDRAW_NO_AUTOSTART=1.
La segunda vía es la configuración clásica del MCP en opencode.json, que es la que documenta el README,
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"excalidraw": {
"type": "local",
"command": ["npx", "-y", "mcp-excalidraw-server"],
"enabled": true
}
}
}
Hay una trampa que me ha hecho perder más tiempo del que me gustaría reconocer. Cuando montamos los MCPs a mano en el episodio en el que te conté lo que le faltaba a tu IA para ser útil de verdad, usábamos la clave mcpServers y un type en stdio. Muchos tutoriales que circulan siguen copiando esa forma,
{
"mcpServers": {
"excalidraw": {
"type": "stdio",
"command": "npx",
"args": ["-y", "mcp-excalidraw-server"]
}
}
}
La documentación actual de OpenCode usa otra cosa, una clave mcp y dentro type en local, con el comando como un array. Es un cambio de nombre y de forma que, si copias la configuración antigua tal cual, puede que ya no te conecte nada. Así que antes de pelearte con la demo, mira bien qué forma tiene tu fichero. Y si al arrancar no conecta, no insistas, tira de la vía de la skill con la CLI, que es la recomendada y no depende de la configuración del MCP.
Hay un par de variables de entorno que merece la pena tener a mano, porque explican muchos comportamientos que parecen magia o que parecen fallos,
| Variable | Para qué | Por defecto |
|---|---|---|
EXPRESS_SERVER_URL | URL del canvas | http://127.0.0.1:3000 |
ENABLE_CANVAS_SYNC | sincronización en tiempo real | true |
EXCALIDRAW_DATA_DIR | persistencia entre reinicios | sin definir, todo en memoria |
EXCALIDRAW_EXPORT_DIR | carpeta que el MCP puede leer y escribir | el directorio de trabajo |
EXCALIDRAW_RENDER_MAX_DIM | lado mayor del PNG headless | 8192 |
EXCALIDRAW_NO_AUTOSTART | 1 desactiva el autoarranque | sin definir |
PORT / HOST | dónde escucha el canvas | 3000 / 127.0.0.1 |
Primera demo: de una frase a un diagrama
Primer movimiento, el más sencillo. Le pido un diagrama con lenguaje natural, sin más contexto, algo tan simple como «dibújame un diagrama de un servicio web con API, base de datos y caché».
Y ya se intuye el cambio de enfoque. El agente no se pone a dibujar a lo loco. Primero consulta la guía y planifica el layout, piensa dónde va el nodo de entrada, dónde el de procesamiento, dónde la base de datos, y cómo reparte el espacio antes de colocar nada. Después lo dibuja en bloque con batch_create_elements, y ahí van cajas, etiquetas y flechas con binding, es decir, flechas que saben de qué elemento salen y a qué elemento llegan, de modo que si mueves una caja, la flecha la sigue.
Ese detalle del binding es el que convierte el dibujo en un grafo y no en una colección de líneas. Si has tocado un SVG generado por una IA, sabes de qué hablo. Allí cada flecha es un path con unas coordenadas absolutas, y mover una caja deja la flecha apuntando al vacío. Aquí la flecha tiene un startElementId y un endElementId, y el motor la recoloca.
Si quieres verlo sin agente de por medio, el CLI acepta un JSON por la entrada estándar y dibuja lo que le mandes,
echo '[
{"id":"api","type":"rectangle","x":100,"y":100,"width":160,"height":80,
"text":"API","backgroundColor":"#a5d8ff"},
{"id":"db","type":"rectangle","x":400,"y":100,"width":160,"height":80,
"text":"PostgreSQL","backgroundColor":"#99e9f2"},
{"type":"arrow","x":0,"y":0,"startElementId":"api","endElementId":"db","text":"SQL"}
]' | npx -y mcp-excalidraw-server add
Eso está bien para entender el modelo de datos, pero no es lo que vas a hacer a diario. A diario le hablas en español y él traduce a cajas, etiquetas y flechas. Y el premio está en que el resultado queda editable después, que es lo que de verdad importa.
Segunda demo: la arquitectura de un repo real
Aquí viene lo que de verdad me parece potente. Le pedimos la arquitectura de un repositorio real, nada de un ejemplo inventado. Abro un proyecto mío, un servicio en Rust con su contenedor y su base de datos, y le digo algo así,
Lee este repo y dibújame en el canvas un diagrama de arquitectura, los componentes principales, las dependencias entre ellos y los servicios externos. Usa la skill de Excalidraw. Luego míralo con un screenshot, corrige cualquier solapamiento o etiqueta cortada, y exporta
docs/arquitectura.excalidrawydocs/arquitectura.png.
Y el agente hace lo que sabe hacer. Explora el código, mira los Cargo.toml, los package.json, las rutas, los Dockerfile, y de ahí saca los componentes. Luego los dibuja, marca las dependencias y señala los servicios externos, esa base de datos, esa API ajena, esa cola. Es el diagrama que tú habrías hecho a mano leyendo el repo durante una tarde, pero hecho en un par de minutos.
Y lo importante es lo de siempre, que el resultado es editable y no una foto. Puedo entrar yo después, mover una caja, recolorear un servicio, poner una nota amarilla que diga «esto hay que partirlo». Está vivo. El agente hizo el trabajo sucio y yo me quedo con el criterio.
Hay un matiz que me ha sorprendido para bien, y es que el agente no copia la estructura de carpetas y ya está. Lee lo que hay dentro, así que distingue entre un módulo que es una librería interna y un cliente HTTP que habla con un servicio de fuera. Esa distinción es justo la que hace útil un diagrama de arquitectura y la que se pierde cuando lo dibujas a mano con prisa.
Tercera demo: el agente se mira y se corrige
Este es el momento que quería enseñarte desde el principio. Tras dibujar, le pido al agente que haga un screenshot y un describe. Es decir, que se mire. Y por CLI sería esto,
npx -y mcp-excalidraw-server screenshot --out diagram.png
npx -y mcp-excalidraw-server describe
Ahí salta lo que ya te contaba. Detecta dos cajas que se pisan y una etiqueta que se ha cortado. No porque yo se lo diga, sino porque lo ve en el render y en el texto estructurado. Entonces se pone a arreglarlo con update_element para recolocar y re-etiquetar, align_elements para alinear un grupo a la izquierda y distribute_elements para repartir el espacio horizontalmente. Y vuelve a mirar.
El equivalente por línea de comandos, para que veas que las herramientas del MCP tienen su reflejo en el CLI,
npx -y mcp-excalidraw-server arrange align --ids api,db,cache --to left
npx -y mcp-excalidraw-server arrange distribute --ids api,db,cache --to horizontal
Ahí tienes el antes y el después. Dos cajas pisándose y una etiqueta cortada, y luego el diagrama limpio, alineado y legible. Esa autocorrección es la diferencia real con lo de «la IA te dibuja regular». No es que el modelo haya mejorado su capacidad de dibujar, es que ahora tiene un mecanismo de realimentación. Dibuja, se mira, se corrige. Como cualquiera de nosotros cuando hace un esquema en una pizarra, que da dos pasos atrás antes de decidir que ya está.
Y una cosa que aprendí a base de verlo trabajar, el bucle no es infinito. El agente itera dos o tres veces y para, porque cada vuelta cuesta un render y un montón de contexto. Si el diagrama es pequeño, a la segunda ya está fino. Si es grande, la tercera vuelta no suele arreglar lo que las dos primeras no arreglaron, y ahí es donde entras tú.
Exportar y el render que no cambia de bytes
Una vez está fino, toca sacarlo del lienzo. El toolkit tiene varias salidas, export_to_image con formato PNG o SVG, export_to_excalidraw_url para un enlace compartible y export_scene para el artefacto editable. Por CLI se ve bien claro,
npx -y mcp-excalidraw-server export --out docs/arquitectura.excalidraw
npx -y mcp-excalidraw-server render docs/arquitectura.excalidraw --out docs/arquitectura.png
npx -y mcp-excalidraw-server render docs/arquitectura.excalidraw --out docs/arquitectura.svg --format svg
npx -y mcp-excalidraw-server share
Hay un dato que me parece de los más importantes de todo el episodio. Desde la versión 2.1, el render es headless. Ya no hace falta abrir una pestaña del navegador para generar el screenshot o el PNG. Dentro del canvas server, Excalidraw corre bajo Node con un shim de jsdom y resvg se encarga de rasterizar. El primer render tarda lo que tarda porque hay que levantar todo, pero a partir de ahí son milisegundos.
La consecuencia es la que me interesa, y es que la salida es determinista byte a byte. Una escena que no ha cambiado renderiza un SVG y un PNG idénticos, píxel a píxel, byte a byte, cada vez. Eso, para git, es oro. Y se comprueba en dos líneas,
npx -y mcp-excalidraw-server render docs/arquitectura.excalidraw --out /tmp/a.png
npx -y mcp-excalidraw-server render docs/arquitectura.excalidraw --out /tmp/b.png
sha256sum /tmp/a.png /tmp/b.png
Si los dos hashes coinciden, tienes lo que necesitas para meter el PNG en el repositorio sin miedo. Si no coinciden, tienes un problema, porque cada render te va a generar un commit que no aporta nada.
Solo dos cosas siguen atadas al navegador, la conversión de Mermaid y set_viewport. El resto es headless, y cuando un comando necesita pestaña, el CLI sale con código 4 y te avisa, así que no hay misterio. Los códigos de salida son 0 si todo va bien, 1 error, 2 uso incorrecto, 3 canvas inalcanzable y 4 hace falta pestaña. Para un script de CI, ese 4 es la señal de que estás llamando a lo que no debes.
Para que no tengas que montarlo desde cero, te he dejado en un gist el flujo completo, un render-diagramas.sh que regenera todos los .excalidraw del repo y te dice cuáles cambian, más un workflow de GitHub Actions que hace lo mismo en cada push,
Aterrizaje en Obsidian
Y el diagrama tiene que aterrizar en algún sitio donde lo vayas a usar de verdad. Para mí ese sitio es el vault de Obsidian, que es donde tengo las notas, la documentación y media vida. Y el toolkit exporta directamente al formato de Obsidian,
npx -y mcp-excalidraw-server export --out ~/vault/diagrams/arquitectura.excalidraw.md
El fichero es un .excalidraw.md, y lo bonito es que el plugin de Excalidraw para Obsidian, el de zsviczian, con sus casi siete mil ochocientas estrellas, lo abre de forma nativa. Sin aviso de modo compatibilidad, sin conversiones raras. Y desde la versión 2.0 del export los elementos van como elementos Excalidraw reales, las etiquetas son bound text y los bindings están vivos, así que puedes seguir editando el diagrama dentro de Obsidian como si lo hubieras dibujado allí.
El remate es que el export es byte-estable y las block references sobreviven a los re-export. Es decir, si referencias ese diagrama desde otra nota de tu vault y luego vuelves a exportar, la referencia sigue intacta. Eso es lo que hace que el diagrama entre en tu base de conocimiento como una pieza más y no como una captura pegada con chinchetas. Si trabajas con notas enlazadas, sabes la diferencia que hay entre las dos cosas.
Un aviso de licencia, porque me parece honesto decirlo. El motor de Excalidraw y el MCP son MIT, pero el plugin de Obsidian es AGPL-3.0. Si lo usas para ti, da igual. Si lo integras en un producto, mira bien qué implica.
El diagrama vive junto al código
Y esta es la tesis de todo el episodio, así que la digo clara. Commitea el .excalidraw al lado de tu código. En docs/arquitectura.excalidraw, junto a los fuentes. Ha dejado de vivir en una carpeta perdida y ahora es un fichero más de tu repositorio, con su historial, sus diferencias y sus revisiones.
El PNG no lo commiteas a mano, lo regeneras. Con el comando render en tu pipeline de CI, que desde la 2.1 es headless y no necesita navegador. Cada vez que se reconstruye, el PNG sale idéntico si nada ha cambiado. Y ahí está la joya, en que al ser determinista byte a byte no tienes phantom diffs, esos diffs fantasma que aparecen porque el renderizador ha decidido cambiar el antialiasing o reordenar un atributo. Aquí no. Si el PNG cambia, es porque tu arquitectura ha cambiado de verdad. Y eso convierte un PNG en algo que merece estar en la revisión de un pull request.
Pero hay un paso más, y es el que me voló la cabeza cuando lo probé. Si el diagrama vive en el repo y el agente sabe leer el repo, puedes pedirle que mantenga el diagrama al día. Basta con dejarlo escrito en el AGENTS.md,
**Diagramas**
- `docs/arquitectura.excalidraw` refleja la arquitectura real del repo.
- Si un cambio toca módulos, dependencias o servicios externos,
actualiza el diagrama con la skill de Excalidraw.
- Antes de terminar: `describe` y `screenshot`, corrige solapamientos
y etiquetas cortadas. Después `render` para regenerar el PNG.
A partir de ahí, cada modificación del código se puede ver reflejada en el dibujo sin que tú entres a mano. Imagina lo que eso significa en una tesis doctoral, donde añades una rama extinta al capítulo tres y el árbol del capítulo uno se actualiza. O en la documentación de la estructura de tu departamento, cuando entra un equipo nuevo y el organigrama se recoloca. El diagrama deja de ser un entregable que se hace una vez y pasa a ser un subproducto del trabajo.
Los límites, sin dramatizar
Como todo, esto tiene límites, y te los vas a encontrar, así que mejor que los conozcas de mi boca que de tu mala tarde.
El primero y el más importante es que no hay auto-layout garantizado. El MCP tiene align, distribute y group, y el agente itera hasta que las etiquetas encajan y nada se solapa, pero eso depende de que revise. En diagramas grandes ese bucle cuesta más, porque cada corrección es un render y una vuelta más de mirar y recolocar. Siete cajas las deja impecables. Treinta, con sus flechas cruzadas y sus subgrafos, probablemente no. Mi consejo es que en diagramas grandes revises tú el resultado. El agente te ahorra el noventa por ciento del trabajo sucio, pero la última pasada de ojo humano no te la quita nadie. Y eso no es culpa del MCP. Colocar treinta nodos sin solapes es un problema de layout difícil y no tiene solución mágica.
El segundo son las fuentes. El render headless usa tipografías empaquetadas, Excalifont, Virgil, Cascadia Code y Liberation Sans, todas SIL OFL 1.1 y todas cubriendo escritura latina. Perfecto para español, inglés y la mayoría de los diagramas técnicos. Pero si metes caracteres CJK, chino, japonés o coreano, o según qué emojis, esas fuentes no los cubren. resvg hace fallback a las fuentes del sistema, con un aviso, y te puede salir el texto en cajas, esos cuadraditos que todos hemos visto en algún PDF mal exportado. La solución está en tu mano, instala una fuente CJK en la máquina donde corre el canvas server y el fallback la encontrará. Si no usas esos alfabetos, este límite ni te roza.
El tercero son dos cosas a la vez y es el que más me importa que te lleves a casa. La primera es la persistencia, porque por defecto el canvas vive en memoria. Si no defines EXCALIDRAW_DATA_DIR, el estado está en RAM y en cuanto reinicias el canvas te encuentras un lienzo en blanco. Todo lo que no hayas exportado, adiós. Por eso insisto tanto en exportar a .excalidraw y commitearlo. Si tu diagrama está en el repo, no te importa que el canvas olvide, lo reconstruyes desde el fichero. Si solo vives del lienzo, un reinicio te volatiliza el trabajo.
La segunda es la seguridad, y es sencilla de resumir. El canvas escucha en 127.0.0.1 sin autenticación. Si lo expones en red poniendo HOST=0.0.0.0, no hay auth y el CORS es permisivo. Traducción, no lo pongas en internet, porque cualquiera puede dibujar, leer y borrar en tu lienzo. Si necesitas acceso desde otra máquina, tírale de cortafuegos o de VPN. El propio README lo avisa, así que no es un descubrimiento mío, pero conviene decirlo en voz alta.
Y hay un cuarto límite que se paga en cada turno, y ese es el contexto. Las 26 herramientas del MCP viajan en cada turno, con sus nombres y sus esquemas, así que un MCP cargado engorda la conversación antes de que hayas escrito nada. Es exactamente el peaje del que te hablé en el episodio en el que conté cómo se le dan manos a una IA, donde con 33 herramientas se me iban unos once mil tokens solo en definiciones. Aquí es menos grave, porque 26 es un número más contenido y porque el MCP solo se carga cuando lo necesitas, pero la lección es la misma. Mide el impacto si vas a tener varios MCPs activos a la vez, y quita los que no uses. Más manos no siempre es mejor si el agente acaba distraído eligiendo cuál usar.
Y hay un par de detalles menores que también cuentan. La conversión de Mermaid y set_viewport siguen necesitando pestaña, con su código de salida 4. La página del canvas carga las fuentes de Excalidraw desde esm.sh, así que sin internet tira de las del sistema, aunque los renders headless no se ven afectados porque usan las empaquetadas. Y si montas el canvas en Docker, la imagen del MCP trae EXCALIDRAW_NO_AUTOSTART=1 porque no lleva frontend, de modo que tienes que correr el canvas como contenedor aparte y ajustar host.docker.internal, que en Linux a veces pide --add-host=host.docker.internal:host-gateway.
Mermaid o Excalidraw MCP, elige por el resultado
Y para cerrar el círculo, volvamos a Mermaid, porque no es cuestión de tirarlo ahora a la basura. Mermaid y el MCP de Excalidraw resuelven momentos distintos, y el truco está en elegir por el resultado que quieres, no por la moda de la semana.
Mermaid es para documentación versionable y trivial. Escribes texto, lo commiteas, se regenera y cualquiera puede editarlo con un editor. No hay lienzo ni control elemento a elemento, pero para un diagrama de flujo dentro de un README o una nota técnica es perfecto. Rápido, barato y diferenciable. Y su propio MCP, el de peng-shawn, hace lo que tiene que hacer, convertir Mermaid en PNG o SVG, sin lienzo y sin edición, que para ese caso de uso es exactamente lo que se necesita.
Excalidraw MCP es para artefactos vistosos y editables. Cuando quieres que quede bien, que la persona que lo abra pueda tocar cajas, y sobre todo cuando quieres que el agente vea el resultado y lo corrija. Ahí Mermaid se queda corto y el toolkit brilla.
El criterio cabe en una pregunta. ¿El diagrama va a vivir dentro de un texto versionable o va a ser un artefacto que la gente va a abrir y manipular? Si es lo primero, Mermaid. Si es lo segundo, Excalidraw MCP. Y si es un diagrama que va a cambiar mil veces porque el proyecto está vivo, entonces la respuesta casi siempre es Excalidraw MCP con el .excalidraw commiteado, porque es el único de los dos que se regenera con el código sin que tú entres a dibujar.
Lo que me llevo
Llegados a este punto, la conclusión es corta. El diagrama deja de ser un dibujo que caduca y pasa a ser un artefacto que se regenera con tu código. Esa diferencia es la que cambia todo, porque ya no dibujas diagramas, los generas, los revisas y los versionas junto a lo que representan.
Recapitulando. Montas el MCP en tu agente, con la vía de la skill por CLI que es la recomendada, le pides el diagrama, dejas que se mire y se corrija él solo, y lo exportas a .excalidraw, a PNG, a SVG o a tu vault de Obsidian. Y commiteas el .excalidraw junto al código, con el PNG regenerándose en CI sin navegador y sin phantom diffs. Y ya no tienes un mentiroso de museo colgado en la pared, tienes una pieza viva del repositorio.
Reconozco que el primer diagrama cuesta. Yo he visto al agente pelearse con la primera versión más de lo que me gustaría, y he visto cómo la segunda y la tercera salían casi solas. Eso va a mejor cada mes, y mientras tanto sigue siendo más rápido que arrastrar cajas un martes por la tarde. 😊
Así que la llamada a la acción es concreta, y es para esta tarde. Coge un proyecto tuyo, arranca el canvas en 127.0.0.1:3000, pídele la arquitectura y deja que la dibuje. Son cinco minutos y el resultado te va a sorprender. Y si te encuentras moviendo la última caja a mano, tranquilo, que eso nos pasa a todos. Nos leemos en los comentarios y nos escuchamos el próximo lunes.
Más información
- mcp_excalidraw, el toolkit protagonista (GitHub) — repositorio, README completo y tabla de las 26 herramientas
- mcp-excalidraw-server en npm — paquete, versión publicada y requisitos de Node
- Excalidraw, el motor de dibujo — el proyecto original, MIT, del que cuelga todo esto
- MCP oficial de Excalidraw — el widget de un solo tiro, para comparar enfoques
- Documentación de OpenCode, servidores MCP — la forma actual de la clave
mcpy eltype: "local" - Documentación de OpenCode, Agent Skills — dónde busca las skills, en proyecto y en global
- Plugin de Excalidraw para Obsidian — abre los
.excalidraw.mdde forma nativa, AGPL-3.0 - Mermaid, documentación oficial — sintaxis, versión del motor y filosofía de diagramas como texto
- mermaid-mcp-server — el contrapunto, Mermaid a PNG/SVG sin lienzo
- Especificación del Model Context Protocol — el estándar que hay debajo de todo esto
- Código fuente de Excalidraw, exportToSvg y render — para entender qué hace el render headless
- Demo en vídeo del toolkit — el agente dibujando, mirando y corrigiendo, en dos minutos