Skip to main content
Glama

MCPGeneration for OpenRouter

Servidor MCP local, em TypeScript, que liga clientes como Claude Desktop/Code à API multimodal do OpenRouter. A geração de imagens é enfileirada numa base SQLite durável e executada por um worker Node independente do transporte MCP; vídeo mantém o fluxo existente.

O servidor usa MCP v2 e transporte stdio. Não inclui uma interface web nem executa um agente autónomo. O cliente MCP decide quando chamar as ferramentas e como integrar os recursos no código do projeto.

Funcionalidades

  • Catálogos atuais de modelos e capacidades publicados pelo OpenRouter.

  • Geração, edição e variações de imagens pelo endpoint dedicado /images, através de jobs duráveis.

  • Geração assíncrona de vídeo, animação de primeiro frame, consulta de estado e download autenticado por streaming.

  • Limites de custo, autorização allow_paid, modo dry_run e registo local de uso.

  • Fila local SQLite/WAL, deduplicação, recuperação conservadora após reinício e estado de entrega separado do estado financeiro.

  • Gravação de imagens e vídeos dentro de raízes autorizadas, sem sobrescrever ficheiros existentes.

  • Respostas MCP com conteúdo legível e structuredContent.

Related MCP server: MiniMax MCP JS

Ferramentas MCP

Ferramenta

Utilização

list_models

Pesquisa capacidades verificadas nos catálogos de imagem e vídeo.

start_image_job

Enfileira uma geração e devolve job_id sem esperar pela resposta paga.

start_image_edit_job

Enfileira edição com input_references e devolve job_id.

get_image_job_status

Consulta estado, fases, custo, erro e ficheiros guardados.

list_image_jobs

Lista jobs e reservas legadas sem as modificar.

recover_image_job_response

Volta a interpretar localmente uma resposta/saída durável; nunca envia POST.

reconcile_image_job

Regista decisão financeira manual com evidência; nunca repete o POST.

generate_image

Wrapper compatível: agora enfileira e devolve job_id.

edit_image

Wrapper compatível: agora enfileira e devolve job_id.

generate_variations

Wrapper compatível: enfileira o conjunto como job durável.

generate_video

Inicia uma tarefa text-to-video e devolve os IDs local e remoto.

animate_image

Envia uma imagem como primeiro frame, quando o modelo declara essa capacidade.

get_video_status

Consulta e persiste o estado de um job já submetido.

download_video

Descarrega uma tarefa concluída para uma raiz autorizada.

estimate_cost

Calcula preço fixo, limite superior, estimativa fundamentada ou unknown.

list_assets

Lista metadados de recursos locais sem enviar conteúdo binário.

Modelos iniciais

Os modelos padrão são google/gemini-3.1-flash-lite-image e heygen/heygen-video-1. O catálogo é consultado em tempo de execução; os identificadores e capacidades podem mudar. google/gemini-3.1-flash-image também está disponível para ser escolhido explicitamente quando existir no catálogo.

O servidor valida proporções, resoluções, durações, áudio, entrada de referência e quantidade de resultados contra os dados que o OpenRouter publica para cada modelo. O campo de áudio é opcional: quando omitido, não é enviado. list_models separa áudio configurável, gerido pelo fornecedor e obrigatório. Não tenta um endpoint de chat como fallback.

Requisitos

  • Node.js 24 ou superior (usa node:sqlite integrado, sem dependência SQLite nativa externa).

  • npm.

  • Uma chave OpenRouter para consultar catálogos ou fazer pedidos à API.

  • Claude Code ou outro cliente MCP que suporte servidores locais stdio.

O SDK MCP instalado é @modelcontextprotocol/server v2.3.1. O runtime do MCP e o worker têm de usar o mesmo diretório de dados; o worker corre como serviço systemd --user no Linux.

Instalação e configuração

git clone git@github.com:yberudev/MCPGeneration-for-Openrouter.git
cd MCPGeneration-for-Openrouter
npm ci
cp .env.example .env

Configure a chave OpenRouter num ficheiro fora do repositório, ~/.config/mcp-generation/worker.env, com permissões 0600. O MCP e o worker também aceitam variáveis herdadas pelo processo. O carregamento não depende do projeto que Claude abriu; não guarde a chave num .mcp.json versionado. .env continua disponível para configuração de desenvolvimento e está ignorado pelo Git.

npm run build
npm run typecheck
npm run lint
npm test

