MCP server that turns AI into an SVG artist. One rendering engine, AI decides everything.
Nakkas provides 3 well-structured tools with detailed descriptions and comprehensive input schemas. render_svg has exceptional documentation (~2000 chars) covering workflow, element types, animations, and design guidance, far exceeding the 194-char baseline for tool descriptions. All tools have clear parameter descriptions and proper schema definitions with types. However, there are gaps in output schema documentation, error handling guidance, and response field naming consistency. The render_svg tool exemplifies strong documentation but the preview and save tools are minimal. STDIO-only transport limits remote accessibility but does not affect definition quality scoring.
Render artifact or SVG content to a base64 PNG for visual inspection at specified width.
Render animated SVG from JSON config. AI controls all design parameters. **Workflow:** render_svg returns a PNG preview of the result plus an artifact id — critique the image, revise the config, render again. Iterate at least 3 times before finalizing. The SVG text stays on the server: pass the artifact id to save (and to preview for a different width). **output options (response shape, not content):** {"svg":false,"preview":true,"previewWidth":800,"minify":false,"frames":4} — all optional. minify:true collapses whitespace in the stored/saved SVG. frames:N (2-10) replaces the static preview with one filmstrip image sampling the CSS animations at N times — use it to verify motion (rotation direction, timing, easing) since a single preview only shows t=0. SMIL is not sampled. **Element types:** rect, circle, ellipse, line, polyline, polygon, path, image, text, textPath, group, use, radial-group, arc-group, grid-group, scatter-group, path-group, parametric **Pattern groups** (use for repetitive designs): radial-group (circular: cx, cy, radius, count), arc-group (arc: cx, cy, radius, count, startAngle, endAngle), grid-group (matrix: cols, rows, colSpacing, rowSpacing), scatter-group (random: width, height, count, seed), path-group (along polyline: waypoints, count). Each takes ONE "child" element. The child is drawn at the local origin and, with rotateChildren true (the default), rotates so local +x points outward from the center: draw spokes, rays and petals long along the x axis, never the y axis, or they render as a chord ring. **Parametric curves** (fn field): rose, heart, lissajous, spiral, star, superformula, epitrochoid, hypotrochoid, wave. Size via "scale" field. Server computes coordinates. **defs:** gradients (linear/radial, SMIL animated stops), filters (presets: glow, neon, blur, drop-shadow, glitch, chromatic-aberration, noise, outline, inner-shadow, emboss + 5 more), clipPaths, masks, patterns (tile fills), markers (arrowheads: triangle, arrow, circle, square, diamond, bar; set markerStart/markerEnd:"id" on line/polyline/path, scales with strokeWidth). **Animations:** CSS @keyframes via animations array. Set cssClass on element matching animation name. For transforms add transformBox="fill-box" transformOrigin="center". SMIL via smilAnimations on elements (animate, animateTransform, animateMotion). **Design guide (what makes output look good):** Pick one spacing unit (e.g. 8) and use multiples of it for every gap and margin; keep content clear of the canvas edges by at least 5% of the smaller dimension (the bbox audit reports overflow in px). Use at most 3 font sizes per design with clear jumps (e.g. 12/16/24). Body-size text needs 4.5:1 contrast against its background, 3:1 from 24px up (the contrast audit checks plain hex pairs). Text ink boxes are measured after every render; escaping or overlapping text comes back as a named design note. Motion: ease-out for entrances, ease-in-out for back-and-forth loops, linear only for continuous rotation or travel; 0.8-3s durations read well for UI-scale loops. **Critical format rules:** - Gradient type must be "linearGradient" or "radialGradient" (not "linear"/"radial"). Each needs id, stops (array with offset 0-1, color). - Filter type must be "preset" with a "preset" field: {"type":"preset","id":"myGlow","preset":"glow","stdDeviation":8,"color":"#ff00ff"} - Keyframe offset: use "from"/"to" or percentage number 0-100 (not "0%"/"100%"). - Gradient stop and filter colors: hex only (#rrggbb or #rrggbbaa). Element fill/stroke accept '#rrggbb', 'none', or 'url(#id)' (hex is safest). - Every element needs "type" field. circle needs r, rect needs width+height, path needs d. **Field names that differ from raw SVG:** - text: string goes in "content" (not "text"): {"type":"text","x":100,"y":50,"content":"Hello","fontSize":24,"textAnchor":"middle"} - textPath: {"type":"textPath","pathId":"idFromDefsPaths","text":"..."} — here the field IS "text". - group: {"type":"group","children":[...]} — children are shapes/text/use only, no nested groups. - Pattern groups take ONE "child" element drawn at local origin (child uses cx=0/cy=0); set rotateChildren:false to keep text upright. **Output:** Pure SVG XML. No JavaScript. CSS @keyframes + SMIL only.
preview and save tool descriptions are minimal (~60 chars each) vs. production baseline of 194 chars. 'Render artifact or SVG content to a base64 PNG' omits when/why to use it, expected output format, or error cases.
Output schemas are not documented for any tool. The render_svg tool returns 'SVG string + design analysis' but the actual response structure (field names, types, pagination, error format) is not specified in the schema or description.
Error handling lacks recovery guidance. No tool descriptions explain what happens on invalid input, missing artifacts, or file write failures. LLMs have no actionable error classification (retryable vs. user-fixable vs. fatal).
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | C | 64 | 2026-07-28+ | v2 |
Save rendered SVG to disk in the requested format (svg, png, or jpg).
The preview tool accepts 'artifact' and 'content' as alternatives but the parameter descriptions do not state they are mutually exclusive or which is preferred. LLMs may pass both, causing ambiguous behavior.
The save tool's 'filename' parameter lacks constraints. No description specifies format (extension auto-added?), length limits, or forbidden characters. LLMs may pass invalid filenames.
preview tool does not document what width values are valid (minimum, maximum, defaults). Numeric parameters without bounds invite absurd values (1px, 100000px).