@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 +21 -0
- package/README.md +188 -0
- package/bin/cli.js +3 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +491 -0
- package/dist/index.js.map +1 -0
- package/package.json +48 -0
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
package/dist/index.d.ts
ADDED
|
@@ -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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,qCAAgD;AAChD,6BAAwB;AACxB,uCAAyB;AACzB,2CAA6B;AAE7B,MAAM,QAAQ,GAAG,4BAA4B,CAAC;AAC9C,MAAM,gBAAgB,GAAG,wCAAwC,CAAC;AAiDlE,kDAAkD;AAClD,SAAS,SAAS;IAChB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;IAE9C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,wEAAwE,CACzE,CAAC;IACJ,CAAC;IAED,uDAAuD;IACvD,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IAEvD,kFAAkF;IAClF,IAAI,CAAC,UAAU,IAAI,UAAU,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;QAC1C,MAAM,IAAI,KAAK,CACb,oGAAoG,UAAU,CAAC,MAAM,EAAE,CACxH,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CACb,kEAAkE,UAAU,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CACnG,CAAC;IACJ,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,yDAAyD;AACzD,SAAS,eAAe;IACtB,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;IAC3C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,SAAS,CAAC,CAAC,wCAAwC;IAC5D,CAAC;IACD,OAAO,OAAO,CAAC,IAAI,EAAE,CAAC;AACxB,CAAC;AAED,iGAAiG;AACjG,SAAS,iBAAiB,CAAC,UAAkB;IAC3C,kDAAkD;IAClD,IAAI,UAAU,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5G,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,kEAAkE;IAClE,IAAI,QAAgB,CAAC;IAErB,IAAI,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/B,oEAAoE;QACpE,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;IAClE,CAAC;SAAM,CAAC;QACN,8CAA8C;QAC9C,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;YACpC,CAAC,CAAC,UAAU;YACZ,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,UAAU,CAAC,CAAC;IAC9C,CAAC;IAED,uBAAuB;IACvB,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,yBAAyB,QAAQ,EAAE,CAAC,CAAC;IACvD,CAAC;IAED,yCAAyC;IACzC,MAAM,KAAK,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACpC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,uBAAuB,QAAQ,EAAE,CAAC,CAAC;IACrD,CAAC;IAED,6BAA6B;IAC7B,MAAM,YAAY,GAAG,KAAK,CAAC,IAAI,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;IAChD,IAAI,YAAY,GAAG,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,4BAA4B,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC;IAC3F,CAAC;IAED,2CAA2C;IAC3C,MAAM,UAAU,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;IAC7C,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;IAE3D,qCAAqC;IACrC,IAAI,QAAQ,GAAG,YAAY,CAAC,CAAC,UAAU;IACvC,IAAI,aAAa,KAAK,MAAM,EAAE,CAAC;QAC7B,QAAQ,GAAG,WAAW,CAAC;IACzB,CAAC;SAAM,IAAI,aAAa,KAAK,MAAM,IAAI,aAAa,KAAK,OAAO,EAAE,CAAC;QACjE,QAAQ,GAAG,YAAY,CAAC;IAC1B,CAAC;SAAM,IAAI,aAAa,KAAK,OAAO,EAAE,CAAC;QACrC,QAAQ,GAAG,YAAY,CAAC;IAC1B,CAAC;IAED,6BAA6B;IAC7B,MAAM,UAAU,GAAG,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACjD,OAAO,QAAQ,QAAQ,WAAW,UAAU,EAAE,CAAC;AACjD,CAAC;AAYD,KAAK,UAAU,cAAc,CAC3B,GAAW,EACX,UAAiC,EAAE,EACnC,aAAqB,CAAC;IAEtB,MAAM,EAAE,UAAU,EAAE,gBAAgB,EAAE,UAAU,GAAG,IAAI,EAAE,GAAG,YAAY,EAAE,GAAG,OAAO,CAAC;IACrF,MAAM,OAAO,GAAG,gBAAgB,IAAI,UAAU,CAAC;IAC/C,IAAI,SAAS,GAAiB,IAAI,CAAC;IAEnC,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC;QACpD,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;YAEhD,sEAAsE;YACtE,MAAM,aAAa,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAC;YACvC,MAAM,YAAY,GAAG,MAAM,aAAa,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;YAEhE,uCAAuC;YACvC,IAAI,QAAQ,CAAC,EAAE,EAAE,CAAC;gBAChB,OAAO,QAAQ,CAAC;YAClB,CAAC;YAED,4CAA4C;YAC5C,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;gBACxB,MAAM,IAAI,KAAK,CACb,wBAAwB,OAAO,GAAG,CAAC,cAAc,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,KAAK,YAAY,EAAE,CAC3G,CAAC;YACJ,CAAC;YAED,uCAAuC;YACvC,SAAS,GAAG,IAAI,KAAK,CAAC,mBAAmB,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;QACrF,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,SAAS,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YAEtE,4CAA4C;YAC5C,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;gBACxB,MAAM,IAAI,KAAK,CACb,wBAAwB,OAAO,GAAG,CAAC,cAAc,SAAS,CAAC,OAAO,EAAE,CACrE,CAAC;YACJ,CAAC;QACH,CAAC;QAED,4DAA4D;QAC5D,MAAM,KAAK,GAAG,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QAChD,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;IAC7D,CAAC;IAED,wDAAwD;IACxD,MAAM,SAAS,IAAI,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;AACnE,CAAC;AAED,sDAAsD;AACtD,KAAK,UAAU,eAAe,CAC5B,SAAiB,EACjB,cAAsB,GAAG,EACzB,eAAuB,KAAK;IAE5B,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,WAAW,EAAE,OAAO,EAAE,EAAE,CAAC;QACvD,MAAM,OAAO,GAAG,GAAG,gBAAgB,4BAA4B,SAAS,EAAE,CAAC;QAC3E,MAAM,YAAY,GAAG,MAAM,cAAc,CAAC,OAAO,EAAE;YACjD,MAAM,EAAE,KAAK;YACb,OAAO,EAAE;gBACP,MAAM,EAAE,kBAAkB;aAC3B;SACF,CAAC,CAAC;QAEH,MAAM,QAAQ,GAAG,CAAC,MAAM,YAAY,CAAC,IAAI,EAAE,CAAwB,CAAC;QAEpE,IAAI,QAAQ,CAAC,MAAM,KAAK,SAAS,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC;YACzD,OAAO,QAAQ,CAAC,UAAU,CAAC;QAC7B,CAAC;QAED,IAAI,QAAQ,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YACjC,MAAM,IAAI,KAAK,CAAC,uCAAuC,SAAS,EAAE,CAAC,CAAC;QACtE,CAAC;QAED,wBAAwB;QACxB,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC;IACpE,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAC;AAChF,CAAC;AAED,sEAAsE;AACtE,KAAK,UAAU,oBAAoB,CACjC,MAAc,EACd,SAAiB,EACjB,cAAsB,GAAG,EACzB,eAAuB,KAAK;IAE5B,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,WAAW,EAAE,OAAO,EAAE,EAAE,CAAC;QACvD,MAAM,OAAO,GAAG,GAAG,QAAQ,gBAAgB,SAAS,EAAE,CAAC;QACvD,MAAM,YAAY,GAAG,MAAM,cAAc,CAAC,OAAO,EAAE;YACjD,MAAM,EAAE,KAAK;YACb,OAAO,EAAE;gBACP,WAAW,EAAE,MAAM;aACpB;SACF,CAAC,CAAC;QAEH,MAAM,QAAQ,GAAG,CAAC,MAAM,YAAY,CAAC,IAAI,EAAE,CAAuB,CAAC;QAEnE,IAAI,QAAQ,CAAC,MAAM,KAAK,SAAS,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC;YACzD,OAAO,QAAQ,CAAC,UAAU,CAAC;QAC7B,CAAC;QAED,IAAI,QAAQ,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YACjC,MAAM,IAAI,KAAK,CAAC,iCAAiC,SAAS,EAAE,CAAC,CAAC;QAChE,CAAC;QAED,wBAAwB;QACxB,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC;IACpE,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;AAC1E,CAAC;AAED,qDAAqD;AACrD,KAAK,UAAU,mBAAmB,CAChC,GAAW,EACX,QAAiB;IAEjB,IAAI,CAAC;QACH,iBAAiB;QACjB,MAAM,QAAQ,GAAG,MAAM,cAAc,CAAC,GAAG,EAAE;YACzC,MAAM,EAAE,KAAK;SACd,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,4BAA4B,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;QACxF,CAAC;QAED,oDAAoD;QACpD,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;QAC/D,IAAI,SAAS,GAAG,EAAE,CAAC;QACnB,IAAI,WAAW,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,WAAW,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YAC5E,SAAS,GAAG,MAAM,CAAC;QACrB,CAAC;aAAM,IAAI,WAAW,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YAC7C,SAAS,GAAG,MAAM,CAAC;QACrB,CAAC;aAAM,IAAI,WAAW,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;YAC9C,SAAS,GAAG,OAAO,CAAC;QACtB,CAAC;aAAM,IAAI,WAAW,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YAC7C,SAAS,GAAG,MAAM,CAAC;QACrB,CAAC;aAAM,IAAI,WAAW,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;YAC9C,SAAS,GAAG,OAAO,CAAC;QACtB,CAAC;aAAM,CAAC;YACN,gCAAgC;YAChC,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC;YACtC,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YAC3C,SAAS,GAAG,YAAY,IAAI,MAAM,CAAC,CAAC,6BAA6B;QACnE,CAAC;QAED,sBAAsB;QACtB,IAAI,aAAqB,CAAC;QAC1B,IAAI,QAAQ,EAAE,CAAC;YACb,aAAa,GAAG,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;gBACvC,CAAC,CAAC,QAAQ;gBACV,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,QAAQ,CAAC,CAAC;YAE1C,gDAAgD;YAChD,IAAI,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;gBAC7E,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;gBACjE,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,UAAU,SAAS,GAAG,SAAS,EAAE,CAAC,CAAC;YAC9E,CAAC;iBAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,CAAC;gBACxC,2BAA2B;gBAC3B,aAAa,GAAG,GAAG,aAAa,GAAG,SAAS,EAAE,CAAC;YACjD,CAAC;QACH,CAAC;aAAM,CAAC;YACN,uCAAuC;YACvC,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YACjE,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,UAAU,SAAS,GAAG,SAAS,EAAE,CAAC,CAAC;QACjF,CAAC;QAED,0BAA0B;QAC1B,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;QACxC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACxB,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACzC,CAAC;QAED,yBAAyB;QACzB,MAAM,WAAW,GAAG,MAAM,QAAQ,CAAC,WAAW,EAAE,CAAC;QACjD,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACxC,EAAE,CAAC,aAAa,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;QAExC,OAAO,aAAa,CAAC;IACvB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,wBAAwB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACpG,CAAC;AACH,CAAC;AAED,wBAAwB;AACxB,MAAM,MAAM,GAAG,IAAI,iBAAO,CAAC;IACzB,IAAI,EAAE,uBAAuB;IAC7B,OAAO,EAAE,OAAO;IAChB,YAAY,EACV,iHAAiH;QACjH,mFAAmF;CACtF,CAAC,CAAC;AAEH,2CAA2C;AAC3C,MAAM,CAAC,OAAO,CAAC;IACb,IAAI,EAAE,gBAAgB;IACtB,WAAW,EACT,gFAAgF;QAChF,8FAA8F;IAChG,UAAU,EAAE,OAAC,CAAC,MAAM,CAAC;QACnB,MAAM,EAAE,OAAC;aACN,MAAM,EAAE;aACR,QAAQ,CAAC,kDAAkD,CAAC;QAC/D,WAAW,EAAE,OAAC;aACX,MAAM,CAAC,OAAC,CAAC,MAAM,EAAE,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC;aAC9B,QAAQ,EAAE;aACV,QAAQ,CACP,+IAA+I;YAC/I,8HAA8H,CAC/H;KACJ,CAAC;IACF,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QACtB,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;QAE3B,MAAM,UAAU,GAAG,GAAG,gBAAgB,QAAQ,CAAC;QAC/C,MAAM,WAAW,GAAG;YAClB,QAAQ,EAAE;gBACR;oBACE,IAAI,EAAE,MAAM;oBACZ,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,MAAM;4BACZ,IAAI,EAAE,IAAI,CAAC,MAAM;yBAClB;qBACF;iBACF;aACF;YACD,IAAI,EAAE,KAAK;YACX,GAAG,CAAC,IAAI,CAAC,WAAW,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC;SAC3D,CAAC;QAEF,MAAM,cAAc,GAAG,MAAM,cAAc,CAAC,UAAU,EAAE;YACtD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,MAAM,EAAE,kBAAkB;gBAC1B,WAAW,EAAE,MAAM;gBACnB,cAAc,EAAE,kBAAkB;aACnC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC;SAClC,CAAC,CAAC;QAEH,MAAM,UAAU,GAAG,CAAC,MAAM,cAAc,CAAC,IAAI,EAAE,CAA0B,CAAC;QAC1E,MAAM,SAAS,GAAG,UAAU,CAAC,UAAU,CAAC;QAExC,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;QACrD,CAAC;QAED,kBAAkB;QAClB,MAAM,SAAS,GAAG,MAAM,eAAe,CAAC,SAAS,CAAC,CAAC;QAEnD,0DAA0D;QAC1D,IAAI,aAAiC,CAAC;QACtC,IAAI,CAAC;YACH,aAAa,GAAG,MAAM,mBAAmB,CAAC,SAAS,EAAE,eAAe,EAAE,CAAC,CAAC;QAC1E,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,yCAAyC;YACzC,OAAO,CAAC,KAAK,CAAC,sBAAsB,EAAE,KAAK,CAAC,CAAC;QAC/C,CAAC;QAED,MAAM,UAAU,GAAG,aAAa;YAC9B,CAAC,CAAC,8CAA8C,SAAS,iBAAiB,SAAS,eAAe,aAAa,EAAE;YACjH,CAAC,CAAC,8CAA8C,SAAS,iBAAiB,SAAS,EAAE,CAAC;QAExF,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,UAAU;iBACjB;gBACD,MAAM,IAAA,sBAAY,EAAC,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC;aACvC;SACF,CAAC;IACJ,CAAC;CACF,CAAC,CAAC;AAEH,wBAAwB;AACxB,MAAM,CAAC,OAAO,CAAC;IACb,IAAI,EAAE,YAAY;IAClB,WAAW,EACT,iDAAiD;QACjD,0HAA0H;IAC5H,UAAU,EAAE,OAAC,CAAC,MAAM,CAAC;QACnB,MAAM,EAAE,OAAC;aACN,MAAM,EAAE;aACR,QAAQ,CACP,8IAA8I,CAC/I;QACH,KAAK,EAAE,OAAC;aACL,MAAM,EAAE;aACR,QAAQ,CACP,+EAA+E;YAC/E,uFAAuF;YACvF,iEAAiE,CAClE;KACJ,CAAC;IACF,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QACtB,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;QAE3B,sDAAsD;QACtD,MAAM,cAAc,GAAG,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAErD,MAAM,UAAU,GAAG,GAAG,QAAQ,gBAAgB,CAAC;QAC/C,MAAM,WAAW,GAAG;YAClB,MAAM,EAAE,CAAC,cAAc,CAAC;YACxB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,IAAI,EAAE,OAAO;SACd,CAAC;QAEF,MAAM,cAAc,GAAG,MAAM,cAAc,CAAC,UAAU,EAAE;YACtD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,WAAW,EAAE,MAAM;aACpB;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC;SAClC,CAAC,CAAC;QAEH,MAAM,UAAU,GAAG,CAAC,MAAM,cAAc,CAAC,IAAI,EAAE,CAAqB,CAAC;QACrE,MAAM,SAAS,GAAG,UAAU,CAAC,UAAU,CAAC;QAExC,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;QACrD,CAAC;QAED,IAAI,SAAiB,CAAC;QAEtB,2CAA2C;QAC3C,IAAI,UAAU,CAAC,MAAM,KAAK,SAAS,IAAI,UAAU,CAAC,UAAU,EAAE,CAAC;YAC7D,SAAS,GAAG,UAAU,CAAC,UAAU,CAAC;QACpC,CAAC;aAAM,CAAC;YACN,kBAAkB;YAClB,SAAS,GAAG,MAAM,oBAAoB,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QAC5D,CAAC;QAED,0DAA0D;QAC1D,IAAI,aAAiC,CAAC;QACtC,IAAI,CAAC;YACH,aAAa,GAAG,MAAM,mBAAmB,CAAC,SAAS,EAAE,eAAe,EAAE,CAAC,CAAC;QAC1E,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,yCAAyC;YACzC,OAAO,CAAC,KAAK,CAAC,sBAAsB,EAAE,KAAK,CAAC,CAAC;QAC/C,CAAC;QAED,MAAM,UAAU,GAAG,aAAa;YAC9B,CAAC,CAAC,2CAA2C,SAAS,iBAAiB,SAAS,eAAe,aAAa,EAAE;YAC9G,CAAC,CAAC,2CAA2C,SAAS,iBAAiB,SAAS,EAAE,CAAC;QAErF,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,UAAU;iBACjB;gBACD,MAAM,IAAA,sBAAY,EAAC,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC;aACvC;SACF,CAAC;IACJ,CAAC;CACF,CAAC,CAAC;AAEH,2BAA2B;AAC3B,MAAM,CAAC,OAAO,CAAC;IACb,IAAI,EAAE,gBAAgB;IACtB,WAAW,EACT,wDAAwD;QACxD,8GAA8G;IAChH,UAAU,EAAE,OAAC,CAAC,MAAM,CAAC;QACnB,MAAM,EAAE,OAAC;aACN,MAAM,EAAE;aACR,QAAQ,CACP,yHAAyH,CAC1H;QACH,KAAK,EAAE,OAAC;aACL,MAAM,EAAE;aACR,QAAQ,CACP,+EAA+E;YAC/E,uFAAuF;YACvF,iEAAiE,CAClE;KACJ,CAAC;IACF,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QACtB,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;QAE3B,sDAAsD;QACtD,MAAM,cAAc,GAAG,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAErD,MAAM,UAAU,GAAG,GAAG,QAAQ,gBAAgB,CAAC;QAC/C,MAAM,WAAW,GAAG;YAClB,MAAM,EAAE,CAAC,cAAc,CAAC;YACxB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,IAAI,EAAE,OAAO;SACd,CAAC;QAEF,MAAM,cAAc,GAAG,MAAM,cAAc,CAAC,UAAU,EAAE;YACtD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,WAAW,EAAE,MAAM;aACpB;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC;SAClC,CAAC,CAAC;QAEH,MAAM,UAAU,GAAG,CAAC,MAAM,cAAc,CAAC,IAAI,EAAE,CAAqB,CAAC;QACrE,MAAM,SAAS,GAAG,UAAU,CAAC,UAAU,CAAC;QAExC,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;QACrD,CAAC;QAED,IAAI,SAAiB,CAAC;QAEtB,2CAA2C;QAC3C,IAAI,UAAU,CAAC,MAAM,KAAK,SAAS,IAAI,UAAU,CAAC,UAAU,EAAE,CAAC;YAC7D,SAAS,GAAG,UAAU,CAAC,UAAU,CAAC;QACpC,CAAC;aAAM,CAAC;YACN,kBAAkB;YAClB,SAAS,GAAG,MAAM,oBAAoB,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QAC5D,CAAC;QAED,0DAA0D;QAC1D,IAAI,aAAiC,CAAC;QACtC,IAAI,CAAC;YACH,aAAa,GAAG,MAAM,mBAAmB,CAAC,SAAS,EAAE,eAAe,EAAE,CAAC,CAAC;QAC1E,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,yCAAyC;YACzC,OAAO,CAAC,KAAK,CAAC,sBAAsB,EAAE,KAAK,CAAC,CAAC;QAC/C,CAAC;QAED,MAAM,UAAU,GAAG,aAAa;YAC9B,CAAC,CAAC,8CAA8C,SAAS,iBAAiB,SAAS,eAAe,aAAa,EAAE;YACjH,CAAC,CAAC,8CAA8C,SAAS,iBAAiB,SAAS,EAAE,CAAC;QAExF,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,UAAU;iBACjB;aACF;SACF,CAAC;IACJ,CAAC;CACF,CAAC,CAAC;AAEH,mBAAmB;AACnB,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;IAC5B,MAAM,CAAC,KAAK,CAAC;QACX,aAAa,EAAE,OAAO;KACvB,CAAC,CAAC;AACL,CAAC;AAED,kBAAe,MAAM,CAAC"}
|
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
|
+
}
|