voidless-mcp 1.6.3 → 1.6.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +1 -1
  2. package/package.json +1 -1
  3. package/tools.js +33 -9
package/README.md CHANGED
@@ -74,7 +74,7 @@ claude mcp add voidless -e VOIDLESS_API_KEY=void_... -- npx -y voidless-mcp
74
74
 
75
75
  | Tool | What it does |
76
76
  | --- | --- |
77
- | `generate_image` | Sprite, character, portrait, prop, tileset, UI piece or artwork in a chosen model, style, palette, size and perspective |
77
+ | `generate_image` | Sprite, character, portrait, prop, tileset, UI piece or artwork in a chosen model, style, palette, size and perspective; artwork can be 16:9 for backdrops |
78
78
  | `edit_image` | Change an image with an instruction; the edit is added as a new frame |
79
79
  | `rotate_sprite` | An 8-way set (front, back, sides, diagonals) in one pass |
80
80
  | `extract_parts` | Split a character into body parts for rigging |
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "voidless-mcp",
3
3
  "mcpName": "dev.voidless/voidless",
4
- "version": "1.6.3",
4
+ "version": "1.6.7",
5
5
  "description": "MCP server for Voidless: generate game sprites, animations, sound, music, video and 3D models",
6
6
  "license": "MIT",
7
7
  "author": "Voidless Dev Inc. <contact@voidless.dev>",
package/tools.js CHANGED
@@ -25,7 +25,7 @@ import { Agent, setGlobalDispatcher } from "undici";
25
25
  // server does.
26
26
  setGlobalDispatcher(new Agent({ headersTimeout: 0, bodyTimeout: 0, connectTimeout: 30_000 }));
27
27
 
28
- export const VERSION = "1.6.3";
28
+ export const VERSION = "1.6.7";
29
29
  const BASE_URL = process.env.VOIDLESS_API_URL || "https://api.voidless.dev";
30
30
  const CDN_URL = "https://cdn.voidless.dev";
31
31
  // Where asset links point. Results link to the asset's page in the app rather than to raw GIFs: the
