Skip to guide

Spriteworks MCP

Agents can search the same approved artwork used by the Design site, compose bunnies, recolor logos and poses, and export files without a browser. The server also accepts agent-authored SVG geometry. Rendering uses the server's local artwork and needs no cloud generation service.

Start here

MCP runs locally. GitHub Pages hosts the website and agent instructions. No shared HTTPS endpoint is configured. Visiting this website does not connect an MCP server or grant an agent filesystem access. Configure the local server in your MCP client using the steps below.

The site and repository require the organization's GitHub access. An unauthenticated cloud crawler may see a sign-in page. Use an authenticated browser or an authorized local checkout. Site sign-in and an MCP endpoint's bearer token are separate credentials.

The site publishes llms.txt, mcp-guide.md, mcp-manifest.json, mcp-tools.json, mcp-capabilities.json, mcp-examples.json, and mcp-client-config.json. These are static documentation files. mcp-tools.json is generated from the real server's tool schemas at build time. After connecting, use the live tools/list and get_capabilities responses as the authority for that server version. The same guide and examples are available as spriteworks://guide and spriteworks://examples MCP resources.

Local connection

Use Node 22.22.1. Clone the repository with an authorized GitHub account, then install dependencies:

git clone https://github.com/autonomouscyberco/spriteworks.git
cd spriteworks
npm ci

If a checkout already exists, use it instead. The catalogs in dist/ are tracked; after editing artwork, run the repository's normal asset build. Python is not needed just to launch MCP and export from the existing catalog.

Configure your MCP client using client-config.example.json, replacing the two absolute paths. Launch node /absolute/path/to/spriteworks/tools/spriteworks-mcp.mjs directly. Using npm run mcp inside an MCP client's command may add npm text to the protocol stream.

After updating the checkout, restart or reconnect the MCP server in your client so it discovers newly added tools.

Refreshing artwork

Use the artwork intake guide to compare a fresh Bunnies export with the approved source. npm run intake:report produces a reviewable change report with explicit placeholder exclusions and affected fit contexts. Intake runs before the offline build and never changes the catalog automatically. Agents can also read the guide at spriteworks://intake.

The default output directory is output/mcp/ in this repository. Override it with --output-dir or SPRITEWORKS_OUTPUT_DIR. Each export gets its own UUID directory. Source artwork and existing exports are never overwritten. Files persist until the operator removes them; there is no automatic retention policy.

Agent workflow

  1. Call get_capabilities for formats, controls, palette references and limits.
  2. Call list_assets with a kind and search query, then inspect_asset for exact IDs, color roles and compatibility.
  3. Call export_asset for an individual asset or export_sprite_sheet for a grid. When a combined freeform layout is requested, the optional compose_image tool can place multiple assets on one canvas.
  4. Inspect the returned preview, dimensions, frame counts and print warnings. Check isError before claiming success.
  5. Use the returned local paths or MCP resource links. read_export reads large files in base64 chunks when a client cannot use resources.

Every export includes a reproducible JSON recipe and, by default, a PNG preview. Tool errors explain invalid IDs, incompatible pieces, unsupported formats or exceeded budgets. One rendering job runs at a time. Cancelling a tool request terminates its worker; a concurrent export receives a retryable busy error.

Tools

Tool Controls and result
get_capabilities No arguments. Returns formats, palette roles, reference swatches, features and limits.
list_assets Optional kind: logo, pose, animation, rig, part, anatomy, base. query: up to 160 characters. offset: zero-based, default 0. limit: 1-100, default 30. Follow nextOffset until null.
inspect_asset Required kind and exact id. Returns color roles, frame information and applicable body compatibility. Check available for static construction and liveRigFit for dressed motion.
export_asset Required asset; all sizing, style, animation and print controls below. Returns a new export ID, dimensions, files, resource links and optional PNG preview.
export_sprite_sheet Required assets; cell sizing, columns, gutters and margin controls below. Returns a new sheet export and atlas metadata in its recipe.
compose_image Optional. Required final canvas dimensions and layers. Combines independently positioned, sized, rotated and colored artwork into one still image. Use when a combined layout is requested.
read_export Required exportId and filename from the export result. Byte offset defaults to 0. length is 1-1,048,576, default 65,536. Returns base64, totalBytes, and nextOffset.

