Krita
Un modelo maneja Krita 5.2.9 a través del Hub para pintar una postal en dos capas y guardarla como archivo .kra. El primer script funcionó. Esta página da el texto, el script, las respuestas del Hub y la captura, y explica cómo se inició el puente: no desde Scripter, que no se probó.
En esta página
Iniciar Krita con su puente
La guía hace que el operador ejecute el archivo del puente desde Scripter. Esta ejecución no usó ese gesto. Inició Krita en una pantalla X virtual, en un perfil nuevo, con una extensión de arranque cuyo __init__.py entero ejecuta el archivo del puente:
xvfb-run -a krita --nosplash
exec(open('/usr/share/libremodular-mcp/bridges/krita_bridge.py', encoding='utf-8').read())
La codificación no es opcional. El Python incorporado de Krita lee los archivos con la codificación de la configuración regional con la que se inició, y el archivo del puente contiene caracteres con acento: en la configuración regional C, un comando sin encoding='utf-8' se detuvo con UnicodeDecodeError, como registra la página de compatibilidad. La ejecución usó el puerto 9312 en config.toml y un token nuevo. El puerto empezó a escuchar 10,4 s después del inicio, y get_state sobre hub enumeró Krita como conectado:
{
"app": "hub",
"app_version": "0.1.0",
"bridge_version": null,
"captured_at": "2026-10-21T12:47:48.951Z",
"connected": true,
"content_origin": "hub",
"screenshot": null,
"state": {
"modules": [
{
"app_version": "5.2.9",
"bridge_version": "1",
"connected": true,
"mode": "tcp",
"name": "krita"
}
]
},
"warnings": []
}Texto dado al modelo
Antes de escribir, el modelo llamó a get_state sobre krita: "document": null. El documento aún no existe, así que el script tiene que crearlo y abrirlo en una ventana antes de poder pintar.
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. El script escribe los bytes de los píxeles en el orden azul, verde, rojo, alfa; los colores de la captura de más abajo muestran que es el orden que Krita espera para este documento. El script activa el modo por lotes antes de saveAs; lo que ocurre sin él no se probó.
import os
krita = Krita.instance()
document = krita.createDocument(600, 400, "Postcard", "RGBA", "U8", "", 72.0)
krita.activeWindow().addView(document)
root = document.rootNode()
def lerp(a, b, t):
return round(a + (b - a) * t)
top, bottom = (0x1c, 0x38, 0x5c), (0x29, 0xa1, 0x96)
sky_pixels = bytearray()
for y in range(400):
t = y / 399
r, g, b = (lerp(top[i], bottom[i], t) for i in range(3))
sky_pixels += bytes((b, g, r, 255)) * 600
sky = document.createNode("Sky", "paintlayer")
root.addChildNode(sky, None)
sky.setPixelData(bytes(sky_pixels), 0, 0, 600, 400)
hill_pixels = bytearray()
for y in range(400):
for x in range(600):
inside = ((x - 300) / 260) ** 2 + ((y - 400) / 120) ** 2 <= 1
hill_pixels += bytes((0x38, 0x54, 0xC2, 255)) if inside else bytes((0, 0, 0, 0))
hill = document.createNode("Hill", "paintlayer")
root.addChildNode(hill, None)
hill.setPixelData(bytes(hill_pixels), 0, 0, 600, 400)
document.refreshProjection()
document.setBatchmode(True)
path = os.path.join(LMM_WORK_DIR, "postcard.kra")
saved = document.saveAs(path)
result = {"saved": saved, "kra_bytes": os.path.getsize(path), "layers": [node.name() for node in document.topLevelNodes()]}Respuesta del Hub
{
"app": "krita",
"duration_ms": 1060,
"error": null,
"result": {
"kra_bytes": 110725,
"layers": [
"Background",
"Sky",
"Hill"
],
"saved": true
},
"status": "ok",
"stderr": "",
"stdout": "",
"truncated": false
}El script se ejecutó en 1,06 s. El documento tiene tres capas, porque un documento nuevo de Krita empieza con una capa Background que el script no tocó, bajo Sky y Hill. get_state describió entonces el documento y devolvió una captura de su proyección:
{
"app": "krita",
"app_version": "5.2.9",
"bridge_version": "1",
"captured_at": "2026-10-21T12:47:50.526Z",
"connected": true,
"content_origin": "document",
"screenshot": "$XDG_RUNTIME_DIR/libremodular-mcp/captures/krita-20261021T124750502Z.png",
"state": {
"document": {
"active_layer": "{727e9cd9-e6e1-423c-ade7-1bf29d6d5289}",
"color_depth": "U8",
"color_model": "RGBA",
"color_profile": "sRGB-elle-V2-srgbtrc.icc",
"height": 400,
"layers": [
{
"id": "{69f5540d-2916-4771-8df7-1fcad46b677f}",
"name": "Background",
"opacity": 255,
"type": "paintlayer",
"visible": true
},
{
"id": "{ed307be8-5a93-4b16-8739-7508916ea687}",
"name": "Sky",
"opacity": 255,
"type": "paintlayer",
"visible": true
},
{
"id": "{727e9cd9-e6e1-423c-ade7-1bf29d6d5289}",
"name": "Hill",
"opacity": 255,
"type": "paintlayer",
"visible": true
}
],
"name": "Postcard",
"width": 600
}
},
"warnings": []
}La imagen producida
La captura es la imagen fusionada que muestra Krita, de 600 por 400 píxeles. Los píxeles que se leen en ella son #1C385C arriba, #29A196 abajo y #C25438 dentro de la colina, los tres colores que pedía el texto. El archivo .kra que guardó el script pesa 110 725 bytes.
