9Router MCP Server

Servidor MCP para 9Router — expõe busca na web, fetch de páginas, TTS e outras capacidades como ferramentas nativas, eliminando a sobrecarga por chamada das abordagens baseadas em arquivos de skill (releitura de instruções, formatação manual, nova tentativa em caso de erro) em favor de chamadas de ferramenta estruturadas via stdio.

Documentação

9Router MCP Server

CI npm version Node

Servidor MCP que expõe as capacidades do 9Router como ferramentas nativas para qualquer cliente MCP: descoberta de modelos, fallback automático e entradas validadas por Zod.

Status: O 9Router já oculta a complexidade específica de cada provedor por trás de uma única API. Este servidor expõe essa API por meio do MCP, para que agentes e aplicativos possam chamar busca na web, fetch de páginas, geração de imagens, TTS, STT e embeddings como ferramentas MCP padrão — sem carregar arquivos de skill, sem código de integração por provedor.

Por que usar

  • As ferramentas são sempre registradas; sem carregamento manual de skills (economiza tokens e contexto).
  • Fallback automático de modelo quando o modelo principal falha.
  • Entradas validadas por Zod com mensagens de erro claras antes de qualquer chamada de rede.
  • Um único arquivo de configuração para endpoint, autenticação e modelos padrão com cadeias de fallback.
  • Transporte único (stdio); funciona com qualquer cliente compatível com MCP.

Chat / geração de código é intencionalmente não incluído — é para isso que serve o modelo do host.

Conteúdo

Instalação

O pacote é ninerouter-mcp no npm. O corpo JSON é idêntico em todos os clientes MCP — apenas a chave de nível superior e o caminho do arquivo diferem. Cole o bloco na chave correta na configuração do seu cliente:

{
    "ninerouter": {
        "type": "stdio",
        "command": "npx",
        "args": ["-y", "ninerouter-mcp"],
        "env": {
            "NINEROUTER_URL": "http://localhost:20128"
        }
    }
}

Chaves de nível superior por cliente: VS Code (servers), OpenCode (mcp, renomeie env → environment, defina type: "local" e enabled: true), Claude Code / Cursor / Windsurf / Claude Desktop / Zed (mcpServers ou context_servers, remova a linha type). O JetBrains usa uma caixa de diálogo em Settings → Tools → AI Assistant → MCP com o mesmo comando, argumentos e env.

Claude Code

claude mcp add --scope user ninerouter -e NINEROUTER_URL=http://localhost:20128 -- npx -y ninerouter-mcp

Codex CLI

codex mcp add ninerouter --env NINEROUTER_URL=http://localhost:20128 -- npx -y ninerouter-mcp

Hermes Agent

Adicione a ~/.hermes/config.yaml:

mcp_servers:
    ninerouter:
        command: npx
        args:
            - -y
            - ninerouter-mcp
        env:
            NINEROUTER_URL: http://localhost:20128

Configuração

O servidor precisa de uma URL base do 9Router. Opcionalmente, aceita uma chave de API e fallbacks de modelo padrão para cada ferramenta.

Fontes, em ordem de prioridade (maior primeiro):

  1. Flag de CLI --config <path> (ou env --config-file, -c, NINEROUTER_CONFIG)
  2. ~/.config/ninerouter-mcp/config.toml
  3. Variáveis de ambiente: NINEROUTER_URL, NINEROUTER_KEY

Se o arquivo de configuração existir, ele tem precedência sobre as variáveis de ambiente.

Configuração rápida

Gere um arquivo de configuração inicial e edite-o:

npx ninerouter-mcp create-config

Isso grava ~/.config/ninerouter-mcp/config.toml e se recusa a sobrescrever um arquivo existente.

Configuração manual (variáveis de ambiente)

Windows (PowerShell):

$env:NINEROUTER_URL = "http://localhost:20128"
$env:NINEROUTER_KEY = "sk-..."   # optional

macOS / Linux:

export NINEROUTER_URL=http://localhost:20128
export NINEROUTER_KEY=sk-...     # optional

NINEROUTER_KEY é opcional e só é necessário quando sua instância do 9Router tem autenticação habilitada.

Configuração manual (arquivo de configuração)

# 9Router base URL (required)
base_url = "http://localhost:20128"

# Optional API key
# api_key = "sk-..."

# Default models with fallback support.
# Single string = one model.
# Array = tried in order, first success wins, errors are aggregated.
[default_models]
web_search      = ["tavily/search", "brave-search/search"]
web_fetch       = ["firecrawl/fetch", "jina-reader/fetch"]
generate_image  = "openai/dall-e-3"
text_to_speech  = "openai/tts-1"
speech_to_text  = ["openai/whisper-1", "groq/whisper-large-v3-turbo"]
embeddings      = "openai/text-embedding-3-small"