Logo example

{
  "asset": { "kind": "logo", "id": "fuzze-logo" },
  "format": "png",
  "name": "fuzze-cyan-banner",
  "canvas": {
    "width": 1200,
    "height": 400,
    "padding": { "top": 40, "right": 80, "bottom": 40, "left": 80 },
    "alignX": "left",
    "fit": "contain"
  },
  "style": { "color": "#03E7F3", "background": "transparent" }
}

Composition and animation

asset.kind supports logo, pose, animation, rig, bunny, and svg. A bunny accepts base, body, head, ears, leg, and parts. Discover their IDs first. Omit anatomy choices for the authored defaults; head, ears, and leg can be none where supported.

Use rig for a dressed pose, animation or sprite sheet. Its id is a discovered fitted motion ID, parts accepts up to nine reviewed item IDs with one per slot, and optional frame selects a still pose. Inspect each piece's liveRigFit first. Headwear and outfits that own their ears suppress a separate ear selection; the result records selected, active and suppressed items. Every library sequence has an authored.<motion ID> fitted track, for example authored.eatCarrot or authored.imposterFly. The hand or mouth stays occupied during authored food/computer use. Equipment follows hole clipping, reveals, dissolves and outlines; blank transition frames stay blank. Native reference tracks retain their original behavior. Monster and Zzz have dedicated moving fits even though their static construction cards use different bases. Pink placeholder cards have no fit.

Rig export shares the website's fitted layer order, limb support and palette rules. Every export records its fit revision and source frames. A stale fit pack fails explicitly. This exports reviewed poses; agents cannot invent new joint geometry or author new fits through this tool.

An animation accepts its clip ID and an optional zero-based frame for a still export. Omit frame for an animated export. fps supports 1 through 60 and playback supports loop or ping-pong. All frames share a fitting envelope to prevent recentering during playback. WebP may combine duplicate frames while preserving their duration; frameCount reports encoded frames and sourceFrameCount reports input frames.

canvas supports arbitrary rectangular dimensions, pixel padding per side, left/center/right and top/center/bottom alignment, contain/cover/stretch fitting, and content/canvas bounds. Omitted dimensions preserve the artwork aspect ratio with a default longest edge of 512 pixels. Bunny content fitting preserves the shared body anchor and authored headroom. Logo and custom-SVG bounds follow their authored canvas.

style.colors overrides named semantic roles, while style.color changes the primary body/logo color. Colors are six-digit RGB hex values. Unknown roles fail explicitly. Backgrounds are transparent or solid RGB. Mirroring preserves padding/alignment. pixelated defaults on for bunny art and off for logos/custom SVG.

Every export control

Field Values / default
asset logo or pose with id; animation with id and optional zero-based frame; rig with motion id, fitted parts and optional frame; bunny with optional base, body, head, ears, leg, parts; or svg with a complete svg string.
asset.parts Up to 32 part IDs for a static bunny, or nine fitted IDs for a rig with one per slot. Static base uses a base ID; body, ears and leg use compatible anatomy IDs. Omit these for defaults. head is original or none; ears and leg also accept original or none.
format Exact format identifiers are in the table below. Default png.
canvas.width, canvas.height Integer pixels, 1-8192. Omit one to derive it from the artwork aspect ratio. Omit both for a 512-pixel longest edge.
canvas.padding Pixels, 0-4096, default 0. One number or an object containing all four of top, right, bottom, left. Must leave room for artwork.
canvas.fit contain (default) keeps all art; cover fills and crops; stretch changes its proportions.
canvas.alignX, canvas.alignY left / center / right; top / center / bottom. Both default center.
canvas.bounds content (default) or canvas. Bunny content fitting retains its body anchor/headroom; logo/custom SVG use their authored canvas.
style.color Primary color as #RRGGBB. Omitted: authored palette.
style.colors Map of supported semantic roles to #RRGGBB. Overrides style.color for a matching role. For custom SVG, add data-role="body" or another catalog role to geometry to recolor it. Unmarked SVG geometry keeps its fill.
style.background transparent (default) or #RRGGBB. JPEG needs a solid color.
style.mirror Boolean, default false. Horizontal reflection.
style.pixelated Boolean. Defaults true for bunny art, false for logos/custom SVG. Controls SVG crisp-edge rendering.
fps Number from 1-60, default 8. Applies to animation timing.
playback loop (default) or ping-pong. Animated exports repeat indefinitely.
quality Integer 1-100, default 95. Applies to JPG, WebP, AVIF and animated WebP.
dpi Integer 36-1200, default 96. Raster density metadata and default print sizing.
printSizeMm Physical longest edge, 1-1000 mm, for PDF/EPS. Omitted: pixel dimensions divided by DPI, converted to mm.
printMode cmyk (default) or spot. Spot output requires documented color references.
allowEstimatedPrintColors Boolean, default true. Set false to reject unverified print-color estimates.
name Filename stem, 1-64 letters, numbers, hyphens or underscores; first character alphanumeric. Default asset. No path or extension.
includePreview Boolean, default true. Adds an inline PNG of the first frame, up to 256 pixels per side. The preview is not the exported file.

