generateImage
Create images from text descriptions using the FLUX AI model, with options to customize dimensions, enhance detail, and adjust safety settings.
Instructions
Generate an image using Black Forest Lab's FLUX model based on a text prompt
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| prompt | Yes | Text description of the image to generate | |
| width | No | Width of the image in pixels | |
| height | No | Height of the image in pixels | |
| promptUpsampling | No | Enhance detail by upsampling the prompt | |
| seed | No | Random seed for reproducible results | |
| safetyTolerance | No | Content moderation tolerance (1-5) | |
| customPath | No | Custom path to save the generated image |
Implementation Reference
- src/services/bflService.ts:102-221 (handler)The core handler function that executes the generateImage tool logic: makes API call to Black Forest Lab FLUX, polls for completion, downloads and saves image locally if requested.export async function generateImage( prompt: string, options: ImageGenerationOptions = {} ): Promise<ImageGenerationResult> { const apiKey = process.env.BFL_API_KEY; if (!apiKey) { throw new Error('API key is required. Set BFL_API_KEY environment variable.'); } // Build the request payload const payload = { prompt, width: options.width || 1024, height: options.height || 1024, prompt_upsampling: options.promptUpsampling || false, safety_tolerance: options.safetyTolerance || 3, ...(options.seed !== undefined && { seed: options.seed }) }; let pollingUrl; try { // Make the initial API request console.error(`[INFO] Sending request to FLUX API for prompt: "${prompt}"`); const response = await axios.post(BFL_API_ENDPOINT, payload, { headers: { 'Content-Type': 'application/json', 'X-Key': apiKey } }); // Check if we need to poll for results if (response.data.polling_url) { pollingUrl = response.data.polling_url; console.error(`[INFO] Got polling URL: ${pollingUrl}`); } else if (response.data.image_url) { // If we got an image URL directly, no need to poll console.error(`[INFO] Got image URL directly: ${response.data.image_url}`); const result: ImageGenerationResult = { image_url: response.data.image_url, local_path: null }; // Save the image locally if requested if (options.saveImage) { try { const filename = options.filename || `flux_${Date.now()}.png`; const savePath = await downloadImage( result.image_url, filename, options.outputDir || process.env.OUTPUT_DIR || './output', options.customPath ); result.local_path = savePath; } catch (downloadError: any) { console.error(`[ERROR] Error saving image: ${downloadError.message}`); // Continue with the operation even if download fails } } return result; } else { throw new Error('Invalid response from Black Forest Lab API: No polling URL or image URL'); } } catch (error: any) { const errorMsg = error.response?.data?.message || error.message || 'Unknown error'; console.error(`[ERROR] Error calling Black Forest Lab API: ${errorMsg}`); throw new Error(`Failed to generate image: ${errorMsg}`); } // If we have a polling URL, poll for the result try { const maxPollingAttempts = options.maxPollingAttempts || 30; const pollingInterval = options.pollingInterval || 2000; const pollResult = await pollForResults( pollingUrl, apiKey, maxPollingAttempts, pollingInterval ); // Check if we have a direct image_url or need to extract it from result.sample if (!pollResult.image_url && pollResult.result && pollResult.result.sample) { pollResult.image_url = pollResult.result.sample; } if (!pollResult.image_url) { throw new Error('No image URL in completed result'); } const result: ImageGenerationResult = { image_url: pollResult.image_url, local_path: null }; // Save the image locally if requested if (options.saveImage) { try { const filename = options.filename || `flux_${Date.now()}.png`; const savePath = await downloadImage( result.image_url, filename, options.outputDir || process.env.OUTPUT_DIR || './output', options.customPath ); result.local_path = savePath; } catch (downloadError: any) { console.error(`[ERROR] Error saving image: ${downloadError.message}`); // Continue with the operation even if download fails } } return result; } catch (error: any) { console.error(`[ERROR] Error in polling process: ${error.message}`); throw new Error(`Failed to generate image: ${error.message}`); } }
- src/schemas.ts:9-50 (schema)The schema definition for the generateImage tool, including input schema, description, and parameters.export const GENERATE_IMAGE_TOOL: Tool = { name: "generateImage", description: "Generate an image using Black Forest Lab's FLUX model based on a text prompt", inputSchema: { type: "object", properties: { prompt: { type: "string", description: "Text description of the image to generate" }, width: { type: "number", description: "Width of the image in pixels", default: 1024 }, height: { type: "number", description: "Height of the image in pixels", default: 1024 }, promptUpsampling: { type: "boolean", description: "Enhance detail by upsampling the prompt", default: false }, seed: { type: "number", description: "Random seed for reproducible results" }, safetyTolerance: { type: "number", description: "Content moderation tolerance (1-5)", default: 3 }, customPath: { type: "string", description: "Custom path to save the generated image" } }, required: ["prompt"] } };
- src/index.ts:48-54 (registration)Registration of the generateImage tool schema in the MCP server's listTools request handler.server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: [ GENERATE_IMAGE_TOOL, QUICK_IMAGE_TOOL, BATCH_GENERATE_IMAGES_TOOL ], }));
- src/index.ts:72-106 (handler)The MCP CallToolRequestSchema handler case for generateImage: validates input arguments, prepares options, calls the core generateImage function, and formats the response.case "generateImage": { // Validate parameters if (typeof args.prompt !== 'string') { throw new Error("Invalid prompt: must be a string"); } // Use the full image generation capabilities const options = { width: typeof args.width === 'number' ? args.width : 1024, height: typeof args.height === 'number' ? args.height : 1024, promptUpsampling: typeof args.promptUpsampling === 'boolean' ? args.promptUpsampling : false, seed: typeof args.seed === 'number' ? args.seed : undefined, safetyTolerance: typeof args.safetyTolerance === 'number' ? args.safetyTolerance : 3, saveImage: true, filename: `flux_${Date.now()}.png`, customPath: typeof args.customPath === 'string' ? args.customPath : undefined }; const result = await generateImage(args.prompt, options); // Return a plain text response with the image URL and save location let textContent = `Image generated\nLink: ${result.image_url}`; // Add information about where the image was saved if (result.local_path) { textContent += `\nImage saved to: ${result.local_path}`; } return { content: [ { type: "text", text: textContent } ], isError: false, }; }