edit_image
Modify existing image files using text prompts and optional reference images. Edit specific images by providing their file paths to apply changes like style adjustments or element additions.
Instructions
Edit a SPECIFIC existing image file, optionally using additional reference images. Use this when you have the exact file path of an image to modify.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| imagePath | Yes | Full file path to the main image file to edit | |
| prompt | Yes | Text describing the modifications to make to the existing image | |
| referenceImages | No | Optional array of file paths to additional reference images to use during editing (e.g., for style transfer, adding elements, etc.) |
Implementation Reference
- src/index.ts:303-442 (handler)The primary handler function that performs image editing using the Gemini API. It reads the input image and optional reference images, encodes them to base64, sends to Gemini with the edit prompt, processes the response, saves the output image, and returns MCP-formatted content with the image and status text.private async editImage(request: CallToolRequest): Promise<CallToolResult> { if (!this.ensureConfigured()) { throw new McpError(ErrorCode.InvalidRequest, "Gemini API token not configured. Use configure_gemini_token first."); } const { imagePath, prompt, referenceImages } = request.params.arguments as { imagePath: string; prompt: string; referenceImages?: string[]; }; try { // Prepare the main image const imageBuffer = await fs.readFile(imagePath); const mimeType = this.getMimeType(imagePath); const imageBase64 = imageBuffer.toString('base64'); // Prepare all image parts const imageParts: any[] = [ { inlineData: { data: imageBase64, mimeType: mimeType, } } ]; // Add reference images if provided if (referenceImages && referenceImages.length > 0) { for (const refPath of referenceImages) { try { const refBuffer = await fs.readFile(refPath); const refMimeType = this.getMimeType(refPath); const refBase64 = refBuffer.toString('base64'); imageParts.push({ inlineData: { data: refBase64, mimeType: refMimeType, } }); } catch (error) { // Continue with other images, don't fail the entire operation continue; } } } // Add the text prompt imageParts.push({ text: prompt }); // Use new API format with multiple images and text const response = await this.genAI!.models.generateContent({ model: "gemini-2.5-flash-image-preview", contents: [ { parts: imageParts } ], }); // Process response const content: any[] = []; const savedFiles: string[] = []; let textContent = ""; // Get appropriate save directory const imagesDir = this.getImagesDirectory(); await fs.mkdir(imagesDir, { recursive: true, mode: 0o755 }); // Extract image from response if (response.candidates && response.candidates[0]?.content?.parts) { for (const part of response.candidates[0].content.parts) { if (part.text) { textContent += part.text; } if (part.inlineData) { // Save edited image const timestamp = new Date().toISOString().replace(/[:.]/g, '-'); const randomId = Math.random().toString(36).substring(2, 8); const fileName = `edited-${timestamp}-${randomId}.png`; const filePath = path.join(imagesDir, fileName); if (part.inlineData.data) { const imageBuffer = Buffer.from(part.inlineData.data, 'base64'); await fs.writeFile(filePath, imageBuffer); savedFiles.push(filePath); this.lastImagePath = filePath; } // Add to MCP response if (part.inlineData.data) { content.push({ type: "image", data: part.inlineData.data, mimeType: part.inlineData.mimeType || "image/png", }); } } } } // Build response let statusText = `šØ Image edited with nano-banana!\n\nOriginal: ${imagePath}\nEdit prompt: "${prompt}"`; if (referenceImages && referenceImages.length > 0) { statusText += `\n\nReference images used:\n${referenceImages.map(f => `- ${f}`).join('\n')}`; } if (textContent) { statusText += `\n\nDescription: ${textContent}`; } if (savedFiles.length > 0) { statusText += `\n\nš Edited image saved to:\n${savedFiles.map(f => `- ${f}`).join('\n')}`; statusText += `\n\nš” View the edited image by:`; statusText += `\n1. Opening the file at the path above`; statusText += `\n2. Clicking on "Called edit_image" in Cursor to expand the MCP call details`; statusText += `\n\nš To continue editing, use: continue_editing`; statusText += `\nš To check current image info, use: get_last_image_info`; } else { statusText += `\n\nNote: No edited image was generated.`; statusText += `\n\nš” Tip: Try running the command again - sometimes the first call needs to warm up the model.`; } content.unshift({ type: "text", text: statusText, }); return { content }; } catch (error) { throw new McpError( ErrorCode.InternalError, `Failed to edit image: ${error instanceof Error ? error.message : String(error)}` ); } }
- src/index.ts:88-107 (schema)JSON schema defining the input parameters for the edit_image tool: required imagePath and prompt, optional referenceImages array.inputSchema: { type: "object", properties: { imagePath: { type: "string", description: "Full file path to the main image file to edit", }, prompt: { type: "string", description: "Text describing the modifications to make to the existing image", }, referenceImages: { type: "array", items: { type: "string" }, description: "Optional array of file paths to additional reference images to use during editing (e.g., for style transfer, adding elements, etc.)", }, }, required: ["imagePath", "prompt"],
- src/index.ts:85-109 (registration)Tool registration in the ListTools response, defining name, description, and inputSchema for edit_image.{ name: "edit_image", description: "Edit a SPECIFIC existing image file, optionally using additional reference images. Use this when you have the exact file path of an image to modify.", inputSchema: { type: "object", properties: { imagePath: { type: "string", description: "Full file path to the main image file to edit", }, prompt: { type: "string", description: "Text describing the modifications to make to the existing image", }, referenceImages: { type: "array", items: { type: "string" }, description: "Optional array of file paths to additional reference images to use during editing (e.g., for style transfer, adding elements, etc.)", }, }, required: ["imagePath", "prompt"], }, },
- src/index.ts:162-163 (registration)Dispatch in the CallTool handler switch statement that routes 'edit_image' calls to the editImage method.case "edit_image": return await this.editImage(request);