Skip to main content
Glama

imagerouter-mcp

An MCP server and a local dashboard for ImageRouter. Generate and edit images, generate videos, pick a model and check your balance from Claude Code, Claude Desktop or any stdio MCP client. Results are saved to disk and the tools return the file path. Requires Bun 1.2 or newer.

Quick start

Create an API key at https://imagerouter.io/api-keys, then register the server.

Claude Code:

claude mcp add imagerouter --env IMAGEROUTER_API_KEY=your-key -- bunx @chronova/imagerouter-mcp

Claude Desktop or any client that takes a JSON config:

{
  "mcpServers": {
    "imagerouter": {
      "command": "bunx",
      "args": ["@chronova/imagerouter-mcp"],
      "env": {
        "IMAGEROUTER_API_KEY": "your-key",
        "IMAGEROUTER_DEFAULT_IMAGE_MODEL": "black-forest-labs/FLUX-1-schnell:free"
      }
    }
  }
}

Desktop apps may not have Bun on their PATH; if the server does not start, use the absolute path to bunx (often /home/you/.bun/bin/bunx) as command.

Without a key the server still starts and list_models works; the other tools return an UNAUTHORIZED error that names IMAGEROUTER_API_KEY.

Updating

bunx keeps using the version it downloaded first, so a new release does not reach you on its own. Run the newest release once with the @latest tag, which also refreshes the cached copy:

bunx @chronova/imagerouter-mcp@latest --version

To always start the newest release, put @chronova/imagerouter-mcp@latest in the commands above instead; bunx then checks the registry on every start.

From source

git clone https://github.com/nx-solutions-ug/imagerouter-mcp.git
cd imagerouter-mcp
bun install
bun run build

Then use bun /path/to/imagerouter-mcp/dist/cli.js wherever the examples above say bunx @chronova/imagerouter-mcp, for example:

claude mcp add imagerouter --env IMAGEROUTER_API_KEY=your-key -- bun /path/to/imagerouter-mcp/dist/cli.js

Related MCP server: mclans-image-mcp

Tools

Tool

What it does

generate_image

Generate an image from a text prompt and save it.

edit_image

Edit images (image-to-image, mask inpainting, background removal) and save.

generate_video

Generate a video from a prompt, from images, or both, and save it.

list_models

List models with capabilities and lowest price in USD. Works without a key.

get_credits

Show the account balance in USD.

Every generation tool resolves its model as: the model argument, then IMAGEROUTER_DEFAULT_IMAGE_MODEL / IMAGEROUTER_DEFAULT_VIDEO_MODEL, otherwise it fails with a message telling you to pass one. edit_image uses the image default. Use list_models to find a model; there are about 200, so filter.

Failures come back as an error result such as INSUFFICIENT_CREDITS: ..., never as a crash. The codes are INVALID_REQUEST, UNAUTHORIZED, INSUFFICIENT_CREDITS, NOT_FOUND, RATE_LIMITED, SERVER_ERROR, CONNECTION_ERROR, TIMEOUT, API_ERROR and LOCAL_ERROR.

Two cases to know about:

  • A TIMEOUT or CONNECTION_ERROR on a generation call warns that the request may still complete and be billed. Check get_credits before retrying.

  • If a generation succeeded but downloading or saving the result failed, the error lists the hosted URLs (kept for 30 days) and any files already saved, so nothing you paid for is lost.

Saving arguments (all three generation tools)

Argument

Meaning

output_dir

Directory to save into. Defaults to IMAGEROUTER_OUTPUT_DIR.

filename

File name without directory. The extension is set from the result.

ephemeral

true: ImageRouter does not store the result and no URL is returned, only the file.

Without filename files are named <yyyyMMdd-HHmmss>-<prompt slug>-<4 hex>.<ext>. Existing files are never overwritten; a numeric suffix is added. The extension comes from the file's own signature when it is recognised, then the download's content type, then the URL, then output_format. A type that cannot be identified is saved as .bin.

