# Agent Config Snapshot Mcp

> 🛡️ Git-style content-addressed snapshots for AI agent config files: MCP-native auto-capture (session baseline + pre-tool-call checkpoints, no daemon), id-based one-command rollback, unified diff. CLI + MCP server for any MCP-compatible agent. / AI Agent 配置文件的 Git 风格快照：MCP 原生自动捕获（无常驻进程），按 id 一键回滚。

- **Type:** MCP server
- **Install:** `agentstack add mcp-theianli-agent-config-snapshot-mcp`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [TheIanLi](https://agentstack.voostack.com/s/theianli)
- **Installs:** 0
- **Category:** [Integrations](https://agentstack.voostack.com/c/integrations)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [TheIanLi](https://github.com/TheIanLi)
- **Source:** https://github.com/TheIanLi/agent-config-snapshot-mcp

## Install

```sh
agentstack add mcp-theianli-agent-config-snapshot-mcp
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

[](README.md)
[](README_zh.md)

# Agent Config Snapshot MCP

> Git-style snapshots for AI agent config files — your safety net when agents go rogue.

[](https://python.org)
[](https://modelcontextprotocol.io/)
[](LICENSE)
[](https://github.com/TheIanLi/agent-config-snapshot-mcp/actions/workflows/test.yml)

## Why This Exists

One day, I asked my AI agent to tweak a config. It modified `config.yaml`, rewrote `SOUL.md`, and then—the agent broke.

Not "hmm, this setting looks odd" broke. Corrupted-personality, fails-to-start, can't-even-read-the-error broke. I spent half a day manually reverting a dozen scattered changes. That's when it hit me: **the same agent that manages my configs can destroy them in seconds.**

This tool grew out of that disaster. The idea is simple — bring VM-style snapshots to agent config files. When things go wrong, roll back. One command, instant recovery.

## What It Does

**agent-config-snapshot-mcp** gives your config files a time machine:

- **Automatic capture with zero resident processes**: the MCP server takes a baseline when your session starts and captures changes before each of its own tool calls — nothing to keep running in the background
- Content-addressed storage (CAS): identical content is stored once, every read is integrity-checked, rollback writes are atomic
- Diff the current version against any snapshot
- Roll back to any version with one command (the current state is auto-saved first)

Works as a standalone CLI and as an MCP server your AI agent can call directly.

## How Automatic Capture Works (the no-daemon design)

The edit that corrupts your config usually never passes through this tool — the agent edits files with its own tooling. So capture happens in three layers, none of which needs a resident process:

| Layer | Mechanism | Coverage |
|------|------|---------|
| L0 session baseline | When the host agent launches the MCP server, every protected file is hash-compared and captured if changed | Every MCP-capable agent (Claude Code / Gemini / Codex / Hermes / OpenClaw…) |
| L1 lazy checkpoint | Before each call to **one of this server's own tools**, changed files are captured first | Same as above |
| L2 pre-edit hooks | `agent-snapshot hooks` prints host hook configs that run `capture --quiet` before every file edit | Hosts with hook support (Claude Code, Gemini CLI ≥0.26) |

Note the coverage boundary: **L1 only fires before this server's own tool calls** — the agent's own Edit/Write tooling does not go through this server, so a mid-session edit made with no snapshot tool call in between is not captured on its own. For a targeted operation (`diff`/`rollback`), the target label is also deliberately excluded from that pre-op checkpoint (so the pre-op capture can't prune away the very snapshot you're reading). Per-edit coverage is exactly what the **L2 hooks** add.

The result: when you notice a broken config and ask the agent to roll back, a good earlier version is already in the store. **Without the L2 hooks, rollback granularity is "the session-start baseline plus every point where a snapshot tool was invoked"** — install the hooks if you want a snapshot before every single edit.

## Features

| Feature | CLI | MCP | Notes |
|---------|:---:|:---:|-------------|
| Discovery | — | ✓ | `list_protected_files` lists protected files and snapshot counts |
| Snapshot | ✓ | ✓ | Save current state; deduplicated when content is unchanged |
| History | ✓ | ✓ | List all snapshots (with snapshot_id), newest first |
| Diff | ✓ | ✓ | Unified diff between the current file and any snapshot (by id) |
| Rollback | ✓ | ✓ | Restore by id (current version auto-saved first, atomic write) |
| Bulk capture | ✓ | — | `capture` grabs all changes at once, for hooks / cron |
| Retention | ✓ | ✓ | Configurable max snapshots per file with auto-pruning |
| Legacy migration | ✓ | — | `migrate` imports ≤0.3.x file-based snapshots (timestamps and reasons preserved) |

## Quick Start

```bash
# 1. Clone
git clone https://github.com/TheIanLi/agent-config-snapshot-mcp.git
cd agent-config-snapshot-mcp

# 2. Install dependencies
uv sync

# 3. Initialize from a preset
uv run agent-snapshot init --preset hermes

# 4. Take your first snapshot
uv run agent-snapshot snapshot hermes_data/SOUL

# 5. View history (each entry has a snapshot_id)
uv run agent-snapshot list hermes_data/SOUL
```

> **Platforms:** Linux / macOS / Windows

## CLI Reference

> The examples below assume the venv is activated (`source .venv/bin/activate` on Linux/macOS, `.venv\Scripts\activate` on Windows); otherwise prefix each command with `uv run`, e.g. `uv run agent-snapshot init`.

### `init` — Initialize configuration

```bash
# Use a preset (recommended)
agent-snapshot init --preset hermes       # Hermes Agent
agent-snapshot init --preset openclaw     # OpenClaw
agent-snapshot init --preset claude-code  # Claude Code
agent-snapshot init --preset gemini       # Gemini CLI
agent-snapshot init --preset codex        # Codex CLI

# Interactive scan (auto-detects installed agents)
agent-snapshot init

# Scan extra directories — supports any agent, even ones not in the built-in list
agent-snapshot init --scan-dir ~/.my-agent

# Non-interactive: protect everything detected, no prompts
agent-snapshot init --all

# Overwrite an existing config (refused by default to protect your curated list)
agent-snapshot init --preset hermes --force
```

> By default `init` **will not overwrite** an existing `snapshot-config.yaml`. Pass `--force` (`-f`) to regenerate.

**How scanning works:** detection is **not filename-based** — every agent directory is scanned for small config-looking files (`.yaml` / `.yml` / `.json` / `.md` / `.toml` / `.env`, under 1MB), automatically skipping bulky dirs like `sessions` / `logs` / `cache`.

> Every file gets a unique `label`. Duplicate labels fail fast at config load time.

### `snapshot` — Manual snapshot

```bash
agent-snapshot snapshot 
# If content matches the latest snapshot you'll be told "not created" — no duplicate pileup
```

### `list` — Snapshot history

```bash
agent-snapshot list 
# Example output:
#   a3f8c2d19b04  2026-07-01 21:30:12  2.5KB  [manual]
#   7e12ff08aa31  2026-07-01 18:04:55  2.8KB  [auto]
#   09cc41b7d2e6  2026-07-01 09:11:02  2.8KB  [baseline]
```

The first column is the **snapshot_id** (sha256 prefix of the content). It is content-derived and **never shifts when new snapshots appear** — an id always points to the same bytes.

### `diff` — Compare changes

```bash
agent-snapshot diff  
# Example
agent-snapshot diff hermes_data/SOUL a3f8c2d1   # any unique prefix of 4+ hex chars works
```

### `rollback` — Restore a snapshot

```bash
agent-snapshot rollback  
```

**The current version is auto-saved** as a safety snapshot first; the write-back is atomic (temp file + rename), so a full disk or power loss can't leave a half-written file.

### `capture` — Bulk change capture

```bash
agent-snapshot capture           # capture all changed protected files and print results
agent-snapshot capture --quiet   # silent, always exits 0 — designed for host hooks / cron
```

### `hooks` — Generate pre-edit hook configs

```bash
agent-snapshot hooks   # prints hook snippets for Claude Code / Gemini CLI
```

### `migrate` — Import legacy snapshots

```bash
agent-snapshot migrate   # imports ≤0.3.x file-based snapshots, preserving timestamps and reasons; originals untouched
```

> **`watch` removed:** the 0.3.x watcher daemon was removed in 0.4.0. Running `agent-snapshot watch` now just prints migration guidance pointing to `hooks` / `capture` instead of doing anything.

## Snapshot Reason Tags

| Tag | Trigger |
|-----|---------|
| `baseline` | MCP server session-start baseline |
| `auto` | Lazy checkpoint before an MCP tool call |
| `hook` | Host pre-edit hook / `capture --quiet` |
| `manual` | Manual snapshot command |
| `safe` | Auto-saved safety snapshot before rollback |

## Configuration

```yaml
# snapshot-config.yaml
protected_files:
  - path: ~/.hermes_data/config.yaml
    label: hermes_data/config          # unique id used by CLI/MCP
  - path: ~/.hermes_data/SOUL.md
    label: hermes_data/SOUL
  - path: ~/.hermes_data/.env
    label: hermes_data/.env

snapshot_dir: ~/.agent-snapshots/      # snapshot storage path
retention:
  max_snapshots_per_file: 50           # max snapshots per file, pruned automatically
```

> Legacy (≤0.3.x) `watch` / `daily_time` fields are accepted and ignored — old configs keep working without edits.

> **Where the config is found:** the CLI and the MCP server share one discovery order — the `SNAPSHOT_CONFIG` env var, then `snapshot-config.yaml` in the current directory, then `~/.agent-snapshots/snapshot-config.yaml`. The home-directory fallback lets `agent-snapshot` run from any directory. Malformed fields (e.g. a scalar `retention`, a `protected_files` entry missing `path`) are rejected with a readable error instead of a raw traceback.

## MCP Integration

```json
{
  "mcpServers": {
    "agent-config-snapshot": {
      "command": "uv",
      "args": ["run", "agent-snapshot-mcp"],
      "cwd": "/path/to/agent-config-snapshot-mcp"
    }
  }
}
```

Your agent gets 5 MCP tools:

| Tool | Purpose |
|------|------|
| `list_protected_files` | Discover labels and snapshot counts (the entry point for the other tools) |
| `snapshot(label)` | Manual snapshot (explicitly reports when content is unchanged) |
| `list_snapshots(label)` | History with snapshot_ids |
| `diff_snapshot(label, snapshot_id)` | Compare changes |
| `rollback(label, snapshot_id)` | Roll back (automatic safety snapshot) |

> **Note:** if the agent is completely broken and its MCP server won't start, the CLI (`agent-snapshot rollback`) runs independently — that's your real lifeline.

> **Windows note:** the snapshot directory is hardened best-effort with ACLs (icacls). Since snapshots contain plaintext secrets like .env / auth.json, please verify the directory is accessible only to you.

## Safety & Reliability Design

| Mechanism | Details |
|-----------|--------|
| Pre-rollback snapshot | Every `rollback` first saves the current version as a `safe` snapshot — zero data-loss risk |
| Atomic write-back | Rollback uses temp file + rename; a crash or full disk can't leave a half-written target |
| Integrity check | Every snapshot read verifies sha256 — a corrupted snapshot fails loudly instead of silently restoring bad data |
| Content dedup | Identical content is stored as one blob; repeated baselines and no-op triggers no longer eat retention slots |
| Tolerant index | One corrupted index record loses only itself, never the whole label's history |
| Retention cap | Configurable max snapshots per file, oldest pruned automatically |
| Permission hardening | Snapshot dir forced to `700` (owner-only). ACL (icacls) on Windows |
| Path sanitization | Labels are whitelist-sanitized (Unicode letters/digits plus `_ . -`, CJK preserved), preventing traversal and Windows reserved-name collisions |

## Project Structure

```
agent-config-snapshot-mcp/
├── src/agent_snapshot/
│   ├── __init__.py        # Package init
│   ├── server.py          # MCP server (5 tools + L0/L1 auto capture)
│   ├── service.py         # Use-case layer shared by CLI and MCP
│   ├── store.py           # Content-addressed store (blobs + index.jsonl)
│   ├── migrate.py         # Legacy snapshot import
│   ├── config.py          # Config types and loading
│   ├── cli.py             # Command-line interface
│   ├── compat.py          # Cross-platform layer (POSIX / Windows)
│   ├── presets/           # Presets (hermes / openclaw / claude-code / gemini / codex)
│   └── __main__.py        # python -m entry point
├── tests/                 # Test suite
└── pyproject.toml
```

## Dependencies

- Python ≥ 3.10
- [mcp[cli]](https://github.com/modelcontextprotocol/python-sdk) ≥ 1.0 — MCP protocol
- [pydantic](https://docs.pydantic.dev/) ≥ 2.0 — snapshot record validation
- [PyYAML](https://pyyaml.org/) ≥ 6.0 — config parsing

## License

MIT License

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [TheIanLi](https://github.com/TheIanLi)
- **Source:** [TheIanLi/agent-config-snapshot-mcp](https://github.com/TheIanLi/agent-config-snapshot-mcp)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** yes
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-theianli-agent-config-snapshot-mcp
- Seller: https://agentstack.voostack.com/s/theianli
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
