Zsnoop

Um servidor MCP para exploração somente leitura de snapshots ZFS em hosts remotos.

Documentação

zsnoop-mcp

PyPI Python License: MIT CI

Pergunte ao seu assistente de IA coisas como:

  • "Recupere meu .zshrc de antes de eu ter feito o commit da reescrita há três semanas."
  • 🧹 "Quais snapshots com mais de 6 meses estão desperdiçando mais espaço?"
  • 🔎 "Quando o diretório /srv/backups apareceu pela primeira vez neste host?"
  • "Encontre tudo que foi excluído sob /home/youruser na última semana e mostre quando cada coisa esteve presente pela última vez."
  • 🏥 "Algum dos meus pools está apresentando erros de disco? Quando foi o último scrub?"

Um servidor MCP para exploração e recuperação de snapshots ZFS em hosts remotos — somente leitura por padrão, com ferramentas restore_* opcionais (v0.4.0+) controladas por host.

Navegue, compare, pesquise e leia arquivos de qualquer snapshot em qualquer um dos seus hosts ZFS através do seu assistente de IA, por uma única conexão SSH persistente por host. Somente leitura por padrão; as ferramentas graváveis restore_file / restore_dir (v0.4.0+) são opcionais por host e limitadas por uma lista de permissões de caminho definida pelo operador — com a configuração padrão, nada no remoto pode ser gravado.

Início rápido

# 1. Install
uv tool install zsnoop-mcp

# 2. Configure one host (more in docs/INSTALL.md)
mkdir -p ~/.config/zsnoop-mcp
cat > ~/.config/zsnoop-mcp/hosts.toml <<'EOF'
[hosts.myhost]
ssh_target = "myhost.example.com"
agent_mode = "bootstrap"
sudo       = false
EOF

# 3. Register the MCP server with Claude Code
claude mcp add zsnoop --scope user -- zsnoop-mcp

# 4. Restart Claude Code, then ask your assistant any of the prompts above.

O agente é transmitido via SSH na primeira conexão — nada precisa ser instalado no host remoto além de python3 (3.11+) e do CLI zfs. Somente leitura por padrão, imposto por uma lista de permissões explícita no lado do agente. As ferramentas graváveis restore_file / restore_dir (v0.4.0+) são opcionais por host e limitadas por uma lista de permissões de caminho definida pelo operador; com a configuração padrão, elas recusam antes de fazer qualquer coisa.

Sobre este código

Este projeto foi desenvolvido em colaboração com Claude Code (Anthropic). O autor humano (Mark Hellewell) definiu a arquitetura, o modelo de segurança e os critérios de aceitação, e revisou cada mudança antes de ela ser incorporada; Claude cuidou da maior parte da redação, da estrutura de testes, das refatorações e da documentação. Somente leitura por padrão foi um requisito rígido desde o primeiro dia, imposto por uma lista de permissões de métodos explícita e pela suíte de testes. As ferramentas restore_* opcionais adicionadas na v0.4.0 são os únicos métodos graváveis e são controladas no lado do servidor por configuração por host (desativadas por padrão; exigem uma lista de permissões de caminho não vazia quando ativadas) — veja SECURITY.md. Se você está revisando ou auditando o código, trate isso como contexto, não como motivo para pular o escrutínio usual.

Como funciona

┌─────────────────┐   MCP (stdio)    ┌────────────────────┐
│   MCP client    │ ───────────────► │  zsnoop-mcp server │
│ (Claude Code,…) │ ◄─────────────── │     (local)        │
└─────────────────┘                  └──────────┬─────────┘
                                                │
                       JSON-RPC over SSH stdio  │  one persistent
                       (one channel per host)   │  subprocess
                                                ▼
                                      ┌─────────────────────┐
                                      │  zfs-snoop-agent    │
                                      │  (remote, Python)   │
                                      └─────────┬───────────┘
                                                │
                                       zfs list / zfs diff,
                                       walk .zfs/snapshot/…
                                                ▼
                                            ZFS pool

O agente remoto é um script Python de arquivo único, apenas com a biblioteca padrão. Ele pode ser pré-instalado em ~/bin/zfs-snoop-agent em cada host, ou transmitido via stdin SSH em cada conexão — sem necessidade de instalação permanente.

Ferramentas expostas ao LLM

Projetado em torno de quatro fluxos de trabalho dominantes: recuperação de arquivos ("me traga /etc/foo como estava ontem" — para sua estação de trabalho, ou restaurado no servidor), auditoria de desvio de configuração ("quando X mudou?"), forense ("o que havia na máquina quando Y quebrou?"), e manutenção de armazenamento ("quais snapshots são maiores / mais antigos?"). As ferramentas estão agrupadas abaixo pelo caso de uso dominante; muitas se combinam entre fluxos de trabalho.

Descoberta e introspecção

FerramentaO que faz
list_hostsHosts configurados
agent_infoVersão do agente, métodos, limites
list_poolsPools ZFS visíveis ao agente (descoberta ao vivo)
pool_statuszpool status analisado: árvore vdev, scrub, erros
list_datasetsSistemas de arquivos e volumes
dataset_propertieszfs get (todos ou filtrados) com valores + fontes

Inventário de snapshots e manutenção

FerramentaO que faz
list_snapshotsSnapshots (filtros opcionais de dataset/tempo/capacidade)
snapshot_cadenceResumo: contagens por classe, lacuna (por dataset), intervalo
stale_snapshotsSnapshots mais antigos que uma frase de tempo, ordenados por exclusividade
size_deltaBytes gravados entre dois snapshots de um dataset

