nan-mcp-server
# NaN MCP Server
[](https://www.npmjs.com/package/nan-mcp-server)
[](https://www.npmjs.com/package/nan-mcp-server)

[](https://github.com/luciferfran/nan-mcp-server/actions/workflows/ci.yml)

[](https://modelcontextprotocol.io)
Servidor MCP (Model Context Protocol) que expone las herramientas de media de la [API de NaN](https://nan.builders) (`api.nan.builders`) para cualquier cliente compatible con MCP.
Al ser un estándar abierto, funciona con **opencode**, **Claude Code**, **Codex**, **Pi**, **Cursor**, **Windsurf**, **Zed**, etc.
## Herramientas
| Herramienta | Descripción | Modelo |
|---|---|---|
| `generate_image` | Generar imagen desde texto | `flux-2-klein` |
| `edit_image` | Editar imagen (imagen→imagen) | `flux-2-klein` |
| `text_to_speech` | Sintetizar audio desde texto | `kokoro` |
| `list_voices` | Listar voces kokoro por idioma | — |
| `speech_to_text` | Transcribir audio a texto | `whisper` |
| `embed_text` | Embeddings vectoriales (4096 dims) | `qwen3-embedding` |
| `rerank_documents` | Reordenar documentos por relevancia (RAG) | `rerank` |
| `list_models` | Listar modelos disponibles con tu key | — |
## Requisitos
- Node.js >= 18
- Una API key de [NaN](https://nan.builders) (`sk-...`)
## Instalación
El paquete se distribuye por [npm](https://www.npmjs.com/package/nan-mcp-server). La forma más simple de usarlo en cualquier cliente MCP es **sin instalarlo**: `npx` lo ejecuta al vuelo.
```bash
export NAN_API_KEY="sk-tu-key-aqui"
npx -y nan-mcp-server@1.2.0
```
Con otro gestor de paquetes, si ya lo usas:
```bash
pnpm dlx nan-mcp-server@1.2.0 # pnpm
yarn dlx nan-mcp-server@1.2.0 # yarn
bunx nan-mcp-server@1.2.0 # bun
```
O instálalo globalmente:
```bash
npm install -g nan-mcp-server@1.2.0 # o: pnpm add -g / bun add -g
nan-mcp-server
```
> **Sobre la versión fijada**: los ejemplos fijan una versión exacta en lugar de `@latest`, a propósito. Con `@latest`, cada arranque descarga la última versión publicada, así que cualquier versión futura —incluida una publicada por una cuenta comprometida— se ejecutaría en tu máquina automáticamente. Fijar la versión te deja decidir cuándo actualizar; consulta las [releases](https://github.com/luciferfran/nan-mcp-server/releases) y sube el número cuando quieras. Si prefieres actualizaciones automáticas, sustituye la versión por `@latest` en cualquiera de los ejemplos.
## Configuración
El servidor se ejecuta vía **stdio** (proceso local). Solo necesita una variable de entorno: `NAN_API_KEY`. Sin ella arranca igualmente y publica su catálogo —para que cualquier inspector pueda leerlo—, pero toda herramienta que llame a la API falla indicando que falta.
Las imágenes y audios generados se guardan en `~/nan-mcp-output/` (configurable con `NAN_OUTPUT_DIR`).
### Configuración por cliente
<details>
<summary>opencode</summary>
Añade a tu `opencode.jsonc` (o créalo en `~/.config/opencode/`):
```jsonc
{
"mcp": {
"nan-media": {
"type": "local",
"command": ["npx", "-y", "nan-mcp-server@1.2.0"],
"environment": {
"NAN_API_KEY": "{env:NAN_API_KEY}"
}
}
}
}
```
</details>
<details>
<summary>Claude Code</summary>
**Instalar vía CLI:**
```bash
claude mcp add nan-media --scope user -e NAN_API_KEY='${NAN_API_KEY}' -- \
npx -y nan-mcp-server@1.2.0
```
**O en `.mcp.json`:**
```json
{
"mcpServers": {
"nan-media": {
"type": "stdio",
"command": "npx",
"args": ["-y", "nan-mcp-server@1.2.0"],
"env": {
"NAN_API_KEY": "${NAN_API_KEY}"
}
}
}
}
```
</details>
<details>
<summary>Codex</summary>
En `~/.codex/config.toml`:
```toml
[mcp_servers.nan-media]
command = "npx"
args = ["-y", "nan-mcp-server@1.2.0"]
env_vars = ["NAN_API_KEY"]
```
> **`env_vars` no es opcional**: codex no propaga su propio entorno a los servidores MCP, así que sin esa línea el servidor arranca sin `NAN_API_KEY` y cada llamada falla con «NAN_API_KEY environment variable is required». `env_vars` nombra las variables que debe heredar; `env` solo admite valores literales, que no conviene escribir en un archivo versionado.
</details>
<details>
<summary>Pi</summary>
Pi usa [`pi-mcp-adapter`](https://github.com/nicobailon/pi-mcp-adapter) y lee los archivos MCP estándar. Instala el adaptador:
```bash
pi install npm:pi-mcp-adapter
```
Crea `~/.config/mcp/mcp.json` (config compartido MCP estándar):
```json
{
"mcpServers": {
"nan-media": {
"command": "npx",
"args": ["-y", "nan-mcp-server@1.2.0"],
"env": {
"NAN_API_KEY": "$env:NAN_API_KEY"
}
}
}
}
```
> La key se interpola con `$env:NAN_API_KEY`, así que ningún secreto queda en el archivo.
Para usar los modelos de NaN en Pi, define el proveedor en `~/.pi/agent/models.json`:
```json
{
"providers": {
"nan": {
"baseUrl": "https://api.nan.builders/v1",
"api": "openai-completions",
"apiKey": "$NAN_API_KEY",
"models": [
{ "id": "deepseek-v4-flash", "name": "DeepSeek V4 Flash", "reasoning": true, "input": ["text", "image"], "contextWindow": 1048576 },
{ "id": "qwen3.6", "name": "Qwen 3.6", "reasoning": true, "input": ["text", "image"], "contextWindow": 262144 }
]
}
}
}
```
Luego usa `--provider nan --model <id>` (p.ej. `pi --provider nan --model deepseek-v4-flash`).
</details>
<details>
<summary>Cursor / Windsurf / Zed</summary>
En la configuración de MCP del cliente, añade un servidor stdio:
```
Comando: npx -y nan-mcp-server@1.2.0
Variables: NAN_API_KEY=tu-clave-de-nan-builders (no la incluyas en el config versionado)
```
</details>
## Uso
Una vez conectado, pide al agente:
- "Genera una imagen de un faro al atardecer con nan-media"
- "Sintetiza en español: Hola mundo, voz ef_dora"
- "Transcribe el audio /ruta/audio.mp3"
- "Reordena estos documentos según la query X"
## Límites de la API
| Recurso | Límite |
|---|---|
| Generación/edición de imágenes | 100 req/mes por usuario, 1 req/s (burst 3) |
| Tamaño máximo archivo (STT / edit_image) | 25 MB por archivo |
| Audios para transcripción | máx. ~2 min por archivo (timeout 524 si supera) |
| Imágenes de referencia (edit_image) | hasta 4 |
## Variables de entorno
| Variable | Obligatoria | Descripción |
|---|---|---|
| `NAN_API_KEY` | Sí, para llamar a la API | API key de NaN. Sin ella el servidor arranca y lista sus herramientas, pero solo `list_voices` responde |
| `NAN_BASE_URL` | No | Base URL de la API (default `https://api.nan.builders/v1`) |
| `NAN_OUTPUT_DIR` | No | Directorio de salida (default `~/nan-mcp-output`) |
| `NAN_TIMEOUT_MS` | No | Timeout por petición en ms (default `180000`, 3 min) |
## Desarrollo
### Estructura
```
nan-mcp-server/
├── server.js # Servidor MCP + herramientas
├── test/server.test.js # Tests (node:test, sin dependencias extra)
├── .github/workflows/ # ci.yml (tests) + publish.yml (npm)
├── package.json
└── README.md
```
### Testing
Los tests usan el test runner nativo de Node (`node:test`), sin dependencias adicionales. No hacen llamadas a la API (usan un valor de prueba para `NAN_API_KEY`), así que se ejecutan sin red ni credenciales.
```bash
npm test
```
Para probar el servidor manualmente contra la API real (requiere key):
```bash
NAN_API_KEY=sk-tu-key-aqui node server.js
```
Y luego una llamada de ejemplo vía stdio:
```bash
printf '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}\n{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}\n' \
| node server.js
```
### Publicación / CI
- El código no contiene secretos: `NAN_API_KEY` se lee solo del entorno.
- El `.gitignore` excluye `node_modules/`, logs y `.env`.
- `.github/workflows/ci.yml` ejecuta los tests en cada push y PR a `main` sobre Node 18, 20, 22 y 24, más un job `strict-deps` con pnpm: su `node_modules` sin hoisting hace fallar cualquier import de un paquete no declarado en `package.json` (npm lo dejaría pasar silenciosamente).
- `.github/workflows/publish.yml` publica en npm al crear un release en GitHub, vía trusted publishing (OIDC), sin token en secrets.
## Notas
- Las imágenes y audios se guardan en `~/nan-mcp-output/` (configurable con `NAN_OUTPUT_DIR`). Los nombres se sanitizan (sin path traversal) y nunca se sobrescriben archivos existentes: si el nombre ya está ocupado se añade `-2`, `-3`, etc.
- Los archivos de entrada (STT / edit_image) se cargan en memoria; para archivos muy grandes conviene dividirlos.
- El servidor no contiene ningún secreto en el código: solo lee `NAN_API_KEY` del entorno.
## Licencia
MIT — ver [LICENSE](LICENSE).
TDQS
Scored across 8 tools
Each tool targets a distinct capability: image generation, image editing, TTS, STT, embedding, reranking, and listing models/voices. The two image tools are explicitly differentiated by starting point, and the TTS/STT pair is clearly opposite. No ambiguity.
All tool names use lowercase snake_case and follow a verb_noun pattern (generate_image, list_voices, embed_text, rerank_documents, edit_image) or clear compound actions (text_to_speech, speech_to_text). The style is uniform and predictable.
With 8 tools, the server covers a broad but focused set of AI capabilities—image, audio, and text embeddings/reranking—without excess. Each tool has a clear purpose and the count is well within the ideal 3-15 range.
The tool surface covers the core lifecycle for the intended AI operations: generation and editing for images, synthesis and transcription for audio, and embedding plus reranking for RAG pipelines. No obvious missing operations for the stated domain.