@@ -288,7 +288,10 @@ export function createVoidlessServer(API_KEY) {
288
288
  "(the gallery displays it) and let them decide. Do not call a generation tool again to try for a better result, " +
289
289
  "to fix a detail, or because the result is not exactly what you pictured — ask the user first, saying what it " +
290
290
  "would cost. Re-run only on a clear failure the tool reports (an error), or when the user asks. " +
291
- "For a character that will be animated, generate it in the 'idle' pose; 'tpose' is only for rigging.";
291
+ "For a character that will be animated, generate it in the 'idle' pose; 'tpose' is only for rigging. " +
292
+ "To use Voidless images inside HTML, a game or any code you write (artifacts and code sandboxes often cannot " +
293
+ "download from voidless.dev), call get_image_data: it returns the image, or an animation as a sprite strip, as a " +
294
+ "data URI you can paste in. Do not ask the user to download and attach files.";
292
295
  const server = new McpServer({ name: "voidless", version: VERSION }, { instructions: INSTRUCTIONS });
293
296
 
294
297
  // Tool annotations (MCP ToolAnnotations). Generation tools create something new in the caller's
@@ -600,7 +603,7 @@ export function createVoidlessServer(API_KEY) {
600
603
  "asset TYPE, output SIZE and PERSPECTIVE; for characters also facing/pose/bodyType. Use the default model " +
601
604
  "(flux2-klein, 1 credit) unless the user names another. Costs by model: flux2-klein 1, flux-juggernaut 1, " +
602
605
  "seedream-5-flash 2, gpt-image-2.5 5, retro-diffusion 10, nano-banana-2 15 credits (a reference image makes it " +
603
- "5 and uses flux2-klein). Call it once per request and " +
606
+ "2 and uses flux2-klein). Call it once per request and " +
604
607
  "show the result; ask the user before generating again (each call spends credits).",
605
608
  {
606
609
  prompt: z.string().max(300).describe("The subject only (max 300 chars). Put style/colour in the style/palette fields."),
@@ -612,7 +615,8 @@ export function createVoidlessServer(API_KEY) {
612
615
  .enum(["object", "character", "character portrait", "artwork", "tileset", "ui"])
613
616
  .describe(
614
617
  "'character' = full-body sprite (uses facing/pose/bodyType); 'character portrait' = headshot; 'object' = props " +
615
- "and items; 'artwork' = scenes/backgrounds; 'tileset' = map tiles; 'ui' = interface pieces (see uiMode)."
618
+ "and items; 'artwork' = scenes/backgrounds; 'tileset' = a terrain tile sheet (always GPT-Image, see " +
619
+ "tilesetKind; below 512 it is drawn at 512 and pixelated); 'ui' = interface pieces (see uiMode)."
616
620
  ),
617
621
  dimension: z.enum(["2d", "top down", "isometric"]).default("2d").describe("'2d' = side view, 'top down' = overhead, 'isometric' = 2.5D"),
618
622
  size: z
@@ -641,6 +645,19 @@ export function createVoidlessServer(API_KEY) {
641
645
  "T-pose (e.g. to rig the character in the skeleton editor)."
642
646
  ),
643
647
  bodyType: z.enum(["humanoid", "quadruped"]).default("humanoid").describe("Characters: body plan"),
648
+ tilesetKind: z
649
+ .enum(["platformer", "blob17", "wang"])
650
+ .optional()
651
+ .describe(
652
+ "type 'tileset' only: 'platformer' = side-view 3x3 ground sheet (default for 2d); 'wang' = top-down two-terrain " +
653
+ "4x5 auto-tile sheet in the free Tileset Generator's layout (default for top down; name both terrains, e.g. " +
654
+ "'a cobblestone path in grass'), every edge matched so any arrangement tiles seamlessly; 'blob17' = top-down " +
655
+ "17-piece sheet of one terrain on transparent. Top-down sheets have 256 px tiles; size 32/64/128 returns pixel tiles"
656
+ ),
657
+ aspect: z
658
+ .enum(["1:1", "16:9"])
659
+ .default("1:1")
660
+ .describe("type 'artwork' only: '16:9' for a backdrop, scene or game background (1344x756 at 1024, 672x378 at 512). Everything that is not artwork is always 1:1"),
644
661
  uiMode: z
645
662
  .enum(["graphic", "title", "text"])
646
663
  .default("graphic")
@@ -650,8 +667,13 @@ export function createVoidlessServer(API_KEY) {
650
667
  styleImage: z.string().default("").describe("Optional raw base64 image whose art style to copy"),
651
668
  },
652
669
  writeTool("Generate image"),
653
- tool(async ({ facing, pose, bodyType, palette, uiMode, ...rest }) => {
654
- const body = { ...rest, palette: [], options: { facing, pose, bodyType, palette, mode: uiMode } };
670
+ tool(async ({ facing, pose, bodyType, palette, uiMode, tilesetKind, aspect, ...rest }) => {
671
+ const wide = rest.type === "artwork" && aspect === "16:9" ? "16:9" : "1:1";
672
+ const tileset = rest.type === "tileset";
673
+ // Tilesets are GPT-Image only (the server enforces it too); the kind rides in options.mode.
674
+ if (tileset) rest.model = "gpt-image-2.5";
675
+ const mode = tileset ? tilesetKind || "" : uiMode;
676
+ const body = { ...rest, palette: [], options: { facing, pose, bodyType, palette, mode, aspect: wide } };
655
677
  return assetResult(await apiPost("/generate/image", body), "Image");
656
678
  })
657
679
  );
@@ -666,7 +688,7 @@ export function createVoidlessServer(API_KEY) {
666
688
  referenceFile,
667
689
  frameId,
668
690
  images: z.array(z.string()).max(4).default([]).describe("Optional extra reference images: image keys from get_asset or https URLs"),
669
- remove_bg: z.boolean().default(false).describe("Remove the background from the result"),
691
+ remove_bg: z.boolean().default(true).describe("Remove the background from the result, as the app's editor does. Set false for artwork or a scene that should keep its background"),
670
692
  },
671
693
  writeTool("Edit image"),
672
694
  // Always the app's own editor, the same one as the editor's "Edit this image" box.
@@ -786,7 +808,9 @@ export function createVoidlessServer(API_KEY) {
786
808
  "was drawn facing the camera), add {assetId, base:true} as 'down'. If it already has 'down' (a side-view " +
787
809
  "sprite), use only the rotation's own images: the base is the side view, not the front. For topdown-idle " +
788
810
  "pick only the 4 cardinals (down, right, up, left).\n" +
789
- "Without a preset, describe the actions in the prompt ('idle, run, jump') for up to 6 custom clips. " +
811
+ "Without a preset, list the actions in the prompt for up to 6 custom clips, one clip each: " +
812
+ "'name: description' separated by semicolons names each clip (e.g. 'attack-2: an overhead slash; block: raise " +
813
+ "the sword to guard'); for one image a plain 'idle, run, jump' also works. Every image gets every action. " +
790
814
  "Cost: 100 credits per pass (200 for 1024px sprites, which run in 4K); a pass holds up to 6 clips. On an " +
791
815
  "8-way rotation set the left, up-left and down-left clips are mirrored from the right-side ones (the " +
792
816
  "rotation's left side is a mirror already), so an 8-way set is ONE pass; set flipFacings false to animate " +
@@ -797,7 +821,7 @@ export function createVoidlessServer(API_KEY) {
797
821
  .enum(["platformer-character", "topdown-walk", "topdown-run", "topdown-dash", "topdown-attack", "topdown-idle"])
798
822
  .optional()
799
823
  .describe("Named set of actions (see get_animation_presets)"),
800
- prompt: z.string().default("").describe("Without a preset: the actions to make. With one: optional extra direction for every clip"),
824
+ prompt: z.string().default("").describe("Without a preset: the actions to make, as 'name: description' separated by semicolons. With one: optional extra direction for every clip"),
801
825
  holdFacing: z.boolean().default(false).describe("End every clip on the frame it started from, so directional loops do not drift"),
802
826
  flipFacings: z.boolean().default(true).describe("On an 8-way rotation set, mirror the left-side clips from the right-side ones instead of animating them (half the price). One-sided details swap sides, as on the rotation images"),
803
827
  autoFlip: z.boolean().default(false).describe("After the run, mirror every right-side clip on the asset that has no left twin (animate only the right-facing turns, get all eight). Free"),