Inkscape
Un modelo maneja Inkscape 1.4 a través del Hub para componer una tarjeta de visita en dos capas. Inkscape es la única aplicación de aquí en la que no hay nada que iniciar: el Hub ejecuta un proceso de Python por cada script. Esta página da el texto, el script, las respuestas del Hub y la captura.

En esta página
Activar Inkscape
No hay puente ni ventana. El Hub busca /usr/bin/python3, /usr/bin/inkscape y las extensiones de Inkscape en /usr/share/inkscape/extensions. Toda la preparación es una entrada en ~/.config/libremodular-mcp/config.toml, después de libremodular-mcp init:
[apps.inkscape]
enabled = true
En un Debian 13 recién instalado, import inkex necesita además python3-tinycss2, que el paquete inkscape no instala: sudo apt install inkscape python3-tinycss2.
get_state sobre hub enumeró Inkscape como conectado en el modo cli, con la versión que informó Inkscape:
{
"app": "hub",
"app_version": "0.1.0",
"bridge_version": null,
"captured_at": "2026-10-21T12:47:13.608Z",
"connected": true,
"content_origin": "hub",
"screenshot": null,
"state": {
"modules": [
{
"app_version": "1.4",
"bridge_version": null,
"connected": true,
"mode": "cli",
"name": "inkscape"
}
]
},
"warnings": []
}Texto dado al modelo
Antes de escribir, el modelo llamó a get_state sobre inkscape. El state estaba vacío y una advertencia decía no document yet: the working document is created by the first script.
Script escrito
Un modelo, Claude Sonnet 5.5, escribió este script a partir de la guía y de ese estado. No es un script tomado de las pruebas del proyecto. Dos líneas vienen de la guía: el script elimina primero los hijos de la raíz, porque el documento se conserva de un script al siguiente, y fija cx, cy y r del círculo uno por uno, porque, como advierte la guía, los dos argumentos de inkex.Circle.new no forman un centro.
import json
import os
import inkex
document = inkex.load_svg(os.environ["LMM_DOCUMENT"])
svg = document.getroot()
for child in list(svg):
svg.remove(child)
svg.set("width", "148mm")
svg.set("height", "105mm")
svg.set("viewBox", "0 0 148 105")
background = svg.add(inkex.Layer.new("Background"))
panel = inkex.Rectangle.new(0, 0, 148, 105)
panel.style = {"fill": "#1c385c"}
background.add(panel)
disc = inkex.Circle()
disc.set("cx", "20")
disc.set("cy", "20")
disc.set("r", "9")
disc.style = {"fill": "#c25438"}
background.add(disc)
rule = inkex.Rectangle.new(20, 62, 108, 0.8)
rule.style = {"fill": "#f2b344"}
background.add(rule)
texts = svg.add(inkex.Layer.new("Text"))
for content, y, size, colour, weight in [("Alice Martin", 56, 12, "#ffffff", "bold"), ("Sound engineer", 76, 6, "#cfd4da", "normal")]:
line = inkex.TextElement()
line.text = content
line.set("x", "20")
line.set("y", str(y))
line.style = {"fill": colour, "font-size": f"{size}px", "font-family": "sans-serif", "font-weight": weight}
texts.add(line)
document.write(os.environ["LMM_DOCUMENT"])
print("LMM_RESULT: " + json.dumps({"layers": [layer.label for layer in svg.descendants().filter(inkex.Layer)], "elements": len(list(svg.descendants()))}))Respuesta del Hub
{
"app": "inkscape",
"duration_ms": 151,
"error": null,
"result": {
"elements": 8,
"layers": [
"Background",
"Text"
]
},
"status": "ok",
"stderr": "",
"stdout": "",
"truncated": false
}El script se ejecutó en 151 ms: se inició y terminó un proceso de Python. El script imprimió su result en la última línea, tras LMM_RESULT: , que es la forma en que un script de Inkscape devuelve un valor. get_state describió entonces el documento de trabajo y devolvió una captura:
{
"app": "inkscape",
"app_version": "1.4",
"bridge_version": null,
"captured_at": "2026-10-21T12:47:14.185Z",
"connected": true,
"content_origin": "document",
"screenshot": "$XDG_RUNTIME_DIR/libremodular-mcp/captures/inkscape-20261021T124713832Z.png",
"state": {
"element_count": 8,
"height": "105mm",
"layers": [
{
"id": null,
"label": "Background"
},
{
"id": null,
"label": "Text"
}
],
"width": "148mm"
},
"warnings": []
}La imagen producida
La captura es el documento de trabajo exportado por el propio inkscape, de 559 por 397 píxeles para una tarjeta de 148 por 105 mm. El texto se dibuja con la fuente sans-serif de esta máquina, así que otra máquina lo dibuja con la suya. El píxel de arriba a la izquierda de la captura es #1C385C y el que está dentro del círculo es #C25438.
