Local Eyes
Provides a cloud vision backend via Google's Gemini API using a Gemma model, enabling image analysis through the same Local Eyes tools when configured with a Gemini API key.
Provides a local/offline vision backend via Ollama running Gemma 4, enabling the read_ui, extract_text, and describe_image tools to analyze images without sending them to the cloud.
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., "@Local Eyes read this UI screenshot ~/Desktop/broken_form.png and tell me why sign-up fails"
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.
Local Eyes 👁️
Private eyes for text-only AI agents. Local Eyes is an MCP server that lets any agent or model see images, using Gemma 4 running on your own machine (Ollama) or through the Gemini API.
Frontier models can already see. But many of the open models people run locally for coding and agents are text-only (gpt-oss, DeepSeek, Qwen-Coder), and private or offline setups can't send screenshots to a cloud model. Local Eyes plugs Gemma 4's vision into any MCP client as three tools that return strict JSON. A text-only agent can then read a broken UI, a stack-trace screenshot or a photo of a receipt, without the image ever leaving the laptop.
text-only agent ──MCP──▶ Local Eyes ──▶ Gemma 4 (Ollama, on this machine)
(gpt-oss, Qwen, read_ui └─ or gemma-4-31b-it on the Gemini API
Claude, Cursor…) extract_text
describe_image ◀── validated JSON (Pydantic), 1 auto-retryTools
Tool | Input | Returns |
| UI screenshot |
|
| any image |
|
| path or URL |
|
Every result is validated against a Pydantic schema. If the model returns invalid JSON, Local Eyes retries once and sends back the exact validation error. On Ollama, the schema is also enforced while the model writes its answer (structured outputs). Each result carries _meta with the backend, model, latency, attempts and whether it came from the cache.
Related MCP server: vision-mcp
Setup
Requires Python 3.10+ and uv.
git clone https://github.com/Arcanum703/local-eyes && cd local-eyes
uv sync
cp .env.example .env # pick a backend; add GEMINI_API_KEY if using geminiPrivate mode (Ollama, works offline):
ollama pull gemma4:e4bCloud mode (Gemini API): set LOCAL_EYES_BACKEND=gemini and GEMINI_API_KEY=... (from AI Studio) in .env. The default model is gemma-4-31b-it. If it returns 5xx or times out (common under load), Local Eyes falls back to gemma-4-26b-a4b-it.
Speed: on a CPU-only laptop, Gemma 4 E4B takes about 40–120 s per image. Gemma 4 thinks by default; Local Eyes turns that off for Ollama (OLLAMA_THINK=1 turns it back on), which made it about 3x faster with the same answers on our demo images. A GPU makes it much faster.
Try it without an MCP client:
uv run local-eyes-cli read_ui demo/broken_form.pngConnect to any MCP client
Claude Code (3 lines):
claude mcp add local-eyes -- uv --directory /path/to/local-eyes run local-eyesClaude Desktop / Cursor / any MCP client (mcpServers entry):
"local-eyes": {
"command": "uv",
"args": ["--directory", "/path/to/local-eyes", "run", "local-eyes"]
}Add "--backend", "gemini" or "--cache" to the args to change behaviour, or set LOCAL_EYES_BACKEND in .env.
Replay cache (--cache)
With --cache, every validated response is saved to cache/<hash>.json. The key is the image bytes + tool + question, so the backend doesn't matter. The next identical call is answered from disk instantly, with no model and no network. This keeps a live demo working through rate limits or dead conference Wi-Fi. Cached results show "_meta": {"cached": true}. Answers for the demo images ship in cache/.
Demo: a text-only agent fixes a broken form
scripts/agent_demo.py is a ~80-line agent harness. Its "brain" is any Ollama model with tool calling, and it never receives image bytes, only Local Eyes' JSON:
uv run python scripts/agent_demo.py demo/broken_form.png "Why can't the user sign up? Propose a fix." --cache
# any tool-calling Ollama model can be the brain: AGENT_MODEL=gpt-oss:20b ...The agent calls read_ui, learns about the invalid email, the mismatched passwords and the 422 date_of_birth expected YYYY-MM-DD banner, then proposes the fix: 1998-10-31, add .com, match the passwords, tick the Terms box. (The 31B/26B models on Gemini also spot the submit button hanging off the card; E4B misses it.) With Ollama it all works with Wi-Fi off.
Other demo images: demo/stacktrace.png (try extract_text on it).
scripts/mcp_smoke.py <tool> <image> [--cache] [--backend gemini] exercises the server exactly like an MCP client does.
Configuration
Env var | Default | |
|
|
|
|
| |
|
| any Ollama vision model |
| required for | |
|
| |
|
| tried on 5xx / timeout |
|
| seconds per model attempt |
| off | turn Gemma 4 thinking on |
| off |
|
|
| |
|
| images are downscaled to this before sending |
| unset | if set, local paths must be inside this folder |
| off | URLs to localhost/private networks are refused by default |
Only files that decode as images are ever sent to a model (25 MB / 50 MP caps).
License
MIT. Built at MLH Hacktoberfest Hack Day Budapest, 31 Oct 2026.
Available Tools
3 toolsdescribe_imageB
Describe an image, or answer a question about it. path_or_url: absolute local path or http(s) URL.
Inputs: path_or_url (required), question.
extract_textB
OCR: return all visible text verbatim, plus any error/warning messages shown (great for UI screenshots).
Inputs: path (required).
read_uiB
Read a UI screenshot: structured elements (type, label, value, state), visible errors, and layout issues.
Inputs: path (required).
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 3 tools
The three tools carve out reasonably distinct niches: free-form description/Q&A, verbatim OCR, and structured UI element extraction. The main friction is that extract_text is explicitly pitched at UI screenshots, overlapping with read_ui, and describe_image's open-ended 'answer a question' scope can subsume either of the others.
All three names follow a clean verb_noun snake_case pattern (describe_image, extract_text, read_ui), with the verb matching the action and the noun matching the input/artifact.
Three tools is on the lean side but well-matched to a narrow image-inspection domain, with each tool earning its place. It sits just above the 'thin' threshold and leaves little room for edge cases like metadata or region-specific reads.
The surface covers the core jobs of local image understanding: general description, text extraction, and structured UI parsing, with clear input handling via path or URL. Minor gaps exist for basic image metadata (dimensions/format) or comparing/reading a specific region, but agents can work around these.
Maintenance
Related MCP Connectors
OCR, transcription, file extraction, and image generation for AI agents via MCP.
Screenshot, diff, audit and sitemap-capture any web page — 5 MCP tools for AI agents.
214 tools for AI agents over one MCP endpoint: image, video, audio, 3D, data, storage, mail, GPUs.
MCP tools for AI agents: render URLs to image/PDF, check link health, convert HTML/CSV/JSON.
Related MCP Servers
- AlicenseAqualityDmaintenanceEnables non-multimodal models to see images by providing MCP tools for image understanding and OCR, backed by any OpenAI-compatible vision model.2MIT
- AlicenseNot gradedqualityNot gradedmaintenanceAdds image recognition and UI grounding capabilities to text-only LLMs through MCP tools, supporting local and cloud vision backends.34 npmMIT
- AlicenseAqualityDmaintenanceVision MCP enables text-only agents to understand images through any OpenAI-compatible vision model. It supports local images, URLs, screenshots, documents, charts, and code errors with tools like analyze_image and understand_image.2MIT
- AlicenseNot gradedqualityDmaintenanceGives text-only LLMs local vision by providing a local VLM and OCR via MCP, enabling agents to analyze screenshots and extract text from images.MIT