# Defaults for the list_models tool (all optional; these are the built-in values)
[list_models]
limit = 20             # default page size
offset = 0             # default start index
cache_ttl_seconds = 60 # 0 disables caching

A tabela ninerouter também é aceita como alias para base_url e api_key de nível superior:

[ninerouter]
base_url = "http://localhost:20128"
api_key  = "sk-..."

Aponte para um arquivo de configuração não padrão:

npx -y ninerouter-mcp --config /path/to/config.toml
# or
NINEROUTER_CONFIG=/path/to/config.toml npx -y ninerouter-mcp

Execução

Após npm install deste repositório:

npm run build
npm start

Ou em modo de observação durante o desenvolvimento:

npm run dev

Usuários do pacote publicado podem executá-lo diretamente:

npx -y ninerouter-mcp

Ferramentas

Toda ferramenta é registrada no servidor MCP na inicialização. Salvo indicação em contrário, todas as ferramentas retornam um único bloco de conteúdo de texto com JSON formatado.

list_models

Consulte os IDs de modelos expostos pelo 9Router. Esta ferramenta é opcional: todas as outras funcionam sem ela, pois cada uma tem um modelo padrão configurado ou cadeia de fallback. Chame-a apenas para mirar um modelo específico ou para descobrir IDs que diferem dos padrões. Ela filtra por search e depois pagina pelos resultados com offset/limit, para que um catálogo grande não inunde a janela de contexto. Cada resposta relata total, count, offset e nextOffset (omitido na última página). A lista upstream é armazenada em cache por cerca de um minuto, porque o 9Router reconstrói todo o catálogo a cada requisição (vários segundos), então apenas a primeira chamada é lenta.

ParâmetroTipoObrigatórioDescrição
kindstringnãoUm de chat, image, tts, embedding, web, stt, image-to-text. Omita para modelos de chat padrão.
searchstringnãoCorrespondência de substring sem diferenciar maiúsculas/minúsculas contra IDs/nomes de modelos.
limitnumbernãoTamanho da página (padrão 20, máximo 500). Use 0 para a lista completa.
offsetnumbernãoÍndice do primeiro modelo a retornar (padrão 0). Use nextOffset para paginar.
refreshbooleannãoIgnora o cache e busca novamente do 9Router.

Os padrões podem ser sobrescritos em config.toml:

[list_models]
limit = 20             # default page size
offset = 0             # default start index
cache_ttl_seconds = 60 # 0 disables caching

Padrões embutidos (usados quando uma chave é omitida): limit = 20, offset = 0, cache_ttl_seconds = 60.

web_search

Busque na web por meio do 9Router.

ParâmetroTipoPadrãoNotas
querystring—Obrigatório.
modelstring—ID do modelo 9Router (ex.: tavily/search). Faz fallback para provider, depois default_models.web_search.
providerstring—Alias para model.
maxResultsnumber51–20.
searchTypestringwebweb ou news.
countrystring—
languagestring—
timeRangestring—
domainFilterstring—

web_fetch

Busque uma URL e retorne-a como markdown, texto ou HTML.

ParâmetroTipoPadrãoNotas
urlstring—Obrigatório. Deve ser uma URL válida.
modelstring—ex.: jina-reader/fetch, firecrawl/fetch.
providerstring—Alias para model.
formatstringmarkdownmarkdown, text ou html.
maxCharactersnumber8000Limite de truncamento.

generate_image

Geração de imagem a partir de texto. Sempre grava um arquivo e retorna a imagem como um bloco de conteúdo base64 mais { outputPath, bytes, contentType }. Omita outputPath para gravar no diretório temporário do SO.

ParâmetroTipoPadrãoNotas
promptstring—Obrigatório.
modelstring—ex.: openai/dall-e-3, gemini/gemini-3-pro-image-preview.
providerstring—Alias para model.
nnumber11–10.
sizestring1024x1024
qualitystring—standard ou hd.
outputPathstringtmpdir do SOOnde gravar o arquivo. Padrão os.tmpdir()/ninerouter-<slug>-<ts>.<ext>. Extensão do content-type.

text_to_speech

Sintetize áudio. Sempre grava um arquivo e retorna o áudio como um bloco de conteúdo base64 mais { outputPath, bytes, contentType }. Omita outputPath para gravar no diretório temporário do SO.

ParâmetroTipoPadrãoNotas
inputstring—Obrigatório.
modelstring—ex.: openai/tts-1, edge-tts/vi-VN-HoaiMyNeural.
providerstring—Alias para model.
outputPathstringtmpdir do SOOnde gravar o arquivo. Padrão os.tmpdir()/ninerouter-<slug>-<ts>.<ext>. Extensão do content-type.