generate_image

Arguments: prompt (required, up to 20000 characters), model, size (auto or WIDTHxHEIGHT), quality (auto|low|medium|high), output_format (webp|jpeg|png), plus the saving arguments.

{
  "path": "/home/you/Pictures/imagerouter/20261007-140509-a-fox-in-snow-3f9a.webp",
  "url": "https://storage.imagerouter.io/....webp",
  "model": "black-forest-labs/FLUX-1-schnell:free",
  "cost": 0,
  "latency_ms": 2140,
  "width": 1024,
  "height": 1024,
  "metadata_path": "/home/you/Pictures/imagerouter/20261007-140509-a-fox-in-snow-3f9a.webp.json"
}

width and height are the actual pixels, read from the saved file (omitted for video and formats that are not recognised). Every saved file also gets a metadata file next to it; metadata_path names the one of the first file and is omitted if it could not be written. In a files array each entry carries its own width, height and metadata_path.

edit_image

Arguments: images (required, 1 to 16: local paths, http(s) URLs or data URIs), prompt (optional; some models such as background removal take none), masks (optional, same forms, for models with mask support), model, size, quality, output_format, plus the saving arguments. Use list_models with supports_edit to find a model that can edit. The result has the same shape as generate_image.

generate_video

Arguments: prompt, images (start images for image-to-video, up to 16; at least one of prompt or images is required), model, size, seconds (auto or 1 to 60; accepted values depend on the model), plus the saving arguments. Video can take several minutes; if the client sent a progress token the server reports progress every 15 seconds. The result has the same shape as generate_image. When a call returns several files, path and url point at the first and a files array lists all of them.

list_models

Arguments: output (image|video), supports_edit, supports_mask, free_only, search (case-insensitive substring of the id), limit (1 to 300, default 50). Newest models come first.

{
  "total": 41,
  "returned": 1,
  "models": [
    {
      "id": "black-forest-labs/FLUX-1-schnell:free",
      "output": "image",
      "text": true,
      "edit": false,
      "mask": false,
      "quality": false,
      "min_price": 0,
      "release_date": "2024-08-01"
    }
  ]
}

min_price is the lowest price in USD across providers, or null when unknown. sizes and seconds appear when the model restricts them.

get_credits

No arguments.

{
  "remaining_credits": 4.82,
  "credit_usage": 0.18,
  "total_deposits": 5
}

Dashboard

IMAGEROUTER_API_KEY=your-key bunx @chronova/imagerouter-mcp@latest dashboard

Starts a page on http://127.0.0.1:4477 and opens your browser. Options:

  • --port <n> or --port=<n>: port to use (default 4477, or IMAGEROUTER_DASHBOARD_PORT).

  • --no-open: do not open a browser.

Any other option is rejected. The dashboard shows your balance, a form to generate, the result with its cost, latency, path and URL, and a gallery of the images and videos saved in the output directory (files of unrecognised type, saved as .bin, are not shown).

The form has four modes:

Mode

Takes

Makes

Text → Image

a prompt

image

Image → Image

images, prompt optional

image

Text → Video

a prompt

video

Image → Video

images, prompt optional

video

The model picker (searchable, with prices and free models marked) lists only the models that can do the selected mode, as ImageRouter reports it. Images have size, quality and format; videos have size and seconds. A video can take several minutes, so keep the tab open.

Input images are added with Add images, by dropping them on the page or by pasting, or with Use as input in the details of a gallery image, which also switches a text mode to the matching image mode. Uploads are PNG, JPEG, WebP or GIF, at most 16 inputs, 10 MB each and 45 MB of uploads in total. They are sent to ImageRouter with the request and are not saved in the output directory.

The mode and, per mode, the model are remembered. When there is no remembered or configured model, or that model is hidden by the current filter or cannot do the mode, the picker selects the first visible free model so a first click never spends credits by accident; when the filter leaves no free model, it shows a disabled "Choose a model" entry and Generate stays blocked until you pick one. Your choice is only changed by you and by a successful generation, so clearing the filter brings it back. IMAGEROUTER_DEFAULT_IMAGE_MODEL is the configured model of the image modes, IMAGEROUTER_DEFAULT_VIDEO_MODEL of the video modes.

