Skip to main content
Glama

nakkaş significa pintor/artista en turco (antiguo).

"make a neon terminal logo with animated binary digits"
  → AI constructs JSON config
  → nakkas renders to animated SVG
  → clean animated SVG output

Por qué

  • Una herramienta, diseños infinitos. render_svg toma una configuración JSON. La IA completa todo.

  • Esquema nativo para IA. Cada campo tiene anotaciones .describe() para que el modelo sepa qué hacer.

  • SVG declarativo puro. CSS @keyframes + animaciones SMIL, sin JavaScript.

  • Cero dependencias externas. Sin API en la nube, sin claves API. Se ejecuta localmente.

Instalación

Claude Desktop

Añade a tu archivo de configuración:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

  • Linux: ~/.config/Claude/claude_desktop_config.json

  • Windows: %APPDATA%\Claude\claude_desktop_config.json

{
  "mcpServers": {
    "nakkas": {
      "command": "npx",
      "args": ["-y", "nakkas@latest"]
    }
  }
}

Claude Code (CLI)

claude mcp add nakkas npx nakkas@latest

Cursor / Zed / Otros clientes MCP

{
  "mcpServers": {
    "nakkas": {
      "command": "npx",
      "args": ["-y", "nakkas@latest"]
    }
  }
}

Desarrollo local

git clone https://github.com/arikusi/nakkas
cd nakkas
npm install && npm run build
# Use dist/index.js as the command

Inicio rápido

Pide a tu IA (con Nakkas conectado):

"Haz un SVG animado: marco de terminal oscuro (800×200), texto cian brillante 'NAKKAS', filtro de neón, desvanecimiento al cargar."

"Crea un spinner de carga: un círculo con una animación de trazo que se repite cada 1.5 segundos."

"Visualización de datos: gráfico de barras animado, 5 barras, cada una desvaneciéndose con un retraso escalonado, rellenos degradados."

"Insignia de perfil (400×120): degradado de azul a morado, texto de nombre de usuario en blanco, sombra paralela, animación de pulso sutil."

Herramientas

Nakkas proporciona tres herramientas:

Herramienta

Propósito

render_svg

Toma JSON de SVGConfig, devuelve cadena SVG + advertencias de análisis de diseño

preview

Toma contenido renderizado, devuelve una imagen PNG para inspección visual

save

Toma contenido renderizado, guarda en disco como SVG (texto) o PNG (ráster)

El flujo de trabajo previsto: renderizar → previsualizar → iterar → guardar. La herramienta save está separada de render_svg para fomentar la previsualización y el refinamiento antes de guardar.

La herramienta save

{ "content": "<svg ...>...</svg>", "outputPath": "./design.svg", "format": "auto" }

Formatos: auto (deducido de la extensión), svg (archivo de texto), png (renderiza a ráster primero). Si el archivo existe, se añade un contador numérico para evitar sobrescribir. Se devuelve la ruta guardada real.

La herramienta render_svg

Entrada: Objeto JSON SVGConfig Salida: Cadena XML SVG completa más notas opcionales de análisis de diseño

Después de renderizar, la respuesta puede incluir advertencias de diseño sobre problemas comunes como demasiadas animaciones simultáneas, falta de transformBox o transformaciones de escala a nivel de grupo.

Estructura de SVGConfig

{
  canvas: {
    width: number | string,   // e.g. 800 or "100%"
    height: number | string,
    viewBox?: string,          // "0 0 800 400"
    background?: string        // hex "#111111" or "transparent"
  },

  defs?: {
    gradients?: Gradient[],   // linearGradient | radialGradient
    filters?: Filter[],        // preset or raw primitives
    clipPaths?: ClipPath[],
    masks?: Mask[],
    symbols?: Symbol[],
    paths?: { id, d }[]       // for textPath elements
  },

  elements: Element[],         // shapes, text, groups, use instances

  animations?: CSSAnimation[]  // CSS @keyframes definitions
}

Tipos de elementos

Tipo

Campos requeridos

Notas

rect

width, height

x, y por defecto 0; rx/ry para esquinas redondeadas

circle

r

cx, cy por defecto 0

ellipse

rx, ry

Radios horizontal/vertical independientes

line

x1, y1, x2, y2

polyline

points

Ruta abierta: "10,20 50,80 90,20"

polygon

points

