---
title: "Give Claude Eyes: A Screenshot MCP Server With 23 Tools"
description: "A screenshot app with a built-in MCP server: 23 tools, file paths not base64, memorable keywords, headless capture. Setup in two minutes."
canonical: https://giglabo.com/blog/hls/screenshot-mcp-server
locale: en
---

# Give Claude Eyes: A Screenshot MCP Server With 23 Tools

> Markdown twin of https://giglabo.com/blog/hls/screenshot-mcp-server
> Fetch this instead of the HTML page: same content, a fraction of the bytes.
> Site structure and the full page list for agents: https://giglabo.com/llms.txt

A screenshot app with a built-in MCP server: 23 tools, file paths not base64, memorable keywords, headless capture. Setup in two minutes.

One. That is the tool count in most screenshot MCP servers on GitHub. One `take_screenshot`, base64 in, base64 out, and the README calls it done.

We counted before building ours. Our server ended up with 23 tools, and seven of them capture pixels. The other sixteen exist because capture turned out to be the easy part. Naming, finding, marking, reading: that is where the work went.

## Why agents need screenshots at all

Language models live in text. Work happens on a screen. The gap shows up on a schedule:

- Someone asks Claude Code to fix a layout bug it cannot see.
- An error dialog refuses text selection, so the stack trace travels by hand.
- The agent "finishes" a UI change and announces it should look right. Should, because it never looked.
- The human becomes the render farm. Run, screenshot, paste, repeat.

All four are the same missing capability. The screen holds the truth, and the agent needs a sanctioned, predictable way to look at it. Plus a way to manage what it looked at.

A pile of unnamed PNGs is a junk drawer, not a library.

## What exists today

Credit where due: the space isn't empty. [Peekaboo](https://peekaboo.sh) pioneered agent screenshots on macOS, a CLI-first tool built around capture-and-analyze vision QA, and it does that job well. On a Mac, for a command-line bridge between the screen and a vision model, it earns its place.

GitHub also hosts dozens of small "screenshot MCP" repos. Most wrap a single capture call, return the image as base64, and stop. They prove the demand. They also mark the ceiling of the one-tool approach: no library, no naming, no annotation, no memory of anything before this session.

"Minimal" is the selling word in those READMEs. Translate it. Minimal means the server does the least possible and the agent improvises the rest in prose, every session, from scratch. That's not minimalism. It's the job left half-described.

## One app, two interfaces

Lazy Shot starts from the other end. A full screenshot application first: capture, annotate, blur, beautify, a searchable library, on macOS and Windows. The MCP server exposes the same application headlessly. Same capture engine. Same library with search and soft delete. Same marker system. Same files on disk.

The human works in the overlay. The agent works through 23 tools. Both look at one library.

That single decision is what turns "the agent can take a screenshot" into "the agent can run a screenshot workflow." The server isn't a demo bolted onto the app. It's the app with the windows turned off.

## The 23 tools, by group

The tools split into four groups, on purpose. Capture makes pixels. Manage makes them findable. Markers make them explainable. And OCR reads the ones nobody explained.

### Capture (7 tools)

Headless, silent except for a brief flash notification. No overlay pops up; the human keeps typing.

| Tool | What it does |
|---|---|
| `capture_region` | Pixel-exact coordinates on any display |
| `capture_window` | Fuzzy-match a window by title or process name |
| `capture_display` | A whole monitor, by index or name |
| `capture_active_window` | Whatever has focus right now |
| `capture_tracked_window` | A window from the recent-focus stack, "the one I was just in" |
| `list_displays` | Monitor geometry, for multi-display math |
| `list_tracked_windows` | The recently-focused-windows stack (opt-in Window Activity Tracker) |

`capture_tracked_window` needs one more paragraph. The Window Activity Tracker is an opt-in feature flag in Settings → Experimental, off by default. When on, Lazy Shot keeps an LRU stack of recently focused windows, capacity 20. So "grab the window I was just looking at" maps to a tool call instead of a guessing game.

### Manage (8 tools)

| Tool | What it does |
|---|---|
| `list_screenshots` | Browse the library with filters and sorting |
| `search_screenshots` | Full-text search by keyword or filename, date ranges |
| `get_screenshot` | Metadata for one screenshot |
| `open_screenshot` | Open it in the viewer, bring the window forward |
| `assign_keyword` | Give a capture a short, memorable name |
| `delete_screenshot` | Soft delete, nothing is ever destroyed |
| `get_app_status` | Version, counts, storage, settings |
| `show_window` | Bring the app's main window forward |

