editImage
Modify existing images using text prompts for precise edits. Adjust settings like width, height, and transparency, and save output in preferred formats. Ideal for custom image transformations.
Instructions
Edit or modify an existing image based on a text prompt. User-configured settings in MCP config will be used as defaults unless specifically overridden.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| enhance | No | Whether to enhance the prompt using an LLM before generating (default: true) | |
| fileName | No | Name of the file to save (without extension, default: generated from prompt) | |
| format | No | Image format to save as (png, jpeg, jpg, webp - default: png) | |
| height | No | Height of the generated image (default: 1024) | |
| imageUrl | Yes | URL of the input image to edit | |
| model | No | Model name to use for editing (default: user config or "gptimage"). Available: "gptimage", "kontext" | |
| outputPath | No | Directory path where to save the image (default: user config or "./mcpollinations-output") | |
| prompt | Yes | The text description of how to edit the image (e.g., "remove the cat and add a dog", "change background to mountains") | |
| safe | No | Whether to apply content filtering (default: false) | |
| seed | No | Seed for reproducible results (default: random) | |
| transparent | No | Generate image with transparent background (gptimage model only, default: false) | |
| width | No | Width of the generated image (default: 1024) |
Implementation Reference
- src/services/imageService.js:218-357 (handler)The core handler function that implements the editImage tool logic: constructs API URL with image editing parameters, fetches the image from Pollinations API, converts to base64, saves to file, and returns metadata and data.export async function editImage(prompt, imageUrl, model = 'kontext', seed = Math.floor(Math.random() * 1000000), width = 1024, height = 1024, enhance = true, safe = false, outputPath = './mcpollinations-output', fileName = '', format = 'png', authConfig = null) { if (!prompt || typeof prompt !== 'string') { throw new Error('Prompt is required and must be a string'); } if (!imageUrl || (typeof imageUrl !== 'string' && !Array.isArray(imageUrl))) { throw new Error('Image URL(s) are required and must be a string or array of strings'); } // Support multi-reference images. Prefer repeating the `image` param per URL // to avoid comma-encoding ambiguities. const imageList = Array.isArray(imageUrl) ? imageUrl.filter(Boolean) : (typeof imageUrl === 'string' && imageUrl.includes(',')) ? imageUrl.split(',').map(s => s.trim()).filter(Boolean) : [imageUrl]; // Build the query parameters const queryParams = new URLSearchParams(); queryParams.append('model', model); for (const u of imageList) { queryParams.append('image', u); } if (seed !== undefined) queryParams.append('seed', seed); if (width !== 1024) queryParams.append('width', width); if (height !== 1024) queryParams.append('height', height); // Add enhance parameter if true if (enhance) queryParams.append('enhance', 'true'); // Add parameters queryParams.append('nologo', 'true'); // Always set nologo to true queryParams.append('private', 'true'); // Always set private to true) queryParams.append('safe', safe.toString()); // Use the customizable safe parameter // Construct the URL const encodedPrompt = encodeURIComponent(prompt); const baseUrl = 'https://image.pollinations.ai'; let url = `${baseUrl}/prompt/${encodedPrompt}`; // Add query parameters const queryString = queryParams.toString(); url += `?${queryString}`; try { // Prepare fetch options with optional auth headers const fetchOptions = {}; if (authConfig) { fetchOptions.headers = {}; if (authConfig.token) { fetchOptions.headers['Authorization'] = `Bearer ${authConfig.token}`; } if (authConfig.referrer) { fetchOptions.headers['Referer'] = authConfig.referrer; } } // Fetch the image from the URL const response = await fetch(url, fetchOptions); if (!response.ok) { throw new Error(`Failed to edit image: ${response.statusText}`); } // Get the image data as an ArrayBuffer const imageBuffer = await response.arrayBuffer(); // Convert the ArrayBuffer to a base64 string const base64Data = Buffer.from(imageBuffer).toString('base64'); // Determine the mime type from the response headers or default to image/jpeg const contentType = response.headers.get('content-type') || 'image/jpeg'; // Prepare the result object const result = { data: base64Data, mimeType: contentType, metadata: { prompt, inputImageUrl: imageUrl, width, height, model, seed, enhance, private: true, nologo: true, safe } }; // Always save the image to a file // Import required modules const fs = await import('fs'); const path = await import('path'); // Create the output directory if it doesn't exist if (!fs.existsSync(outputPath)) { fs.mkdirSync(outputPath, { recursive: true }); } // Generate a filename if not provided let finalFileName = fileName; if (!finalFileName) { // Create a filename from the prompt (first 20 characters) and timestamp const sanitizedPrompt = prompt.replace(/[^a-zA-Z0-9]/g, '_').substring(0, 20); const timestamp = Date.now(); const randomSuffix = Math.floor(Math.random() * 1000); finalFileName = `edited_${sanitizedPrompt}_${timestamp}_${randomSuffix}`; } // Ensure the filename has the correct extension const extension = format.toLowerCase(); if (!finalFileName.endsWith(`.${extension}`)) { finalFileName += `.${extension}`; } // Check if file already exists and add a number suffix if needed let finalFilePath = path.join(outputPath, finalFileName); let counter = 1; while (fs.existsSync(finalFilePath)) { const nameWithoutExt = finalFileName.replace(`.${extension}`, ''); const numberedFileName = `${nameWithoutExt}_${counter}.${extension}`; finalFilePath = path.join(outputPath, numberedFileName); counter++; } // Write the image data to the file fs.writeFileSync(finalFilePath, Buffer.from(base64Data, 'base64')); // Add the file path to the result result.filePath = finalFilePath; return result; } catch (error) { log('Error editing image:', error); throw error; } }
- src/services/imageSchema.js:116-172 (schema)JSON schema defining the input parameters, types, descriptions, and requirements for the editImage tool.export const editImageSchema = { name: 'editImage', description: 'Edit or modify an existing image based on a text prompt. User-configured settings in MCP config will be used as defaults unless specifically overridden.', inputSchema: { type: 'object', properties: { prompt: { type: 'string', description: 'The text description of how to edit the image (e.g., "remove the cat and add a dog", "change background to mountains")' }, imageUrl: { oneOf: [ { type: 'string' }, { type: 'array', items: { type: 'string' } } ], description: 'Public HTTP(S) URL(s) of the input image(s) to edit. Accepts a string or an array for multiple references (first is most important). Local file paths, file uploads, or base64/data URLs are not supported.' }, model: { type: 'string', description: 'Model name to use for editing (default: user config or "kontext"). Available: "kontext", "nanobanana", "seedream"' }, seed: { type: 'number', description: 'Seed for reproducible results (default: random)' }, width: { type: 'number', description: 'Width of the generated image (default: 1024)' }, height: { type: 'number', description: 'Height of the generated image (default: 1024)' }, enhance: { type: 'boolean', description: 'Whether to enhance the prompt using an LLM before generating (default: true)' }, safe: { type: 'boolean', description: 'Whether to apply content filtering (default: false)' }, outputPath: { type: 'string', description: 'Directory path where to save the image (default: user config or "./mcpollinations-output")' }, fileName: { type: 'string', description: 'Name of the file to save (without extension, default: generated from prompt)' }, format: { type: 'string', description: 'Image format to save as (png, jpeg, jpg, webp - default: png)' } }, required: ['prompt', 'imageUrl'] } };
- pollinations-mcp-server.js:363-398 (registration)MCP server request handler for CallToolRequestSchema that dispatches to editImage function when name === 'editImage', applies defaults, handles response formatting with image content and metadata text, and error handling.} else if (name === 'editImage') { try { const { prompt, imageUrl, model = 'kontext', seed, width = defaultConfig.image.width, height = defaultConfig.image.height, enhance = defaultConfig.image.enhance, safe = defaultConfig.image.safe, outputPath = defaultConfig.resources.output_dir, fileName = '', format = 'png' } = args; const result = await editImage(prompt, imageUrl, model, seed, width, height, enhance, safe, outputPath, fileName, format, finalAuthConfig); // Prepare the response content const content = [ { type: 'image', data: result.data, mimeType: result.mimeType } ]; // Prepare the response text let responseText = `Edited image from prompt: "${prompt}"\nInput image: ${imageUrl}\n\nImage metadata: ${JSON.stringify(result.metadata, null, 2)}`; // Add file path information if the image was saved to a file if (result.filePath) { responseText += `\n\nImage saved to: ${result.filePath}`; } content.push({ type: 'text', text: responseText }); return { content }; } catch (error) { return { content: [ { type: 'text', text: `Error editing image: ${error.message}` } ], isError: true }; }
- pollinations-mcp-server.js:198-200 (registration)MCP server registration for ListToolsRequestSchema that returns all tool schemas including editImageSchema via getAllToolSchemas().server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: getAllToolSchemas() }));
- src/schemas.js:36-36 (schema)Inclusion of editImageSchema in the central getAllToolSchemas() array used for MCP tool listing.editImageSchema,