@mixio-pro/kalaasetu-mcp 1.0.16 → 1.0.17

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": "1.0.16",
3
+ "version": "1.0.17",
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",
@@ -16,32 +16,23 @@ const ai = new GoogleGenAI({
16
16
  apiKey: process.env.GEMINI_API_KEY || "",
17
17
  });
18
18
 
19
+ import { ensureLocalFile } from "../utils/url-file";
20
+
19
21
  async function fileToGenerativePart(filePath: string) {
20
- const storage = getStorage();
22
+ const fileResult = await ensureLocalFile(filePath);
21
23
 
22
- // Check if file exists
23
- const exists = await storage.exists(filePath);
24
- if (!exists) {
25
- // Try to provide more helpful error information
26
- const isAbsolute = path.isAbsolute(filePath);
27
- const resolvedPath = isAbsolute
28
- ? filePath
29
- : path.resolve(process.cwd(), filePath);
30
- throw new Error(
31
- `File not found: ${filePath}\n` +
32
- `Resolved path: ${resolvedPath}\n` +
33
- `Is absolute: ${isAbsolute}\n` +
34
- `CWD: ${process.cwd()}`
35
- );
24
+ try {
25
+ const storage = getStorage();
26
+ const imageBytes = await storage.readFile(fileResult.path);
27
+ return {
28
+ inlineData: {
29
+ data: Buffer.from(imageBytes).toString("base64"),
30
+ mimeType: "image/jpeg",
31
+ },
32
+ };
33
+ } finally {
34
+ fileResult.cleanup();
36
35
  }
37
-
38
- const imageBytes = await storage.readFile(filePath);
39
- return {
40
- inlineData: {
41
- data: Buffer.from(imageBytes).toString("base64"),
42
- mimeType: "image/jpeg",
43
- },
44
- };
45
36
  }
46
37
 
47
38
  // Helper function to save WAV file
@@ -165,29 +156,18 @@ async function processVideoInput(
165
156
  },
166
157
  };
167
158
  } else {
168
- // Local file processing - use File Upload API
169
- const storage = getStorage();
159
+ // Local file processing or non-YouTube URL - use File Upload API
160
+ // ensureLocalFile handles downloading URLs if needed
161
+ const fileResult = await ensureLocalFile(input);
170
162
 
171
- // Check if file exists
172
- const exists = await storage.exists(input);
173
- if (!exists) {
174
- // Try to provide more helpful error information
175
- const isAbsolute = path.isAbsolute(input);
176
- const resolvedPath = isAbsolute
177
- ? input
178
- : path.resolve(process.cwd(), input);
179
- throw new Error(
180
- `Video file not found: ${input}\n` +
181
- `Resolved path: ${resolvedPath}\n` +
182
- `Is absolute: ${isAbsolute}\n` +
183
- `CWD: ${process.cwd()}`
184
- );
163
+ try {
164
+ // Upload file to Gemini API
165
+ // We pass the local path (temp or original)
166
+ const uploadedFile = await uploadFileToGemini(fileResult.path);
167
+ return uploadedFile;
168
+ } finally {
169
+ fileResult.cleanup();
185
170
  }
186
-
187
- // Upload file to Gemini API
188
- const uploadedFile = await uploadFileToGemini(input);
189
-
190
- return uploadedFile;
191
171
  }
192
172
  }
193
173
 
@@ -11,32 +11,23 @@ async function wait(ms: number): Promise<void> {
11
11
  return new Promise((resolve) => setTimeout(resolve, ms));
12
12
  }
13
13
 
