{"id":28264268,"url":"https://github.com/stabgan/openrouter-mcp-multimodal","last_synced_at":"2026-05-03T19:05:07.994Z","repository":{"id":284593211,"uuid":"955447940","full_name":"stabgan/openrouter-mcp-multimodal","owner":"stabgan","description":"MCP server for OpenRouter: 300+ LLMs with vision, image gen, audio in/out, and video analysis + generation (Veo 3.1 / Sora 2 Pro / Seedance / Wan). Structured errors, IPv6 SSRF guards, path sandbox.","archived":false,"fork":false,"pushed_at":"2026-05-03T16:36:45.000Z","size":1823,"stargazers_count":34,"open_issues_count":0,"forks_count":18,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-05-03T17:29:13.709Z","etag":null,"topics":["ai","audio-generation","audio-transcription","claude","docker","image-analysis","image-generation","llm","mcp","mcp-server","model-context-protocol","multimodal","nodejs","openrouter","seedance","sora","typescript","veo","video-generation","video-understanding"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/@stabgan/openrouter-mcp-multimodal","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/stabgan.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-03-26T16:49:03.000Z","updated_at":"2026-05-03T16:36:49.000Z","dependencies_parsed_at":"2025-05-20T21:02:36.825Z","dependency_job_id":null,"html_url":"https://github.com/stabgan/openrouter-mcp-multimodal","commit_stats":null,"previous_names":["stabgan/openrouter-mcp-multimodal"],"tags_count":19,"template":false,"template_full_name":null,"purl":"pkg:github/stabgan/openrouter-mcp-multimodal","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stabgan%2Fopenrouter-mcp-multimodal","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stabgan%2Fopenrouter-mcp-multimodal/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stabgan%2Fopenrouter-mcp-multimodal/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stabgan%2Fopenrouter-mcp-multimodal/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stabgan","download_url":"https://codeload.github.com/stabgan/openrouter-mcp-multimodal/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stabgan%2Fopenrouter-mcp-multimodal/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32581044,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-03T06:36:36.687Z","status":"ssl_error","status_checked_at":"2026-05-03T06:36:09.306Z","response_time":103,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai","audio-generation","audio-transcription","claude","docker","image-analysis","image-generation","llm","mcp","mcp-server","model-context-protocol","multimodal","nodejs","openrouter","seedance","sora","typescript","veo","video-generation","video-understanding"],"created_at":"2025-05-20T09:10:21.866Z","updated_at":"2026-05-03T19:05:07.988Z","avatar_url":"https://github.com/stabgan.png","language":"TypeScript","funding_links":[],"categories":["Multimodal Input Processing","Aggregators","🌐 Web Development","Apps","AI \u0026 Machine Learning"],"sub_categories":["How to Submit","[OpenRouter MCP Multimodal](https://github.com/stabgan/openrouter-mcp-multimodal)"],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"assets/logo.png\" alt=\"OpenRouter MCP Multimodal\" width=\"200\" height=\"200\" /\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003eOpenRouter MCP Multimodal Server\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cstrong\u003eThe all-in-one MCP server for 300+ LLMs — text, vision, audio, and video in a single package.\u003c/strong\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://www.npmjs.com/package/@stabgan/openrouter-mcp-multimodal\"\u003e\u003cimg src=\"https://img.shields.io/npm/v/@stabgan/openrouter-mcp-multimodal.svg?label=npm\u0026color=cb3837\u0026logo=npm\" alt=\"npm version\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://hub.docker.com/r/stabgan/openrouter-mcp-multimodal\"\u003e\u003cimg src=\"https://img.shields.io/docker/v/stabgan/openrouter-mcp-multimodal/latest?label=docker\u0026color=2496ed\u0026logo=docker\u0026logoColor=white\" alt=\"Docker version\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/stabgan/openrouter-mcp-multimodal/actions/workflows/publish.yml\"\u003e\u003cimg src=\"https://github.com/stabgan/openrouter-mcp-multimodal/actions/workflows/publish.yml/badge.svg\" alt=\"CI\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://opensource.org/licenses/MIT\"\u003e\u003cimg src=\"https://img.shields.io/badge/License-MIT-yellow.svg\" alt=\"MIT\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://nodejs.org\"\u003e\u003cimg src=\"https://img.shields.io/badge/node-%E2%89%A518-43853d?logo=node.js\u0026logoColor=white\" alt=\"Node.js\" /\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://www.npmjs.com/package/@stabgan/openrouter-mcp-multimodal\"\u003e\u003cimg src=\"https://img.shields.io/npm/dt/@stabgan/openrouter-mcp-multimodal.svg?label=npm%20downloads\u0026color=cb3837\u0026logo=npm\" alt=\"npm downloads\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://www.npmjs.com/package/@stabgan/openrouter-mcp-multimodal\"\u003e\u003cimg src=\"https://img.shields.io/npm/dm/@stabgan/openrouter-mcp-multimodal.svg?label=monthly\u0026color=cb3837\u0026logo=npm\" alt=\"npm monthly\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://hub.docker.com/r/stabgan/openrouter-mcp-multimodal\"\u003e\u003cimg src=\"https://img.shields.io/docker/pulls/stabgan/openrouter-mcp-multimodal.svg?label=docker%20pulls\u0026color=2496ed\u0026logo=docker\u0026logoColor=white\" alt=\"Docker pulls\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/stabgan/openrouter-mcp-multimodal/stargazers\"\u003e\u003cimg src=\"https://img.shields.io/github/stars/stabgan/openrouter-mcp-multimodal.svg?style=social\" alt=\"GitHub stars\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/stabgan/openrouter-mcp-multimodal/network/members\"\u003e\u003cimg src=\"https://img.shields.io/github/forks/stabgan/openrouter-mcp-multimodal.svg?style=social\" alt=\"GitHub forks\" /\u003e\u003c/a\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n  \u003csub\u003e3,800+ installs across npm + Docker Hub \u0026middot; ~950 npm installs/month and accelerating\u003c/sub\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"#one-click-install\"\u003eInstall\u003c/a\u003e \u0026middot;\n  \u003ca href=\"#tools\"\u003eTools\u003c/a\u003e \u0026middot;\n  \u003ca href=\"#quick-start\"\u003eQuick Start\u003c/a\u003e \u0026middot;\n  \u003ca href=\"#configuration\"\u003eConfig\u003c/a\u003e \u0026middot;\n  \u003ca href=\"#usage-examples\"\u003eExamples\u003c/a\u003e \u0026middot;\n  \u003ca href=\"#architecture\"\u003eArchitecture\u003c/a\u003e \u0026middot;\n  \u003ca href=\"./CHANGELOG.md\"\u003eChangelog\u003c/a\u003e\n\u003c/p\u003e\n\n---\n[![Verified on MseeP](https://mseep.ai/badge.svg)](https://mseep.ai/app/8f27d6d4-0877-4b86-b377-8a33f451e755)\n\nAccess 300+ LLMs through [OpenRouter](https://openrouter.ai) via the [Model Context Protocol](https://modelcontextprotocol.io). Analyze images, audio, and video. Generate images, audio, and video. Chat with any model. Every tool returns structured `_meta.code` errors so MCP clients can switch on failure modes without parsing strings.\n\n\n\n## One-Click Install\n\n\u003ctable\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cstrong\u003eKiro\u003c/strong\u003e\u003c/td\u003e\u003ctd\u003e\u003ca href=\"https://kiro.dev/launch/mcp/add?name=openrouter\u0026config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40stabgan%2Fopenrouter-mcp-multimodal%22%5D%2C%22env%22%3A%7B%22OPENROUTER_API_KEY%22%3A%22sk-or-v1-...%22%7D%2C%22disabled%22%3Afalse%2C%22autoApprove%22%3A%5B%5D%7D\"\u003e\u003cimg src=\"https://img.shields.io/badge/Add_to-Kiro-232F3E?style=for-the-badge\u0026logo=amazonaws\u0026logoColor=white\" alt=\"Add to Kiro\" /\u003e\u003c/a\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cstrong\u003eCursor\u003c/strong\u003e\u003c/td\u003e\u003ctd\u003e\u003ca href=\"https://cursor.com/en/install-mcp?name=openrouter\u0026config=eyJ0eXBlIjoic3RkaW8iLCJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBzdGFiZ2FuL29wZW5yb3V0ZXItbWNwLW11bHRpbW9kYWwiXSwiZW52Ijp7Ik9QRU5ST1VURVJfQVBJX0tFWSI6InNrLW9yLXYxLS4uLiJ9fQ%3D%3D\"\u003e\u003cimg src=\"https://cursor.com/deeplink/mcp-install-dark.svg\" alt=\"Add to Cursor\" /\u003e\u003c/a\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cstrong\u003eVS Code\u003c/strong\u003e\u003c/td\u003e\u003ctd\u003e\u003ca href=\"https://insiders.vscode.dev/redirect/mcp/install?name=openrouter\u0026config=%7B%22type%22%3A%22stdio%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40stabgan%2Fopenrouter-mcp-multimodal%22%5D%2C%22env%22%3A%7B%22OPENROUTER_API_KEY%22%3A%22sk-or-v1-...%22%7D%7D\"\u003e\u003cimg src=\"https://img.shields.io/badge/Add_to-VS_Code-007ACC?style=for-the-badge\u0026logo=visualstudiocode\u0026logoColor=white\" alt=\"Add to VS Code\" /\u003e\u003c/a\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cstrong\u003eVS Code Insiders\u003c/strong\u003e\u003c/td\u003e\u003ctd\u003e\u003ca href=\"https://insiders.vscode.dev/redirect/mcp/install?name=openrouter\u0026config=%7B%22type%22%3A%22stdio%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40stabgan%2Fopenrouter-mcp-multimodal%22%5D%2C%22env%22%3A%7B%22OPENROUTER_API_KEY%22%3A%22sk-or-v1-...%22%7D%7D\u0026quality=insiders\"\u003e\u003cimg src=\"https://img.shields.io/badge/Add_to-VS_Code_Insiders-24bfa5?style=for-the-badge\u0026logo=visualstudiocode\u0026logoColor=white\" alt=\"Add to VS Code Insiders\" /\u003e\u003c/a\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cstrong\u003eClaude Desktop\u003c/strong\u003e\u003c/td\u003e\u003ctd\u003e\u003ca href=\"#option-1-npx-no-install\"\u003eInstall Guide\u003c/a\u003e — Add to \u003ccode\u003eclaude_desktop_config.json\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cstrong\u003eWindsurf\u003c/strong\u003e\u003c/td\u003e\u003ctd\u003e\u003ca href=\"#option-1-npx-no-install\"\u003eInstall Guide\u003c/a\u003e — Add to \u003ccode\u003e~/.codeium/windsurf/mcp_config.json\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cstrong\u003eCline\u003c/strong\u003e\u003c/td\u003e\u003ctd\u003e\u003ca href=\"#option-1-npx-no-install\"\u003eInstall Guide\u003c/a\u003e — Add via Cline MCP settings\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\u003cstrong\u003eSmithery\u003c/strong\u003e\u003c/td\u003e\u003ctd\u003e\u003ccode\u003enpx -y @smithery/cli install @stabgan/openrouter-mcp-multimodal --client claude\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003c/table\u003e\n\n\u003e After clicking, the target client opens a confirmation prompt. You'll need to paste your `OPENROUTER_API_KEY` — the deeplink ships a placeholder so no secrets end up in shared links.\n\n\u003c!--\nInstall-link audit (2026-04-20, round 4 — HTTPS redirectors only):\n  GitHub Markdown strips non-HTTPS schemes (cursor://, vscode:) from href attributes\n  and rewrites them to cursor.sh / nothing. The only deeplinks that survive GitHub's\n  sanitizer are HTTPS URLs. Fortunately both Cursor and VS Code publish official\n  HTTPS redirector endpoints that hand off to the IDE's native protocol handler:\n\n  - Kiro:    https://kiro.dev/launch/mcp/add?name=\u003cname\u003e\u0026config=\u003curl-encoded JSON\u003e\n  - Cursor:  https://cursor.com/en/install-mcp?name=\u003cname\u003e\u0026config=\u003cbase64\u003e\n             (config excludes `name`; badge is cursor.com/deeplink/mcp-install-dark.svg)\n  - VS Code: https://insiders.vscode.dev/redirect/mcp/install?name=\u003cname\u003e\u0026config=\u003curlenc JSON\u003e\n             (config excludes `name`; append \u0026quality=insiders for Insiders)\n\n  Earlier rounds used cursor://anysphere.cursor-deeplink/... and vscode:mcp/install?...\n  — both got stripped by GitHub and rendered as broken redirects to cursor.sh or a\n  camo.githubusercontent.com image-proxy URL. Pattern confirmed against\n  github/github-mcp-server and modelcontextprotocol/servers READMEs.\n\n  Regenerate with: node scripts/make-install-links.mjs\n--\u003e\n\n## Why This One?\n\n| Feature | Status |\n| :--- | :--- |\n| Text chat with 300+ models | ✅ |\n| Image analysis (vision) | ✅ Native with sharp optimization |\n| Audio analysis | ✅ Transcription + analysis, base64 auto-encoded |\n| Audio generation | ✅ Conversational, speech, and music with format auto-detection |\n| Image generation | ✅ Path-sandboxed disk output |\n| **Video understanding** | ✅ **v3** — mp4, mpeg, mov, webm from files, URLs, or data URLs |\n| **Video generation** | ✅ **v3** — Veo 3.1 / Sora 2 Pro / Seedance / Wan via async API with progress notifications |\n| Auto image resize + compress | ✅ Configurable (defaults 800px max, JPEG 80%) |\n| Model search + validation | ✅ Filter by vision / audio / video modality |\n| Free model support | ✅ Default: free Nemotron VL |\n| Docker support | ✅ Multi-arch (amd64 + arm64), ~345 MB Alpine |\n| Retry-After + jitter | ✅ Honors `Retry-After` header, avoids thundering herd |\n| IPv4 + IPv6 SSRF blocklist | ✅ Covers mapped, compat, multicast, 6to4, Teredo, ORCHID |\n| Structured error taxonomy | ✅ Closed `_meta.code` so clients can switch on failure modes |\n| Reasoning-model awareness | ✅ Detects `max_tokens` cutoff during CoT, guides the caller |\n| MCP 2025 tool annotations | ✅ `readOnlyHint` / `destructiveHint` / `idempotentHint` on every tool |\n\n## Tools\n\n| Tool | Description |\n| :--- | :--- |\n| `chat_completion` | Send messages to any OpenRouter model. Detects reasoning-model cutoffs. |\n| `analyze_image` | Analyze images from local files, URLs, or data URIs. Auto-optimized with sharp. |\n| `analyze_audio` | Analyze/transcribe audio (WAV, MP3, FLAC, OGG, etc.) from files, URLs, or data URIs. |\n| `analyze_video` | Analyze/transcribe video (mp4, mpeg, mov, webm) from files, URLs, or data URIs. |\n| `generate_image` | Generate images from text prompts. Optional path-sandboxed disk save. |\n| `generate_audio` | Generate audio from text. Auto-detects format, wraps raw PCM in WAV. |\n| `generate_video` | Generate video via OpenRouter's async API (Veo 3.1 / Sora 2 Pro / Seedance / Wan). Submits, polls, downloads, saves. |\n| `get_video_status` | Resume polling a `generate_video` job by id. Download + save when complete. |\n| `search_models` | Search/filter models by name, provider, or capabilities (vision / audio / video). |\n| `get_model_info` | Get pricing, context length, and capabilities for any model. |\n| `validate_model` | Check if a model ID exists on OpenRouter. |\n\n\u003e All error responses carry `_meta.code` from a closed taxonomy: `INVALID_INPUT` · `UNSAFE_PATH` · `UPSTREAM_HTTP` · `UPSTREAM_TIMEOUT` · `UPSTREAM_REFUSED` · `UNSUPPORTED_FORMAT` · `RESOURCE_TOO_LARGE` · `ZDR_INCOMPATIBLE` · `MODEL_NOT_FOUND` · `JOB_FAILED` · `JOB_STILL_RUNNING` · `INTERNAL`\n\n## Quick Start\n\n### Prerequisites\n\nGet a free API key from [openrouter.ai/keys](https://openrouter.ai/keys).\n\n### Option 1: npx (no install)\n\n```json\n{\n  \"mcpServers\": {\n    \"openrouter\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@stabgan/openrouter-mcp-multimodal\"],\n      \"env\": {\n        \"OPENROUTER_API_KEY\": \"sk-or-v1-...\"\n      }\n    }\n  }\n}\n```\n\n### Option 2: Docker\n\n```json\n{\n  \"mcpServers\": {\n    \"openrouter\": {\n      \"command\": \"docker\",\n      \"args\": [\n        \"run\", \"--rm\", \"-i\",\n        \"-e\", \"OPENROUTER_API_KEY=sk-or-v1-...\",\n        \"stabgan/openrouter-mcp-multimodal:latest\"\n      ]\n    }\n  }\n}\n```\n\n### Option 3: Global install\n\n```bash\nnpm install -g @stabgan/openrouter-mcp-multimodal\n```\n\n```json\n{\n  \"mcpServers\": {\n    \"openrouter\": {\n      \"command\": \"openrouter-multimodal\",\n      \"env\": { \"OPENROUTER_API_KEY\": \"sk-or-v1-...\" }\n    }\n  }\n}\n```\n\n### Option 4: Smithery\n\n```bash\nnpx -y @smithery/cli install @stabgan/openrouter-mcp-multimodal --client claude\n```\n\n## Configuration\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eEnvironment variables\u003c/strong\u003e (click to expand)\u003c/summary\u003e\n\n| Variable | Required | Default | Description |\n| :--- | :---: | :--- | :--- |\n| `OPENROUTER_API_KEY` | Yes | — | Your OpenRouter API key |\n| `OPENROUTER_DEFAULT_MODEL` | No | `nvidia/nemotron-nano-12b-v2-vl:free` | Default model for chat + analyze tools |\n| `DEFAULT_MODEL` | No | — | Alias for above |\n| `OPENROUTER_MODEL_CACHE_TTL_MS` | No | `3600000` | Model cache TTL (ms) |\n| `OPENROUTER_IMAGE_MAX_DIMENSION` | No | `800` | Longest edge for resize (px) |\n| `OPENROUTER_IMAGE_JPEG_QUALITY` | No | `80` | JPEG quality (1–100) |\n| `OPENROUTER_IMAGE_FETCH_TIMEOUT_MS` | No | `30000` | Image URL timeout |\n| `OPENROUTER_IMAGE_MAX_DOWNLOAD_BYTES` | No | `26214400` | Image URL size cap (~25 MB) |\n| `OPENROUTER_IMAGE_MAX_REDIRECTS` | No | `8` | Image URL redirect cap |\n| `OPENROUTER_IMAGE_MAX_DATA_URL_BYTES` | No | `20971520` | Image data URL size cap (~20 MB) |\n| `OPENROUTER_AUDIO_FETCH_TIMEOUT_MS` | No | `30000` | Audio URL timeout |\n| `OPENROUTER_AUDIO_MAX_DOWNLOAD_BYTES` | No | `26214400` | Audio URL size cap (~25 MB) |\n| `OPENROUTER_AUDIO_MAX_REDIRECTS` | No | `8` | Audio URL redirect cap |\n| `OPENROUTER_AUDIO_MAX_DATA_URL_BYTES` | No | `20971520` | Audio data URL size cap |\n| `OPENROUTER_DEFAULT_VIDEO_MODEL` | No | `google/gemini-2.5-flash` | Default for `analyze_video` |\n| `OPENROUTER_DEFAULT_VIDEO_GEN_MODEL` | No | `google/veo-3.1` | Default for `generate_video` |\n| `OPENROUTER_VIDEO_FETCH_TIMEOUT_MS` | No | `60000` | Video URL timeout |\n| `OPENROUTER_VIDEO_MAX_DOWNLOAD_BYTES` | No | `104857600` | Video URL size cap (~100 MB) |\n| `OPENROUTER_VIDEO_MAX_REDIRECTS` | No | `8` | Video URL redirect cap |\n| `OPENROUTER_VIDEO_MAX_DATA_URL_BYTES` | No | `104857600` | Video data URL size cap |\n| `OPENROUTER_VIDEO_POLL_INTERVAL_MS` | No | `15000` | Async video poll cadence |\n| `OPENROUTER_VIDEO_MAX_WAIT_MS` | No | `600000` | Max wait before returning a resumable handle |\n| `OPENROUTER_VIDEO_GEN_MAX_BYTES` | No | `268435456` | Generated video download cap (~256 MB) |\n| `OPENROUTER_VIDEO_INLINE_MAX_BYTES` | No | `10485760` | Inline video ceiling (~10 MB) |\n| `OPENROUTER_OUTPUT_DIR` | No | `process.cwd()` | Sandbox root for `save_path` |\n| `OPENROUTER_ALLOW_UNSAFE_PATHS` | No | — | `1` disables the sandbox |\n| `OPENROUTER_LOG_LEVEL` | No | `info` | `error` / `warn` / `info` / `debug` |\n\n\u003c/details\u003e\n\n### Security notes\n\n- **Analyze tools** can read local files and fetch HTTP(S) URLs. URL fetches block private/link-local/reserved IPv4 and IPv6 targets (SSRF mitigation) and cap response size.\n- **Generate tools** write to disk through a path sandbox: `save_path` is resolved against `OPENROUTER_OUTPUT_DIR` and any traversal attempt is rejected. Override with `OPENROUTER_ALLOW_UNSAFE_PATHS=1`.\n- **IPv6 SSRF blocklist** covers loopback, unspecified, IPv4-mapped, IPv4-compatible, link-local, site-local, ULA, multicast, documentation, Teredo, ORCHID, and 6to4 of private IPv4.\n\n## Usage Examples\n\n```\n# Chat\nUse chat_completion to explain quantum computing in simple terms.\n\n# Vision\nUse analyze_image on /path/to/photo.jpg and tell me what you see.\n\n# Audio transcription\nUse analyze_audio on /path/to/recording.mp3 to transcribe it.\n\n# Video understanding\nUse analyze_video on /path/to/clip.mp4 — what happens at 00:15?\n\n# Generate audio\nUse generate_audio with prompt \"Explain neural networks\" and voice \"alloy\", save to ./response.wav\n\n# Generate music\nUse generate_audio with model \"google/lyria-3-clip-preview\" and prompt \"upbeat jazz piano trio\"\n\n# Generate image\nUse generate_image with prompt \"a cat astronaut on mars\" and save to ./cat.png\n\n# Generate video\nUse generate_video with model \"google/veo-3.1\", prompt \"a calm river at sunrise\",\nresolution 720p, duration 4, save to ./river.mp4\n\n# Resume a video job\nUse get_video_status with video_id \"vid_abc123\" and save_path \"./river.mp4\"\n```\n\n## Architecture\n\n```\nsrc/\n├── index.ts                    # Entry, env validation, graceful shutdown\n├── tool-handlers.ts            # 11 tools (annotated) + dispatch\n├── model-cache.ts              # TTL + in-flight coalescing\n├── openrouter-api.ts           # REST client (chat + /videos)\n├── errors.ts                   # Closed ErrorCode enum\n├── logger.ts                   # JSON-line structured logger\n└── tool-handlers/\n    ├── fetch-utils.ts          # SSRF, bounded fetch, data-URL parser\n    ├── openrouter-errors.ts    # SDK/HTTP → ErrorCode classifier\n    ├── completion-utils.ts     # Reasoning-model cutoff detection\n    ├── path-safety.ts          # save_path sandbox\n    ├── chat-completion.ts      # Text + multimodal chat\n    ├── analyze-image.ts        # Vision analysis\n    ├── analyze-audio.ts        # Audio transcription\n    ├── analyze-video.ts        # Video understanding\n    ├── generate-image.ts       # Image generation\n    ├── generate-audio.ts       # Audio generation + streaming\n    ├── generate-video.ts       # Video generation (async)\n    ├── image-utils.ts          # Sharp optimization, MIME sniffing\n    ├── audio-utils.ts          # Audio format detection\n    ├── video-utils.ts          # Video format detection\n    ├── search-models.ts        # Model search\n    ├── get-model-info.ts       # Model detail lookup\n    └── validate-model.ts       # Model existence check\n```\n\n## Development\n\n```bash\ngit clone https://github.com/stabgan/openrouter-mcp-multimodal.git\ncd openrouter-mcp-multimodal\nnpm install\ncp .env.example .env  # Add your API key\nnpm run build\nnpm start\n```\n\n```bash\nnpm test                    # 163 unit tests, \u003c1s\nnpm run test:integration    # Live API tests\nnpm run lint\nnode scripts/live-e2e.mjs  # 16 live E2E scenarios\n```\n\n## Upgrading from v2\n\nv3 is **additive** — no tool schemas or env vars were removed.\n\n- Three new tools: `analyze_video`, `generate_video`, `get_video_status`\n- Structured `_meta.code` on every error response (text messages preserved)\n- `save_path` sandboxed by default — set `OPENROUTER_OUTPUT_DIR` or `OPENROUTER_ALLOW_UNSAFE_PATHS=1`\n- Reasoning-model awareness: `content: null` + `finish_reason: length` now returns `INVALID_INPUT` with a preview instead of empty string\n- IPv6 SSRF coverage extended to mapped, compat, multicast, 6to4, Teredo, ORCHID\n\n## Compatibility\n\nWorks with any MCP client: [Kiro](https://kiro.dev) · [Claude Desktop](https://claude.ai/download) · [Cursor](https://cursor.sh) · [Windsurf](https://codeium.com/windsurf) · [Cline](https://github.com/cline/cline) · any MCP-compatible client.\n\n## License\n\nMIT\n\n## Contributing\n\nIssues and PRs welcome. Please open an issue first for major changes.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstabgan%2Fopenrouter-mcp-multimodal","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstabgan%2Fopenrouter-mcp-multimodal","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstabgan%2Fopenrouter-mcp-multimodal/lists"}