Skip to main content
Glama
nguyen1oc

OpenRouter Custom Image Generation MCP Server

by nguyen1oc

šŸ–¼ļø MCP Image Generation Server for LibreChat

A custom Model Context Protocol (MCP) server that provides AI image generation capabilities to LibreChat via OpenRouter.

Model: Locked to google/gemini-2.5-flash-image for all requests. To change the model, modify the source code in tools.js.


šŸ“‚ Project Structure

mcp-image-gen-custom/
ā”œā”€ā”€ index.js          # Express app, SSE transport, MCP server + tool registration
ā”œā”€ā”€ tools.js          # Tool handlers: get_user_images, generate_image, rate limiting
ā”œā”€ā”€ openrouter.js     # OpenRouter API communication (chat completions with image modality)
ā”œā”€ā”€ files.js          # MongoDB file record lookup + local file stream reader
ā”œā”€ā”€ db.js             # MongoDB connection pool manager
ā”œā”€ā”€ Dockerfile        # Container build definition
ā”œā”€ā”€ package.json
└── example/
    ā”œā”€ā”€ docker-compose.override.example.yml   # Docker service config example
    ā”œā”€ā”€ librechat.example.yaml                # librechat.yaml MCP config example
    └── system_instructions.example.md        # Agent system prompt template

Related MCP server: OpenRouter Image MCP Server

šŸ› ļø Tools Provided

1. get_user_images

Retrieves images uploaded by the current user in LibreChat, returning index aliases and file_ids for use as reference images.

Argument

Type

Required

Description

limit

number

No

Max images to return. Default: 10

Example response:

Found 2 uploaded image(s):
1. [INDEX_1] file_id: "cab88c4e-aecb-4812-9fff-6c85aede6362" — mycar.png
2. [INDEX_2] file_id: "f6752381-3a6d-4b69-a92b-5555a9521069" — cat.png

Use EITHER the file_id OR the index number (e.g., '1', '2' or 'INDEX_1', 'INDEX_2') as the reference_image_url when calling generate_image.

2. generate_image

Generates an image from a text prompt. Supports Text-to-Image and Image-to-Image (editing) via reference images.

Argument

Type

Required

Description

prompt

string

āœ…

Text description of the image to generate

reference_image_url

string

No

Index alias ("1", "INDEX_1") or local file_id of a single reference image

reference_image_urls

string[]

No

List of index aliases or file_ids for multiple reference images

aspect_ratio

string

No

Output image dimensions. See options below

Aspect ratio options:

Value

Shape

Common use

1:1

Square

Profile pictures, feed posts

16:9

Wide landscape

Banners, cover photos

9:16

Tall portrait

Stories, Reels, TikTok

4:5

Portrait

Feed posts (portrait)

Note: aspect_ratio only controls image dimensions — it does not affect image style or content.

Note: Do NOT pass Google/OpenAI temporary file-xxxx IDs into reference_image_url. These are not stored in the local database. Always use get_user_images first to get valid index aliases or local file_ids.


šŸ”’ Per-User Rate Limiting

The server enforces configurable usage limits per user to prevent spam. Limits are tracked in MongoDB (mcp_image_gen_usage collection).

Env Variable

Default

Description

IMAGE_GEN_DAILY_LIMIT

3

Max images per user per day (reset at midnight local time)

IMAGE_GEN_COOLDOWN_SEC

30

Min seconds between generations per user

To reset limits manually (all users):

docker exec chat-mongodb mongosh LibreChat --eval "db.mcp_image_gen_usage.deleteMany({})"

To reset limits for a specific user:

docker exec chat-mongodb mongosh LibreChat --eval "db.mcp_image_gen_usage.deleteMany({ userId: ObjectId('<userId>') })"

To view current usage:

docker exec chat-mongodb mongosh LibreChat --eval "db.mcp_image_gen_usage.aggregate([{ \$group: { _id: '\$userId', count: { \$sum: 1 } } }]).forEach(r => print(r._id, '->', r.count))"

āš™ļø How Index Resolution Works

The LLM agent only sees image bytes in chat history — it does not know the database file_id. This server resolves short index aliases (e.g., "1" or "INDEX_1") to the correct local file_id automatically.

