Zsnoop

Un servidor MCP para exploración de solo lectura de instantáneas ZFS en hosts remotos.

Documentación

zsnoop-mcp

PyPI Python License: MIT CI

Pregúntale a tu asistente de IA cosas como:

  • "Recupera mi .zshrc de antes de que hiciera el commit de la reescritura hace tres semanas."
  • 🧹 "¿Qué instantáneas de más de 6 meses están desperdiciando más espacio?"
  • 🔎 "¿Cuándo apareció por primera vez el directorio /srv/backups en este host?"
  • "Encuentra todo lo eliminado bajo /home/youruser en la última semana, y muéstrame cuándo estuvo presente cada cosa por última vez."
  • 🏥 "¿Alguno de mis pools está dando errores de disco? ¿Cuándo fue el último scrub?"

Un servidor MCP para exploración y recuperación de instantáneas ZFS en hosts remotos — solo lectura por defecto, con herramientas restore_* opt-in (v0.4.0+) habilitadas por host.

Explora, compara, busca y lee archivos de cualquier instantánea en cualquiera de tus hosts ZFS a través de tu asistente de IA, mediante una única conexión SSH persistente por host. Solo lectura por defecto; las herramientas de escritura restore_file / restore_dir (v0.4.0+) son opt-in por host y están limitadas por una lista de permitidos de rutas definida por el operador — con la configuración estándar, nada en el remoto puede escribirse.

Inicio 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.

El agente se transmite por SSH en la primera conexión — no es necesario instalar nada en el host remoto más allá de python3 (3.11+) y la CLI de zfs. Solo lectura por defecto, aplicado mediante una lista de permitidos explícita en el lado del agente. Las herramientas de escritura restore_file / restore_dir (v0.4.0+) son opt-in por host y están limitadas por una lista de permitidos de rutas definida por el operador; con la configuración predeterminada se niegan antes de hacer nada.

Acerca de este código

Este proyecto se desarrolló en colaboración con Claude Code (Anthropic). El autor humano (Mark Hellewell) definió la arquitectura, el modelo de seguridad y los criterios de aceptación, y revisó cada cambio antes de que se integrara; Claude se encargó de la mayor parte del borrador, el andamiaje de pruebas, las refactorizaciones y la documentación. El modo solo-lectura por defecto fue un requisito estricto desde el primer día, aplicado mediante una lista de permitidos de métodos explícita y la suite de pruebas. Las herramientas restore_* opt-in añadidas en v0.4.0 son los únicos métodos de escritura y están controladas en el lado del servidor mediante configuración por host (desactivadas por defecto; requieren una lista de permitidos de rutas no vacía cuando se activan) — ver SECURITY.md. Si estás revisando o auditando el código, trátalo como contexto, no como una razón para saltarte el escrutinio habitual.

Cómo 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

El agente remoto es un script de Python de un solo archivo, solo con la biblioteca estándar. Puede estar preinstalado en ~/bin/zfs-snoop-agent en cada host, o transmitirse por SSH stdin en cada conexión — no se requiere instalación permanente.

Herramientas expuestas al LLM

Diseñado en torno a cuatro flujos de trabajo dominantes: recuperación de archivos ("dame /etc/foo tal como estaba ayer" — en tu estación de trabajo, o restaurado en su lugar en el servidor), auditoría de deriva de configuración ("¿cuándo cambió X?"), forensia ("¿qué había en la máquina cuando Y se rompió?"), y mantenimiento de almacenamiento ("¿qué instantáneas son las más grandes / más antiguas?"). Las herramientas se agrupan a continuación por su caso de uso dominante; muchas se combinan entre flujos de trabajo.

Descubrimiento e introspección

HerramientaQué hace
list_hostsHosts configurados
agent_infoVersión del agente, métodos, límites
list_poolsPools ZFS visibles para el agente (descubrimiento en vivo)
pool_statuszpool status analizado: árbol vdev, scrub, errores
list_datasetsSistemas de archivos y volúmenes
dataset_propertieszfs get (todos o filtrados) con valores y fuentes

Inventario de instantáneas y mantenimiento

HerramientaQué hace
list_snapshotsInstantáneas (filtros opcionales de dataset/tiempo/capacidad)
snapshot_cadenceResumen: recuentos por clase, brecha (por dataset), extensión
stale_snapshotsInstantáneas más antiguas que una frase de tiempo, ordenadas por unicidad
size_deltaBytes escritos entre dos instantáneas de un dataset

