@mixio-pro/kalaasetu-mcp 2.0.1-beta → 2.0.2-beta

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mixio-pro/kalaasetu-mcp",
3
- "version": "2.0.1-beta",
3
+ "version": "2.0.2-beta",
4
4
  "description": "A powerful Model Context Protocol server providing AI tools for content generation and analysis",
5
5
  "type": "module",
6
6
  "module": "src/index.ts",
package/src/index.ts CHANGED
@@ -36,11 +36,16 @@ server.addTool(imageToVideo);
36
36
  // server.addTool(perplexityImages);
37
37
  // server.addTool(perplexityVideos);
38
38
 
39
+ import { getGenerationStatus } from "./tools/get-status";
40
+
39
41
  // Fal AI Tools
40
42
  server.addTool(falListPresets);
41
43
  server.addTool(falGenerate);
42
44
  server.addTool(falUploadFile);
43
45
 
46
+ // Unified Status Tool (works with both FAL and Vertex AI)
47
+ server.addTool(getGenerationStatus);
48
+
44
49
  server.start({
45
50
  transportType: "stdio",
46
51
  });
@@ -119,7 +119,7 @@ export const falGenerate = {
119
119
  "Use the 'request_id' returned in an 'IN_PROGRESS' response or after a timeout error."
120
120
  ),
121
121
  }),