speech_to_text

Transcreva áudio. Forneça exatamente um de audioPath ou audioBase64.

ParâmetroTipoPadrãoNotas
audioPathstring—Caminho de arquivo local.
audioBase64string—Payload base64.
fileNamestringderivadoUsado para o nome do arquivo no upload multipart.
modelstring—ex.: openai/whisper-1, groq/whisper-large-v3-turbo.
providerstring—Alias para model.
languagestring—Código ISO-639-1, ex.: en, vi.
promptstring—
responseFormatstringjsonjson, text, verbose_json, srt, vtt.
temperaturenumber—0–1.

embeddings

Gere embeddings para uma string ou um lote de strings.

ParâmetroTipoPadrãoObservações
inputstring | array—Obrigatório. Uma string ou um array de strings não vazias.
modelstring—Ex.: openai/text-embedding-3-small.
providerstring—Alias para model.
encodingFormatstringfloatfloat ou base64.
dimensionsnumber—Substituição opcional.

Notas de comportamento

  • Cadeia de fallback. Para toda ferramenta que usa modelo: se model/provider estiver definido, apenas esse modelo é tentado. Caso contrário, a cadeia em default_models.<tool> é tentada em ordem. Se todas as entradas falharem, a ferramenta lança um erro All models failed. Errors: ... que inclui cada mensagem por modelo.
  • provider é um alias para model em toda ferramenta que aceita um modelo. Defina o que ficar melhor para o seu caso de uso.
  • Imagem e áudio são sempre gravados em um arquivo e retornados como um bloco de conteúdo. generate_image e text_to_speech solicitam b64_json / mp3 do upstream, gravam os bytes em outputPath (ou no diretório temporário do SO se você omitir) e retornam o ativo como um bloco de conteúdo MCP image / audio além de { outputPath, bytes, contentType }. O host pode exibir inline ou apenas usar o caminho. A extensão é derivada do content-type do upstream.
  • O arquivo de configuração tem prioridade sobre variáveis de ambiente. Se você precisar de configurações diferentes para uma única execução, prefira --config em vez de exportar variáveis de ambiente.
  • Upload multipart de STT. A ferramenta envia o áudio como multipart/form-data; fileName só importa quando o provedor upstream inspeciona o nome do arquivo.
  • list_models é limitado e armazenado em cache. A ferramenta limita sua saída (padrão 20) e mantém a lista completa do upstream em memória por cerca de um minuto. Isso não é paginação no lado do servidor: /v1/models ignora parâmetros de consulta e sempre retorna o catálogo inteiro. O limite protege a janela de contexto, e o cache protege a latência, já que o 9Router reconstrói o catálogo a cada solicitação (observado ~7s, mesmo para /v1/models/<kind>, que retorna um corpo pequeno). Passe refresh: true para forçar uma nova busca.
  • A configuração é lida uma vez na inicialização. Edite config.toml ou altere NINEROUTER_URL / NINEROUTER_KEY e reinicie o servidor MCP no seu cliente. Recarga a quente não é implementada.

Solução de problemas

  • NINEROUTER_URL is required — defina a variável de ambiente ou crie ~/.config/ninerouter-mcp/config.toml com base_url.
  • No model specified and no default_models.<tool> configured — passe model na chamada ou adicione uma entrada default_models à sua configuração.
  • All models failed. Errors: ... — todo modelo de fallback retornou um erro; a mensagem agregada inclui cada um para diagnóstico.
  • Erros de autenticação (401/403) — sua instância do 9Router exige uma chave; defina NINEROUTER_KEY ou api_key no arquivo de configuração.
  • STT falha com "Provide audioPath or audioBase64" — exatamente um desses dois deve ser definido.

Desenvolvimento

npm install
npm run dev          # tsx watch mode
npm run build        # tsc -> dist/
npm start            # node dist/index.js
npm run check        # typecheck + lint + prettier --check

Estrutura do projeto:

src/
  index.ts               # bin entry; dispatches create-config or server
  server.ts              # McpServer setup
  ninerouter-client.ts   # config + HTTP helpers
  create-config.ts       # `ninerouter-mcp create-config` subcommand
  tools/
    models.ts            # list_models
    web.ts               # web_search, web_fetch
    media.ts             # generate_image, text_to_speech, speech_to_text
    embeddings.ts        # embeddings
    common.ts            # shared fallback + json helpers
config.example.toml      # sample config (mirrors create-config output)

Licença

Apache-2.0. Consulte LICENSE.