nvidia-nim-mcp 2.0.0 → 2.1.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/dist/client.d.ts +15 -0
- package/dist/client.js +92 -2
- package/dist/config.d.ts +3 -0
- package/dist/config.js +11 -4
- package/dist/handlers.js +113 -6
- package/dist/logger.js +2 -2
- package/dist/models.js +48 -7
- package/dist/tools.d.ts +35 -7
- package/dist/tools.js +15 -3
- package/package.json +1 -1
package/dist/client.d.ts
CHANGED
|
@@ -153,6 +153,21 @@ export declare class NIMClient {
|
|
|
153
153
|
embeddings(request: EmbeddingRequest): Promise<EmbeddingResponse>;
|
|
154
154
|
rerank(request: RerankRequest): Promise<RerankResponse>;
|
|
155
155
|
generateImage(request: ImageGenerationRequest): Promise<ImageGenerationResponse>;
|
|
156
|
+
generateImageFluxSchnell(request: {
|
|
157
|
+
prompt: string;
|
|
158
|
+
width?: number;
|
|
159
|
+
height?: number;
|
|
160
|
+
seed?: number;
|
|
161
|
+
steps?: number;
|
|
162
|
+
}): Promise<ImageGenerationResponse>;
|
|
163
|
+
generateImageFluxKontext(request: {
|
|
164
|
+
prompt: string;
|
|
165
|
+
image: string;
|
|
166
|
+
aspect_ratio?: string;
|
|
167
|
+
steps?: number;
|
|
168
|
+
cfg_scale?: number;
|
|
169
|
+
seed?: number;
|
|
170
|
+
}): Promise<ImageGenerationResponse>;
|
|
156
171
|
analyzeImage(request: ImageAnalysisRequest): Promise<ChatCompletionResponse>;
|
|
157
172
|
listModels(): Promise<string[]>;
|
|
158
173
|
}
|
package/dist/client.js
CHANGED
|
@@ -96,8 +96,13 @@ export class NIMClient {
|
|
|
96
96
|
return new Error(`Authentication failed: ${apiMsg}`);
|
|
97
97
|
if (status === 403)
|
|
98
98
|
return new Error(`Authorization failed: ${apiMsg}`);
|
|
99
|
-
if (status === 404)
|
|
100
|
-
|
|
99
|
+
if (status === 404) {
|
|
100
|
+
const msg = `Model not found: ${apiMsg}. ` +
|
|
101
|
+
`Note: Image generation models (SDXL, FLUX, SD3) are not deployed on the free integration endpoint. ` +
|
|
102
|
+
`They require dedicated GPU instances (H100/B200). ` +
|
|
103
|
+
`Use a self-hosted NIM or check https://build.nvidia.com for available models.`;
|
|
104
|
+
return new Error(msg);
|
|
105
|
+
}
|
|
101
106
|
if (status === 422)
|
|
102
107
|
return new Error(`Invalid request: ${apiMsg}`);
|
|
103
108
|
if (status === 429)
|
|
@@ -144,6 +149,91 @@ export class NIMClient {
|
|
|
144
149
|
});
|
|
145
150
|
return data;
|
|
146
151
|
}
|
|
152
|
+
// ─── FLUX.1-schnell (AI Foundation Models) ──────────────────────────────────
|
|
153
|
+
async generateImageFluxSchnell(request) {
|
|
154
|
+
await this.httpClient.rateLimiter.acquire();
|
|
155
|
+
const payload = {
|
|
156
|
+
prompt: request.prompt,
|
|
157
|
+
width: request.width ?? 1024,
|
|
158
|
+
height: request.height ?? 1024,
|
|
159
|
+
seed: request.seed ?? 0,
|
|
160
|
+
steps: 4, // FLUX Schnell is fixed at 4 steps
|
|
161
|
+
};
|
|
162
|
+
const modelId = config.DEFAULT_FLUX_SCHNELL_MODEL;
|
|
163
|
+
const url = `${config.NVIDIA_AI_FOUNDATION_URL}/${modelId}`;
|
|
164
|
+
logger.debug("FLUX Schnell request", { prompt: request.prompt, width: payload.width, height: payload.height });
|
|
165
|
+
const response = await fetch(url, {
|
|
166
|
+
method: "POST",
|
|
167
|
+
headers: {
|
|
168
|
+
"Authorization": `Bearer ${config.NVIDIA_API_KEY}`,
|
|
169
|
+
"Accept": "application/json",
|
|
170
|
+
"Content-Type": "application/json",
|
|
171
|
+
},
|
|
172
|
+
body: JSON.stringify(payload),
|
|
173
|
+
signal: AbortSignal.timeout(config.IMAGE_GENERATION_TIMEOUT_MS),
|
|
174
|
+
});
|
|
175
|
+
if (!response.ok) {
|
|
176
|
+
const errorText = await response.text();
|
|
177
|
+
logger.error("FLUX Schnell API error", { status: response.status, error: errorText });
|
|
178
|
+
throw new Error(`FLUX Schnell API error (${response.status}): ${errorText}`);
|
|
179
|
+
}
|
|
180
|
+
const data = await response.json();
|
|
181
|
+
logger.debug("FLUX Schnell response", { keys: Object.keys(data), hasImages: !!data.images, hasImage: !!data.image, hasData: !!data.data, hasArtifacts: !!data.artifacts, dataType: typeof data.data, imagesType: typeof data.images });
|
|
182
|
+
// Handle different response formats
|
|
183
|
+
const images = data.images ?? data.data ?? data.artifacts ?? (data.image ? [data.image] : []);
|
|
184
|
+
return {
|
|
185
|
+
created: Date.now(),
|
|
186
|
+
model: modelId,
|
|
187
|
+
data: images.map((img) => ({
|
|
188
|
+
b64_json: img.b64_json ?? img.base64,
|
|
189
|
+
revised_prompt: request.prompt,
|
|
190
|
+
})),
|
|
191
|
+
usage: { total_images: images.length },
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
// ─── FLUX.1-kontext-dev (AI Foundation Models) ──────────────────────────────
|
|
195
|
+
async generateImageFluxKontext(request) {
|
|
196
|
+
await this.httpClient.rateLimiter.acquire();
|
|
197
|
+
const payload = {
|
|
198
|
+
prompt: request.prompt,
|
|
199
|
+
image: request.image,
|
|
200
|
+
aspect_ratio: request.aspect_ratio ?? "match_input_image",
|
|
201
|
+
steps: request.steps ?? 30,
|
|
202
|
+
cfg_scale: request.cfg_scale ?? 3.5,
|
|
203
|
+
seed: request.seed ?? 0,
|
|
204
|
+
};
|
|
205
|
+
const modelId = config.DEFAULT_FLUX_KONTEXT_MODEL;
|
|
206
|
+
const url = `${config.NVIDIA_AI_FOUNDATION_URL}/${modelId}`;
|
|
207
|
+
logger.debug("FLUX Kontext request", { prompt: request.prompt, aspect_ratio: payload.aspect_ratio, steps: payload.steps });
|
|
208
|
+
const response = await fetch(url, {
|
|
209
|
+
method: "POST",
|
|
210
|
+
headers: {
|
|
211
|
+
"Authorization": `Bearer ${config.NVIDIA_API_KEY}`,
|
|
212
|
+
"Accept": "application/json",
|
|
213
|
+
"Content-Type": "application/json",
|
|
214
|
+
},
|
|
215
|
+
body: JSON.stringify(payload),
|
|
216
|
+
signal: AbortSignal.timeout(config.IMAGE_GENERATION_TIMEOUT_MS),
|
|
217
|
+
});
|
|
218
|
+
if (!response.ok) {
|
|
219
|
+
const errorText = await response.text();
|
|
220
|
+
logger.error("FLUX Kontext API error", { status: response.status, error: errorText });
|
|
221
|
+
throw new Error(`FLUX Kontext API error (${response.status}): ${errorText}`);
|
|
222
|
+
}
|
|
223
|
+
const data = await response.json();
|
|
224
|
+
logger.debug("FLUX Kontext response", { keys: Object.keys(data), hasImages: !!data.images, hasImage: !!data.image, hasData: !!data.data, hasArtifacts: !!data.artifacts });
|
|
225
|
+
// Handle different response formats
|
|
226
|
+
const images = data.images ?? data.data ?? data.artifacts ?? (data.image ? [data.image] : []);
|
|
227
|
+
return {
|
|
228
|
+
created: Date.now(),
|
|
229
|
+
model: modelId,
|
|
230
|
+
data: images.map((img) => ({
|
|
231
|
+
b64_json: img.b64_json ?? img.base64,
|
|
232
|
+
revised_prompt: request.prompt,
|
|
233
|
+
})),
|
|
234
|
+
usage: { total_images: images.length },
|
|
235
|
+
};
|
|
236
|
+
}
|
|
147
237
|
async analyzeImage(request) {
|
|
148
238
|
await this.httpClient.rateLimiter.acquire();
|
|
149
239
|
const payload = {
|
package/dist/config.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export declare class ConfigError extends Error {
|
|
|
4
4
|
export declare function getConfig(): {
|
|
5
5
|
NVIDIA_API_KEY?: string;
|
|
6
6
|
NVIDIA_NIM_BASE_URL?: string;
|
|
7
|
+
NVIDIA_AI_FOUNDATION_URL?: string;
|
|
7
8
|
MCP_SERVER_NAME?: string;
|
|
8
9
|
MCP_SERVER_VERSION?: string;
|
|
9
10
|
MCP_SERVER_PORT?: number;
|
|
@@ -18,6 +19,8 @@ export declare function getConfig(): {
|
|
|
18
19
|
DEFAULT_TOP_P?: number;
|
|
19
20
|
DEFAULT_MAX_TOKENS?: number;
|
|
20
21
|
DEFAULT_IMAGE_MODEL?: string;
|
|
22
|
+
DEFAULT_FLUX_SCHNELL_MODEL?: string;
|
|
23
|
+
DEFAULT_FLUX_KONTEXT_MODEL?: string;
|
|
21
24
|
IMAGE_GENERATION_TIMEOUT_MS?: number;
|
|
22
25
|
ENABLE_IMAGE_GENERATION?: boolean;
|
|
23
26
|
ENABLE_VISION?: boolean;
|
package/dist/config.js
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
const ConfigSchema = z.object({
|
|
3
|
-
// NVIDIA API - Primary connection
|
|
3
|
+
// NVIDIA API - Primary connection (self-hosted NIM)
|
|
4
4
|
NVIDIA_API_KEY: z.string().min(1, "NVIDIA_API_KEY is required"),
|
|
5
5
|
NVIDIA_NIM_BASE_URL: z
|
|
6
6
|
.string()
|
|
7
7
|
.url()
|
|
8
8
|
.default("https://integrate.api.nvidia.com/v1"),
|
|
9
|
+
// NVIDIA AI Foundation Models (cloud, free tier available)
|
|
10
|
+
NVIDIA_AI_FOUNDATION_URL: z
|
|
11
|
+
.string()
|
|
12
|
+
.url()
|
|
13
|
+
.default("https://ai.api.nvidia.com/v1/genai"),
|
|
9
14
|
// Server
|
|
10
15
|
MCP_SERVER_NAME: z.string().default("nvidia-nim-mcp"),
|
|
11
16
|
MCP_SERVER_VERSION: z.string().default("1.0.0"),
|
|
@@ -21,12 +26,14 @@ const ConfigSchema = z.object({
|
|
|
21
26
|
MAX_RETRIES: z.coerce.number().int().min(0).max(10).default(3),
|
|
22
27
|
RETRY_DELAY_MS: z.coerce.number().int().positive().default(1000),
|
|
23
28
|
// Defaults
|
|
24
|
-
DEFAULT_MODEL: z.string().default("
|
|
29
|
+
DEFAULT_MODEL: z.string().default("meta/llama-3.1-8b-instruct"),
|
|
25
30
|
DEFAULT_TEMPERATURE: z.coerce.number().min(0).max(2).default(0.3),
|
|
26
31
|
DEFAULT_TOP_P: z.coerce.number().min(0).max(1).default(0.95),
|
|
27
32
|
DEFAULT_MAX_TOKENS: z.coerce.number().int().positive().default(4096),
|
|
28
|
-
// Image Generation
|
|
29
|
-
DEFAULT_IMAGE_MODEL: z.string().default("black-forest-labs/flux.1-
|
|
33
|
+
// Image Generation - AI Foundation Models (free tier available)
|
|
34
|
+
DEFAULT_IMAGE_MODEL: z.string().default("black-forest-labs/flux.1-schnell"),
|
|
35
|
+
DEFAULT_FLUX_SCHNELL_MODEL: z.string().default("black-forest-labs/flux.1-schnell"),
|
|
36
|
+
DEFAULT_FLUX_KONTEXT_MODEL: z.string().default("black-forest-labs/flux.1-kontext-dev"),
|
|
30
37
|
IMAGE_GENERATION_TIMEOUT_MS: z.coerce.number().int().positive().default(300000),
|
|
31
38
|
// Feature flags
|
|
32
39
|
ENABLE_IMAGE_GENERATION: z.coerce.boolean().default(true),
|
package/dist/handlers.js
CHANGED
|
@@ -2,6 +2,9 @@ import { NIM_MODELS, getModelsByCategory, getModel } from "./models.js";
|
|
|
2
2
|
import { getConfig } from "./config.js";
|
|
3
3
|
import { logger } from "./logger.js";
|
|
4
4
|
import { ChatCompletionSchema, TextGenerationSchema, EmbeddingsSchema, RerankSchema, FunctionCallingSchema, ListModelsSchema, ModelInfoSchema, ImageGenerationSchema, ImageAnalysisSchema, MultimodalTaskSchema, CompareModelsSchema, } from "./tools.js";
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
import { writeFileSync, mkdirSync, existsSync } from "fs";
|
|
7
|
+
import { dirname, resolve } from "path";
|
|
5
8
|
const config = getConfig();
|
|
6
9
|
function ok(data) {
|
|
7
10
|
return {
|
|
@@ -14,6 +17,42 @@ function err(message) {
|
|
|
14
17
|
isError: true,
|
|
15
18
|
};
|
|
16
19
|
}
|
|
20
|
+
// Extended schema for FLUX Kontext (image-to-image)
|
|
21
|
+
const FluxKontextSchema = ImageGenerationSchema.extend({
|
|
22
|
+
image: z.string().optional().describe("Base64 data URL of input image (required for FLUX Kontext)"),
|
|
23
|
+
aspect_ratio: z.string().optional().describe("Aspect ratio for output (e.g., 'match_input_image', '1:1', '16:9')"),
|
|
24
|
+
// File save options
|
|
25
|
+
save_path: z.string().optional().describe("Optional file path to save the generated image as PNG (e.g., './output/image.png' or '/absolute/path/image.png')"),
|
|
26
|
+
save_filename: z.string().optional().describe("Optional filename (without extension) to auto-generate path in current directory"),
|
|
27
|
+
});
|
|
28
|
+
// Helper function to save base64 image as PNG file
|
|
29
|
+
function saveBase64Image(base64, savePath, saveFilename) {
|
|
30
|
+
if (!savePath && !saveFilename) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
let filePath;
|
|
34
|
+
if (savePath) {
|
|
35
|
+
filePath = resolve(savePath);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
const timestamp = Date.now();
|
|
39
|
+
const filename = `${saveFilename || `generated_${timestamp}`}.png`;
|
|
40
|
+
filePath = resolve(process.cwd(), filename);
|
|
41
|
+
}
|
|
42
|
+
// Ensure directory exists
|
|
43
|
+
const dir = dirname(filePath);
|
|
44
|
+
if (!existsSync(dir)) {
|
|
45
|
+
mkdirSync(dir, { recursive: true });
|
|
46
|
+
}
|
|
47
|
+
// Remove data URL prefix if present
|
|
48
|
+
const base64Data = base64.replace(/^data:image\/[a-z]+;base64,/, "");
|
|
49
|
+
const buffer = Buffer.from(base64Data, "base64");
|
|
50
|
+
writeFileSync(filePath, buffer);
|
|
51
|
+
return {
|
|
52
|
+
path: filePath,
|
|
53
|
+
absolutePath: filePath,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
17
56
|
export class ToolHandlers {
|
|
18
57
|
client;
|
|
19
58
|
constructor(client) {
|
|
@@ -217,6 +256,69 @@ export class ToolHandlers {
|
|
|
217
256
|
}
|
|
218
257
|
const args = ImageGenerationSchema.parse(rawArgs);
|
|
219
258
|
const model = args.model ?? config.DEFAULT_IMAGE_MODEL;
|
|
259
|
+
// Route to appropriate backend based on model
|
|
260
|
+
const isFluxSchnell = model === "black-forest-labs/flux.1-schnell" || model === config.DEFAULT_FLUX_SCHNELL_MODEL;
|
|
261
|
+
const isFluxKontext = model === "black-forest-labs/flux.1-kontext-dev" || model === config.DEFAULT_FLUX_KONTEXT_MODEL;
|
|
262
|
+
// FLUX.1-schnell: Fast text-to-image via AI Foundation
|
|
263
|
+
if (isFluxSchnell) {
|
|
264
|
+
const fluxArgs = FluxKontextSchema.parse(rawArgs); // Reuse schema, image is optional
|
|
265
|
+
const response = await this.client.generateImageFluxSchnell({
|
|
266
|
+
prompt: fluxArgs.prompt,
|
|
267
|
+
width: fluxArgs.width,
|
|
268
|
+
height: fluxArgs.height,
|
|
269
|
+
seed: fluxArgs.seed,
|
|
270
|
+
});
|
|
271
|
+
const images = response.data.map((img, idx) => {
|
|
272
|
+
const saved = saveBase64Image(img.b64_json, fluxArgs.save_path, fluxArgs.save_filename);
|
|
273
|
+
return {
|
|
274
|
+
index: idx,
|
|
275
|
+
b64_json: img.b64_json,
|
|
276
|
+
revised_prompt: img.revised_prompt,
|
|
277
|
+
saved_path: saved?.absolutePath,
|
|
278
|
+
};
|
|
279
|
+
});
|
|
280
|
+
return ok({
|
|
281
|
+
model: response.model,
|
|
282
|
+
created: response.created,
|
|
283
|
+
images,
|
|
284
|
+
usage: response.usage,
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
// FLUX.1-kontext-dev: Image-to-image editing via AI Foundation
|
|
288
|
+
if (isFluxKontext) {
|
|
289
|
+
const fluxArgs = FluxKontextSchema.parse(rawArgs);
|
|
290
|
+
if (!fluxArgs.image) {
|
|
291
|
+
return err("FLUX Kontext requires an 'image' parameter (base64 data URL of input image)");
|
|
292
|
+
}
|
|
293
|
+
const response = await this.client.generateImageFluxKontext({
|
|
294
|
+
prompt: fluxArgs.prompt,
|
|
295
|
+
image: fluxArgs.image,
|
|
296
|
+
aspect_ratio: fluxArgs.aspect_ratio,
|
|
297
|
+
steps: fluxArgs.steps,
|
|
298
|
+
cfg_scale: fluxArgs.cfg_scale,
|
|
299
|
+
seed: fluxArgs.seed,
|
|
300
|
+
});
|
|
301
|
+
const images = response.data.map((img, idx) => {
|
|
302
|
+
const saved = saveBase64Image(img.b64_json, fluxArgs.save_path, fluxArgs.save_filename);
|
|
303
|
+
return {
|
|
304
|
+
index: idx,
|
|
305
|
+
b64_json: img.b64_json,
|
|
306
|
+
revised_prompt: img.revised_prompt,
|
|
307
|
+
saved_path: saved?.absolutePath,
|
|
308
|
+
};
|
|
309
|
+
});
|
|
310
|
+
return ok({
|
|
311
|
+
model: response.model,
|
|
312
|
+
created: response.created,
|
|
313
|
+
images,
|
|
314
|
+
usage: response.usage,
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
// Self-hosted NIM (SDXL, SD3, flux.1-dev, etc.)
|
|
318
|
+
if (!config.DEFAULT_IMAGE_MODEL && !args.model) {
|
|
319
|
+
return err("No default image generation model configured for self-hosted NIM. " +
|
|
320
|
+
"Set DEFAULT_IMAGE_MODEL or specify a model explicitly.");
|
|
321
|
+
}
|
|
220
322
|
const request = {
|
|
221
323
|
model,
|
|
222
324
|
prompt: args.prompt,
|
|
@@ -229,18 +331,23 @@ export class ToolHandlers {
|
|
|
229
331
|
seed: args.seed,
|
|
230
332
|
sampler: args.sampler,
|
|
231
333
|
scheduler: args.scheduler,
|
|
232
|
-
response_format: args.response_format,
|
|
334
|
+
response_format: args.response_format ?? "b64_json",
|
|
233
335
|
};
|
|
234
336
|
const response = await this.client.generateImage(request);
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
images: response.data.map((img, idx) => ({
|
|
337
|
+
const images = response.data.map((img, idx) => {
|
|
338
|
+
const saved = saveBase64Image(img.b64_json ?? "", args.save_path, args.save_filename);
|
|
339
|
+
return {
|
|
239
340
|
index: idx,
|
|
240
341
|
url: img.url,
|
|
241
342
|
b64_json: img.b64_json,
|
|
242
343
|
revised_prompt: img.revised_prompt,
|
|
243
|
-
|
|
344
|
+
saved_path: saved?.absolutePath,
|
|
345
|
+
};
|
|
346
|
+
});
|
|
347
|
+
return ok({
|
|
348
|
+
model: response.model ?? model,
|
|
349
|
+
created: response.created,
|
|
350
|
+
images,
|
|
244
351
|
usage: response.usage,
|
|
245
352
|
});
|
|
246
353
|
}
|
package/dist/logger.js
CHANGED
|
@@ -10,7 +10,7 @@ export let logger = winston.createLogger({
|
|
|
10
10
|
},
|
|
11
11
|
transports: [
|
|
12
12
|
new winston.transports.Console({
|
|
13
|
-
stderrLevels: ["error", "warn"],
|
|
13
|
+
stderrLevels: ["error", "warn", "info", "debug", "silly"],
|
|
14
14
|
}),
|
|
15
15
|
],
|
|
16
16
|
});
|
|
@@ -27,7 +27,7 @@ export function initLogger(options) {
|
|
|
27
27
|
},
|
|
28
28
|
transports: [
|
|
29
29
|
new winston.transports.Console({
|
|
30
|
-
stderrLevels: ["error", "warn"],
|
|
30
|
+
stderrLevels: ["error", "warn", "info", "debug", "silly"],
|
|
31
31
|
}),
|
|
32
32
|
],
|
|
33
33
|
});
|
package/dist/models.js
CHANGED
|
@@ -976,10 +976,49 @@ export const NIM_MODELS = {
|
|
|
976
976
|
},
|
|
977
977
|
tags: ["text-to-image", "photorealistic", "flux", "controlnet", "controlnet-canny", "controlnet-depth"],
|
|
978
978
|
},
|
|
979
|
+
// === FLUX.1 AI Foundation Models (Free Tier) ===
|
|
980
|
+
"black-forest-labs/flux.1-schnell": {
|
|
981
|
+
id: "black-forest-labs/flux.1-schnell",
|
|
982
|
+
name: "FLUX.1 [schnell]",
|
|
983
|
+
description: "Fast text-to-image model (4 steps, distilled). Optimized for speed. Available on NVIDIA AI Foundation free tier.",
|
|
984
|
+
category: "image_generation",
|
|
985
|
+
contextLength: 512,
|
|
986
|
+
supportsStreaming: false,
|
|
987
|
+
supportsFunctionCalling: false,
|
|
988
|
+
supportsImageGeneration: true,
|
|
989
|
+
maxTokens: 512,
|
|
990
|
+
recommendedUseCases: [
|
|
991
|
+
"Fast text-to-image generation",
|
|
992
|
+
"Rapid prototyping",
|
|
993
|
+
"Real-time applications",
|
|
994
|
+
"Interactive image generation",
|
|
995
|
+
],
|
|
996
|
+
license: "Apache 2.0 (non-commercial default, commercial via contact)",
|
|
997
|
+
commercialUse: false,
|
|
998
|
+
thirdPartyModel: true,
|
|
999
|
+
minGpuRequirements: ["N/A - Cloud API"],
|
|
1000
|
+
supportedHardware: ["Cloud"],
|
|
1001
|
+
runtimeEngines: ["NVIDIA AI Foundation"],
|
|
1002
|
+
imageGenSpecs: {
|
|
1003
|
+
supportedResolutions: ["1024x1024", "1152x896", "896x1152", "1344x768", "768x1344"],
|
|
1004
|
+
supportedAspectRatios: ["1:1", "16:9", "9:16", "4:3", "3:4", "21:9", "9:21"],
|
|
1005
|
+
maxImagesPerRequest: 1,
|
|
1006
|
+
recommendedSamplers: ["euler"],
|
|
1007
|
+
recommendedSchedulers: ["simple"],
|
|
1008
|
+
defaultSteps: 4,
|
|
1009
|
+
defaultCfgScale: 1.0,
|
|
1010
|
+
supportsNegativePrompt: false,
|
|
1011
|
+
supportsImageToImage: false,
|
|
1012
|
+
supportsInpainting: false,
|
|
1013
|
+
supportsControlNet: false,
|
|
1014
|
+
},
|
|
1015
|
+
tags: ["text-to-image", "fast", "schnell", "flux", "free-tier", "distilled"],
|
|
1016
|
+
deploymentNotes: "Available via NVIDIA AI Foundation Models API (https://ai.api.nvidia.com/v1/genai/black-forest-labs/flux.1-schnell). 4-step distilled model for rapid generation.",
|
|
1017
|
+
},
|
|
979
1018
|
"black-forest-labs/flux.1-kontext-dev": {
|
|
980
1019
|
id: "black-forest-labs/flux.1-kontext-dev",
|
|
981
1020
|
name: "FLUX.1 Kontext [dev]",
|
|
982
|
-
description: "
|
|
1021
|
+
description: "Image-to-image editing with context preservation. Inpainting, outpainting, style transfer with layout preservation. Available on NVIDIA AI Foundation free tier.",
|
|
983
1022
|
category: "image_generation",
|
|
984
1023
|
contextLength: 512,
|
|
985
1024
|
supportsStreaming: false,
|
|
@@ -991,27 +1030,29 @@ export const NIM_MODELS = {
|
|
|
991
1030
|
"Inpainting and outpainting",
|
|
992
1031
|
"Style transfer with layout preservation",
|
|
993
1032
|
"Character consistency across images",
|
|
1033
|
+
"Object replacement in images",
|
|
994
1034
|
],
|
|
995
1035
|
license: "Apache 2.0 (non-commercial default, commercial via contact)",
|
|
996
1036
|
commercialUse: false,
|
|
997
1037
|
thirdPartyModel: true,
|
|
998
|
-
minGpuRequirements: ["
|
|
999
|
-
supportedHardware: ["
|
|
1000
|
-
runtimeEngines: ["
|
|
1038
|
+
minGpuRequirements: ["N/A - Cloud API"],
|
|
1039
|
+
supportedHardware: ["Cloud"],
|
|
1040
|
+
runtimeEngines: ["NVIDIA AI Foundation"],
|
|
1001
1041
|
imageGenSpecs: {
|
|
1002
1042
|
supportedResolutions: ["1024x1024", "1152x896", "896x1152", "1344x768", "768x1344"],
|
|
1003
|
-
supportedAspectRatios: ["1:1", "16:9", "9:16", "4:3", "3:4", "21:9", "9:21"],
|
|
1043
|
+
supportedAspectRatios: ["1:1", "16:9", "9:16", "4:3", "3:4", "21:9", "9:21", "match_input_image"],
|
|
1004
1044
|
maxImagesPerRequest: 1,
|
|
1005
1045
|
recommendedSamplers: ["euler", "euler_a"],
|
|
1006
1046
|
recommendedSchedulers: ["simple"],
|
|
1007
|
-
defaultSteps:
|
|
1047
|
+
defaultSteps: 30,
|
|
1008
1048
|
defaultCfgScale: 3.5,
|
|
1009
1049
|
supportsNegativePrompt: true,
|
|
1010
1050
|
supportsImageToImage: true,
|
|
1011
1051
|
supportsInpainting: true,
|
|
1012
1052
|
supportsControlNet: false,
|
|
1013
1053
|
},
|
|
1014
|
-
tags: ["image-to-image", "editing", "inpainting", "outpainting", "style-transfer", "flux", "character-consistency"],
|
|
1054
|
+
tags: ["image-to-image", "editing", "inpainting", "outpainting", "style-transfer", "flux", "kontext", "free-tier", "character-consistency"],
|
|
1055
|
+
deploymentNotes: "Available via NVIDIA AI Foundation Models API (https://ai.api.nvidia.com/v1/genai/black-forest-labs/flux.1-kontext-dev). Requires input image as base64 data URL.",
|
|
1015
1056
|
},
|
|
1016
1057
|
// === Multimodal ===
|
|
1017
1058
|
"nvidia/neva-22b": {
|
package/dist/tools.d.ts
CHANGED
|
@@ -73,6 +73,7 @@ export declare const ChatCompletionSchema: z.ZodObject<{
|
|
|
73
73
|
presence_penalty: z.ZodOptional<z.ZodNumber>;
|
|
74
74
|
seed: z.ZodOptional<z.ZodNumber>;
|
|
75
75
|
}, "strip", z.ZodTypeAny, {
|
|
76
|
+
seed?: number;
|
|
76
77
|
model?: string;
|
|
77
78
|
messages?: {
|
|
78
79
|
role?: "system" | "user" | "assistant";
|
|
@@ -85,8 +86,8 @@ export declare const ChatCompletionSchema: z.ZodObject<{
|
|
|
85
86
|
stop?: string | string[];
|
|
86
87
|
frequency_penalty?: number;
|
|
87
88
|
presence_penalty?: number;
|
|
88
|
-
seed?: number;
|
|
89
89
|
}, {
|
|
90
|
+
seed?: number;
|
|
90
91
|
model?: string;
|
|
91
92
|
messages?: {
|
|
92
93
|
role?: "system" | "user" | "assistant";
|
|
@@ -99,7 +100,6 @@ export declare const ChatCompletionSchema: z.ZodObject<{
|
|
|
99
100
|
stop?: string | string[];
|
|
100
101
|
frequency_penalty?: number;
|
|
101
102
|
presence_penalty?: number;
|
|
102
|
-
seed?: number;
|
|
103
103
|
}>;
|
|
104
104
|
export declare const TextGenerationSchema: z.ZodObject<{
|
|
105
105
|
model: z.ZodOptional<z.ZodString>;
|
|
@@ -290,9 +290,14 @@ export declare const ImageGenerationSchema: z.ZodObject<{
|
|
|
290
290
|
sampler: z.ZodOptional<z.ZodString>;
|
|
291
291
|
scheduler: z.ZodOptional<z.ZodString>;
|
|
292
292
|
response_format: z.ZodDefault<z.ZodOptional<z.ZodEnum<["url", "b64_json"]>>>;
|
|
293
|
+
image: z.ZodOptional<z.ZodString>;
|
|
294
|
+
aspect_ratio: z.ZodOptional<z.ZodString>;
|
|
295
|
+
save_path: z.ZodOptional<z.ZodString>;
|
|
296
|
+
save_filename: z.ZodOptional<z.ZodString>;
|
|
293
297
|
}, "strip", z.ZodTypeAny, {
|
|
294
|
-
|
|
298
|
+
image?: string;
|
|
295
299
|
seed?: number;
|
|
300
|
+
model?: string;
|
|
296
301
|
prompt?: string;
|
|
297
302
|
negative_prompt?: string;
|
|
298
303
|
width?: number;
|
|
@@ -303,9 +308,13 @@ export declare const ImageGenerationSchema: z.ZodObject<{
|
|
|
303
308
|
sampler?: string;
|
|
304
309
|
scheduler?: string;
|
|
305
310
|
response_format?: "url" | "b64_json";
|
|
311
|
+
aspect_ratio?: string;
|
|
312
|
+
save_path?: string;
|
|
313
|
+
save_filename?: string;
|
|
306
314
|
}, {
|
|
307
|
-
|
|
315
|
+
image?: string;
|
|
308
316
|
seed?: number;
|
|
317
|
+
model?: string;
|
|
309
318
|
prompt?: string;
|
|
310
319
|
negative_prompt?: string;
|
|
311
320
|
width?: number;
|
|
@@ -316,6 +325,9 @@ export declare const ImageGenerationSchema: z.ZodObject<{
|
|
|
316
325
|
sampler?: string;
|
|
317
326
|
scheduler?: string;
|
|
318
327
|
response_format?: "url" | "b64_json";
|
|
328
|
+
aspect_ratio?: string;
|
|
329
|
+
save_path?: string;
|
|
330
|
+
save_filename?: string;
|
|
319
331
|
}>;
|
|
320
332
|
export declare const ImageAnalysisSchema: z.ZodObject<{
|
|
321
333
|
model: z.ZodOptional<z.ZodString>;
|
|
@@ -755,13 +767,13 @@ export declare const TOOL_DEFINITIONS: readonly [{
|
|
|
755
767
|
};
|
|
756
768
|
}, {
|
|
757
769
|
readonly name: "generate_image";
|
|
758
|
-
readonly description: "Generate images from text prompts using NVIDIA NIM image generation models (Stable Diffusion XL, SDXL Turbo, SD3, FLUX.1). Supports various resolutions, samplers, and schedulers.";
|
|
770
|
+
readonly description: "Generate images from text prompts using NVIDIA NIM image generation models (Stable Diffusion XL, SDXL Turbo, SD3, FLUX.1). Supports various resolutions, samplers, and schedulers. FLUX.1-schnell and FLUX.1-kontext-dev are available on the free NVIDIA AI Foundation tier. Can save generated images as PNG files to disk.";
|
|
759
771
|
readonly inputSchema: {
|
|
760
772
|
readonly type: "object";
|
|
761
773
|
readonly properties: {
|
|
762
774
|
readonly model: {
|
|
763
775
|
readonly type: "string";
|
|
764
|
-
readonly description: "Image generation model ID (e.g., nvidia/stable-diffusion-xl, nvidia/sdxl-turbo, stabilityai/sd-3-medium, black-forest-labs/flux.1-dev)";
|
|
776
|
+
readonly description: "Image generation model ID (e.g., nvidia/stable-diffusion-xl, nvidia/sdxl-turbo, stabilityai/sd-3-medium, black-forest-labs/flux.1-dev, black-forest-labs/flux.1-schnell, black-forest-labs/flux.1-kontext-dev)";
|
|
765
777
|
};
|
|
766
778
|
readonly prompt: {
|
|
767
779
|
readonly type: "string";
|
|
@@ -797,7 +809,7 @@ export declare const TOOL_DEFINITIONS: readonly [{
|
|
|
797
809
|
readonly minimum: 1;
|
|
798
810
|
readonly maximum: 100;
|
|
799
811
|
readonly default: 20;
|
|
800
|
-
readonly description: "Number of diffusion steps";
|
|
812
|
+
readonly description: "Number of diffusion steps (ignored for FLUX Schnell, fixed at 4)";
|
|
801
813
|
};
|
|
802
814
|
readonly cfg_scale: {
|
|
803
815
|
readonly type: "number";
|
|
@@ -824,6 +836,22 @@ export declare const TOOL_DEFINITIONS: readonly [{
|
|
|
824
836
|
readonly default: "url";
|
|
825
837
|
readonly description: "Response format: URL or base64 JSON";
|
|
826
838
|
};
|
|
839
|
+
readonly image: {
|
|
840
|
+
readonly type: "string";
|
|
841
|
+
readonly description: "Base64 data URL of input image (required for FLUX Kontext image-to-image editing, format: data:image/png;base64,...)";
|
|
842
|
+
};
|
|
843
|
+
readonly aspect_ratio: {
|
|
844
|
+
readonly type: "string";
|
|
845
|
+
readonly description: "Aspect ratio for output (e.g., 'match_input_image', '1:1', '16:9', '4:3', '3:4', '21:9')";
|
|
846
|
+
};
|
|
847
|
+
readonly save_path: {
|
|
848
|
+
readonly type: "string";
|
|
849
|
+
readonly description: "Optional file path to save the generated image as PNG (e.g., './output/image.png' or '/absolute/path/image.png')";
|
|
850
|
+
};
|
|
851
|
+
readonly save_filename: {
|
|
852
|
+
readonly type: "string";
|
|
853
|
+
readonly description: "Optional filename (without extension) to auto-generate path in current directory (e.g., 'my-image' creates './my-image.png')";
|
|
854
|
+
};
|
|
827
855
|
};
|
|
828
856
|
readonly required: readonly ["prompt"];
|
|
829
857
|
};
|
package/dist/tools.js
CHANGED
|
@@ -81,6 +81,12 @@ export const ImageGenerationSchema = z.object({
|
|
|
81
81
|
sampler: z.string().optional().describe("Sampler algorithm (e.g., euler, euler_a, dpmpp_2m)"),
|
|
82
82
|
scheduler: z.string().optional().describe("Scheduler type (e.g., karras, exponential, simple)"),
|
|
83
83
|
response_format: z.enum(["url", "b64_json"]).optional().default("url").describe("Response format"),
|
|
84
|
+
// FLUX Kontext specific parameters
|
|
85
|
+
image: z.string().optional().describe("Base64 data URL of input image (required for FLUX Kontext image-to-image editing)"),
|
|
86
|
+
aspect_ratio: z.string().optional().describe("Aspect ratio for output (e.g., 'match_input_image', '1:1', '16:9', '4:3')"),
|
|
87
|
+
// File save options
|
|
88
|
+
save_path: z.string().optional().describe("Optional file path to save the generated image as PNG (e.g., './output/image.png' or '/absolute/path/image.png')"),
|
|
89
|
+
save_filename: z.string().optional().describe("Optional filename (without extension) to auto-generate path in current directory"),
|
|
84
90
|
});
|
|
85
91
|
export const ImageAnalysisSchema = z.object({
|
|
86
92
|
model: z.string().optional().describe("Vision/multimodal model ID"),
|
|
@@ -281,22 +287,28 @@ export const TOOL_DEFINITIONS = [
|
|
|
281
287
|
},
|
|
282
288
|
{
|
|
283
289
|
name: "generate_image",
|
|
284
|
-
description: "Generate images from text prompts using NVIDIA NIM image generation models (Stable Diffusion XL, SDXL Turbo, SD3, FLUX.1). Supports various resolutions, samplers, and schedulers.",
|
|
290
|
+
description: "Generate images from text prompts using NVIDIA NIM image generation models (Stable Diffusion XL, SDXL Turbo, SD3, FLUX.1). Supports various resolutions, samplers, and schedulers. FLUX.1-schnell and FLUX.1-kontext-dev are available on the free NVIDIA AI Foundation tier. Can save generated images as PNG files to disk.",
|
|
285
291
|
inputSchema: {
|
|
286
292
|
type: "object",
|
|
287
293
|
properties: {
|
|
288
|
-
model: { type: "string", description: "Image generation model ID (e.g., nvidia/stable-diffusion-xl, nvidia/sdxl-turbo, stabilityai/sd-3-medium, black-forest-labs/flux.1-dev)" },
|
|
294
|
+
model: { type: "string", description: "Image generation model ID (e.g., nvidia/stable-diffusion-xl, nvidia/sdxl-turbo, stabilityai/sd-3-medium, black-forest-labs/flux.1-dev, black-forest-labs/flux.1-schnell, black-forest-labs/flux.1-kontext-dev)" },
|
|
289
295
|
prompt: { type: "string", description: "Text prompt describing the image to generate" },
|
|
290
296
|
negative_prompt: { type: "string", description: "Negative prompt to avoid unwanted features" },
|
|
291
297
|
width: { type: "integer", minimum: 64, maximum: 2048, default: 1024, description: "Image width in pixels" },
|
|
292
298
|
height: { type: "integer", minimum: 64, maximum: 2048, default: 1024, description: "Image height in pixels" },
|
|
293
299
|
num_images: { type: "integer", minimum: 1, maximum: 4, default: 1, description: "Number of images to generate" },
|
|
294
|
-
steps: { type: "integer", minimum: 1, maximum: 100, default: 20, description: "Number of diffusion steps" },
|
|
300
|
+
steps: { type: "integer", minimum: 1, maximum: 100, default: 20, description: "Number of diffusion steps (ignored for FLUX Schnell, fixed at 4)" },
|
|
295
301
|
cfg_scale: { type: "number", minimum: 1, maximum: 20, default: 7.0, description: "Classifier-free guidance scale" },
|
|
296
302
|
seed: { type: "integer", description: "Random seed for reproducibility" },
|
|
297
303
|
sampler: { type: "string", description: "Sampler algorithm (e.g., euler, euler_a, dpmpp_2m, dpmpp_sde, ddim)" },
|
|
298
304
|
scheduler: { type: "string", description: "Scheduler type (e.g., karras, exponential, simple, ddim_uniform)" },
|
|
299
305
|
response_format: { type: "string", enum: ["url", "b64_json"], default: "url", description: "Response format: URL or base64 JSON" },
|
|
306
|
+
// FLUX Kontext specific parameters
|
|
307
|
+
image: { type: "string", description: "Base64 data URL of input image (required for FLUX Kontext image-to-image editing, format: data:image/png;base64,...)" },
|
|
308
|
+
aspect_ratio: { type: "string", description: "Aspect ratio for output (e.g., 'match_input_image', '1:1', '16:9', '4:3', '3:4', '21:9')" },
|
|
309
|
+
// File save options
|
|
310
|
+
save_path: { type: "string", description: "Optional file path to save the generated image as PNG (e.g., './output/image.png' or '/absolute/path/image.png')" },
|
|
311
|
+
save_filename: { type: "string", description: "Optional filename (without extension) to auto-generate path in current directory (e.g., 'my-image' creates './my-image.png')" },
|
|
300
312
|
},
|
|
301
313
|
required: ["prompt"],
|
|
302
314
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nvidia-nim-mcp",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Production-ready MCP server for NVIDIA NIM models - 50+ LLMs, multimodal, image generation, embeddings, reranking with rich metadata for agent selection",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|