122
- timeoutMs: 600000, // 10 minutes max
122
+ timeoutMs: 90000, // 90 seconds MCP timeout (internal timeout is 60s)
123
123
  execute: async (
124
124
  args: {
125
125
  preset_name?: string;
@@ -362,7 +362,7 @@ export const falGenerate = {
362
362
  }
363
363
 
364
364
  const startTime = Date.now();
365
- const MAX_POLL_TIME = 600000; // 10 minutes
365
+ const MAX_POLL_TIME = 60000; // 60 seconds internal timeout - then return resume_id
366
366
  let pollCount = 0;
367
367
  const POLL_INTERVAL = 3000;
368
368
 
@@ -0,0 +1,174 @@
1
+ /**
2
+ * Unified status checking tool for FAL and Vertex AI generation operations.
3
+ * This tool allows resuming/checking status of operations that timed out.
4
+ */
5
+
6
+ import { z } from "zod";
7
+ import { safeToolExecute } from "../utils/tool-wrapper";
8
+ import { getGoogleAccessToken } from "../utils/google-auth";
9
+
10
+ const FAL_KEY = process.env.FAL_KEY;
11
+
12
+ /**
13
+ * Check FAL generation status using the status URL
14
+ */
15
+ async function checkFalStatus(statusUrl: string): Promise<any> {
16
+ if (!FAL_KEY) {
17
+ throw new Error("FAL_KEY environment variable not set");
18
+ }
19
+
20
+ const response = await fetch(statusUrl, {
21
+ method: "GET",
22
+ headers: {
23
+ Authorization: `Key ${FAL_KEY}`,
24
+ "Content-Type": "application/json",
25
+ },
26
+ });
27
+
28
+ if (!response.ok) {
29
+ const errorText = await response.text();
30
+ throw new Error(`FAL API error [${response.status}]: ${errorText}`);
31
+ }
32
+
33
+ const statusResult = (await response.json()) as { status?: string };
34
+
35
+ if (statusResult.status === "COMPLETED") {
36
+ // Fetch the actual result
37
+ const responseUrl = statusUrl.replace(/\/status$/, "");
38
+ const resultResponse = await fetch(responseUrl, {
39
+ method: "GET",
40
+ headers: {
41
+ Authorization: `Key ${FAL_KEY}`,
42
+ "Content-Type": "application/json",
43
+ },
44
+ });
45
+
46
+ if (resultResponse.ok) {
47
+ return await resultResponse.json();
48
+ }
49
+ }
50
+
51
+ return statusResult;
52
+ }
53
+
54
+ /**
55
+ * Check Vertex AI operation status
56
+ */
57
+ async function checkVertexStatus(
58
+ operationName: string,
59
+ projectId: string,
60
+ locationId: string
61
+ ): Promise<any> {
62
+ const accessToken = await getGoogleAccessToken();
63
+
64
+ const operationsUrl = `https://${locationId}-aiplatform.googleapis.com/v1/projects/${projectId}/locations/${locationId}/publishers/google/models/veo-3.1-generate-preview/operations/${operationName}`;
65
+
66
+ const response = await fetch(operationsUrl, {
67
+ method: "GET",
68
+ headers: {
69
+ Authorization: `Bearer ${accessToken}`,
70
+ "Content-Type": "application/json",
71
+ },
72
+ });
73
+
74
+ if (!response.ok) {
75
+ const errorText = await response.text();
76
+ throw new Error(`Vertex AI API error [${response.status}]: ${errorText}`);
77
+ }
78
+
79
+ return await response.json();
80
+ }
81
+
82
+ export const getGenerationStatus = {
83
+ name: "get_generation_status",
84
+ description:
85
+ "Check the status or retrieve the result of a generation operation that was started by 'fal_generate' or 'generateVideoi2v'. " +
86
+ "Use this when the original generation tool returned an 'IN_PROGRESS' status with a 'resume_id'. " +
87
+ "Pass the resume_id exactly as it was returned. " +
88
+ "For FAL operations, the resume_id is a full URL. " +
89
+ "For Vertex AI operations, the resume_id is an operation name.",
90
+ parameters: z.object({
91
+ resume_id: z
92
+ .string()
93
+ .describe(
94
+ "The resume_id returned by the original generation tool. " +
95
+ "For FAL: This is a full URL (starts with 'https://queue.fal.run/...'). " +
96
+ "For Vertex AI: This is an operation name."
97
+ ),
98
+ source: z
99
+ .enum(["fal", "vertex", "auto"])
100
+ .optional()
101
+ .default("auto")
102
+ .describe(
103
+ "Source of the operation: 'fal' for FAL AI, 'vertex' for Google Vertex AI, or 'auto' to auto-detect based on resume_id format."
104
+ ),
105
+ project_id: z
106
+ .string()
107
+ .optional()
108
+ .default("mixio-pro")
109
+ .describe("GCP Project ID (only needed for Vertex AI operations)."),
110
+ location_id: z
111
+ .string()
112
+ .optional()
113
+ .default("us-central1")
114
+ .describe("GCP region (only needed for Vertex AI operations)."),
115
+ }),
116
+ timeoutMs: 30000, // 30 seconds for status check
117
+ execute: async (args: {
118
+ resume_id: string;
119
+ source?: "fal" | "vertex" | "auto";
120
+ project_id?: string;
121
+ location_id?: string;
122
+ }) => {
123
+ return safeToolExecute(async () => {
124
+ const {
125
+ resume_id,
126
+ source = "auto",
127
+ project_id = "mixio-pro",
128
+ location_id = "us-central1",
129
+ } = args;
130
+
131
+ // Auto-detect source based on resume_id format
132
+ let detectedSource = source;
133
+ if (source === "auto") {
134
+ if (
135
+ resume_id.startsWith("https://queue.fal.run") ||
136
+ resume_id.startsWith("https://fal.run")
137
+ ) {
138
+ detectedSource = "fal";
139
+ } else {
140
+ detectedSource = "vertex";
141
+ }
142
+ }
143
+
144
+ let result: any;
145
+
146
+ if (detectedSource === "fal") {
147
+ result = await checkFalStatus(resume_id);
148
+ } else {
149
+ result = await checkVertexStatus(resume_id, project_id, location_id);
150
+ }
151
+
152
+ // Normalize the response
153
+ const status =
154
+ result.status || (result.done ? "COMPLETED" : "IN_PROGRESS");
155
+
156
+ return JSON.stringify(
157
+ {
158
+ source: detectedSource,
159
+ status,
160
+ resume_id,
161
+ result,
162
+ message:
163
+ status === "COMPLETED"
164
+ ? "Generation completed! The result is included in the 'result' field."
165
+ : status === "FAILED"
166
+ ? "Generation failed. Check the 'result' field for error details."
167
+ : "Generation is still in progress. Call this tool again with the same resume_id to check later.",
168
+ },
169
+ null,
170
+ 2
171
+ );
172
+ }, "get_generation_status");
173
+ },
174
+ };
@@ -152,7 +152,7 @@ export const imageToVideo = {
152
152
  "When using Veo, setting this to 'veo' (or setting auto_enhance=true) will trigger the LLM-based enhancer."
153
153
  ),
154
154
  }),
155
- timeoutMs: 1200000, // 20 minutes
155
+ timeoutMs: 90000, // 90 seconds MCP timeout (internal timeout is 60s)
156
156
  async execute(
157
157
  args: {
158
158
  prompt?: string;
@@ -477,7 +477,7 @@ export const imageToVideo = {
477
477
  // Resume_id was already streamed, so if MCP client times out the LLM still has it
478
478
  let done = current ? !!current.done || !!current.response : false;
479
479
  const startTime = Date.now();
480
- const MAX_POLL_TIME = 600000; // 10 minutes - full tool timeout is 20 mins
480
+ const MAX_POLL_TIME = 60000; // 60 seconds internal timeout - then return resume_id
481
481
 
482
482
  while (!done && Date.now() - startTime < MAX_POLL_TIME) {
483
483
  await wait(10000); // 10 second intervals