Skip to main content

zsnoop-mcp

PyPI Python License: MIT CI

Ask your AI assistant things like:

  • ⏪ "Recover my .zshrc from before I committed the rewrite three weeks ago."
  • 🧹 "Which snapshots older than 6 months are wasting the most space?"
  • 🔎 "When did the directory /srv/backups first appear on this host?"
  • ⌛ "Find everything deleted under /home/youruser in the last week, and show me when each thing was last present."
  • 🏥 "Are any of my pools throwing disk errors? When was the last scrub?"

An MCP server for ZFS snapshot exploration and recovery on remote hosts — read-only by default, with opt-in restore_* tools (v0.4.0+) gated per host.

Browse, diff, search, and read files from any snapshot on any of your ZFS hosts through your AI assistant, over a single persistent SSH connection per host. Read-only by default; the writable restore_file / restore_dir tools (v0.4.0+) are opt-in per host and bounded by an operator-defined path allowlist — with the stock config, nothing on the remote can be written.

Quickstart

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

The agent is streamed over SSH on first connect — nothing needs to be installed on the remote host beyond python3 (3.11+) and the zfs CLI. Read-only by default, enforced by an explicit allowlist on the agent side. The writable restore_file / restore_dir tools (v0.4.0+) are opt-in per host and bounded by an operator-defined path allowlist; with the default config they refuse before doing anything.

About this codebase

This project was developed collaboratively with Claude Code (Anthropic). The human author (Mark Hellewell) defined the architecture, security model, and acceptance criteria, and reviewed every change before it landed; Claude handled the bulk of the drafting, test scaffolding, refactors, and documentation. Read-only-by-default was a hard requirement from day one, enforced by an explicit method allowlist and the test suite. The opt-in restore_* tools added in v0.4.0 are the only writable methods and are gated server-side on per-host config (off by default; requires a non-empty path allowlist when enabled) — see SECURITY.md. If you're reviewing or auditing the code, treat that as context, not as a reason to skip the usual scrutiny.

How it works

┌─────────────────┐   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

The remote agent is a single-file, stdlib-only Python script. It can be pre-installed at ~/bin/zfs-snoop-agent on each host, or streamed over SSH stdin on each connection — no permanent install required.

Tools exposed to the LLM

Designed around four dominant workflows: file recovery ("get me /etc/foo as it was yesterday" — to your workstation, or restored in place on the server), config drift audit ("when did X change?"), forensics ("what was on the box when Y broke?"), and storage housekeeping ("which snapshots are biggest / oldest?"). The tools are grouped below by their dominant use case; many compose across workflows.

Discovery & introspection

Tool What it does
list_hosts Configured hosts
agent_info Agent version, methods, limits
list_pools ZFS pools visible to the agent (live discovery)
pool_status Parsed zpool status: vdev tree, scrub, errors
list_datasets Filesystems and volumes
dataset_properties zfs get (all or filtered) with values + sources

Snapshot inventory & housekeeping

Tool What it does
list_snapshots Snapshots (optional dataset/time/cap filters)
snapshot_cadence Summary: counts by class, gap (per-dataset), span
stale_snapshots Snapshots older than a time phrase, sorted by uniqueness
size_delta Bytes written between two snapshots of one dataset

Browsing & sizing within a snapshot

Tool What it does
list_dir Bounded directory listing within a snapshot
size_breakdown Recursive bytes for a snapshot dir + per-child sizes
top_consumers Top-N largest files/dirs under a snapshot subtree

Reading content

Tool What it does
read_file Bounded read; UTF-8 or base64 for binary
find_files fnmatch name search inside a snapshot
content_grep Regex content search inside a snapshot
checksum_file Full-file SHA-256 (256 MiB cap) for integrity checks

Comparing snapshots & tracing change

