openrouter-media
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@openrouter-mediagenerate a 4-second video of a cat surfing a wave"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
openrouter-media-mcp
A local MCP server, logical name openrouter-media, that exposes OpenRouter's
image generation, video generation, image-to-video, and model discovery to
local AI clients (Claude Code, OpenCode, OMP, Codex). Everything runs stdio,
local today; a remote transport is possible future work.
Architecture
Claude Desktop (not currently registered)
Claude Code ----\
OpenCode -----> wrapper (bin/openrouter-media-mcp) --> server.py --> OpenRouter API
OMP ----/ (loads the key, (FastMCP,
Codex ---/ execs server) stdio)Every client points at the same wrapper executable. The wrapper is the only place that touches the secret. The server never receives the key from a client config file.
Verified API cheat sheet
Source: https://openrouter.ai/docs/guides/overview/multimodal/video-generation
Purpose | Method and path | Notes |
Submit video |
| Fields: |
Video status |
| Status: |
Video download |
| |
Video model list |
| Video models do not appear in the plain |
Image, dedicated |
| Fields: |
Image, via chat |
| With |
Model discovery |
| Filter on |
Auth | Header |
Other notes: polling interval suggested by the docs is about 30 s; generation
takes 30 s to several minutes. Pricing is per video-second with resolution
tiers, see docs/models.md for current rates. Result
retention window is unconfirmed by OpenRouter; download promptly on
completed.
Tool surface
Tool | Purpose |
| Calls |
| Calls |
| Calls |
| Calls |
| Calls |
| Calls |
| Convenience: submit, then poll every 10 to 15 s with backoff. Accepts an optional |
Design rules:
No single tool call blocks past a client's tool timeout; the submit / status / download split keeps every call short.
No hardcoded default video model. The caller picks from
list_video_models; defaults when omitted are short and cheap (4 s, 720p).Path sandboxing: the server computes all output paths from
OPENROUTER_MEDIA_DIR, generates filenames itself (timestamp, model slug, short hash), and rejects absolute paths and..in any argument.Server hygiene: stderr-only logging (stdout is the MCP protocol channel); explicit httpx connect/read timeouts on every API call; a
failedjob surfaces the API's error text.
Setup
Prerequisites
Python and
uvinstalled.An OpenRouter API key. Create one dedicated to this MCP server, with a credit limit set in the dashboard as a cost backstop.
Install
git clone <this repo>
cd openrouter-media-mcp
uv syncProvide the API key
The wrapper (bin/openrouter-media-mcp) reads the key itself so no client
config ever holds it:
macOS Keychain (primary):
security add-generic-password -s OPENROUTER_MEDIA_KEY -a "$USER" -w "sk-or-...".envfallback: copy.env.exampleto.envin the repo root and fill inOPENROUTER_MEDIA_KEY..envis gitignored. Used only if the Keychain item above does not exist.
The wrapper execs the project's own venv interpreter
(.venv/bin/python server.py) by absolute path, so it works even under a
GUI client's minimal PATH (no dependency on uv or npx at runtime).
Environment variables
Variable | Purpose |
| The OpenRouter API key dedicated to this project. Provided by the wrapper (Keychain primary, |
| Where generated images and videos are written. Default: |
Output path safety
The server only writes inside the configured media dir, rejects absolute
paths and .. in tool arguments, and generates filenames itself.
Per-client registration
Server name openrouter-media, wrapper path
/absolute/path/to/openrouter-media-mcp/bin/openrouter-media-mcp in every
client below. Replace /absolute/path/to/openrouter-media-mcp with the real
path to your clone (run pwd inside the repo). No env block is needed in any
client config, because the wrapper loads the secret itself and resolves its
own repo root at run time.
Registrations are scoped project-local: Claude Code --scope local,
OpenCode project opencode.json, OMP project .omp/mcp.json, Codex project
.codex/config.toml. No user/global config is touched, so no other project
on your machine sees this server.
OpenCode, OMP, and Codex each read a project file that must contain an
absolute path, so those three are generated from committed .example
templates rather than committed directly:
for f in .codex/config.toml .omp/mcp.json .opencode/opencode.json; do
sed "s#/absolute/path/to/openrouter-media-mcp#$(pwd)#g" "${f}.example" > "$f"
doneRun that once after cloning, from the repo root. The generated files contain no secrets, only your own clone's path, which is why they stay gitignored.
Claude Code
claude mcp add --scope local --transport stdio openrouter-media -- /absolute/path/to/openrouter-media-mcp/bin/openrouter-media-mcp
claude mcp list
claude mcp get openrouter-medialocal scope is stored in ~/.claude.json under the project's path,
visible only in sessions opened in this repo. /mcp in a session shows
status and lists the 7 tools. Relevant env vars: MCP_TIMEOUT (server
startup, ms), MCP_TOOL_TIMEOUT (per tool call, ms).
Note: OMP imports Claude Code's user-scope entries only; a local-scope entry like this one does not propagate to OMP. Configure OMP via its own project file below.
OpenCode
Config lives in .opencode/opencode.json in the repo (not the documented
root opencode.json). Generated from the committed
.opencode/opencode.json.example template (see above).
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"openrouter-media": {
"type": "local",
"command": ["/absolute/path/to/openrouter-media-mcp/bin/openrouter-media-mcp"],
"enabled": true,
"timeout": 180000
}
}
}The server name sits directly under "mcp": there is no "servers" level.
Optional fields: cwd, environment, timeout (milliseconds; scopes tool
fetching, default 5000 ms).
opencode mcp list shows connection status; opencode mcp add,
opencode mcp auth, opencode mcp debug <name> are also available.
OMP (Oh My Pi)
Path: .omp/mcp.json in the repo (project scope, applies under every OMP
profile). The user-scope file ~/.omp/agent/mcp.json is deliberately not
used. Generated from the committed .omp/mcp.json.example template.
{
"$schema": "https://raw.githubusercontent.com/can1357/oh-my-pi/main/packages/coding-agent/src/config/mcp-schema.json",
"mcpServers": {
"openrouter-media": {
"type": "stdio",
"command": "/absolute/path/to/openrouter-media-mcp/bin/openrouter-media-mcp",
"timeout": 180000
}
}
}timeout is not optional here. OMP's default MCP request timeout is
30 s; a 120 s generate_video_and_wait call would be killed without this
field. The process-wide OMP_MCP_TIMEOUT_MS env var overrides per-server
values.
OMP also imports MCP definitions from other tools' user-scope files
(Claude Code, Codex, OpenCode, Cursor, Windsurf, VS Code, Gemini CLI).
Because this rollout registers nothing at user scope, nothing leaks into
OMP through discovery. In-app commands: /mcp list, /mcp add,
/mcp reload, /mcp test openrouter-media.
Codex CLI
Project file .codex/config.toml, generated from the committed
.codex/config.toml.example template. Do not touch the global
~/.codex/config.toml.
[mcp_servers.openrouter-media]
command = "/absolute/path/to/openrouter-media-mcp/bin/openrouter-media-mcp"codex mcp add openrouter-media -- /absolute/path/to/openrouter-media-mcp/bin/openrouter-media-mcpClaude Desktop
Not currently registered: Claude Desktop's config is app-global rather than
project-scoped, so it is out of scope for this project-local rollout. If you
want it anyway, add an openrouter-media entry under mcpServers in
~/Library/Application Support/Claude/claude_desktop_config.json pointing
at the same wrapper path, then restart Claude Desktop.
Security notes
Key handling. No client config contains the key; every client references only the wrapper's path. Only the wrapper touches the secret.
Key naming and source.
OPENROUTER_MEDIA_KEYis the reserved name for the OpenRouter API key dedicated to this project. Primary source: macOS Keychain viasecurity find-generic-password(no install needed). Fallback: the gitignored.envin the repo root, only if Keychain is unavailable. Shell-only exports (e.g..zshrc) are not sufficient for GUI apps such as Claude Desktop, which do not inherit shell environment.Dedicated key. Create one OpenRouter API key for this MCP with a credit limit set in the dashboard as the cost backstop.
Residual exposure. The wrapper exports the key into the server process environment, where the same user can read it via
ps -E. Acceptable for a single-user machine; if that assumption changes, move the key read inside the server, per call.Never commit secrets.
.gitignorecovers.env,media/, and.venv/from the first commit.Path sandboxing. See "Output path safety" above.
Pricing
Video is billed per video-second, with resolution tiers, and can range from cents to several dollars per clip depending on model, duration, and resolution. Defaults are short and cheap (4 s, 720p); opt into a specific model and duration for anything larger. Set a credit limit on the dedicated key in the OpenRouter dashboard as a backstop. See docs/models.md for current per-model rates.
Troubleshooting
Symptom | Likely cause |
Claude Desktop can't find the key | GUI apps do not inherit |
Server fails to start only from a GUI client | A PATH-dependent binary inside the wrapper ( |
One-time Keychain prompt on first GUI use | Expected Keychain ACL behavior. Choose "Always Allow" once, re-test. |
An OMP tool call dies after ~30 s | OMP's default MCP request timeout. Set |
A video tool call times out client-side | Long single-call polling. Use the |
A video model does not show up in model lists | Video models are not in |
| OpenRouter's result retention window is unconfirmed. Download promptly; |
OpenCode config seems to be ignored | Wrong nesting: the server name goes directly under |
Codex does not pick up the config | Confirm the project |
Documentation
docs/models.md: current image and video model list and pricing.
docs/design.md: design notes and rationale behind the architecture and client-registration approach.
This server cannot be deployed
Maintenance
Related MCP Connectors
LLM chat, text tools, image generation, editing, batch image jobs, and asynchronous video generation
The OpenRouter MCP server plugs OpenRouter into the AI tools you already use. Once connected, your assistant can pull live OpenRouter data (models, prices, your credits, rankings, and docs) and send quick test messages, all without leaving your editor.
Generate images, video, music and voice from your CLI or AI agent. On-brand AI media toolkit.
Multi-model AI image and video generator. 14 models behind one OAuth-secured MCP endpoint.