openrouter-mcp-multimodal
Servidor MCP para OpenRouter: mais de 300 LLMs com visão, geração de imagens, entrada/saída de áudio e análise + geração de vídeo (Veo 3.1 / Sora 2 Pro / Seedance / Wan). Erros estruturados, proteções SSRF IPv6, sandbox de caminho.
Documentação
OpenRouter MCP Multimodal
O servidor MCP para agentes de IA multimodais.
Uma instalação · 19 ferramentas · 300+ modelos OpenRouter · texto, visão, áudio & vídeo — análise e geração.
Início rápido · Ferramentas · Exemplos · Segurança · Solução de problemas · Desenvolvimento · Lançamento · Perguntas frequentes
O que é isto?
OpenRouter MCP Multimodal é um servidor Model Context Protocol (MCP) de nível de produção — listado no registro oficial de MCP como io.github.stabgan/openrouter-multimodal. Ele conecta agentes de codificação de IA (Cursor, Claude Desktop, VS Code, Windsurf, Cline e outros) à API unificada de LLM do OpenRouter via stdio.
Ao contrário de servidores MCP somente texto, uma única instalação cobre a superfície multimodal completa:
| Capacidade | Ferramentas | Destaques |
|---|---|---|
| Chat | chat_completion, start_chat_completion, get_chat_completion_status | 300+ modelos, sufixos :nitro / :floor / :free / :online / :exacto, roteamento de provedores, busca na web, cache de respostas, tokens de raciocínio, tarefas assíncronas para modelos de longa execução |
| Visão | analyze_image, generate_image, generate_image_dedicated | OCR, legendagem, VQA, geração de imagens com entradas de referência, API de imagem dedicada com controle de resolução/qualidade/formato |
| Áudio | analyze_audio, generate_audio, text_to_speech, speech_to_text | Transcrição, geração de fala/música, TTS dedicado (padrão gratuito Deepgram; vozes específicas de modelo, mp3/pcm), STT dedicado (Whisper/GPT-4o Transcribe) |
| Vídeo | analyze_video, generate_video, generate_video_from_image, get_video_status | Compreensão de clipes, geração Veo 3.1 / Seedance 2.0 / Wan 2.7 com notificações de progresso |
| Catálogo | search_models, get_model_info, validate_model, rerank_documents, health_check | Descoberta de modelos, validação, reclassificação, saúde operacional |
Robustez de produção: sandboxes de caminhos de entrada/saída (incluindo arquivos locais analyze_* a partir da v4.5.2), proteções SSRF, erros estruturados com _meta.code, saídas estruturadas MCP 2025-06-18, ícones de ferramentas (2025-11-25), notificações assíncronas de progresso de vídeo e 1000+ testes automatizados (unitários, mock, regressão e integração ao vivo).
Início rápido
1. Obtenha uma chave de API (o nível gratuito funciona) → openrouter.ai/keys
2. Execute o servidor
export OPENROUTER_API_KEY=sk-or-v1-...
npx -y @stabgan/openrouter-mcp-multimodal
3. Adicione ao seu cliente MCP — copie um bloco JSON de Instalação para a configuração do seu cliente:
| Cliente | Local da configuração |
|---|---|
| Cursor | Projeto: .cursor/mcp.json · Usuário: Configurações do Cursor → MCP |
| Claude Desktop | macOS: ~/Library/Application Support/Claude/claude_desktop_config.json · Windows: %APPDATA%\Claude\claude_desktop_config.json |
| VS Code | .vscode/mcp.json (workspace) ou Configurações do Usuário → MCP |
| Windsurf | Configurações do Windsurf → MCP (mesma forma JSON mcpServers que o Cursor) |
Use o objeto mcpServers de Configuração manual abaixo.
Nenhum crédito necessário para começar. Modelos gratuitos como
google/gemma-4-26b-a4b-it:freefuncionam para chat e visão. A geração de vídeo/áudio normalmente exige créditos.
Instalação
Os servidores MCP são distribuídos por vários modelos de empacotamento. Este servidor é implementado em Node.js/TypeScript; a tabela abaixo mapeia cada método do ecossistema para como executá-lo aqui.
| Método | Runtime | Melhor para | Este servidor |
|---|---|---|---|
| npx | Node.js 22+ | A maioria dos clientes MCP (padrão) | ✅ @stabgan/openrouter-mcp-multimodal |
| uvx / pipx | Python 3.10+ e Node.js 22+ | Fluxos de trabalho com foco em Python, mesmo padrão dos servidores MCP PyPI | ✅ mcp-server-openrouter-multimodal |
| npm global | Node.js 22+ | Fixar uma versão sem baixar novamente | ✅ |
| node (local) | Node.js 22+ | Contribuidores / builds isolados | ✅ |
| Docker Hub | Docker | Isolamento, sem Node no host | ✅ stabgan/openrouter-mcp-multimodal |
| GHCR | Docker | Pulls OCI nativos do GitHub | ✅ ghcr.io/stabgan/openrouter-mcp-multimodal |
| Smithery CLI | Node.js (via instalador) | Instalação interativa no Claude/Cursor/etc. | ✅ |
| Registro MCP | npm ou OCI | Descoberta oficial (io.github.stabgan/openrouter-multimodal) | ✅ listagem |
| Deeplinks de um clique | Node.js | Cursor, VS Code, Kiro | ✅ |
| Claude Code CLI | Node.js | Usuários do Claude Code com foco em terminal | ✅ |
| MCP Inspector | Node.js | Depurar / listar ferramentas localmente | ✅ |
Windows cmd /c npx | Node.js | Claude Desktop / Cursor quando npx não está no PATH da GUI | ✅ veja abaixo |
| pip / uv (direto) | — | Apenas servidores MCP Python nativos | — use a linha uvx acima |
| Extensões de desktop DXT | — | .dxt do Claude Desktop empacotado | ainda não |
| HTTP / SSE remoto | — | Endpoints hospedados Smithery / Cloudflare | via Smithery |
uvx vs npx: No ecossistema MCP,
npxexecuta pacotes npm (Node) euvxexecuta pacotes PyPI (Python). Como este servidor é baseado em Node,uvxusa um launcher Python fino que executanpx -y @stabgan/openrouter-mcp-multimodal— você ainda precisa ter o Node instalado.
Um clique
| Cursor | |
| VS Code | |
| Kiro | |
| Claude Desktop / Windsurf / Cline | Configuração JSON manual (escolha qualquer método abaixo) |
| Smithery | npx -y @smithery/cli install @stabgan/openrouter-mcp-multimodal --client claude |
| Registro MCP | Página oficial do registro — pacotes npm + OCI |
Cole seu OPENROUTER_API_KEY quando solicitado — os deeplinks usam espaços reservados para que segredos nunca apareçam em URLs.
Configuração manual
npx (recomendado)
export OPENROUTER_API_KEY=sk-or-v1-...
npx -y @stabgan/openrouter-mcp-multimodal
{
"mcpServers": {
"openrouter": {
"command": "npx",
"args": ["-y", "@stabgan/openrouter-mcp-multimodal"],
"env": {
"OPENROUTER_API_KEY": "sk-or-v1-..."
}
}
}
}
Fixar uma versão: "args": ["-y", "@stabgan/openrouter-mcp-multimodal@5.0.1"]
uvx / pipx (iniciador Python)
Instale o uv (inclui uvx), garanta que o Node.js 22+ também esteja no seu PATH, então:
export OPENROUTER_API_KEY=sk-or-v1-...
uvx mcp-server-openrouter-multimodal
# pin npm version: OPENROUTER_MCP_NPM_VERSION=5.0.1 uvx mcp-server-openrouter-multimodal
{
"mcpServers": {
"openrouter": {
"command": "uvx",
"args": ["mcp-server-openrouter-multimodal"],
"env": {
"OPENROUTER_API_KEY": "sk-or-v1-..."
}
}
}
}
Equivalente pipx: pipx run mcp-server-openrouter-multimodal
Opcional: OPENROUTER_MCP_NPM_VERSION=5.0.1 fixa o pacote npm subjacente.
npm global
npm install -g @stabgan/openrouter-mcp-multimodal
{
"mcpServers": {
"openrouter": {
"command": "openrouter-multimodal",
"env": { "OPENROUTER_API_KEY": "sk-or-v1-..." }
}
}
}
node (clone local)
git clone https://github.com/stabgan/openrouter-mcp-multimodal.git
cd openrouter-mcp-multimodal
npm ci && npm run build
{
"mcpServers": {
"openrouter": {
"command": "node",
"args": ["/absolute/path/to/openrouter-mcp-multimodal/dist/index.js"],
"env": { "OPENROUTER_API_KEY": "sk-or-v1-..." }
}
}
}
Docker
docker run --rm -i -e OPENROUTER_API_KEY=sk-or-v1-... stabgan/openrouter-mcp-multimodal:latest
{
"mcpServers": {
"openrouter": {
"command": "docker",
"args": [
"run",
"--rm",
"-i",
"-e",
"OPENROUTER_API_KEY=sk-or-v1-...",
"stabgan/openrouter-mcp-multimodal:latest"
]
}
}
}
Use -i (stdio interativo). Evite -t (TTY corrompe o enquadramento MCP em alguns hosts).
GHCR (Registro de Contêineres GitHub)
docker run --rm -i -e OPENROUTER_API_KEY=sk-or-v1-... \
ghcr.io/stabgan/openrouter-mcp-multimodal:5.0.1
{
"mcpServers": {
"openrouter": {
"command": "docker",
"args": [
"run",
"--rm",
"-i",
"-e",
"OPENROUTER_API_KEY=sk-or-v1-...",
"ghcr.io/stabgan/openrouter-mcp-multimodal:5.0.1"
]
}
}
}
Smithery
Instalação interativa (grava a configuração para o seu cliente):
npx -y @smithery/cli install @stabgan/openrouter-mcp-multimodal --client claude
# or: --client cursor | vscode | windsurf | ...
Listagem: smithery.ai/server/@stabgan/openrouter-mcp-multimodal
Registro MCP
Nome oficial: io.github.stabgan/openrouter-multimodal
- Registro: registry.modelcontextprotocol.io
- Pacote npm:
@stabgan/openrouter-mcp-multimodal - Imagem OCI:
docker.io/stabgan/openrouter-mcp-multimodal
Clientes que suportam instalação orientada por registro oferecerão npm ou Docker; caso contrário, use os blocos JSON acima.
CLI do Claude Code
claude mcp add openrouter -- npx -y @stabgan/openrouter-mcp-multimodal
# project scope:
claude mcp add --scope project openrouter -- npx -y @stabgan/openrouter-mcp-multimodal
Defina OPENROUTER_API_KEY no seu shell ou ambiente do cliente antes de iniciar o Claude Code.
Inspetor MCP
Depure tools/list e chamadas de ferramentas com uma chave OpenRouter ativa:
export OPENROUTER_API_KEY=sk-or-v1-...
npx -y @modelcontextprotocol/inspector npx -y @stabgan/openrouter-mcp-multimodal
Windows npx
Quando o Claude Desktop ou o Cursor não conseguem encontrar npx (aplicativos GUI frequentemente perdem o PATH do shell), envolva com cmd:
{
"mcpServers": {
"openrouter": {
"command": "cmd",
"args": ["/c", "npx", "-y", "@stabgan/openrouter-mcp-multimodal"],
"env": { "OPENROUTER_API_KEY": "sk-or-v1-..." }
}
}
}
Se ainda falhar, use o caminho completo de where npx como comando.
Por que este servidor?
| Capacidade | Este servidor | Servidores MCP LLM típicos |
|---|---|---|
| Chat de texto (300+ modelos) | ✅ | ✅ |
| Análise + geração de imagens | ✅ | parcial |
| Análise de áudio + TTS | ✅ | ❌ |
| Análise + geração de vídeo | ✅ | ❌ |
| Busca / validação / rerank de modelos | ✅ | ❌ |
| Sandbox de caminho + proteção SSRF | ✅ | raro |
| Saídas estruturadas MCP 2025 | ✅ | raro |
| Vídeo assíncrono + notificações de progresso | ✅ | ❌ |
Ferramentas
19 ferramentas MCP. Cada descrição inclui Use quando, Exemplos bons/ruins, Falha quando e Funciona com para que agentes escolham a ferramenta certa e se recuperem de erros.
| Ferramenta | Finalidade |
|---|---|
chat_completion | Chat de texto, busca na web, roteamento de provedor, cache, raciocínio |
start_chat_completion | Trabalho assíncrono em segundo plano para modelos de raciocínio longos |
get_chat_completion_status | Consultar / recuperar resultados de conclusão assíncrona |
analyze_image | Visão — caminho local, URL ou data URL + question |
analyze_audio | Transcrever / analisar arquivos de áudio |
analyze_video | Descrever / perguntas e respostas sobre arquivos de vídeo |
generate_image | Texto para imagem via conclusões de chat com imagens de referência |
generate_image_dedicated | Texto para imagem via /api/v1/images dedicado (resolução, qualidade, formato) |
generate_audio | Texto para fala / música via conclusões de chat |
text_to_speech | TTS dedicado (/api/v1/audio/speech) — padrão gratuito Deepgram, vozes, velocidade, mp3/pcm |
speech_to_text | STT dedicado (/api/v1/audio/transcriptions) — Whisper, GPT-4o |
generate_video | Texto para vídeo (assíncrono, retomável) |
generate_video_from_image | Imagem para vídeo (esquema mais restrito) |
get_video_status | Consultar / retomar trabalhos de vídeo |
search_models | Busca paginada no catálogo de modelos |
get_model_info | Preços, contexto, modalidades |
validate_model | Verificação barata de existência de ID de modelo |
rerank_documents | Classificação de relevância para RAG |
health_check | Sonda de chave de API + acessibilidade |
Erros usam uma taxonomia fechada _meta.code: INVALID_INPUT · UNSAFE_PATH · UPSTREAM_* · MODEL_NOT_FOUND · JOB_STILL_RUNNING · e mais.
Resultados binários de ferramentas (v4.7.0+)
Ferramentas de geração (generate_image, generate_image_dedicated, generate_audio, text_to_speech, generate_video, generate_video_from_image, get_video_status) retornam bytes de imagem, áudio ou vídeo. A partir de 4.7.0 o comportamento é explícito:
save_path | Resultado da ferramenta |
|---|---|
| Definido | Somente ponteiro de texto — ex.: Image saved to: out.png (… bytes, image/png) mais _meta.save_path. Sem base64 inline (evita duplicar grandes cargas no canal MCP). |
| Não definido, abaixo do teto de bytes | Bloco de mídia inline e texto resumido (imagens/áudio usam tipos MCP image / audio; vídeo usa blocos MCP resource). |
| Não definido, acima do teto | Somente texto com dica para passar save_path. |
Tetos inline padrão (substitua por tipo ou globalmente):
| Tipo | Padrão | Variáveis de ambiente (precedência: por tipo → global) |
|---|---|---|
| Imagem | 1 MiB | OPENROUTER_IMAGE_INLINE_MAX_BYTES → OPENROUTER_INLINE_MAX_BYTES |
| Áudio | 1 MiB | OPENROUTER_AUDIO_INLINE_MAX_BYTES → OPENROUTER_INLINE_MAX_BYTES |
| Vídeo | 10 MiB | OPENROUTER_VIDEO_INLINE_MAX_BYTES → OPENROUTER_INLINE_MAX_BYTES |
Se você dependia anteriormente de ambos um arquivo salvo e mídia inline no mesmo resultado de ferramenta, leia o arquivo de _meta.save_path (ou omita save_path para obter mídia inline quando abaixo do teto).
Exemplos
Chat (modelo gratuito)
{
"tool": "chat_completion",
"arguments": {
"model": "google/gemma-4-26b-a4b-it:free",
"messages": [{ "role": "user", "content": "Summarize MCP in one sentence." }]
}
}
Analisar uma imagem
{
"tool": "analyze_image",
"arguments": {
"image_path": "diagram.png",
"question": "List every label in this diagram."
}
}
Use
image_pathequestion— nãoimage/prompt.
Buscar modelos (visão + gratuito)
{
"tool": "search_models",
"arguments": {
"query": "gemma",
"capabilities": { "vision": true },
"limit": 10,
"offset": 0
}
}
Gerar vídeo (assíncrono)
{
"tool": "generate_video",
"arguments": {
"model": "google/veo-3.1",
"prompt": "Ocean waves at sunrise, cinematic drone shot",
"duration": 4,
"save_path": "river.mp4"
}
}
Se o trabalho ainda estiver em execução quando max_wait_ms expirar, a resposta é bem-sucedida com _meta.code: JOB_STILL_RUNNING e um video_id — chame get_video_status para retomar. Isso não é um erro.
Com save_path definido (como acima), o resultado é um ponteiro de texto para o arquivo salvo quando concluído — não vídeo inline. Veja Resultados binários de ferramentas.
Mais exemplos: docs/plans/tool-description-improvement.md
Segurança
- Sandbox de caminho de entrada — caminhos locais em
analyze_*e imagens de referência devem permanecer dentro deOPENROUTER_INPUT_DIR(recai paraOPENROUTER_OUTPUT_DIR, depoiscwd) - Sandbox de caminho de saída —
save_pathdeve permanecer dentro deOPENROUTER_OUTPUT_DIR - Leituras de trabalhos assíncronos —
get_chat_completion_statusresolve caminhos de disco somente sobOPENROUTER_OUTPUT_DIR/openrouter-jobs/(4.7.0+) - Proteção SSRF — IPs privados/reservados bloqueados em buscas de URL
- Conteúdo não confiável — saídas de análise marcadas
_meta.content_is_untrusted: true
Substitua sandboxes somente com OPENROUTER_ALLOW_UNSAFE_PATHS=1 (desencorajado).
Reporte vulnerabilidades: SECURITY.md (divulgação privada — não abra issues públicas para exploits).
Configuração
Variáveis de ambiente
| Variável | Obrigatória | Padrão | Descrição |
|---|---|---|---|
OPENROUTER_API_KEY | Sim | — | Chave de API OpenRouter |
OPENROUTER_DEFAULT_MODEL | Não | google/gemma-4-26b-a4b-it:free | Padrão quando ferramentas omitem model |
OPENROUTER_OUTPUT_DIR | Não | cwd | Raiz do sandbox para save_path |
OPENROUTER_INPUT_DIR | Não | OUTPUT_DIR ou cwd | Raiz do sandbox para arquivos de entrada locais |
OPENROUTER_INLINE_MAX_BYTES | Não | 1048576 (imagem/áudio) | Teto global de mídia inline |
OPENROUTER_IMAGE_INLINE_MAX_BYTES | Não | recai para global | Teto inline por tipo |
OPENROUTER_AUDIO_INLINE_MAX_BYTES | Não | recai para global | Teto inline por tipo |
OPENROUTER_VIDEO_INLINE_MAX_BYTES | Não | 10485760 | Teto inline de vídeo |
OPENROUTER_LOG_LEVEL | Não | info | error / warn / info / debug |
Veja .env.example para a lista completa (roteamento de provedor, limites de busca, cache, sondagem de vídeo, trabalhos assíncronos, substituições de teste de integração).
Desenvolvimento
git clone https://github.com/stabgan/openrouter-mcp-multimodal.git
cd openrouter-mcp-multimodal
npm install
cp .env.example .env # add OPENROUTER_API_KEY
npm run build
Testes
| Comando | O que executa |
|---|---|
npm test | 1018 testes unitários + mocks (sem chave de API, <20s) |
npm run test:regression | Guardas de regressão de segurança + esquema |
npm run test:integration | 16 cenários OpenRouter ao vivo (requer chave .env) |
npm run test:e2e | Teste de fumaça MCP stdio completo (scripts/live-e2e.mjs) |
npm run ci | lint + formatação + build + tudo acima exceto e2e |
Modelos gratuitos para contas CI / sem créditos: os testes de integração usam por padrão google/gemma-4-26b-a4b-it:free (substitua com OPENROUTER_INTEGRATION_MODEL). O GitHub Actions exige o segredo do repositório OPENROUTER_API_KEY. |
Os testes simulados ficam em src/__tests__/mock/ e cobrem handlers, sandboxes de caminho, bloqueios de SSRF, paginação de cache de modelos, descrições de ferramentas e saídas estruturadas — mais de 330 casos adicionais além do conjunto principal.
npm run lint
npm run format:check
npm run version:check # package.json vs src/version.ts, server.json, pyproject.toml
Lançamento
Os artefatos publicados (npm, PyPI/uvx, Docker, GHCR) são todos enviados a partir do mesmo semver em uma tag git (vX.Y.Z). Enviar para main executa os testes, mas não publica no npm ou PyPI.
Fluxo normal: mescle commits convencionais para main → o Release Please abre um PR de lançamento → mescle-o → a tag é criada → o CI publica em todos os lugares.
Fluxo manual: atualize todos os arquivos de versão → npm run version:check → npm run ci + testes de fumaça → commit → git tag vX.Y.Z → git push origin vX.Y.Z.
Lista de verificação completa, lista de arquivos, segredos de CI e instruções para agentes:
docs/RELEASING.md— guia de lançamento para mantenedoresAGENTS.md— referência rápida para agentes de IA
Solução de problemas
| Sintoma | Causa provável | Correção |
|---|---|---|
O servidor sai imediatamente / OPENROUTER_API_KEY is required | Chave de API ausente ou vazia | Defina OPENROUTER_API_KEY no cliente env ou no shell — obtenha uma em openrouter.ai/keys |
_meta.code: INVALID_CREDENTIALS ou HTTP 401 | Chave inválida ou revogada | Gere novamente em openrouter.ai/keys; reinicie o cliente MCP |
_meta.code: MODEL_NOT_FOUND | Erro de digitação ou ID de modelo descontinuado | Execute search_models ou validate_model; verifique openrouter.ai/models |
| HTTP 402 / créditos insuficientes | Modelo pago ou geração com saldo zero | Adicione créditos em openrouter.ai/credits ou use um modelo :free |
_meta.code: UPSTREAM_HTTP com 429 | Limite de taxa | Aguarde _meta.retry_after_seconds se presente; reduza a concorrência |
_meta.code: UNSAFE_PATH | Caminho local fora do sandbox | Coloque os arquivos em OPENROUTER_INPUT_DIR ou defina OPENROUTER_OUTPUT_DIR mais amplo; veja Segurança |
npx não encontrado (aplicativos GUI do Windows) | O PATH da GUI difere do terminal | Use o wrapper cmd /c do npx do Windows |
| Sem imagem/áudio inline após a atualização | v4.7.0 com save_path definido | Esperado — o resultado é apenas texto + _meta.save_path; omita save_path ou leia o arquivo salvo |
| O cliente MCP mostra uma lista de ferramentas desatualizada | Cache do cliente | Reinicie o MCP / recarregue a janela após atualizar o pacote fixado |
Erros estruturados incluem _meta.suggestions com próximos passos orientados a agentes quando disponíveis.
Perguntas frequentes
Preciso de créditos pagos do OpenRouter?
Não, para começar. Modelos gratuitos funcionam para chat e visão. A geração de áudio/vídeo geralmente exige créditos; a análise pode retornar 402 em alguns modelos — o servidor apresenta isso como um erro estruturado.
Quais clientes MCP são suportados?
Qualquer cliente compatível com MCP via stdio: Cursor, Claude Desktop, VS Code Copilot, Windsurf, Cline, Kiro e agentes personalizados.
Como isso é diferente de chamar o OpenRouter diretamente?
Este servidor adiciona esquemas de ferramentas MCP, sandboxes de segurança, taxonomia de erros, cache de modelos, polling assíncrono de vídeo com notificações de progresso e descrições de ferramentas orientadas a agentes — para que LLMs invoquem a capacidade certa sem código HTTP personalizado.
Onde está o aviso de segurança para travessia de caminho?
Corrigido na 4.5.2+ — veja GHSA-3q7p-736f-x44v, SECURITY.md e docs/solutions/security-issues/.
Compatibilidade
Funciona com qualquer cliente MCP. Protocolo: MCP 2025-06-18. Node ≥ 22 (a imagem Docker usa Node 24).
Licença
Apache 2.0 — veja LICENSE.
Contribuição
Issues e PRs são bem-vindos. Para mudanças grandes, abra uma issue primeiro.
Antes de enviar: execute npm run ci. Use Conventional Commits (fix:, feat:, etc.) para que o Release Please possa cortar o próximo lançamento. Veja docs/RELEASING.md se precisar enviar uma versão.