`assign_keyword` is the one that pays off later. Agents name each capture with a short word: `login-bug`, `rabbit`, `checkout-step-3`. Not a UUID, not a timestamp. Collisions get a numeric suffix, `login-bug-2`, and the tool returns the final keyword, which the agent uses from then on. Days later, in a different session, "find login-bug" just works.

### Markers (5 tools)

| Tool | What it does |
|---|---|
| `add_markers` | Place numbered markers, on a **copy** |
| `edit_screenshot` | Apply edits to a saved screenshot, on a copy |
| `list_marker_presets` | Saved marker layouts |
| `get_marker_preset` | One preset in detail |
| `search_marker_presets` | Find presets by name |

The rule that matters: markers fork, never mutate. An agent that annotates a screenshot gets an annotated copy. The original stays pristine. Nobody loses the clean evidence because an agent decided to draw on it.

### OCR (3 tools)

| Tool | What it does |
|---|---|
| `ocr_screenshot` | Text out of a screenshot already in the library |
| `ocr_image_path` | Text out of any image file by path |
| `list_ocr_languages` | The OCR languages available on this machine |

One caveat before the FAQ gets there first: OCR over MCP runs on macOS only right now. Phase 1. The rest of the server is cross-platform; these three are not, yet.

### Why twenty-three tools and not one

Every minimal screenshot MCP ships the same thing: one `take_screenshot` returning base64. The demo looks great. Then the first real session starts, and real sessions are mostly not capture. They are "find the shot from Tuesday," "name this so we can talk about it," "mark steps 1 to 3 on a copy," "which monitor is the browser on." One tool forces the agent to improvise all of that in prose.

Handing an agent one capture tool and no library is giving a carpenter a saw and no workbench. The cut isn't the job.

Capture doesn't need twenty-three tools. Workflows do.

Narrow tools with obvious names are also the ones agents call correctly on the first try.

The taxonomy is the interface.

### Resources and built-in prompts

Beyond tools, the server publishes auto-updating MCP resources: `screenshots://recent` for the live tail of the library, `config://displays` and `config://settings` for current geometry and preferences, and per-screenshot metadata at `screenshots://{id}/metadata`. Clients that support resources get ambient context without spending a tool call. The agent can know what was just captured before deciding to look.

Two workflow prompts ship in the box: `document-ui-flow` and `batch-capture`. Both encode the multi-step routines people request most, so nobody has to prompt-engineer them by hand. Both show up below.

## Design principles, the short version

Five decisions shape how the server behaves. They have their own article: file-path-first MCP design. Here is the summary.

1. **File paths, never base64.** Every tool that touches an image returns a `file_path`, not an inline blob. A path costs about 20 tokens. A base64 blob isn't an answer. It's a bill the context window keeps paying for the rest of the session. The agent reads pixels only when the task requires looking.
2. **Memorable keywords, not UUIDs.** Recall by short words, for humans and agents alike.
3. **Markers fork, never mutate.** Annotation is additive by construction.
4. **Capture is headless and directed.** No overlay interrupts anyone, and no shot happens silently. Every capture is an explicit tool call, and every capture flashes a notification. The agent has eyes, not surveillance.
5. **Everything lands in one log.** Every operation writes to a single rotating file, `heretic-lazy-shot_<timestamp>.log` in `~/.heretic-lazy-shot/logs/`. Rotation at 10 MB or 24 hours, whichever comes first. MCP lines carry an `[MCP]` tag, so one grep isolates the agent's trail. When an agent misbehaves, the log says what happened. Reading beats guessing.

## Two-minute setup

The switch lives in Settings → MCP. The default endpoint is `http://localhost:5055/mcp`, streamable-http. If 5055 is busy, the server tries the next port, up to 10 attempts, and shows the real endpoint in the UI.

The server binds to 127.0.0.1 out of the box, because local agents are the target. Rebinding to 0.0.0.0 takes one toggle in Settings → MCP. Flip it with open eyes: the screenshots on that machine become reachable from whatever network the machine sits on.

**Claude Desktop.** Add to `claude_desktop_config.json`:

```json
{
 "mcpServers": {
 "heretic-lazy-shot": { "url": "http://localhost:5055/mcp" }
 }
}
```

**Claude Code.** One command:

```bash
claude mcp add --transport http heretic-lazy-shot http://localhost:5055/mcp
```

**n8n (self-hosted).** MCP Client node:

```json
{ "serverUrl": "http://localhost:5055/mcp", "transport": "streamable-http" }
```

Restart the client and ask what MCP tools it has. The answer should list 23.

## Three worked examples

### 1. Document a UI flow, with numbered steps

