Automatizar dibujos DWG con Python (y con AutoLISP o MCP)
Dibujar la misma rejilla de ejes en cada proyecto, contar bloques en cien planos o poner en capa lo que alguien dejó en la capa 0 son tareas que se repiten. LinceCAD se puede manejar desde fuera con una API local: un script de Python abre dibujos, crea entidades, cambia capas, ejecuta comandos y guarda en DWG. Todo va por canales del propio equipo; nada sale a internet.
Cuatro caminos, según lo que necesites
| Vía | Qué es | Cuándo usarla |
|---|---|---|
| API local (JSON-RPC) | Un mensaje JSON por línea por una tubería con nombre (Windows) o un socket (Linux). Funciona desde cualquier lenguaje. | Manejar LinceCAD, con la ventana abierta o sin ella, desde tus propios programas. |
Cliente lince de Python | Una biblioteca sin dependencias sobre esa API: dib.linea(…), dib.guardar_como(…)… | Scripts de Python más cortos y legibles. |
Rueda lince_nucleo | Un módulo de Python compilado que lee, modifica y guarda DWG/DXF sin abrir LinceCAD. | Lotes de archivos, servidores o Jupyter. |
| AutoLISP | El intérprete incorporado, con unas 200 funciones. | Comandos propios dentro del programa, o rutinas LISP que ya tengas. |
Además, LinceCAD trae un servidor MCP para conectar asistentes de IA, del que hablamos al final.
Paso 1: activar la automatización
La API está desactivada por defecto. Hay dos formas de usarla:
- Con la ventana abierta: en
OPCIONES, pestaña Automatización, activa el canal local. Ahí también puedes dejarla en solo lectura y limitar las carpetas en las que se puede abrir, guardar y trazar. El canal es\\.\pipe\lince-<usuario>en Windows y$XDG_RUNTIME_DIR/lince.socken Linux. - Sin ventana:
lince --servidoratiende la API sin nada a la vista, para procesos por lotes. Con--canal NOMBREeliges el nombre de la tubería. En Linux necesita una sesión gráfica (oxvfb-run).
Los programas se identifican con una ficha (una contraseña de 64 caracteres) que está en
api.toml, en %APPDATA%\lince en Windows o ~/.config/lince en Linux. Solo tu
usuario puede leerla.
Paso 2: un script con la biblioteca estándar
Este ejemplo no necesita instalar nada más que Python. Arranca antes lince --servidor --canal blogpy
(o usa el canal de la ventana abierta). El script se presenta con la ficha, crea un dibujo, una capa y una parcela
de 30 × 20 y la guarda en DWG:
import json, os
# La ficha (contraseña de la API) está en %APPDATA%\lince\api.toml
toml = os.path.join(os.environ["APPDATA"], "lince", "api.toml")
ficha = next(l.split("=", 1)[1].strip().strip('"')
for l in open(toml, encoding="utf-8") if l.startswith("ficha"))
canal = open(r"\\.\pipe\blogpy", "r+b", buffering=0) # lince --servidor --canal blogpy
n = 0
def llamar(metodo, **params):
global n
n += 1
msg = {"jsonrpc": "2.0", "id": n, "method": metodo, "params": params}
canal.write((json.dumps(msg) + "\n").encode("utf-8"))
r = json.loads(canal.readline())
if "error" in r:
raise RuntimeError(r["error"]["message"])
return r["result"]
llamar("session.hello", token=ficha)
llamar("document.new")
llamar("layer.create", name="PARCELA", color=1)
llamar("entity.create", entity={"type": "LWPOLYLINE", "layer": "PARCELA", "closed": True,
"vertices": [[0, 0], [30, 0], [30, 20], [0, 20]]})
print(llamar("document.summary")["byType"]) # {'LWPOLYLINE': 1}
print(llamar("document.saveAs", path=r"C:\planos\parcela.dwg"))
La primera petición de cada conexión tiene que ser session.hello; si no, la conexión se cierra. En
Linux, en vez de open(), conecta un socket.AF_UNIX a la ruta del socket y usa
s.makefile("rwb", buffering=0); el resto es igual.
La API tiene métodos para dibujos (document.open, save, saveAs,
summary…), entidades (entity.query, get, create,
set, delete, como objetos o como listas DXF de entget), capas, bloques,
estilos, variables, designación, deshacer, comandos (command.run), AutoLISP (lisp.eval),
trazado a PDF, PNG y SVG, captura de la vista y eventos. document.saveAs guarda en DWG o DXF según la
extensión, en versión 2018 por defecto o en 2013, 2010, 2007, 2004, 2000 y R14.
Paso 3: lo mismo con el cliente de Python
El cliente lince envuelve esa API en objetos. Este script, con lince.iniciar(), arranca
LinceCAD sin ventana, dibuja una rejilla de ejes con sus rótulos y doce pilares de 30 × 30 cm, y guarda el DWG, un
PDF y una imagen:
import lince
ejes_x = [0, 5.0, 10.5, 16.0] # posición de los ejes, en metros
ejes_y = [0, 4.5, 9.0]
h = 0.15 # medio lado de un pilar de 30 x 30 cm
with lince.iniciar() as s: # arranca LinceCAD sin ventana
dib = s.nuevo()
dib.crear_capa("EJES", color=1)
dib.crear_capa("PILARES", color=7)
dib.crear_capa("ROTULOS", color=3)
with dib.transaccion(): # todo queda en un solo paso de deshacer
for i, x in enumerate(ejes_x):
dib.linea([x, -1.5], [x, ejes_y[-1] + 1.5], layer="EJES")
dib.texto([x - 0.15, ejes_y[-1] + 2], str(i + 1), altura=0.4, layer="ROTULOS")
for j, y in enumerate(ejes_y):
dib.linea([-1.5, y], [ejes_x[-1] + 1.5, y], layer="EJES")
dib.texto([-2.3, y - 0.2], "ABC"[j], altura=0.4, layer="ROTULOS")
for x in ejes_x:
for y in ejes_y:
dib.polilinea([[x - h, y - h], [x + h, y - h], [x + h, y + h], [x - h, y + h]],
cerrada=True, layer="PILARES")
print(dib.resumen()["byType"]) # {'LINE': 7, 'LWPOLYLINE': 12, 'TEXT': 7}
dib.trazar_pdf(r"C:\planos\ejes.pdf")
dib.guardar_como(r"C:\planos\ejes.dwg")
dib.captura(r"C:\planos\ejes.png", ancho=1280)

