9Router MCP Server

Servidor MCP para 9Router: expone búsqueda web, recuperación web, TTS y otras capacidades como herramientas nativas, eliminando la sobrecarga por llamada de los enfoques basados en archivos de habilidades (relectura de instrucciones, formato manual, reintento ante errores) en favor de llamadas estructuradas a herramientas a través de stdio.

Documentación

9Router MCP Server

CI npm version Node

Servidor MCP que expone las capacidades de 9Router como herramientas nativas para cualquier cliente MCP: descubrimiento de modelos, respaldo automático y entradas validadas con Zod.

Estado: 9Router ya oculta la complejidad específica de cada proveedor detrás de una única API. Este servidor expone esa API a través de MCP, para que agentes y aplicaciones puedan llamar a búsqueda web, recuperación web, generación de imágenes, TTS, STT y embeddings como herramientas MCP estándar — sin cargar archivos de habilidades, sin código de integración por proveedor.

Por qué usarlo

  • Las herramientas siempre están registradas; no hay carga manual de habilidades (ahorra tokens y contexto).
  • Respaldo automático de modelo cuando el modelo principal falla.
  • Entradas validadas con Zod con mensajes de error claros antes de cualquier llamada de red.
  • Un solo archivo de configuración para endpoint, autenticación y modelos predeterminados con cadenas de respaldo.
  • Transporte único (stdio); funciona con cualquier cliente compatible con MCP.

El chat / la generación de código están intencionalmente excluidos — para eso está el modelo anfitrión.

Contenido

Instalación

El paquete es ninerouter-mcp en npm. El cuerpo JSON es idéntico en todos los clientes MCP — solo la clave de nivel superior y la ruta del archivo difieren. Pega el bloque en la clave correcta de la configuración de tu cliente:

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

Claves de nivel superior por cliente: VS Code (servers), OpenCode (mcp, renombra env → environment, establece type: "local" y enabled: true), Claude Code / Cursor / Windsurf / Claude Desktop / Zed (mcpServers o context_servers, elimina la línea type). JetBrains usa un diálogo de interfaz en Settings → Tools → AI Assistant → MCP con el mismo comando, argumentos y entorno.

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

Añade a ~/.hermes/config.yaml:

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

Configuración

El servidor necesita una URL base de 9Router. Opcionalmente acepta una clave de API y respaldos de modelo predeterminado para cada herramienta.

Fuentes, en orden de prioridad (la más alta primero):

  1. Indicador de línea de comandos --config <path> (o entorno --config-file, -c, NINEROUTER_CONFIG)
  2. ~/.config/ninerouter-mcp/config.toml
  3. Variables de entorno: NINEROUTER_URL, NINEROUTER_KEY

Si el archivo de configuración existe, tiene prioridad sobre las variables de entorno.

Configuración rápida

Genera un archivo de configuración inicial y edítalo:

npx ninerouter-mcp create-config

Esto escribe ~/.config/ninerouter-mcp/config.toml y se niega a sobrescribir un archivo existente.

Configuración manual (variables de entorno)

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 es opcional y solo se requiere cuando tu instancia de 9Router tiene la autenticación habilitada.

Configuración manual (archivo de configuración)

# 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

La tabla ninerouter también se acepta como alias para base_url y api_key de nivel superior:

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

Apunta a un archivo de configuración no predeterminado:

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

Ejecución

Después de npm install desde este repositorio:

npm run build
npm start

O en modo de observación durante el desarrollo:

npm run dev

Los usuarios del paquete publicado pueden ejecutarlo directamente:

npx -y ninerouter-mcp

Herramientas

Cada herramienta se registra con el servidor MCP al inicio. Salvo que se indique lo contrario, todas las herramientas devuelven un único bloque de contenido de texto con JSON impreso de forma legible.

list_models

Consulta los identificadores de modelo expuestos por 9Router. Esta herramienta es opcional: todas las demás funcionan sin ella, porque cada una tiene un modelo predeterminado configurado o una cadena de respaldo. Llámala solo para apuntar a un modelo específico o para descubrir identificadores que difieren de los predeterminados. Filtra por search, luego pagina entre las coincidencias con offset/limit, de modo que un catálogo grande no pueda inundar la ventana de contexto. Cada respuesta informa total, count, offset y nextOffset (omitido en la última página). La lista ascendente se almacena en caché durante aproximadamente un minuto, porque 9Router reconstruye todo el catálogo en cada solicitud (varios segundos), por lo que solo la primera llamada es lenta.

ParámetroTipoObligatorioDescripción
kindstringnoUno de chat, image, tts, embedding, web, stt, image-to-text. Omítelo para los modelos de chat predeterminados.
searchstringnoCoincidencia de subcadena sin distinción de mayúsculas/minúsculas contra identificadores/nombres de modelo.
limitnumbernoTamaño de página (predeterminado 20, máximo 500). Usa 0 para la lista completa.
offsetnumbernoÍndice del primer modelo a devolver (predeterminado 0). Usa nextOffset para paginar.
refreshbooleannoOmite la caché y vuelve a obtener de 9Router.

Los valores predeterminados se pueden sobrescribir en config.toml:

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

Valores predeterminados integrados (usados cuando se omite una clave): limit = 20, offset = 0, cache_ttl_seconds = 60.

web_search

Busca en la web a través de 9Router.

ParámetroTipoPredeterminadoNotas
querystring—Obligatorio.
modelstring—Identificador de modelo de 9Router (p. ej. tavily/search). Se respalda en provider, luego en default_models.web_search.
providerstring—Alias para model.
maxResultsnumber51–20.
searchTypestringwebweb o news.
countrystring—
languagestring—
timeRangestring—
domainFilterstring—