Exploración y dimensionamiento dentro de una instantánea

HerramientaQué hace
list_dirListado de directorio acotado dentro de una instantánea
size_breakdownBytes recursivos para un directorio de instantánea + tamaños por hijo
top_consumersTop-N archivos/directorios más grandes bajo un subárbol de instantánea

Lectura de contenido

HerramientaQué hace
read_fileLectura acotada; UTF-8 o base64 para binarios
find_filesBúsqueda de nombres fnmatch dentro de una instantánea
content_grepBúsqueda de contenido con regex dentro de una instantánea
checksum_fileSHA-256 de archivo completo (límite de 256 MiB) para comprobaciones de integridad

Comparación de instantáneas y seguimiento de cambios

HerramientaQué hace
diff_snapshotsDiff a nivel de ruta entre dos instantáneas
file_diffDiff unificado de un archivo entre dos instantáneas
file_historyLa versión de cada instantánea de un archivo dado en un dataset
versions_offile_history deduplicado por hash (solo versiones distintas)
snapshots_containingInstantáneas en las que una ruta existe actualmente (con rango de tiempo)
first_appearanceInstantánea más temprana que contiene una ruta
last_appearanceInstantánea más reciente que contiene una ruta; revela cuándo se eliminó
find_deletedRutas eliminadas entre dos instantáneas en una ventana de tiempo
bisect_changeBúsqueda binaria de la instantánea donde un predicado cambia

Recuperación — copiar a tu estación de trabajo

HerramientaQué hace
fetch_fileCopiar un archivo de instantánea a una ruta local vía SFTP
fetch_dirCopiar un árbol de directorios de instantánea a una ruta local vía SFTP

Recuperación — restaurar en el servidor (opt-in, v0.4.0+)

Estas son las únicas herramientas de escritura. Desactivadas por host por defecto; requieren allow_restore = true y una lista de permitidos restore_paths no vacía en hosts.toml. Ver SECURITY.md para el modelo de amenazas.

HerramientaQué hace
restore_fileRestaurar un archivo de instantánea a una ruta del servidor (opt-in)
restore_dirRestaurar un árbol de directorios de instantánea a una ruta del servidor

Los parámetros de rango de tiempo aceptan ISO 8601 o frases en lenguaje natural — yesterday, last week, 3 days ago, 2 hours ago, etc. El análisis se realiza localmente; el agente solo ve marcas de tiempo ISO 8601 absolutas.

Instalación

Desde PyPI (recomendado)

uv tool install zsnoop-mcp

Ejecútalo con zsnoop-mcp.

Desde un clon (para modificar el código)

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

Ejecútalo con uv run zsnoop-mcp desde el checkout.

Ver docs/PUBLISHING.md para el flujo por versión (bump de versión → tag → CI publica vía OIDC).

Configuración

Crea ~/.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"

Configuración por host en el remoto (una sola vez):

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

Ver docs/INSTALL.md para la configuración completa, incluido el modo sudo para leer archivos de instantánea propiedad de root.

Conectar con Claude Code

Después de uv tool install zsnoop-mcp:

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

Eso escribe la entrada directamente en tu configuración de Claude Code; no se necesita edición de JSON. Reinicia tu sesión de Claude Code; las herramientas aparecen bajo el espacio de nombres zsnoop.

Si estás ejecutando desde un worktree en lugar de un binario instalado, apunta el comando a uv run --directory <path> en su lugar:

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

O, si prefieres editar ~/.claude/settings.json a mano:

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

Uso

Ver docs/USAGE.md para ejemplos de prompts que ejercitan los flujos de trabajo de recuperación de archivos, auditoría de deriva y forensia.

Documentación

  • ¿Nuevo aquí? Comienza con el tutorial de incorporación — un recorrido de 10 capítulos sobre qué/por qué/cómo a través del código, que termina con un ejemplo práctico de cómo añadir una nueva herramienta de principio a fin. Se renderiza bien como HTML vía uv run mkdocs serve (ver --group docs).
  • Instalación — configuración local, delegación ZFS, modo sudo
  • Ejemplos de uso — prompts concretos que las herramientas manejan
  • Modelo de seguridad — modelo de amenazas, garantías, compensación de sudo
  • Publicación — publicación en PyPI

Desarrollo

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

Pre-commit ejecuta pip-audit automáticamente cada vez que pyproject.toml o uv.lock cambian.

Licencia

MIT — ver LICENSE.