#
tokens: 3353/50000 7/7 files
lines: off (toggle) GitHub
raw markdown copy
# Directory Structure

```
├── .gitignore
├── Dockerfile
├── LICENSE
├── package-lock.json
├── package.json
├── README.md
├── smithery.yaml
├── src
│   └── index.ts
└── tsconfig.json
```

# Files

--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------

```
node_modules/
build/
*.log
.env*
```

--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------

```markdown
# Image Generation MCP Server
![](https://badge.mcpx.dev?type=server 'MCP Server')

[![smithery badge](https://smithery.ai/badge/@GongRzhe/Image-Generation-MCP-Server)](https://smithery.ai/server/@GongRzhe/Image-Generation-MCP-Server)

This MCP server provides image generation capabilities using the Replicate Flux model.

## Installation

### Installing via Smithery

To install Image Generation MCP Server for Claude Desktop automatically via [Smithery](https://smithery.ai/server/@GongRzhe/Image-Generation-MCP-Server):

```bash
npx -y @smithery/cli install @GongRzhe/Image-Generation-MCP-Server --client claude
```

### Option 1: NPX Method (No Local Setup Required)
You can use the package directly from npm without installing it locally:

```bash
# No installation needed - npx will handle it
```

### Option 2: Local Installation
If you prefer a local installation:

```bash
# Global installation
npm install -g @gongrzhe/image-gen-server

# Or local installation
npm install @gongrzhe/image-gen-server
```

## Setup

### Configure Claude Desktop

Edit your Claude Desktop configuration file:

- On MacOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
- On Windows: `%APPDATA%/Claude/claude_desktop_config.json`

#### Option 1: NPX Configuration (Recommended)
This method runs the server directly from npm without needing local files:

```json
{
  "mcpServers": {
    "image-gen": {
      "command": "npx",
      "args": ["@gongrzhe/image-gen-server"],
      "env": {
        "REPLICATE_API_TOKEN": "your-replicate-api-token",
        "MODEL": "alternative-model-name"
      },
      "disabled": false,
      "autoApprove": []
    }
  }
}
```

#### Option 2: Local Installation Configuration
If you installed the package locally:

```json
{
  "mcpServers": {
    "image-gen": {
      "command": "node",
      "args": ["/path/to/image-gen-server/build/index.js"],
      "env": {
        "REPLICATE_API_TOKEN": "your-replicate-api-token",
        "MODEL": "alternative-model-name"
      },
      "disabled": false,
      "autoApprove": []
    }
  }
}
```

### Get Your Replicate API Token

1. Sign up/login at https://replicate.com
2. Go to https://replicate.com/account/api-tokens
3. Create a new API token
4. Copy the token and replace `your-replicate-api-token` in the MCP settings

![image](https://github.com/user-attachments/assets/583afa78-1a08-4eb5-9a37-decb95bd50c4)

### Environment Variables

- `REPLICATE_API_TOKEN` (required): Your Replicate API token for authentication
- `MODEL` (optional): The Replicate model to use for image generation. Defaults to "black-forest-labs/flux-schnell"

### Configuration Parameters

- `disabled`: Controls whether the server is enabled (`false`) or disabled (`true`)
- `autoApprove`: Array of tool names that can be executed without user confirmation. Empty array means all tool calls require confirmation.

## Available Tools

### generate_image

Generates images using the Flux model based on text prompts.

![image](https://github.com/user-attachments/assets/766921ce-ca8e-4d68-866d-8c7b55b2e09d)

![out-0 (1)](https://github.com/user-attachments/assets/83549b2e-525a-4ff9-825c-83ba74459575)

#### Parameters

- `prompt` (required): Text description of the image to generate
- `seed` (optional): Random seed for reproducible generation
- `aspect_ratio` (optional): Image aspect ratio (default: "1:1")
- `output_format` (optional): Output format - "webp", "jpg", or "png" (default: "webp")
- `num_outputs` (optional): Number of images to generate (1-4, default: 1)

#### Example Usage

```typescript
const result = await use_mcp_tool({
  server_name: "image-gen",
  tool_name: "generate_image",
  arguments: {
    prompt: "A beautiful sunset over mountains",
    aspect_ratio: "16:9",
    output_format: "png",
    num_outputs: 1
  }
});
```

The tool returns an array of URLs to the generated images.

## 📜 License

This project is licensed under the MIT License.

```

