Navi MCP Server
Servidor MCP para automatizar o gerenciamento de exposição.
Documentação
Suíte navi-mcp
Um servidor MCP para o CLI navi da Tenable (Tenable Vulnerability Management / Tenable One), além do conjunto complementar navi-claude-skills, fornecido aqui para que o servidor possa servi-los.
A superfície de ferramentas é validada contra a fonte do navi — as declarações @click.option
em navi/plugins/*.py, não uma captura de --help — porque o texto de ajuda
não pode mostrar uma proteção que avisa sem sair, uma flag que é silenciosamente
ignorada para o seletor com o qual você a combinou, ou um prompt que causará deadlock em uma
chamada de ferramenta. docs/gap-ledger.md carrega o rastro por descoberta.
Estrutura
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
Na raiz do repositório, pyproject.toml compila o acima em um pacote instalável
(navi-mcp-suite/server/ → navi_mcp/, navi-mcp-suite/skills/ →
navi_mcp/resources/skills/) sem mover arquivos, e fix-mcp.sh é um
script de diagnóstico que verifica toda a cadeia de inicialização.
As 17 skills
Direcionando o servidor: navi (roteador) · 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
Criação de conteúdo de conformidade Nessus: navi-audit · navi-audit-syntax ·
navi-audit-platforms · navi-audit-catalog. Estas não usam o servidor MCP,
mas o roteador direciona para elas, então elas viajam com o conjunto.
Material aprofundado (schema completo, catálogo exaustivo de seletores, exemplos longos e trabalhados)
vive em references/*.md e é puxado sob demanda.
Estas são uma cópia fornecida. Elas são mantidas em
packetchaos/navi-claude-skills
e vivem aqui apenas para que NAVI_SKILL_DIR tenha algo para servir. Atualize-as —
e verifique-as contra a superfície real de ferramentas do servidor — com:
python tools/sync_skills.py --dry-run # what would change
python tools/sync_skills.py --verify # sync, then cross-check vs server.py
--verify analisa cada chamada navi_*(...) escrita nas skills e sinaliza nomes de ferramentas
que o servidor não registra, argumentos de palavra-chave que uma ferramenta não aceita, e
ferramentas que nenhuma skill documenta. Execute-o sempre que a superfície de ferramentas mudar: é assim
que navi_action_delete(kind="scan", id=…) foi detectado, onde o parâmetro real é
object_id.
Executando o servidor MCP
O servidor chama o binário navi e lê o navi.db local. Ele
não gerencia chaves de API — defina-as fora de banda com navi config keys
primeiro (veja skills/navi-core).
Requisitos
mcp >= 1.9, < 2. O limite superior não é cautela — mcp 2.0 renomeou
mcp.server.fastmcp para mcp.server.mcpserver e FastMCP para MCPServer, então
2.x falha na importação com ModuleNotFoundError: No module named 'mcp.server.fastmcp' antes que qualquer ferramenta seja registrada. No Claude Desktop isso aparece
apenas como "Server disconnected". Não execute pip install --upgrade mcp — ele
instala 2.x. Instalar este projeto como pacote aplica o pin para você.
Instalação
pip install navi-mcp # from PyPI
pip install "navi-mcp[navi]" # also pulls navi-pro into the same environment
Para uma instalação autocontida que outros pacotes no interpretador não possam perturbar — que é o que você quer por trás do Claude Desktop — use pipx:
pipx install "navi-mcp[navi]"
Ou a partir do código-fonte:
pip install . # from a checkout
pip install "git+https://github.com/packetchaos/navi-mcp"
Execução
navi-mcp # stdio (default); waits for a client
navi-mcp --http # streamable HTTP on :8000
python -m navi_mcp # equivalent entry point
A partir de um checkout, sem instalar:
python navi-mcp-suite/server/server.py # stdio
python navi-mcp-suite/server/server.py --http # streamable HTTP on :8000
Variáveis de ambiente
Cada uma delas é lida uma vez, na inicialização do servidor. Alterar qualquer uma significa reiniciar o servidor (e, no Claude Desktop, sair completamente do aplicativo) — nenhuma delas pode ser alterada de dentro de uma chamada de ferramenta, que é o ponto das proteções.
| Var | Propósito | Padrão se não definido |
|---|---|---|
NAVI_WORKDIR | Diretório que contém navi.db e exportações CSV. O servidor executa cada subprocesso do navi com este como cwd. | ~/.navi-mcp — criado na inicialização se ausente |
NAVI_BIN | Caminho para o executável navi | navi (resolvido em PATH) |
NAVI_SKILL_DIR | O diretório skills/, para que os recursos navi://skill/... sejam resolvidos | <dir of server.py>/resources/skills. Instalado como pacote, isso resolve para as skills incluídas e a var é opcional; executando a partir de um checkout ele não existe, então os recursos de skill retornam 404 até você defini-lo |
NAVI_SKILL_PATH | Legado: um único SKILL.md monolítico. Definir isso coloca o servidor em modo de arquivo único e NAVI_SKILL_DIR é ignorado. Prefira NAVI_SKILL_DIR. | não definido |
NAVI_MCP_ALLOW_WRITES | 1 abre a proteção mestre de escrita (veja abaixo) | não definido → somente leitura |
NAVI_EMAIL | 1 habilita navi_action_mail. Empilha na proteção de escrita. | não definido → desligado |
NAVI_REMOTE_CODE_EXECUTION | 1 habilita navi_action_push. Empilha na proteção de escrita. | não definido → desligado |
Armadilha de primeira instalação.
NAVI_WORKDIRtem como padrão~/.navi-mcp, não o seu diretório atual. O CLI do navi escrevenavi.dbno diretório de onde você o executou, então se você deixarNAVI_WORKDIRnão definido, o servidor criará silenciosamente um~/.navi-mcpvazio, não encontrará banco de dados lá, e cada leitura retornará vazia — parecendo um tenant quebrado em vez de um caminho errado. Leianavi://workdirprimeiro: ele imprime o workdir resolvido e senavi.dbestá realmente presente.
Aponte NAVI_SKILL_DIR para a pasta skills/ deste repositório. O servidor lê
pastas de skills descompactadas, não zips empacotados de .skill/.plugin.
As proteções
Três camadas independentes. Uma ferramenta só é executada quando cada camada que se aplica
a ela é satisfeita; elas são 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
Camada 1 — a proteção mestre de escrita. Desligada por padrão, então uma instalação nova é
somente leitura e segura para apontar para produção. Abri-la habilita tudo que
muda estado no seu tenant Tenable: marcação, ACR, importação de ativos, controle de scan,
lançamentos WAS, exclusões, rotação de chaves, cancelamento de exportação, navi_config(kind='url'),
e navi_explore_api POST/PUT. Também cobre navi_config_rebuild — essa
destrói dados locais em vez de dados do tenant (veja abaixo), mas é destrutiva
o suficiente para ficar atrás do mesmo interruptor.
Camada 2 — proteções de capacidade. Duas capacidades são perigosas de maneiras que gravações comuns de plataforma não são, então cada uma precisa de seu próprio opt-in separado além da camada 1. Abrir a proteção de escrita sozinha não habilita nenhuma delas:
NAVI_EMAIL=1→navi_action_mailpode enviar e-mail como você. Também precisa de SMTP configurado fora de banda vianavi config smtp. Harness:skills/navi-mail.NAVI_REMOTE_CODE_EXECUTION=1→navi_action_pushpode executar comandos de shell em hosts remotos. Também precisa de credenciais SSH vianavi config ssh. Esta é a capacidade de maior risco no navi. Harness:skills/navi-remote-exec.
Camada 3 — confirm=True. Uma flag por chamada em cada ferramenta protegida. As camadas 1 e 2
são decisões permanentes tomadas uma vez pelo operador; a camada 3 é uma decisão sobre
esta chamada específica, e a convenção é que o modelo narra exatamente o que
está prestes a fazer e recebe uma resposta humana antes de passá-la. Como ela vive na
chamada de ferramenta em vez do ambiente, é a única camada que um modelo pode
satisfazer sozinho — que é precisamente por que nunca é a única camada para
qualquer coisa que toca o tenant.
O que precisa do quê
| Ferramenta | Proteção de escrita | Proteção de capacidade | confirm=True |
|---|---|---|---|
navi_enrich_tag, navi_enrich_acr, navi_enrich_add | ✅ | — | ✅ |
navi_scan (create/start/stop/pause/resume) | ✅ | — | ✅ |
navi_was (scan/start/upload) | ✅ | — | ✅ |
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 não-SELECT | — | — | ✅ |
todo o resto (leituras, exportações, navi_explore_api GET, encrypt/decrypt) | — | — | — |
Duas assimetrias que valem a pena conhecer em vez de descobrir:
navi_explore_querynão-SELECT é somente confirmação. UmDELETE/DROPatravés dele atinge seu navi.db local, nunca o tenant, então fica fora da proteção de escrita — mas é destrutivo, e ao contrário denavi_config_rebuildnada além deconfirm=Truefica na frente dele. Se você quer um banco de dados local estritamente somente leitura além de um tenant somente leitura, isso não é o que a proteção de escrita oferece hoje.- O
confirm=Truedenavi_config_rebuildestá fazendo trabalho literal. O próprio caminho-rebuilddo navi chamaclick.confirm()antes de descartar a tabela. Sob MCP, stdin está fechado, então esse prompt abortaria o comando — o servidor responde em seu nome. Seuconfirm=Trueé o "y" sendo digitado. É por isso que a ferramenta recusa sem ele em vez de tratá-lo como formalidade.
Somente leitura por padrão
Sem variáveis de ambiente definidas além de NAVI_WORKDIR e NAVI_BIN, o
servidor expõe apenas leituras. Essa é a postura inicial recomendada: conecte-o,
leia navi://workdir, execute uma consulta ou duas, e abra proteções deliberadamente uma vez que você
confie no que ele está apontando.
Ferramentas destrutivas
Apenas duas ferramentas destroem algo, e nenhuma toca a Tenable:
navi_config_rebuild— DROPa uma tabela localassetsouvulns, recria-a, e rebaixa novamente. Nada no Tenable VM muda; o que você perde é o cache local e as horas que levou para construí-lo em um tenant grande. Tabelas derivadas dessas (certs,software,vuln_route,vuln_paths) ficam obsoletas no mesmo momento — o_noticeda ferramenta nomeia as chamadas que atualizam cada uma. AnotadodestructiveHint=True, quenavi_config_updatedeliberadamente não é: uma atualização mescla na tabela existente e nunca descarta.navi_action_delete— remove tags, usuários, scans, ativos, grupos de alvos, grupos de usuários, ou tags TONE no tenant. Protegido por escrita e confirmação.
Reconstruir ambas as tabelas de uma vez é navi config update full -rebuild no CLI;
full não é exposto como ferramenta porque executa por horas independentemente.
Instalação no Claude Desktop
Passo a passo completo em INSTALL.md. A versão curta — instale o pacote, então aponte a configuração para o script de console:
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"
}
}
}
}
Sem args, sem NAVI_SKILL_DIR (as skills vêm no pacote), e sem
NAVI_BIN quando navi está instalado junto via o extra [navi]. Use um
caminho absoluto — o Claude Desktop não terá o PATH do seu shell.
Executando a partir de um checkout? Deixe o helper descobrir os caminhos, execute com o interpretador que você quer que o 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)
As flags de proteção no helper mapeiam um-para-um para as variáveis de ambiente acima:
--allow-writes, --allow-email, --allow-remote-code-execution. As duas últimas
não têm efeito sem a primeira.
Após editar a configuração, saia completamente e reabra o Claude Desktop, então leia
navi://workdir para confirmar que ele conectou.
Recursos
navi://schema/{table}— definições de colunas ao vivo para uma tabela navi.dbnavi://workdir— workdir resolvido, presença/tamanho/atualização denavi.db, todos os três estados de proteção, binário navi, orçamento de chamadas, e status do diretório de skillsnavi://skill/{name}— carrega uma skill (router/core/mcp/…); lista suas referênciasnavi://skill/{name}/{ref}— carrega uma referência incluída (ex.:navi://skill/core/schema)
Além do prompt navi_workflow, que injeta a skill do roteador.
Operações de longa duração
Exportações do navi podem rodar por dezenas de minutos em tenants grandes — além do teto de
~4 minutos por chamada de ferramenta do host MCP. O servidor aplica um orçamento de chamadas (~220s) e
retorna um erro limpo nomeando o comando CLI exato para executar em vez disso, com escopo
idêntico à chamada que expirou. Sincronizações fundamentais
(navi config update full) permanecem intencionalmente somente CLI. A principal alavanca para
encaixar uma sincronização dentro do orçamento é o escopo: days, since, severity,
plugin_id, ou um par de tags category/value em navi_config_update. Veja
skills/navi-core e skills/navi-troubleshooting.
Testes
python server/tests/run_all.py # summary
python server/tests/run_all.py -v # every check
As suítes simulam o subprocesso do navi e verificam o argv que cada ferramenta constrói,
portanto não precisam de tenant, nem de chaves de API, nem de navi.db. O NAVI_WORKDIR é
redirecionado para um diretório temporário e o binário real do navi nunca é invocado —
seguro para executar contra uma instalação de produção. Execute-as após instalar em uma nova
máquina: elas detectarão um mcp SDK quebrado, um Python antigo demais para a sintaxe
de tipos, ou um checkout parcial antes de você conectar um cliente.
Instalando as skills como skills do Claude
Instale-as a partir de
packetchaos/navi-claude-skills,
que gera um pacote navi-skills.plugin para Claude.ai / Claude Cowork /
Claude Code. Este repositório não distribui mais cópias empacotadas: um segundo canal de
distribuição é uma segunda coisa para esquecer de atualizar, e é exatamente assim que as
skills aqui acabaram descrevendo um servidor que evoluiu sem elas. A pasta
skills/ permanece porque o servidor MCP a lê diretamente.
Status de validação
server.py compila sem erros, todas as ferramentas estão anotadas, todas as 20 registram, e as
suítes em server/tests/ estão verdes. As anotações de ferramentas exigem mcp >= 1.9;
mcp.types.ToolAnnotations é importado atrás de um try/except para que um SDK
mais antigo degrade para ferramentas sem anotações em vez de falhar. Um SDK 2.x não degrada
de forma graciosa — ele falha diretamente, e é por isso que a dependência está fixada em <2.
Ele não foi testado em tempo de execução contra um tenant Tenable ativo. As verificações
confirmam o que o servidor pede ao navi para fazer; elas não podem verificar o que o navi e a
API do Tenable fazem em resposta. Antes de confiar nele, valide com uma leitura ativa —
navi_explore_data(subcommand="cve", cve="CVE-2021-44228") — e leia
navi://workdir para confirmar que o diretório de trabalho e os estados de gate são os que você pretendia.
Consulte docs/verified-findings.md para o inventário por bug e
docs/gap-ledger.md para o registro completo de auditoria.