@iborymagic/aseprite-mcp 0.4.0 → 0.4.2
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 +8 -0
- package/build/aseprite/cli.js +1 -6
- package/build/aseprite/tools.js +5 -11
- package/build/index.js +16 -2
- package/build/lua/tools.js +93 -89
- package/build/util.js +2 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -16,6 +16,14 @@ Supports fundamental Aseprite export workflow:
|
|
|
16
16
|
Adds deeper control using Aseprite Lua scripting, enabling safe AI-driven editing operations such as:
|
|
17
17
|
- `aseprite_list_lua_templates`: Lists available Lua templates
|
|
18
18
|
- Predefined safe Lua automation(templates)
|
|
19
|
+
- `get_active_sprite_info`: Provides basic information about the currently active sprite
|
|
20
|
+
- `get_frame_info`: Inspects the animation timeline and frame structure of the active sprite
|
|
21
|
+
- `get_layer_list`: Returns a full structural overview of all layers in the active sprite, including groups
|
|
22
|
+
- `get_tag_list`: Lists all animation tags defined in the active sprite
|
|
23
|
+
- `get_is_layer_exists`: Checks whether a layer with a specific name exists
|
|
24
|
+
- `get_is_tag_exists`: Checks whether a specific animation tag exists
|
|
25
|
+
- `get_palette_info`: Inspects the current palette of the active sprite
|
|
26
|
+
- `get_selection_bounds`: Inspects the current selection state and its bounds
|
|
19
27
|
- `remove_layer_by_name`: Removing specific layers
|
|
20
28
|
- `recolor_palette`: Palette recoloring
|
|
21
29
|
- `normalize_animation_speed`: Normalizing animation speed
|
package/build/aseprite/cli.js
CHANGED
|
@@ -11,12 +11,7 @@ export async function runAsepriteCommand(args, timeout = 10_000) {
|
|
|
11
11
|
}
|
|
12
12
|
catch (error) {
|
|
13
13
|
if (error.killed === true && error.code === null) {
|
|
14
|
-
|
|
15
|
-
command,
|
|
16
|
-
stdout: "",
|
|
17
|
-
stderr: "Aseprite command timed out",
|
|
18
|
-
timedOut: true
|
|
19
|
-
};
|
|
14
|
+
throw new Error(`Aseprite command timed out: ${command}`);
|
|
20
15
|
}
|
|
21
16
|
throw new Error(`Failed to run Aseprite command: ${command}\n${error instanceof Error ? error.message : String(error)}`);
|
|
22
17
|
}
|
package/build/aseprite/tools.js
CHANGED
|
@@ -34,15 +34,13 @@ export function createToolHandlers() {
|
|
|
34
34
|
if (dataAbsPath)
|
|
35
35
|
args.push("--data", `"${dataAbsPath}"`);
|
|
36
36
|
const result = await runAsepriteCommand(args);
|
|
37
|
-
return successResult("aseprite_export_sheet", {
|
|
37
|
+
return successResult("aseprite_export_sheet", result.stdout.trim(), {
|
|
38
38
|
command: result.command,
|
|
39
39
|
inputFile: inputAbsPath,
|
|
40
40
|
outputSheet: sheetAbsPath,
|
|
41
|
-
sheetType,
|
|
41
|
+
sheetType: sheetType,
|
|
42
42
|
dataFile: dataAbsPath ? dataAbsPath : undefined,
|
|
43
43
|
tag: tag ? tag : undefined,
|
|
44
|
-
stdout: result.stdout.trim(),
|
|
45
|
-
stderr: result.stderr.trim(),
|
|
46
44
|
});
|
|
47
45
|
}
|
|
48
46
|
catch (e) {
|
|
@@ -62,13 +60,11 @@ export function createToolHandlers() {
|
|
|
62
60
|
if (tag)
|
|
63
61
|
args.push("--tag", `"${tag}"`);
|
|
64
62
|
const result = await runAsepriteCommand(args);
|
|
65
|
-
return successResult("aseprite_export_frames", {
|
|
63
|
+
return successResult("aseprite_export_frames", result.stdout.trim(), {
|
|
66
64
|
command: result.command,
|
|
67
65
|
inputFile: inputAbsPath,
|
|
68
66
|
outputPattern: outputAbsPath,
|
|
69
67
|
tag: tag ? tag : undefined,
|
|
70
|
-
stdout: result.stdout.trim(),
|
|
71
|
-
stderr: result.stderr.trim(),
|
|
72
68
|
});
|
|
73
69
|
}
|
|
74
70
|
catch (e) {
|
|
@@ -95,13 +91,11 @@ export function createToolHandlers() {
|
|
|
95
91
|
catch (e) {
|
|
96
92
|
metaText = `Failed to read metadata: ${e instanceof Error ? e.message : String(e)}`;
|
|
97
93
|
}
|
|
98
|
-
return successResult("aseprite_export_metadata", {
|
|
94
|
+
return successResult("aseprite_export_metadata", result.stdout.trim(), {
|
|
99
95
|
command: result.command,
|
|
100
96
|
inputFile: inputAbsPath,
|
|
101
97
|
dataFile: dataAbsPath,
|
|
102
|
-
format
|
|
103
|
-
stdout: result.stdout.trim(),
|
|
104
|
-
stderr: result.stderr.trim(),
|
|
98
|
+
format,
|
|
105
99
|
metadata: metaText,
|
|
106
100
|
});
|
|
107
101
|
}
|
package/build/index.js
CHANGED
|
@@ -5,14 +5,28 @@ import { createToolHandlers as createAsepriteToolHandlers, createToolSchemas as
|
|
|
5
5
|
import { createToolHandlers as createLuaToolHandlers, createToolSchemas as createLuaToolSchemas } from "./lua/tools.js";
|
|
6
6
|
import path from "node:path";
|
|
7
7
|
import { readFileSync } from "node:fs";
|
|
8
|
+
import { fileURLToPath } from "node:url";
|
|
8
9
|
let version;
|
|
9
10
|
try {
|
|
10
|
-
|
|
11
|
+
// Get the directory of the current file (build/index.js)
|
|
12
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
13
|
+
const __dirname = path.dirname(__filename);
|
|
14
|
+
// Go up one level from build/ to package root
|
|
15
|
+
const packageJsonPath = path.join(__dirname, "..", "package.json");
|
|
11
16
|
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf8"));
|
|
12
17
|
version = packageJson.version;
|
|
13
18
|
}
|
|
14
19
|
catch (error) {
|
|
15
|
-
|
|
20
|
+
// Fallback: try process.cwd() if the above fails
|
|
21
|
+
try {
|
|
22
|
+
const packageJsonPath = path.join(process.cwd(), "package.json");
|
|
23
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf8"));
|
|
24
|
+
version = packageJson.version;
|
|
25
|
+
}
|
|
26
|
+
catch (fallbackError) {
|
|
27
|
+
// If both fail, use default version
|
|
28
|
+
version = undefined;
|
|
29
|
+
}
|
|
16
30
|
}
|
|
17
31
|
const server = new McpServer({
|
|
18
32
|
name: "aseprite-mcp",
|
package/build/lua/tools.js
CHANGED
|
@@ -28,9 +28,6 @@ export function createToolHandlers() {
|
|
|
28
28
|
throw new Error(`Missing required params: ${missing.join(", ")}`);
|
|
29
29
|
}
|
|
30
30
|
const result = await runLuaScriptFile(template.scriptPath, params);
|
|
31
|
-
if (result.timedOut) {
|
|
32
|
-
throw new Error(`Lua script timed out while executing template: ${templateId}`);
|
|
33
|
-
}
|
|
34
31
|
const stderrTrimmed = result.stderr.trim();
|
|
35
32
|
const stdoutTrimmed = result.stdout.trim();
|
|
36
33
|
if (stderrTrimmed && stderrTrimmed.includes("ERROR:")) {
|
|
@@ -54,10 +51,9 @@ export function createToolHandlers() {
|
|
|
54
51
|
saveOutput: ensureSafePath(saveOutput, { createDirIfNeeded: true })
|
|
55
52
|
}
|
|
56
53
|
});
|
|
57
|
-
return successResult("auto_crop_transparent", {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
stderr: result.stderr
|
|
54
|
+
return successResult("auto_crop_transparent", result.stdout, {
|
|
55
|
+
inputFile: inputFile,
|
|
56
|
+
saveOutput: saveOutput,
|
|
61
57
|
});
|
|
62
58
|
}
|
|
63
59
|
catch (err) {
|
|
@@ -73,10 +69,10 @@ export function createToolHandlers() {
|
|
|
73
69
|
saveOutput: ensureSafePath(saveOutput, { createDirIfNeeded: true })
|
|
74
70
|
}
|
|
75
71
|
});
|
|
76
|
-
return successResult("merge_visible_layers", {
|
|
72
|
+
return successResult("merge_visible_layers", result.stdout, {
|
|
77
73
|
command: result.command,
|
|
78
|
-
|
|
79
|
-
|
|
74
|
+
inputFile: inputFile,
|
|
75
|
+
saveOutput: saveOutput,
|
|
80
76
|
});
|
|
81
77
|
}
|
|
82
78
|
catch (err) {
|
|
@@ -93,10 +89,11 @@ export function createToolHandlers() {
|
|
|
93
89
|
targetDuration
|
|
94
90
|
}
|
|
95
91
|
});
|
|
96
|
-
return successResult("normalize_animation_speed", {
|
|
92
|
+
return successResult("normalize_animation_speed", result.stdout, {
|
|
97
93
|
command: result.command,
|
|
98
|
-
|
|
99
|
-
|
|
94
|
+
inputFile: inputFile,
|
|
95
|
+
saveOutput: saveOutput,
|
|
96
|
+
targetDuration: targetDuration,
|
|
100
97
|
});
|
|
101
98
|
}
|
|
102
99
|
catch (err) {
|
|
@@ -113,10 +110,11 @@ export function createToolHandlers() {
|
|
|
113
110
|
inputFile
|
|
114
111
|
}
|
|
115
112
|
});
|
|
116
|
-
return successResult("recolor_palette", {
|
|
113
|
+
return successResult("recolor_palette", result.stdout, {
|
|
117
114
|
command: result.command,
|
|
118
|
-
|
|
119
|
-
|
|
115
|
+
inputFile: inputFile,
|
|
116
|
+
saveOutput: saveOutput,
|
|
117
|
+
mapping: mapping,
|
|
120
118
|
});
|
|
121
119
|
}
|
|
122
120
|
catch (err) {
|
|
@@ -125,6 +123,15 @@ export function createToolHandlers() {
|
|
|
125
123
|
};
|
|
126
124
|
const remove_layer_by_name = async ({ layerName, saveOutput, inputFile }) => {
|
|
127
125
|
try {
|
|
126
|
+
const getIsLayerExistsResult = await get_is_layer_exists({
|
|
127
|
+
inputFile,
|
|
128
|
+
layerName
|
|
129
|
+
}, {});
|
|
130
|
+
const content = getIsLayerExistsResult.content[0];
|
|
131
|
+
const isLayerExist = JSON.parse(content.text).result === 'true';
|
|
132
|
+
if (!isLayerExist) {
|
|
133
|
+
return errorResult("remove_layer_by_name", `Layer not found: ${layerName}`);
|
|
134
|
+
}
|
|
128
135
|
const result = await run_lua_template({
|
|
129
136
|
templateId: "remove_layer_by_name",
|
|
130
137
|
params: {
|
|
@@ -133,10 +140,11 @@ export function createToolHandlers() {
|
|
|
133
140
|
inputFile
|
|
134
141
|
}
|
|
135
142
|
});
|
|
136
|
-
return successResult("remove_layer_by_name", {
|
|
143
|
+
return successResult("remove_layer_by_name", result.stdout, {
|
|
137
144
|
command: result.command,
|
|
138
|
-
|
|
139
|
-
|
|
145
|
+
inputFile: inputFile,
|
|
146
|
+
layerName: layerName,
|
|
147
|
+
saveOutput: saveOutput,
|
|
140
148
|
});
|
|
141
149
|
}
|
|
142
150
|
catch (err) {
|
|
@@ -145,6 +153,15 @@ export function createToolHandlers() {
|
|
|
145
153
|
};
|
|
146
154
|
const export_layer_only = async ({ layerName, outputDir, inputFile }) => {
|
|
147
155
|
try {
|
|
156
|
+
const getIsLayerExistsResult = await get_is_layer_exists({
|
|
157
|
+
inputFile,
|
|
158
|
+
layerName
|
|
159
|
+
}, {});
|
|
160
|
+
const content = getIsLayerExistsResult.content[0];
|
|
161
|
+
const isLayerExist = JSON.parse(content.text).result === 'true';
|
|
162
|
+
if (!isLayerExist) {
|
|
163
|
+
return errorResult("export_layer_only", `Layer not found: ${layerName}`);
|
|
164
|
+
}
|
|
148
165
|
const result = await run_lua_template({
|
|
149
166
|
templateId: "export_layer_only",
|
|
150
167
|
params: {
|
|
@@ -153,10 +170,11 @@ export function createToolHandlers() {
|
|
|
153
170
|
inputFile
|
|
154
171
|
}
|
|
155
172
|
});
|
|
156
|
-
return successResult("export_layer_only", {
|
|
173
|
+
return successResult("export_layer_only", result.stdout, {
|
|
157
174
|
command: result.command,
|
|
158
|
-
|
|
159
|
-
|
|
175
|
+
inputFile: inputFile,
|
|
176
|
+
layerName: layerName,
|
|
177
|
+
outputDir: outputDir,
|
|
160
178
|
});
|
|
161
179
|
}
|
|
162
180
|
catch (err) {
|
|
@@ -165,6 +183,15 @@ export function createToolHandlers() {
|
|
|
165
183
|
};
|
|
166
184
|
const export_tag_frames = async ({ tag, outputDir, filenamePrefix, inputFile }) => {
|
|
167
185
|
try {
|
|
186
|
+
const getIsTagExistsResult = await get_is_tag_exists({
|
|
187
|
+
inputFile,
|
|
188
|
+
tagName: tag
|
|
189
|
+
}, {});
|
|
190
|
+
const content = getIsTagExistsResult.content[0];
|
|
191
|
+
const isTagExist = JSON.parse(content.text).result === 'true';
|
|
192
|
+
if (!isTagExist) {
|
|
193
|
+
return errorResult("export_tag_frames", `Tag not found: ${tag}`);
|
|
194
|
+
}
|
|
168
195
|
const result = await run_lua_template({
|
|
169
196
|
templateId: "export_tag_frames",
|
|
170
197
|
params: {
|
|
@@ -174,10 +201,12 @@ export function createToolHandlers() {
|
|
|
174
201
|
inputFile
|
|
175
202
|
}
|
|
176
203
|
});
|
|
177
|
-
return successResult("export_tag_frames", {
|
|
204
|
+
return successResult("export_tag_frames", result.stdout, {
|
|
178
205
|
command: result.command,
|
|
179
|
-
|
|
180
|
-
|
|
206
|
+
inputFile: inputFile,
|
|
207
|
+
tag: tag,
|
|
208
|
+
outputDir: outputDir,
|
|
209
|
+
filenamePrefix: filenamePrefix,
|
|
181
210
|
});
|
|
182
211
|
}
|
|
183
212
|
catch (err) {
|
|
@@ -190,26 +219,11 @@ export function createToolHandlers() {
|
|
|
190
219
|
templateId: "get_is_layer_exists",
|
|
191
220
|
params: { layerName, inputFile }
|
|
192
221
|
});
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
// Empty stdout might mean false or error
|
|
199
|
-
exists = false;
|
|
200
|
-
}
|
|
201
|
-
else {
|
|
202
|
-
try {
|
|
203
|
-
// Aseprite outputs Lua return values as JSON
|
|
204
|
-
const parsed = JSON.parse(stdoutTrimmed);
|
|
205
|
-
exists = parsed === true;
|
|
206
|
-
}
|
|
207
|
-
catch {
|
|
208
|
-
// If not valid JSON, try string comparison
|
|
209
|
-
exists = stdoutTrimmed.toLowerCase() === "true" || stdoutTrimmed === "1";
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
return successResult("get_is_layer_exists", exists);
|
|
222
|
+
return successResult("get_is_layer_exists", result.stdout, {
|
|
223
|
+
command: result.command,
|
|
224
|
+
inputFile: inputFile,
|
|
225
|
+
layerName: layerName,
|
|
226
|
+
});
|
|
213
227
|
}
|
|
214
228
|
catch (err) {
|
|
215
229
|
return errorResult("get_is_layer_exists", `Execution failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -221,26 +235,11 @@ export function createToolHandlers() {
|
|
|
221
235
|
templateId: "get_is_tag_exists",
|
|
222
236
|
params: { tagName, inputFile }
|
|
223
237
|
});
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
// Empty stdout might mean false or error
|
|
230
|
-
exists = false;
|
|
231
|
-
}
|
|
232
|
-
else {
|
|
233
|
-
try {
|
|
234
|
-
// Aseprite outputs Lua return values as JSON
|
|
235
|
-
const parsed = JSON.parse(stdoutTrimmed);
|
|
236
|
-
exists = parsed === true;
|
|
237
|
-
}
|
|
238
|
-
catch {
|
|
239
|
-
// If not valid JSON, try string comparison
|
|
240
|
-
exists = stdoutTrimmed.toLowerCase() === "true" || stdoutTrimmed === "1";
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
return successResult("get_is_tag_exists", exists);
|
|
238
|
+
return successResult("get_is_tag_exists", result.stdout, {
|
|
239
|
+
command: result.command,
|
|
240
|
+
inputFile: inputFile,
|
|
241
|
+
tagName: tagName,
|
|
242
|
+
});
|
|
244
243
|
}
|
|
245
244
|
catch (err) {
|
|
246
245
|
return errorResult("get_is_tag_exists", `Execution failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -252,9 +251,10 @@ export function createToolHandlers() {
|
|
|
252
251
|
templateId: "get_palette_info",
|
|
253
252
|
params: { inputFile }
|
|
254
253
|
});
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
254
|
+
return successResult("get_palette_info", result.stdout, {
|
|
255
|
+
command: result.command,
|
|
256
|
+
inputFile: inputFile,
|
|
257
|
+
});
|
|
258
258
|
}
|
|
259
259
|
catch (err) {
|
|
260
260
|
return errorResult("get_palette_info", `Execution failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -266,9 +266,10 @@ export function createToolHandlers() {
|
|
|
266
266
|
templateId: "get_selection_bounds",
|
|
267
267
|
params: { inputFile }
|
|
268
268
|
});
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
269
|
+
return successResult("get_selection_bounds", result.stdout, {
|
|
270
|
+
command: result.command,
|
|
271
|
+
inputFile: inputFile,
|
|
272
|
+
});
|
|
272
273
|
}
|
|
273
274
|
catch (err) {
|
|
274
275
|
return errorResult("get_selection_bounds", `Execution failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -280,9 +281,10 @@ export function createToolHandlers() {
|
|
|
280
281
|
templateId: "get_tag_list",
|
|
281
282
|
params: { inputFile }
|
|
282
283
|
});
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
284
|
+
return successResult("get_tag_list", result.stdout, {
|
|
285
|
+
command: result.command,
|
|
286
|
+
inputFile: inputFile,
|
|
287
|
+
});
|
|
286
288
|
}
|
|
287
289
|
catch (err) {
|
|
288
290
|
return errorResult("get_tag_list", `Execution failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -294,9 +296,10 @@ export function createToolHandlers() {
|
|
|
294
296
|
templateId: "get_layer_list",
|
|
295
297
|
params: { inputFile }
|
|
296
298
|
});
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
299
|
+
return successResult("get_layer_list", result.stdout, {
|
|
300
|
+
command: result.command,
|
|
301
|
+
inputFile: inputFile,
|
|
302
|
+
});
|
|
300
303
|
}
|
|
301
304
|
catch (err) {
|
|
302
305
|
return errorResult("get_layer_list", `Execution failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -308,9 +311,10 @@ export function createToolHandlers() {
|
|
|
308
311
|
templateId: "get_frame_info",
|
|
309
312
|
params: { inputFile }
|
|
310
313
|
});
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
+
return successResult("get_frame_info", result.stdout, {
|
|
315
|
+
command: result.command,
|
|
316
|
+
inputFile: inputFile,
|
|
317
|
+
});
|
|
314
318
|
}
|
|
315
319
|
catch (err) {
|
|
316
320
|
return errorResult("get_frame_info", `Execution failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -322,9 +326,10 @@ export function createToolHandlers() {
|
|
|
322
326
|
templateId: "get_active_sprite_info",
|
|
323
327
|
params: { inputFile }
|
|
324
328
|
});
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
329
|
+
return successResult("get_active_sprite_info", result.stdout, {
|
|
330
|
+
command: result.command,
|
|
331
|
+
inputFile: inputFile,
|
|
332
|
+
});
|
|
328
333
|
}
|
|
329
334
|
catch (err) {
|
|
330
335
|
return errorResult("get_active_sprite_info", `Execution failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -342,9 +347,6 @@ export function createToolHandlers() {
|
|
|
342
347
|
luaFilePath = tempPath;
|
|
343
348
|
}
|
|
344
349
|
const result = await runLuaScriptFile(luaFilePath, params);
|
|
345
|
-
if (result.timedOut) {
|
|
346
|
-
return errorResult("aseprite_run_lua_script", `Lua script timed out while executing script: ${luaFilePath}`);
|
|
347
|
-
}
|
|
348
350
|
const stderrTrimmed = result.stderr.trim();
|
|
349
351
|
const stdoutTrimmed = result.stdout.trim();
|
|
350
352
|
if (stderrTrimmed && stderrTrimmed.includes("ERROR:")) {
|
|
@@ -353,10 +355,12 @@ export function createToolHandlers() {
|
|
|
353
355
|
if (stdoutTrimmed && stdoutTrimmed.includes("ERROR:")) {
|
|
354
356
|
return errorResult("aseprite_run_lua_script", `Script execution failed: ${stdoutTrimmed}`);
|
|
355
357
|
}
|
|
356
|
-
return successResult("aseprite_run_lua_script", {
|
|
358
|
+
return successResult("aseprite_run_lua_script", result.stdout, {
|
|
357
359
|
command: result.command,
|
|
358
|
-
|
|
359
|
-
|
|
360
|
+
inputFile: params.inputFile,
|
|
361
|
+
scriptPath: luaFilePath,
|
|
362
|
+
scriptContent: scriptContent,
|
|
363
|
+
params: params,
|
|
360
364
|
});
|
|
361
365
|
}
|
|
362
366
|
catch (err) {
|
package/build/util.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export function successResult(tool, result) {
|
|
1
|
+
export function successResult(tool, result, params) {
|
|
2
2
|
return {
|
|
3
3
|
content: [
|
|
4
4
|
{
|
|
@@ -6,6 +6,7 @@ export function successResult(tool, result) {
|
|
|
6
6
|
text: JSON.stringify({
|
|
7
7
|
success: true,
|
|
8
8
|
tool,
|
|
9
|
+
params: params ?? null,
|
|
9
10
|
result,
|
|
10
11
|
}, null, 2)
|
|
11
12
|
}
|