sequenceDiagram
    actor User
    participant Agent as LLM Agent
    participant MCP as MCP Server
    participant DB as MongoDB

    User->>Agent: "Edit this image" (uploads car.png)
    Agent->>MCP: get_user_images()
    MCP->>DB: Query user's latest images
    DB-->>MCP: [car.png → file_id: "abc-123"]
    MCP-->>Agent: "1. [INDEX_1] file_id: 'abc-123' — car.png"
    Agent->>MCP: generate_image(prompt="make it red", reference_image_url="INDEX_1")
    Note over MCP: Resolves "INDEX_1" → "abc-123"
    MCP->>DB: Fetch file "abc-123" from disk
    MCP-->>User: Returns edited image āœ…

šŸš€ Installation & Deployment

Prerequisites

  • LibreChat running via Docker Compose

  • An OpenRouter API key


Step 1: Place this folder

Clone or copy this mcp-image-gen-custom/ directory into the root of your LibreChat repository:

LibreChat/
ā”œā”€ā”€ mcp-image-gen-custom/   ← here
ā”œā”€ā”€ api/
ā”œā”€ā”€ docker-compose.yml
└── ...

Step 2: Configure Environment Variables

Add the following to your .env file at the LibreChat root:

# Required
OPENROUTER_KEY=your_openrouter_api_key_here

# Optional — image generation rate limits
IMAGE_GEN_DAILY_LIMIT=3
IMAGE_GEN_COOLDOWN_SEC=30

Step 3: Add the MCP service to Docker Compose

Add the following to your docker-compose.override.yml (create it if it doesn't exist):

services:
  api:
    volumes:
      - type: bind
        source: ./librechat.yaml
        target: /app/librechat.yaml

  mcp-image-gen:
    build: ./mcp-image-gen-custom
    restart: always
    environment:
      NODE_ENV: ${NODE_ENV:-production}
      PORT: 3013
      OPENROUTER_KEY: ${OPENROUTER_KEY}
      OPENROUTER_API_KEY: ${OPENROUTER_KEY}
      MONGO_URI: mongodb://mongodb:27017/LibreChat
      IMAGE_GEN_DAILY_LIMIT: ${IMAGE_GEN_DAILY_LIMIT:-3}
      IMAGE_GEN_COOLDOWN_SEC: ${IMAGE_GEN_COOLDOWN_SEC:-30}
    volumes:
      - ./uploads:/app/uploads   # shared with LibreChat api container
      - ./images:/app/images     # shared with LibreChat api container
    expose:
      - "3013"
    networks:
      - default

See example/docker-compose.override.example.yml for a complete example.


Step 4: Register the MCP server in librechat.yaml

Append the following to your librechat.yaml:

mcpSettings:
  allowedDomains:
    - 'mcp-image-gen'
  allowedAddresses:
    - 'mcp-image-gen:3013'

mcpServers:
  openrouter-imager:
    type: sse
    url: http://mcp-image-gen:3013/sse
    headers:
      x-user-id: '{{LIBRECHAT_USER_ID}}'

See example/librechat.example.yaml for a complete example.


Step 5: Build and start

# Build and start all services
docker compose up -d --build

# Restart the LibreChat API to reload librechat.yaml
docker compose restart api

Step 6: Configure the Agent in LibreChat UI

  1. Go to LibreChat → Agents and create a new agent (or edit an existing one).

  2. Enable the openrouter-imager MCP tool.

  3. Paste the system prompt from example/system_instructions.example.md into the Instructions field.


šŸ”§ Changing the Model

The model is hardcoded to google/gemini-2.5-flash-image in tools.js:

const selectedModel = "google/gemini-2.5-flash-image";

To use a different model, edit this line directly and rebuild the container:

docker compose up -d --build mcp-image-gen

šŸ“‹ Useful Commands

# View live MCP server logs
docker logs librechat-mcp-image-gen-1 -f

# Rebuild and restart MCP server only
docker compose up -d --build mcp-image-gen

# Reset all image generation usage limits
docker exec chat-mongodb mongosh LibreChat --eval "db.mcp_image_gen_usage.deleteMany({})"

Related MCP Connectors

Related MCP Servers