create_image
Generate images from text prompts using AI, with options for size, format, quality, and background settings.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| prompt | Yes | ||
| background | No | ||
| n | No | ||
| output_compression | No | ||
| output_format | No | ||
| quality | No | ||
| size | No | ||
| user | No | ||
| moderation | No |
Implementation Reference
- src/index.ts:174-361 (handler)The async handler function that implements the 'create_image' tool logic: calls OpenAI's images.generate API with gpt-image-1 model, processes the base64 response, saves images to disk using saveImageToDisk, handles detailed errors, and returns a rich formatted response with text summary and image contents.async (args: CreateImageArgs, extra: any) => { try { // Use the OpenAI SDK's createImage method with detailed error handling let apiResponse; try { apiResponse = await openai.images.generate({ model: "gpt-image-1", prompt: args.prompt, size: args.size || "1024x1024", quality: args.quality || "high", n: args.n || 1 }); // Check if the response contains an error field (shouldn't happen with SDK but just in case) if (apiResponse && 'error' in apiResponse) { const error = (apiResponse as any).error; throw { message: error.message || 'Unknown API error', type: error.type || 'api_error', code: error.code || 'unknown', response: { data: { error } } }; } } catch (apiError: any) { // Enhance the error with more details if possible console.error("OpenAI API Error:", apiError); // Rethrow with enhanced information throw apiError; } // Create a Response-like object with a json() method for compatibility with the built-in tool const response = { json: () => Promise.resolve(apiResponse) }; const responseData = apiResponse; const format = args.output_format || "png"; // Save images to disk and create response with file paths const savedImages = []; const imageContents = []; if (responseData.data && responseData.data.length > 0) { for (const item of responseData.data) { if (item.b64_json) { // Save the image to disk const imagePath = saveImageToDisk(item.b64_json, format); // Add the saved image info to our response savedImages.push({ path: imagePath, format: format }); // Also include the image content for compatibility imageContents.push({ type: "image" as const, data: item.b64_json, mimeType: `image/${format}` }); } else if (item.url) { console.error(`Image URL: ${item.url}`); console.error("The gpt-image-1 model returned a URL instead of base64 data."); console.error("To view the image, open the URL in your browser."); // Add the URL info to our response savedImages.push({ url: item.url, format: format }); // Include a text message about the URL in the content imageContents.push({ type: "text" as const, text: `Image available at URL: ${item.url}` }); } } } // Create a beautifully formatted response with emojis and details const formatSize = (size: string | undefined) => size || "1024x1024"; const formatQuality = (quality: string | undefined) => quality || "high"; // Create a beautiful formatted message const formattedMessage = ` šØ **Image Generation Complete!** šØ ⨠**Prompt**: "${args.prompt}" š **Generation Parameters**: ⢠Size: ${formatSize(args.size)} ⢠Quality: ${formatQuality(args.quality)} ⢠Number of Images: ${args.n || 1} ${args.background ? `⢠Background: ${args.background}` : ''} ${args.output_format ? `⢠Format: ${args.output_format}` : ''} ${args.output_compression ? `⢠Compression: ${args.output_compression}%` : ''} ${args.moderation ? `⢠Moderation: ${args.moderation}` : ''} š **Generated ${savedImages.length} Image${savedImages.length > 1 ? 's' : ''}**: ${savedImages.map((img, index) => ` ${index + 1}. ${img.path || img.url}`).join('\n')} ${responseData.usage ? `ā” **Token Usage**: ⢠Total Tokens: ${responseData.usage.total_tokens} ⢠Input Tokens: ${responseData.usage.input_tokens} ⢠Output Tokens: ${responseData.usage.output_tokens}` : ''} š You can find your image${savedImages.length > 1 ? 's' : ''} at the path${savedImages.length > 1 ? 's' : ''} above! `; // Return both the image content and the saved file paths with the beautiful message return { content: [ { type: "text" as const, text: formattedMessage }, ...imageContents ], ...(responseData.usage && { _meta: { usage: responseData.usage, savedImages: savedImages } }) }; } catch (error: any) { // Log the full error for debugging console.error("Error generating image:", error); // Extract detailed error information const errorCode = error.status || error.code || 'Unknown'; const errorType = error.type || 'Error'; const errorMessage = error.message || 'An unknown error occurred'; // Check for specific OpenAI API errors let detailedError = ''; if (error.response) { // If we have a response object from OpenAI, extract more details try { const responseData = error.response.data || {}; if (responseData.error) { detailedError = `\nš **Details**: ${responseData.error.message || 'No additional details available'}`; // Add parameter errors if available if (responseData.error.param) { detailedError += `\nš **Parameter**: ${responseData.error.param}`; } // Add code if available if (responseData.error.code) { detailedError += `\nš¢ **Error Code**: ${responseData.error.code}`; } // Add type if available if (responseData.error.type) { detailedError += `\nš **Error Type**: ${responseData.error.type}`; } } } catch (parseError) { // If we can't parse the response, just use what we have detailedError = '\nš **Details**: Could not parse error details from API response'; } } // Construct a comprehensive error message const fullErrorMessage = `ā **Image Generation Failed**\n\nā ļø **Error ${errorCode}**: ${errorType} - ${errorMessage}${detailedError}\n\nš Please try again with a different prompt or parameters.`; // Return the detailed error to the client return { content: [{ type: "text", text: fullErrorMessage }], isError: true, _meta: { error: { code: errorCode, type: errorType, message: errorMessage, raw: JSON.stringify(error, Object.getOwnPropertyNames(error)) } } }; } }
- src/index.ts:155-166 (schema)Zod schema defining the input parameters for the create_image tool, including prompt, size, quality, etc., with validation rules.const createImageSchema = z.object({ prompt: z.string().max(32000, "Prompt exceeds maximum length for gpt-image-1."), background: z.enum(["transparent", "opaque", "auto"]).optional(), n: z.number().int().min(1).max(10).optional(), output_compression: z.number().int().min(0).max(100).optional(), output_format: z.enum(["png", "jpeg", "webp"]).optional(), quality: z.enum(["high", "medium", "low", "auto"]).optional(), size: z.enum(["1024x1024", "1536x1024", "1024x1536", "auto"]).optional(), user: z.string().optional(), moderation: z.enum(["low", "auto"]).optional() }); type CreateImageArgs = z.infer<typeof createImageSchema>;
- src/index.ts:168-173 (registration)Registers the 'create_image' tool with the MCP server using server.tool(), specifying the name, input schema, metadata title, and handler function.server.tool( "create_image", createImageSchema.shape, { title: "Generate new images using OpenAI's gpt-image-1 model" },
- src/index.ts:87-110 (helper)Helper utility to save base64-encoded image data to a file in the configured output directory, used by the create_image handler to persist generated images.function saveImageToDisk(base64Data: string, format: string = 'png'): string { // Create a dedicated folder for generated images if we're using the workspace root // This keeps the workspace organized while still saving in the current directory const imagesFolder = path.join(outputDir, 'gpt-images'); // Create the images folder if it doesn't exist if (!fs.existsSync(imagesFolder)) { fs.mkdirSync(imagesFolder, { recursive: true }); console.error(`Created images folder: ${imagesFolder}`); } const timestamp = new Date().toISOString().replace(/[:.]/g, '-'); const filename = `image-${timestamp}.${format}`; const outputPath = path.join(imagesFolder, filename); // Remove the data URL prefix if present const base64Image = base64Data.replace(/^data:image\/\w+;base64,/, ''); // Write the image to disk fs.writeFileSync(outputPath, Buffer.from(base64Image, 'base64')); console.error(`Image saved to: ${outputPath}`); return outputPath; }