#
tokens: 4606/50000 7/7 files
lines: on (toggle) GitHub
raw markdown copy reset
# Directory Structure

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

# Files

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

```
1 | node_modules/
2 | build/
3 | *.log
4 | .env*
```

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

```markdown
  1 | # Image Generation MCP Server
  2 | ![](https://badge.mcpx.dev?type=server 'MCP Server')
  3 | 
  4 | [![smithery badge](https://smithery.ai/badge/@GongRzhe/Image-Generation-MCP-Server)](https://smithery.ai/server/@GongRzhe/Image-Generation-MCP-Server)
  5 | 
  6 | This MCP server provides image generation capabilities using the Replicate Flux model.
  7 | 
  8 | ## Installation
  9 | 
 10 | ### Installing via Smithery
 11 | 
 12 | To install Image Generation MCP Server for Claude Desktop automatically via [Smithery](https://smithery.ai/server/@GongRzhe/Image-Generation-MCP-Server):
 13 | 
 14 | ```bash
 15 | npx -y @smithery/cli install @GongRzhe/Image-Generation-MCP-Server --client claude
 16 | ```
 17 | 
 18 | ### Option 1: NPX Method (No Local Setup Required)
 19 | You can use the package directly from npm without installing it locally:
 20 | 
 21 | ```bash
 22 | # No installation needed - npx will handle it
 23 | ```
 24 | 
 25 | ### Option 2: Local Installation
 26 | If you prefer a local installation:
 27 | 
 28 | ```bash
 29 | # Global installation
 30 | npm install -g @gongrzhe/image-gen-server
 31 | 
 32 | # Or local installation
 33 | npm install @gongrzhe/image-gen-server
 34 | ```
 35 | 
 36 | ## Setup
 37 | 
 38 | ### Configure Claude Desktop
 39 | 
 40 | Edit your Claude Desktop configuration file:
 41 | 
 42 | - On MacOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
 43 | - On Windows: `%APPDATA%/Claude/claude_desktop_config.json`
 44 | 
 45 | #### Option 1: NPX Configuration (Recommended)
 46 | This method runs the server directly from npm without needing local files:
 47 | 
 48 | ```json
 49 | {
 50 |   "mcpServers": {
 51 |     "image-gen": {
 52 |       "command": "npx",
 53 |       "args": ["@gongrzhe/image-gen-server"],
 54 |       "env": {
 55 |         "REPLICATE_API_TOKEN": "your-replicate-api-token",
 56 |         "MODEL": "alternative-model-name"
 57 |       },
 58 |       "disabled": false,
 59 |       "autoApprove": []
 60 |     }
 61 |   }
 62 | }
 63 | ```
 64 | 
 65 | #### Option 2: Local Installation Configuration
 66 | If you installed the package locally:
 67 | 
 68 | ```json
 69 | {
 70 |   "mcpServers": {
 71 |     "image-gen": {
 72 |       "command": "node",
 73 |       "args": ["/path/to/image-gen-server/build/index.js"],
 74 |       "env": {
 75 |         "REPLICATE_API_TOKEN": "your-replicate-api-token",
 76 |         "MODEL": "alternative-model-name"
 77 |       },
 78 |       "disabled": false,
 79 |       "autoApprove": []
 80 |     }
 81 |   }
 82 | }
 83 | ```
 84 | 
 85 | ### Get Your Replicate API Token
 86 | 
 87 | 1. Sign up/login at https://replicate.com
 88 | 2. Go to https://replicate.com/account/api-tokens
 89 | 3. Create a new API token
 90 | 4. Copy the token and replace `your-replicate-api-token` in the MCP settings
 91 | 
 92 | ![image](https://github.com/user-attachments/assets/583afa78-1a08-4eb5-9a37-decb95bd50c4)
 93 | 
 94 | ### Environment Variables
 95 | 
 96 | - `REPLICATE_API_TOKEN` (required): Your Replicate API token for authentication
 97 | - `MODEL` (optional): The Replicate model to use for image generation. Defaults to "black-forest-labs/flux-schnell"
 98 | 
 99 | ### Configuration Parameters
100 | 
101 | - `disabled`: Controls whether the server is enabled (`false`) or disabled (`true`)
102 | - `autoApprove`: Array of tool names that can be executed without user confirmation. Empty array means all tool calls require confirmation.
103 | 
104 | ## Available Tools
105 | 
106 | ### generate_image
107 | 
108 | Generates images using the Flux model based on text prompts.
109 | 
110 | ![image](https://github.com/user-attachments/assets/766921ce-ca8e-4d68-866d-8c7b55b2e09d)
111 | 
112 | ![out-0 (1)](https://github.com/user-attachments/assets/83549b2e-525a-4ff9-825c-83ba74459575)
113 | 
114 | #### Parameters
115 | 
116 | - `prompt` (required): Text description of the image to generate
117 | - `seed` (optional): Random seed for reproducible generation
118 | - `aspect_ratio` (optional): Image aspect ratio (default: "1:1")
119 | - `output_format` (optional): Output format - "webp", "jpg", or "png" (default: "webp")
120 | - `num_outputs` (optional): Number of images to generate (1-4, default: 1)
121 | 
122 | #### Example Usage
123 | 
124 | ```typescript
125 | const result = await use_mcp_tool({
126 |   server_name: "image-gen",
127 |   tool_name: "generate_image",
128 |   arguments: {
129 |     prompt: "A beautiful sunset over mountains",
130 |     aspect_ratio: "16:9",
131 |     output_format: "png",
132 |     num_outputs: 1
133 |   }
134 | });
135 | ```
136 | 
137 | The tool returns an array of URLs to the generated images.
138 | 
139 | ## 📜 License
140 | 
141 | This project is licensed under the MIT License.
142 | 
```

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

```json
 1 | {
 2 |   "compilerOptions": {
 3 |     "target": "ES2020",
 4 |     "module": "ES2020",
 5 |     "moduleResolution": "node",
 6 |     "esModuleInterop": true,
 7 |     "strict": true,
 8 |     "outDir": "build",
 9 |     "skipLibCheck": true,
10 |     "forceConsistentCasingInFileNames": true
11 |   },
12 |   "include": ["src/**/*"],
13 |   "exclude": ["node_modules"]
14 | }
15 | 
```

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

```dockerfile
 1 | # Generated by https://smithery.ai. See: https://smithery.ai/docs/config#dockerfile
 2 | FROM node:lts-alpine AS builder
 3 | 
 4 | WORKDIR /app
 5 | 
 6 | # Copy dependency definitions
 7 | COPY package.json package-lock.json ./
 8 | 
 9 | # Install dependencies, including production and dev
10 | RUN npm install
11 | 
12 | # Copy source files and configuration
13 | COPY tsconfig.json ./
14 | COPY src ./src
15 | 
16 | # Build the project
17 | RUN npm run build
18 | 
19 | FROM node:lts-alpine
20 | 
21 | WORKDIR /app
22 | 
23 | # Copy built files and node_modules from builder stage
24 | COPY --from=builder /app/package.json ./
25 | COPY --from=builder /app/build ./build
26 | COPY --from=builder /app/node_modules ./node_modules
27 | 
28 | EXPOSE 3000
29 | 
30 | CMD ["node", "build/index.js"]
31 | 
```

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

```json
 1 | {
 2 |   "name": "@gongrzhe/image-gen-server",
 3 |   "version": "1.0.1",
 4 |   "type": "module",
 5 |   "main": "build/index.js",
 6 |   "scripts": {
 7 |     "build": "tsc",
 8 |     "start": "node build/index.js",
 9 |     "prepublishOnly": "npm run build"
10 |   },
11 |   "keywords": [],
12 |   "author": "GongRzhe",
13 |   "license": "MIT",
14 |   "description": "An MCP server for image generation using the Replicate Flux model",
15 |   "dependencies": {
16 |     "@modelcontextprotocol/sdk": "^1.5.0",
17 |     "@types/node": "^22.13.5",
18 |     "axios": "^1.7.9",
19 |     "typescript": "^5.7.3"
20 |   },
21 |   "repository": {
22 |     "type": "git",
23 |     "url": "git+https://github.com/GongRzhe/image-gen-server.git"
24 |   },
25 |   "bugs": {
26 |     "url": "https://github.com/GongRzhe/image-gen-server/issues"
27 |   },
28 |   "homepage": "https://github.com/GongRzhe/image-gen-server#readme",
29 |   "bin": {
30 |     "image-gen-server": "build/index.js"
31 |   },
32 |   "files": [
33 |     "build/**/*"
34 |   ]
35 | }
36 | 
```

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

```yaml
 1 | # Smithery configuration file: https://smithery.ai/docs/config#smitheryyaml
 2 | 
 3 | startCommand:
 4 |   type: stdio
 5 |   configSchema:
 6 |     # JSON Schema defining the configuration options for the MCP.
 7 |     type: object
 8 |     required:
 9 |       - replicateApiToken
10 |     properties:
11 |       replicateApiToken:
12 |         type: string
13 |         description: Replicate API token for authentication
14 |       model:
15 |         type: string
16 |         default: black-forest-labs/flux-schnell
17 |         description: Replicate model to use for image generation
18 |   commandFunction:
19 |     # A JS function that produces the CLI command based on the given config to start the MCP on stdio.
20 |     |-
21 |     (config) => ({
22 |       command: 'node',
23 |       args: ['build/index.js'],
24 |       env: {
25 |         REPLICATE_API_TOKEN: config.replicateApiToken,
26 |         MODEL: config.model
27 |       }
28 |     })
29 |   exampleConfig:
30 |     replicateApiToken: example-token-1234
31 |     model: alternative-model-name
32 | 
```

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

```typescript
  1 | #!/usr/bin/env node
  2 | import { Server } from '@modelcontextprotocol/sdk/server/index.js';
  3 | import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
  4 | import {
  5 |   CallToolRequestSchema,
  6 |   ErrorCode,
  7 |   ListToolsRequestSchema,
  8 |   McpError,
  9 | } from '@modelcontextprotocol/sdk/types.js';
 10 | import axios from 'axios';
 11 | 
 12 | const REPLICATE_API_TOKEN = process.env.REPLICATE_API_TOKEN;
 13 | if (!REPLICATE_API_TOKEN) {
 14 |   throw new Error('REPLICATE_API_TOKEN environment variable is required');
 15 | }
 16 | 
 17 | interface FluxInput {
 18 |   prompt: string;
 19 |   seed?: number;
 20 |   go_fast?: boolean;
 21 |   megapixels?: '1' | '0.25';
 22 |   num_outputs?: number;
 23 |   aspect_ratio?: '1:1' | '16:9' | '21:9' | '3:2' | '2:3' | '4:5' | '5:4' | '3:4' | '4:3' | '9:16' | '9:21';
 24 |   output_format?: 'webp' | 'jpg' | 'png';
 25 |   output_quality?: number;
 26 |   num_inference_steps?: number;
 27 |   disable_safety_checker?: boolean;
 28 | }
 29 | 
 30 | class ImageGenerationServer {
 31 |   private server: Server;
 32 |   private axiosInstance;
 33 |   private readonly MODEL = process.env.MODEL || 'black-forest-labs/flux-schnell';
 34 | 
 35 |   constructor() {
 36 |     this.server = new Server(
 37 |       {
 38 |         name: 'image-generation-server',
 39 |         version: '0.1.0',
 40 |       },
 41 |       {
 42 |         capabilities: {
 43 |           tools: {},
 44 |         },
 45 |       }
 46 |     );
 47 | 
 48 |     this.axiosInstance = axios.create({
 49 |       baseURL: 'https://api.replicate.com/v1',
 50 |       headers: {
 51 |         'Authorization': `Token ${REPLICATE_API_TOKEN}`,
 52 |         'Content-Type': 'application/json',
 53 |       },
 54 |     });
 55 | 
 56 |     this.setupToolHandlers();
 57 |     
 58 |     // Error handling
 59 |     this.server.onerror = (error) => console.error('[MCP Error]', error);
 60 |     process.on('SIGINT', async () => {
 61 |       await this.server.close();
 62 |       process.exit(0);
 63 |     });
 64 |   }
 65 | 
 66 |   private setupToolHandlers() {
 67 |     this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
 68 |       tools: [
 69 |         {
 70 |           name: 'generate_image',
 71 |           description: 'Generate an image using the Flux model',
 72 |           inputSchema: {
 73 |             type: 'object',
 74 |             properties: {
 75 |               prompt: {
 76 |                 type: 'string',
 77 |                 description: 'Prompt for generated image',
 78 |               },
 79 |               seed: {
 80 |                 type: 'integer',
 81 |                 description: 'Random seed for reproducible generation',
 82 |               },
 83 |               aspect_ratio: {
 84 |                 type: 'string',
 85 |                 enum: ['1:1', '16:9', '21:9', '3:2', '2:3', '4:5', '5:4', '3:4', '4:3', '9:16', '9:21'],
 86 |                 description: 'Aspect ratio for the generated image',
 87 |                 default: '1:1',
 88 |               },
 89 |               output_format: {
 90 |                 type: 'string',
 91 |                 enum: ['webp', 'jpg', 'png'],
 92 |                 description: 'Format of the output images',
 93 |                 default: 'webp',
 94 |               },
 95 |               num_outputs: {
 96 |                 type: 'integer',
 97 |                 description: 'Number of outputs to generate (1-4)',
 98 |                 default: 1,
 99 |                 minimum: 1,
100 |                 maximum: 4,
101 |               },
102 |             },
103 |             required: ['prompt'],
104 |           },
105 |         },
106 |       ],
107 |     }));
108 | 
109 |     this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
110 |       if (request.params.name !== 'generate_image') {
111 |         throw new McpError(
112 |           ErrorCode.MethodNotFound,
113 |           `Unknown tool: ${request.params.name}`
114 |         );
115 |       }
116 | 
117 |       // Validate input arguments
118 |       if (!request.params.arguments || typeof request.params.arguments !== 'object') {
119 |         throw new McpError(
120 |           ErrorCode.InvalidParams,
121 |           'Arguments must be an object'
122 |         );
123 |       }
124 | 
125 |       if (!('prompt' in request.params.arguments) || typeof request.params.arguments.prompt !== 'string') {
126 |         throw new McpError(
127 |           ErrorCode.InvalidParams,
128 |           'Prompt is required and must be a string'
129 |         );
130 |       }
131 | 
132 |       const input: FluxInput = {
133 |         prompt: request.params.arguments.prompt,
134 |       };
135 | 
136 |       // Add optional parameters if they exist and are valid
137 |       if ('seed' in request.params.arguments && typeof request.params.arguments.seed === 'number') {
138 |         input.seed = request.params.arguments.seed;
139 |       }
140 |       if ('aspect_ratio' in request.params.arguments && typeof request.params.arguments.aspect_ratio === 'string') {
141 |         input.aspect_ratio = request.params.arguments.aspect_ratio as FluxInput['aspect_ratio'];
142 |       }
143 |       if ('output_format' in request.params.arguments && typeof request.params.arguments.output_format === 'string') {
144 |         input.output_format = request.params.arguments.output_format as FluxInput['output_format'];
145 |       }
146 |       if ('num_outputs' in request.params.arguments && typeof request.params.arguments.num_outputs === 'number') {
147 |         input.num_outputs = Math.min(Math.max(1, request.params.arguments.num_outputs), 4);
148 |       }
149 | 
150 |       try {
151 |         // Create prediction
152 |         const createResponse = await this.axiosInstance.post('/predictions', {
153 |           version: this.MODEL,
154 |           input,
155 |         });
156 | 
157 |         const predictionId = createResponse.data.id;
158 | 
159 |         // Poll for completion
160 |         while (true) {
161 |           const getResponse = await this.axiosInstance.get(`/predictions/${predictionId}`);
162 |           const prediction = getResponse.data;
163 | 
164 |           if (prediction.status === 'succeeded') {
165 |             return {
166 |               content: [
167 |                 {
168 |                   type: 'text',
169 |                   text: JSON.stringify(prediction.output),
170 |                 },
171 |               ],
172 |             };
173 |           } else if (prediction.status === 'failed') {
174 |             throw new McpError(
175 |               ErrorCode.InternalError,
176 |               `Image generation failed: ${prediction.error || 'Unknown error'}`
177 |             );
178 |           }
179 | 
180 |           // Wait before polling again
181 |           await new Promise(resolve => setTimeout(resolve, 1000));
182 |         }
183 |       } catch (error) {
184 |         if (axios.isAxiosError(error)) {
185 |           throw new McpError(
186 |             ErrorCode.InternalError,
187 |             `Replicate API error: ${error.response?.data?.detail || error.message}`
188 |           );
189 |         }
190 |         throw error;
191 |       }
192 |     });
193 |   }
194 | 
195 |   async run() {
196 |     const transport = new StdioServerTransport();
197 |     await this.server.connect(transport);
198 |     console.error('Image Generation MCP server running on stdio');
199 |   }
200 | }
201 | 
202 | const server = new ImageGenerationServer();
203 | server.run().catch(console.error);
204 | 
```