Optional freeform compositions

compose_image creates a single still image from multiple assets, for example a banner with a logo and several bunnies. It is an optional tool: use it when the user wants a combined layout. Individual assets and grids continue to use export_asset and export_sprite_sheet directly. There is no extra composition step in those workflows and no separate canvas-editor page to open.

Field Values / default
canvas.width, canvas.height Required final image dimensions, integer pixels, 1-8192 each, up to 16,777,216 total pixels.
canvas.background transparent (default) or #RRGGBB. JPEG requires a solid final background.
layers 1-64 layers, drawn in array order from bottom to top. Later layers cover earlier layers.
layers[].asset A logo, pose, built bunny, fitted rig or custom SVG using the same asset fields as export_asset. Animation and rig selections must include an explicit zero-based frame; composition exports are still images.
layers[].x, layers[].y Position of the layer canvas's top-left corner before rotation, in final-canvas pixels. Default 0; range -8192 to 8192. Negative positions are allowed.
layers[].canvas The existing canvas controls: width, height, padding, contain/cover/stretch, alignment and bounds. These size and fit that layer before rotation. Omit size for a 512-pixel longest edge, or supply one dimension to retain its aspect ratio.
layers[].style Independent primary/semantic colors, mirroring, crisp-edge rendering and optional background for each layer. Default background is transparent.
layers[].rotation Clockwise degrees around the center of the layer canvas, -360 to 360, default 0. Rotation includes the layer's background and padding.
layers[].opacity 0-1, default 1, applied to the entire layer as a group.
format png (default), svg, jpg, webp, avif, tiff, pdf or eps.
name, quality, dpi, printSizeMm, printMode, allowEstimatedPrintColors, includePreview Same controls as single exports. Default name composition. EPS is process CMYK only; use PDF for Pantone spot inks or partial opacity.

Artwork outside the final canvas is clipped. Mirroring preserves the layer's padding and alignment; the fitted layer is then rotated and positioned. The sum of all layer-canvas areas is limited to 67,108,864 pixels, and assembled layer SVG geometry is limited to 8 MiB. Custom SVG limits still apply to each custom layer. Inputs reference the approved local catalog or inline SVG geometry; image URLs, local file imports, raster photos, text/fonts and animated compositions are not supported. Text can be supplied as outlined SVG paths.

The result uses the usual export ID, files, resource links and PNG preview, plus layerCount. Its recipe.json records full inputs, resolved layer dimensions, bunny recipes and catalog revisions. Reorder the layers array to change stacking. A complete 1920 by 1080 banner example appears in the runnable examples and spriteworks://examples.

Sprite sheet controls

Field Values / default
assets 1-128 asset selections using the same asset shapes above. Up to 256 frames after expansion.
format zip (default), png, or svg. ZIP contains <name>.png, atlas.json and recipe.json.
cell Same fields as canvas: dimensions, padding, fitting, alignment and bounds. Default 128 by 128 pixels. If a cell dimension is omitted it defaults to 128.
columns Integer 1-32, default 8. The requested count is preserved, including empty trailing cells.
gap Integer 0-1024 pixels between cells, default 0.
margin Integer 0-1024 pixels around the sheet, default 0.
expandAnimations Boolean, default true. Expands selected clips into frames. False uses only the first selected frame of each clip.
fps 1-60, default 8; recorded as atlas timing. Does not animate the sheet.
style, name, includePreview Same controls as single exports; style applies to every cell. Default name sprites.