No Linux, instale e inicie o worker de imagens depois de colocar a chave no ficheiro externo. O script compila, cria cópias datadas dos JSON financeiros/metadados e instala um serviço systemd --user:

scripts/worker/prepare-env.sh
scripts/worker/install-systemd-user.sh
scripts/worker/verify.sh

Para testar gratuitamente a conectividade e a chave sem gerar conteúdo, execute npm run diagnose:network. Faz um GET autenticado à chave e um POST inválido sem autenticação; nunca envia um pedido válido de geração.

prepare-env.sh move a variável de .env para o ficheiro externo, quando necessário, preserva uma cópia com permissões restritas e nunca mostra o valor. Se não existir uma chave local, crie ~/.config/mcp-generation/worker.env com OPENROUTER_API_KEY=<a sua chave> e modo 0600. Consulte operação e recuperação do worker.

Inicie o servidor localmente com npm start. Num terminal, o processo fica à espera de um cliente MCP; a saída padrão é reservada ao protocolo.

Integração com Claude Code

Claude Code define CLAUDE_PROJECT_DIR no processo do servidor MCP. Assim, o projeto ativo passa a ser a raiz autorizada sem depender de process.cwd(). Num registo global, a chave pode ficar no .env da pasta de instalação deste servidor ou no ambiente que inicia Claude Code. O carregamento do .env é ancorado à pasta de instalação, não ao projeto aberto.

  1. Exporte a chave no terminal ou no gestor de ambiente usado para iniciar Claude Code:

    export OPENROUTER_API_KEY='sk-or-…'
  2. Registe o servidor no âmbito do utilizador. Para esta cópia do workspace:

    claude mcp add --scope user --transport stdio mcp-generation-openrouter -- node /home/yberudev/Documentos/MCPGeneration/dist/index.js

    Se mudar a pasta do repositório, substitua esse caminho absoluto pelo caminho de dist/index.js na nova localização.

  3. Inicie Claude Code no projeto e confirme a ligação:

    claude mcp list
    claude mcp get mcp-generation-openrouter

    Dentro da sessão, use /mcp para ver as ferramentas disponíveis. Um servidor no âmbito de projeto configurado por .mcp.json pode pedir aprovação na primeira utilização.

Também pode usar um ficheiro .mcp.json de projeto. O exemplo sem credenciais está em examples/.mcp.json.example. Atualize o caminho absoluto para o executável e disponibilize OPENROUTER_API_KEY no ambiente do Claude Code.

Depois de ligado, peça ao Claude Code, por exemplo: “Lista os modelos de vídeo, gera uma imagem de teste com allow_paid=true e guarda-a no meu projeto.” As chamadas pagas exigem essa autorização explícita. Para acompanhar vídeos, peça get_video_status com o ID local que generate_video devolveu e, quando o estado for completed, peça download_video.

Diretórios e persistência

Por omissão, os recursos ficam em:

<projeto>/public/assets/generated/images/
<projeto>/public/assets/generated/videos/

YBERU_ASSETS_DIR altera o diretório de saída relativo ao projeto. YBERU_PROJECT_ROOT substitui a raiz detetada; YBERU_ALLOWED_ROOTS acrescenta outras raízes autorizadas, separadas pelo separador de caminhos do sistema (: no Linux/macOS). Um caminho absoluto passado a uma ferramenta só é aceite se estiver dentro de uma dessas raízes. O servidor rejeita directory traversal, symlinks de saída e colisões; nunca substitui ficheiros existentes.

O estado local fica em ~/.local/share/mcp-generation-openrouter/ por omissão. YBERU_DATA_DIR define outra pasta absoluta e tem de ser igual para MCP e worker. O diretório guarda os metadados legados jobs.json, assets.json, usage.json, requests.json e a nova fila image-jobs.sqlite (WAL, diretório 0700, base/sidecars 0600). A fila contém payloads locais, prompts e imagens de entrada em base64 até à entrega; não são escritos nos logs. Respostas HTTP 200 completas são preservadas na tabela privada image_job_raw_responses antes do parsing JSON/Zod/base64/MIME; a base SQLite fica com modo 0600. Respostas interpretadas e outputs duráveis têm o corpo HTTP removido, mantendo hash, tamanho e metadados estruturais seguros. Respostas com falha de parsing ficam retidas até recuperação local; a quota total predefinida é 512 MiB e não há remoção por idade. requests.json contém hashes e reservas, não imagens.