--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------

```json
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ES2020",
    "moduleResolution": "node",
    "esModuleInterop": true,
    "strict": true,
    "outDir": "build",
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules"]
}

```

--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------

```dockerfile
# Generated by https://smithery.ai. See: https://smithery.ai/docs/config#dockerfile
FROM node:lts-alpine AS builder

WORKDIR /app

# Copy dependency definitions
COPY package.json package-lock.json ./

# Install dependencies, including production and dev
RUN npm install

# Copy source files and configuration
COPY tsconfig.json ./
COPY src ./src

# Build the project
RUN npm run build

FROM node:lts-alpine

WORKDIR /app

# Copy built files and node_modules from builder stage
COPY --from=builder /app/package.json ./
COPY --from=builder /app/build ./build
COPY --from=builder /app/node_modules ./node_modules

EXPOSE 3000

CMD ["node", "build/index.js"]

```

--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------

```json
{
  "name": "@gongrzhe/image-gen-server",
  "version": "1.0.1",
  "type": "module",
  "main": "build/index.js",
  "scripts": {
    "build": "tsc",
    "start": "node build/index.js",
    "prepublishOnly": "npm run build"
  },
  "keywords": [],
  "author": "GongRzhe",
  "license": "MIT",
  "description": "An MCP server for image generation using the Replicate Flux model",
  "dependencies": {
    "@modelcontextprotocol/sdk": "^1.5.0",
    "@types/node": "^22.13.5",
    "axios": "^1.7.9",
    "typescript": "^5.7.3"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/GongRzhe/image-gen-server.git"
  },
  "bugs": {
    "url": "https://github.com/GongRzhe/image-gen-server/issues"
  },
  "homepage": "https://github.com/GongRzhe/image-gen-server#readme",
  "bin": {
    "image-gen-server": "build/index.js"
  },
  "files": [
    "build/**/*"
  ]
}

```

--------------------------------------------------------------------------------
/smithery.yaml:
--------------------------------------------------------------------------------

```yaml
# Smithery configuration file: https://smithery.ai/docs/config#smitheryyaml

startCommand:
  type: stdio
  configSchema:
    # JSON Schema defining the configuration options for the MCP.
    type: object
    required:
      - replicateApiToken
    properties:
      replicateApiToken:
        type: string
        description: Replicate API token for authentication
      model:
        type: string
        default: black-forest-labs/flux-schnell
        description: Replicate model to use for image generation
  commandFunction:
    # A JS function that produces the CLI command based on the given config to start the MCP on stdio.
    |-
    (config) => ({
      command: 'node',
      args: ['build/index.js'],
      env: {
        REPLICATE_API_TOKEN: config.replicateApiToken,
        MODEL: config.model
      }
    })
  exampleConfig:
    replicateApiToken: example-token-1234
    model: alternative-model-name

```

--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------