Sheet width = 2 * margin + columns * cell.width + (columns - 1) * gap. Height uses ceil(frameCount / columns) rows. The entire sheet must fit the same canvas budget. To use different colors per cell, export individual assets or author a custom SVG; the sheet has one shared style.

Formats and limits

Output Formats
Still assets svg, png, jpg, webp, avif, tiff, pdf, eps
Animation gif, apng, animated-webp, animated-svg
Sprite sheets svg, png, zip with PNG + atlas.json + recipe.json
Optional compositions Same still formats; PDF supports named spot inks, EPS uses process CMYK

Getting the actual files

The text/structured export result contains id, width, height, frameCount and a files array. Each file has name, server-local path, MIME type, and a spriteworks://exports/... URI. The main file also has byte length and a SHA-256 checksum. recipe.json records the complete inputs and source revisions.

For a local client on the same machine, copy or attach the returned file. For a remote client, the returned path belongs to the server, not your computer: call MCP resources/read with the returned URI. If the client lacks resource reads or the file is over 4 MiB, call read_export using the returned export ID and exact filename. Start at offset 0, decode each base64 chunk to bytes, append the bytes in order, and use nextOffset until it is null. Do not concatenate base64 strings. Verify the completed byte count/checksum, save locally, and attach the result to the user. A spriteworks:// URI is not a public browser download URL.

Open the preview or output to check it before delivery. For animation, inspect sourceFrameCount, encoded frameCount and durationMs. For sheets, inspect atlas.json inside the ZIP or the atlas in the outer recipe. A tool error is a failed request, not a file.

Scope and common failures

Some browsers may expose the site's separate read_avatar_recipe and configure_avatar_recipe WebMCP tools. They depend on browser support and configure the editor only; they do not save/download exports. The server tools above provide the documented file export workflow.

HTTP and HTTPS deployment

GitHub Pages serves static files and cannot run this Node process. Keep the Design website there. A shared MCP endpoint needs a running host or container with persistent export storage and TLS, such as an existing server behind an HTTPS reverse proxy. No shared endpoint is currently published; https://your-host.example/mcp below is a placeholder, not a working server. Do not use the Pages website URL as an MCP endpoint.

Set a random secret of at least 32 characters in SPRITEWORKS_MCP_TOKEN, then run:

node tools/spriteworks-mcp.mjs --transport http --host 127.0.0.1 --port 5180 --public-url https://your-host.example/mcp

Configure the client with endpoint https://your-host.example/mcp and header Authorization: Bearer <your token>. Store the secret in the host/client's secret configuration, never in Git. HTTP mode refuses to start without it. /healthz reports readiness without exposing assets. Requests validate Host and Origin. The endpoint supports modern MCP and the 2025 stateless Streamable HTTP compatibility flow.

The Node process serves HTTP. The reverse proxy must terminate HTTPS, preserve the public Host header, forward /mcp, allow responses up to the export-resource size, and permit tool calls to run for at least 120 seconds. A token grants access to this instance's complete catalog and exports; use separate instances/output volumes/tokens for separate trust groups. This is configured bearer authentication, not a multi-user OAuth service.

For container hosts, build from the repository root using docker build -f mcp/Dockerfile -t spriteworks-mcp .. Mount persistent writable storage at /data, supply the token through the platform's secret manager, and pass --public-url https://your-host.example/mcp as container arguments. The image keeps the rendering process unprivileged. No hosted service, DNS, certificate or public access is provisioned by these files.

Validation

npm run typecheck includes the MCP sources. npm test includes actual stdio and authenticated HTTP client exchanges, artifact/resource reads, all advertised output formats, geometry/color/padding checks, animation timing, atlas coordinates, invalid-input rejection and worker cancellation. These checks do not require a browser or cloud credentials.

Live fits and reusable layouts

list_assets and inspect_asset include liveRigFit for parts and anatomy. A non-null entry identifies a reviewed preview/export fit, its slot and fitted outfit contexts. The app independently selects which items have achievement unlocks. A null entry still allows normal static composition when the asset is compatible with the selected body. The Fitted poses page shows and exports those appearances. Action fits previews combat, carrot breaks, coffee sips, magnifier inspection and laptop use. Select rig for dressed MCP exports, or animation for an authored clip.

