screenshot-vision-mcp
Allows capturing screenshots of Google Chrome windows and analyzing them with a local vision model, including locating UI elements and returning click coordinates.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@screenshot-vision-mcp What does the example.com landing page look like?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
screenshot-vision-mcp
When reviewing a PR locally, you need to see if the UI looks right. Normally that means Claude takes a screenshot — which burns vision tokens and sends your screen contents to Anthropic. This MCP server routes screenshots through a local Ollama vision model instead: zero token cost, nothing leaves your machine.
Tool | When to use |
| Public or local URLs — headless browser, no session needed |
| Any app window on screen — sees your real logged-in session |
| Native macOS apps only — returns click coordinates without Claude seeing the image |
Chrome automation: for clicking elements in Chrome, prefer
javascript_tool + getBoundingClientRect— it's exact and requires no vision at all. See Clicking in Chrome.
Requirements
macOS (window capture uses
screencaptureand AppleScript)Node.js 22+
Ollama installed (the server auto-starts it if it isn't running)
A multimodal Ollama model — default is
gemma4:e4b:ollama pull gemma4:e4b
Related MCP server: Screen Vision MCP Server
Installation
git clone git@github.com:AVS845/screenshot-vision-mcp.git
cd screenshot-vision-mcp
npm install
npx playwright install chromium
npm run buildClaude Code configuration
Add this to your ~/.claude/settings.json under mcpServers:
{
"mcpServers": {
"screenshot-vision": {
"command": "node",
"args": ["/absolute/path/to/screenshot-vision-mcp/dist/index.js"]
}
}
}Replace /absolute/path/to/ with the actual path. Then restart Claude Code.
Two optional env vars let you configure the server without touching call sites:
Variable | Default | Description |
|
| Ollama host |
|
| Default vision model for all tools |
Tools
analyze_screenshot
Takes a screenshot of a URL in a headless Playwright browser and analyzes it with Ollama.
analyze_screenshot(
url: "http://localhost:3004/dashboard",
question: "Does the revenue chart render correctly? Are there any layout issues?"
)Parameter | Type | Default | Description |
| string | — | URL to screenshot |
| string | — | What to analyze |
| string |
| Ollama vision model |
| number |
| Viewport width in px |
| number |
| Viewport height in px |
| number |
| Wait after page load (ms) |
| boolean |
| Capture full page height, not just the visible viewport |
| number |
| Max slices when |
When full_page: true, the page is sliced into viewport_height-tall segments and sent as multiple images. This matters because Gemma 4's image token budget is ~280 tokens — a single tall screenshot gets crushed into noise, while properly-proportioned slices each get full detail.
capture_window
Captures an app window currently on screen and analyzes it. Use this when the page requires a login — it sees your real browser session.
capture_window(
app_name: "Google Chrome",
question: "Is the form validation error displaying correctly under the email field?"
)Parameter | Type | Default | Description |
| string | — | Exact macOS app name, e.g. |
| string | — | What to analyze |
| string |
| Ollama vision model |
| number |
| Which window (1 = frontmost) |
| number |
| Upscale factor (2–3 helps with small text) |
| object | — | Crop to a sub-region before analysis |
The crop parameter uses fractional values (0–1). To inspect just the bottom half of the window:
{ "x": 0, "y": 0.5, "width": 1, "height": 0.5 }locate_element
Finds a UI element in a native macOS app window and returns its click coordinates. Designed for apps where DOM access isn't available — Terminal, Figma, Xcode, etc.
Not recommended for Chrome. Chrome's DOM gives exact coordinates with no vision model involved. See Clicking in Chrome.
Parameter | Type | Default | Description |
| string | — | Exact macOS app name, e.g. |
| string | — | Natural language description of the element |
| string |
| Ollama vision model |
| number |
| Which window (1 = frontmost) |
| object | — | Screen-coordinate bounds of the region to capture |
Returns { x, y, coordinate_mode, clamped }. clamped: true means the model returned out-of-range coordinates that were corrected — treat as low confidence.
Accuracy note: gemma4:e4b has a ~280-token image budget, which limits spatial precision. Elements in the center of the screen locate reliably; elements near edges may have 50–150px errors. Use a larger model (e.g. gemma4:26b) if precision matters, at the cost of slower inference.
Clicking in Chrome
For Chrome browser automation, skip locate_element entirely. Use javascript_tool to get exact coordinates from the DOM:
// In javascript_tool — returns perfect viewport coordinates, no vision needed
const el = document.querySelector('button.submit');
const r = el.getBoundingClientRect();
JSON.stringify({ x: Math.round(r.left + r.width/2), y: Math.round(r.top + r.height/2) });Only fall back to locate_element for elements that genuinely can't be DOM-queried (canvas content, rendered images, visually-composed widgets without CSS selectors). When you do, pass viewport_bounds so the returned coordinates are viewport-relative and work directly with the Chrome computer tool.
Measure viewport bounds immediately before the call — the Chrome automation InfoBar shifts innerHeight, causing ~40px errors with stale bounds:
// javascript_tool — run right before locate_element
JSON.stringify({
screenX: window.screenX,
screenY: window.screenY,
outerHeight: window.outerHeight,
innerWidth: window.innerWidth,
innerHeight: window.innerHeight,
})locate_element(
app_name: "Google Chrome",
element_description: "the close button on the confirmation modal",
viewport_bounds: {
x: screenX,
y: screenY + outerHeight - innerHeight,
width: innerWidth,
height: innerHeight,
}
)
→ { x: 891, y: 267, coordinate_mode: "viewport" }How it works
analyze_screenshotlaunches a headless Chromium browser via Playwright, navigates to the URL, waits for JS to settle, and captures a PNG.capture_windowuses AppleScript to get the window bounds,screencapture -Rto grab exactly that region, and optionallysipsto crop and scale.locate_elementcaptures the specified region, asks Ollama to return element coordinates as JSON fractions (0–1), then converts to pixel coordinates.All tools base64-encode the PNG and POST it to Ollama's
/api/generateendpoint.If Ollama isn't running, the server spawns
ollama serveand waits up to 30 seconds for it to become ready.
Rebuilding after changes
npm run buildThen restart Claude Code to reload the server.
Available Tools
3 toolsanalyze_screenshotA
Take a screenshot of a URL in a headless browser and analyze it with a local Ollama vision model. Good for public pages. For pages requiring login, use capture_window instead. Use full_page: true to capture content below the fold — the page is sliced into segments and sent as multiple images so no detail is lost.
Inputs: url (required), question (required), model, wait_ms, +4 more.
capture_windowA
Capture a specific app window currently visible on screen and analyze it with a local Ollama vision model. Unlike analyze_screenshot, this sees your real browser with your logged-in session and live state — ideal for testing local apps.
Inputs: app_name (required), question (required), crop, model, +2 more.
locate_elementA
Find a UI element in an app window and return its click coordinates. Uses a local Ollama vision model — Claude never sees the image. For Google Chrome, pass viewport_bounds (computed from javascript_tool: {x: screenX, y: screenY + outerHeight - innerHeight, width: innerWidth, height: innerHeight}) to get viewport-relative coordinates usable directly with the Chrome computer tool. Without viewport_bounds, returns absolute screen coordinates.
Inputs: app_name (required), element_description (required), model, window_index, +1 more.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 3 tools
analyze_screenshot and capture_window both perform capture-and-analyze, but their contexts are clearly differentiated (headless URL vs. live window). locate_element is distinct as it returns coordinates. Minor overlap exists for public pages that could be captured either way.
All three tools follow a consistent verb_noun pattern with snake_case: analyze_screenshot, capture_window, locate_element. Predictable and clear.
Three tools is a focused, appropriate scope for a screenshot-vision server—each serves a distinct purpose without redundancy.
The set covers the core workflows: capture from URL, capture from live window, and element location. A general 'analyze existing image' tool is missing, but the primary use cases are covered.
Maintenance
Related MCP Connectors
Hosted Screenshots MCP server for Claude, ChatGPT and Cursor, with each action switched per account.
MCP Server for Web2MD — convert URLs to Markdown from Claude Desktop, Cursor, etc.
Hosted Web Crawler MCP server for Claude, ChatGPT and Cursor, with each action switched per account.
Screenshot and HTML render MCP server for AI agents
Related MCP Servers
- AlicenseBqualityDmaintenanceA local vision-language MCP server that enables Claude Code to perform image analysis, OCR, and UI-to-code generation using the Qwen3 VL 4B model via LM Studio. It provides privacy-focused visual processing by running entirely on the user's local hardware without external API dependencies.336 npm1MIT
- FlicenseAqualityDmaintenanceEnables Claude to capture screenshots, watch your screen in real-time, read text via OCR, and analyze video files, all running locally as an MCP server.14-
- FlicenseNot gradedqualityDmaintenanceAn MCP server that gives Claude the ability to watch any desktop window, detecting changes and providing compact image bundles for Claude's vision, enabling real-time screen-watching without API costs.-
- AlicenseAqualityDmaintenanceMCP server for vision capabilities, enabling screenshot, camera, and image analysis using Ollama vision models.41MIT