Custos e operações pagas

  • allow_paid começa em false em todas as ferramentas que geram conteúdo.

  • Os limites padrão são $5 por operação e $20 acumulados. Um valor passado em max_cost_usd não pode ultrapassar o limite global por operação.

  • O servidor consulta preços atuais do catálogo OpenRouter e limites por fornecedor em GET /api/v1/models/{model}/endpoints. Catálogos incompletos ou contraditórios resultam em unknown; com ALLOW_UNKNOWN_COST=false, a geração continua bloqueada.

  • google/gemini-3.1-flash-lite-image tem estimativa quando o catálogo publica tarifas/limites suficientes: 1K usa 1.120 tokens de imagem de saída; o cálculo soma o máximo publicado de tokens de entrada e de conclusão aos tokens da imagem. Com os dados verificados em 23-10-2026, o limite superior é $0.138457 por imagem (65536 × $0.00000025 + 58982 × $0.0000015 + 1120 × $0.00003). Referências ocupam o teto de entrada; n.max=1; variações multiplicam o limite por chamada. Se faltar qualquer dado, a estimativa volta a unknown.

  • black-forest-labs/flux-3-image seleciona variant da tarifa OpenRouter: 768 $0.041, 1K $0.048, 1.5K $0.070, 2K $0.100, 4K $0.607. Sem resolução usa o maior preço publicado como limite superior, nunca o primeiro da lista. Os preços coincidem com a tabela BFL.

  • ALLOW_UNKNOWN_COST=true continua a ser uma exceção explícita e não garante um teto absoluto; esta versão mantém ALLOW_UNKNOWN_COST=false.

  • max_cost_usd compara estimativa/limite superior com limites locais e reserva orçamento; não limita a cobrança do fornecedor. O custo real é lido da resposta e pode exceder a estimativa.

  • Vídeos usam as pricing_skus atuais quando existe uma tarifa compatível com a duração, resolução e referências. A estimativa não garante o custo final.

  • dry_run=true consulta capacidades e custos, mostra o payload API (com base64 omitido) e não cria job nem inicia geração.

  • Antes de cada POST, o servidor reserva a despesa e guarda um hash do pedido. Se o resultado de um POST ficar incerto por timeout ou falha 5xx, não repete o pedido; a reserva permanece para bloquear uma duplicação. Use reconcile_image_job apenas com evidência verificada; não remova manualmente reservas incertas.

As fórmulas atuais para Gemini 3.1 Flash Lite Image e FLUX 3 Image, os endpoints oficiais consultados, a distinção entre estimativa e limite superior e a preservação privada de respostas HTTP 200 estão descritos em custos de imagem e recuperação local.

As ferramentas de imagem agora devolvem rapidamente job_id e estado local queued; o worker reserva o orçamento antes do POST. Consulte get_image_job_status até completed, failed, uncertain ou reconciliation_required. completed só significa que todos os outputs esperados foram validados, guardados, verificados por hash e ligados aos metadados. Se o Claude fechar/cancelar a chamada MCP, o worker continua. Um estado uncertain bloqueia repetição automática. O HTTP_TIMEOUT_MS continua a limitar a chamada HTTP do worker, não o tempo de vida do job.

Nenhuma chamada de geração paga é necessária para iniciar o processo ou descobrir ferramentas. As consultas GET públicas dos catálogos de modelos e preços não enviam a chave. Consultar estado de uma tarefa, gerar conteúdo ou descarregar vídeo requer autenticação.

Text-to-video e image-to-video

generate_video envia model, prompt e parâmetros suportados; recebe um job assíncrono e persiste o ID. get_video_status consulta o mesmo ID e não cria outro job. O download usa /videos/{id}/content, autenticação OpenRouter e streaming; não usa URLs externos de resultado como links permanentes.

animate_image envia a imagem local como frame_images[0] com frame_type: "first_frame", desde que o modelo publique essa capacidade. O pedido local usa uma data URL; alguns fornecedores exigem uma imagem HTTPS pública e podem rejeitá-la. Nessa situação, passe input_image_url HTTPS de uma imagem publicamente acessível; o MCP não descarrega esse URL e não lhe envia a chave OpenRouter. URLs com IP literal, host local, credenciais ou fragmentos são recusados. O servidor não hospeda automaticamente uma imagem local na Internet.