The runnable composition examples include a square profile card, a wide header and a multi-character banner. These are optional, editable JSON recipes. Copy a recipe, replace the asset IDs and colors, adjust canvas dimensions and layer positions together, then call compose_image. Each export also saves its exact recipe.json for reuse.

Client configuration

Replace both absolute paths for the machine running your MCP client. If Node is not on that client's PATH, use its absolute executable path as command. This is the common mcpServers JSON shape; clients with other configuration formats need the same command and arguments.

{
  "mcpServers": {
    "spriteworks": {
      "command": "node",
      "args": [
        "/absolute/path/to/spriteworks/tools/spriteworks-mcp.mjs",
        "--output-dir",
        "/absolute/path/to/generated-assets"
      ]
    }
  }
}

Runnable examples

These are MCP tool calls, not HTTP request bodies. Discover and inspect the selected IDs first. Each example is exercised by the documentation integration test.

Dressed astronaut walking animation

{
  "name": "export_asset",
  "arguments": {
    "asset": {
      "kind": "rig",
      "id": "walk",
      "parts": [
        "clothes-15-astronaut-suit",
        "headwear-18-astronaut-helmet-1",
        "props-36-football"
      ]
    },
    "format": "apng",
    "name": "astronaut-walk",
    "canvas": {
      "width": 160,
      "height": 96,
      "padding": 4
    },
    "style": {
      "color": "#70F149",
      "background": "transparent"
    },
    "fps": 10
  }
}

Lab coat walking sprite sheet

{
  "name": "export_sprite_sheet",
  "arguments": {
    "assets": [
      {
        "kind": "rig",
        "id": "walk",
        "parts": [
          "clothes-13-lab-coat",
          "headwear-17-top-hat",
          "props-07-briefcase"
        ]
      }
    ],
    "format": "zip",
    "name": "lab-coat-walk",
    "cell": {
      "width": 96,
      "height": 96,
      "padding": 4
    },
    "columns": 4,
    "gap": 4,
    "margin": 8
  }
}

Cyan logo with asymmetric spacing

{
  "name": "export_asset",
  "arguments": {
    "asset": {
      "kind": "logo",
      "id": "fuzze-logo"
    },
    "format": "png",
    "name": "cyan-logo",
    "canvas": {
      "width": 1200,
      "height": 400,
      "padding": {
        "top": 40,
        "right": 80,
        "bottom": 40,
        "left": 80
      },
      "alignX": "left",
      "fit": "contain"
    },
    "style": {
      "color": "#03E7F3",
      "background": "transparent"
    }
  }
}

Purple bunny with a pirate hat

{
  "name": "export_asset",
  "arguments": {
    "asset": {
      "kind": "bunny",
      "base": "original",
      "parts": [
        "headwear-08-pirate-hat"
      ]
    },
    "format": "svg",
    "name": "pirate-bunny",
    "canvas": {
      "width": 512,
      "height": 512,
      "padding": 24
    },
    "style": {
      "color": "#A365FF",
      "mirror": true
    }
  }
}

Still pose on a solid background

{
  "name": "export_asset",
  "arguments": {
    "asset": {
      "kind": "pose",
      "id": "hop-jump-015"
    },
    "format": "jpg",
    "name": "jump-pose",
    "canvas": {
      "width": 320,
      "height": 240,
      "padding": 12
    },
    "style": {
      "color": "#70F149",
      "background": "#FFFFFF"
    },
    "quality": 90,
    "dpi": 300
  }
}

Walking animation with ping-pong playback

{
  "name": "export_asset",
  "arguments": {
    "asset": {
      "kind": "animation",
      "id": "walk"
    },
    "format": "gif",
    "name": "walking-bunny",
    "canvas": {
      "width": 192,
      "height": 144,
      "padding": 8
    },
    "style": {
      "color": "#03E7F3"
    },
    "fps": 12,
    "playback": "ping-pong"
  }
}

Walking sprite atlas with cell padding and gutters