Forma cerrada automáticamente

path

d

Comandos de ruta SVG completos

image

href, width, height

URL o URI data:image/... para imágenes incrustadas

text

content

Cadena o matriz (string | Tspan)[]

textPath

pathId, text

Texto siguiendo una curva; ruta definida en defs.paths

group

children

Atributos compartidos aplicados a todos los hijos (sin grupos anidados)

use

href

Instanciar un símbolo o clonar un elemento por #id

radial-group

cx, cy, count, radius, child

Colocar N copias alrededor de un círculo completo

arc-group

cx, cy, radius, count, startAngle, endAngle, child

Colocar N copias a lo largo de un arco circular

grid-group

cols, rows, colSpacing, rowSpacing, child

Colocar copias en una cuadrícula de M por N

scatter-group

width, height, count, seed, child

Dispersar N copias en posiciones aleatorias con semilla

path-group

waypoints, count, child

Distribuir N copias uniformemente a lo largo de una polilínea

parametric

fn

Curva matemática: rose, heart, star, lissajous, spiral, superformula, epitrochoid, hypotrochoid, wave

Todos los elementos visuales (Campos compartidos)

{
  id?: string,             // required for filter/gradient/clip references
  cssClass?: string,       // matches CSS animation names
  fill?: string,           // "#rrggbb" | "none" | "url(#gradId)"
  stroke?: string,
  strokeWidth?: number,
  strokeDasharray?: string, // "10 5", use for draw-on animation
  strokeDashoffset?: number,
  opacity?: number,        // 0–1
  filter?: string,         // "url(#filterId)"
  clipPath?: string,       // "url(#clipId)"
  transform?: string,      // "rotate(45)" "translate(100, 50)"
  transformBox?: "fill-box" | "view-box" | "stroke-box",  // set "fill-box" for CSS rotation
  transformOrigin?: string, // "center", works with fill-box
  smilAnimations?: SMILAnimation[]
}

Ajustes preestablecidos de filtros

Referencia como filter: "url(#myId)" en cualquier elemento después de definirlo en defs.filters:

{ "type": "preset", "id": "myGlow", "preset": "glow", "stdDeviation": 8, "color": "#ff00ff" }

Ajuste

Parámetros clave

Efecto

glow

stdDeviation, color

Halo suave

neon

stdDeviation, color

Brillo intenso

blur

stdDeviation

Desenfoque gaussiano

drop-shadow

stdDeviation, offsetX, offsetY, color

Sombra paralela

glitch

stdDeviation

Desplazamiento de turbulencia (animado)

grayscale

value (0–1)

Desaturar

sepia

Tono sepia cálido

invert

Invertir colores

saturate

value

Aumentar/reducir saturación

hue-rotate

value (grados)

Cambiar tonos

chromatic-aberration

value (desplazamiento px, por defecto 3)

División de canal RGB para efecto de distorsión de lente

noise

value (opacidad 0 a 1, por defecto 0.25)

Grano de película y superposición de textura

outline

color, value (grosor, por defecto 2)

Contorno coloreado alrededor del elemento

inner-shadow

color, stdDeviation, value (opacidad, por defecto 0.5)

Sombra dentro del elemento

emboss

stdDeviation, value (intensidad, por defecto 1.5)

Efecto de sombreado en relieve 3D

Animaciones CSS

{
  "animations": [{
    "name": "pulse",
    "duration": "2s",
    "iterationCount": "infinite",
    "direction": "alternate",
    "keyframes": [
      { "offset": "from", "properties": { "opacity": "0.3", "transform": "scale(0.9)" } },
      { "offset": "to",   "properties": { "opacity": "1",   "transform": "scale(1.1)" } }
    ]
  }],
  "elements": [{
    "type": "circle",
    "cx": 100, "cy": 100, "r": 40,
    "cssClass": "pulse",
    "transformBox": "fill-box",
    "transformOrigin": "center"
  }]
}

Claves de propiedad CSS: camelCase (strokeDashoffset) o kebab-case (stroke-dashoffset). Ambos funcionan.

Propiedades CSS animables: opacity, fill, stroke, transform, filter, clip-path, stroke-dasharray, stroke-dashoffset, font-size, letter-spacing y más.

Animaciones SMIL

Tres tipos de SMIL, definidos en línea en cada elemento mediante smilAnimations: []:

{ "kind": "animate",          "attributeName": "d",       "from": "...", "to": "...", "dur": "2s" }
{ "kind": "animateTransform", "type": "rotate",            "from": "0 100 100", "to": "360 100 100", "dur": "3s" }
{ "kind": "animateMotion",    "path": "M 0 0 C ...",      "dur": "4s", "rotate": "auto" }

Morfología de ruta (attributeName: "d"): las rutas de origen/destino deben tener tipos y recuentos de comandos idénticos. Solo pueden diferir las coordenadas.

Fuentes

Las fuentes del sistema funcionan en todas partes sin necesidad de carga: Arial, Helvetica, Courier New, Georgia, Verdana, monospace, sans-serif, serif.

También se aceptan familias de fuentes personalizadas. Funcionan cuando la fuente está disponible en el entorno de renderizado (página web con fuentes cargadas, herramienta de diseño, etc.).

Casos de uso y compatibilidad

Contexto

CSS @keyframes

SMIL

Fuentes externas

Interactivo (onclick)

GitHub README <img>

Página web <img>

SVG en línea en página web

Exportación de herramienta de diseño

Visor de archivos estáticos

depende

depende

Solución de problemas

"MCP error -32602: Input validation error"

Esto significa que el SDK de MCP rechazó la entrada antes de que llegara al controlador. Suele ocurrir en el primer intento y funciona al reintentar. Los disparadores más comunes:

  • Error tipográfico en el tipo de degradado. Usa "linearGradient" o "radialGradient", no "linear" o "radial". Este es el error más frecuente.

  • Desplazamiento de fotograma clave como cadena. Escribe 0 o 100 (números) o "from" / "to". Escribir "0%" o "100%" fallará.

  • Colores con nombre. Solo funcionan los valores hexadecimales: "#ff0000", no "red". Tampoco rgb().

  • Falta type en los elementos. Cada objeto de elemento necesita un campo type.

Si estás creando una integración de cliente MCP y ves esto constantemente, el problema probablemente esté en cómo tu cliente serializa los argumentos. Consulta anthropics/claude-code#29104 para obtener contexto sobre peculiaridades de serialización conocidas.

La vista previa muestra una imagen en blanco o inesperada

La herramienta de vista previa renderiza una instantánea estática en t=0. Las animaciones no se capturan. Lo que ves es el estado inicial del SVG antes de que comience cualquier animación CSS o SMIL.

Si la imagen está completamente en blanco:

  • Comprueba que tus elementos tengan fill o stroke configurados. Una forma sin relleno en un lienzo transparente es invisible.

  • Comprueba las coordenadas. Un elemento en x: 2000 en un lienzo de 800px de ancho está simplemente fuera de la pantalla.

  • Si usas filter: "url(#myFilter)", asegúrate de que myFilter esté realmente definido en defs.filters.

Las animaciones no funcionan en GitHub

Los README de GitHub renderizan SVG a través de etiquetas <img>, que eliminan JavaScript pero mantienen CSS y SMIL. Si tu animación funciona localmente pero no en GitHub:

  • Evita <script> o controladores de eventos (onclick, onmouseover). Estos se eliminan.

  • Las fuentes externas no se cargarán. Limítate a las fuentes del sistema: Arial, Courier New, Georgia, monospace, sans-serif.

  • CSS @import para fuentes está bloqueado. Si necesitas una fuente específica, usa <text> en línea con una alternativa del sistema.

Salida SVG grande

Si render_svg devuelve una advertencia sobre el tamaño del archivo (más de 50kb), las curvas paramétricas o los grupos de patrones probablemente estén generando demasiados elementos. Reduce steps en las curvas paramétricas o count en los grupos de patrones. Un grid-group con cols: 50, rows: 50 produce 2500 elementos, lo cual suma rápidamente.

Stack tecnológico

  • TypeScript + Node.js 18+

  • @modelcontextprotocol/sdk (servidor MCP)

  • zod (validación de esquema y guía de tipos para IA)

  • Sin bibliotecas SVG externas, construcción XML pura

  • Vitest (280 pruebas)

Licencia

MIT. Creado por arikusi.

Install Server
A
security – no known vulnerabilities
A
license - permissive license
-
quality - not tested

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/arikusi/nakkas'

If you have feedback or need assistance with the MCP directory API, please join our Discord server