generate_audio distingue campo omitido, true e false: o campo omitido permanece fora do JSON enviado. HeyGen Video 1 sempre produz áudio; o catálogo publica generate_audio: false, mas esse valor não significa saída silenciosa e o endpoint rejeita generate_audio: false. O MCP recusa esse pedido localmente com VIDEO_AUDIO_REQUIRED. Modelos que anunciam controlo configurável preservam os booleans escolhidos. Para modelos sem esse controlo, o MCP não promete silêncio. O áudio gerado por HeyGen pode ser removido depois com FFmpeg (por exemplo, ffmpeg -i input.mp4 -c:v copy -an output.mp4); esse pós-processamento não faz parte da geração do MCP.

frame_images fixa uma imagem num ponto específico do vídeo; input_references dá imagens para orientar a cena sem fixar o frame. O custo usa SKUs diferentes: para HeyGen Video, a consulta real de 22-10-2026 publica, a 480p, $0.02/s em duration_seconds_480p, $0.07/s em reference_duration_seconds_480p e $0.04 por imagem em reference_input_images. Assim, cinco segundos a 480p estimam $0.10 para texto ou primeiro frame e $0.39 para uma imagem de referência. O custo real continua a ser o informado pelo OpenRouter após a geração. Este projeto gera ficheiros multimédia; não cria modelos 3D manipuláveis nem animações interativas.

Exemplos

Os prompts e os padrões para personagem, edição, animação e homepage estão em examples/README.md. Os testes não geram esses recursos.

Testes

npm test usa respostas HTTP simuladas e um cliente MCP de teste. Abrange descoberta de ferramentas, enqueue rápido com respostas simuladas de 75/150 segundos, encerramento do adaptador, retomada segura, incerteza sem retry, HTTP 400/5xx, ECONNRESET, PNG/JPEG/WebP, JSON/esquema/base64/MIME inválido, preservação antes do parsing, custo após falha, recuperação sem segundo POST, quota/hash de respostas, falha de gravação, reconciliação, variações parciais, vídeo, limites, persistência, caminhos e sanitização dos logs. Fixtures do catálogo OpenRouter guardam as tarifas reais de Gemini e FLUX 3 obtidas por GET. Inclui concorrência entre processos para reservas. Estes testes não fazem gerações reais nem consomem créditos.

npm run test:catalog consulta os catálogos e preços reais, verifica Nano Banana 2, Nano Banana 2 Lite e HeyGen Video e executa dry_run de geração, edição, vídeo e animação. O teste faz apenas GET e verifica que nenhum POST foi enviado; requer acesso à Internet, mas não uma API key nem créditos.

Existe um teste pago de uma imagem em tests/paid/. Só corre se as variáveis estiverem explicitamente configuradas, incluindo RUN_PAID_TESTS=true, OPENROUTER_API_KEY, YBERU_PROJECT_ROOT, ALLOW_UNKNOWN_COST=true e PAID_TEST_MAX_COST_USD. Não foi executado durante este desenvolvimento.

Limitações conhecidas

  • O custo antecipado de modelos por token continua desconhecido quando faltam resolução, tarifas de entrada/saída ou limites máximos publicados. O catálogo pode mudar; a estimativa guardada identifica a observação usada na autorização.

  • Alguns fornecedores de vídeo não aceitam data URLs; use um URL HTTPS público quando a API do modelo o exigir.

  • O acompanhamento de vídeo continua a ser sob pedido, sem polling em segundo plano nem ferramenta de cancelamento. Jobs de imagem são executados em segundo plano pelo serviço local.

  • O worker só funciona enquanto o serviço systemd --user está instalado/ativo. O job fica persistido enquanto estiver parado.

  • Se o processo morrer após iniciar o POST mas antes de receber/preservar o corpo HTTP completo, o job fica uncertain; não há retry automático e não se garante recuperação pelo histórico OpenRouter. Depois de HTTP 200 e preservação local, falhas de interpretação podem ser recuperadas com recover_image_job_response, sem segundo POST. A recuperação depende da integridade local e da quota. A reconciliação financeira não reenvia o pedido.

  • Só são guardados vídeos cujo tipo MIME e assinatura básica sejam MP4 ou WebM.

  • A disponibilidade e os parâmetros de modelos mudam; list_models é a fonte atual.

Segurança

  • A API key só vem do ambiente; o repositório ignora .env e o servidor limita o host a openrouter.ai.

  • Prompts não são comandos. O servidor não invoca shell.

  • Downloads usam apenas o endpoint autenticado de conteúdo do OpenRouter, recusam redirecionamentos e têm limite de tamanho/MIME/assinatura.

  • Os caminhos de leitura e escrita ficam dentro de raízes autorizadas. Symlinks em entradas/saídas são recusados e ficheiros existentes não são substituídos.

  • POSTs de geração não têm retry automático. Erros incertos deixam uma reserva persistente para impedir duplicação inadvertida.

  • Logs e erros não incluem cabeçalhos Authorization nem base64 de imagens; stdout permanece reservado ao MCP.

