{
  "markdown": "<p align=\"center\">\n  <img src=\"assets/logo.png\" alt=\"SnapStack\" width=\"440\">\n</p>\n\n<p align=\"center\">\n  <a href=\"https://github.com/bgaze/snapstack-server/actions/workflows/ci.yml\"><img src=\"https://github.com/bgaze/snapstack-server/actions/workflows/ci.yml/badge.svg\" alt=\"CI\"></a>\n  <a href=\"LICENSE\"><img src=\"https://img.shields.io/github/license/bgaze/snapstack-server?color=blue\" alt=\"License: MIT\"></a>\n  <img src=\"https://img.shields.io/badge/node-%3E%3D18-brightgreen\" alt=\"Node >= 18\">\n  <a href=\"https://modelcontextprotocol.io\"><img src=\"https://img.shields.io/badge/MCP-compatible-blueviolet\" alt=\"MCP compatible\"></a>\n  <img src=\"https://img.shields.io/badge/100%25-local-success\" alt=\"100% local\">\n  <a href=\"https://www.npmjs.com/package/snapstack-server\"><img src=\"https://img.shields.io/npm/v/snapstack-server?label=npm\" alt=\"npm version\"></a>\n  <a href=\"https://www.npmjs.com/package/snapstack-server\"><img src=\"https://img.shields.io/npm/dm/snapstack-server?label=downloads\" alt=\"npm downloads\"></a>\n  <a href=\"https://glama.ai/mcp/servers/bgaze/snapstack-server\"><img src=\"https://glama.ai/mcp/servers/bgaze/snapstack-server/badges/score.svg\" alt=\"Glama score\"></a>\n</p>\n\n<p align=\"center\">\n  <img src=\"assets/demo.gif\" alt=\"SnapStack demo — capture a browser tab, your AI reads the screenshots over MCP\" width=\"900\">\n</p>\n\nThe **SnapStack server** is a single always-on Node process: it receives browser captures from the\n[extension](https://github.com/bgaze/snapstack-extension), stacks them on disk, and serves them to any\nMCP-capable LLM client over **Streamable HTTP**. It listens only on `127.0.0.1` — nothing ever leaves your machine.\n\n> **New here?** The full install + usage guide lives in the **extension README**:\n> **[snapstack-extension](https://github.com/bgaze/snapstack-extension)**. This page is the technical reference.\n\n## Architecture\n\nOne always-on process serves both the extension (capture) and your MCP client, decoupled by a folder on disk.\n\n```\n[MV3 extension]  --POST /push (bytes) ┐\n                                      ▼\n                              [SnapStack server - 127.0.0.1:4123]   \n                                 ├─ writes           →  stack on disk\n                                 └─ MCP /mcp (HTTP)  ←  MCP client\n```\n\n- **Capture** — the extension encodes the shot as WebP (PNG fallback), downscales it, and POSTs it here.\n- **Stack** — one image file (`.webp`/`.png`) plus a twin `.json` (url, title, timestamp, dimensions) per capture,\n  named `NN <timestamp>`: a stable two-digit **number** (assigned in capture order, restarts at `01` when the stack\n  empties) plus a timestamp, under `~/.snapstack/`.\n- **Retrieval** — `get_screenshots` returns a JSON **manifest** (number, absolute path, dimensions, metadata —\n  *no image bytes*); the client reads only the files it needs, by path. Deletion is a separate, explicit\n  `clear_screenshots` step. **Retrieval never deletes.**\n\n## Requirements\n\n- **Node.js ≥ 18** (tested on Node 20). No git needed at runtime.\n- An **MCP-capable LLM client** speaking the **HTTP** (Streamable HTTP) or **stdio** transport.\n- The **[snapstack-extension](https://github.com/bgaze/snapstack-extension)** loaded in your browser.\n\n## Install & run\n\n> On Windows, **use an Administrator terminal**, otherwise the global npm install and the scheduled-task registration\n> may get rejected.\n\nThe server ships on npm and installation is straightforward on macOS, Linux and Windows:\n\n1. Install globally: `npm i -g snapstack-server`\n2. Enable background service: `snapstack enable`\n\nSnapStack auto-starts on login, restarts on crash, and updates itself on each launch.  \nTo check its status or if an update is available, simply run `snapstack` in your terminal.\n\nAvailable commands:\n\n```bash\nsnapstack                            # status report: service + server health, update check\nsnapstack start | stop | restart     # control the running service (this session)\nsnapstack update                     # update the CLI (npm i -g) + restart the server on the latest\nsnapstack run                        # run the daemon in the foreground (no auto-start)\n```\n\nThe **daemon** self-updates on each (re)start/login; the **global CLI** (the `snapstack` command) does not.\nRun `snapstack update` to bring **both** to the latest in one go.\n\nThe full end-to-end walkthrough (idiomatic install paths, MCP client registration, the extension) is in the\n**[extension README](https://github.com/bgaze/snapstack-extension)**.\n\n## MCP\n\nSnapStack speaks two MCP transports over the same on-disk stack — pick whichever your client supports:\n\n```jsonc\n// HTTP (server already running) — register http://127.0.0.1:4123/mcp; copy deploy/mcp.json\n{ \"type\": \"http\", \"url\": \"http://127.0.0.1:4123/mcp\" }\n```\n\n```jsonc\n// stdio (the client spawns the process)\n{ \"command\": \"npx\", \"args\": [\"-y\", \"-p\", \"snapstack-server\", \"snapstack\", \"mcp\"] }\n```\n\nThe HTTP `/mcp` endpoint is **stateless** (a fresh server + transport per request); the stdio front-end\n(`snapstack mcp`) is spawned on demand and reads the same `~/.snapstack` stack.  \nCapture intake (`/push`) always stays in the running server, independent of either MCP front-end.\n\n### Exposed tools\n\n| Tool                | Description                                                                                                                                                                         |\n|---------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| `get_screenshots`   | Lists pending captures as a JSON manifest (stable number, absolute path, dimensions, metadata) — **no image bytes, no deletion**. Pass `numbers` (e.g. `[1,3]`) to list only those. |\n| `clear_screenshots` | Deletes captures. Pass `numbers` to delete specific ones; omit to clear the whole stack. Numbering restarts at `01` once empty.                                                     |\n| `count_screenshots` | Number of pending captures, without retrieving them.                                                                                                                                |\n\n`get_screenshots` and `count_screenshots` are **read-only**; only `clear_screenshots` is **destructive**. \n\n## Configuration\n\n### Environment variables (infrastructure)\n\n| Variable         | Default        | Purpose                                 |\n|------------------|----------------|-----------------------------------------|\n| `SNAPSTACK_DIR`  | `~/.snapstack` | Stack folder.                           |\n| `SNAPSTACK_PORT` | `4123`         | Listening port (always on `127.0.0.1`). |\n\n### Capture policy (shared across your browsers)\n\nThe encoding/capture settings are **owned by the server** and stored in `~/.snapstack/config.json`, so a single\nedit applies to **every browser** running the extension. They are edited from the extension's **options page** — not\nan environment variable — and fetched by the extension before each capture.\n\n| Key         | Default | Meaning                                                                   |\n|-------------|---------|---------------------------------------------------------------------------|\n| `format`    | `webp`  | Image format: `webp`, `png` or `jpg`.                                     |\n| `quality`   | `0.85`  | Lossy quality (`0`–`1`; the extension UI shows it as a percentage).       |\n| `maxWidth`  | `1568`  | Downscale captures wider than this to this width in px (`0` = no resize). |\n| `maxSlices` | `50`    | Full-page capture: hard cap on stitched slices.                           |\n\nTwo endpoints back it: `GET /config` returns the effective policy; `POST /config` validates and replaces it (host- +\nCORS-guarded like every capture route). The file is a non-image, so a stack clear never touches it; deleting it just\nrestores the defaults above.\n\n## Troubleshooting\n\n- **Capture server not started message in the extension:** run `snapstack start` (or `snapstack run` in the foreground),\n  or check the auto-start with `snapstack`. Test: `curl http://127.0.0.1:4123/health`.\n- **Port already in use (`EADDRINUSE`):** set `SNAPSTACK_PORT` to another value.\n- **`snapstack: command not found` after switching Node version** (nvm, fnm, volta, Laravel Herd, nvm-windows): `npm i -g`\n  drops the `snapstack` command in the global bin of the Node version that was active at install time only, so switching\n  versions hides it. This is how npm globals work, not a SnapStack bug — the **background service is unaffected and keeps\n  capturing**; only the CLI command disappears. Fix: re-run `npm i -g snapstack-server` under the current Node version (or\n  switch back to the one used at install).\n- **The client doesn't see the tools:** the server must run **before** the MCP client starts; check the config\n  (`type: \"http\"`, correct URL). Direct test: `curl http://127.0.0.1:4123/count`.\n- **Inspect the stack:** `ls ~/.snapstack` (image files + human-readable `.json`).\n\n## Support\n\n- **A question or an idea?** → [GitHub Discussions](https://github.com/bgaze/snapstack-server/discussions)\n- **Found a bug?** → [open an issue](https://github.com/bgaze/snapstack-server/issues)\n\n## License\n\nMIT — see [LICENSE](./LICENSE).\n",
  "bytes": 9342,
  "sha": "4a743d0016100736caa3f21cf648812eac8e45cac90001566d9f6d177daf28e4",
  "repo_slug": "bgaze/snapstack-server",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_bgaze_snapstack_server_6d97339e/readme"
}