text2image-mcp 2.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 +359 -0
- package/dist/chat-session.d.ts +20 -0
- package/dist/chat-session.d.ts.map +1 -0
- package/dist/chat-session.js +54 -0
- package/dist/chat-session.js.map +1 -0
- package/dist/config.d.ts +13 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +56 -0
- package/dist/config.js.map +1 -0
- package/dist/image-utils.d.ts +12 -0
- package/dist/image-utils.d.ts.map +1 -0
- package/dist/image-utils.js +48 -0
- package/dist/image-utils.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +11 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +98 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/config-tools.d.ts +7 -0
- package/dist/tools/config-tools.d.ts.map +1 -0
- package/dist/tools/config-tools.js +48 -0
- package/dist/tools/config-tools.js.map +1 -0
- package/dist/tools/continue.d.ts +9 -0
- package/dist/tools/continue.d.ts.map +1 -0
- package/dist/tools/continue.js +111 -0
- package/dist/tools/continue.js.map +1 -0
- package/dist/tools/edit.d.ts +8 -0
- package/dist/tools/edit.d.ts.map +1 -0
- package/dist/tools/edit.js +123 -0
- package/dist/tools/edit.js.map +1 -0
- package/dist/tools/generate.d.ts +9 -0
- package/dist/tools/generate.d.ts.map +1 -0
- package/dist/tools/generate.js +106 -0
- package/dist/tools/generate.js.map +1 -0
- package/dist/tools/info.d.ts +4 -0
- package/dist/tools/info.d.ts.map +1 -0
- package/dist/tools/info.js +38 -0
- package/dist/tools/info.js.map +1 -0
- package/dist/types.d.ts +25 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +19 -0
- package/dist/types.js.map +1 -0
- package/package.json +63 -0
package/dist/server.js
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// src/server.ts
|
|
2
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
3
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, ErrorCode, McpError, } from "@modelcontextprotocol/sdk/types.js";
|
|
4
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5
|
+
import { ConfigManager } from "./config.js";
|
|
6
|
+
import { ChatSessionManager } from "./chat-session.js";
|
|
7
|
+
// Tool definitions & handlers
|
|
8
|
+
import { configureGeminiTokenTool, getConfigurationStatusTool, handleConfigureToken, handleGetConfigStatus } from "./tools/config-tools.js";
|
|
9
|
+
import { generateImageTool, handleGenerateImage } from "./tools/generate.js";
|
|
10
|
+
import { editImageTool, handleEditImage } from "./tools/edit.js";
|
|
11
|
+
import { continueEditingTool, handleContinueEditing } from "./tools/continue.js";
|
|
12
|
+
import { getLastImageInfoTool, handleGetLastImageInfo } from "./tools/info.js";
|
|
13
|
+
export class NanoBananaMCP {
|
|
14
|
+
server;
|
|
15
|
+
configManager;
|
|
16
|
+
chatSession = null;
|
|
17
|
+
lastImagePath = null;
|
|
18
|
+
constructor() {
|
|
19
|
+
this.configManager = new ConfigManager();
|
|
20
|
+
this.server = new Server({ name: "text2image-mcp", version: "2.0.0" }, { capabilities: { tools: {} } });
|
|
21
|
+
this.setupHandlers();
|
|
22
|
+
}
|
|
23
|
+
setupHandlers() {
|
|
24
|
+
// List tools
|
|
25
|
+
this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
26
|
+
tools: [
|
|
27
|
+
configureGeminiTokenTool,
|
|
28
|
+
getConfigurationStatusTool,
|
|
29
|
+
generateImageTool,
|
|
30
|
+
editImageTool,
|
|
31
|
+
continueEditingTool,
|
|
32
|
+
getLastImageInfoTool,
|
|
33
|
+
],
|
|
34
|
+
}));
|
|
35
|
+
// Call tools
|
|
36
|
+
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
37
|
+
try {
|
|
38
|
+
return await this.routeToolCall(request);
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
if (error instanceof McpError)
|
|
42
|
+
throw error;
|
|
43
|
+
throw new McpError(ErrorCode.InternalError, `Tool execution failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
async routeToolCall(request) {
|
|
48
|
+
const { name } = request.params;
|
|
49
|
+
// Config tools don't need API key
|
|
50
|
+
if (name === "configure_gemini_token") {
|
|
51
|
+
return handleConfigureToken(request, this.configManager);
|
|
52
|
+
}
|
|
53
|
+
if (name === "get_configuration_status") {
|
|
54
|
+
return handleGetConfigStatus(this.configManager);
|
|
55
|
+
}
|
|
56
|
+
// All other tools need configured API
|
|
57
|
+
if (!this.configManager.isConfigured()) {
|
|
58
|
+
throw new McpError(ErrorCode.InvalidRequest, "Gemini API token not configured. Use configure_gemini_token first or set GEMINI_API_KEY env var.");
|
|
59
|
+
}
|
|
60
|
+
const genAI = this.configManager.genAI;
|
|
61
|
+
// Lazy-init chat session manager
|
|
62
|
+
if (!this.chatSession) {
|
|
63
|
+
this.chatSession = new ChatSessionManager(genAI);
|
|
64
|
+
}
|
|
65
|
+
switch (name) {
|
|
66
|
+
case "generate_image": {
|
|
67
|
+
const { result, savedPath } = await handleGenerateImage(request, genAI, this.chatSession);
|
|
68
|
+
if (savedPath)
|
|
69
|
+
this.lastImagePath = savedPath;
|
|
70
|
+
return result;
|
|
71
|
+
}
|
|
72
|
+
case "edit_image": {
|
|
73
|
+
const { result, savedPath } = await handleEditImage(request, genAI);
|
|
74
|
+
if (savedPath) {
|
|
75
|
+
this.lastImagePath = savedPath;
|
|
76
|
+
this.chatSession.reset(); // New base image, reset chat context
|
|
77
|
+
}
|
|
78
|
+
return result;
|
|
79
|
+
}
|
|
80
|
+
case "continue_editing": {
|
|
81
|
+
const { result, savedPath } = await handleContinueEditing(request, genAI, this.chatSession, this.lastImagePath);
|
|
82
|
+
if (savedPath)
|
|
83
|
+
this.lastImagePath = savedPath;
|
|
84
|
+
return result;
|
|
85
|
+
}
|
|
86
|
+
case "get_last_image_info":
|
|
87
|
+
return handleGetLastImageInfo(this.lastImagePath);
|
|
88
|
+
default:
|
|
89
|
+
throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
async run() {
|
|
93
|
+
await this.configManager.load();
|
|
94
|
+
const transport = new StdioServerTransport();
|
|
95
|
+
await this.server.connect(transport);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { CallToolRequest, CallToolResult, Tool } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
import { ConfigManager } from "../config.js";
|
|
3
|
+
export declare const configureGeminiTokenTool: Tool;
|
|
4
|
+
export declare const getConfigurationStatusTool: Tool;
|
|
5
|
+
export declare function handleConfigureToken(request: CallToolRequest, configManager: ConfigManager): Promise<CallToolResult>;
|
|
6
|
+
export declare function handleGetConfigStatus(configManager: ConfigManager): Promise<CallToolResult>;
|
|
7
|
+
//# sourceMappingURL=config-tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-tools.d.ts","sourceRoot":"","sources":["../../src/tools/config-tools.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAC3F,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,eAAO,MAAM,wBAAwB,EAAE,IAatC,CAAC;AAEF,eAAO,MAAM,0BAA0B,EAAE,IAQxC,CAAC;AAEF,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,eAAe,EACxB,aAAa,EAAE,aAAa,GAC3B,OAAO,CAAC,cAAc,CAAC,CAUzB;AAED,wBAAsB,qBAAqB,CACzC,aAAa,EAAE,aAAa,GAC3B,OAAO,CAAC,cAAc,CAAC,CAczB"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export const configureGeminiTokenTool = {
|
|
2
|
+
name: "configure_gemini_token",
|
|
3
|
+
description: "Configure your Gemini API token for nano-banana image generation",
|
|
4
|
+
inputSchema: {
|
|
5
|
+
type: "object",
|
|
6
|
+
properties: {
|
|
7
|
+
apiKey: {
|
|
8
|
+
type: "string",
|
|
9
|
+
description: "Your Gemini API key from Google AI Studio",
|
|
10
|
+
},
|
|
11
|
+
},
|
|
12
|
+
required: ["apiKey"],
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
export const getConfigurationStatusTool = {
|
|
16
|
+
name: "get_configuration_status",
|
|
17
|
+
description: "Check if Gemini API token is configured",
|
|
18
|
+
inputSchema: {
|
|
19
|
+
type: "object",
|
|
20
|
+
properties: {},
|
|
21
|
+
additionalProperties: false,
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
export async function handleConfigureToken(request, configManager) {
|
|
25
|
+
const { apiKey } = request.params.arguments;
|
|
26
|
+
await configManager.setApiKey(apiKey);
|
|
27
|
+
return {
|
|
28
|
+
content: [{
|
|
29
|
+
type: "text",
|
|
30
|
+
text: "Gemini API token configured successfully. You can now use nano-banana image generation features.",
|
|
31
|
+
}],
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export async function handleGetConfigStatus(configManager) {
|
|
35
|
+
const isConfigured = configManager.isConfigured();
|
|
36
|
+
let statusText;
|
|
37
|
+
if (isConfigured) {
|
|
38
|
+
const sourceLabel = configManager.configSource === "environment"
|
|
39
|
+
? "Environment variable (GEMINI_API_KEY)"
|
|
40
|
+
: "Local configuration file (.nano-banana-config.json)";
|
|
41
|
+
statusText = `Gemini API token is configured and ready.\nSource: ${sourceLabel}`;
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
statusText = `Gemini API token is not configured.\n\nConfiguration options (priority order):\n1. MCP client env: "env": { "GEMINI_API_KEY": "your-key" }\n2. System env: export GEMINI_API_KEY="your-key"\n3. Use configure_gemini_token tool`;
|
|
45
|
+
}
|
|
46
|
+
return { content: [{ type: "text", text: statusText }] };
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=config-tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-tools.js","sourceRoot":"","sources":["../../src/tools/config-tools.ts"],"names":[],"mappings":"AAIA,MAAM,CAAC,MAAM,wBAAwB,GAAS;IAC5C,IAAI,EAAE,wBAAwB;IAC9B,WAAW,EAAE,kEAAkE;IAC/E,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,MAAM,EAAE;gBACN,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,2CAA2C;aACzD;SACF;QACD,QAAQ,EAAE,CAAC,QAAQ,CAAC;KACrB;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,0BAA0B,GAAS;IAC9C,IAAI,EAAE,0BAA0B;IAChC,WAAW,EAAE,yCAAyC;IACtD,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE,EAAE;QACd,oBAAoB,EAAE,KAAK;KAC5B;CACF,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,OAAwB,EACxB,aAA4B;IAE5B,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,SAA+B,CAAC;IAClE,MAAM,aAAa,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAEtC,OAAO;QACL,OAAO,EAAE,CAAC;gBACR,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,kGAAkG;aACzG,CAAC;KACH,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,aAA4B;IAE5B,MAAM,YAAY,GAAG,aAAa,CAAC,YAAY,EAAE,CAAC;IAElD,IAAI,UAAkB,CAAC;IACvB,IAAI,YAAY,EAAE,CAAC;QACjB,MAAM,WAAW,GAAG,aAAa,CAAC,YAAY,KAAK,aAAa;YAC9D,CAAC,CAAC,uCAAuC;YACzC,CAAC,CAAC,qDAAqD,CAAC;QAC1D,UAAU,GAAG,sDAAsD,WAAW,EAAE,CAAC;IACnF,CAAC;SAAM,CAAC;QACN,UAAU,GAAG,iOAAiO,CAAC;IACjP,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC;AAC3D,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { CallToolRequest, CallToolResult, Tool } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
import { GoogleGenAI } from "@google/genai";
|
|
3
|
+
import { ChatSessionManager } from "../chat-session.js";
|
|
4
|
+
export declare const continueEditingTool: Tool;
|
|
5
|
+
export declare function handleContinueEditing(request: CallToolRequest, genAI: GoogleGenAI, chatSession: ChatSessionManager, lastImagePath: string | null): Promise<{
|
|
6
|
+
result: CallToolResult;
|
|
7
|
+
savedPath: string | null;
|
|
8
|
+
}>;
|
|
9
|
+
//# sourceMappingURL=continue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"continue.d.ts","sourceRoot":"","sources":["../../src/tools/continue.ts"],"names":[],"mappings":"AACA,OAAO,EACL,eAAe,EAAE,cAAc,EAAuB,IAAI,EAC3D,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAG5C,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAExD,eAAO,MAAM,mBAAmB,EAAE,IA6BjC,CAAC;AAEF,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,eAAe,EACxB,KAAK,EAAE,WAAW,EAClB,WAAW,EAAE,kBAAkB,EAC/B,aAAa,EAAE,MAAM,GAAG,IAAI,GAC3B,OAAO,CAAC;IAAE,MAAM,EAAE,cAAc,CAAC;IAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAmD/D"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
// src/tools/continue.ts
|
|
2
|
+
import { ErrorCode, McpError, } from "@modelcontextprotocol/sdk/types.js";
|
|
3
|
+
import { ASPECT_RATIOS, RESOLUTIONS } from "../types.js";
|
|
4
|
+
import { saveImageFromBase64, readImageAsBase64 } from "../image-utils.js";
|
|
5
|
+
export const continueEditingTool = {
|
|
6
|
+
name: "continue_editing",
|
|
7
|
+
description: "Continue editing the LAST generated/edited image using multi-turn conversation. The model remembers previous context. Supports reference images, aspect ratio, and resolution changes.",
|
|
8
|
+
inputSchema: {
|
|
9
|
+
type: "object",
|
|
10
|
+
properties: {
|
|
11
|
+
prompt: {
|
|
12
|
+
type: "string",
|
|
13
|
+
description: "Text describing the changes to make to the last image",
|
|
14
|
+
},
|
|
15
|
+
referenceImages: {
|
|
16
|
+
type: "array",
|
|
17
|
+
items: { type: "string" },
|
|
18
|
+
description: "Optional file paths to reference images for style/content guidance",
|
|
19
|
+
},
|
|
20
|
+
aspectRatio: {
|
|
21
|
+
type: "string",
|
|
22
|
+
enum: [...ASPECT_RATIOS],
|
|
23
|
+
description: "Change the aspect ratio for this edit",
|
|
24
|
+
},
|
|
25
|
+
resolution: {
|
|
26
|
+
type: "string",
|
|
27
|
+
enum: [...RESOLUTIONS],
|
|
28
|
+
description: "Change the resolution for this edit (Pro model only)",
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
required: ["prompt"],
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
export async function handleContinueEditing(request, genAI, chatSession, lastImagePath) {
|
|
35
|
+
if (!lastImagePath) {
|
|
36
|
+
throw new McpError(ErrorCode.InvalidRequest, "No previous image found. Use generate_image or edit_image first.");
|
|
37
|
+
}
|
|
38
|
+
const args = request.params.arguments;
|
|
39
|
+
// If no active chat session, fall back to re-sending the last image
|
|
40
|
+
if (!chatSession.hasActiveSession()) {
|
|
41
|
+
const mainImage = await readImageAsBase64(lastImagePath);
|
|
42
|
+
const parts = [
|
|
43
|
+
{ inlineData: { data: mainImage.base64, mimeType: mainImage.mimeType } },
|
|
44
|
+
];
|
|
45
|
+
if (args.referenceImages) {
|
|
46
|
+
for (const refPath of args.referenceImages) {
|
|
47
|
+
try {
|
|
48
|
+
const refImg = await readImageAsBase64(refPath);
|
|
49
|
+
parts.push({ inlineData: { data: refImg.base64, mimeType: refImg.mimeType } });
|
|
50
|
+
}
|
|
51
|
+
catch { /* skip */ }
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
parts.push({ text: args.prompt });
|
|
55
|
+
const config = { responseModalities: ["TEXT", "IMAGE"] };
|
|
56
|
+
const imageConfig = {};
|
|
57
|
+
if (args.aspectRatio)
|
|
58
|
+
imageConfig.aspectRatio = args.aspectRatio;
|
|
59
|
+
if (args.resolution)
|
|
60
|
+
imageConfig.imageSize = args.resolution;
|
|
61
|
+
if (Object.keys(imageConfig).length > 0)
|
|
62
|
+
config.imageConfig = imageConfig;
|
|
63
|
+
const response = await genAI.models.generateContent({
|
|
64
|
+
model: "gemini-2.5-flash-image",
|
|
65
|
+
contents: [{ parts }],
|
|
66
|
+
config,
|
|
67
|
+
});
|
|
68
|
+
return processResponse(response, args);
|
|
69
|
+
}
|
|
70
|
+
// Active chat session exists — use it for true multi-turn
|
|
71
|
+
const response = await chatSession.sendMessage(args.prompt);
|
|
72
|
+
return processResponse(response, args);
|
|
73
|
+
}
|
|
74
|
+
async function processResponse(response, args) {
|
|
75
|
+
const content = [];
|
|
76
|
+
let savedPath = null;
|
|
77
|
+
let textContent = "";
|
|
78
|
+
if (response.candidates?.[0]?.content?.parts) {
|
|
79
|
+
for (const part of response.candidates[0].content.parts) {
|
|
80
|
+
if (part.text && !part.thought)
|
|
81
|
+
textContent += part.text;
|
|
82
|
+
if (part.inlineData?.data && !part.thought) {
|
|
83
|
+
const saved = await saveImageFromBase64(part.inlineData.data, "edited");
|
|
84
|
+
savedPath = saved.filePath;
|
|
85
|
+
content.push({
|
|
86
|
+
type: "image",
|
|
87
|
+
data: part.inlineData.data,
|
|
88
|
+
mimeType: part.inlineData.mimeType || "image/png",
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
let statusText = `Image updated with nano-banana (continue_editing)`;
|
|
94
|
+
statusText += `\n\nEdit prompt: "${args.prompt}"`;
|
|
95
|
+
if (args.aspectRatio)
|
|
96
|
+
statusText += `\nAspect ratio: ${args.aspectRatio}`;
|
|
97
|
+
if (args.resolution)
|
|
98
|
+
statusText += `\nResolution: ${args.resolution}`;
|
|
99
|
+
if (textContent)
|
|
100
|
+
statusText += `\n\nDescription: ${textContent}`;
|
|
101
|
+
if (savedPath) {
|
|
102
|
+
statusText += `\n\nEdited image saved to: ${savedPath}`;
|
|
103
|
+
statusText += `\nUse continue_editing again for further changes.`;
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
statusText += `\n\nNo edited image generated. Try again.`;
|
|
107
|
+
}
|
|
108
|
+
content.unshift({ type: "text", text: statusText });
|
|
109
|
+
return { result: { content }, savedPath };
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=continue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"continue.js","sourceRoot":"","sources":["../../src/tools/continue.ts"],"names":[],"mappings":"AAAA,wBAAwB;AACxB,OAAO,EAC4B,SAAS,EAAE,QAAQ,GACrD,MAAM,oCAAoC,CAAC;AAE5C,OAAO,EAAE,aAAa,EAAE,WAAW,EAA2B,MAAM,aAAa,CAAC;AAClF,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAG3E,MAAM,CAAC,MAAM,mBAAmB,GAAS;IACvC,IAAI,EAAE,kBAAkB;IACxB,WAAW,EACT,wLAAwL;IAC1L,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,MAAM,EAAE;gBACN,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,uDAAuD;aACrE;YACD,eAAe,EAAE;gBACf,IAAI,EAAE,OAAO;gBACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gBACzB,WAAW,EAAE,oEAAoE;aAClF;YACD,WAAW,EAAE;gBACX,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,CAAC,GAAG,aAAa,CAAC;gBACxB,WAAW,EAAE,uCAAuC;aACrD;YACD,UAAU,EAAE;gBACV,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,CAAC,GAAG,WAAW,CAAC;gBACtB,WAAW,EAAE,sDAAsD;aACpE;SACF;QACD,QAAQ,EAAE,CAAC,QAAQ,CAAC;KACrB;CACF,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,OAAwB,EACxB,KAAkB,EAClB,WAA+B,EAC/B,aAA4B;IAE5B,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,MAAM,IAAI,QAAQ,CAChB,SAAS,CAAC,cAAc,EACxB,kEAAkE,CACnE,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,SAK3B,CAAC;IAEF,oEAAoE;IACpE,IAAI,CAAC,WAAW,CAAC,gBAAgB,EAAE,EAAE,CAAC;QACpC,MAAM,SAAS,GAAG,MAAM,iBAAiB,CAAC,aAAa,CAAC,CAAC;QACzD,MAAM,KAAK,GAAU;YACnB,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,EAAE,QAAQ,EAAE,SAAS,CAAC,QAAQ,EAAE,EAAE;SACzE,CAAC;QAEF,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YACzB,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;gBAC3C,IAAI,CAAC;oBACH,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,OAAO,CAAC,CAAC;oBAChD,KAAK,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;gBACjF,CAAC;gBAAC,MAAM,CAAC,CAAC,UAAU,CAAC,CAAC;YACxB,CAAC;QACH,CAAC;QAED,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QAElC,MAAM,MAAM,GAAQ,EAAE,kBAAkB,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;QAC9D,MAAM,WAAW,GAAQ,EAAE,CAAC;QAC5B,IAAI,IAAI,CAAC,WAAW;YAAE,WAAW,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC;QACjE,IAAI,IAAI,CAAC,UAAU;YAAE,WAAW,CAAC,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC;QAC7D,IAAI,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,MAAM,GAAG,CAAC;YAAE,MAAM,CAAC,WAAW,GAAG,WAAW,CAAC;QAE1E,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,eAAe,CAAC;YAClD,KAAK,EAAE,wBAAwB;YAC/B,QAAQ,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC;YACrB,MAAM;SACP,CAAC,CAAC;QAEH,OAAO,eAAe,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACzC,CAAC;IAED,0DAA0D;IAC1D,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC5D,OAAO,eAAe,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;AACzC,CAAC;AAED,KAAK,UAAU,eAAe,CAC5B,QAAa,EACb,IAAmE;IAEnE,MAAM,OAAO,GAAU,EAAE,CAAC;IAC1B,IAAI,SAAS,GAAkB,IAAI,CAAC;IACpC,IAAI,WAAW,GAAG,EAAE,CAAC;IAErB,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QAC7C,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YACxD,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO;gBAAE,WAAW,IAAI,IAAI,CAAC,IAAI,CAAC;YACzD,IAAI,IAAI,CAAC,UAAU,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;gBAC3C,MAAM,KAAK,GAAG,MAAM,mBAAmB,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;gBACxE,SAAS,GAAG,KAAK,CAAC,QAAQ,CAAC;gBAC3B,OAAO,CAAC,IAAI,CAAC;oBACX,IAAI,EAAE,OAAO;oBACb,IAAI,EAAE,IAAI,CAAC,UAAU,CAAC,IAAI;oBAC1B,QAAQ,EAAE,IAAI,CAAC,UAAU,CAAC,QAAQ,IAAI,WAAW;iBAClD,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,UAAU,GAAG,mDAAmD,CAAC;IACrE,UAAU,IAAI,qBAAqB,IAAI,CAAC,MAAM,GAAG,CAAC;IAClD,IAAI,IAAI,CAAC,WAAW;QAAE,UAAU,IAAI,mBAAmB,IAAI,CAAC,WAAW,EAAE,CAAC;IAC1E,IAAI,IAAI,CAAC,UAAU;QAAE,UAAU,IAAI,iBAAiB,IAAI,CAAC,UAAU,EAAE,CAAC;IACtE,IAAI,WAAW;QAAE,UAAU,IAAI,oBAAoB,WAAW,EAAE,CAAC;IAEjE,IAAI,SAAS,EAAE,CAAC;QACd,UAAU,IAAI,8BAA8B,SAAS,EAAE,CAAC;QACxD,UAAU,IAAI,mDAAmD,CAAC;IACpE,CAAC;SAAM,CAAC;QACN,UAAU,IAAI,2CAA2C,CAAC;IAC5D,CAAC;IAED,OAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;IACpD,OAAO,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,EAAE,SAAS,EAAE,CAAC;AAC5C,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { CallToolRequest, CallToolResult, Tool } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
import { GoogleGenAI } from "@google/genai";
|
|
3
|
+
export declare const editImageTool: Tool;
|
|
4
|
+
export declare function handleEditImage(request: CallToolRequest, genAI: GoogleGenAI): Promise<{
|
|
5
|
+
result: CallToolResult;
|
|
6
|
+
savedPath: string | null;
|
|
7
|
+
}>;
|
|
8
|
+
//# sourceMappingURL=edit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"edit.d.ts","sourceRoot":"","sources":["../../src/tools/edit.ts"],"names":[],"mappings":"AACA,OAAO,EACL,eAAe,EAAE,cAAc,EAAE,IAAI,EACtC,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAI5C,eAAO,MAAM,aAAa,EAAE,IAsC3B,CAAC;AAEF,wBAAsB,eAAe,CACnC,OAAO,EAAE,eAAe,EACxB,KAAK,EAAE,WAAW,GACjB,OAAO,CAAC;IAAE,MAAM,EAAE,cAAc,CAAC;IAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CA6F/D"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { MODELS, ASPECT_RATIOS, RESOLUTIONS } from "../types.js";
|
|
2
|
+
import { saveImageFromBase64, readImageAsBase64 } from "../image-utils.js";
|
|
3
|
+
export const editImageTool = {
|
|
4
|
+
name: "edit_image",
|
|
5
|
+
description: "Edit a SPECIFIC existing image file with text prompts. Supports optional reference images, model selection, aspect ratios, and resolution.",
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: "object",
|
|
8
|
+
properties: {
|
|
9
|
+
imagePath: {
|
|
10
|
+
type: "string",
|
|
11
|
+
description: "Full file path to the image to edit",
|
|
12
|
+
},
|
|
13
|
+
prompt: {
|
|
14
|
+
type: "string",
|
|
15
|
+
description: "Text describing the modifications to make",
|
|
16
|
+
},
|
|
17
|
+
referenceImages: {
|
|
18
|
+
type: "array",
|
|
19
|
+
items: { type: "string" },
|
|
20
|
+
description: "Optional file paths to reference images (up to 3 for Flash, up to 14 for Pro)",
|
|
21
|
+
},
|
|
22
|
+
model: {
|
|
23
|
+
type: "string",
|
|
24
|
+
enum: ["flash", "pro"],
|
|
25
|
+
description: "Model to use. 'flash' (default) for speed. 'pro' for quality and more reference images.",
|
|
26
|
+
},
|
|
27
|
+
aspectRatio: {
|
|
28
|
+
type: "string",
|
|
29
|
+
enum: [...ASPECT_RATIOS],
|
|
30
|
+
description: "Aspect ratio for the output image",
|
|
31
|
+
},
|
|
32
|
+
resolution: {
|
|
33
|
+
type: "string",
|
|
34
|
+
enum: [...RESOLUTIONS],
|
|
35
|
+
description: "Image resolution (Pro model only): '1K', '2K', '4K'",
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
required: ["imagePath", "prompt"],
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
export async function handleEditImage(request, genAI) {
|
|
42
|
+
const args = request.params.arguments;
|
|
43
|
+
let model = args.model || "flash";
|
|
44
|
+
// Auto-upgrade to Pro if many reference images or Pro-only features
|
|
45
|
+
if ((args.referenceImages && args.referenceImages.length > 3) ||
|
|
46
|
+
args.resolution === "2K" || args.resolution === "4K") {
|
|
47
|
+
model = "pro";
|
|
48
|
+
}
|
|
49
|
+
const modelId = MODELS[model];
|
|
50
|
+
// Build image parts
|
|
51
|
+
const mainImage = await readImageAsBase64(args.imagePath);
|
|
52
|
+
const parts = [
|
|
53
|
+
{ inlineData: { data: mainImage.base64, mimeType: mainImage.mimeType } },
|
|
54
|
+
];
|
|
55
|
+
// Add reference images
|
|
56
|
+
if (args.referenceImages) {
|
|
57
|
+
for (const refPath of args.referenceImages) {
|
|
58
|
+
try {
|
|
59
|
+
const refImg = await readImageAsBase64(refPath);
|
|
60
|
+
parts.push({ inlineData: { data: refImg.base64, mimeType: refImg.mimeType } });
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
// Skip unreadable reference images
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
parts.push({ text: args.prompt });
|
|
68
|
+
// Build config
|
|
69
|
+
const config = {
|
|
70
|
+
responseModalities: ["TEXT", "IMAGE"],
|
|
71
|
+
};
|
|
72
|
+
const imageConfig = {};
|
|
73
|
+
if (args.aspectRatio)
|
|
74
|
+
imageConfig.aspectRatio = args.aspectRatio;
|
|
75
|
+
if (args.resolution && model === "pro")
|
|
76
|
+
imageConfig.imageSize = args.resolution;
|
|
77
|
+
if (Object.keys(imageConfig).length > 0)
|
|
78
|
+
config.imageConfig = imageConfig;
|
|
79
|
+
const response = await genAI.models.generateContent({
|
|
80
|
+
model: modelId,
|
|
81
|
+
contents: [{ parts }],
|
|
82
|
+
config,
|
|
83
|
+
});
|
|
84
|
+
// Process response
|
|
85
|
+
const content = [];
|
|
86
|
+
let savedPath = null;
|
|
87
|
+
let textContent = "";
|
|
88
|
+
if (response.candidates?.[0]?.content?.parts) {
|
|
89
|
+
for (const part of response.candidates[0].content.parts) {
|
|
90
|
+
if (part.text && !part.thought)
|
|
91
|
+
textContent += part.text;
|
|
92
|
+
if (part.inlineData?.data && !part.thought) {
|
|
93
|
+
const saved = await saveImageFromBase64(part.inlineData.data, "edited");
|
|
94
|
+
savedPath = saved.filePath;
|
|
95
|
+
content.push({
|
|
96
|
+
type: "image",
|
|
97
|
+
data: part.inlineData.data,
|
|
98
|
+
mimeType: part.inlineData.mimeType || "image/png",
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
let statusText = `Image edited with nano-banana (${model === "pro" ? "Gemini 3 Pro" : "Gemini 2.5 Flash"})`;
|
|
104
|
+
statusText += `\n\nOriginal: ${args.imagePath}`;
|
|
105
|
+
statusText += `\nEdit prompt: "${args.prompt}"`;
|
|
106
|
+
if (args.referenceImages?.length) {
|
|
107
|
+
statusText += `\nReference images: ${args.referenceImages.length}`;
|
|
108
|
+
}
|
|
109
|
+
if (args.aspectRatio)
|
|
110
|
+
statusText += `\nAspect ratio: ${args.aspectRatio}`;
|
|
111
|
+
if (textContent)
|
|
112
|
+
statusText += `\n\nDescription: ${textContent}`;
|
|
113
|
+
if (savedPath) {
|
|
114
|
+
statusText += `\n\nEdited image saved to: ${savedPath}`;
|
|
115
|
+
statusText += `\nUse continue_editing to make further changes.`;
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
statusText += `\n\nNo edited image generated. Try again.`;
|
|
119
|
+
}
|
|
120
|
+
content.unshift({ type: "text", text: statusText });
|
|
121
|
+
return { result: { content }, savedPath };
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=edit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"edit.js","sourceRoot":"","sources":["../../src/tools/edit.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { CallToolRequest, CallToolResult, Tool } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
import { GoogleGenAI } from "@google/genai";
|
|
3
|
+
import { ChatSessionManager } from "../chat-session.js";
|
|
4
|
+
export declare const generateImageTool: Tool;
|
|
5
|
+
export declare function handleGenerateImage(request: CallToolRequest, genAI: GoogleGenAI, chatSession: ChatSessionManager): Promise<{
|
|
6
|
+
result: CallToolResult;
|
|
7
|
+
savedPath: string | null;
|
|
8
|
+
}>;
|
|
9
|
+
//# sourceMappingURL=generate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/tools/generate.ts"],"names":[],"mappings":"AACA,OAAO,EACL,eAAe,EAAE,cAAc,EAAE,IAAI,EACtC,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAG5C,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAExD,eAAO,MAAM,iBAAiB,EAAE,IAiC/B,CAAC;AAEF,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,eAAe,EACxB,KAAK,EAAE,WAAW,EAClB,WAAW,EAAE,kBAAkB,GAC9B,OAAO,CAAC;IAAE,MAAM,EAAE,cAAc,CAAC;IAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAiF/D"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { MODELS, ASPECT_RATIOS, RESOLUTIONS } from "../types.js";
|
|
2
|
+
import { saveImageFromBase64 } from "../image-utils.js";
|
|
3
|
+
export const generateImageTool = {
|
|
4
|
+
name: "generate_image",
|
|
5
|
+
description: "Generate a NEW image from a text prompt. Supports model selection, aspect ratios, and resolution control. Use 'pro' model for higher quality, 4K resolution, and Google Search grounding.",
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: "object",
|
|
8
|
+
properties: {
|
|
9
|
+
prompt: {
|
|
10
|
+
type: "string",
|
|
11
|
+
description: "Text prompt describing the image to create",
|
|
12
|
+
},
|
|
13
|
+
model: {
|
|
14
|
+
type: "string",
|
|
15
|
+
enum: ["flash", "pro"],
|
|
16
|
+
description: "Model to use. 'flash' (default) = fast/efficient. 'pro' = higher quality, supports 4K and search grounding.",
|
|
17
|
+
},
|
|
18
|
+
aspectRatio: {
|
|
19
|
+
type: "string",
|
|
20
|
+
enum: [...ASPECT_RATIOS],
|
|
21
|
+
description: "Aspect ratio for the output image. Defaults to 1:1.",
|
|
22
|
+
},
|
|
23
|
+
resolution: {
|
|
24
|
+
type: "string",
|
|
25
|
+
enum: [...RESOLUTIONS],
|
|
26
|
+
description: "Image resolution (Pro model only). '1K' (default), '2K', or '4K'.",
|
|
27
|
+
},
|
|
28
|
+
useGoogleSearch: {
|
|
29
|
+
type: "boolean",
|
|
30
|
+
description: "Enable Google Search grounding for real-time data (Pro model only). Useful for weather, news, charts.",
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
required: ["prompt"],
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
export async function handleGenerateImage(request, genAI, chatSession) {
|
|
37
|
+
const args = request.params.arguments;
|
|
38
|
+
// Auto-select Pro if Pro-only features are requested
|
|
39
|
+
let model = args.model || "flash";
|
|
40
|
+
if ((args.resolution === "2K" || args.resolution === "4K" || args.useGoogleSearch) && model === "flash") {
|
|
41
|
+
model = "pro";
|
|
42
|
+
}
|
|
43
|
+
const modelId = MODELS[model];
|
|
44
|
+
// Build config
|
|
45
|
+
const config = {
|
|
46
|
+
responseModalities: ["TEXT", "IMAGE"],
|
|
47
|
+
};
|
|
48
|
+
const imageConfig = {};
|
|
49
|
+
if (args.aspectRatio)
|
|
50
|
+
imageConfig.aspectRatio = args.aspectRatio;
|
|
51
|
+
if (args.resolution && model === "pro")
|
|
52
|
+
imageConfig.imageSize = args.resolution;
|
|
53
|
+
if (Object.keys(imageConfig).length > 0)
|
|
54
|
+
config.imageConfig = imageConfig;
|
|
55
|
+
if (args.useGoogleSearch && model === "pro") {
|
|
56
|
+
config.tools = [{ googleSearch: {} }];
|
|
57
|
+
}
|
|
58
|
+
// Reset chat session (new generation = fresh context)
|
|
59
|
+
chatSession.reset();
|
|
60
|
+
const response = await genAI.models.generateContent({
|
|
61
|
+
model: modelId,
|
|
62
|
+
contents: args.prompt,
|
|
63
|
+
config,
|
|
64
|
+
});
|
|
65
|
+
// Process response
|
|
66
|
+
const content = [];
|
|
67
|
+
let savedPath = null;
|
|
68
|
+
let textContent = "";
|
|
69
|
+
if (response.candidates?.[0]?.content?.parts) {
|
|
70
|
+
for (const part of response.candidates[0].content.parts) {
|
|
71
|
+
if (part.text && !part.thought) {
|
|
72
|
+
textContent += part.text;
|
|
73
|
+
}
|
|
74
|
+
if (part.inlineData?.data && !part.thought) {
|
|
75
|
+
const saved = await saveImageFromBase64(part.inlineData.data, "generated");
|
|
76
|
+
savedPath = saved.filePath;
|
|
77
|
+
content.push({
|
|
78
|
+
type: "image",
|
|
79
|
+
data: part.inlineData.data,
|
|
80
|
+
mimeType: part.inlineData.mimeType || "image/png",
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// Build status text
|
|
86
|
+
let statusText = `Image generated with nano-banana (${model === "pro" ? "Gemini 3 Pro" : "Gemini 2.5 Flash"})`;
|
|
87
|
+
statusText += `\n\nPrompt: "${args.prompt}"`;
|
|
88
|
+
if (args.aspectRatio)
|
|
89
|
+
statusText += `\nAspect ratio: ${args.aspectRatio}`;
|
|
90
|
+
if (args.resolution && model === "pro")
|
|
91
|
+
statusText += `\nResolution: ${args.resolution}`;
|
|
92
|
+
if (args.useGoogleSearch)
|
|
93
|
+
statusText += `\nGoogle Search grounding: enabled`;
|
|
94
|
+
if (textContent)
|
|
95
|
+
statusText += `\n\nDescription: ${textContent}`;
|
|
96
|
+
if (savedPath) {
|
|
97
|
+
statusText += `\n\nImage saved to: ${savedPath}`;
|
|
98
|
+
statusText += `\n\nUse continue_editing to modify this image.`;
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
statusText += `\n\nNo image was generated. Try running again.`;
|
|
102
|
+
}
|
|
103
|
+
content.unshift({ type: "text", text: statusText });
|
|
104
|
+
return { result: { content }, savedPath };
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=generate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate.js","sourceRoot":"","sources":["../../src/tools/generate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"info.d.ts","sourceRoot":"","sources":["../../src/tools/info.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAG1E,eAAO,MAAM,oBAAoB,EAAE,IAQlC,CAAC;AAEF,wBAAsB,sBAAsB,CAC1C,aAAa,EAAE,MAAM,GAAG,IAAI,GAC3B,OAAO,CAAC,cAAc,CAAC,CA0BzB"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import fs from "fs/promises";
|
|
2
|
+
export const getLastImageInfoTool = {
|
|
3
|
+
name: "get_last_image_info",
|
|
4
|
+
description: "Get information about the last generated/edited image (file path, size, etc.)",
|
|
5
|
+
inputSchema: {
|
|
6
|
+
type: "object",
|
|
7
|
+
properties: {},
|
|
8
|
+
additionalProperties: false,
|
|
9
|
+
},
|
|
10
|
+
};
|
|
11
|
+
export async function handleGetLastImageInfo(lastImagePath) {
|
|
12
|
+
if (!lastImagePath) {
|
|
13
|
+
return {
|
|
14
|
+
content: [{
|
|
15
|
+
type: "text",
|
|
16
|
+
text: "No previous image found. Use generate_image or edit_image first.",
|
|
17
|
+
}],
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
try {
|
|
21
|
+
const stats = await fs.stat(lastImagePath);
|
|
22
|
+
return {
|
|
23
|
+
content: [{
|
|
24
|
+
type: "text",
|
|
25
|
+
text: `Last Image:\n\nPath: ${lastImagePath}\nSize: ${Math.round(stats.size / 1024)} KB\nModified: ${stats.mtime.toLocaleString()}\n\nUse continue_editing to make changes.`,
|
|
26
|
+
}],
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return {
|
|
31
|
+
content: [{
|
|
32
|
+
type: "text",
|
|
33
|
+
text: `Last Image:\n\nPath: ${lastImagePath}\nStatus: File not found (may have been moved or deleted)\n\nUse generate_image to create a new image.`,
|
|
34
|
+
}],
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=info.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"info.js","sourceRoot":"","sources":["../../src/tools/info.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,aAAa,CAAC;AAE7B,MAAM,CAAC,MAAM,oBAAoB,GAAS;IACxC,IAAI,EAAE,qBAAqB;IAC3B,WAAW,EAAE,+EAA+E;IAC5F,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE,EAAE;QACd,oBAAoB,EAAE,KAAK;KAC5B;CACF,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,aAA4B;IAE5B,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,OAAO;YACL,OAAO,EAAE,CAAC;oBACR,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,kEAAkE;iBACzE,CAAC;SACH,CAAC;IACJ,CAAC;IAED,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAC3C,OAAO;YACL,OAAO,EAAE,CAAC;oBACR,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,wBAAwB,aAAa,WAAW,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,kBAAkB,KAAK,CAAC,KAAK,CAAC,cAAc,EAAE,2CAA2C;iBAC7K,CAAC;SACH,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;YACL,OAAO,EAAE,CAAC;oBACR,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,wBAAwB,aAAa,wGAAwG;iBACpJ,CAAC;SACH,CAAC;IACJ,CAAC;AACH,CAAC"}
|