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
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):
- Flag de CLI
--config <path>(ou env--config-file,-c,NINEROUTER_CONFIG) ~/.config/ninerouter-mcp/config.toml- 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âmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
kind | string | não | Um de chat, image, tts, embedding, web, stt, image-to-text. Omita para modelos de chat padrão. |
search | string | não | Correspondência de substring sem diferenciar maiúsculas/minúsculas contra IDs/nomes de modelos. |
limit | number | não | Tamanho da página (padrão 20, máximo 500). Use 0 para a lista completa. |
offset | number | não | Índice do primeiro modelo a retornar (padrão 0). Use nextOffset para paginar. |
refresh | boolean | não | Ignora 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âmetro | Tipo | Padrão | Notas |
|---|---|---|---|
query | string | — | Obrigatório. |
model | string | — | ID do modelo 9Router (ex.: tavily/search). Faz fallback para provider, depois default_models.web_search. |
provider | string | — | Alias para model. |
maxResults | number | 5 | 1–20. |
searchType | string | web | web ou news. |
country | string | — | |
language | string | — | |
timeRange | string | — | |
domainFilter | string | — |
web_fetch
Busque uma URL e retorne-a como markdown, texto ou HTML.
| Parâmetro | Tipo | Padrão | Notas |
|---|---|---|---|
url | string | — | Obrigatório. Deve ser uma URL válida. |
model | string | — | ex.: jina-reader/fetch, firecrawl/fetch. |
provider | string | — | Alias para model. |
format | string | markdown | markdown, text ou html. |
maxCharacters | number | 8000 | Limite 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âmetro | Tipo | Padrão | Notas |
|---|---|---|---|
prompt | string | — | Obrigatório. |
model | string | — | ex.: openai/dall-e-3, gemini/gemini-3-pro-image-preview. |
provider | string | — | Alias para model. |
n | number | 1 | 1–10. |
size | string | 1024x1024 | |
quality | string | — | standard ou hd. |
outputPath | string | tmpdir do SO | Onde 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âmetro | Tipo | Padrão | Notas |
|---|---|---|---|
input | string | — | Obrigatório. |
model | string | — | ex.: openai/tts-1, edge-tts/vi-VN-HoaiMyNeural. |
provider | string | — | Alias para model. |
outputPath | string | tmpdir do SO | Onde 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âmetro | Tipo | Padrão | Notas |
|---|---|---|---|
audioPath | string | — | Caminho de arquivo local. |
audioBase64 | string | — | Payload base64. |
fileName | string | derivado | Usado para o nome do arquivo no upload multipart. |
model | string | — | ex.: openai/whisper-1, groq/whisper-large-v3-turbo. |
provider | string | — | Alias para model. |
language | string | — | Código ISO-639-1, ex.: en, vi. |
prompt | string | — | |
responseFormat | string | json | json, text, verbose_json, srt, vtt. |
temperature | number | — | 0–1. |
embeddings
Gere embeddings para uma string ou um lote de strings.
| Parâmetro | Tipo | Padrão | Observações |
|---|---|---|---|
input | string | array | — | Obrigatório. Uma string ou um array de strings não vazias. |
model | string | — | Ex.: openai/text-embedding-3-small. |
provider | string | — | Alias para model. |
encodingFormat | string | float | float ou base64. |
dimensions | number | — | Substituição opcional. |
Notas de comportamento
- Cadeia de fallback. Para toda ferramenta que usa modelo: se
model/providerestiver definido, apenas esse modelo é tentado. Caso contrário, a cadeia emdefault_models.<tool>é tentada em ordem. Se todas as entradas falharem, a ferramenta lança um erroAll models failed. Errors: ...que inclui cada mensagem por modelo. provideré um alias paramodelem 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_imageetext_to_speechsolicitamb64_json/mp3do upstream, gravam os bytes emoutputPath(ou no diretório temporário do SO se você omitir) e retornam o ativo como um bloco de conteúdo MCPimage/audioalém de{ outputPath, bytes, contentType }. O host pode exibir inline ou apenas usar o caminho. A extensão é derivada docontent-typedo 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
--configem vez de exportar variáveis de ambiente. - Upload multipart de STT. A ferramenta envia o áudio como
multipart/form-data;fileNamesó importa quando o provedor upstream inspeciona o nome do arquivo. list_modelsé limitado e armazenado em cache. A ferramenta limita sua saída (padrão20) 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/modelsignora 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). Passerefresh: truepara forçar uma nova busca.- A configuração é lida uma vez na inicialização. Edite
config.tomlou altereNINEROUTER_URL/NINEROUTER_KEYe 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.tomlcombase_url.No model specified and no default_models.<tool> configured— passemodelna chamada ou adicione uma entradadefault_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_KEYouapi_keyno 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.