Navegação e dimensionamento dentro de um snapshot

FerramentaO que faz
list_dirListagem de diretório limitada dentro de um snapshot
size_breakdownBytes recursivos para um diretório de snapshot + tamanhos por filho
top_consumersTop-N maiores arquivos/diretórios sob uma subárvore de snapshot

Leitura de conteúdo

FerramentaO que faz
read_fileLeitura limitada; UTF-8 ou base64 para binário
find_filesPesquisa de nome fnmatch dentro de um snapshot
content_grepPesquisa de conteúdo com regex dentro de um snapshot
checksum_fileSHA-256 do arquivo completo (limite de 256 MiB) para verificações de integridade

Comparando snapshots e rastreando mudanças

FerramentaO que faz
diff_snapshotsDiff em nível de caminho entre dois snapshots
file_diffDiff unificado de um arquivo entre dois snapshots
file_historyVersão de cada snapshot de um determinado arquivo em um dataset
versions_offile_history deduplicado por hash (apenas versões distintas)
snapshots_containingSnapshots em que um caminho existe atualmente (com intervalo de tempo)
first_appearanceSnapshot mais antigo contendo um caminho
last_appearanceSnapshot mais recente contendo um caminho; revela quando foi excluído
find_deletedCaminhos excluídos entre dois snapshots em uma janela de tempo
bisect_changeBusca binária pelo snapshot onde um predicado muda

Recuperação — copiar para sua estação de trabalho

FerramentaO que faz
fetch_fileCopiar um arquivo de snapshot para um caminho local via SFTP
fetch_dirCopiar uma árvore de diretórios de snapshot para um caminho local via SFTP

Recuperação — restaurar no servidor (opcional, v0.4.0+)

Estas são as únicas ferramentas graváveis. Desativadas por host por padrão; exigem allow_restore = true e uma lista de permissões restore_paths não vazia em hosts.toml. Veja SECURITY.md para o modelo de ameaças.

FerramentaO que faz
restore_fileRestaurar um arquivo de snapshot para um caminho do servidor (opcional)
restore_dirRestaurar uma árvore de diretórios de snapshot para um caminho do servidor

Os parâmetros de intervalo de tempo aceitam ISO 8601 ou frases humanas — yesterday, last week, 3 days ago, 2 hours ago, etc. A análise ocorre localmente; o agente só vê timestamps absolutos ISO 8601.

Instalação

Via PyPI (recomendado)

uv tool install zsnoop-mcp

Execute com zsnoop-mcp.

A partir de um clone (para mexer no código)

git clone https://github.com/hamsolodev/zsnoop-mcp.git
cd zsnoop-mcp
uv sync

Execute com uv run zsnoop-mcp a partir do checkout.

Veja docs/PUBLISHING.md para o fluxo por versão (incremento de versão → tag → CI publica via OIDC).

Configuração

Crie ~/.config/zsnoop-mcp/hosts.toml:

[hosts.r2d2]
ssh_target = "r2d2.example.com"
agent_mode = "bootstrap"          # or "preinstalled"
sudo       = false                # set true to read root-owned snapshot files
pools      = ["rpool", "bpool"]   # used by the LLM for scoping hints

[hosts.c3po]
ssh_target = "c3po.example.com"
agent_mode = "bootstrap"
sudo       = false
pools      = ["rpool"]

[hosts.this-box]
transport  = "local"              # run the agent on this machine, no SSH
agent_mode = "bootstrap"

Configuração por host no remoto (uma vez):

# user mode: grant diff for each pool you want to compare snapshots in
sudo zfs allow -u $USER diff rpool

Veja docs/INSTALL.md para a configuração completa, incluindo o modo sudo para ler arquivos de snapshot de propriedade do root.

Integrar ao Claude Code

Após uv tool install zsnoop-mcp:

claude mcp add zsnoop --scope user -- zsnoop-mcp

Isso grava a entrada diretamente na sua configuração do Claude Code; não é necessário editar JSON. Reinicie sua sessão do Claude Code; as ferramentas aparecem sob o namespace zsnoop.

Se você estiver executando a partir de um worktree em vez de um binário instalado, aponte o comando para uv run --directory <path> em vez disso:

claude mcp add zsnoop --scope user -- \
    uv run --directory ~/path/to/zsnoop-mcp zsnoop-mcp

Ou, se preferir editar ~/.claude/settings.json manualmente:

{
  "mcpServers": {
    "zsnoop": { "command": "zsnoop-mcp" }
  }
}

Uso

Veja docs/USAGE.md para exemplos de prompts que exercitam os fluxos de recuperação de arquivos, auditoria de desvio e forense.

Documentação

  • Novo aqui? Comece com o tutorial de integração — um passeio de 10 capítulos, o que/porquê/como pelo código, terminando com um exemplo prático de adição de uma nova ferramenta de ponta a ponta. Renderiza bem como HTML via uv run mkdocs serve (veja --group docs).
  • Instalação — configuração local, delegação ZFS, modo sudo
  • Exemplos de uso — prompts concretos que as ferramentas lidam
  • Modelo de segurança — modelo de ameaças, garantias, trade-off do sudo
  • Publicação — lançamento no PyPI

Desenvolvimento

uv sync                            # install runtime + dev deps into .venv
uv run pytest                      # tests
uv run ruff check                  # lint
uv run ruff format                 # format
uv run mypy                        # type-check
uv run pip-audit --skip-editable   # CVE scan of locked deps
uv run pre-commit install          # set up hooks

O pre-commit executa pip-audit automaticamente sempre que pyproject.toml ou uv.lock mudam.

Licença

MIT — veja LICENSE.