
alicepagano/claude_web_annotator
Developer toolsDraw boxes on any website, attach TODOs and questions, and send them with screenshots and DOM context to Claude Code via MCP. Zero-dependency Node.js.
Overview
Web Annotator lets you review a site in your browser the way you'd mark up a printout: drag a box over something, type a ("make this headline smaller") or a ("why is this grey?"), and keep going. When you're done, send everything as one batch. Each box carries a screenshot and the page structure underneath it (headings, element ids, text, CSS paths), so an AI agent knows exactly what you mean and where it lives in the code. - : a local dev server (Vite, Next, webpack, with hot reload), a folder of static files, or a public URL. - : every box records a cropped screenshot, the section it's in, the elements inside it, and their ids, classes and data-src attributes. - : an included MCP server lets Claude read your batches, look at the screenshots, and work through them item by item. - : plain Node.js, no npm install, no build step. Open . A small demo site loads so you can try it straight away. To review your own project, start its dev server as usual and point the annotator at it: 1.
README
Web Annotator
Draw boxes on any website, say what you want changed, and hand the whole list to Claude.
Web Annotator lets you review a site in your browser the way you’d mark up a printout: drag a box over something, type a TODO (“make this headline smaller”) or a Question (“why is this grey?”), and keep going. When you’re done, send everything as one batch. Each box carries a screenshot and the page structure underneath it (headings, element ids, text, CSS paths), so an AI agent knows exactly what you mean and where it lives in the code.
- Works with what you’re building: a local dev server (Vite, Next, webpack, with hot reload), a folder of static files, or a public URL.
- Precise feedback: every box records a cropped screenshot, the section it’s in, the elements inside it, and their
ids, classes anddata-srcattributes. - Made for Claude Code: an included MCP server lets Claude read your batches, look at the screenshots, and work through them item by item.
- Zero install: plain Node.js, no
npm install, no build step.
Quick start
You need Node.js 20 or newer.
git clone https://github.com//web-annotator.git
cd web-annotator
npm run demo
Open http://127.0.0.1:8790/__wa/. A small demo site loads so you can try it straight away.
To review your own project, start its dev server as usual and point the annotator at it:
node app/main.mjs --site localhost:5173
How to use it
- Press
B(or click Box) and drag a box over anything on the page. Scrolling still works while you draw. - Choose TODO or Question, type your note, and press Save (
Ctrl/Cmd + Enter). - Keep browsing. Navigate with the site’s own links or the address bar. Each page keeps its own boxes, and nothing is lost if you reload.
- Click Send selected. The batch is saved as a folder with
message.md,batch.jsonand onebox-NN.pngper box. Copy the message into any AI chat, or let Claude Code pick it up through MCP (below).
| Key | Action |
|---|---|
B |
Toggle Box mode (Alt + B works even while typing) |
Esc |
Cancel a drag → close the card → leave Box mode |
Delete / Backspace |
Delete the open box (when you’re not typing) |
Ctrl/Cmd + Enter |
Save the open box |
The List drawer groups boxes by page. From there you can pick which ones to send, jump to a box, edit it, or delete it.
What the agent receives
Annotations on localhost (1 TODO, 1 question) — batch folder: ~/web-annotator-batches/2026-10-15_18-25-02
Site: http://localhost:5173
Reply item by item: for each, first restate it as '#n [TODO|Question] — "" — ', then give the answer / say what was changed.
## TODO
1. [#1 · page http://localhost:5173/ · "Coffee roasted around the corner."] Headline feels too big on laptops — try ~56px.
context: h1 "Coffee roasted around the corner."
screenshot: ~/web-annotator-batches/2026-10-15_18-25-02/box-01.png
## Questions
1. [#2 · page http://localhost:5173/ · section "This week's beans" (#beans) · data-src content/beans/colombia.md] Can we show tasting notes as tags?
context: article.card "Colombia Huila Red apple, caramel and cocoa…" (data-src content/beans/colombia.md)
screenshot: ~/web-annotator-batches/2026-10-15_18-25-02/box-02.png
Full context: ~/web-annotator-batches/2026-10-15_18-25-02/batch.json
Use with Claude Code
Register the MCP server once, using the absolute path to your clone:
claude mcp add web-annotator -- node /path/to/web-annotator/mcp/server.mjs
After sending a batch, just tell Claude:
Handle my latest annotation batch.
Claude reads the message and screenshots, makes each change or answers each question, and marks the batch as done.
| Tool | What it does |
|---|---|
list_annotation_batches |
Lists batches, newest first (include_done, limit) |
get_annotation_batch |
Returns the message, up to 12 screenshots, and optionally the full batch.json (batch_id = latest_pending / latest / an id) |
mark_annotation_batch_done |
Marks a batch as handled, with an optional note |
If you save batches somewhere other than the default, give the MCP server the same folder with --batch-root or WEB_ANNOTATOR_BATCH_ROOT.
Options
node app/main.mjs [--port 8790] [--site ] [--batch-root ] [--data-dir ]
| Option | Default | |
|---|---|---|
--port |
8790 |
Listens on 127.0.0.1 only |
--site |
last used | localhost:5173, https://example.com/docs, ~/project/dist, ./site |
--batch-root |
~/web-annotator-batches |
Also settable with WEB_ANNOTATOR_BATCH_ROOT |
--data-dir |
~/.config/web-annotator |
Settings and screenshots not yet sent |
You can also switch sites at any time from the address bar or the ⚙ settings panel.
How it works
The annotator needs to read the page’s DOM to capture context and screenshots, which browsers only allow when the page is same-origin. So one local server serves both:
/__wa/: the annotator UI and its small JSON API.- Everything else: your site. Folders go through a hardened static server (it blocks path traversal and symlink escapes, and falls back to
index.htmlfor single-page apps). URLs go through a reverse proxy that removes framing and CSP headers, rewrites absolute links to stay on the proxy, and tunnels WebSockets so hot reload keeps working.
A small script injected into each page disables service workers and keeps fetch, XHR, WebSockets and links pointed at the proxy. Screenshots are rendered from the DOM with html-to-image (vendored, MIT).
app/
main.mjs HTTP server: UI, JSON API, static server, proxy routing
proxy.mjs reverse proxy + WebSocket tunnel
lib.mjs pure helpers (site parsing, safe paths, rewriting, message builder)
inject.js shim injected into every reviewed page
index.html, annotator.js, styles.css, welcome.html
vendor/ html-to-image 1.11.13 + LICENSE
mcp/server.mjs stdio MCP server (no dependencies)
examples/ demo site
selfcheck.mjs test suite
Limitations
Web Annotator is a local review tool. These trade-offs are worth knowing:
- Logged-in pages mostly don’t work. The real domain’s cookies aren’t sent, and SSO/OAuth flows break. It works best on local dev servers and public pages.
- APIs on other subdomains may fail CORS.
- Links to other domains leave the frame. A banner offers Back to site.
- Screenshots are rendered from the DOM, not captured from the screen. Cross-origin images, fonts and WebGL can come out blank, and layers that sit outside the boxed element (for example a background photo behind a text block) may be missing.
- Reviewed sites share the annotator’s origin, including
localStorageand cookies.
Security and privacy
- The reviewed page runs on the same origin as the annotator UI, so its scripts could drive the UI. Only open sites you trust.
- The server binds to
127.0.0.1only. Don’t expose it to a network: it would act as an open proxy. - Screenshots and page text are sent to whichever AI model reads the batch. Only send content you’re allowed to share with it.
Development
npm test # or: node selfcheck.mjs
The self-check uses only node:assert. It covers site parsing, path-traversal blocking (unit tests and raw HTTP), static serving, HTML injection, origin rewriting, the proxy end to end against a throwaway upstream (gzip/brotli, header stripping, redirects, binaries, POST bodies, WebSockets, 502s), the exact message format, and the MCP server. If Chrome is installed, it also drives the real UI headlessly over the DevTools protocol: it draws boxes, types, takes screenshots, navigates, and sends a batch. Set CHROME_PATH to use a specific browser.
License
MIT. Includes html-to-image (MIT, © W.Y.).
Install
This server does not publish a one-line install command.
Open the repository installation guideConfiguration
{
"mcpServers": {
"web-annotator": { "command": "node", "args": ["/path/to/web-annotator/mcp/server.mjs"] }
}
}