nakkas
nakkaş в переводе с турецкого (устар.) означает художник/живописец.
"make a neon terminal logo with animated binary digits"
→ AI constructs JSON config
→ nakkas renders to animated SVG
→ clean animated SVG outputПочему
Один инструмент, бесконечные дизайны.
render_svgпринимает JSON-конфигурацию. ИИ заполняет всё остальное.Схема, созданная для ИИ. Каждое поле имеет аннотации
.describe(), чтобы модель знала, что делать.Чистый декларативный SVG. CSS @keyframes + анимации SMIL, никакого JavaScript.
Никаких внешних зависимостей. Нет облачных API, нет API-ключей. Запускается локально.
Установка
Claude Desktop
Добавьте в свой конфигурационный файл:
macOS:
~/Library/Application Support/Claude/claude_desktop_config.jsonLinux:
~/.config/Claude/claude_desktop_config.jsonWindows:
%APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"nakkas": {
"command": "npx",
"args": ["-y", "nakkas@latest"]
}
}
}Claude Code (CLI)
claude mcp add nakkas npx nakkas@latestCursor / Zed / Другие MCP-клиенты
{
"mcpServers": {
"nakkas": {
"command": "npx",
"args": ["-y", "nakkas@latest"]
}
}
}Локальная разработка
git clone https://github.com/arikusi/nakkas
cd nakkas
npm install && npm run build
# Use dist/index.js as the commandБыстрый старт
Попросите свой ИИ (с подключенным Nakkas):
"Создай анимированный SVG: темная рамка терминала (800×200), светящийся голубой текст 'NAKKAS', неоновый фильтр свечения, плавное появление при загрузке."
"Создай индикатор загрузки: круг с анимацией отрисовки контура, которая зацикливается каждые 1,5 секунды."
"Визуализация данных: анимированная гистограмма, 5 столбцов, каждый появляется с задержкой, градиентная заливка."
"Значок профиля (400×120): градиент от синего к фиолетовому, белый текст имени пользователя, падающая тень, тонкая пульсирующая анимация."
Инструменты
Nakkas предоставляет три инструмента:
Инструмент | Назначение |
| Принимает JSON SVGConfig, возвращает SVG-строку + предупреждения анализа дизайна |
| Принимает отрендеренный контент, возвращает PNG-изображение для визуальной проверки |
| Принимает отрендеренный контент, сохраняет на диск как SVG (текст) или PNG (растр) |
Рекомендуемый рабочий процесс: рендеринг → предварительный просмотр → итерация → сохранение. Инструмент save отделен от render_svg, чтобы стимулировать предварительный просмотр и доработку перед сохранением.
Инструмент save
{ "content": "<svg ...>...</svg>", "outputPath": "./design.svg", "format": "auto" }Форматы: auto (определяется по расширению), svg (текстовый файл), png (сначала рендерится в растр). Если файл существует, добавляется числовой счетчик, чтобы предотвратить перезапись. Возвращается фактический путь сохранения.
Инструмент render_svg
Входные данные: JSON-объект SVGConfig
Выходные данные: Полная XML-строка SVG плюс дополнительные примечания по анализу дизайна
После рендеринга ответ может включать предупреждения о распространенных проблемах, таких как слишком большое количество одновременных анимаций, отсутствие transformBox или масштабирование на уровне группы.
Структура 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
}Типы элементов
Тип | Обязательные поля | Примечания |
|
|
|
|
|
|
|
| Независимые горизонтальный/вертикальный радиусы |
|
| |
|
| Открытый путь: |
|
| Автоматически замыкаемая фигура |
|
| Полные команды пути SVG |
|
| URL или URI |
|
| Строка или массив |
|
| Текст вдоль кривой; путь определяется в |
|
| Общие атрибуты, применяемые ко всем дочерним элементам (без вложенных групп) |
|
| Создание экземпляра символа или клонирование элемента по |
|
| Размещение N копий по кругу |
|
| Размещение N копий вдоль дуги |
|
| Размещение копий в сетке M на N |
|
| Разброс N копий в случайных позициях |
|
| Равномерное распределение N копий вдоль полилинии |
|
| Математическая кривая: |
Все визуальные элементы (общие поля)
{
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[]
}Пресеты фильтров
Ссылайтесь как filter: "url(#myId)" на любой элемент после определения в defs.filters:
{ "type": "preset", "id": "myGlow", "preset": "glow", "stdDeviation": 8, "color": "#ff00ff" }Пресет | Ключевые параметры | Эффект |
|
| Мягкий ореол |
|
| Интенсивное яркое свечение |
|
| Гауссово размытие |
|
| Падающая тень |
|
| Смещение турбулентности (анимированное) |
|
| Обесцвечивание |
| — | Теплый тон сепии |
| — | Инверсия цветов |
|
| Усиление/уменьшение насыщенности |
|
| Сдвиг оттенка |
|
| Разделение каналов RGB для эффекта искажения линзы |
|
| Зернистость пленки и наложение текстуры |
|
| Цветной контур вокруг элемента |
|
| Тень внутри элемента |
|
| Эффект 3D-рельефа |
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"
}]
}Ключи CSS-свойств: camelCase (strokeDashoffset) или kebab-case (stroke-dashoffset). Работают оба варианта.
Анимируемые CSS-свойства: opacity, fill, stroke, transform, filter, clip-path, stroke-dasharray, stroke-dashoffset, font-size, letter-spacing и другие.
Анимации SMIL
Три типа SMIL, определяются внутри каждого элемента через 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" }Морфинг путей (attributeName: "d"): начальный и конечный пути должны иметь идентичные типы и количество команд. Различаться могут только координаты.
Шрифты
Системные шрифты работают везде без загрузки: Arial, Helvetica, Courier New, Georgia, Verdana, monospace, sans-serif, serif.
Пользовательские семейства шрифтов также принимаются. Они работают, если шрифт доступен в среде рендеринга (веб-страница с загруженными шрифтами, дизайнерский инструмент и т.д.).
Варианты использования и совместимость
Контекст | CSS @keyframes | SMIL | Внешние шрифты | Интерактивность (onclick) |
GitHub README | ✅ | ✅ | ❌ | ❌ |
Веб-страница | ✅ | ✅ | ❌ | ❌ |
Встроенный SVG на веб-странице | ✅ | ✅ | ✅ | ✅ |
Экспорт из дизайн-инструмента | ✅ | ✅ | ✅ | — |
Просмотрщик статических файлов | ✅ | ✅ | зависит от | зависит от |
Устранение неполадок
"MCP error -32602: Input validation error"
Это означает, что SDK MCP отклонил входные данные до того, как они достигли обработчика. Обычно это происходит при первой попытке и работает при повторной. Самые частые причины:
Опечатка в типе градиента. Используйте
"linearGradient"или"radialGradient", а не"linear"или"radial". Это самая частая ошибка.Смещение ключевого кадра как строка. Пишите
0или100(числа) или"from"/"to". Написание"0%"или"100%"приведет к ошибке.Именованные цвета. Работают только шестнадцатеричные значения:
"#ff0000", а не"red".rgb()также не поддерживается.Отсутствие
typeу элементов. Каждый объект элемента должен иметь полеtype.
Если вы создаете интеграцию с MCP-клиентом и постоянно видите эту ошибку, проблема, скорее всего, в том, как ваш клиент сериализует аргументы. См. anthropics/claude-code#29104 для контекста об известных особенностях сериализации.
Предварительный просмотр показывает пустое или неожиданное изображение
Инструмент предварительного просмотра рендерит статический снимок в момент времени t=0. Анимации не захватываются. То, что вы видите, — это начальное состояние SVG до начала любой CSS или SMIL анимации.
Если изображение полностью пустое:
Проверьте, установлены ли у ваших элементов
fillилиstroke. Фигура без заливки на прозрачном холсте невидима.Проверьте координаты. Элемент с
x: 2000на холсте шириной800pxпросто находится за пределами экрана.Если используете
filter: "url(#myFilter)", убедитесь, чтоmyFilterдействительно определен вdefs.filters.
Анимации не работают на GitHub
GitHub README рендерит SVG через теги <img>, которые удаляют JavaScript, но сохраняют CSS и SMIL. Если ваша анимация работает локально, но не на GitHub:
Избегайте
<script>или обработчиков событий (onclick,onmouseover). Они удаляются.Внешние шрифты не загрузятся. Используйте системные шрифты:
Arial,Courier New,Georgia,monospace,sans-serif.CSS
@importдля шрифтов заблокирован. Если вам нужен специфический шрифт, используйте встроенный<text>с системным резервным вариантом.
Большой размер вывода SVG
Если render_svg возвращает предупреждение о размере файла (более 50 К
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