Navi MCP Server
Servidor MCP para automatizar la gestión de exposición.
Documentación
suite navi-mcp
Un servidor MCP para la CLI navi de Tenable (Tenable Vulnerability Management / Tenable One), junto con el conjunto navi-claude-skills, incluido aquí para que el servidor pueda servirlos.
La superficie de herramientas se valida contra el código fuente de navi — las
declaraciones @click.option en navi/plugins/*.py, no una captura de --help — porque el texto de ayuda
no puede mostrarte una guardia que advierte sin salir, una bandera que se ignora
silenciosamente para el selector con el que la combinaste, o un prompt que bloqueará una
llamada de herramienta. docs/gap-ledger.md lleva el rastro por hallazgo.
Estructura
server/ server.py — the MCP server (20 tools + resources)
server/tests/ argv-level check suites + run_all.py (no live tenant needed)
skills/ the 17 skills, in NAVI_SKILL_DIR layout — a vendored copy of
upstream (<skill>/SKILL.md, plus references/ on the denser ones)
tools/ navi_mcp_config.py — auto-detects paths, emits the install config
sync_skills.py — refresh skills/ from upstream, verify vs server
docs/ audit framework, gap ledger, verified findings, help-crawler,
fix-xref-prompt.md (a reported bug in the navi CLI, not this repo)
INSTALL.md step-by-step install for Claude Desktop
README.md this file
En la raíz del repositorio, pyproject.toml construye lo anterior en un paquete
instalable (navi-mcp-suite/server/ → navi_mcp/, navi-mcp-suite/skills/ →
navi_mcp/resources/skills/) sin mover ningún archivo, y fix-mcp.sh es un
script de diagnóstico que verifica toda la cadena de lanzamiento.
Las 17 habilidades
Impulsando el servidor: navi (router) · navi-core · navi-mcp ·
navi-troubleshooting · navi-acr · navi-export · navi-scan · navi-was ·
navi-action · navi-mail · navi-remote-exec · navi-explore · navi-enrich
Creación de contenido de cumplimiento Nessus: navi-audit · navi-audit-syntax ·
navi-audit-platforms · navi-audit-catalog. Estas no usan el servidor MCP,
pero el router enruta hacia ellas, así que viajan con el conjunto.
Material profundo (esquema completo, catálogo exhaustivo de selectores, ejemplos
largos trabajados) vive en references/*.md y se extrae bajo demanda.
Estas son una copia incluida. Se mantienen en
packetchaos/navi-claude-skills
y viven aquí solo para que NAVI_SKILL_DIR tenga algo que servir. Actualízalas —
y verifícalas contra la superficie real de herramientas del servidor — con:
python tools/sync_skills.py --dry-run # what would change
python tools/sync_skills.py --verify # sync, then cross-check vs server.py
--verify analiza cada llamada navi_*(...) escrita en las habilidades y marca
nombres de herramientas que el servidor no registra, argumentos de palabra clave que una
herramienta no acepta, y herramientas que ninguna habilidad documenta. Ejecútalo
siempre que cambie la superficie de herramientas: así es como
se detectó navi_action_delete(kind="scan", id=…), donde el parámetro real es
object_id.
Ejecutar el servidor MCP
El servidor invoca el binario navi y lee el navi.db local. No
gestiona claves API — configúralas fuera de banda con navi config keys
primero (ver skills/navi-core).
Requisitos
mcp >= 1.9, < 2. El límite superior no es precaución — mcp 2.0 renombró
mcp.server.fastmcp a mcp.server.mcpserver y FastMCP a MCPServer, así que
2.x falla en la importación con ModuleNotFoundError: No module named 'mcp.server.fastmcp' antes de que se registre cualquier herramienta. En Claude Desktop
eso aparece solo como "Server disconnected". No ejecutes pip install --upgrade mcp — instala
2.x. Instalar este proyecto como paquete aplica el pin por ti.
Instalación
pip install navi-mcp # from PyPI
pip install "navi-mcp[navi]" # also pulls navi-pro into the same environment
Para una instalación autocontenida que otros paquetes en el intérprete no puedan alterar — que es lo que quieres detrás de Claude Desktop — usa pipx:
pipx install "navi-mcp[navi]"
O desde el código fuente:
pip install . # from a checkout
pip install "git+https://github.com/packetchaos/navi-mcp"
Ejecución
navi-mcp # stdio (default); waits for a client
navi-mcp --http # streamable HTTP on :8000
python -m navi_mcp # equivalent entry point
Desde un checkout, sin instalar:
python navi-mcp-suite/server/server.py # stdio
python navi-mcp-suite/server/server.py --http # streamable HTTP on :8000
Variables de entorno
Cada una de estas se lee una vez, al iniciar el servidor. Cambiar cualquiera significa reiniciar el servidor (y, en Claude Desktop, salir completamente de la aplicación) — ninguna puede cambiarse desde dentro de una llamada de herramienta, que es el punto de las compuertas.
| Var | Propósito | Valor por defecto si no está definida |
|---|---|---|
NAVI_WORKDIR | Directorio que contiene navi.db y exportaciones CSV. El servidor ejecuta cada subproceso de navi con esto como su cwd. | ~/.navi-mcp — creado al inicio si falta |
NAVI_BIN | Ruta al ejecutable navi | navi (resuelto en PATH) |
NAVI_SKILL_DIR | El directorio skills/, para que los recursos navi://skill/... se resuelvan | <dir of server.py>/resources/skills. Instalado como paquete, esto resuelve a las habilidades incluidas y la variable es opcional; ejecutando desde un checkout no existe, así que los recursos de habilidades dan 404 hasta que la configures |
NAVI_SKILL_PATH | Legado: un único SKILL.md monolítico. Configurarlo pone al servidor en modo de archivo único y NAVI_SKILL_DIR se ignora. Prefiere NAVI_SKILL_DIR. | sin definir |
NAVI_MCP_ALLOW_WRITES | 1 abre la compuerta maestra de escritura (ver abajo) | sin definir → solo lectura |
NAVI_EMAIL | 1 habilita navi_action_mail. Se apila sobre la compuerta de escritura. | sin definir → desactivado |
NAVI_REMOTE_CODE_EXECUTION | 1 habilita navi_action_push. Se apila sobre la compuerta de escritura. | sin definir → desactivado |
Trampa de primera instalación.
NAVI_WORKDIRpor defecto es~/.navi-mcp, no tu directorio actual. La CLI de navi escribenavi.dben el directorio desde el que la ejecutaste, así que si dejasNAVI_WORKDIRsin definir, el servidor creará silenciosamente un~/.navi-mcpvacío, no encontrará base de datos allí, y cada lectura volverá vacía — pareciendo un tenant roto en lugar de una ruta incorrecta. Leenavi://workdirprimero: imprime el workdir resuelto y sinavi.dbestá realmente presente.
Apunta NAVI_SKILL_DIR a la carpeta skills/ de este repositorio. El servidor lee
carpetas de habilidades desempaquetadas, no zips empaquetados de .skill/.plugin.
Las compuertas
Tres capas independientes. Una herramienta se ejecuta solo cuando cada capa que
le aplica está satisfecha; están ANDed, nunca ORed.
Layer 1 NAVI_MCP_ALLOW_WRITES=1 master write gate server env, restart
Layer 2 NAVI_EMAIL=1 email capability server env, restart
NAVI_REMOTE_CODE_EXECUTION=1 remote-exec capability server env, restart
Layer 3 confirm=True per-call intent in the tool call
Capa 1 — la compuerta maestra de escritura. Desactivada por defecto, así que una
instalación nueva es de solo lectura y segura para apuntar a producción. Abrirla habilita
todo lo que cambia estado en tu tenant de Tenable: etiquetado, ACR, importación de
activos, control de escaneos, lanzamientos WAS, eliminaciones, rotación de claves,
cancelación de exportaciones, navi_config(kind='url'),
y navi_explore_api POST/PUT. También cubre navi_config_rebuild — esa
destruye datos locales en lugar de datos del tenant (ver abajo), pero es lo
suficientemente destructiva como para estar detrás del mismo interruptor.
Capa 2 — compuertas de capacidad. Dos capacidades son peligrosas de maneras que las escrituras ordinarias de plataforma no son, así que cada una necesita su propia aceptación separada además de la capa 1. Abrir la compuerta de escritura sola no habilita ninguna:
NAVI_EMAIL=1→navi_action_mailpuede enviar correo como tú. También necesita SMTP configurado fuera de banda víanavi config smtp. Arnés:skills/navi-mail.NAVI_REMOTE_CODE_EXECUTION=1→navi_action_pushpuede ejecutar comandos de shell en hosts remotos. También necesita credenciales SSH víanavi config ssh. Esta es la capacidad de mayor riesgo en navi. Arnés:skills/navi-remote-exec.
Capa 3 — confirm=True. Una bandera por llamada en cada herramienta con compuerta.
Las capas 1 y 2 son decisiones permanentes tomadas una vez por el operador; la capa 3 es
una decisión sobre esta llamada específica, y la convención es que el modelo narra
exactamente lo que está a punto de hacer y obtiene una respuesta humana antes de pasarla.
Como vive en la llamada de herramienta en lugar del entorno, es la única capa que un
modelo puede satisfacer por sí solo — que es precisamente por qué nunca es la única capa
para nada que toque el tenant.
Qué necesita qué
| Herramienta | Compuerta de escritura | Compuerta de capacidad | confirm=True |
|---|---|---|---|
navi_enrich_tag, navi_enrich_acr, navi_enrich_add | ✅ | — | ✅ |
navi_scan (crear/iniciar/detener/pausar/reanudar) | ✅ | — | ✅ |
navi_was (escanear/iniciar/subir) | ✅ | — | ✅ |
navi_action_delete, navi_action_rotate, navi_action_cancel | ✅ | — | ✅ |
navi_config(kind='url') | ✅ | — | ✅ |
navi_explore_api POST/PUT | ✅ | — | ✅ |
navi_config_rebuild | ✅ | — | ✅ |
navi_action_mail | ✅ | NAVI_EMAIL=1 | ✅ |
navi_action_push | ✅ | NAVI_REMOTE_CODE_EXECUTION=1 | ✅ |
navi_explore_query no-SELECT | — | — | ✅ |
todo lo demás (lecturas, exportaciones, navi_explore_api GET, cifrar/descifrar) | — | — | — |
Dos asimetrías que vale la pena conocer en lugar de descubrir:
navi_explore_queryno-SELECT es solo confirmación. UnDELETE/DROPa través de ella golpea tu navi.db local, nunca el tenant, así que está fuera de la compuerta de escritura — pero es destructiva, y a diferencia denavi_config_rebuildnada más queconfirm=Truese interpone frente a ella. Si quieres una base de datos local estrictamente de solo lectura además de un tenant de solo lectura, eso no es lo que la compuerta de escritura te da hoy.- El
confirm=Truedenavi_config_rebuildestá haciendo trabajo literal. El propio camino-rebuildde navi llama aclick.confirm()antes de soltar la tabla. Bajo MCP, stdin está cerrado, así que ese prompt abortaría el comando — el servidor lo responde en tu nombre. Tuconfirm=Truees la "y" que se está escribiendo. Por eso la herramienta se niega sin ella en lugar de tratarla como una formalidad.
Solo lectura por defecto
Sin variables de entorno configuradas más allá de NAVI_WORKDIR y NAVI_BIN, el
servidor expone solo lecturas. Esa es la postura inicial recomendada: conéctalo,
lee navi://workdir, ejecuta una consulta o dos, y abre compuertas deliberadamente una vez
que confíes en a dónde está apuntado.
Herramientas destructivas
Solo dos herramientas destruyen algo, y ninguna toca Tenable:
navi_config_rebuild— HACE DROP de una tabla localassetsovulns, la re-crea, y re-descarga. Nada en Tenable VM cambia; lo que pierdes es el caché local y las horas que tomó construirlo en un tenant grande. Las tablas derivadas de esas (certs,software,vuln_route,vuln_paths) se vuelven obsoletas en el mismo momento — el_noticede la herramienta nombra las llamadas que refrescan cada una. AnotadodestructiveHint=True, quenavi_config_updatedeliberadamente no es: una actualización se fusiona en la tabla existente y nunca hace drop.navi_action_delete— elimina etiquetas, usuarios, escaneos, activos, grupos objetivo, grupos de usuarios, o etiquetas TONE en el tenant. Con compuerta de escritura y confirmación.
Reconstruir ambas tablas a la vez es navi config update full -rebuild en la CLI;
full no se expone como herramienta porque se ejecuta durante horas de todos modos.
Instalar en Claude Desktop
Guía completa en INSTALL.md. La versión corta — instala el paquete, luego apunta la configuración al script de consola:
pip install ".[navi]"
which navi-mcp # absolute path for "command"
{
"mcpServers": {
"navi": {
"command": "/absolute/path/to/navi-mcp",
"env": {
"NAVI_WORKDIR": "/absolute/path/to/folder-with-navi.db",
"NAVI_MCP_ALLOW_WRITES": "0",
"NAVI_EMAIL": "0",
"NAVI_REMOTE_CODE_EXECUTION": "0"
}
}
}
}
Sin args, sin NAVI_SKILL_DIR (las habilidades viajan en el paquete), y sin
NAVI_BIN cuando navi se instala junto vía el extra [navi]. Usa una
ruta absoluta — Claude Desktop no tendrá el PATH de tu shell.
¿Ejecutando desde un checkout en su lugar? Deja que el helper descubra las rutas, ejecuta con el intérprete que quieras que Claude Desktop use:
python tools/navi_mcp_config.py # print the mcpServers JSON
python tools/navi_mcp_config.py --write # merge into your config (backs up first)
Las banderas de compuerta en el helper mapean uno a uno a las variables de entorno de arriba:
--allow-writes, --allow-email, --allow-remote-code-execution. Las últimas dos
no tienen efecto sin la primera.
Después de editar la configuración, sal completamente y reabre Claude Desktop, luego lee
navi://workdir para confirmar que se conectó.
Recursos
navi://schema/{table}— definiciones de columnas en vivo para una tabla navi.dbnavi://workdir— workdir resuelto, presencia/tamaño/frescura denavi.db, los tres estados de compuerta, binario navi, presupuesto de llamadas, y estado del directorio de habilidadesnavi://skill/{name}— carga una habilidad (router/core/mcp/…); lista sus referenciasnavi://skill/{name}/{ref}— carga una referencia incluida (p. ej.navi://skill/core/schema)
Más el prompt navi_workflow, que inyecta la habilidad del router.
Operaciones de larga duración
Las exportaciones de navi pueden ejecutarse durante decenas de minutos en tenants grandes —
más allá del techo de ~4 minutos de llamada de herramienta del host MCP. El servidor aplica
un presupuesto de llamadas (~220s) y devuelve un error limpio nombrando el comando CLI exacto
para ejecutar en su lugar, con el mismo alcance que la llamada que expiró. Las sincronizaciones
fundacionales (navi config update full) siguen siendo intencionalmente solo CLI. La palanca principal
para encajar una sincronización dentro del presupuesto es el alcance: days, since, severity,
plugin_id, o un par de etiquetas category/value en navi_config_update. Ver
skills/navi-core y skills/navi-troubleshooting.
Pruebas
python server/tests/run_all.py # summary
python server/tests/run_all.py -v # every check
Las suites simulan el subproceso de navi y verifican el argv que cada herramienta construye,
por lo que no necesitan tenant, ni claves de API, ni navi.db. NAVI_WORKDIR se
redirige a un directorio temporal y el binario real de navi nunca se invoca:
es seguro ejecutarlas contra una instalación de producción. Ejecútalas después de instalar en una
máquina nueva: detectarán un SDK de mcp roto, un Python demasiado antiguo para la sintaxis
de tipos, o un checkout incompleto antes de conectar un cliente.
Instalando las skills como skills de Claude
Instálalas desde
packetchaos/navi-claude-skills,
que genera un paquete navi-skills.plugin para Claude.ai / Claude Cowork /
Claude Code. Este repositorio ya no incluye copias empaquetadas: un segundo canal de
distribución es una segunda cosa que olvidar actualizar, y es precisamente así como
las skills aquí terminaron describiendo un servidor que había avanzado sin ellas. La
carpeta skills/ se mantiene porque el servidor MCP la lee directamente.
Estado de validación
server.py compila limpiamente, cada herramienta está anotada, las 20 se registran y las
suites en server/tests/ están en verde. Las anotaciones de herramientas requieren mcp >= 1.9;
mcp.types.ToolAnnotations se importa detrás de un try/except para que un SDK
más antiguo degrade a herramientas sin anotar en lugar de fallar. Un SDK 2.x no degrada
de forma elegante: falla directamente, por eso la dependencia está fijada en <2.
No se ha probado en tiempo de ejecución contra un tenant de Tenable en vivo. Las comprobaciones
verifican lo que el servidor le pide a navi que haga; no pueden verificar lo que navi y la
API de Tenable hacen en respuesta. Antes de confiar en ello, valida con una lectura en vivo:
navi_explore_data(subcommand="cve", cve="CVE-2021-44228") — y lee
navi://workdir para confirmar que el directorio de trabajo y los estados de gate son los que pretendías.
Consulta docs/verified-findings.md para el inventario por error y
docs/gap-ledger.md para el registro de auditoría completo.