The built-in `document-ui-flow` prompt runs the loop documentation teams do by hand. Capture each step of a flow, keyword it (`onboarding-step-1`, `onboarding-step-2`, and so on), then place numbered markers on the elements worth explaining. Markers land on annotated copies; originals stay untouched. The output is a set of named, ordered, annotated images ready for docs. After the next release, the agent re-captures the same keyword list and reapplies the same marker preset. Documentation screenshots become build artifacts instead of files that rot.

### 2. Batch-capture everything touched today

The second built-in prompt, `batch-capture`, pairs `list_tracked_windows` with a capture loop: list the recently focused windows, capture each, keyword each. One agent run turns "screenshot every screen before the release" from a skipped chore into a checklist with file paths. The same pattern sweeps every monitor via `list_displays` plus `capture_display`. Dashboards, ops walls, and whatever else counts as a monitor.

### 3. "Grab the window I was just in"

The smallest example and the most-used one. Here it is as it happens.

Late afternoon. We're in the editor, and an error toast pops up in the app window behind it. No alt-tab. One sentence into Claude Code: grab the window I was just in and tell me what that error means. The agent calls `capture_tracked_window`, gets a file path back, reads the image. CORS failure on `api.example.dev`, preflight rejected. The evidence lands in the library under a keyword, searchable next week.

What made that work was the file-path contract. The tool response was a 20-token path, not a payload. The agent chose to read the pixels because the question required it. In a bookkeeping call, "capture and file this for later," it would not have. Multiply that decision across a 30-step session and it separates an agent that finishes from an agent that drowns in its own screenshots.

A whole book of these patterns lives in the [Lazy Shot Cookbook](https://github.com/GigLaboCom/lazy-shot-cookbook) on GitHub: a self-verifying UI loop for Claude Code, visual bug-fixing, pairing with Playwright, n8n monitoring. Public recipes, copy-paste prompts, a drop-in `CLAUDE.md`.

## What this is not

Honesty section, because the gaps are findable anyway. Lazy Shot's MCP doesn't click, type, or drive a browser. Eyes, not hands. Pair it with Playwright MCP or any computer-use tool for actions. No scrolling capture. No video recording. The file-path contract ties the server to agents on the same machine: Claude Desktop, Claude Code, Cursor, self-hosted n8n. Remote SaaS runners can't read the disk, so the paths mean nothing to them.

"Eyes, not hands" isn't modesty. It's a boundary. Three of the 23 tools respect another one: OCR runs on macOS only for now, and the Windows side is on the list, not in the build.

## FAQ

**Does the agent see my screen all the time?**
No. Nothing is ambient. Every capture is an explicit tool call, and every capture fires a visible flash notification. No call, no capture.

**Do screenshots leave my machine?**
Not through Lazy Shot. Capture, storage, search, and OCR all run locally, and the app phones home for nothing. No telemetry exists to disable. If the agent reads a screenshot with a cloud model, those pixels go to that model's provider. That's the agent's behavior, and worth knowing.

**Which clients work?**
Anything speaking MCP over streamable-http: Claude Desktop, Claude Code, Cursor, n8n's MCP Client node, and the growing rest.

**Can two agents use it at once?**
Yes. A local HTTP server, one shared library. One agent captures during a session; another finds the evidence next week.

**What about Peekaboo?**
Different thesis, honest respect. [Peekaboo](https://peekaboo.sh) is CLI-first, macOS-only, centered on capture-and-analyze vision QA. Lazy Shot is a GUI app for humans that agents share, cross-platform, centered on the library and workflows. Some people run both.

**What if port 5055 is taken?**
The server tries the next port, up to 10 attempts, and shows the actual endpoint in Settings → MCP. Point the client at what the UI says, not at what a blog post says.

**Does it work with local models?**
Yes. The server doesn't care what brain sits on the other end. Captures never leave the machine, and reading happens wherever the model runs. A local model makes the whole pipeline end-to-end offline.

**Something failed. Where do I look?**
`~/.heretic-lazy-shot/logs/` first. One rotating file, `heretic-lazy-shot_<timestamp>.log`, MCP lines tagged `[MCP]`. For a bug report, Settings → System has a copy system info button. Agents can check `get_app_status` themselves before retrying.

---

**Heretic Lazy Shot** is the app this server lives in. macOS and Windows. One-time license: €14.99 for one device, €29.99 for three. No subscription. No account. No telemetry. The trial ships inside the download.

[Heretic Lazy Shot](https://giglabo.com/heretic/applications/heretic-lazy-shot)

If your agent still asks you to paste screenshots, that part is fixable.

## Related

- HTML version of this page: https://giglabo.com/blog/hls/screenshot-mcp-server
- Site map for agents: https://giglabo.com/llms.txt