{
  "name": "export_sprite_sheet",
  "arguments": {
    "assets": [
      {
        "kind": "animation",
        "id": "walk"
      }
    ],
    "format": "zip",
    "name": "walk-atlas",
    "cell": {
      "width": 96,
      "height": 96,
      "padding": 6
    },
    "columns": 4,
    "gap": 4,
    "margin": 8,
    "fps": 12
  }
}

Agent-authored vector geometry

{
  "name": "export_asset",
  "arguments": {
    "asset": {
      "kind": "svg",
      "svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 100 100\"><rect x=\"10\" y=\"10\" width=\"80\" height=\"80\" rx=\"12\" data-role=\"body\" fill=\"#70F149\"/></svg>"
    },
    "format": "webp",
    "name": "custom-mark",
    "canvas": {
      "width": 256,
      "height": 256,
      "padding": 16
    },
    "style": {
      "colors": {
        "body": "#FF5FE4"
      }
    }
  }
}

Optional composition: a logo and three bunnies on one banner

{
  "name": "compose_image",
  "arguments": {
    "name": "bunny-banner",
    "format": "png",
    "canvas": {
      "width": 1920,
      "height": 1080,
      "background": "#101010"
    },
    "layers": [
      {
        "asset": {
          "kind": "logo",
          "id": "fuzze-logo"
        },
        "x": 120,
        "y": 90,
        "canvas": {
          "width": 650,
          "height": 180,
          "alignX": "left"
        },
        "style": {
          "color": "#70F149"
        }
      },
      {
        "asset": {
          "kind": "bunny",
          "base": "original",
          "parts": [
            "headwear-08-pirate-hat"
          ]
        },
        "x": 130,
        "y": 375,
        "canvas": {
          "width": 440,
          "height": 570,
          "padding": 16
        },
        "style": {
          "color": "#A365FF"
        },
        "rotation": -6
      },
      {
        "asset": {
          "kind": "animation",
          "id": "walk",
          "frame": 2
        },
        "x": 740,
        "y": 405,
        "canvas": {
          "width": 440,
          "height": 540,
          "padding": 16
        },
        "style": {
          "color": "#03E7F3"
        }
      },
      {
        "asset": {
          "kind": "bunny",
          "base": "original"
        },
        "x": 1350,
        "y": 375,
        "canvas": {
          "width": 440,
          "height": 570,
          "padding": 16
        },
        "style": {
          "color": "#70F149",
          "mirror": true
        },
        "rotation": 6,
        "opacity": 0.9
      }
    ]
  }
}

Optional reusable layout: square profile card

{
  "name": "compose_image",
  "arguments": {
    "name": "profile-card",
    "format": "png",
    "canvas": {
      "width": 1080,
      "height": 1080,
      "background": "#000000"
    },
    "layers": [
      {
        "asset": {
          "kind": "logo",
          "id": "fuzze-logo"
        },
        "x": 80,
        "y": 64,
        "canvas": {
          "width": 480,
          "height": 140,
          "alignX": "left"
        },
        "style": {
          "color": "#70F149"
        }
      },
      {
        "asset": {
          "kind": "bunny",
          "base": "original",
          "parts": [
            "headwear-08-pirate-hat"
          ]
        },
        "x": 170,
        "y": 250,
        "canvas": {
          "width": 740,
          "height": 740,
          "padding": 24
        },
        "style": {
          "color": "#A365FF"
        }
      }
    ]
  }
}

Optional reusable layout: wide header

{
  "name": "compose_image",
  "arguments": {
    "name": "wide-header",
    "format": "png",
    "canvas": {
      "width": 1536,
      "height": 512,
      "background": "#101010"
    },
    "layers": [
      {
        "asset": {
          "kind": "logo",
          "id": "fuzze-logo"
        },
        "x": 80,
        "y": 170,
        "canvas": {
          "width": 700,
          "height": 180,
          "alignX": "left"
        },
        "style": {
          "color": "#03E7F3"
        }
      },
      {
        "asset": {
          "kind": "bunny",
          "base": "original"
        },
        "x": 1020,
        "y": 48,
        "canvas": {
          "width": 420,
          "height": 416,
          "padding": 16
        },
        "style": {
          "color": "#70F149",
          "mirror": true
        }
      }
    ]
  }
}