Tool What it does
diff_snapshots Path-level diff between two snapshots
file_diff Unified diff of one file across two snapshots
file_history Every snapshot's version of a given file in a dataset
versions_of file_history deduped by hash (distinct versions only)
snapshots_containing Snapshots in which a path currently exists (time-ranged)
first_appearance Earliest snapshot containing a path
last_appearance Latest snapshot containing a path; reveals when deleted
find_deleted Paths deleted between two snapshots in a time window
bisect_change Binary-search for the snapshot where a predicate flips

Recovery — copy out to your workstation

Tool What it does
fetch_file Copy a snapshot file to a local path via SFTP
fetch_dir Copy a snapshot directory tree to a local path via SFTP

Recovery — restore in place on the server (opt-in, v0.4.0+)

These are the only writable tools. Disabled per host by default; require allow_restore = true and a non-empty restore_paths allowlist in hosts.toml. See SECURITY.md for the threat model.

Tool What it does
restore_file Restore a snapshot file to a server path (opt-in)
restore_dir Restore a snapshot directory tree to a server path

Time-range parameters accept ISO 8601 or human phrases — yesterday, last week, 3 days ago, 2 hours ago, etc. Parsing happens locally; the agent only sees absolute ISO 8601 timestamps.

Install

uv tool install zsnoop-mcp

Run it with zsnoop-mcp.

From a clone (for hacking on the code)

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

Run it with uv run zsnoop-mcp from the checkout.

See docs/PUBLISHING.md for the per-release flow (version bump → tag → CI publishes via OIDC).

Configure

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

Per-host setup on the remote (one-time):

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

See docs/INSTALL.md for the full setup, including sudo mode for reading root-owned snapshot files.

Wire into Claude Code

After uv tool install zsnoop-mcp:

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

That writes the entry directly to your Claude Code config; no JSON editing needed. Restart your Claude Code session; the tools appear under the zsnoop namespace.

If you're running from a worktree instead of an installed binary, point the command at uv run --directory <path> instead:

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

Or, if you'd rather edit ~/.claude/settings.json by hand:

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

Use

See docs/USAGE.md for example prompts that exercise the file-recovery, drift-audit, and forensics workflows.

Documentation

  • New here? Start with the onboarding tutorial — a 10-chapter, what/why/how walk through the codebase, ending with a worked example of adding a new tool end-to-end. Renders nicely as HTML via uv run mkdocs serve (see --group docs).
  • Installation — local setup, ZFS delegation, sudo mode
  • Usage examples — concrete prompts the tools handle
  • Security model — threat model, guarantees, sudo tradeoff
  • Publishing — releasing to PyPI

Development

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 runs pip-audit automatically whenever pyproject.toml or uv.lock change.

License

MIT — see LICENSE.

Metadata

Release files for zsnoop-mcp 0.4.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for zsnoop-mcp 0.4.3
File Size Uploaded
zsnoop_mcp-0.4.3.tar.gz 265.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for zsnoop-mcp 0.4.3
File Interpreter ABI Platform
zsnoop_mcp-0.4.3-py3-none-any.whl Python 3 none any Details

Total release size: 323.6 kB

Release files / zsnoop_mcp-0.4.3.tar.gz

Download URL zsnoop_mcp-0.4.3.tar.gz
Size 265.0 kB
Tags Source
SHA-256 checksum
How to use checksums
57d73a9bbb7f940a46de291b51b5f6a4867428a9ec617447d4770d179f023566
BLAKE2b-256 checksum
How to use checksums
0f5e1cf731c4ddce2ad1d268a9ebba0136b88a598cbd4541671addd9db52b574
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 28, 2026.

Transparency log

Release files / zsnoop_mcp-0.4.3-py3-none-any.whl

Download URL zsnoop_mcp-0.4.3-py3-none-any.whl
Size 58.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
331536cdb1fa38973e5c766f48ab51af009a7e947b8e619920015c8a9c02dc61
BLAKE2b-256 checksum
How to use checksums
8d0be2c2fae307903a975059ab580dfb15c6a8933fda908cacd667cc8368b869
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 28, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.4.3 This release

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page