@iborymagic/aseprite-mcp 0.1.0 → 0.2.0
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.
- package/README.md +24 -7
- package/build/aseprite/env.js +3 -2
- package/build/aseprite/tools.js +145 -0
- package/build/index.js +31 -13
- package/build/lua/templates.js +60 -0
- package/build/lua/tools.js +93 -0
- package/package.json +11 -6
package/README.md
CHANGED
|
@@ -1,9 +1,32 @@
|
|
|
1
1
|
# Aseprite-MCP
|
|
2
2
|
This server automates Aseprite workflows using the Model Context Protocol (MCP).
|
|
3
|
-
It enables AI, chat assistants, and automation pipelines to directly execute Aseprite tasks such as sprite sheet export, frame extraction, and metadata output.
|
|
3
|
+
It enables AI, chat assistants, and automation pipelines to directly execute Aseprite tasks such as sprite sheet export, frame extraction, and metadata output.
|
|
4
|
+
|
|
4
5
|
*Lua-based automation and high-level sprite/tile generation features are not included yet.
|
|
5
6
|
*Aseprite must be installed in order to use this MCP server.
|
|
6
7
|
|
|
8
|
+
## Features Overview
|
|
9
|
+
### V1 - Export/Utility
|
|
10
|
+
Supports fundamental Aseprite export workflow:
|
|
11
|
+
- `aseprite_check_environment`: Checks Aseprite installation status, executable path, and version
|
|
12
|
+
- `aseprite_export_sheet`: Exports a sprite sheet as PNG + JSON
|
|
13
|
+
- `aseprite_export_frames`: Exports each animation frame as an individual PNG file
|
|
14
|
+
- `aseprite_export_metadata`: Exports Aseprite metadata in JSON format
|
|
15
|
+
|
|
16
|
+
### V2 - Lua Automation
|
|
17
|
+
Adds deeper control using Aseprite Lua scripting, enabling safe AI-driven editing operations such as:
|
|
18
|
+
- `aseprite_list_lua_templates`: Lists available Lua templates
|
|
19
|
+
- `aseprite_run_lua_template`: Runs a predefined safe Lua automation(templates)
|
|
20
|
+
- `remove_layer_by_name`: Removing specific layers
|
|
21
|
+
- `export_tag_frames`: Palette recoloring
|
|
22
|
+
- `recolor_palette`: Normalizing animation speed
|
|
23
|
+
- `normalize_animation_speed`: Exporting only specific animation tags
|
|
24
|
+
- `auto_crop_transparent`: Removing empty transparent borders around the sprite
|
|
25
|
+
- `export_layer_only`: Exporting only a specific layer as a flattened PNG image
|
|
26
|
+
- `export_tag_frames`: Exporting all frames within a specific animation tag as individual PNG files
|
|
27
|
+
- `merge_visible_layers`: Merging all currently visible layers into a single layer
|
|
28
|
+
- `aseprite_run_lua`: Executes a raw Lua script (advanced / unsafe)
|
|
29
|
+
|
|
7
30
|
## How to use
|
|
8
31
|
1) Run directly with npx
|
|
9
32
|
```bash
|
|
@@ -53,9 +76,3 @@ Add the following to your .cursor.json
|
|
|
53
76
|
}
|
|
54
77
|
}
|
|
55
78
|
```
|
|
56
|
-
|
|
57
|
-
## Tools
|
|
58
|
-
- `aseprite_check_environment`: Checks Aseprite installation status, executable path, and version
|
|
59
|
-
- `aseprite_export_sheet`: Exports a sprite sheet as PNG + JSON
|
|
60
|
-
- `aseprite_export_frames`: Exports each animation frame as an individual PNG file
|
|
61
|
-
- `aseprite_export_metadata`: Exports Aseprite metadata in JSON format
|
package/build/aseprite/env.js
CHANGED
|
@@ -33,7 +33,7 @@ function getSteamVdfPaths() {
|
|
|
33
33
|
path.join(os.homedir(), "Library/Application Support/Steam/steamapps/libraryfolders.vdf")
|
|
34
34
|
];
|
|
35
35
|
default:
|
|
36
|
-
//
|
|
36
|
+
// Linux
|
|
37
37
|
return [
|
|
38
38
|
path.join(os.homedir(), ".steam/steam/steamapps/libraryfolders.vdf"),
|
|
39
39
|
path.join(os.homedir(), ".local/share/Steam/steamapps/libraryfolders.vdf")
|
|
@@ -81,7 +81,8 @@ export function getSteamAsepritePaths() {
|
|
|
81
81
|
case "darwin":
|
|
82
82
|
paths.push(path.join(lib, "steamapps/common/Aseprite/Aseprite.app/Contents/MacOS/aseprite"));
|
|
83
83
|
break;
|
|
84
|
-
default:
|
|
84
|
+
default:
|
|
85
|
+
// Linux
|
|
85
86
|
paths.push(path.join(lib, "steamapps/common/Aseprite/aseprite"));
|
|
86
87
|
break;
|
|
87
88
|
}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import z from "zod";
|
|
2
|
+
import { resolveAsepritePath } from "./env.js";
|
|
3
|
+
import { runAsepriteCommand } from "./cli.js";
|
|
4
|
+
import { errorResult, successResult } from "../util.js";
|
|
5
|
+
import { ensureSafePath } from "./path.js";
|
|
6
|
+
import { readFileSync } from "node:fs";
|
|
7
|
+
const toolSchemas = createToolSchemas();
|
|
8
|
+
export function createToolHandlers() {
|
|
9
|
+
const aseprite_check_environment = async () => {
|
|
10
|
+
try {
|
|
11
|
+
const asepritePath = await resolveAsepritePath();
|
|
12
|
+
const { stdout: version } = await runAsepriteCommand(["--version"]);
|
|
13
|
+
return successResult("aseprite_check_environment", { path: asepritePath, version });
|
|
14
|
+
}
|
|
15
|
+
catch (e) {
|
|
16
|
+
return errorResult("aseprite_check_environment", e instanceof Error ? e.message : String(e));
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
const aseprite_export_sheet = async ({ inputFile, outputSheet, sheetType = "packed", dataFile, tag }) => {
|
|
20
|
+
try {
|
|
21
|
+
const inputAbsPath = ensureSafePath(inputFile, { mustExist: true });
|
|
22
|
+
const sheetAbsPath = ensureSafePath(outputSheet, { createDirIfNeeded: true });
|
|
23
|
+
const dataAbsPath = dataFile ? ensureSafePath(dataFile, { createDirIfNeeded: true }) : undefined;
|
|
24
|
+
const args = [
|
|
25
|
+
"--batch",
|
|
26
|
+
`"${inputAbsPath}"`,
|
|
27
|
+
"--sheet",
|
|
28
|
+
`"${sheetAbsPath}"`,
|
|
29
|
+
"--sheet-type",
|
|
30
|
+
sheetType
|
|
31
|
+
];
|
|
32
|
+
if (tag)
|
|
33
|
+
args.push("--tag", `"${tag}"`);
|
|
34
|
+
if (dataAbsPath)
|
|
35
|
+
args.push("--data", `"${dataAbsPath}"`);
|
|
36
|
+
const result = await runAsepriteCommand(args);
|
|
37
|
+
return successResult("aseprite_export_sheet", {
|
|
38
|
+
command: result.command,
|
|
39
|
+
inputFile: inputAbsPath,
|
|
40
|
+
outputSheet: sheetAbsPath,
|
|
41
|
+
sheetType,
|
|
42
|
+
dataFile: dataAbsPath ? dataAbsPath : undefined,
|
|
43
|
+
tag: tag ? tag : undefined,
|
|
44
|
+
stdout: result.stdout.trim(),
|
|
45
|
+
stderr: result.stderr.trim(),
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
catch (e) {
|
|
49
|
+
return errorResult("aseprite_export_sheet", e instanceof Error ? e.message : String(e));
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
const aseprite_export_frames = async ({ inputFile, outputPattern, tag }) => {
|
|
53
|
+
try {
|
|
54
|
+
const inputAbsPath = ensureSafePath(inputFile, { mustExist: true });
|
|
55
|
+
const outputAbsPath = ensureSafePath(outputPattern, { createDirIfNeeded: true });
|
|
56
|
+
const args = [
|
|
57
|
+
"--batch",
|
|
58
|
+
`"${inputAbsPath}"`,
|
|
59
|
+
"--save-as",
|
|
60
|
+
`"${outputAbsPath}"`
|
|
61
|
+
];
|
|
62
|
+
if (tag)
|
|
63
|
+
args.push("--tag", `"${tag}"`);
|
|
64
|
+
const result = await runAsepriteCommand(args);
|
|
65
|
+
return successResult("aseprite_export_frames", {
|
|
66
|
+
command: result.command,
|
|
67
|
+
inputFile: inputAbsPath,
|
|
68
|
+
outputPattern: outputAbsPath,
|
|
69
|
+
tag: tag ? tag : undefined,
|
|
70
|
+
stdout: result.stdout.trim(),
|
|
71
|
+
stderr: result.stderr.trim(),
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
catch (e) {
|
|
75
|
+
return errorResult("aseprite_export_frames", e instanceof Error ? e.message : String(e));
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
const aseprite_export_metadata = async ({ inputFile, dataFile, format }) => {
|
|
79
|
+
try {
|
|
80
|
+
const inputAbsPath = ensureSafePath(inputFile, { mustExist: true });
|
|
81
|
+
const dataAbsPath = ensureSafePath(dataFile, { createDirIfNeeded: true });
|
|
82
|
+
const args = [
|
|
83
|
+
"--batch",
|
|
84
|
+
`"${inputAbsPath}"`,
|
|
85
|
+
"--data",
|
|
86
|
+
`"${dataAbsPath}"`
|
|
87
|
+
];
|
|
88
|
+
if (format)
|
|
89
|
+
args.push("--format", `"${format}"`);
|
|
90
|
+
const result = await runAsepriteCommand(args);
|
|
91
|
+
let metaText = "";
|
|
92
|
+
try {
|
|
93
|
+
metaText = readFileSync(dataAbsPath, "utf8");
|
|
94
|
+
}
|
|
95
|
+
catch (e) {
|
|
96
|
+
metaText = `Failed to read metadata: ${e instanceof Error ? e.message : String(e)}`;
|
|
97
|
+
}
|
|
98
|
+
return successResult("aseprite_export_metadata", {
|
|
99
|
+
command: result.command,
|
|
100
|
+
inputFile: inputAbsPath,
|
|
101
|
+
dataFile: dataAbsPath,
|
|
102
|
+
format: format ? format : undefined,
|
|
103
|
+
stdout: result.stdout.trim(),
|
|
104
|
+
stderr: result.stderr.trim(),
|
|
105
|
+
metadata: metaText,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
catch (e) {
|
|
109
|
+
return errorResult("aseprite_export_metadata", e instanceof Error ? e.message : String(e));
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
return {
|
|
113
|
+
aseprite_check_environment,
|
|
114
|
+
aseprite_export_sheet,
|
|
115
|
+
aseprite_export_frames,
|
|
116
|
+
aseprite_export_metadata
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
export function createToolSchemas() {
|
|
120
|
+
return {
|
|
121
|
+
aseprite_export_sheet: z.object({
|
|
122
|
+
inputFile: z.string(),
|
|
123
|
+
outputSheet: z.string(),
|
|
124
|
+
sheetType: z.enum(["rows", "columns", "packed"]).optional().default("packed"),
|
|
125
|
+
dataFile: z.string().optional(),
|
|
126
|
+
tag: z.string().optional(),
|
|
127
|
+
}),
|
|
128
|
+
aseprite_export_frames: z.object({
|
|
129
|
+
inputFile: z.string(),
|
|
130
|
+
outputPattern: z.string(),
|
|
131
|
+
tag: z.string().optional(),
|
|
132
|
+
}),
|
|
133
|
+
aseprite_export_metadata: z.object({
|
|
134
|
+
inputFile: z.string(),
|
|
135
|
+
dataFile: z.string(),
|
|
136
|
+
format: z.string().optional(),
|
|
137
|
+
}),
|
|
138
|
+
aseprite_output_result: z.object({
|
|
139
|
+
content: z.array(z.object({
|
|
140
|
+
type: z.literal("text"),
|
|
141
|
+
text: z.string(),
|
|
142
|
+
})),
|
|
143
|
+
}),
|
|
144
|
+
};
|
|
145
|
+
}
|
package/build/index.js
CHANGED
|
@@ -1,33 +1,51 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
3
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
-
import { createToolHandlers, createToolSchemas } from "./tools.js";
|
|
4
|
+
import { createToolHandlers as createAsepriteToolHandlers, createToolSchemas as createAsepriteToolSchemas } from "./aseprite/tools.js";
|
|
5
|
+
import { createToolHandlers as createLuaToolHandlers, createToolSchemas as createLuaToolSchemas } from "./lua/tools.js";
|
|
5
6
|
const server = new McpServer({
|
|
6
7
|
name: "aseprite-mcp",
|
|
7
8
|
version: "0.1.0"
|
|
8
9
|
});
|
|
9
|
-
const
|
|
10
|
-
const
|
|
10
|
+
const asepriteToolSchemas = createAsepriteToolSchemas();
|
|
11
|
+
const luaToolSchemas = createLuaToolSchemas();
|
|
12
|
+
const asepriteToolHandlers = createAsepriteToolHandlers();
|
|
13
|
+
const luaToolHandlers = createLuaToolHandlers();
|
|
11
14
|
server.registerTool("aseprite_check_environment", {
|
|
12
15
|
description: "Check the environment of Aseprite",
|
|
13
16
|
inputSchema: undefined,
|
|
14
17
|
outputSchema: undefined,
|
|
15
|
-
},
|
|
18
|
+
}, asepriteToolHandlers.aseprite_check_environment);
|
|
16
19
|
server.registerTool("aseprite_export_sheet", {
|
|
17
20
|
description: "Export Aseprite file to sprite sheet image",
|
|
18
|
-
inputSchema:
|
|
19
|
-
outputSchema:
|
|
20
|
-
},
|
|
21
|
+
inputSchema: asepriteToolSchemas.aseprite_export_sheet,
|
|
22
|
+
outputSchema: asepriteToolSchemas.aseprite_output_result,
|
|
23
|
+
}, asepriteToolHandlers.aseprite_export_sheet);
|
|
21
24
|
server.registerTool("aseprite_export_frames", {
|
|
22
25
|
description: "Export each frame of Aseprite file",
|
|
23
|
-
inputSchema:
|
|
24
|
-
outputSchema:
|
|
25
|
-
},
|
|
26
|
+
inputSchema: asepriteToolSchemas.aseprite_export_frames,
|
|
27
|
+
outputSchema: asepriteToolSchemas.aseprite_output_result,
|
|
28
|
+
}, asepriteToolHandlers.aseprite_export_frames);
|
|
26
29
|
server.registerTool("aseprite_export_metadata", {
|
|
27
30
|
description: "Export metadata json from Aseprite file",
|
|
28
|
-
inputSchema:
|
|
29
|
-
outputSchema:
|
|
30
|
-
},
|
|
31
|
+
inputSchema: asepriteToolSchemas.aseprite_export_metadata,
|
|
32
|
+
outputSchema: asepriteToolSchemas.aseprite_output_result,
|
|
33
|
+
}, asepriteToolHandlers.aseprite_export_metadata);
|
|
34
|
+
server.registerTool("aseprite_list_lua_templates", {
|
|
35
|
+
description: "List available Aseprite Lua templates.",
|
|
36
|
+
inputSchema: undefined,
|
|
37
|
+
outputSchema: undefined,
|
|
38
|
+
}, luaToolHandlers.aseprite_list_lua_templates);
|
|
39
|
+
server.registerTool("aseprite_run_lua_template", {
|
|
40
|
+
description: "Run a predefined Aseprite Lua template with parameters.",
|
|
41
|
+
inputSchema: luaToolSchemas.aseprite_run_lua_template,
|
|
42
|
+
outputSchema: luaToolSchemas.lua_output_result,
|
|
43
|
+
}, luaToolHandlers.aseprite_run_lua_template);
|
|
44
|
+
server.registerTool("aseprite_run_lua_script", {
|
|
45
|
+
description: "Run a raw Lua script (advanced / unsafe).",
|
|
46
|
+
inputSchema: luaToolSchemas.aseprite_run_lua_script,
|
|
47
|
+
outputSchema: luaToolSchemas.lua_output_result,
|
|
48
|
+
}, luaToolHandlers.aseprite_run_lua_script);
|
|
31
49
|
async function main() {
|
|
32
50
|
const transport = new StdioServerTransport();
|
|
33
51
|
await server.connect(transport);
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
import { ensureSafePath } from "../aseprite/path.js";
|
|
4
|
+
import { runAsepriteCommand } from "../aseprite/cli.js";
|
|
5
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = path.dirname(__filename);
|
|
7
|
+
export const LUA_TEMPLATES = [
|
|
8
|
+
{
|
|
9
|
+
id: "remove_layer_by_name",
|
|
10
|
+
description: "Removes a layer with a given name and saves to a new file (or overwrites).",
|
|
11
|
+
params: ["inputFile", "layerName"],
|
|
12
|
+
optionalParams: ["saveOutput"],
|
|
13
|
+
scriptPath: path.join(__dirname, "templates", "remove_layer_by_name.lua")
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
id: "export_tag_frames",
|
|
17
|
+
description: "Exports only the frames of a specific tag as PNG images.",
|
|
18
|
+
params: ["inputFile", "tag", "outputDir"],
|
|
19
|
+
optionalParams: ["filenamePrefix"],
|
|
20
|
+
scriptPath: path.join(__dirname, "templates", "export_tag_frames.lua")
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
id: "recolor_palette",
|
|
24
|
+
description: "Recolors the palette based on a mapping of from->to colors.",
|
|
25
|
+
params: ["inputFile", "saveOutput", "mapping"],
|
|
26
|
+
optionalParams: [],
|
|
27
|
+
scriptPath: path.join(__dirname, "templates", "recolor_palette.lua")
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
id: "normalize_animation_speed",
|
|
31
|
+
description: "Normalizes all frame durations to a single target duration (in seconds).",
|
|
32
|
+
params: ["inputFile", "saveOutput", "targetDuration"],
|
|
33
|
+
optionalParams: [],
|
|
34
|
+
scriptPath: path.join(__dirname, "templates", "normalize_animation_speed.lua")
|
|
35
|
+
}
|
|
36
|
+
];
|
|
37
|
+
export function findLuaTemplate(id) {
|
|
38
|
+
return LUA_TEMPLATES.find(t => t.id === id);
|
|
39
|
+
}
|
|
40
|
+
export async function runLuaTemplate(template, params) {
|
|
41
|
+
return runLua(template, params);
|
|
42
|
+
}
|
|
43
|
+
export async function runLuaScript(scriptPath, params) {
|
|
44
|
+
return runLua(scriptPath, params);
|
|
45
|
+
}
|
|
46
|
+
export async function runLua(script, params) {
|
|
47
|
+
const args = ["--batch"];
|
|
48
|
+
if (typeof params.inputFile === "string") {
|
|
49
|
+
const inputAbs = ensureSafePath(params.inputFile, { mustExist: true });
|
|
50
|
+
args.push(`"${inputAbs}"`);
|
|
51
|
+
}
|
|
52
|
+
const scriptPath = typeof script === "string" ? script : script.scriptPath;
|
|
53
|
+
args.push("--script", `"${scriptPath}"`);
|
|
54
|
+
for (const [key, value] of Object.entries(params)) {
|
|
55
|
+
if (key === "inputFile" || value == null)
|
|
56
|
+
continue;
|
|
57
|
+
args.push("--script-param", `${key}=${value}`);
|
|
58
|
+
}
|
|
59
|
+
return runAsepriteCommand(args);
|
|
60
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { errorResult, successResult } from "../util.js";
|
|
2
|
+
import { findLuaTemplate, LUA_TEMPLATES, runLuaScript, runLuaTemplate } from "./templates.js";
|
|
3
|
+
import { ensureSafePath } from "../aseprite/path.js";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import z from "zod";
|
|
6
|
+
import os from "node:os";
|
|
7
|
+
import fs from "node:fs/promises";
|
|
8
|
+
const toolSchemas = createToolSchemas();
|
|
9
|
+
export function createToolHandlers() {
|
|
10
|
+
const aseprite_list_lua_templates = async () => {
|
|
11
|
+
return successResult("aseprite_list_lua_templates", {
|
|
12
|
+
templates: LUA_TEMPLATES.map(template => ({
|
|
13
|
+
id: template.id,
|
|
14
|
+
description: template.description,
|
|
15
|
+
params: template.params,
|
|
16
|
+
optionalParams: template.optionalParams ?? []
|
|
17
|
+
}))
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
const aseprite_run_lua_template = async ({ templateId, params = {} }) => {
|
|
21
|
+
const template = findLuaTemplate(templateId);
|
|
22
|
+
if (!template) {
|
|
23
|
+
return errorResult("aseprite_run_lua_template", new Error(`Unknown templateId: ${templateId}`));
|
|
24
|
+
}
|
|
25
|
+
const missing = template.params.filter(key => !params.hasOwnProperty(key));
|
|
26
|
+
if (missing.length > 0) {
|
|
27
|
+
return errorResult("aseprite_run_lua_template", new Error(`Missing required params: ${missing.join(", ")}`));
|
|
28
|
+
}
|
|
29
|
+
try {
|
|
30
|
+
const result = await runLuaTemplate(template, params);
|
|
31
|
+
return successResult("aseprite_run_lua_template", {
|
|
32
|
+
command: result.command,
|
|
33
|
+
templateId,
|
|
34
|
+
stdout: result.stdout.trim(),
|
|
35
|
+
stderr: result.stderr.trim()
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
return errorResult("aseprite_run_lua_template", new Error(`Execution failed: ${err instanceof Error ? err.message : String(err)}`));
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
const aseprite_run_lua_script = async ({ scriptPath, scriptContent, params = {} }) => {
|
|
43
|
+
try {
|
|
44
|
+
let luaFilePath;
|
|
45
|
+
if (scriptPath) {
|
|
46
|
+
luaFilePath = ensureSafePath(scriptPath, { mustExist: true });
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
const tempPath = path.join(os.tmpdir(), `aseprite-mcp-${Date.now()}.lua`);
|
|
50
|
+
await fs.writeFile(tempPath, String(scriptContent), "utf8");
|
|
51
|
+
luaFilePath = tempPath;
|
|
52
|
+
}
|
|
53
|
+
const result = await runLuaScript(luaFilePath, params);
|
|
54
|
+
return successResult("aseprite_run_lua_script", {
|
|
55
|
+
command: result.command,
|
|
56
|
+
stdout: result.stdout.trim(),
|
|
57
|
+
stderr: result.stderr.trim()
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
return errorResult("aseprite_run_lua_script", new Error(`Execution failed: ${err instanceof Error ? err.message : String(err)}`));
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
return {
|
|
65
|
+
aseprite_list_lua_templates,
|
|
66
|
+
aseprite_run_lua_template,
|
|
67
|
+
aseprite_run_lua_script
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
;
|
|
71
|
+
export function createToolSchemas() {
|
|
72
|
+
return {
|
|
73
|
+
aseprite_run_lua_template: z.object({
|
|
74
|
+
templateId: z.string(),
|
|
75
|
+
params: z.record(z.string(), z.any()).optional()
|
|
76
|
+
}),
|
|
77
|
+
aseprite_run_lua_script: z
|
|
78
|
+
.object({
|
|
79
|
+
scriptPath: z.string().optional(),
|
|
80
|
+
scriptContent: z.string().optional(),
|
|
81
|
+
params: z.record(z.string(), z.any()).optional()
|
|
82
|
+
})
|
|
83
|
+
.refine(v => !!v.scriptPath || !!v.scriptContent, {
|
|
84
|
+
message: "Either scriptPath or scriptContent is required."
|
|
85
|
+
}),
|
|
86
|
+
lua_output_result: z.object({
|
|
87
|
+
content: z.array(z.object({
|
|
88
|
+
type: z.literal("text"),
|
|
89
|
+
text: z.string()
|
|
90
|
+
}))
|
|
91
|
+
})
|
|
92
|
+
};
|
|
93
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iborymagic/aseprite-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "MCP server for using Aseprite API",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -14,19 +14,24 @@
|
|
|
14
14
|
"build": "tsc",
|
|
15
15
|
"start": "node build/index.js",
|
|
16
16
|
"dev": "npm run build && npm run start",
|
|
17
|
-
"test": "
|
|
17
|
+
"test": "vitest"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"@modelcontextprotocol/sdk": "^1.25.1",
|
|
21
21
|
"zod": "^4.2.1"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
|
-
"@types/jest": "^30.0.0",
|
|
25
24
|
"@types/node": "^25.0.0",
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"typescript": "^5.0.0"
|
|
25
|
+
"typescript": "^5.0.0",
|
|
26
|
+
"vitest": "^4.0.16"
|
|
29
27
|
},
|
|
30
28
|
"author": "iborymagic",
|
|
29
|
+
"repository": {
|
|
30
|
+
"type": "git",
|
|
31
|
+
"url": "https://github.com/iborymagic/aseprite-mcp"
|
|
32
|
+
},
|
|
33
|
+
"bugs": {
|
|
34
|
+
"url": "https://github.com/iborymagic/aseprite-mcp/issues"
|
|
35
|
+
},
|
|
31
36
|
"license": "MIT"
|
|
32
37
|
}
|