14
+ import { ensureLocalFile } from "../utils/url-file";
15
+
14
16
  async function fileToBase64(
15
17
  filePath: string
16
18
  ): Promise<{ data: string; mimeType: string }> {
17
- const storage = getStorage();
19
+ const fileResult = await ensureLocalFile(filePath);
18
20
 
19
- // Check if file exists
20
- const exists = await storage.exists(filePath);
21
- if (!exists) {
22
- // Try to provide more helpful error information
23
- const isAbsolute = path.isAbsolute(filePath);
24
- const resolvedPath = isAbsolute
25
- ? filePath
26
- : path.resolve(process.cwd(), filePath);
27
- throw new Error(
28
- `File not found: ${filePath}\n` +
29
- `Resolved path: ${resolvedPath}\n` +
30
- `Is absolute: ${isAbsolute}\n` +
31
- `CWD: ${process.cwd()}`
32
- );
21
+ try {
22
+ const storage = getStorage();
23
+ const buf = await storage.readFile(fileResult.path);
24
+ const data = Buffer.from(buf).toString("base64");
25
+ // Default to PNG if not sure, similar to existing code
26
+ const mimeType = "image/png";
27
+ return { data, mimeType };
28
+ } finally {
29
+ fileResult.cleanup();
33
30
  }
34
-
35
- const buf = await storage.readFile(filePath);
36
- const data = Buffer.from(buf).toString("base64");
37
- // Default to PNG if not sure, similar to existing code
38
- const mimeType = "image/png";
39
- return { data, mimeType };
40
31
  }
41
32
 
42
33
  export const imageToVideo = {
@@ -0,0 +1,91 @@
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+ import * as os from "os";
4
+ import { getStorage } from "../storage";
5
+ import { generateTimestampedFilename } from "./filename";
6
+
7
+ export interface LocalFileResult {
8
+ path: string;
9
+ isTemp: boolean;
10
+ cleanup: () => void;
11
+ }
12
+
13
+ /**
14
+ * Ensures the input is a local file path.
15
+ * If input is a URL, downloads it to a temporary file.
16
+ * If input is a file path, returns it as is (resolving if necessary).
17
+ */
18
+ export async function ensureLocalFile(input: string): Promise<LocalFileResult> {
19
+ const isUrl = input.startsWith("http://") || input.startsWith("https://");
20
+
21
+ if (isUrl) {
22
+ const tempDir = os.tmpdir();
23
+ // Use a timestamped filename to avoid collisions
24
+ // Try to guess extension from URL or default to bin/tmp
25
+ const urlPath = new URL(input).pathname;
26
+ const ext = path.extname(urlPath) || ".tmp";
27
+ // We'll use a simple name since generateTimestampedFilename expects a file path
28
+ const safeName = `mcp_download_${Date.now()}${ext}`;
29
+ const tempFilePath = path.join(tempDir, safeName);
30
+
31
+ try {
32
+ const response = await fetch(input);
33
+ if (!response.ok) {
34
+ throw new Error(
35
+ `Failed to download URL: ${input} (${response.status} ${response.statusText})`
36
+ );
37
+ }
38
+
39
+ const arrayBuffer = await response.arrayBuffer();
40
+ const buffer = Buffer.from(arrayBuffer);
41
+ fs.writeFileSync(tempFilePath, buffer);
42
+
43
+ return {
44
+ path: tempFilePath,
45
+ isTemp: true,
46
+ cleanup: () => {
47
+ try {
48
+ if (fs.existsSync(tempFilePath)) {
49
+ fs.unlinkSync(tempFilePath);
50
+ }
51
+ } catch (e) {
52
+ console.error(`Failed to cleanup temp file ${tempFilePath}:`, e);
53
+ }
54
+ },
55
+ };
56
+ } catch (error: any) {
57
+ // If download failed, clean up if we created the file
58
+ try {
59
+ if (fs.existsSync(tempFilePath)) {
60
+ fs.unlinkSync(tempFilePath);
61
+ }
62
+ } catch {}
63
+ throw new Error(`Failed to process URL ${input}: ${error.message}`);
64
+ }
65
+ } else {
66
+ // It's a local file path (or at least we treat it as one)
67
+ // We verify existence using our storage abstraction or fs
68
+ const storage = getStorage();
69
+ const exists = await storage.exists(input);
70
+
71
+ if (!exists) {
72
+ // Try to provide more helpful error information
73
+ const isAbsolute = path.isAbsolute(input);
74
+ const resolvedPath = isAbsolute
75
+ ? input
76
+ : path.resolve(process.cwd(), input);
77
+ throw new Error(
78
+ `File not found: ${input}\n` +
79
+ `Resolved path: ${resolvedPath}\n` +
80
+ `Is absolute: ${isAbsolute}\n` +
81
+ `CWD: ${process.cwd()}`
82
+ );
83
+ }
84
+
85
+ return {
86
+ path: input,
87
+ isTemp: false,
88
+ cleanup: () => {}, // No-op for existing local files
89
+ };
90
+ }
91
+ }