@eternalai-org/mcp-server 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Eternal AI
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,188 @@
1
+ # Eternal AI MCP Server
2
+
3
+ A Model Context Protocol (MCP) server for Eternal AI that provides tools for image generation, image editing, and video generation.
4
+
5
+ ## Features
6
+
7
+ - 🎨 **Image Generation**: Generate images from text prompts with LoRA style support
8
+ - ✏️ **Image Editing**: Edit existing images by changing outfits, backgrounds, poses, and more
9
+ - 🎬 **Video Generation**: Animate static images into videos based on text prompts
10
+ - 💾 **Auto-save**: Automatically saves generated files to disk
11
+ - 📁 **Local File Support**: Use local image files directly with `@filename.jpg` syntax
12
+
13
+ ## Installation
14
+
15
+ ### Using npx (Recommended)
16
+
17
+ You can run the MCP server directly without installation:
18
+
19
+ ```bash
20
+ ETERNAL_AI_API_KEY=your_api_key_here npx @eternalai-org/mcp-server
21
+ ```
22
+
23
+ ### Global Installation
24
+
25
+ ```bash
26
+ npm install -g @eternalai-org/mcp-server
27
+ ```
28
+
29
+ Then run:
30
+
31
+ ```bash
32
+ ETERNAL_AI_API_KEY=your_api_key_here eternal-ai-mcp
33
+ ```
34
+
35
+ ### Local Installation
36
+
37
+ ```bash
38
+ npm install @eternalai-org/mcp-server
39
+ ```
40
+
41
+ ## Environment Variables
42
+
43
+ - **ETERNAL_AI_API_KEY** (required): Your Eternal AI API key. Must start with `sa_` and be at least 20 characters.
44
+ - **SAVE_FILE_PATH** (optional): Directory or file path where generated files should be saved. If not set, files are saved to the current working directory.
45
+
46
+ ### Example
47
+
48
+ ```bash
49
+ # Set environment variables
50
+ export ETERNAL_AI_API_KEY="sa_your_api_key_here"
51
+ export SAVE_FILE_PATH="/path/to/save/files" # Optional
52
+
53
+ # Run the server
54
+ npx @eternalai-org/mcp-server
55
+ ```
56
+
57
+ ## Usage with MCP Clients
58
+
59
+ ### Claude Desktop
60
+
61
+ Add the following to your Claude Desktop configuration file:
62
+
63
+ **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
64
+ **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
65
+
66
+ ```json
67
+ {
68
+ "mcpServers": {
69
+ "eternal-ai": {
70
+ "command": "npx",
71
+ "args": [
72
+ "-y",
73
+ "@eternalai-org/mcp-server"
74
+ ],
75
+ "env": {
76
+ "ETERNAL_AI_API_KEY": "sa_your_api_key_here",
77
+ "SAVE_FILE_PATH": "/path/to/save/files"
78
+ }
79
+ }
80
+ }
81
+ }
82
+ ```
83
+
84
+ ### Cursor
85
+
86
+ Add to your Cursor MCP settings (Settings → Features → MCP):
87
+
88
+ ```json
89
+ {
90
+ "mcpServers": {
91
+ "eternal-ai": {
92
+ "command": "npx",
93
+ "args": [
94
+ "-y",
95
+ "@eternalai-org/mcp-server"
96
+ ],
97
+ "env": {
98
+ "ETERNAL_AI_API_KEY": "sa_your_api_key_here",
99
+ "SAVE_FILE_PATH": "/path/to/save/files"
100
+ }
101
+ }
102
+ }
103
+ }
104
+ ```
105
+
106
+ ### Direct CLI Usage
107
+
108
+ ```bash
109
+ ETERNAL_AI_API_KEY=sa_your_api_key_here SAVE_FILE_PATH=./output npx @eternalai-org/mcp-server
110
+ ```
111
+
112
+ ## Available Tools
113
+
114
+ ### 1. generate_image
115
+
116
+ Generate an image from a text prompt.
117
+
118
+ **Parameters:**
119
+ - `prompt` (string, required): Text description of the image to generate
120
+ - `lora_config` (object, optional): LoRA configuration for art styles. Example:
121
+ ```json
122
+ {
123
+ "Art_style_Impressionist": 0.8,
124
+ "psycho_art": 0.5
125
+ }
126
+ ```
127
+
128
+ **Example:**
129
+ ```
130
+ Generate an image of a sunset over mountains with impressionist style
131
+ ```
132
+
133
+ ### 2. edit_image
134
+
135
+ Edit an existing image based on a text prompt.
136
+
137
+ **Parameters:**
138
+ - `prompt` (string, required): Description of how to transform the image
139
+ - `image` (string, required): Image URL, base64 data URI, or local file path (use `@filename.jpg`)
140
+
141
+ **Example:**
142
+ ```
143
+ Edit @photo.jpg: Change the outfit to a sporty top. Keep the same person, pose, lighting, and background.
144
+ ```
145
+
146
+ ### 3. generate_video
147
+
148
+ Animate an image into a video based on a text prompt.
149
+
150
+ **Parameters:**
151
+ - `prompt` (string, required): Description of the animation to create
152
+ - `image` (string, required): Image URL, base64 data URI, or local file path (use `@filename.jpg`)
153
+
154
+ **Example:**
155
+ ```
156
+ Animate @photo.jpg: The person in the image is forming a heart shape with their both hands
157
+ ```
158
+
159
+ ## Local File Support
160
+
161
+ You can use local image files directly by prefixing the filename with `@`:
162
+
163
+ - `@image.jpg` - Relative to current working directory
164
+ - `@/path/to/image.jpg` - Absolute path (remove leading `/` after `@`)
165
+ - `/absolute/path/to/image.jpg` - Absolute path without `@`
166
+
167
+ ## File Saving
168
+
169
+ Generated files are automatically saved to disk:
170
+
171
+ - If `SAVE_FILE_PATH` is set to a directory, files are saved there with auto-generated names
172
+ - If `SAVE_FILE_PATH` is set to a file path, files are saved to that location
173
+ - If `SAVE_FILE_PATH` is not set, files are saved to the current working directory
174
+
175
+ File names are automatically generated with timestamps: `result-2026-01-27T08-01-23-708Z.jpg`
176
+
177
+ ## Requirements
178
+
179
+ - Node.js 18.0.0 or higher
180
+ - Eternal AI API key
181
+
182
+ ## License
183
+
184
+ MIT
185
+
186
+ ## Support
187
+
188
+ For issues and questions, please visit the [Eternal AI documentation](https://open.eternalai.org).
package/bin/cli.js ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+
3
+ require("../dist/index.js");
@@ -0,0 +1,4 @@
1
+ import { FastMCP } from "fastmcp";
2
+ declare const server: FastMCP<Record<string, unknown> | undefined>;
3
+ export default server;
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAgB,MAAM,SAAS,CAAC;AA6VhD,QAAA,MAAM,MAAM,8CAMV,CAAC;AAmQH,eAAe,MAAM,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,491 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ const fastmcp_1 = require("fastmcp");
37
+ const zod_1 = require("zod");
38
+ const fs = __importStar(require("fs"));
39
+ const path = __importStar(require("path"));
40
+ const API_BASE = "https://open.eternalai.org";
41
+ const CREATIVE_AI_BASE = "https://open.eternalai.org/creative-ai";
42
+ // Helper function to get API key from environment
43
+ function getApiKey() {
44
+ const envKey = process.env.ETERNAL_AI_API_KEY;
45
+ if (!envKey) {
46
+ throw new Error("API key not found. Please set ETERNAL_AI_API_KEY environment variable.");
47
+ }
48
+ // Trim whitespace and newlines that might cause issues
49
+ const trimmedKey = envKey.trim().replace(/\r?\n/g, '');
50
+ // Validate API key format (should start with 'sa_' and be at least 20 characters)
51
+ if (!trimmedKey || trimmedKey.length < 20) {
52
+ throw new Error(`Invalid API key format. Expected key starting with 'sa_' and at least 20 characters, got length: ${trimmedKey.length}`);
53
+ }
54
+ if (!trimmedKey.startsWith('sa_')) {
55
+ throw new Error(`Invalid API key format. Expected key starting with 'sa_', got: ${trimmedKey.substring(0, 10)}...`);
56
+ }
57
+ return trimmedKey;
58
+ }
59
+ // Helper function to get save file path from environment
60
+ function getSaveFilePath() {
61
+ const envPath = process.env.SAVE_FILE_PATH;
62
+ if (!envPath) {
63
+ return undefined; // Defaults to current working directory
64
+ }
65
+ return envPath.trim();
66
+ }
67
+ // Helper function to process image input (supports URLs, base64 data URIs, and local file paths)
68
+ function processImageInput(imageInput) {
69
+ // If it's already a data URI or URL, return as-is
70
+ if (imageInput.startsWith("data:") || imageInput.startsWith("http://") || imageInput.startsWith("https://")) {
71
+ return imageInput;
72
+ }
73
+ // Handle local file paths (starting with @ or regular file paths)
74
+ let filePath;
75
+ if (imageInput.startsWith("@")) {
76
+ // Remove @ prefix and resolve relative to current working directory
77
+ filePath = path.resolve(process.cwd(), imageInput.substring(1));
78
+ }
79
+ else {
80
+ // Try to resolve as relative or absolute path
81
+ filePath = path.isAbsolute(imageInput)
82
+ ? imageInput
83
+ : path.resolve(process.cwd(), imageInput);
84
+ }
85
+ // Check if file exists
86
+ if (!fs.existsSync(filePath)) {
87
+ throw new Error(`Image file not found: ${filePath}`);
88
+ }
89
+ // Check if it's a file (not a directory)
90
+ const stats = fs.statSync(filePath);
91
+ if (!stats.isFile()) {
92
+ throw new Error(`Path is not a file: ${filePath}`);
93
+ }
94
+ // Check file size (max 5 MB)
95
+ const fileSizeInMB = stats.size / (1024 * 1024);
96
+ if (fileSizeInMB > 5) {
97
+ throw new Error(`Image file is too large: ${fileSizeInMB.toFixed(2)} MB (maximum 5 MB)`);
98
+ }
99
+ // Read file and convert to base64 data URI
100
+ const fileBuffer = fs.readFileSync(filePath);
101
+ const fileExtension = path.extname(filePath).toLowerCase();
102
+ // Determine MIME type from extension
103
+ let mimeType = "image/jpeg"; // default
104
+ if (fileExtension === ".png") {
105
+ mimeType = "image/png";
106
+ }
107
+ else if (fileExtension === ".jpg" || fileExtension === ".jpeg") {
108
+ mimeType = "image/jpeg";
109
+ }
110
+ else if (fileExtension === ".webp") {
111
+ mimeType = "image/webp";
112
+ }
113
+ // Convert to base64 data URI
114
+ const base64Data = fileBuffer.toString("base64");
115
+ return `data:${mimeType};base64,${base64Data}`;
116
+ }
117
+ async function fetchWithRetry(url, options = {}, maxRetries = 3) {
118
+ const { maxRetries: optionMaxRetries, retryDelay = 1000, ...fetchOptions } = options;
119
+ const retries = optionMaxRetries ?? maxRetries;
120
+ let lastError = null;
121
+ for (let attempt = 0; attempt <= retries; attempt++) {
122
+ try {
123
+ const response = await fetch(url, fetchOptions);
124
+ // Clone response to read body for error messages without consuming it
125
+ const responseClone = response.clone();
126
+ const responseBody = await responseClone.text().catch(() => "");
127
+ // If response is successful, return it
128
+ if (response.ok) {
129
+ return response;
130
+ }
131
+ // If it's the last attempt, throw the error
132
+ if (attempt === retries) {
133
+ throw new Error(`Request failed after ${retries + 1} attempts: ${response.status} ${response.statusText}\n${responseBody}`);
134
+ }
135
+ // For non-ok responses, wait and retry
136
+ lastError = new Error(`Request failed: ${response.status} ${response.statusText}`);
137
+ }
138
+ catch (error) {
139
+ lastError = error instanceof Error ? error : new Error(String(error));
140
+ // If it's the last attempt, throw the error
141
+ if (attempt === retries) {
142
+ throw new Error(`Request failed after ${retries + 1} attempts: ${lastError.message}`);
143
+ }
144
+ }
145
+ // Wait before retrying (exponential backoff: 1s, 2s, 4s...)
146
+ const delay = retryDelay * Math.pow(2, attempt);
147
+ await new Promise((resolve) => setTimeout(resolve, delay));
148
+ }
149
+ // This should never be reached, but TypeScript needs it
150
+ throw lastError || new Error("Request failed after all retries");
151
+ }
152
+ // Helper function to poll for image generation result
153
+ async function pollImageResult(requestId, maxAttempts = 100, pollInterval = 10000) {
154
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
155
+ const pollUrl = `${CREATIVE_AI_BASE}/result/image?request_id=${requestId}`;
156
+ const pollResponse = await fetchWithRetry(pollUrl, {
157
+ method: "GET",
158
+ headers: {
159
+ accept: "application/json",
160
+ },
161
+ });
162
+ const pollData = (await pollResponse.json());
163
+ if (pollData.status === "success" && pollData.result_url) {
164
+ return pollData.result_url;
165
+ }
166
+ if (pollData.status === "failed") {
167
+ throw new Error(`Image generation failed: Request ID ${requestId}`);
168
+ }
169
+ // Wait before next poll
170
+ await new Promise((resolve) => setTimeout(resolve, pollInterval));
171
+ }
172
+ throw new Error("Image generation timeout: Maximum polling attempts reached");
173
+ }
174
+ // Helper function to poll for generation result (image editing/video)
175
+ async function pollGenerationResult(apiKey, requestId, maxAttempts = 100, pollInterval = 10000) {
176
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
177
+ const pollUrl = `${API_BASE}/poll-result/${requestId}`;
178
+ const pollResponse = await fetchWithRetry(pollUrl, {
179
+ method: "GET",
180
+ headers: {
181
+ "x-api-key": apiKey,
182
+ },
183
+ });
184
+ const pollData = (await pollResponse.json());
185
+ if (pollData.status === "success" && pollData.result_url) {
186
+ return pollData.result_url;
187
+ }
188
+ if (pollData.status === "failed") {
189
+ throw new Error(`Generation failed: Request ID ${requestId}`);
190
+ }
191
+ // Wait before next poll
192
+ await new Promise((resolve) => setTimeout(resolve, pollInterval));
193
+ }
194
+ throw new Error("Generation timeout: Maximum polling attempts reached");
195
+ }
196
+ // Helper function to download and save file from URL
197
+ async function downloadAndSaveFile(url, savePath) {
198
+ try {
199
+ // Fetch the file
200
+ const response = await fetchWithRetry(url, {
201
+ method: "GET",
202
+ });
203
+ if (!response.ok) {
204
+ throw new Error(`Failed to download file: ${response.status} ${response.statusText}`);
205
+ }
206
+ // Determine file extension from URL or Content-Type
207
+ const contentType = response.headers.get("content-type") || "";
208
+ let extension = "";
209
+ if (contentType.includes("image/jpeg") || contentType.includes("image/jpg")) {
210
+ extension = ".jpg";
211
+ }
212
+ else if (contentType.includes("image/png")) {
213
+ extension = ".png";
214
+ }
215
+ else if (contentType.includes("image/webp")) {
216
+ extension = ".webp";
217
+ }
218
+ else if (contentType.includes("video/mp4")) {
219
+ extension = ".mp4";
220
+ }
221
+ else if (contentType.includes("video/webm")) {
222
+ extension = ".webm";
223
+ }
224
+ else {
225
+ // Try to get extension from URL
226
+ const urlPath = new URL(url).pathname;
227
+ const urlExtension = path.extname(urlPath);
228
+ extension = urlExtension || ".jpg"; // Default to .jpg if unknown
229
+ }
230
+ // Determine save path
231
+ let finalSavePath;
232
+ if (savePath) {
233
+ finalSavePath = path.isAbsolute(savePath)
234
+ ? savePath
235
+ : path.resolve(process.cwd(), savePath);
236
+ // If savePath is a directory, generate filename
237
+ if (fs.existsSync(finalSavePath) && fs.statSync(finalSavePath).isDirectory()) {
238
+ const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
239
+ finalSavePath = path.join(finalSavePath, `result-${timestamp}${extension}`);
240
+ }
241
+ else if (!path.extname(finalSavePath)) {
242
+ // If no extension, add one
243
+ finalSavePath = `${finalSavePath}${extension}`;
244
+ }
245
+ }
246
+ else {
247
+ // Default to current working directory
248
+ const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
249
+ finalSavePath = path.resolve(process.cwd(), `result-${timestamp}${extension}`);
250
+ }
251
+ // Ensure directory exists
252
+ const dir = path.dirname(finalSavePath);
253
+ if (!fs.existsSync(dir)) {
254
+ fs.mkdirSync(dir, { recursive: true });
255
+ }
256
+ // Download and save file
257
+ const arrayBuffer = await response.arrayBuffer();
258
+ const buffer = Buffer.from(arrayBuffer);
259
+ fs.writeFileSync(finalSavePath, buffer);
260
+ return finalSavePath;
261
+ }
262
+ catch (error) {
263
+ throw new Error(`Failed to save file: ${error instanceof Error ? error.message : String(error)}`);
264
+ }
265
+ }
266
+ // Create FastMCP server
267
+ const server = new fastmcp_1.FastMCP({
268
+ name: "Eternal AI MCP Server",
269
+ version: "1.0.0",
270
+ instructions: "This server provides tools for image generation, image editing, and video generation using the Eternal AI API. " +
271
+ "All tools support polling for results and will automatically wait for completion.",
272
+ });
273
+ // Tool 1: Image Generation (Text-to-Image)
274
+ server.addTool({
275
+ name: "generate_image",
276
+ description: "Generate an image from a text prompt using Eternal AI's image generation API. " +
277
+ "This uses the legacy API endpoint and supports LoRA configurations for different art styles.",
278
+ parameters: zod_1.z.object({
279
+ prompt: zod_1.z
280
+ .string()
281
+ .describe("The text prompt describing the image to generate"),
282
+ lora_config: zod_1.z
283
+ .record(zod_1.z.string(), zod_1.z.number())
284
+ .optional()
285
+ .describe("Optional LoRA configuration object. Keys are LoRA names (e.g., 'Art_style_Impressionist', 'psycho_art'), values are weights (typically 0-1). " +
286
+ "Available LoRAs include: Art_style_Impressionist, psycho_art, FLUX-daubrez-DB4RZ, Flux_1_MechanicalBloom, RM_Artistify_v1_0M"),
287
+ }),
288
+ execute: async (args) => {
289
+ const apiKey = getApiKey();
290
+ const requestUrl = `${CREATIVE_AI_BASE}/image`;
291
+ const requestBody = {
292
+ messages: [
293
+ {
294
+ role: "user",
295
+ content: [
296
+ {
297
+ type: "text",
298
+ text: args.prompt,
299
+ },
300
+ ],
301
+ },
302
+ ],
303
+ type: "new",
304
+ ...(args.lora_config && { lora_config: args.lora_config }),
305
+ };
306
+ const createResponse = await fetchWithRetry(requestUrl, {
307
+ method: "POST",
308
+ headers: {
309
+ accept: "application/json",
310
+ "x-api-key": apiKey,
311
+ "Content-Type": "application/json",
312
+ },
313
+ body: JSON.stringify(requestBody),
314
+ });
315
+ const createData = (await createResponse.json());
316
+ const requestId = createData.request_id;
317
+ if (!requestId) {
318
+ throw new Error("No request_id returned from API");
319
+ }
320
+ // Poll for result
321
+ const resultUrl = await pollImageResult(requestId);
322
+ // Save file (always save, path from environment variable)
323
+ let savedFilePath;
324
+ try {
325
+ savedFilePath = await downloadAndSaveFile(resultUrl, getSaveFilePath());
326
+ }
327
+ catch (error) {
328
+ // Log error but don't fail the tool call
329
+ console.error("Failed to save file:", error);
330
+ }
331
+ const resultText = savedFilePath
332
+ ? `Image generated successfully!\nRequest ID: ${requestId}\nResult URL: ${resultUrl}\nSaved to: ${savedFilePath}`
333
+ : `Image generated successfully!\nRequest ID: ${requestId}\nResult URL: ${resultUrl}`;
334
+ return {
335
+ content: [
336
+ {
337
+ type: "text",
338
+ text: resultText,
339
+ },
340
+ await (0, fastmcp_1.imageContent)({ url: resultUrl }),
341
+ ],
342
+ };
343
+ },
344
+ });
345
+ // Tool 2: Image Editing
346
+ server.addTool({
347
+ name: "edit_image",
348
+ description: "Edit an existing image based on a text prompt. " +
349
+ "This tool can modify images by changing outfits, backgrounds, poses, and more while preserving the original composition.",
350
+ parameters: zod_1.z.object({
351
+ prompt: zod_1.z
352
+ .string()
353
+ .describe("Description of how to transform the image (e.g., 'Change the outfit to a sporty top. Keep the same person, pose, lighting, and background.')"),
354
+ image: zod_1.z
355
+ .string()
356
+ .describe("Input image URL, base64-encoded image (data URI format), or local file path. " +
357
+ "For local files, use @filename.jpg (relative to current directory) or absolute path. " +
358
+ "Maximum size: 5 MB. Supported formats: .jpg, .jpeg, .png, .webp"),
359
+ }),
360
+ execute: async (args) => {
361
+ const apiKey = getApiKey();
362
+ // Process image input (convert local files to base64)
363
+ const processedImage = processImageInput(args.image);
364
+ const requestUrl = `${API_BASE}/base/generate`;
365
+ const requestBody = {
366
+ images: [processedImage],
367
+ prompt: args.prompt,
368
+ type: "image",
369
+ };
370
+ const createResponse = await fetchWithRetry(requestUrl, {
371
+ method: "POST",
372
+ headers: {
373
+ "Content-Type": "application/json",
374
+ "x-api-key": apiKey,
375
+ },
376
+ body: JSON.stringify(requestBody),
377
+ });
378
+ const createData = (await createResponse.json());
379
+ const requestId = createData.request_id;
380
+ if (!requestId) {
381
+ throw new Error("No request_id returned from API");
382
+ }
383
+ let resultUrl;
384
+ // Check if result_url is already available
385
+ if (createData.status === "success" && createData.result_url) {
386
+ resultUrl = createData.result_url;
387
+ }
388
+ else {
389
+ // Poll for result
390
+ resultUrl = await pollGenerationResult(apiKey, requestId);
391
+ }
392
+ // Save file (always save, path from environment variable)
393
+ let savedFilePath;
394
+ try {
395
+ savedFilePath = await downloadAndSaveFile(resultUrl, getSaveFilePath());
396
+ }
397
+ catch (error) {
398
+ // Log error but don't fail the tool call
399
+ console.error("Failed to save file:", error);
400
+ }
401
+ const resultText = savedFilePath
402
+ ? `Image edited successfully!\nRequest ID: ${requestId}\nResult URL: ${resultUrl}\nSaved to: ${savedFilePath}`
403
+ : `Image edited successfully!\nRequest ID: ${requestId}\nResult URL: ${resultUrl}`;
404
+ return {
405
+ content: [
406
+ {
407
+ type: "text",
408
+ text: resultText,
409
+ },
410
+ await (0, fastmcp_1.imageContent)({ url: resultUrl }),
411
+ ],
412
+ };
413
+ },
414
+ });
415
+ // Tool 3: Video Generation
416
+ server.addTool({
417
+ name: "generate_video",
418
+ description: "Animate an image into a video based on a text prompt. " +
419
+ "This tool takes a static image and creates an animated video showing the described motion or transformation.",
420
+ parameters: zod_1.z.object({
421
+ prompt: zod_1.z
422
+ .string()
423
+ .describe("Description of the animation to create (e.g., 'The person in the image is forming a heart shape with their both hands')"),
424
+ image: zod_1.z
425
+ .string()
426
+ .describe("Input image URL, base64-encoded image (data URI format), or local file path. " +
427
+ "For local files, use @filename.jpg (relative to current directory) or absolute path. " +
428
+ "Maximum size: 5 MB. Supported formats: .jpg, .jpeg, .png, .webp"),
429
+ }),
430
+ execute: async (args) => {
431
+ const apiKey = getApiKey();
432
+ // Process image input (convert local files to base64)
433
+ const processedImage = processImageInput(args.image);
434
+ const requestUrl = `${API_BASE}/base/generate`;
435
+ const requestBody = {
436
+ images: [processedImage],
437
+ prompt: args.prompt,
438
+ type: "video",
439
+ };
440
+ const createResponse = await fetchWithRetry(requestUrl, {
441
+ method: "POST",
442
+ headers: {
443
+ "Content-Type": "application/json",
444
+ "x-api-key": apiKey,
445
+ },
446
+ body: JSON.stringify(requestBody),
447
+ });
448
+ const createData = (await createResponse.json());
449
+ const requestId = createData.request_id;
450
+ if (!requestId) {
451
+ throw new Error("No request_id returned from API");
452
+ }
453
+ let resultUrl;
454
+ // Check if result_url is already available
455
+ if (createData.status === "success" && createData.result_url) {
456
+ resultUrl = createData.result_url;
457
+ }
458
+ else {
459
+ // Poll for result
460
+ resultUrl = await pollGenerationResult(apiKey, requestId);
461
+ }
462
+ // Save file (always save, path from environment variable)
463
+ let savedFilePath;
464
+ try {
465
+ savedFilePath = await downloadAndSaveFile(resultUrl, getSaveFilePath());
466
+ }
467
+ catch (error) {
468
+ // Log error but don't fail the tool call
469
+ console.error("Failed to save file:", error);
470
+ }
471
+ const resultText = savedFilePath
472
+ ? `Video generated successfully!\nRequest ID: ${requestId}\nResult URL: ${resultUrl}\nSaved to: ${savedFilePath}`
473
+ : `Video generated successfully!\nRequest ID: ${requestId}\nResult URL: ${resultUrl}`;
474
+ return {
475
+ content: [
476
+ {
477
+ type: "text",
478
+ text: resultText,
479
+ },
480
+ ],
481
+ };
482
+ },
483
+ });
484
+ // Start the server
485
+ if (require.main === module) {
486
+ server.start({
487
+ transportType: "stdio",
488
+ });
489
+ }
490
+ exports.default = server;
491
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@eternalai-org/mcp-server",
3
+ "version": "1.0.0",
4
+ "description": "MCP server for Eternal AI image generation, editing, and video generation",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "eternal-ai-mcp": "./bin/cli.js"
8
+ },
9
+ "scripts": {
10
+ "build": "tsc",
11
+ "prepublishOnly": "npm run build",
12
+ "dev": "npx fastmcp dev src/index.ts"
13
+ },
14
+ "keywords": [
15
+ "mcp",
16
+ "model-context-protocol",
17
+ "eternal-ai",
18
+ "image-generation",
19
+ "image-editing",
20
+ "video-generation",
21
+ "ai",
22
+ "claude",
23
+ "cursor"
24
+ ],
25
+ "author": "",
26
+ "license": "MIT",
27
+ "dependencies": {
28
+ "fastmcp": "^3.30.1",
29
+ "zod": "^4.3.6"
30
+ },
31
+ "devDependencies": {
32
+ "@types/node": "^20.0.0",
33
+ "typescript": "^5.0.0"
34
+ },
35
+ "engines": {
36
+ "node": ">=18.0.0"
37
+ },
38
+ "files": [
39
+ "dist",
40
+ "bin",
41
+ "README.md",
42
+ "LICENSE"
43
+ ],
44
+ "repository": {
45
+ "type": "git",
46
+ "url": ""
47
+ }
48
+ }