@meshy-ai/meshy-mcp-server 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/.env.example +14 -0
- package/LICENSE +21 -0
- package/README.md +108 -0
- package/dist/constants.d.ts +123 -0
- package/dist/constants.js +169 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +130 -0
- package/dist/instructions.d.ts +6 -0
- package/dist/instructions.js +90 -0
- package/dist/schemas/balance.d.ts +11 -0
- package/dist/schemas/balance.js +8 -0
- package/dist/schemas/common.d.ts +38 -0
- package/dist/schemas/common.js +52 -0
- package/dist/schemas/generation.d.ts +219 -0
- package/dist/schemas/generation.js +217 -0
- package/dist/schemas/image.d.ts +55 -0
- package/dist/schemas/image.js +46 -0
- package/dist/schemas/output.d.ts +75 -0
- package/dist/schemas/output.js +41 -0
- package/dist/schemas/postprocessing.d.ts +135 -0
- package/dist/schemas/postprocessing.js +123 -0
- package/dist/schemas/printing.d.ts +63 -0
- package/dist/schemas/printing.js +54 -0
- package/dist/schemas/tasks.d.ts +123 -0
- package/dist/schemas/tasks.js +85 -0
- package/dist/services/error-handler.d.ts +32 -0
- package/dist/services/error-handler.js +141 -0
- package/dist/services/file-utils.d.ts +15 -0
- package/dist/services/file-utils.js +55 -0
- package/dist/services/meshy-client.d.ts +54 -0
- package/dist/services/meshy-client.js +172 -0
- package/dist/services/output-manager.d.ts +52 -0
- package/dist/services/output-manager.js +284 -0
- package/dist/tools/balance.d.ts +9 -0
- package/dist/tools/balance.js +61 -0
- package/dist/tools/generation.d.ts +9 -0
- package/dist/tools/generation.js +419 -0
- package/dist/tools/image.d.ts +9 -0
- package/dist/tools/image.js +154 -0
- package/dist/tools/postprocessing.d.ts +9 -0
- package/dist/tools/postprocessing.js +405 -0
- package/dist/tools/printing.d.ts +9 -0
- package/dist/tools/printing.js +338 -0
- package/dist/tools/tasks.d.ts +9 -0
- package/dist/tools/tasks.js +1074 -0
- package/dist/tools/workspace.d.ts +9 -0
- package/dist/tools/workspace.js +161 -0
- package/dist/types.d.ts +261 -0
- package/dist/types.js +4 -0
- package/dist/utils/endpoints.d.ts +16 -0
- package/dist/utils/endpoints.js +38 -0
- package/dist/utils/request-builder.d.ts +15 -0
- package/dist/utils/request-builder.js +24 -0
- package/dist/utils/response-formatter.d.ts +27 -0
- package/dist/utils/response-formatter.js +37 -0
- package/dist/utils/slicer-detector.d.ts +29 -0
- package/dist/utils/slicer-detector.js +237 -0
- package/package.json +64 -0
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Post-processing tools (remesh, retexture, rig, animate)
|
|
3
|
+
*/
|
|
4
|
+
import { handleMeshyError } from "../services/error-handler.js";
|
|
5
|
+
import { RemeshInputSchema, RetextureInputSchema, RigInputSchema, AnimateInputSchema } from "../schemas/postprocessing.js";
|
|
6
|
+
import { TaskCreatedOutputSchema } from "../schemas/output.js";
|
|
7
|
+
import { RIGGING_MAX_FACES } from "../constants.js";
|
|
8
|
+
import { formatTaskCreatedResponse } from "../utils/response-formatter.js";
|
|
9
|
+
import { fetchTaskByIdFromKnownEndpoints } from "../services/meshy-client.js";
|
|
10
|
+
/**
|
|
11
|
+
* Register post-processing tools with the MCP server
|
|
12
|
+
*/
|
|
13
|
+
export function registerPostProcessingTools(server, client) {
|
|
14
|
+
// Remesh tool
|
|
15
|
+
server.registerTool("meshy_remesh", {
|
|
16
|
+
title: "Remesh or Convert 3D Model",
|
|
17
|
+
description: `Remesh an existing 3D model or convert it to different formats using Meshy AI.
|
|
18
|
+
|
|
19
|
+
Use this to optimize polygon count, change topology, convert formats, or reposition model origin.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
- input_task_id (string, optional): Task ID of an existing completed task to remesh
|
|
23
|
+
- model_url (string, optional): Direct URL to a model file to remesh
|
|
24
|
+
(Provide either input_task_id or model_url)
|
|
25
|
+
- target_formats (array, optional): Output formats to generate (default: ["glb"]). Options: "glb", "fbx", "obj", "usdz", "blend", "stl"
|
|
26
|
+
- topology (enum, optional): Mesh topology - "quad" or "triangle"
|
|
27
|
+
- target_polycount (number, optional): Target polygon count (100–300,000)
|
|
28
|
+
- resize_height (number, optional): Resize model height in meters (0 = no resize, default: 0)
|
|
29
|
+
- origin_at (enum, optional): Model origin placement - "bottom" or "center"
|
|
30
|
+
- convert_format_only (boolean, optional): Only convert format without remeshing (default: false)
|
|
31
|
+
- response_format (enum): Output format - "markdown" or "json" (default: "markdown")
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
{
|
|
35
|
+
"task_id": "abc-123-def",
|
|
36
|
+
"status": "PENDING",
|
|
37
|
+
"message": "Remesh task created...",
|
|
38
|
+
"estimated_time": "1-2 minutes"
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
Next Steps:
|
|
42
|
+
Use meshy_get_task_status with task_id and task_type="remesh" to check progress.
|
|
43
|
+
|
|
44
|
+
Examples:
|
|
45
|
+
- Remesh by task: { input_task_id: "abc-123", target_polycount: 10000 }
|
|
46
|
+
- Convert format: { model_url: "https://...", target_formats: ["fbx", "obj"], convert_format_only: true }
|
|
47
|
+
|
|
48
|
+
Error Handling:
|
|
49
|
+
- Returns "NotFound" if input_task_id doesn't exist
|
|
50
|
+
- Returns "InvalidModel" if model_url is not accessible`,
|
|
51
|
+
inputSchema: RemeshInputSchema,
|
|
52
|
+
outputSchema: TaskCreatedOutputSchema,
|
|
53
|
+
annotations: {
|
|
54
|
+
readOnlyHint: false,
|
|
55
|
+
destructiveHint: false,
|
|
56
|
+
idempotentHint: false,
|
|
57
|
+
openWorldHint: true
|
|
58
|
+
}
|
|
59
|
+
}, async (params) => {
|
|
60
|
+
try {
|
|
61
|
+
if (!params.input_task_id && !params.model_url) {
|
|
62
|
+
return {
|
|
63
|
+
isError: true,
|
|
64
|
+
content: [{
|
|
65
|
+
type: "text",
|
|
66
|
+
text: "Error: Either input_task_id or model_url must be provided."
|
|
67
|
+
}]
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
const request = {
|
|
71
|
+
target_formats: params.target_formats,
|
|
72
|
+
resize_height: params.resize_height,
|
|
73
|
+
convert_format_only: params.convert_format_only
|
|
74
|
+
};
|
|
75
|
+
if (params.input_task_id)
|
|
76
|
+
request.input_task_id = params.input_task_id;
|
|
77
|
+
if (params.model_url)
|
|
78
|
+
request.model_url = params.model_url;
|
|
79
|
+
if (params.topology)
|
|
80
|
+
request.topology = params.topology;
|
|
81
|
+
if (params.target_polycount)
|
|
82
|
+
request.target_polycount = params.target_polycount;
|
|
83
|
+
if (params.auto_size !== undefined)
|
|
84
|
+
request.auto_size = params.auto_size;
|
|
85
|
+
if (params.origin_at)
|
|
86
|
+
request.origin_at = params.origin_at;
|
|
87
|
+
const response = await client.post("/openapi/v1/remesh", request);
|
|
88
|
+
const taskId = response.result;
|
|
89
|
+
const output = {
|
|
90
|
+
task_id: taskId,
|
|
91
|
+
status: "PENDING",
|
|
92
|
+
message: `Remesh task created successfully. Task ID: ${taskId}`,
|
|
93
|
+
estimated_time: "1-2 minutes"
|
|
94
|
+
};
|
|
95
|
+
return formatTaskCreatedResponse(output, params.response_format, "Remesh Task Created", "Remeshing the model with the specified parameters.", "remesh");
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
return {
|
|
99
|
+
isError: true,
|
|
100
|
+
content: [{
|
|
101
|
+
type: "text",
|
|
102
|
+
text: handleMeshyError(error)
|
|
103
|
+
}]
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
// Retexture tool
|
|
108
|
+
server.registerTool("meshy_retexture", {
|
|
109
|
+
title: "Retexture 3D Model",
|
|
110
|
+
description: `Apply new AI-generated textures to an existing 3D model using Meshy AI.
|
|
111
|
+
|
|
112
|
+
IMPORTANT: Before calling this tool, ask the user to provide EITHER:
|
|
113
|
+
- text_style_prompt: A text description of the desired texture style (e.g. "rusty metal", "cartoon style")
|
|
114
|
+
- image_style_url: A reference image URL for the texture style
|
|
115
|
+
One of these is REQUIRED — the tool will fail without it.
|
|
116
|
+
If both are provided, image_style_url takes precedence.
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
- input_task_id (string, optional): Task ID of an existing completed task to retexture
|
|
120
|
+
- model_url (string, optional): Direct URL to a model file to retexture
|
|
121
|
+
(Provide either input_task_id or model_url)
|
|
122
|
+
- text_style_prompt (string): Text prompt describing the desired texture style. Max 600 characters. REQUIRED if image_style_url not provided.
|
|
123
|
+
- image_style_url (string): URL of an image to use as texture style reference. REQUIRED if text_style_prompt not provided. Takes precedence if both given.
|
|
124
|
+
- ai_model (enum): AI model - "meshy-5", "meshy-6", or "latest" (default). Ask user which model before proceeding
|
|
125
|
+
- enable_original_uv (boolean): Preserve original UV mapping (default: true)
|
|
126
|
+
- enable_pbr (boolean): Enable PBR textures (default: false)
|
|
127
|
+
- remove_lighting (boolean, optional): Remove highlights/shadows from base color texture. Default true. Only meshy-6/latest
|
|
128
|
+
- target_formats (string[], optional): Output formats. 3MF must be explicitly included if needed.
|
|
129
|
+
- response_format (enum): Output format - "markdown" or "json" (default: "markdown")
|
|
130
|
+
|
|
131
|
+
Returns:
|
|
132
|
+
{
|
|
133
|
+
"task_id": "abc-123-def",
|
|
134
|
+
"status": "PENDING",
|
|
135
|
+
"message": "Retexture task created...",
|
|
136
|
+
"estimated_time": "2-3 minutes"
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
Next Steps:
|
|
140
|
+
Use meshy_get_task_status with task_id and task_type="retexture" to check progress.
|
|
141
|
+
|
|
142
|
+
Examples:
|
|
143
|
+
- Text style: { input_task_id: "abc-123", text_style_prompt: "rusty metal" }
|
|
144
|
+
- Image style: { model_url: "https://...", image_style_url: "https://style-ref.jpg" }
|
|
145
|
+
|
|
146
|
+
Error Handling:
|
|
147
|
+
- Returns "NotFound" if input_task_id doesn't exist
|
|
148
|
+
- Returns error if neither text_style_prompt nor image_style_url is provided`,
|
|
149
|
+
inputSchema: RetextureInputSchema,
|
|
150
|
+
outputSchema: TaskCreatedOutputSchema,
|
|
151
|
+
annotations: {
|
|
152
|
+
readOnlyHint: false,
|
|
153
|
+
destructiveHint: false,
|
|
154
|
+
idempotentHint: false,
|
|
155
|
+
openWorldHint: true
|
|
156
|
+
}
|
|
157
|
+
}, async (params) => {
|
|
158
|
+
try {
|
|
159
|
+
if (!params.input_task_id && !params.model_url) {
|
|
160
|
+
return {
|
|
161
|
+
isError: true,
|
|
162
|
+
content: [{
|
|
163
|
+
type: "text",
|
|
164
|
+
text: "Error: Either input_task_id or model_url must be provided."
|
|
165
|
+
}]
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
if (!params.text_style_prompt && !params.image_style_url) {
|
|
169
|
+
return {
|
|
170
|
+
isError: true,
|
|
171
|
+
content: [{
|
|
172
|
+
type: "text",
|
|
173
|
+
text: "Error: Either text_style_prompt or image_style_url must be provided."
|
|
174
|
+
}]
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
const request = {
|
|
178
|
+
enable_original_uv: params.enable_original_uv,
|
|
179
|
+
enable_pbr: params.enable_pbr
|
|
180
|
+
};
|
|
181
|
+
if (params.input_task_id)
|
|
182
|
+
request.input_task_id = params.input_task_id;
|
|
183
|
+
if (params.model_url)
|
|
184
|
+
request.model_url = params.model_url;
|
|
185
|
+
if (params.text_style_prompt)
|
|
186
|
+
request.text_style_prompt = params.text_style_prompt;
|
|
187
|
+
if (params.image_style_url)
|
|
188
|
+
request.image_style_url = params.image_style_url;
|
|
189
|
+
if (params.ai_model)
|
|
190
|
+
request.ai_model = params.ai_model;
|
|
191
|
+
if (params.remove_lighting !== undefined)
|
|
192
|
+
request.remove_lighting = params.remove_lighting;
|
|
193
|
+
if (params.target_formats)
|
|
194
|
+
request.target_formats = params.target_formats;
|
|
195
|
+
const response = await client.post("/openapi/v1/retexture", request);
|
|
196
|
+
const taskId = response.result;
|
|
197
|
+
const output = {
|
|
198
|
+
task_id: taskId,
|
|
199
|
+
status: "PENDING",
|
|
200
|
+
message: `Retexture task created successfully. Task ID: ${taskId}`,
|
|
201
|
+
estimated_time: "2-3 minutes"
|
|
202
|
+
};
|
|
203
|
+
return formatTaskCreatedResponse(output, params.response_format, "Retexture Task Created", "Applying new textures to the model.", "retexture");
|
|
204
|
+
}
|
|
205
|
+
catch (error) {
|
|
206
|
+
return {
|
|
207
|
+
isError: true,
|
|
208
|
+
content: [{
|
|
209
|
+
type: "text",
|
|
210
|
+
text: handleMeshyError(error)
|
|
211
|
+
}]
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
// Rig tool
|
|
216
|
+
server.registerTool("meshy_rig", {
|
|
217
|
+
title: "Auto-Rig 3D Character",
|
|
218
|
+
description: `Automatically rig a 3D character model for animation using Meshy AI.
|
|
219
|
+
|
|
220
|
+
Creates a skeletal rig for character models, enabling them to be animated. Rigging INCLUDES free walking + running animations.
|
|
221
|
+
|
|
222
|
+
IMPORTANT: The source model should be generated with pose_mode="t-pose" for best rigging results. When the user asks to rig or animate, always ensure the generation step used t-pose. If the model was not generated with t-pose, recommend regenerating with pose_mode="t-pose" first.
|
|
223
|
+
|
|
224
|
+
CONSTRAINT: Model must have ≤300,000 faces. This tool auto-checks and suggests remeshing if exceeded.
|
|
225
|
+
|
|
226
|
+
Args:
|
|
227
|
+
- input_task_id (string, optional): Task ID of an existing completed task to rig
|
|
228
|
+
- model_url (string, optional): Direct URL to a model file to rig
|
|
229
|
+
(Provide either input_task_id or model_url)
|
|
230
|
+
- height_meters (number, optional): Height of the character in meters (default: 1.7)
|
|
231
|
+
- texture_image_url (string, optional): URL of a texture image to apply to the model
|
|
232
|
+
- response_format (enum): Output format - "markdown" or "json" (default: "markdown")
|
|
233
|
+
|
|
234
|
+
Returns:
|
|
235
|
+
{
|
|
236
|
+
"task_id": "abc-123-def",
|
|
237
|
+
"status": "PENDING",
|
|
238
|
+
"message": "Rigging task created...",
|
|
239
|
+
"estimated_time": "2-3 minutes"
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
Included with rigging (FREE):
|
|
243
|
+
- Walking animation (GLB + FBX)
|
|
244
|
+
- Running animation (GLB + FBX)
|
|
245
|
+
Only call meshy_animate (3 credits) for CUSTOM animations beyond walking/running.
|
|
246
|
+
|
|
247
|
+
Examples:
|
|
248
|
+
- Basic rig: { input_task_id: "abc-123" }
|
|
249
|
+
- With height: { model_url: "https://...", height_meters: 1.8 }
|
|
250
|
+
|
|
251
|
+
Error Handling:
|
|
252
|
+
- Returns "NotFound" if input_task_id doesn't exist
|
|
253
|
+
- Returns error if model exceeds 300K faces (suggests remeshing)
|
|
254
|
+
- Returns error if model is not suitable for rigging`,
|
|
255
|
+
inputSchema: RigInputSchema,
|
|
256
|
+
outputSchema: TaskCreatedOutputSchema,
|
|
257
|
+
annotations: {
|
|
258
|
+
readOnlyHint: false,
|
|
259
|
+
destructiveHint: false,
|
|
260
|
+
idempotentHint: false,
|
|
261
|
+
openWorldHint: true
|
|
262
|
+
}
|
|
263
|
+
}, async (params) => {
|
|
264
|
+
try {
|
|
265
|
+
if (!params.input_task_id && !params.model_url) {
|
|
266
|
+
return {
|
|
267
|
+
isError: true,
|
|
268
|
+
content: [{
|
|
269
|
+
type: "text",
|
|
270
|
+
text: "Error: Either input_task_id or model_url must be provided."
|
|
271
|
+
}]
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
// Pre-validate face count for rigging constraint
|
|
275
|
+
if (params.input_task_id) {
|
|
276
|
+
try {
|
|
277
|
+
const result = await fetchTaskByIdFromKnownEndpoints(client, params.input_task_id);
|
|
278
|
+
const sourceTask = result?.task;
|
|
279
|
+
if (sourceTask?.face_count && sourceTask.face_count > RIGGING_MAX_FACES) {
|
|
280
|
+
const faceCount = sourceTask.face_count.toLocaleString();
|
|
281
|
+
const maxFaces = RIGGING_MAX_FACES.toLocaleString();
|
|
282
|
+
return {
|
|
283
|
+
content: [{
|
|
284
|
+
type: "text",
|
|
285
|
+
text: `# Rigging Blocked: Face Count Too High
|
|
286
|
+
|
|
287
|
+
**Model faces**: ${faceCount}
|
|
288
|
+
**Maximum allowed**: ${maxFaces}
|
|
289
|
+
|
|
290
|
+
The model exceeds the ${maxFaces}-face limit for rigging.
|
|
291
|
+
|
|
292
|
+
**How to fix**:
|
|
293
|
+
1. Call \`meshy_remesh\` with input_task_id "${params.input_task_id}" and target_polycount 100000
|
|
294
|
+
2. Wait for remesh to complete (use \`meshy_get_task_status\` with task_type "remesh")
|
|
295
|
+
3. Then call \`meshy_rig\` with the remeshed task's ID`
|
|
296
|
+
}]
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
catch {
|
|
301
|
+
// If we can't fetch the source task, proceed anyway — the API will catch it
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
const request = {
|
|
305
|
+
height_meters: params.height_meters
|
|
306
|
+
};
|
|
307
|
+
if (params.input_task_id)
|
|
308
|
+
request.input_task_id = params.input_task_id;
|
|
309
|
+
if (params.model_url)
|
|
310
|
+
request.model_url = params.model_url;
|
|
311
|
+
if (params.texture_image_url)
|
|
312
|
+
request.texture_image_url = params.texture_image_url;
|
|
313
|
+
const response = await client.post("/openapi/v1/rigging", request);
|
|
314
|
+
const taskId = response.result;
|
|
315
|
+
const output = {
|
|
316
|
+
task_id: taskId,
|
|
317
|
+
status: "PENDING",
|
|
318
|
+
message: `Rigging task created successfully. Task ID: ${taskId}`,
|
|
319
|
+
estimated_time: "2-3 minutes"
|
|
320
|
+
};
|
|
321
|
+
return formatTaskCreatedResponse(output, params.response_format, "Rigging Task Created", `Rigging INCLUDES walking + running animations for free. Download with \`meshy_download_model\` (task_type "rigging").\nOnly call \`meshy_animate\` (3 credits) for CUSTOM animations beyond walking/running.`, "rigging");
|
|
322
|
+
}
|
|
323
|
+
catch (error) {
|
|
324
|
+
return {
|
|
325
|
+
isError: true,
|
|
326
|
+
content: [{
|
|
327
|
+
type: "text",
|
|
328
|
+
text: handleMeshyError(error, { tool: "meshy_rig", taskId: params.input_task_id })
|
|
329
|
+
}]
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
// Animate tool
|
|
334
|
+
server.registerTool("meshy_animate", {
|
|
335
|
+
title: "Animate Rigged 3D Character",
|
|
336
|
+
description: `Apply a CUSTOM animation to a rigged 3D character using Meshy AI. Cost: 3 credits.
|
|
337
|
+
|
|
338
|
+
NOTE: Walking and running animations are already FREE with meshy_rig. Only use this tool for CUSTOM animations (dancing, jumping, fighting, etc.) that are NOT included in rigging.
|
|
339
|
+
|
|
340
|
+
Applies a predefined animation action to a character that has been rigged with meshy_rig.
|
|
341
|
+
|
|
342
|
+
Args:
|
|
343
|
+
- rig_task_id (string): Task ID of the completed rigging task (required)
|
|
344
|
+
- action_id (number): Integer ID of the animation action to apply (required)
|
|
345
|
+
- post_process (object, optional): Optional post-processing to apply after animation:
|
|
346
|
+
- operation_type (enum): "change_fps", "fbx2usdz", or "extract_armature"
|
|
347
|
+
- fps (number, optional): Target FPS for change_fps operation (24, 25, 30, or 60)
|
|
348
|
+
- response_format (enum): Output format - "markdown" or "json" (default: "markdown")
|
|
349
|
+
|
|
350
|
+
Returns:
|
|
351
|
+
{
|
|
352
|
+
"task_id": "abc-123-def",
|
|
353
|
+
"status": "PENDING",
|
|
354
|
+
"message": "Animation task created...",
|
|
355
|
+
"estimated_time": "1-2 minutes"
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
Next Steps:
|
|
359
|
+
Use meshy_get_task_status with task_id and task_type="animation" to check progress.
|
|
360
|
+
|
|
361
|
+
Examples:
|
|
362
|
+
- Basic animate: { rig_task_id: "abc-123", action_id: 1 }
|
|
363
|
+
- With FPS change: { rig_task_id: "abc-123", action_id: 1, post_process: { operation_type: "change_fps", fps: 30 } }
|
|
364
|
+
|
|
365
|
+
Error Handling:
|
|
366
|
+
- Returns "NotFound" if rig_task_id doesn't exist
|
|
367
|
+
- Returns error if rig task is not yet completed`,
|
|
368
|
+
inputSchema: AnimateInputSchema,
|
|
369
|
+
outputSchema: TaskCreatedOutputSchema,
|
|
370
|
+
annotations: {
|
|
371
|
+
readOnlyHint: false,
|
|
372
|
+
destructiveHint: false,
|
|
373
|
+
idempotentHint: false,
|
|
374
|
+
openWorldHint: true
|
|
375
|
+
}
|
|
376
|
+
}, async (params) => {
|
|
377
|
+
try {
|
|
378
|
+
const request = {
|
|
379
|
+
rig_task_id: params.rig_task_id,
|
|
380
|
+
action_id: params.action_id
|
|
381
|
+
};
|
|
382
|
+
if (params.post_process) {
|
|
383
|
+
request.post_process = params.post_process;
|
|
384
|
+
}
|
|
385
|
+
const response = await client.post("/openapi/v1/animations", request);
|
|
386
|
+
const taskId = response.result;
|
|
387
|
+
const output = {
|
|
388
|
+
task_id: taskId,
|
|
389
|
+
status: "PENDING",
|
|
390
|
+
message: `Animation task created successfully. Task ID: ${taskId}`,
|
|
391
|
+
estimated_time: "1-2 minutes"
|
|
392
|
+
};
|
|
393
|
+
return formatTaskCreatedResponse(output, params.response_format, "Animation Task Created", "Applying custom animation to the rigged character.", "animation");
|
|
394
|
+
}
|
|
395
|
+
catch (error) {
|
|
396
|
+
return {
|
|
397
|
+
isError: true,
|
|
398
|
+
content: [{
|
|
399
|
+
type: "text",
|
|
400
|
+
text: handleMeshyError(error)
|
|
401
|
+
}]
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
});
|
|
405
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 3D printing tools (send to slicer, analyze printability, process multicolor)
|
|
3
|
+
*/
|
|
4
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
5
|
+
import { MeshyClient } from "../services/meshy-client.js";
|
|
6
|
+
/**
|
|
7
|
+
* Register 3D printing tools with the MCP server
|
|
8
|
+
*/
|
|
9
|
+
export declare function registerPrintingTools(server: McpServer, client: MeshyClient): void;
|