Macos Vision Mcp
io.github.woladi由 GitHub 账号 woladi 发布v0.7.0更新于 Oct 24, 2026
Local OCR & screen understanding for agents: read any window, find what to click. No uploads.
概览
本地运行的 macOS 服务器,为助手提供端上 OCR、图像分析和屏幕读取,文档与截图无需离开本机。
- 可以做什么
- 从图片和 PDF 中提取文字,返回按页的段落和边界框,便于重建为 Markdown 或 HTML;执行整份文档分析,合并文字、人脸、条码和矩形;检测人脸、读取二维码等条码、定位文档四角并对图像内容分类;截取屏幕或窗口并读取其中文字;列出窗口、按可见文字定位界面元素并取得点击坐标;断言屏幕上文字存在或不存在,并快照窗口的无障碍布局;报告 macOS 版本与权限状态。
- 适用场景
- 适合在 Mac 上让助手读取发票、合同、扫描件或截图而不上传原件,或需要查看并验证应用当前显示内容(包括被遮挡窗口),再把点击坐标交给独立的输入驱动。
- 运行要求
- 仅限 macOS,通过 npx 或全局 npm 安装在本机运行。屏幕捕获需为宿主应用(Terminal、Claude Desktop、Cursor)授予“屏幕录制”权限,布局快照还需“辅助功能”权限,且 Mac 须处于解锁状态。首次运行会从 GitHub Releases 下载预编译辅助程序,需要网络;无需 API 密钥。
安装
在 SourceWeft 中
- 打开 控制台中的 Macos Vision Mcp,将其添加到工作区。
- 为需要使用其工具的对话启用该服务。
Desktop only,通过 STDIO。 STDIO 服务会启动本地进程,因此需要 SourceWeft 桌面宿主。
其他 MCP 客户端
参照 仓库 中的启动说明。
README
[macos-vision-mcp logo — a viewfinder locked onto an eye]
macos-vision-mcp
Your documents and your screen stay on the machine. Only extracted text and structured JSON ever reach the model.
Local, private, offline OCR and UI testing for any MCP client — no API keys, no uploads. Cut document token costs by ~97%, and let an agent see and click your Mac's UI without a single screenshot leaving the machine.
[npm version] [npm downloads] [GitHub stars] [License: MIT] [macOS 13.0+] [No API Key] [Offline] [Glama]
Pre-extracts text and image data locally before your AI ever sees it — cutting token usage by ~97% on real documents and returning structured paragraphs, lines, and bounding boxes so the model can reconstruct the document into Markdown, HTML, DOCX, or any other format. Files never leave your Mac: no cloud API, no API keys, no network requests.
How the ~97% is measured: a 44-page scanned PDF sent as page images costs ~73,500 tokens; the same file run through
analyze_documentreturns ~2,400 tokens of extracted text and structure (raw page-image tokens vs. extracted-text tokens). Your numbers vary with page density and tokenizer — treat 97% as the order of magnitude, not a guarantee.
Contents: Quick Start · What you get · What agents use this for · UI testing · Why it's different · Available Tools · Usage · Example workflows · Configuration · Privacy layer
What you get
- OCR for images and PDFs (JPG, PNG, HEIC, TIFF, multi-page PDF) via Apple Vision Framework.
- ~97% token reduction: a 44-page PDF costs ~2,400 tokens instead of ~73,500.
- Reading-order paragraphs + raw text blocks with bounding boxes — rich structure for the model to reconstruct the document into any output format (Markdown, HTML, DOCX, JSON), not a lossy plain-text dump.
- Face detection, barcode/QR reading, and image classification — all on-device.
- Full document pipeline: OCR + faces + barcodes + rectangles in a single tool call.
- Works with Claude Code, Claude Desktop, and Cursor — any MCP-compatible client.
- No files uploaded to any server — processing stays entirely on your Mac.
- UI testing for agents: screenshot a window locally, find an element by its visible text, get back click coordinates, and assert what's on screen — all without uploading the screenshot.
- 100% offline after
npm install— powered by Apple Vision Framework, same engine as Live Text in Photos.app.
❌ Without / ✅ With
❌ Without macos-vision-mcp:
- Sending a 44-page PDF costs ~73,500 tokens
- Every image, invoice, or contract goes through a cloud API
- Sensitive documents leave your machine on every request
✅ With macos-vision-mcp:
- Local Apple Vision pre-extracts text before Claude ever sees it
- ~2,400 tokens for the same 44-page PDF — 97% fewer
- Files never leave your Mac
What agents use this for
Most work an agent does on a Mac needs no deep understanding of a layout. It needs to see what is
on screen, find the thing it is looking for, act on it, and confirm what happened. That loop —
list_windows → find_element → click (via any input driver) → assert_text — covers a lot,
and every step of it runs on the machine.
- Drive an app that has no API. Native tools, Electron apps, internal software, anything with
a GUI and no scripting interface.
find_element("Export")returns the point to click. - Read what is on screen right now. A dialog, an error banner, a notification, a progress state — including a window sitting behind others, without bringing it to the front.
- Confirm an action actually worked.
assert_textis string matching after unicode normalisation, so it answers pass/fail the same way every time instead of asking a model to judge a picture. - Pull data out of software that will not export it. OCR a window, get the text, move on.
- Audit accessibility.
ui_snapshotreports every piece of visible text the accessibility tree does not account for — unlabelled controls and custom-drawn text, with coordinates. - Test a UI for regressions. The case this started as, and still a good one — see the chapter below.
- Work through documents. The original job: invoices, contracts, scans, PDFs.
Why doing it locally is better, not just different
Cheaper. A verdict costs ~240 tokens against ~6,900 for the screenshot it replaces — about 29×. Over a twenty-step task that is ~4,800 tokens instead of ~138,000. It is the difference between an agent that can afford to check its work after every step and one that cannot.
More private, and this is the part that never shows up on a bill. A screenshot is not a neat crop of the button you cared about. It carries whatever else was on screen: another window, a password manager, an open inbox, a customer's record. Sending one to a third party is a disclosure you cannot withdraw, and it repeats on every single step. Here the image is written to a temp file, read by a model on the Neural Engine, and never serialised into the conversation. That invariant is enforced in the code, not promised in this README: no tool returns image bytes.
Faster in practice, and predictable, which matters more. find_element takes 1.17–1.25 s end
to end on an M1 Pro — capture 0.31–0.41 s, OCR ~1.04 s, matching under a millisecond. There is no
network term at all: no ~750 KB upload before inference can start, no rate limit, no provider
under load, no failure when the Wi-Fi drops. The same call costs the same on a plane as it does
at a desk.
What this does not do: click. It is eyes, not hands, and therefore never asks for control of your machine. Pair it with an input driver —
cliclick, amacos-mcp-style automation server, or anything that accepts screen coordinates — and hand it theclickPointthatfind_elementreturns. The split is deliberate: seeing and acting are different permissions, and this server only ever asks for the first.
UI testing without sending screenshots anywhere
The usual way to let an agent work with a GUI is to screenshot the screen and upload it to a vision model. That is one network round trip, one image-token bill, and one copy of whatever was on screen — per step. A ten-step flow means ten uploads of your desktop.
This server does the seeing locally. Apple's Vision framework runs on the Neural Engine, so the screenshot stays on disk and only text, geometry, and verdicts reach the model.
What the agent actually receives. Element boxes, roles and labels — measured, not guessed — and the exact point to click. The screenshot itself never leaves the Mac.
clickPoint is in global screen points with a top-left origin — the same space click drivers
use, so it goes straight to a driver with no conversion. This server deliberately does not click:
it is eyes, not hands, and therefore never asks for control of your machine.
Is it actually cheaper, safer, and faster?
Measured on an Apple M1 Pro (2021, 16 GB) against a 2992×1734 Retina window capture of a real, text-dense app — median of five runs each.
Image tokens are estimated with Anthropic's
width × height / 750rule; other providers tile differently, so the exact figure moves but the order of magnitude does not. Local token counts are the actual JSON payloads the tools returned, at ~4 characters per token.
Same question, same answer, ~29× the price. Measured on an M1 Pro against a 2992×1734 window capture.
The three claims behind that table — cheaper, safer, faster — are argued in What agents use this for above. What this section adds is the measurement: the numbers are a median of five runs on an Apple M1 Pro (2021, 16 GB) against a 2992×1734 Retina capture of a real, text-dense window.
We have not benchmarked any specific vision provider, so treat the right-hand column as structure rather than a measured figure. What can be stated is that the local path has no variance from bandwidth, rate limits or provider load, and does not fail when the network does.
Two honest caveats. Targeting a single region instead of a whole window cuts the OCR term sharply, since cost scales with pixels searched. And the first call after install spends ~2 s compiling a small Swift helper; every call after that is warm.
What it is good at — and what it is not
Good at: native macOS apps, Electron apps with poor accessibility, canvas/WebGL UIs, games,
and design mockups — anything where there is no DOM to query. Also good when you want a
deterministic assertion rather than a model's opinion: assert_text is string matching after
unicode normalisation, so it returns the same answer every time.
Not the right tool for a plain web page: Playwright or the DOM will be faster and more precise
there. And OCR only sees what is rendered, so it cannot read a control's enabled state or its
accessibility role.
Text matching is normalised before comparison — NFC, collapsed whitespace, unicode dashes and
quotes folded — then tried exact → substring → fuzzy (Levenshtein). When a match is rejected it
is still reported under nearMisses, so "the label is there but OCR read Zapisr for Zapisz"
is distinguishable from "the label is genuinely absent".
Substring hits are graded rather than treated alike: a query that stands on word boundaries,
opens the label, and covers more of it scores higher. That ordering matters when the answer is
a button — for the query Save, Save Changes must outrank Don't Save. Each match reports
wholeWord, and assert_text decides its verdict only on matches where it is true: Save
inside Unsaved changes is a coincidence of spelling, and it neither proves a Save button is on
screen nor proves it is gone. Such hits are still listed, under incidental.
Requirements
-
Screen Recording permission for the app hosting the MCP server (Terminal, Claude Desktop, Cursor): System Settings → Privacy & Security → Screen Recording, then restart that app. No compiler or Xcode tooling is needed — the native helper arrives prebuilt.
The grant is per host process, not per package: the same server can be fully working under one client and blind under another on the same Mac. Without it, capture fails outright and macOS additionally withholds every window title, so
list_windowsreportstitle: ""for everything — that case is flagged astitlesAvailable: falserather than left to look like a screen full of untitled windows. Runvision_capabilitiesfirst:readyandblockerssay what works right now. -
An unlocked Mac. On a locked machine window and region capture fail outright and a full-screen capture returns only the lock screen;
vision_capabilitiesreportsscreenLockedso an agent can check before it starts rather than guessing at a failure afterwards.
Why it's different
Most OCR options for LLMs either ship your documents to a cloud vision API or make you stand up and tune your own engine. This runs on Apple's on-device Vision framework — the same engine behind Live Text in Photos.app — so extraction is free, private, and instant.
The trade-off is honest: it's macOS-only, and on heavily skewed or low-contrast scans a cloud model may still read more. For the common case — invoices, contracts, receipts, screenshots, clean PDFs — you get cloud-grade extraction with zero cost, zero setup, and nothing leaving your machine.
Privacy layer
macos-vision-mcp acts as a local pre-processing layer between your documents and the cloud. Useful for:
- Legal documents, contracts, NDAs
- Financial reports, invoices, internal spreadsheets
- Medical records or any GDPR-sensitive content
- Any situation where you want to extract structured data locally before deciding what (if anything) to send upstream
Instead of sending the raw document to your AI, you extract the text and structure locally first. The model then works only with the extracted text — never the original file.
The same applies to your screen. A screenshot taken for one small check still carries everything else that happened to be visible — other windows, a password manager, a customer record, an open inbox. The UI-testing tools keep that image on disk and return only paths, geometry, and text, so a UI assertion does not become an unplanned disclosure. No tool in this server returns image bytes to the model.
Quick Start
Add to your MCP client (example for Claude Code):
Using Claude Desktop or Cursor? Jump to Configuration ↓
Restart your client. npx fetches the package on first run, caches it, and the tools appear automatically — no separate install step. This is the convention used by most MCP servers and recommended by Anthropic, Cursor, and other clients.
Note: On first run, the package downloads prebuilt Swift helper binaries (
vision-helper,pdf-helper,ui-helper,ax-helper) from its GitHub Releases (~276 KB compressed, ~1–2s). Subsequent invocations hit the npx cache and start instantly. Xcode Command Line Tools are only required as a fallback when the download can't reach the network — setMACOS_VISION_SKIP_DOWNLOAD=1to force local compilation withswiftc.
Prefer instant cold-starts (no npx cache lookup)? Install globally with
npm install -g macos-vision-mcpand use the alternative config shown at the bottom of Configuration.
Available Tools
UI-testing tools (local, no screenshots sent to the cloud)
These tools let an agent see and verify your Mac's UI without ever sending a screenshot to a
cloud model. Screenshots are captured locally, OCR runs on-device, and only paths, geometry,
and extracted text are returned. find_element gives click coordinates in screen points, ready
to hand to any input driver (this server deliberately does not click — eyes, not hands).
Requires Screen Recording permission for the app hosting the MCP server (Terminal / Claude Desktop / Cursor): System Settings → Privacy & Security → Screen Recording, then restart that app. Nothing else to install — the native helper ships prebuilt with
macos-vision.
ui_snapshot — the layout, not just the text
find_element answers "where is X". ui_snapshot answers "what is on this screen": every
element's measured box (from the accessibility API, not inferred from OCR), its role, label
and enabled state, the parent/child structure, and optionally colours sampled from the capture
and real font data.
unresolved is text Vision can read that no accessibility node accounts for. It completes the
picture where AX is blind — canvas, WebGL, games, text baked into images — and each entry is an
accessibility gap in the app: coveredByNode present means a control is there but unlabelled,
absent means nothing is exposed at all.
Read it honestly: budget.capped means the tree is incomplete, and summary.axTextCoverage
is null in that case on purpose — a capped walk measures how much was visited, not how
accessible the app is. Colours come from pixels, so an occluded element reports whatever is drawn
on top; borderWidth is inferred and there is no padding or margin. This is not the CSS box
model.
Needs Accessibility permission in addition to Screen Recording, and an unlocked Mac — a locked screen exposes no accessibility windows at all.
Usage
Use the tool name explicitly in your prompt to guarantee local processing:
Extract text from an image or PDF:
Detect faces in a photo:
Classify image content:
Full document analysis + reconstruction:
The tool returns structured JSON; the model picks the output format you ask for (Markdown, HTML, DOCX outline, etc.) without any extra dependencies — no Ollama, no cloud LLM, no extra tooling.
Example workflows
Real-world combinations that work out of the box once the server is connected:
- "Convert PDF → clean Markdown for LLM" —
analyze_documentreturns reading-order paragraphs and bounding boxes; the model renders Markdown ready to drop into a docs site, knowledge base, or RAG pipeline. - "Extract invoice data locally before sending to GPT" — pull line items, totals, vendor, and dates from the PDF locally with
analyze_document, then send only the structured JSON upstream. The original document never leaves your Mac. - "Scan receipts → JSON → expense tracker" —
ocr_imageon a phone photo, the model normalizes amount / date / merchant, and pipes the result straight into your expense tool's API. - "Decode a QR code from a screenshot" —
detect_barcodesreturns the decoded value plus symbology in one round trip. - "Crop a photo of a paper form before OCR" —
detect_documentreturns the four corner points so you (or a downstream tool) can deskew and crop the image before reading the text. - "Click the Save button in my app" —
find_elementreturnsclickPointin screen points; hand it to a click driver (macos-mcp, cliclick). The screenshot never leaves the Mac. - "Check my app still renders correctly after this change" —
assert_textgives a deterministic pass/fail on what is on screen, at ~240 tokens per check instead of ~6,900 for the screenshot. - "Read the error message in that background window" —
read_screen_textcaptures a specific window, even one hidden behind others, and returns just the text. - "What is my app showing right now?" —
list_windowsto pick the target,read_screen_textto read it, without bringing the window to the front.
Output schema (analyze_document)
Use paragraphs[].text for the 95% case (rebuild Markdown/HTML/plain text directly). Reach for textBlocks[] when you need spatial context — multi-column layouts, tables, forms, IDs.
Notes:
ocr_imageinblocksmode returns the same per-page shape minus the detection sections:{ pages: [{ page, paragraphs, textBlocks }] }.- PDFs are processed page by page. All coordinates are page-local (0–1), and
paragraphId/lineIdreset on every page. - Face, barcode, and rectangle detection on PDFs is best-effort — the underlying binary analyzes the file as a whole rather than per page, so any detections returned are attached to page 0 only.
- Paragraph grouping uses spatial heuristics. For multi-column layouts (magazine spreads, wiki pages with side panels) the heuristic can collapse the whole page into a single paragraph. When that happens, fall back to
textBlocks[]and reconstruct from the bounding boxes.
Configuration
All examples below use npx -y — the recommended default. No prior npm install needed; the package is fetched and cached on first run, and updates pick up automatically when the npx cache rolls over.
Claude Code
Claude Desktop
Edit ~/Library/Application Support/Claude/claude_desktop_config.json:
Cursor
Add to ~/.cursor/mcp.json:
Alternative: global install
If you'd rather skip the npx cache lookup on cold starts — or you want to pin a specific version — install once:
…then use "command": "macos-vision-mcp" (no args) in any of the JSON configs above, or claude mcp add macos-vision-mcp -- macos-vision-mcp for Claude Code. Note that global installs can break when switching Node versions with nvm / asdf / volta — re-run npm install -g after switching.
Support
If macos-vision-mcp saved you tokens or kept a document on your Mac, consider starring the repo — it helps others find it.
Contributing
Contributions are welcome. Please follow Conventional Commits for commit messages.
Releases run on changesets. If your change is user-visible, add a changeset to the PR:
Merging to master then opens a "version packages" PR that bumps the version, server.json and the changelog; merging that PR publishes to npm (Trusted Publishing, with provenance), tags the release, and refreshes the MCP registry entry.
License
MIT — Adrian Wolczuk
来源:README.md,提交 ba9154c
工具
0版本历史
1- v0.7.0最新Sep 16, 2026
评分
已满足适用检查项的 50%
该评分衡量此收录条目的完整程度,依据注册中心条目、端点与公开来源计算得出。它不是对服务器本身的评价,也不表示服务器安全或当前可用:可连通性是带日期的检查结果,评分也不包含安装量或用户评价。
- 近 30 天内可连通25 分
请保持端点能够响应 MCP 握手;SourceWeft 每 30 天探测一次。
- 已声明认证方式10 分
请在注册中心条目中声明凭据请求头,或保持端点能够响应探测,以便判定其认证方式。
- 已列出工具15 分
请让服务器在无凭据时响应 tools/list,或发布可在沙箱中无凭据启动的软件包。
- 描述必需15 分
- 图标10 分
- 文档15 分
- 许可证10 分