web_fetch

Recupera una URL y la devuelve como markdown, texto o HTML.

ParámetroTipoPredeterminadoNotas
urlstring—Obligatorio. Debe ser una URL válida.
modelstring—p. ej. jina-reader/fetch, firecrawl/fetch.
providerstring—Alias para model.
formatstringmarkdownmarkdown, text o html.
maxCharactersnumber8000Límite de truncamiento.

generate_image

Generación de texto a imagen. Siempre escribe un archivo y devuelve la imagen como bloque de contenido base64 más { outputPath, bytes, contentType }. Omite outputPath para escribir en el directorio temporal del sistema operativo.

ParámetroTipoPredeterminadoNotas
promptstring—Obligatorio.
modelstring—p. ej. openai/dall-e-3, gemini/gemini-3-pro-image-preview.
providerstring—Alias para model.
nnumber11–10.
sizestring1024x1024
qualitystring—standard o hd.
outputPathstringtmpdir del SODónde escribir el archivo. Predeterminado os.tmpdir()/ninerouter-<slug>-<ts>.<ext>. Extensión desde el tipo de contenido.

text_to_speech

Sintetiza audio. Siempre escribe un archivo y devuelve el audio como bloque de contenido base64 más { outputPath, bytes, contentType }. Omite outputPath para escribir en el directorio temporal del sistema operativo.

ParámetroTipoPredeterminadoNotas
inputstring—Obligatorio.
modelstring—p. ej. openai/tts-1, edge-tts/vi-VN-HoaiMyNeural.
providerstring—Alias para model.
outputPathstringtmpdir del SODónde escribir el archivo. Predeterminado os.tmpdir()/ninerouter-<slug>-<ts>.<ext>. Extensión desde el tipo de contenido.

speech_to_text

Transcribe audio. Proporciona exactamente uno de audioPath o audioBase64.

ParámetroTipoPredeterminadoNotas
audioPathstring—Ruta de archivo local.
audioBase64string—Carga útil base64.
fileNamestringderivadoSe usa para el nombre de archivo de la carga multiparte.
modelstring—p. ej. openai/whisper-1, groq/whisper-large-v3-turbo.
providerstring—Alias para model.
languagestring—Código ISO-639-1, p. ej. en, vi.
promptstring—
responseFormatstringjsonjson, text, verbose_json, srt, vtt.
temperaturenumber—0–1.

embeddings

Genera embeddings para una cadena o un lote de cadenas.

ParámetroTipoPredeterminadoNotas
inputstring | array—Obligatorio. O un solo string o un array de strings no vacíos.
modelstring—p. ej. openai/text-embedding-3-small.
providerstring—Alias de model.
encodingFormatstringfloatfloat o base64.
dimensionsnumber—Anulación opcional.

Notas de comportamiento

  • Cadena de respaldo. Para cada herramienta que usa modelos: si model/provider está definido, solo se prueba ese modelo. De lo contrario, se prueba la cadena en default_models.<tool> en orden. Si todas las entradas fallan, la herramienta lanza un error All models failed. Errors: ... que incluye cada mensaje por modelo.
  • provider es un alias de model en cada herramienta que acepta un modelo. Usa el que se lea mejor para tu caso de uso.
  • Las imágenes y el audio siempre se escriben en un archivo y se devuelven como un bloque de contenido. generate_image y text_to_speech solicitan b64_json / mp3 al proveedor, escriben los bytes en outputPath (o en el directorio temporal del sistema si lo omites) y devuelven el recurso como un bloque de contenido MCP image / audio además de { outputPath, bytes, contentType }. El host puede mostrarlo en línea o simplemente usar la ruta. La extensión se deriva del content-type del proveedor.
  • El archivo de configuración tiene prioridad sobre las variables de entorno. Si necesitas ajustes diferentes para una sola ejecución, prefiere --config sobre exportar variables de entorno.
  • Carga multiparte de STT. La herramienta envía el audio como multipart/form-data; fileName solo importa cuando el proveedor inspecciona el nombre del archivo.
  • list_models se recorta y se almacena en caché. La herramienta limita su salida (predeterminado 20) y mantiene la lista completa del proveedor en memoria durante aproximadamente un minuto. Esto no es paginación del lado del servidor: /v1/models ignora los parámetros de consulta y siempre devuelve el catálogo completo. El límite protege la ventana de contexto y la caché protege la latencia, ya que 9Router reconstruye el catálogo en cada solicitud (observado ~7s, incluso para /v1/models/<kind>, que devuelve un cuerpo pequeño). Pasa refresh: true para forzar una nueva obtención.
  • La configuración se lee una vez al inicio. Edita config.toml o cambia NINEROUTER_URL / NINEROUTER_KEY, luego reinicia el servidor MCP en tu cliente. La recarga en caliente no está implementada.

Solución de problemas

  • NINEROUTER_URL is required — define la variable de entorno o crea ~/.config/ninerouter-mcp/config.toml con base_url.
  • No model specified and no default_models.<tool> configured — o pasa model en la llamada o añade una entrada default_models a tu configuración.
  • All models failed. Errors: ... — cada modelo de respaldo devolvió un error; el mensaje agregado incluye cada uno para el diagnóstico.
  • Errores de autenticación (401/403) — tu instancia de 9Router requiere una clave; define NINEROUTER_KEY o api_key en el archivo de configuración.
  • STT falla con "Provide audioPath or audioBase64" — exactamente uno de esos dos debe estar definido.

Desarrollo

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

Estructura del proyecto:

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)

Licencia

Apache-2.0. Consulta LICENSE.