dib.captura.Para trabajar con la ventana ya abierta se usa lince.conectar() y s.dibujo (el dibujo
activo). Hay también .circulo, .arco, .mtexto, .insertar (bloques),
.consultar (por tipo, capa, caja o filtro), .comando, .lisp y
.trazar_png/.trazar_svg.
Sin abrir LinceCAD: la rueda lince_nucleo
Para procesar muchos archivos, la rueda lince_nucleo trabaja dentro del propio proceso de Python. Este
fragmento, de la documentación, lista los círculos de un plano y lo guarda en DWG 2018:
import lince_nucleo as ln
dib = ln.abrir("plano.dwg")
for e in dib.consultar(tipo="CIRCLE"):
print(e["handle"], e["radius"])
dib.guardar("salida.dwg", "2018")
La alternativa sin Python: AutoLISP
Si ya trabajas con LISP, puedes seguir haciéndolo. El intérprete de LinceCAD admite defun C:,
ssget con filtros, entget, entmod, entmake y
command, entre otras; las rutinas se cargan con APPLOAD o automáticamente desde
acaddoc.lsp. Este comando cuenta los pilares del plano anterior:
(defun C:CONTARPILARES (/ ss) (setq ss (ssget "X" '((0 . "LWPOLYLINE") (8 . "PILARES")))) (princ (strcat "\nPilares: " (itoa (if ss (sslength ss) 0)))) (princ) )
Sobre ejes.dwg responde «Pilares: 12». Para secuencias fijas de órdenes también están los guiones
(SCRIPT).
Asistentes de IA con MCP
lince --mcp es un servidor MCP (Model Context Protocol) por la entrada y la salida estándar,
para los asistentes que lo arrancan ellos. Con la ventana abierta se puede activar además un servidor MCP por HTTP, solo en
127.0.0.1. El asistente ve herramientas para abrir, consultar, crear, acotar, insertar bloques, trazar a
PDF, capturar la vista y deshacer, y la ayuda de LinceCAD como documentación. Por ejemplo, para darlo de alta en
Claude Code:
claude mcp add --scope project lince -- "C:\Program Files\lince\lince.exe" --mcp
Con la confirmación activada, cada cambio que pide el asistente espera en la paleta ACCIONESIA hasta
que lo aceptas o lo rechazas, y todo lo que hace una llamada se deshace con un solo DESHACER. La lista
completa de herramientas y una sesión real están en qué es MCP y cómo usarlo con
LinceCAD.
Limitaciones
- Solo local. La API atiende programas del mismo equipo; la tubería rechaza clientes remotos y el
HTTP no escucha fuera de
127.0.0.1. - Una petición cada vez por conexión y sin lotes JSON-RPC. Para trabajar en paralelo, abre varias conexiones.
- Entidades del espacio modelo. Las cotas son de solo lectura por
entity.create: se crean concommand.runo con la herramienta MCPadd_dimension. El color verdadero se lee pero no se escribe. - Sin preguntas al usuario.
lisp.evalfalla si la rutina pide datos (getpoint,entsel…), y el modo sin ventana no abre cuadros de diálogo. - La rueda no ejecuta comandos, AutoLISP, trazados ni capturas: eso lo hacen el cliente o la ventana.
- Paquetes de Python en la beta. La API y el servidor MCP vienen en
lince.exe. Los paqueteslinceylince_nucleotodavía no se publican en PyPI ni con el instalador (el paquete que hoy se llamalinceen PyPI es de otro proyecto); el ejemplo del paso 2 funciona sin ellos.
Preguntas frecuentes
¿Y si el plano de partida es un escaneo? Primero hay que pasarlo a vectores: lo explicamos en cómo vectorizar un plano escaneado y pasarlo a DWG.
¿Y en Linux? La API funciona igual, con un socket Unix. Lee cómo abrir y editar DWG en Linux.
¿Y para topografía? El proceso con la ficha Topografía está en curvas de nivel a partir de una nube de puntos LAS/LAZ.
La API local, AutoLISP y el servidor MCP vienen en LinceCAD, con licencia perpetua. Descargas · Ver precios · AutoLISP, automatización y el resto de funciones.