Skip to main content
Glama
mikeyny

Image Generation MCP Server

by mikeyny

generate-image

Create custom images from text descriptions with configurable settings for size, format, and quality. Save generated images to specified directories for various applications.

Instructions

Generate an image based on a prompt

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
promptYes
output_dirYesFull absolute path to output directory. For Windows, use double backslashes like 'C:\\Users\\name\\path'. For Unix/Mac use '/path/to/dir'. Always use the proper path otherwise you will get an error.
filenameNoBase filename to save the image(s) with
go_fastNo
megapixelsNo
num_outputsNo
aspect_ratioNo
output_formatNo
output_qualityNo
num_inference_stepsNo

Implementation Reference

  • Core handler method of ImageGenerationService that implements the image generation logic: caching, calling Replicate API, downloading images, saving to disk, and error handling.
    async generateImages(params: ImageGenerationParams): Promise<ImageGenerationResponse> {
      const startTime = Date.now();
    
      try {
        // Check cache first
        const cacheKey = this.generateCacheKey(params);
        const cached = this.cache.get(cacheKey);
        
        if (cached) {
          // Verify files still exist
          const allFilesExist = cached.response.image_paths.every(path => fs.existsSync(path));
          if (allFilesExist) {
            return {
              ...cached.response,
              metadata: {
                ...cached.response.metadata,
                cache_hit: true
              }
            };
          }
          // If files don't exist, remove from cache
          this.cache.delete(cacheKey);
        }
    
        // Prepare model input
        const modelInput = {
          prompt: params.prompt,
          go_fast: params.go_fast ?? false,
          megapixels: params.megapixels ?? "1",
          num_outputs: params.num_outputs ?? 1,
          aspect_ratio: params.aspect_ratio ?? "1:1",
          num_inference_steps: params.num_inference_steps ?? 4
        };
    
        // Call Replicate API
        const output = await this.replicate.run(
          this.MODEL,
          { input: modelInput }
        ) as string[];
    
        // Download and save images
        const imagePaths = await this.saveImages(
          output,
          params.output_dir,
          params.output_format ?? 'webp',
          params.output_quality ?? 80,
          params.filename
        );
    
        const endTime = Date.now();
    
        const response: ImageGenerationResponse = {
          image_paths: imagePaths,
          metadata: {
            model: this.MODEL,
            inference_time_ms: endTime - startTime,
            cache_hit: false
          }
        };
    
        // Cache the result
        this.cache.set(cacheKey, {
          response,
          timestamp: Date.now()
        });
    
        return response;
    
      } catch (error: any) {
    
        if (error.response) {
          const apiError = new Error(error.message) as APIError;
          apiError.code = 'API_ERROR';
          apiError.details = {
            message: error.message,
            status: error.response.status
          };
          throw apiError;
        }
    
        const serverError = new Error('Server error occurred') as ServerError;
        serverError.code = 'SERVER_ERROR';
        serverError.details = {
          message: 'Failed to generate or save images',
          system_error: error.message
        };
        throw serverError;
      }
    }
  • src/server.ts:18-52 (registration)
    MCP server tool registration for 'generate-image', including description, Zod input schema, and wrapper handler delegating to ImageGenerationService.
    // Register the image generation tool
    server.tool(
      "generate-image",
      "Generate an image based on a prompt",
      {
        prompt: z.string(),
        output_dir: z.string().describe("Full absolute path to output directory. For Windows, use double backslashes like 'C:\\\\Users\\\\name\\\\path'. For Unix/Mac use '/path/to/dir'. Always use the proper path otherwise you will get an error."),
        filename: z.string().optional().describe("Base filename to save the image(s) with"),
        go_fast: z.boolean().optional(),
        megapixels: z.enum(["1", "2", "4"]).optional(),
        num_outputs: z.number().min(1).max(4).optional(),
        aspect_ratio: z.enum(["1:1", "4:3", "16:9"]).optional(),
        output_format: z.enum(["webp", "png", "jpeg"]).optional(),
        output_quality: z.number().min(1).max(100).optional(),
        num_inference_steps: z.number().min(4).max(20).optional()
      },
      async (params) => {
        try {
          const result = await imageService.generateImages(params);
          return {
            content: [{
              type: "text",
              text: JSON.stringify(result, null, 2)
            }]
          };
        } catch (error: any) {
          return {
            content: [{
              type: "text",
              text: `Error: ${error.message}`
            }]
          };
        }
      }
    );
  • TypeScript interface defining the input parameters for the generate-image tool, used by ImageGenerationService.
    export interface ImageGenerationParams {
      prompt: string;
      output_dir: string;
      filename?: string;
      go_fast?: boolean;
      megapixels?: "1" | "2" | "4";
      num_outputs?: number;
      aspect_ratio?: "1:1" | "4:3" | "16:9";
      output_format?: "webp" | "png" | "jpeg";
      output_quality?: number;
      num_inference_steps?: number;
    }
  • Helper method to download images from URLs (with retries), save them to disk in batches with concurrency limit, and return file paths.
    private async saveImages(
      imageUrls: string[],
      outputDir: string,
      format: 'webp' | 'png' | 'jpeg',
      quality: number,
      baseFilename?: string
    ): Promise<string[]> {
      // Create output directory if it doesn't exist
      if (!fs.existsSync(outputDir)) {
        fs.mkdirSync(outputDir, { recursive: true });
      }
    
      // Prepare download tasks
      const downloadTasks = imageUrls.map(async (imageUrl, i) => {
        const filename = baseFilename 
          ? (imageUrls.length > 1 ? `${baseFilename}_${i + 1}.${format}` : `${baseFilename}.${format}`)
          : `output_${i}.${format}`;
        const filePath = path.join(outputDir, filename);
    
        try {
          // Download image with retry mechanism
          const buffer = await this.downloadWithRetry(imageUrl);
          
          // Save image atomically using temporary file
          const tempPath = `${filePath}.tmp`;
          fs.writeFileSync(tempPath, buffer);
          fs.renameSync(tempPath, filePath);
          
          return filePath;
        } catch (error: any) {
          const serverError = new Error('Failed to save image') as ServerError;
          serverError.code = 'SERVER_ERROR';
          serverError.details = {
            message: `Failed to save image ${i}`,
            system_error: error.message
          };
          throw serverError;
        }
      });
    
      // Execute all downloads in parallel with a concurrency limit
      const CONCURRENCY_LIMIT = 3;
      const imagePaths: string[] = [];
      
      for (let i = 0; i < downloadTasks.length; i += CONCURRENCY_LIMIT) {
        const batch = downloadTasks.slice(i, i + CONCURRENCY_LIMIT);
        const results = await Promise.all(batch);
        imagePaths.push(...results);
      }
    
      return imagePaths;
    }
Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/mikeyny/ai-image-gen-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server