Files that have a metadata file show their model and pixel size under the thumbnail, with the prompt as tooltip; a video is marked "Video". Click a file for its details: prompt, model, requested size and actual pixels, quality, format, seconds, cost, latency, creation time and file name, with buttons to copy the prompt, the path and the hosted URL. A video plays there. The search box above the gallery filters by prompt, model or file name, and "Spent $X.XX on N files" next to the count sums the recorded costs of all N matching files (not only the tiles shown), counting a multi-result request once.

Use these settings loads the prompt, model, size, quality and format of a text → image record into the form and switches to that mode. It never submits; if the recorded model is no longer offered, the other fields are still loaded and you are told. Fields the record lacks, or values the model does not offer, are set to neutral defaults (empty prompt, auto, auto, webp). It is not offered for edits or videos, whose input images cannot be restored. Files without a metadata file (for example from before that feature) still show, without details.

Masks are available through the edit_image tool only.

It listens on 127.0.0.1 only and answers only requests addressed to localhost or 127.0.0.1 on its own port. Cross-site POSTs are refused and responses carry security headers. Your API key stays in the server process; the browser never sees it. The browser can hand over image bytes and the name of a file in the output directory, never a path.

Configuration

Variable

Default

Purpose

IMAGEROUTER_API_KEY

none

Required for everything except listing models

IMAGEROUTER_BASE_URL

https://api.imagerouter.io

Override for testing

IMAGEROUTER_OUTPUT_DIR

~/Pictures/imagerouter

Where results are saved

IMAGEROUTER_DEFAULT_IMAGE_MODEL

none

Used when a call omits model

IMAGEROUTER_DEFAULT_VIDEO_MODEL

none

Same, for video

IMAGEROUTER_IMAGE_TIMEOUT_MS

180000

Request timeout, image calls

IMAGEROUTER_VIDEO_TIMEOUT_MS

900000

Request timeout, video calls

IMAGEROUTER_DASHBOARD_PORT

4477

Dashboard port (--port overrides)

Where files go and what is public

Results are saved to ~/Pictures/imagerouter unless IMAGEROUTER_OUTPUT_DIR or the output_dir argument says otherwise. Unless you pass ephemeral: true, ImageRouter also stores each result for 30 days at a hosted URL that anyone holding the link can open. Use ephemeral: true when the content must not be stored on ImageRouter; you then get only the local file and no URL, and the result cannot be fetched again if saving fails.

Next to every saved file X the server writes X.json (for example fox.jpg.json) with the prompt, model, requested size, quality and format, the actual pixel size, byte size, cost and latency of the request, the hosted URL, whether it was ephemeral, the input images and masks you passed (a data URI is stored as the literal data-uri, never its content), the creation time and, for a request that returned several files, the index and count. Each file of such a request carries the same cost, the cost of the whole request. The prompt is stored in plain text in the output directory, also for ephemeral requests, which only skip ImageRouter's storage; do not put a prompt there that you would not leave on disk. The metadata file is best-effort: if it cannot be written the generation still succeeds and metadata_path is left out. Delete the .json to forget a record; the sidecar file itself is not served by the dashboard and not shown as an image (its contents are returned by /api/images).

Development

bun install
bun run test        # unit and integration tests, no network
bun run test:live   # smoke test against the real API, needs IMAGEROUTER_API_KEY
bun run build       # bundle into dist/
bun run dashboard   # build, then start the dashboard

bun run test:live is skipped without a key and uses only the free models test/test and ir/test-video, so it costs nothing. Before opening a pull request also run bun run type-check, bun run lint and bun run format:check. See CONTRIBUTING.md and AGENTS.md.

License

MIT, see LICENSE.

Related MCP Connectors

Related MCP Servers