MCP server that turns AI into an SVG artist.
One rendering engine. AI decides everything.
Officially listed on the MCP Registry, Glama, LobeHub, and PulseMCP.
*纳克卡斯* 土耳其语中的“画家/艺术家”(旧)。
"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@关键帧+SMIL动画,无需JavaScript。
- 零外部存款。 没有云API,没有API密钥。在当地运行。
安装
克劳德桌面
添加到您的配置文件中:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Linux:
~/.config/Claude/claude_desktop_config.json - 窗户:
%APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"nakkas": {
"command": "npx",
"args": ["-y", "nakkas@latest"]
}
}
}克劳德代码(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提供了三种工具:
| 工具 | 目的 |
|---|---|
render_svg | 接受SVGConfig JSON,返回SVG字符串+设计分析警告 |
preview | 获取渲染内容,返回PNG图像进行视觉检查 |
save | 获取渲染内容,以SVG(文本)或PNG(光栅)格式保存到磁盘 |
预期的工作流程:渲染→ 预览→ 迭代→ save.这 save 工具与 render_svg 鼓励在保存前进行预览和优化。
这 save 工具
{ "content": "...", "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
}元素类型
| 类型 | 必填字段 | 备注 | |
|---|---|---|---|
rect | width, height | x, y 默认值0; rx/ry 用于圆角 | |
circle | r | cx, cy 默认值0 | |
ellipse | rx, ry | 独立的水平/垂直半径 | |
line | x1, y1, x2, y2 | ||
polyline | points | 开放路径: "10,20 50,80 90,20" | |
polygon | points | 自动闭合形状 | |
path | d | 完整SVG路径命令 | |
image | href, width, height | URL或 data:image/... 嵌入图像的URI | |
text | content | 字符串或 `(string \ | Tspan)[]` 阵列 |
textPath | pathId, text | 曲线后的文本;路径定义于 defs.paths | |
group | children | 共享属性应用于所有子项(无嵌套组) | |
use | href | 通过以下方式实例化符号或克隆元素 #id | |
radial-group | cx, cy, count, radius, child | 在一个完整的圆圈周围放置N个副本 | |
arc-group | cx, cy, radius, count, startAngle, endAngle, child | 沿圆弧放置N个副本 | |
grid-group | cols, rows, colSpacing, rowSpacing, child | 将副本放置在M乘N网格中 | |
scatter-group | width, height, count, seed, child | 将N个副本分散到种子随机位置 | |
path-group | waypoints, count, child | 沿折线均匀分布N个副本 | |
parametric | fn | 数学曲线: rose, heart, star, lissajous, spiral, superformula, epitrochoid, hypotrochoid, wave |
所有视觉元素(共享字段)
{
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" }| 预设 | 关键参数 | 效果 |
|---|---|---|
glow | stdDeviation, color | 柔和光晕 |
neon | stdDeviation, color | 强烈明亮的光芒 |
blur | stdDeviation | 高斯模糊 |
drop-shadow | stdDeviation, offsetX, offsetY, color | 投下阴影 |
glitch | stdDeviation | 湍流位移(动画) |
grayscale | value (0–1) | 去饱和 |
sepia | -- | 温暖的棕褐色调 |
invert | -- | 反转颜色 |
saturate | value | 提高/降低饱和度 |
hue-rotate | value (度) | 变换色调 |
chromatic-aberration | value (像素偏移,默认3) | RGB通道分割用于镜头失真外观 |
noise | value (不透明度0到1,默认值0.25) | 胶片颗粒和纹理叠加 |
outline | color, value (厚度,默认值2) | 元素周围的彩色轮廓 |
inner-shadow | color, stdDeviation, value (不透明度,默认值为0.5) | 元素内部的阴影 |
emboss | stdDeviation, value (强度,默认1.5) | 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)或烤肉串箱(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@关键帧 | SMIL | 外部字体 | 交互式(onclick) |
|---|---|---|---|---|
| GitHub自述 `` | ✅ | ✅ | ❌ | ❌ |
| 网页 `` | ✅ | ✅ | ❌ | ❌ |
| 网页内联SVG | ✅ | ✅ | ✅ | ✅ |
| 设计工具导出 | ✅ | ✅ | ✅ | — |
| 静态文件查看器 | ✅ | ✅ | 取决于 | 取决于 |
故障排除
“MCP错误-32602:输入验证错误”
这意味着MCP SDK在输入到达处理程序之前拒绝了输入。它通常发生在第一次尝试时,并在重试时起作用。最常见的触发因素:
- 渐变类型拼写错误。 使用
"linearGradient"或"radialGradient",不"linear"或"radial"这是最常见的错误。 - 关键帧偏移量为字符串。 写
0或100(数字)或"from"/"to".写作"0%"或"100%"将失败。 - 命名颜色。 只有十六进制值有效:
"#ff0000",不"red"不rgb()要么。 - 缺失
type关于元素。 每个元素对象都需要一个type现场。
如果您正在构建MCP客户端集成,并且一直看到这一点,那么问题可能在于您的客户端如何序列化参数。看 人类学/克劳德编码#29104 了解已知序列化怪癖的上下文。
预览显示空白或意外图像
预览工具在t=0时渲染静态快照。动画不会被捕获。您看到的是SVG在任何CSS或SMIL动画开始之前的初始状态。
如果图像完全空白:
- 检查你的元素是否
fill或stroke集。透明画布上没有填充的形状是不可见的。 - 检查坐标。一个元素在
x: 2000在A800px宽画布只是屏幕外的。 - 如果使用
filter: "url(#myFilter)",确保myFilter实际上是在defs.filters.
动画无法在GitHub上运行
GitHub README通过以下方式呈现SVG `` 标签,它剥离了JavaScript,但保留了CSS和SMIL。如果你的动画在本地运行,但不在GitHub上运行:
- 避免 `
或事件处理程序(onclick,onmouseover`).这些已被删除。 - 外部字体无法加载。坚持使用系统字体:
Arial,Courier New,Georgia,monospace,sans-serif. - 层叠样式表
@import因为字体被阻止。如果需要特定字体,请使用内联字体 `` 系统回退。
大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。由...建造 礼仪.
