Skip to main content
Glama
Brandon-35
by Brandon-35

webshot-mcp

Give your agent eyes — without giving it a browser or your network. An MCP server with two tools, screenshot and page_text, that connects to a Chrome you already have running (over CDP) and captures full pages or single elements. No browser is ever launched or downloaded; private-network targets are blocked by an SSRF-aware URL policy.

Why this exists

Two lessons from running visual check → fix loops with coding agents:

  1. Launching a browser per screenshot is the slow, flaky way. A persistent headless Chromium (Docker sidecar, CI service, your desktop Chrome with --remote-debugging-port) is warm, shared, and reliable. The missing piece is a disciplined client: connect over CDP, open a fresh context per shot, close only what you opened, never kill the shared browser. That discipline is this repo.

  2. A screenshot tool inside your network is an SSRF proxy with a camera. An agent that can be talked into "screenshot http://169.254.169.254/…" or http://redis.internal:6379/ will happily photograph your cloud metadata endpoint. So the URL policy blocks loopback, RFC-1918, link-local, CGNAT, and v6-local targets — including hostnames that resolve to them — unless you allowlist the hostname explicitly. Local dev servers are the legitimate exception, and you name them one by one.

Related MCP server: @uicheck/mcp

Quick start

npm install
npm test        # URL-policy test suite — no browser needed
npm run demo    # policy walkthrough + a real screenshot if a CDP Chrome is reachable

Get a CDP-enabled Chrome (any one of):

# your installed Chrome, headless
chrome --headless --remote-debugging-port=9222 --remote-debugging-address=127.0.0.1 about:blank

# or a Docker sidecar you keep running
docker run -d -p 127.0.0.1:9222:9222 chromedp/headless-shell

Wire into Claude Code:

claude mcp add webshot \
  -e WEBSHOT_CDP_URL=http://127.0.0.1:9222 \
  -e WEBSHOT_ALLOW_HOSTS=localhost,127.0.0.1 \
  -- npx tsx src/server.ts

Then ask the agent things like "screenshot the hero section of localhost:5173 — just .hero — and tell me what's off": selector crops to one element, which keeps the agent's attention (and your tokens) on the part under discussion instead of a 4,000-px page.

Tools

Tool

Contract

screenshot

url, optional selector (element crop), fullPage, viewport width/height, settleMs. Returns the PNG as MCP image content + {finalUrl, title, httpStatus}. Refuses to capture HTTP ≥ 400 — a screenshot of an error page silently poisons whatever the agent does next.

page_text

Body innerText — the cheap check when the agent needs to read, not see. Same URL policy.

Design notes

  • Fresh context per shot, shared browser for life. Contexts are cheap and isolated (cookies, cache, viewport); the browser is expensive and shared. browser.close() on a CDP connection disconnects without killing the remote browser — the server can restart all day without touching Chrome.

  • DNS is checked, rebinding is documented. Non-IP hostnames are resolved and every returned address re-verified against the private ranges. A malicious DNS server that answers differently on the browser's own second resolution (classic rebinding) is out of scope for a screenshot tool — noted here rather than hand-waved.

  • deviceScaleFactor: 2 — retina captures, because agents (and humans) misread blurry text in screenshots more often than you'd think.

  • Policy is fail-closed and testable. evaluateUrl is a pure function with the entire threat table in its test file; the server never calls the browser before the policy says yes.

Stack

TypeScript · @modelcontextprotocol/sdk (stdio) · playwright-core (CDP client only — no bundled browsers) · zod · vitest.

License

MIT © Brandon Ta

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables AI assistants to control and inspect a live Chrome browser for automated web debugging, performance analysis, and Lighthouse audits. It allows agents to capture screenshots, monitor network requests, and measure Core Web Vitals using plain-English prompts.
    1,516,489 npm
    Apache 2.0
  • A
    license
    A
    quality
    C
    maintenance
    Enables AI agents to control a persistent Chromium browser or attach to an existing Chrome with sandboxed JavaScript and structured tools for web interaction and automation.
    16
    MIT