@codingmantra/mcp-server 0.1.1 → 0.1.3
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 +3 -3
- package/build/index.js +143 -0
- package/package.json +1 -1
- package/src/index.ts +154 -0
package/README.md
CHANGED
|
@@ -4,9 +4,9 @@ A **Model Context Protocol (MCP)** server that connects AI agents (like Claude D
|
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
- **Product Photography** — Generate AI studio product photos with custom scenes
|
|
8
|
-
- **Logo Creator** — Generate AI brand logos with style and color customization
|
|
9
|
-
- **QR Code Generator** — Create custom QR codes (URL, text, WiFi, vCard, UPI, email)
|
|
7
|
+
- **Product Photography** — Generate AI studio product photos with custom scenes, resolutions, templates, and dynamic logo/text overlays.
|
|
8
|
+
- **Logo Creator** — Generate AI brand logos with style, resolution, references, and color customization.
|
|
9
|
+
- **QR Code Generator** — Create custom QR codes (URL, text, WiFi, vCard, UPI, email) with branding and colors.
|
|
10
10
|
|
|
11
11
|
## Setup
|
|
12
12
|
|
package/build/index.js
CHANGED
|
@@ -48,6 +48,30 @@ const GENERATE_PRODUCT_PHOTO_TOOL = {
|
|
|
48
48
|
referenceImage: {
|
|
49
49
|
type: "string",
|
|
50
50
|
description: "An optional URL or data URI of a reference image to guide style."
|
|
51
|
+
},
|
|
52
|
+
promptId: {
|
|
53
|
+
type: "string",
|
|
54
|
+
description: "Optional ID of a pre-defined prompt template."
|
|
55
|
+
},
|
|
56
|
+
logoImage: {
|
|
57
|
+
type: "string",
|
|
58
|
+
description: "Optional URL or Base64 data URI of a logo to place on the image."
|
|
59
|
+
},
|
|
60
|
+
logoPlacement: {
|
|
61
|
+
type: "string",
|
|
62
|
+
description: "Where to place the logo (e.g., 'top-left', 'bottom-right')."
|
|
63
|
+
},
|
|
64
|
+
logoSize: {
|
|
65
|
+
type: "number",
|
|
66
|
+
description: "Scale of the logo overlay (0.1 to 1.0)."
|
|
67
|
+
},
|
|
68
|
+
overlayText: {
|
|
69
|
+
type: "string",
|
|
70
|
+
description: "Optional text to overlay on the image."
|
|
71
|
+
},
|
|
72
|
+
marketingText: {
|
|
73
|
+
type: "string",
|
|
74
|
+
description: "Optional marketing text to overlay."
|
|
51
75
|
}
|
|
52
76
|
},
|
|
53
77
|
required: ["productImages", "scenePrompt"]
|
|
@@ -94,6 +118,14 @@ const GENERATE_LOGO_TOOL = {
|
|
|
94
118
|
resolution: {
|
|
95
119
|
type: "string",
|
|
96
120
|
description: "Output resolution (e.g., '1K', '2K'). Default is '1K'.",
|
|
121
|
+
},
|
|
122
|
+
promptId: {
|
|
123
|
+
type: "string",
|
|
124
|
+
description: "Optional ID or value of a pre-defined style template."
|
|
125
|
+
},
|
|
126
|
+
referenceImage: {
|
|
127
|
+
type: "string",
|
|
128
|
+
description: "An optional general style reference image URL or data URI."
|
|
97
129
|
}
|
|
98
130
|
},
|
|
99
131
|
required: ["companyName", "stylePrompt"]
|
|
@@ -149,6 +181,64 @@ const GENERATE_QR_CODE_SIMPLE_TOOL = {
|
|
|
149
181
|
required: ["text"]
|
|
150
182
|
}
|
|
151
183
|
};
|
|
184
|
+
const COMMON_VIDEO_PROPERTIES = {
|
|
185
|
+
prompt: { type: "string", description: "Detailed video description or prompt." },
|
|
186
|
+
mainImage: { type: "string", description: "Base64 data URI or URL for the main image (Image-to-Video mode)." },
|
|
187
|
+
startImage: { type: "string", description: "Base64 data URI or URL for the first frame." },
|
|
188
|
+
endImage: { type: "string", description: "Base64 data URI or URL for the last frame." },
|
|
189
|
+
referenceImages: {
|
|
190
|
+
type: "array",
|
|
191
|
+
items: { type: "object", properties: { image: { type: "string" }, label: { type: "string" } } },
|
|
192
|
+
description: "Array of reference images for style matching."
|
|
193
|
+
},
|
|
194
|
+
negativePrompt: { type: "string", description: "Elements to exclude from the video." },
|
|
195
|
+
dialogue: { type: "string", description: "Optional voiceover or dialogue." },
|
|
196
|
+
soundSuggestion: { type: "string", description: "Background music or sound effects." },
|
|
197
|
+
cameraMotion: { type: "string", description: "Camera motion instructions." },
|
|
198
|
+
ambientNoise: { type: "string", description: "Ambient sound description." },
|
|
199
|
+
language: { type: "string", description: "Voiceover language." },
|
|
200
|
+
timeDuration: { type: "string", description: "Video duration in seconds. Default is '4'." },
|
|
201
|
+
resolution: { type: "string", description: "Resolution (e.g., '720p', '1080p'). Default is '720p'." },
|
|
202
|
+
model: { type: "string", description: "Model slug (e.g., 'google/veo-3.1-fast', 'openrouter/wan-2.7')." },
|
|
203
|
+
aspectRatio: { type: "string", description: "Aspect ratio (e.g., '9:16', '16:9'). Default is '9:16'." },
|
|
204
|
+
generateAudio: { type: "boolean", description: "Whether to generate audio. Default is false." }
|
|
205
|
+
};
|
|
206
|
+
const GENERATE_PRODUCT_VIDEO_TOOL = {
|
|
207
|
+
name: "generate_product_video",
|
|
208
|
+
description: "Generates a product video. Asynchronous: returns a jobId. You MUST use check_video_job_status with the jobId to poll for completion. Automatically deducts credits.",
|
|
209
|
+
inputSchema: { type: "object", properties: COMMON_VIDEO_PROPERTIES }
|
|
210
|
+
};
|
|
211
|
+
const GENERATE_APPAREL_VIDEO_TOOL = {
|
|
212
|
+
name: "generate_apparel_video",
|
|
213
|
+
description: "Generates an apparel try-on video. Asynchronous: returns a jobId. You MUST use check_video_job_status with the jobId to poll for completion. Automatically deducts credits.",
|
|
214
|
+
inputSchema: { type: "object", properties: COMMON_VIDEO_PROPERTIES }
|
|
215
|
+
};
|
|
216
|
+
const GENERATE_FESTIVAL_VIDEO_TOOL = {
|
|
217
|
+
name: "generate_festival_video",
|
|
218
|
+
description: "Generates a festival or event video. Asynchronous: returns a jobId. You MUST use check_video_job_status with the jobId to poll for completion. Automatically deducts credits.",
|
|
219
|
+
inputSchema: { type: "object", properties: COMMON_VIDEO_PROPERTIES }
|
|
220
|
+
};
|
|
221
|
+
const GENERATE_JEWELRY_VIDEO_TOOL = {
|
|
222
|
+
name: "generate_jewelry_video",
|
|
223
|
+
description: "Generates a jewelry showcase video. Asynchronous: returns a jobId. You MUST use check_video_job_status with the jobId to poll for completion. Automatically deducts credits.",
|
|
224
|
+
inputSchema: { type: "object", properties: COMMON_VIDEO_PROPERTIES }
|
|
225
|
+
};
|
|
226
|
+
const GENERATE_LOGO_VIDEO_TOOL = {
|
|
227
|
+
name: "generate_logo_video",
|
|
228
|
+
description: "Generates a logo animation video. Asynchronous: returns a jobId. You MUST use check_video_job_status with the jobId to poll for completion. Automatically deducts credits.",
|
|
229
|
+
inputSchema: { type: "object", properties: COMMON_VIDEO_PROPERTIES }
|
|
230
|
+
};
|
|
231
|
+
const CHECK_JOB_STATUS_TOOL = {
|
|
232
|
+
name: "check_video_job_status",
|
|
233
|
+
description: "Checks the status of an asynchronous video generation job. Call this repeatedly (e.g. every 10-30 seconds) until the job status is 'completed' or 'failed'.",
|
|
234
|
+
inputSchema: {
|
|
235
|
+
type: "object",
|
|
236
|
+
properties: {
|
|
237
|
+
jobId: { type: "string", description: "The ID of the job to check." }
|
|
238
|
+
},
|
|
239
|
+
required: ["jobId"]
|
|
240
|
+
}
|
|
241
|
+
};
|
|
152
242
|
// ─── Tool Registration ─────────────────────────────────────────────────────────
|
|
153
243
|
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
154
244
|
return {
|
|
@@ -157,6 +247,12 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
157
247
|
GENERATE_LOGO_TOOL,
|
|
158
248
|
GENERATE_QR_CODE_TOOL,
|
|
159
249
|
GENERATE_QR_CODE_SIMPLE_TOOL,
|
|
250
|
+
GENERATE_PRODUCT_VIDEO_TOOL,
|
|
251
|
+
GENERATE_APPAREL_VIDEO_TOOL,
|
|
252
|
+
GENERATE_FESTIVAL_VIDEO_TOOL,
|
|
253
|
+
GENERATE_JEWELRY_VIDEO_TOOL,
|
|
254
|
+
GENERATE_LOGO_VIDEO_TOOL,
|
|
255
|
+
CHECK_JOB_STATUS_TOOL,
|
|
160
256
|
],
|
|
161
257
|
};
|
|
162
258
|
});
|
|
@@ -242,6 +338,53 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
242
338
|
content: [{ type: "text", text: `✅ QR Code generated. Result: ${JSON.stringify(response.data).substring(0, 500)}` }],
|
|
243
339
|
};
|
|
244
340
|
}
|
|
341
|
+
// ── Video Generation (Asynchronous) ──────────────────────────────────────
|
|
342
|
+
const videoEndpoints = {
|
|
343
|
+
generate_product_video: '/product-video-generation',
|
|
344
|
+
generate_apparel_video: '/apparel-video-generation',
|
|
345
|
+
generate_festival_video: '/festival-video-generation',
|
|
346
|
+
generate_jewelry_video: '/jewelry-video-generation',
|
|
347
|
+
generate_logo_video: '/logo-video-generation'
|
|
348
|
+
};
|
|
349
|
+
if (videoEndpoints[name]) {
|
|
350
|
+
const response = await apiClient(videoEndpoints[name], {
|
|
351
|
+
method: 'POST',
|
|
352
|
+
body: JSON.stringify(args),
|
|
353
|
+
});
|
|
354
|
+
const result = response.data || response;
|
|
355
|
+
if (result?.jobId) {
|
|
356
|
+
return {
|
|
357
|
+
content: [{
|
|
358
|
+
type: "text",
|
|
359
|
+
text: `✅ Job created successfully!\nJob ID: ${result.jobId}\nMessage: ${result.message}\n\nPlease use the check_video_job_status tool with this Job ID to poll for the result. Wait about 10-30 seconds between polls. Video generation can take several minutes.`
|
|
360
|
+
}]
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
return { content: [{ type: "text", text: `Job started. Result: ${JSON.stringify(result).substring(0, 500)}` }] };
|
|
364
|
+
}
|
|
365
|
+
// ── Check Job Status ─────────────────────────────────────────────────────
|
|
366
|
+
if (name === 'check_video_job_status') {
|
|
367
|
+
const { jobId } = args;
|
|
368
|
+
const response = await apiClient(`/jobs/status?jobId=${encodeURIComponent(jobId)}`, {
|
|
369
|
+
method: 'GET',
|
|
370
|
+
});
|
|
371
|
+
const result = response.data || response;
|
|
372
|
+
if (result?.job) {
|
|
373
|
+
const job = result.job;
|
|
374
|
+
let text = `Job Status: ${job.status}\nProgress: ${job.progress}%\nStage: ${job.stage || 'N/A'}`;
|
|
375
|
+
if (job.status === 'completed' && job.result?.videoUrl) {
|
|
376
|
+
text += `\n\n✅ Video generated successfully!\nVideo URL: ${job.result.videoUrl}`;
|
|
377
|
+
}
|
|
378
|
+
else if (job.status === 'failed') {
|
|
379
|
+
text += `\n\n❌ Job failed: ${job.error || 'Unknown error'}`;
|
|
380
|
+
}
|
|
381
|
+
else {
|
|
382
|
+
text += `\n\nJob is still running. Please check back again shortly.`;
|
|
383
|
+
}
|
|
384
|
+
return { content: [{ type: "text", text }] };
|
|
385
|
+
}
|
|
386
|
+
return { content: [{ type: "text", text: `Status check result: ${JSON.stringify(result).substring(0, 500)}` }] };
|
|
387
|
+
}
|
|
245
388
|
throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
|
|
246
389
|
}
|
|
247
390
|
catch (error) {
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -55,6 +55,30 @@ const GENERATE_PRODUCT_PHOTO_TOOL = {
|
|
|
55
55
|
referenceImage: {
|
|
56
56
|
type: "string",
|
|
57
57
|
description: "An optional URL or data URI of a reference image to guide style."
|
|
58
|
+
},
|
|
59
|
+
promptId: {
|
|
60
|
+
type: "string",
|
|
61
|
+
description: "Optional ID of a pre-defined prompt template."
|
|
62
|
+
},
|
|
63
|
+
logoImage: {
|
|
64
|
+
type: "string",
|
|
65
|
+
description: "Optional URL or Base64 data URI of a logo to place on the image."
|
|
66
|
+
},
|
|
67
|
+
logoPlacement: {
|
|
68
|
+
type: "string",
|
|
69
|
+
description: "Where to place the logo (e.g., 'top-left', 'bottom-right')."
|
|
70
|
+
},
|
|
71
|
+
logoSize: {
|
|
72
|
+
type: "number",
|
|
73
|
+
description: "Scale of the logo overlay (0.1 to 1.0)."
|
|
74
|
+
},
|
|
75
|
+
overlayText: {
|
|
76
|
+
type: "string",
|
|
77
|
+
description: "Optional text to overlay on the image."
|
|
78
|
+
},
|
|
79
|
+
marketingText: {
|
|
80
|
+
type: "string",
|
|
81
|
+
description: "Optional marketing text to overlay."
|
|
58
82
|
}
|
|
59
83
|
},
|
|
60
84
|
required: ["productImages", "scenePrompt"]
|
|
@@ -102,6 +126,14 @@ const GENERATE_LOGO_TOOL = {
|
|
|
102
126
|
resolution: {
|
|
103
127
|
type: "string",
|
|
104
128
|
description: "Output resolution (e.g., '1K', '2K'). Default is '1K'.",
|
|
129
|
+
},
|
|
130
|
+
promptId: {
|
|
131
|
+
type: "string",
|
|
132
|
+
description: "Optional ID or value of a pre-defined style template."
|
|
133
|
+
},
|
|
134
|
+
referenceImage: {
|
|
135
|
+
type: "string",
|
|
136
|
+
description: "An optional general style reference image URL or data URI."
|
|
105
137
|
}
|
|
106
138
|
},
|
|
107
139
|
required: ["companyName", "stylePrompt"]
|
|
@@ -160,6 +192,71 @@ const GENERATE_QR_CODE_SIMPLE_TOOL = {
|
|
|
160
192
|
}
|
|
161
193
|
};
|
|
162
194
|
|
|
195
|
+
const COMMON_VIDEO_PROPERTIES = {
|
|
196
|
+
prompt: { type: "string", description: "Detailed video description or prompt." },
|
|
197
|
+
mainImage: { type: "string", description: "Base64 data URI or URL for the main image (Image-to-Video mode)." },
|
|
198
|
+
startImage: { type: "string", description: "Base64 data URI or URL for the first frame." },
|
|
199
|
+
endImage: { type: "string", description: "Base64 data URI or URL for the last frame." },
|
|
200
|
+
referenceImages: {
|
|
201
|
+
type: "array",
|
|
202
|
+
items: { type: "object", properties: { image: { type: "string" }, label: { type: "string" } } },
|
|
203
|
+
description: "Array of reference images for style matching."
|
|
204
|
+
},
|
|
205
|
+
negativePrompt: { type: "string", description: "Elements to exclude from the video." },
|
|
206
|
+
dialogue: { type: "string", description: "Optional voiceover or dialogue." },
|
|
207
|
+
soundSuggestion: { type: "string", description: "Background music or sound effects." },
|
|
208
|
+
cameraMotion: { type: "string", description: "Camera motion instructions." },
|
|
209
|
+
ambientNoise: { type: "string", description: "Ambient sound description." },
|
|
210
|
+
language: { type: "string", description: "Voiceover language." },
|
|
211
|
+
timeDuration: { type: "string", description: "Video duration in seconds. Default is '4'." },
|
|
212
|
+
resolution: { type: "string", description: "Resolution (e.g., '720p', '1080p'). Default is '720p'." },
|
|
213
|
+
model: { type: "string", description: "Model slug (e.g., 'google/veo-3.1-fast', 'openrouter/wan-2.7')." },
|
|
214
|
+
aspectRatio: { type: "string", description: "Aspect ratio (e.g., '9:16', '16:9'). Default is '9:16'." },
|
|
215
|
+
generateAudio: { type: "boolean", description: "Whether to generate audio. Default is false." }
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
const GENERATE_PRODUCT_VIDEO_TOOL = {
|
|
219
|
+
name: "generate_product_video",
|
|
220
|
+
description: "Generates a product video. Asynchronous: returns a jobId. You MUST use check_video_job_status with the jobId to poll for completion. Automatically deducts credits.",
|
|
221
|
+
inputSchema: { type: "object" as const, properties: COMMON_VIDEO_PROPERTIES }
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
const GENERATE_APPAREL_VIDEO_TOOL = {
|
|
225
|
+
name: "generate_apparel_video",
|
|
226
|
+
description: "Generates an apparel try-on video. Asynchronous: returns a jobId. You MUST use check_video_job_status with the jobId to poll for completion. Automatically deducts credits.",
|
|
227
|
+
inputSchema: { type: "object" as const, properties: COMMON_VIDEO_PROPERTIES }
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
const GENERATE_FESTIVAL_VIDEO_TOOL = {
|
|
231
|
+
name: "generate_festival_video",
|
|
232
|
+
description: "Generates a festival or event video. Asynchronous: returns a jobId. You MUST use check_video_job_status with the jobId to poll for completion. Automatically deducts credits.",
|
|
233
|
+
inputSchema: { type: "object" as const, properties: COMMON_VIDEO_PROPERTIES }
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
const GENERATE_JEWELRY_VIDEO_TOOL = {
|
|
237
|
+
name: "generate_jewelry_video",
|
|
238
|
+
description: "Generates a jewelry showcase video. Asynchronous: returns a jobId. You MUST use check_video_job_status with the jobId to poll for completion. Automatically deducts credits.",
|
|
239
|
+
inputSchema: { type: "object" as const, properties: COMMON_VIDEO_PROPERTIES }
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
const GENERATE_LOGO_VIDEO_TOOL = {
|
|
243
|
+
name: "generate_logo_video",
|
|
244
|
+
description: "Generates a logo animation video. Asynchronous: returns a jobId. You MUST use check_video_job_status with the jobId to poll for completion. Automatically deducts credits.",
|
|
245
|
+
inputSchema: { type: "object" as const, properties: COMMON_VIDEO_PROPERTIES }
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
const CHECK_JOB_STATUS_TOOL = {
|
|
249
|
+
name: "check_video_job_status",
|
|
250
|
+
description: "Checks the status of an asynchronous video generation job. Call this repeatedly (e.g. every 10-30 seconds) until the job status is 'completed' or 'failed'.",
|
|
251
|
+
inputSchema: {
|
|
252
|
+
type: "object" as const,
|
|
253
|
+
properties: {
|
|
254
|
+
jobId: { type: "string", description: "The ID of the job to check." }
|
|
255
|
+
},
|
|
256
|
+
required: ["jobId"]
|
|
257
|
+
}
|
|
258
|
+
};
|
|
259
|
+
|
|
163
260
|
// ─── Tool Registration ─────────────────────────────────────────────────────────
|
|
164
261
|
|
|
165
262
|
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
@@ -169,6 +266,12 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
169
266
|
GENERATE_LOGO_TOOL,
|
|
170
267
|
GENERATE_QR_CODE_TOOL,
|
|
171
268
|
GENERATE_QR_CODE_SIMPLE_TOOL,
|
|
269
|
+
GENERATE_PRODUCT_VIDEO_TOOL,
|
|
270
|
+
GENERATE_APPAREL_VIDEO_TOOL,
|
|
271
|
+
GENERATE_FESTIVAL_VIDEO_TOOL,
|
|
272
|
+
GENERATE_JEWELRY_VIDEO_TOOL,
|
|
273
|
+
GENERATE_LOGO_VIDEO_TOOL,
|
|
274
|
+
CHECK_JOB_STATUS_TOOL,
|
|
172
275
|
],
|
|
173
276
|
};
|
|
174
277
|
});
|
|
@@ -263,6 +366,57 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
263
366
|
};
|
|
264
367
|
}
|
|
265
368
|
|
|
369
|
+
// ── Video Generation (Asynchronous) ──────────────────────────────────────
|
|
370
|
+
const videoEndpoints: Record<string, string> = {
|
|
371
|
+
generate_product_video: '/product-video-generation',
|
|
372
|
+
generate_apparel_video: '/apparel-video-generation',
|
|
373
|
+
generate_festival_video: '/festival-video-generation',
|
|
374
|
+
generate_jewelry_video: '/jewelry-video-generation',
|
|
375
|
+
generate_logo_video: '/logo-video-generation'
|
|
376
|
+
};
|
|
377
|
+
|
|
378
|
+
if (videoEndpoints[name]) {
|
|
379
|
+
const response = await apiClient(videoEndpoints[name], {
|
|
380
|
+
method: 'POST',
|
|
381
|
+
body: JSON.stringify(args),
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
const result = response.data || response;
|
|
385
|
+
if (result?.jobId) {
|
|
386
|
+
return {
|
|
387
|
+
content: [{
|
|
388
|
+
type: "text",
|
|
389
|
+
text: `✅ Job created successfully!\nJob ID: ${result.jobId}\nMessage: ${result.message}\n\nPlease use the check_video_job_status tool with this Job ID to poll for the result. Wait about 10-30 seconds between polls. Video generation can take several minutes.`
|
|
390
|
+
}]
|
|
391
|
+
};
|
|
392
|
+
}
|
|
393
|
+
return { content: [{ type: "text", text: `Job started. Result: ${JSON.stringify(result).substring(0, 500)}` }] };
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// ── Check Job Status ─────────────────────────────────────────────────────
|
|
397
|
+
if (name === 'check_video_job_status') {
|
|
398
|
+
const { jobId } = args as { jobId: string };
|
|
399
|
+
const response = await apiClient(`/jobs/status?jobId=${encodeURIComponent(jobId)}`, {
|
|
400
|
+
method: 'GET',
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
const result = response.data || response;
|
|
404
|
+
if (result?.job) {
|
|
405
|
+
const job = result.job;
|
|
406
|
+
let text = `Job Status: ${job.status}\nProgress: ${job.progress}%\nStage: ${job.stage || 'N/A'}`;
|
|
407
|
+
|
|
408
|
+
if (job.status === 'completed' && job.result?.videoUrl) {
|
|
409
|
+
text += `\n\n✅ Video generated successfully!\nVideo URL: ${job.result.videoUrl}`;
|
|
410
|
+
} else if (job.status === 'failed') {
|
|
411
|
+
text += `\n\n❌ Job failed: ${job.error || 'Unknown error'}`;
|
|
412
|
+
} else {
|
|
413
|
+
text += `\n\nJob is still running. Please check back again shortly.`;
|
|
414
|
+
}
|
|
415
|
+
return { content: [{ type: "text", text }] };
|
|
416
|
+
}
|
|
417
|
+
return { content: [{ type: "text", text: `Status check result: ${JSON.stringify(result).substring(0, 500)}` }] };
|
|
418
|
+
}
|
|
419
|
+
|
|
266
420
|
throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
|
|
267
421
|
} catch (error: any) {
|
|
268
422
|
return {
|