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 配置。AI 填充所有内容。AI 原生模式。 每个字段都有
.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快速入门
询问您的 AI(在连接 Nakkas 的情况下):
"制作一个动态 SVG:深色终端框架 (800×200),发光的青色文字 'NAKKAS',霓虹发光滤镜,加载时淡入。"
"创建一个加载旋转器:一个带有绘制描边动画的圆圈,每 1.5 秒循环一次。"
"数据可视化:动态柱状图,5 个柱子,每个柱子交错延迟淡入,渐变填充。"
"个人资料徽章 (400×120):蓝到紫渐变,白色用户名文字,投影,细微的脉冲动画。"
工具
Nakkas 提供三个工具:
工具 | 用途 |
| 接收 SVGConfig JSON,返回 SVG 字符串 + 设计分析警告 |
| 接收渲染内容,返回用于视觉检查的 PNG 图像 |
| 接收渲染内容,保存为 SVG(文本)或 PNG(栅格)到磁盘 |
推荐工作流:渲染 → 预览 → 迭代 → 保存。save 工具与 render_svg 分开,旨在鼓励在保存前进行预览和优化。
save 工具
{ "content": "<svg ...>...</svg>", "outputPath": "./design.svg", "format": "auto" }格式:auto(根据扩展名推断)、svg(文本文件)、png(先渲染为栅格)。如果文件已存在,将附加一个数字计数器以防止覆盖。返回实际保存的路径。
render_svg 工具
输入: SVGConfig JSON 对象
输出: 完整的 SVG XML 字符串以及可选的设计分析说明
渲染后,响应可能包含关于常见问题的设计警告,例如并发动画过多、缺少 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 或 |
|
| 字符串或 |
|
| 沿曲线排列的文本;路径定义在 |
|
| 应用于所有子元素的共享属性(不支持嵌套组) |
|
| 实例化符号或通过 |
|
| 在完整圆周上放置 N 个副本 |
|
| 沿圆弧放置 N 个副本 |
|
| 在 M x 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[]
}滤镜预设
在 defs.filters 中定义后,可在任何元素上通过 filter: "url(#myId)" 引用:
{ "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 属性键:驼峰式 (strokeDashoffset) 或短横线式 (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"):from/to 路径必须具有相同的命令类型和数量。仅坐标可以不同。
字体
系统字体无需加载即可在任何地方使用:Arial, Helvetica, Courier New, Georgia, Verdana, monospace, sans-serif, serif。
也接受自定义字体系列。当渲染环境中存在该字体(加载了字体的网页、设计工具等)时,它们可以正常工作。
使用场景与兼容性
上下文 | CSS @keyframes | SMIL | 外部字体 | 交互 (onclick) |
GitHub README | ✅ | ✅ | ❌ | ❌ |
网页 | ✅ | ✅ | ❌ | ❌ |
网页内联 SVG | ✅ | ✅ | ✅ | ✅ |
设计工具导出 | ✅ | ✅ | ✅ | — |
静态文件查看器 | ✅ | ✅ | 取决于环境 | 取决于环境 |
故障排除
"MCP error -32602: Input validation error"
这意味着 MCP SDK 在到达处理程序之前拒绝了输入。这通常发生在第一次尝试时,重试即可解决。最常见的原因:
渐变类型拼写错误。 使用
"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。在透明画布上没有填充的形状是不可见的。检查坐标。在
800px宽的画布上,位于x: 2000的元素在屏幕外。如果使用
filter: "url(#myFilter)",请确保myFilter已在defs.filters中定义。
动画在 GitHub 上不工作
GitHub README 通过 <img> 标签渲染 SVG,该标签会剥离 JavaScript,但保留 CSS 和 SMIL。如果您的动画在本地有效但在 GitHub 上无效:
避免使用
<script>或事件处理程序 (onclick,onmouseover)。这些会被移除。外部字体不会加载。请坚持使用系统字体:
Arial,Courier New,Georgia,monospace,sans-serif。字体 CSS
@import被阻止。如果需要特定字体,请使用带有系统回退的内联<text>。
SVG 输出过大
如果 render_svg 返回关于文件大小(超过 50kb)的警告,可能是参数化曲线或图案组生成了过多的元素。减少参数化曲线的 steps 或图案组的 count。一个 cols: 50, rows: 50 的网格组会产生 2500 个元素,这会迅速增加文件大小。
技术栈
TypeScript + Node.js 18+
@modelcontextprotocol/sdk(MCP 服务器)zod(模式验证和 AI 类型引导)无外部 SVG 库,纯 XML 构建
Vitest (280 个测试)
许可证
MIT。由 arikusi 构建。
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