Openrouter
FreeNot checkedMCP stdio server and CLI for OpenRouter: model discovery, image generation/editing, and image description
About
MCP stdio server and CLI for OpenRouter: model discovery, image generation/editing, and image description
README
License: MIT OR Apache-2.0 Release MCPB MSRV
MCP (stdio) server and CLI for OpenRouter, in a
single Rust binary. Discover models, generate and edit images (with parallel
variants and a sidecar manifest), describe images with a vision model, and track
per-process usage - all behind one openrouter-mcp executable.
Features
- Model discovery -
list_modelswith server-side filters (modality, supported params, sort, min context), local search, and pricing;describe_modelreturns full detail for one model id (architecture, context, benchmarks, and per-provider endpoints with pricing - including realpricing_skusfor video). - Image generation -
generate_image: text-to-image, image editing / image-to-image (multiple local inputs), and parallel variants (seed-stepped).- Input images may be PNG, JPEG, WebP, GIF, or SVG. SVG inputs are rasterized to PNG (longest side scaled to the dimension cap; transparency preserved). Text in SVGs is not rendered (no fonts are loaded) and is flagged as a warning.
- The output format is chosen by the provider: PNG/JPEG/WebP/GIF are
sniffed from the response bytes; SVG is taken from the provider's declared
media type instead (sniffing can't detect it). Either way the file
extension is set to match what actually came back. An
output_formatrequest hint is passed through, but support varies by model. - Requested
aspect_ratio/image_sizeare verified against the actual decoded pixels; mismatches are surfaced as warnings. - Every job writes a
*.manifest.jsonsidecar (full settings, per-input and per-variant metadata, cost, provider, timing). - Asynchronous: if a job runs longer than
wait_seconds(default 10) the tool returns atask_id; pollget_resultfor completion.
- Video generation -
generate_video: text-to-video and image-to-video (first/last frame and reference images) with an OpenRouter video model. Asynchronous: if the job runs longer thanwait_seconds(default 20, video usually needs it) the tool returns atask_id; pollget_resultfor completion. Once done, the clip is downloaded and saved to disk (a local path, plus afile://resource link when inline previews are enabled for sandboxed clients), not just the hosted URL.with_audio(renamed fromgenerate_audioin 0.6.0) controls the clip's audio track; if a provider ignores it, the result carries a warning andhas_audioreports the file's real state. - Speech generation -
generate_audio: text-to-speech with an OpenRouter TTS model (voice/format/speed); saves the audio to disk with a manifest. - Transcription -
transcribe_audio: speech-to-text with an OpenRouter STT model; audio by localpathor inlinebase64, optional language hint. - Image description -
describe_image: image -> detailed text via any vision-capable model (image input, text output). - Chat completion -
chat_completion: send a prompt to any OpenRouter chat/text model and get its text reply - route a sub-task to a different model (optionalsystem,temperature,max_tokens). Optionally attachimages(path/url/base64) for a vision-capable model; the call is rejected only when the model is known not to accept image input (otherwise it is sent as-is). - Reasoning effort -
chat_completionanddescribe_imagetake an optionalreasoning_effort:max,xhigh,high,medium,low,minimalornone. It is omitted from the request unless you set it, so each model keeps its catalogdefault_effort(seereasoning.supported_effortsinlist_models). Reasoning tokens bill as output tokens, sononeis the cheapest and fastest setting on models that allow it. Some models make reasoning mandatory and rejectnonewith a 400. - Account info -
get_account: basic info about the API key in use (label, owning user id, credit usage with daily/weekly/monthly breakdown, spending limit / remaining balance, and tier / key-type flags). - Usage stats -
get_usage_stats(read-only) andreset_usage_stats(destructive, requiresconfirm: true): per-process request/cost counters with a by-model breakdown.
Add to Claude Desktop (one-click)
This server ships as a Claude Desktop extension (.mcpb) for macOS,
Windows, and Linux - no terminal or Rust toolchain required.
- Download the bundle for your platform from the
latest release:
openrouter-mcp-macos.mcpb,openrouter-mcp-windows.mcpb, oropenrouter-mcp-linux.mcpb. - Double-click it (or drag it into Claude Desktop -> Settings -> Extensions).
- Click Install, paste your OpenRouter API key, and enable it.
Your API key is stored by Claude Desktop (the OS keychain/credential store) and
injected into the server as OPENROUTER_API_KEY. See Privacy Policy.
To build the bundle yourself, run the cross-platform generator on the target platform:
node scripts/build-mcpb.mjs # -> dist/openrouter-mcp-<os>.mcpb
Per-platform specifics, all handled by the generator: macOS produces a universal
arm64+x86_64 binary (via lipo); Linux builds a static x86_64-unknown-linux-musl
binary so the bundle runs on any distro regardless of the host's glibc version;
Windows statically links the CRT so it starts on a fresh install with no Visual
C++ Redistributable. TLS is pure-Rust rustls
trusting the OS certificate store, so no system OpenSSL is needed to build any
target and custom/corporate root CAs installed on the machine still work.
Connect another client (CLI, IDE, agent)
openrouter-mcp is a universal local stdio MCP server. CONNECT.md
has copy-paste setup for Claude Code, Codex CLI, Gemini CLI, Antigravity, Cursor,
Windsurf, VS Code (Copilot), Zed, Cline, Roo Code, Continue, Goose, opencode,
Crush, Amp, OpenHands, and more.
Install (CLI / other MCP clients)
One-click install into a supported IDE (both wire up openrouter-mcp mcp over
stdio - replace the placeholder sk-or-v1-YOUR_KEY with your real key after):
Add to Cursor Install in VS Code
Both require openrouter-mcp to be on your PATH (install it below first).
From a local checkout:
cargo install --path . --locked --force
From crates.io:
cargo install openrouter-mcp
Configuration
Set an OpenRouter API key:
export OPENROUTER_API_KEY="sk-or-v1-..."
On PowerShell:
$env:OPENROUTER_API_KEY = "sk-or-v1-..."
A local .env file is also loaded if present (real env vars take precedence):
OPENROUTER_API_KEY=sk-or-v1-...
Do not commit .env.
All environment variables read by the server/CLI:
| Variable | Purpose | Default |
|---|---|---|
OPENROUTER_API_KEY |
OpenRouter API key. The only required variable; every API-backed call errors without it. May also be supplied via .env. |
(none - required) |
OPENROUTER_MCP_IMAGE_PREVIEWS |
Whether generate_image/generate_video/generate_audio (and get_result) embed inline previews - base64 image previews, video file:// resource links, and inline audio blocks: always, never, or auto. |
auto (inline for all clients except claude-code) |
OPENROUTER_MCP_OUTPUT_DIR |
Base directory for auto-named output artifacts (images/video/audio + manifests). | $HOME/Downloads/openrouter-mcp (system temp dir if HOME unset) |
OPENROUTER_IMAGE_MAX_DIMENSION |
Longest-side pixel cap for normalized input images before sending. Clamped to a hard ceiling of 4096; larger values are reduced to 4096. |
1536 |
OPENROUTER_VIDEO_POLL_INTERVAL |
Polling interval (seconds) for the video generation status loop. | 5 |
OPENROUTER_VIDEO_POLL_TIMEOUT |
Ceiling (seconds) on the video generation poll loop. | 600 |
OPENROUTER_HTTP_REFERER |
Overrides the HTTP-Referer app-attribution header (OpenRouter rankings only; no effect on responses). |
https://github.com/thesimj/rust-openrouter-mcp |
OPENROUTER_X_TITLE |
Overrides the X-Title app-attribution header. |
rust-openrouter-mcp |
HOME |
OS variable; only used to derive the default output directory when OPENROUTER_MCP_OUTPUT_DIR is unset. Only HOME is checked, not USERPROFILE - a stock Windows install without HOME set falls straight to the system temp dir. |
(OS-provided) |
A few of these warrant extra detail.
OPENROUTER_MCP_IMAGE_PREVIEWS controls whether generate_image,
generate_video, generate_audio, and get_result embed the generated
media inline in the tool result (base64 images, video file:// resource
links, or inline audio blocks), in addition to saving it to disk:
auto(default) - inline previews for every client except the localclaude-codeCLI, which shares the filesystem and can open the saved file directly.always- always embed previews. The Claude Desktop connector sets this, because Desktop runs the server in a sandboxed filesystem it can't read, so the saved path is unreachable and the image must come back inline.never- paths only, never inline bytes.
Inline previews are downscaled to a 1568px longest side; the full-resolution image is always the file saved on disk. At most 4 inline previews are embedded per job (remaining images are reported by path only in the JSON), and inline audio previews are capped at 4 MB (larger clips are saved to disk with the path returned instead).
MCP usage
The server speaks MCP over stdio (the mcp subcommand); it is local-only, with
no remote/HTTP transport.
Start the stdio server (mcp subcommand is implied when none is given):
openrouter-mcp # or: openrouter-mcp mcp
Example MCP client config:
{
"mcpServers": {
"openrouter": {
"command": "openrouter-mcp",
"env": { "OPENROUTER_API_KEY": "sk-or-v1-..." }
}
}
}
If the client already provides OPENROUTER_API_KEY in the environment, the env
block is optional.
MCP tools
| Tool | Kind | Description |
|---|---|---|
list_models |
read-only | List models with capabilities and pricing (server-side filters, local search; human-readable $X/M tokens pricing; tiered/time-window overrides are passed through raw and rendered in pricing_human when a model has them). |
describe_model |
read-only | Full detail for one model id: description, architecture, context, benchmarks, per-provider endpoints, (for video models) real pricing_skus, and (for image models) per-endpoint image capabilities merged under an image key. |
generate_image |
write | Generate or edit images via OpenRouter's dedicated /api/v1/images endpoint (works with any image model: Nano Banana, Grok, Seedream, FLUX, GPT Image, Recraft, ...); supports variants; async with task_id. Inputs by path/url/base64. Optional quality (auto/low/medium/high), output_format (png/jpeg/webp/svg), background (auto/transparent/opaque), and output_compression (0-100, webp/jpeg only) pass through to the provider. No defaults for model, prompt, aspect_ratio, image_size - all four are required by the schema, not just prose; output is optional (auto-named under OPENROUTER_MCP_OUTPUT_DIR). |
generate_video |
write | Text-to-video / image-to-video with an OpenRouter video model; async, poll by task_id. Required: model, prompt, duration, with_audio (renamed from generate_audio in 0.6.0). |
generate_audio |
write | Text-to-speech with an OpenRouter TTS model; saves audio to disk. |
transcribe_audio |
read-only | Speech-to-text via /api/v1/audio/transcriptions: audio by path or base64 (wav/mp3/flac/m4a/ogg/webm/aac, max 25 MB), optional ISO-639-1 language, response_format (json/verbose_json), timestamp_granularities (segment/word - verbose_json + OpenAI-compatible providers only), and temperature; returns the transcript. Find models with list_models + output_modalities="transcription". |
chat_completion |
write | Send a prompt to any OpenRouter chat/text model and return its text reply; route a sub-task to a different model. Optionally attach images for a vision model (best-effort gated on the model's declared image-input support). |
describe_image |
read-only | Describe image(s) - by path, url, or base64/data-URL - with a vision-capable model; returns text. |
get_result |
read-only | Fetch a job by task_id: pending / completed / failed. |
get_account |
read-only | Basic info about the API key in use: label, owning user id, credit usage (total + daily/weekly/monthly), limit/remaining, and tier/key-type flags. |
get_usage_stats |
read-only | In-memory request/cost counters (and server version) with a by-model breakdown. |
reset_usage_stats |
destructive | Reset all counters (confirm: true required). |
generate_image returns a lean result - saved paths, decoded width/height,
requested vs. actual aspect/size, seeds, and a pointer to the sidecar manifest;
the full per-variant detail lives in the manifest on disk.
CLI usage
The same binary is a CLI. Subcommands: models, image, video, audio,
transcribe, describe, chat, key, mcp.
Show info about the API key in use:
openrouter-mcp key
Send a prompt to a chat/text model:
openrouter-mcp chat --model openai/gpt-5.4 --prompt "Summarize MCP in one sentence."
openrouter-mcp chat -m anthropic/claude-sonnet-4.6 -s "Be terse." -p "Why Rust?" --temperature 0.3
Browse models:
openrouter-mcp models --query openai --sort newest --table
openrouter-mcp models --output-modalities image --sort newest --table
openrouter-mcp models --query openai --search codex
openrouter-mcp models --query claude --all
Generate an image:
openrouter-mcp image \
--model google/gemini-3.1-flash-image-preview \
--prompt "a photorealistic owl with one cybernetic eye, starry sky" \
--aspect-ratio 1:1 --image-size 1K --seed 1200 \
--output ./out/owl.png
Edit / image-to-image (repeatable --image, optional label=path):
openrouter-mcp image \
--model google/gemini-3.1-flash-image-preview \
--prompt "add a small wizard hat" \
--image ./out/owl.png \
--output ./out/owl-hat.png
Four parallel variants (files named *-var-<seed>.<ext> plus a manifest):
openrouter-mcp image -m bytedance-seed/seedream-4.5 \
--prompt "a cute pixar-style baby dragon" \
--aspect-ratio 1:1 --image-size 1K --seed 1490 --variants 4 \
--output ./out/dragon.png
Also accepts --quality, --output-format, --background, and
--output-compression (provider support varies; see --help).
Describe an image:
openrouter-mcp describe -m google/gemini-2.5-flash-lite --image ./out/owl.png
The image format the provider returns is not guaranteed; the CLI corrects the saved file's extension to match what actually came back.
Generate a video (blocks through submit + poll; text-to-video or
image-to-video via --first-frame / --last-frame):
openrouter-mcp video \
--model bytedance/seedance-2.0 \
--prompt "a paper boat drifting down a rain-soaked street, cinematic" \
--duration 8 --resolution 1080p --output ./out/boat.mp4
Generate speech (text-to-speech):
openrouter-mcp audio \
--model hexgrad/kokoro-82m --voice af_heart \
--input "Hello from OpenRouter." --output ./out/hello.mp3
Transcribe audio (speech-to-text):
openrouter-mcp transcribe \
--model openai/gpt-4o-mini-transcribe --file ./out/hello.mp3 --language en
Also accepts --response-format verbose_json (segment/word timestamps, duration,
detected language - OpenAI-compatible providers only), --timestamp-granularities segment,word, and --temperature.
Development
cargo fmt --check
cargo clippy --all-targets --all-features -- -D warnings
cargo test
cargo llvm-cov --summary-only # coverage (cargo install cargo-llvm-cov)
CI (.github/workflows/ci.yml) runs fmt --check, clippy -D warnings, and the
test suite on every push to main and every pull request, plus a separate
msrv job that runs cargo check --all-targets at the declared
rust-version floor; the release workflow only fires on a version tag, so
this is the gate that runs before anything ships.
Live smoke tests (require OPENROUTER_API_KEY):
cargo run -- models --query openai --sort newest --table
cargo run -- describe -m google/gemini-2.5-flash-lite --image ./some.png
Privacy Policy
openrouter-mcp runs entirely on your machine and collects no telemetry. Full
details, including the one third-party-URL-fetch exception (image url
inputs are fetched directly, not via OpenRouter) and where generated files
land (the path you specify, or an auto-named one under
OPENROUTER_MCP_OUTPUT_DIR / $HOME/Downloads/openrouter-mcp / the system
temp dir): PRIVACY.md.
License
Licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE)
- MIT license (LICENSE-MIT)
at your option.
Installing Openrouter
This server has no published package — it is built from source. Open the repository and follow its README.
▸ github.com/thesimj/rust-openrouter-mcpFAQ
Is Openrouter MCP free?
Yes, Openrouter MCP is free — one-click install via Unyly at no cost.
Does Openrouter need an API key?
No, Openrouter runs without API keys or environment variables.
Is Openrouter hosted or self-hosted?
Self-hosted: the server runs locally on your machine via the install command above.
How do I install Openrouter in Claude Desktop, Claude Code or Cursor?
Open Openrouter on unyly.org, pick your client tab (Claude Desktop, Claude Code, Cursor) and press Install — the config is generated automatically, no JSON editing.
Related MCPs
ARA
Generate images, video and audio from any AI agent — one connector.
by ARAOmni Video
An MCP server that transforms LLM-enabled IDEs into professional video editors by pre-processing footage into text proxies, generating motion graphics via HTML/
by buildwithtazaYouTube
Transcripts, channel stats, search
by YouTubeEverArt
AI image generation using various models.
by modelcontextprotocolgpu-bridge/mcp-server
Unified GPU inference API with 30 AI services (LLM, image gen, video, TTS, whisper, embeddings, reranking, OCR) as MCP tools. Pay-per-use via x402 USDC or API k
by gpu-bridgehamflx/imagen3-mcp
A powerful image generation tool using Google's Imagen 3.0 API through MCP. Generate high-quality images from text prompts with advanced photography, artistic,
by hamflxmerterbak/Grok-MCP
MCP server for xAI's [Grok API](https://docs.x.ai/docs/overview) with agentic tool calling, image generation, vision, and file support.
by merterbakSureScaleAI/openai-gpt-image-mcp
OpenAI GPT image generation/editing MCP server.
by SureScaleAIYangLiangwei/PersonalizationMCP
Comprehensive personal data aggregation MCP server with Steam, YouTube, Bilibili, Spotify, Reddit and other platforms integrations. Features OAuth2 authenticati
by YangLiangweiAceDataCloud/MCPFlux
Flux AI image generation and editing (Black Forest Labs) via Ace Data Cloud API.
by AceDataCloudCompare Openrouter with
Not sure what to pick?
Find your stack in 60 seconds
Author?
Embed badge for your README
Browse similar
All media MCPs