```typescript
#!/usr/bin/env node
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import {
  CallToolRequestSchema,
  ErrorCode,
  ListToolsRequestSchema,
  McpError,
} from '@modelcontextprotocol/sdk/types.js';
import axios from 'axios';

const REPLICATE_API_TOKEN = process.env.REPLICATE_API_TOKEN;
if (!REPLICATE_API_TOKEN) {
  throw new Error('REPLICATE_API_TOKEN environment variable is required');
}

interface FluxInput {
  prompt: string;
  seed?: number;
  go_fast?: boolean;
  megapixels?: '1' | '0.25';
  num_outputs?: number;
  aspect_ratio?: '1:1' | '16:9' | '21:9' | '3:2' | '2:3' | '4:5' | '5:4' | '3:4' | '4:3' | '9:16' | '9:21';
  output_format?: 'webp' | 'jpg' | 'png';
  output_quality?: number;
  num_inference_steps?: number;
  disable_safety_checker?: boolean;
}

class ImageGenerationServer {
  private server: Server;
  private axiosInstance;
  private readonly MODEL = process.env.MODEL || 'black-forest-labs/flux-schnell';

  constructor() {
    this.server = new Server(
      {
        name: 'image-generation-server',
        version: '0.1.0',
      },
      {
        capabilities: {
          tools: {},
        },
      }
    );

    this.axiosInstance = axios.create({
      baseURL: 'https://api.replicate.com/v1',
      headers: {
        'Authorization': `Token ${REPLICATE_API_TOKEN}`,
        'Content-Type': 'application/json',
      },
    });

    this.setupToolHandlers();
    
    // Error handling
    this.server.onerror = (error) => console.error('[MCP Error]', error);
    process.on('SIGINT', async () => {
      await this.server.close();
      process.exit(0);
    });
  }

  private setupToolHandlers() {
    this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
      tools: [
        {
          name: 'generate_image',
          description: 'Generate an image using the Flux model',
          inputSchema: {
            type: 'object',
            properties: {
              prompt: {
                type: 'string',
                description: 'Prompt for generated image',
              },
              seed: {
                type: 'integer',
                description: 'Random seed for reproducible generation',
              },
              aspect_ratio: {
                type: 'string',
                enum: ['1:1', '16:9', '21:9', '3:2', '2:3', '4:5', '5:4', '3:4', '4:3', '9:16', '9:21'],
                description: 'Aspect ratio for the generated image',
                default: '1:1',
              },
              output_format: {
                type: 'string',
                enum: ['webp', 'jpg', 'png'],
                description: 'Format of the output images',
                default: 'webp',
              },
              num_outputs: {
                type: 'integer',
                description: 'Number of outputs to generate (1-4)',
                default: 1,
                minimum: 1,
                maximum: 4,
              },
            },
            required: ['prompt'],
          },
        },
      ],
    }));

    this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
      if (request.params.name !== 'generate_image') {
        throw new McpError(
          ErrorCode.MethodNotFound,
          `Unknown tool: ${request.params.name}`
        );
      }

      // Validate input arguments
      if (!request.params.arguments || typeof request.params.arguments !== 'object') {
        throw new McpError(
          ErrorCode.InvalidParams,
          'Arguments must be an object'
        );
      }

      if (!('prompt' in request.params.arguments) || typeof request.params.arguments.prompt !== 'string') {
        throw new McpError(
          ErrorCode.InvalidParams,
          'Prompt is required and must be a string'
        );
      }

      const input: FluxInput = {
        prompt: request.params.arguments.prompt,
      };

      // Add optional parameters if they exist and are valid
      if ('seed' in request.params.arguments && typeof request.params.arguments.seed === 'number') {
        input.seed = request.params.arguments.seed;
      }
      if ('aspect_ratio' in request.params.arguments && typeof request.params.arguments.aspect_ratio === 'string') {
        input.aspect_ratio = request.params.arguments.aspect_ratio as FluxInput['aspect_ratio'];
      }
      if ('output_format' in request.params.arguments && typeof request.params.arguments.output_format === 'string') {
        input.output_format = request.params.arguments.output_format as FluxInput['output_format'];
      }
      if ('num_outputs' in request.params.arguments && typeof request.params.arguments.num_outputs === 'number') {
        input.num_outputs = Math.min(Math.max(1, request.params.arguments.num_outputs), 4);
      }

      try {
        // Create prediction
        const createResponse = await this.axiosInstance.post('/predictions', {
          version: this.MODEL,
          input,
        });

        const predictionId = createResponse.data.id;

        // Poll for completion
        while (true) {
          const getResponse = await this.axiosInstance.get(`/predictions/${predictionId}`);
          const prediction = getResponse.data;

          if (prediction.status === 'succeeded') {
            return {
              content: [
                {
                  type: 'text',
                  text: JSON.stringify(prediction.output),
                },
              ],
            };
          } else if (prediction.status === 'failed') {
            throw new McpError(
              ErrorCode.InternalError,
              `Image generation failed: ${prediction.error || 'Unknown error'}`
            );
          }

          // Wait before polling again
          await new Promise(resolve => setTimeout(resolve, 1000));
        }
      } catch (error) {
        if (axios.isAxiosError(error)) {
          throw new McpError(
            ErrorCode.InternalError,
            `Replicate API error: ${error.response?.data?.detail || error.message}`
          );
        }
        throw error;
      }
    });
  }

  async run() {
    const transport = new StdioServerTransport();
    await this.server.connect(transport);
    console.error('Image Generation MCP server running on stdio');
  }
}

const server = new ImageGenerationServer();
server.run().catch(console.error);

```