Roadmap

  • Presets de estilo, consistência de personagens e geração de spritesheets.

  • Otimização/conversão de imagens, thumbnails e pipelines imagem → vídeo.

  • Ferramentas de comparação entre modelos e catálogo local pesquisável.

  • Integração opcional com FFmpeg, motores de jogo e fornecedores adicionais.

As funcionalidades futuras não fazem parte da implementação atual.

Desenvolvimento

npm run dev
npm run build
npm run typecheck
npm run lint
npm test

Para adicionar um modelo, consulte o catálogo em vez de inserir capacidades fixas. As rotas e respostas do OpenRouter estão separadas do registo das ferramentas MCP.

Licença

MIT. Consulte LICENSE.

Referências oficiais

Available Tools

10 tools
animate_imageB

Anima uma imagem local como primeiro frame num pedido de vídeo. Só está disponível para modelos que publiquem supported_frame_images.first_frame. generate_audio omitido deixa o fornecedor decidir; HeyGen Video 1 exige áudio. O ficheiro é enviado como data URL; alguns fornecedores podem exigir URL HTTPS pública.

Inputs: prompt (required), input_image_path (required), model, dry_run, +9 more.

download_videoB

Descarrega por streaming um vídeo concluído pelo endpoint autenticado /videos/{id}/content. Usa gravação temporária e renomeação exclusiva; não segue URLs externos.

Inputs: job_id (required), index, filename, output_dir.

edit_imageC

Edita uma imagem local usando input_references do endpoint /images. A origem permanece intacta e a imagem editada é guardada como novo recurso.

Inputs: prompt (required), input_image_path (required), size, model, +7 more.

estimate_costC

Estima o custo com metadados atuais do OpenRouter. Devolve unknown quando os catálogos não permitem um cálculo fiável; não usa uma tabela fixa.

Inputs: type (required), model (required), count, duration, +6 more.

generate_imageB

Gera imagens pelo endpoint dedicado /images do OpenRouter, valida o modelo e guarda cada resultado dentro de uma raiz local autorizada. A geração exige allow_paid=true.

Inputs: prompt (required), n, size, model, +7 more.

generate_variationsC

Gera um conjunto limitado de variações de um prompt ou imagem. Usa n quando publicado pelo modelo; caso contrário envia exatamente count pedidos, após autorização explícita.

Inputs: prompt (required), size, count, model, +8 more.

generate_videoB

Inicia text-to-video de forma assíncrona e persiste o job. generate_audio é opcional: omitido deixa o fornecedor decidir; HeyGen Video 1 exige áudio. Geração exige allow_paid=true.

Inputs: prompt (required), model, dry_run, duration, +7 more.

get_video_statusA

Consulta o estado de uma tarefa de vídeo existente pelo ID local ou remoto. Nunca cria uma nova geração.

Inputs: job_id (required).

list_assetsB

Lista metadados de imagens e vídeos gerados pelo MCP, sem devolver conteúdo binário.

Inputs: type, limit, project_root.

list_modelsB

Consulta os catálogos atuais de modelos de imagem e vídeo do OpenRouter. Expõe somente capacidades e preços publicados pelos endpoints.

Inputs: type, search, refresh.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    B3.4/5.0

    Scored across 10 tools

    Disambiguation4/5

    The tools mostly target distinct resource/action pairs, and descriptions clarify boundaries such as generate_video versus animate_image and generate_image versus edit_image. Minor potential confusion remains around generate_variations, which overlaps conceptually with generate_image/edit_image, but its purpose is still distinguishable.

    Naming Consistency5/5

    All tool names use consistent snake_case and follow a predictable verb_noun pattern: list_models, generate_video, get_video_status, estimate_cost, list_assets, generate_image, edit_image, generate_variations. Even animate_image fits the same convention as a specific action on a resource.

    Tool Count5/5

    Ten tools are well-scoped for this server's media-generation purpose. Each tool covers a distinct operation across models, images, videos, assets, and cost estimation without excessive surface area.

    Completeness4/5

    The surface covers the main lifecycle: listing models, generating/editing images, generating variations, generating/an image-animating videos, checking status, downloading videos, listing assets, and estimating cost. Minor gaps exist around asset deletion/cleanup and job cancellation, but core workflows are well covered.

    Maintenance

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers