# 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 | 
3 |
4 | [](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 | 
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 | 
111 |
112 | 
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 |
```