mcpField
H
hunch

hunch

本地服务
github.com/PrithviSeran生产力225 天前更新

关于 hunch

Hunch 是用于控制 macOS 原生应用、浏览器、文件及其他本机功能的 MCP 服务和 Python 库。分层控制方式优先采用后台、无需切换焦点的操作;无法通过辅助功能处理时,可使用需确认的截图备用方式。

主要功能

  1. 01后台控制 Mac 原生应用
  2. 02基于辅助功能读取和操作 UI
  3. 03通过 AppleScript 和系统 API 操作文件
  4. 04通过 Safari 扩展或 CDP 控制浏览器
  5. 05对高风险或抢占焦点的操作设置确认

适用场景

  1. 01自动处理已登录的 Mac 应用任务
  2. 02在不中断前台工作的情况下检查 UI
  3. 03在后台执行浏览器工作流
  4. 04通过 Python 脚本控制 Mac

MCP 相关

作为本地 stdio MCP 服务由 MCP 主机启动,提供 macOS 应用、辅助功能、文件和浏览器控制工具。相同的操作原语也可通过其 Python 库使用。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"prithviseran-hunch": {
"command": "uvx",
"args": [
"hunch-sdk"
]
}
}
}
启动命令uvx hunch-sdk

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
pypihunch-sdk0.6.6

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

Hunch

Hunch

通过任何大模型操控 Mac:无需占用焦点,在后台运行,并通过 MCP 操作。

Hunch 是一个 MCP 服务,让大模型 Agent 能够直接操作你的 Mac:你安装的应用、已登录的会话和文件,而且不会接管你的屏幕。当你继续在前台工作时,Agent 可以读取后台应用的界面、点击其中的按钮、通过 AppleScript 操控 Mail 或 Music、填写网页表单,或移动文件。它适用于真正的原生应用,而不只是浏览器。

与现代大模型搭配效果最佳。 Hunch 附带详细的操作手册,作为 MCP 服务说明;能力较强的工具调用型模型(Claude Sonnet/Opus 级及以上)能够很好地遵循。较小的模型可能会选择不够理想的方式(使用屏幕截图和按键操作,而不是读取界面树并点击)。

四个层级

Hunch 始终优先使用最直接的层级。这样速度更快、可靠性更高,而且(最后一层除外)不会触碰你的屏幕:

层级工具用途
OS-APItrash file_op open_file clipboard_* launch_app …通过直接 API 调用处理文件、剪贴板和应用生命周期
AppleScriptapplescript可脚本化的应用:Mail、Messages、Notes、Calendar、Music、Finder、Safari …
Webweb_open web_snapshot web_act web_login …通过内置扩展操控 Safari,或通过 CDP 在后台操控 Chromium/Electron
辅助功能snapshot act任意原生应用的界面:读取界面树、按引用点击/选择/输入

对于辅助功能树确实为空的应用,还提供了一个需要确认的最后手段(screenshot + 坐标点击/按键操作)。它会抢占焦点,因此会先征求你的同意。

如需在 Safari 中进行不占用焦点的视觉操作,可通过 web_open(..., app="Safari", new_window=True) 打开一个由扩展管理的专用窗口。web_screenshot 可截取该后台窗口的图像,而 web_act 可使用返回的像素坐标进行操作,不会移动共享鼠标、键盘或前台窗口。扩展仍不可或缺:它负责管理隔离的 Safari 窗口,并分发实体屏幕截图无法执行的渲染进程本地操作。

工作原理(无服务端,无云端)

称它为“MCP 服务”还不足以体现它的本地化程度。hunch serve 是一个普通的 Python 进程,由你的 MCP 宿主(Claude Desktop、Cursor、…)作为子进程启动,并通过 stdin/stdout 上的 JSON-RPC(MCP 的 stdio 传输)与之通信。它没有 HTTP 端点、没有监听端口、没有守护进程,也没有遥测。宿主退出时,Hunch 也随之退出。

这些工具会在进程内直接调用 macOS API:通过 pyobjc 调用辅助功能框架、通过 osascript 调用 AppleScript、通过操作系统 API 处理文件/剪贴板、通过本地 WebSocket 连接 Chromium 的 DevTools 端口,以及通过经过签名的本地 Safari 扩展桥接程序。可选的 Safari 配套程序仅使用经过身份验证的环回连接,将输入的命令转发给 Apple 沙盒中的扩展。浏览流量仍由所选浏览器发出。模型能看到的内容仅限于工具经由宿主返回的内容;没有其他信息会离开这台设备。

基准测试

Hunch 在真实且已登录的 Mac 上,与其他 macOS 计算机操作 Agent 进行比较,测试项目为 mac-agent-bench——同一个大脑,不同的操作方式: 每项任务都使用相同的 claude -p,只有 MCP 适配器不同。它通过程序化检查器评估任务成功率,还会衡量干扰程度:Agent 工作时对光标和前台窗口的影响有多大。

在 5 项复杂的多步骤任务中(n=3):

工具成功率成本干扰(焦点·光标)超时
Hunch15/15$1.521·00
Peekaboo13/15$14.6022·162
cua-driver15/15$17.7022·00

可靠性完美,成本约低 10 倍,速度快约 5–10 倍,而且几乎从不触碰你的屏幕(15 次试验中光标移动为 0 次,焦点切换为 1 次)。完整的方法说明和逐项任务表格见 基准测试仓库。

安装

macOS 13+。从 PyPI 安装(发行包为 hunch-sdk;导入模块和 CLI 均为 hunch):

pipx install hunch-sdk          # or: pip install hunch-sdk
pip install 'hunch-sdk[subscription]'    # + the agent loop on Claude   (provider="claude")
pip install --pre 'hunch-sdk[codex]'     # + the agent loop on OpenAI Codex (provider="codex")

也可以通过 Homebrew 安装——如果你不管理 Python 环境,这是最好的选择;它会在稳定路径下附带一个隔离的 Python 环境,让 macOS 权限授权最可预测:

brew install prithviseran/hunch/hunch

然后,只需执行一次:

hunch setup      # walk the macOS permission grants
hunch doctor     # verify every layer; fix anything it flags
hunch connect claude-desktop   # or: claude-code, cursor

重启你的 MCP 宿主,并让它“使用 hunch 来……” 。

坦诚说明权限

macOS 信任的是运行服务的应用,也就是你的 MCP 宿主(Claude Desktop、 Cursor 或你的终端),而不是“hunch”本身。hunch setup 会引导你完成设置:

  • 辅助功能(必需):允许 Hunch 读取应用界面,并在不获取焦点的情况下点击。在“系统设置”→“隐私与安全性”→“辅助功能”中,为你的 MCP 宿主应用授予权限。
  • 自动化(按应用授权,自动提示):Hunch 首次对某个应用执行脚本操作时,macOS 会显示一次性的 “允许控制”提示。
  • 屏幕录制(可选):仅用于屏幕截图/视觉回退方案。

hunch doctor 会报告已授予的权限。注意:其中“辅助功能”一项反映的是你运行该命令所用的终端权限;服务继承的是宿主的授权。

Python SDK(库用法)

Hunch 也可以作为可导入的库使用——它提供与 MCP 工具相同、不会抢焦点的基础操作,可通过你自己的 Python 程序(定时任务、测试框架或自定义 Agent 循环)确定性地驱动,无需大模型。发行包名为 hunch-sdk;导入名为 hunch:

from hunch import Hunch

mac = Hunch()                              # your machine, your logged-in apps
print(mac.snapshot("Mail"))                # accessibility tree, focus-free
mac.act([{"action": "click", "ref": "e12"}])
mac.web.open(url="https://github.com")     # real persistent Chrome profile over CDP
mac.web.open(url="https://github.com", app="Safari")  # user's Safari session via extension
print(mac.web.snapshot())
mac.files.trash(["~/Downloads/old.zip"])   # reversible delete, no Finder
mac.applescript('tell application "Music" to play')

构造参数:app(初始快照的目标)、confirm="dialog"|"off"(见下文)、check_permissions(预先检查辅助功能权限)、simultaneous(绝不触碰前台、光标或键盘)、cdp_port。

要在 Chromium/Electron CDP 会话中显示悬停菜单或工具提示,请使用最新 web_snapshot 中的 ref:

mac.web.act([{"action": "hover", "ref": "e12"}], detailed=True)
print(mac.web.snapshot())  # verify the revealed UI and get fresh refs before clicking

MCP 中的对应操作是使用相同动作的 web_act。悬停会发送渲染器本地的鼠标移动事件,不会点击、激活应用或移动 Mac 光标。除非明确的后置条件验证了所请求的字段,否则其回执为 performed_unverified。Safari 会返回不支持(详细调用会以 blocked 返回,且尝试操作数为零);原生 act 不提供悬停功能。

  • 权限:对于库用法,需要辅助功能权限的是运行脚本的程序——也就是你的终端或 IDE(而 MCP 服务使用宿主应用的授权)。构造函数会检查权限,若未获授权则会抛出 AccessibilityNotGranted 并提供操作说明。screenshot() 还需要屏幕录制权限。
  • 安全门默认开启:与 MCP 服务一样,默认启用单击一次的“继续”对话框和 ~/.hunch/config.json 安全门。Hunch(confirm="off") 仅对此实例自动批准——用于无人值守脚本时,注意事项与 auto_approve_all 相同。
  • 错误:方法会返回状态字符串(检查是否为 REFUSED);SDK 仅会抛出 ApprovalDenied(用户拒绝了对话框)、AccessibilityNotGranted、WebNotOpen(在调用 .web.open() 前使用 .web)、StaleRef(重新获取快照),以及 HunchError(无法打开 CDP 浏览器;调用 web.restart() 可恢复过期实例)。
  • 凭据:mac.web.fill_login(service) / fill_secret(service, ref) 会将 Keychain 中的值直接输入页面,且绝不会返回这些值;系统会强制执行域名绑定。
  • 共存:SDK 和 MCP 服务共用 CDP 端口(9337)和持久化的 Hunch 浏览器配置文件——无论谁先打开,都会复用已打开的实例;但 web.restart() / web.login() 会终止占用该端口的任何程序。

可运行的脚本位于 examples/。

Agent 循环(mac.agent)

实例 SDK 提供确定性的基础操作。Agent 循环让大模型掌舵:你用通俗英语交给它一项任务,它就通过这些相同的基础操作来驱动 Mac——在你的机器上,使用你已登录的应用。构造时选择一次提供商——Anthropic Claude 或 OpenAI Codex——此后所有操作都与提供商无关。这是可选的额外组件(基础安装无需包含大模型 SDK):

pip install 'hunch-sdk[subscription]'                    # Claude
# or, for Codex (the SDK is beta):  pip install --pre 'hunch-sdk[codex]'
python -c 'import hunch; hunch.provider("claude").login()'   # sign-in (browser OAuth) — no API key
from hunch import Hunch

mac = Hunch(provider="claude")          # or Hunch(provider="codex")
result = mac.agent.run("reply to Sarah's latest email, but don't send it")
print(result.text)          # the model's final summary
print(result.turns, result.usage)
登录

身份验证是明确的、限定提供商的功能——不会静默搜寻任何信息。你只需选择一次服务商,之后便可使用同一组不带前缀的方法:

mac = Hunch(provider="codex")       # or "claude" (the default)
mac.login()                         # codex: ChatGPT browser sign-in · claude: Claude sign-in
mac.status()                        # -> AuthStatus(provider, logged_in, method, email, plan)
mac.logout()
mac.agent.run(task)                 # runs on the configured provider

也可以独立使用身份验证,无需 Mac 实例(例如,在引导脚本中):

import hunch

st = hunch.provider("codex").status()
if not st.logged_in:
    hunch.provider("codex").login()               # browser OAuth (blocks until done)
    # headless/remote box instead:
    #   h = hunch.provider("codex").device_login()
    #   print(h.verification_url, h.user_code); h.wait()
服务商登录方式费用
claudemac.login() / hunch.provider("claude").login() — 使用与 Claude Code 相同的浏览器 OAuth。已经在这台 Mac 上登录 Claude Code?那就完成了;Hunch 会复用该登录状态。你的 Claude 套餐(无按 Token 计费)
codexmac.login() / codex login — 通过浏览器登录 ChatGPT/Codex。你的 ChatGPT/Codex 套餐

两者都通过订阅/登录运行——不会开放按量计费的 API 密钥。如果没有有效登录,run() 会显示错误并提示你返回 login()——绝不会擅自猜测。

  • 查看运行过程:使用 on_event(kind, data) 回调——kind 可以是 text(推理过程)、 tool({name, input})、tool_result(预览)、done(最终文本)、error。
  • 延续对话:后续调用 run() 会保留对话(模型仍记得 Sarah 的电子邮件地址);mac.agent.reset() 会开始一项新任务。
  • 自由组合不同层:在 mac.agent.run(...) 前后确定性地调用 mac.snapshot(...) / mac.clipboard.get()——这是云端沙箱无法在你的真实设备上做到的事。
  • 参数:run(task, model=None, max_turns=40, effort=None, on_event=None, system_suffix="") — model=None 会使用该服务商自己的默认模型。AgentResult 包含 text、turns、 stop_reason、usage、aborted。
  • 安全性:循环由实例的门控配置控制。默认的 confirm="dialog" 会在任何可能抢占焦点或有风险的步骤前弹出真实的“继续?”对话框——适合你守在设备旁时使用,但受门控的操作可能会因等待对话框超时而卡住无人值守的运行。对于 cron 作业,请使用 Hunch(confirm="off") 并接受相应风险;对于不可逆或会影响外部的操作,模型仍会通过 notify_user 先征求你的同意。被拒绝的门控操作会返回 REFUSED 结果,因此循环会调整处理方式,而不会崩溃。
  • 费用:运行会占用你所用服务商套餐的使用额度——没有按 Token 计费。max_turns 用于限制运行轮数。

Codex 说明: codex 服务商会驱动 OpenAI Codex Agent,通过 MCP(一个独立的 hunch serve 进程)使用 Hunch 的工具,因此,对于危险动词的审批会使用 Hunch 自己的点击批准对话框,而不是宿主提供的 can_use_tool 回调。

其他模型:实例 SDK 的基础功能与服务商无关——你可以将 mac.snapshot() / mac.act() 接入自己的 OpenAI/Gemini 等 Agent 工作流,将它们用作工具。

基于 Hunch 构建应用

SDK 以开发者为先:**语义统一,一切归实例所有,除非你主动选择,否则不使用任何环境级配置。**上面的 MCP 服务本身就是基于它构建的第一个应用——它的“个人”行为(~/.hunch/config.json 策略、“Hunch”品牌对话框、共享浏览器配置文件)不过是构造函数参数。

from hunch import Hunch, ConsentRequest, OAuthToken

mac = Hunch(
    provider="claude",                  # which LLM vendor drives mac.agent ("claude" | "codex")
    app_id="com.acme.mailbot",          # pure namespacing — own Keychain slots, browser
                                        #   profile, and CDP port; never a behavior switch
    app_name="Acme Mailbot",            # what consent dialogs + notifications say
    confirm=my_consent_callback,        # ConsentRequest -> bool, rendered in YOUR UI
    notify=my_toast_handler,            # callback, or True for native macOS banners (default: off)
    policy={"gates": {"shell": True}},  # instance-owned safety; the user's personal
                                        #   config can never disarm your app
    auth=OAuthToken(token),             # the exact Claude subscription token YOUR app manages
    can_use_tool=my_approver,           # optional: route every tool through your Approve/Deny UI
)

这样做的好处:

  • 共存 — 使用不同 app_id 的两个应用会获得互不相通的 Keychain 服务、凭据存储、浏览器配置文件和 CDP 端口。它们无法读取彼此的登录信息、将彼此登出,或终止彼此的浏览器会话。这是结构上的隔离,而非约定俗成。
  • 你的品牌,你的 UX — 每个对话框、拒绝消息和通知都会显示你的 app_name;confirm= 和 notify= 会通过你的应用处理同意确认和提醒,而不是使用 osascript 对话框和 macOS 横幅通知。故障的同意回调会默认拒绝。
  • 隔离的安全策略 — 机器上的 hunch config(以及 HUNCH_NO_INTERNAL_GATE)只管理个人 MCP 服务,不会影响你的实例。
  • 明确的身份验证 — 使用 provider="claude" 和 auth=hunch.OAuthToken(...) 时,会严格使用指定的订阅令牌(repr 会进行脱敏),因此你的应用绝不会在用户不知情的情况下使用最终用户自己的 Claude 登录信息。(codex 提供方通过 mac.login() / codex login 进行身份验证。)

程序化凭据管理使用相同的命名空间:hunch.creds.set_credential(name, user, pw, namespace=your_app_id) 等。可运行的示例见 examples/embedded_app.py。

凭据:Agent 使用它们,但永远看不到它们

hunch creds add github --domain github.com
hunch creds list

凭据值会直接写入 macOS Keychain。Agent 只需调用 web_fill_login("github"),并提供服务名称即可登录;Hunch 会从 Keychain 读取机密,并通过 CDP 将其输入网页。该值绝不会进入模型上下文、模型日志或模型提供方的服务器。

域名绑定:使用 --domain github.com 添加的凭据只会输入到 github.com 及其子域名。如果被误导或遭提示词注入的 Agent 进入了仿冒页面,填充操作会被拒绝。请为每项凭据绑定域名;空白(适用于任何网站)仅为兼容性保留。

如果没有已存储的凭据,Agent 会改用 web_login,打开一个带标记的浏览器窗口,由你亲自登录;之后会话会保存在 Hunch 专用的浏览器配置文件中。

确认关卡

MCP 宿主的工具审批是主要权限层。Hunch 增加了一个了解内容的第二道关卡:一键式 macOS 对话框,用于处理灾难性操作:

关卡触发条件
gates.focus_steal接管键盘/光标的操作(key、click_xy、未指定引用的输入)
gates.app_to_front将应用置于前台(切换焦点,即使处于全屏状态)
gates.shell含有 do shell script 的 AppleScript
gates.destructive_applescript删除/发送/清空废纸篓/关机/……

一次审批涵盖后续操作:点击“继续”(在 request_focus、受关卡限制的 act 或应用置于前台对话框中)后,会在约 15 秒内授权其所提示的切换:不会再弹出第二个对话框,也会抑制焦点切换通知。切换要么询问过,要么通知过,绝不会两者兼有,也绝不会静默发生(关闭 gates.app_to_front 后,切换会改为发送通知)。

默认全部开启。对于 MCP 服务,可通过 hunch config show/hunch config set gates.shell off 调整;更改会立即生效,即使服务正在运行也一样。auto_approve_all 会关闭所有关卡,并要求你确认已了解相关风险。

对于 SDK 实例,关卡由实例管理:Hunch() 默认开启所有关卡,且不会读取配置文件——传入 policy={"gates": {...}}、callable(category) -> bool,或 policy="personal",即可为自己的脚本启用实时读取配置文件的行为。

Hunch 还会禁止 Agent 通过文件工具编辑 ~/.hunch/ 下的任何内容(其自身的策略和凭据元数据);权限更改须由人在终端中进行。

环境变量

变量作用
HUNCH_NO_INTERNAL_GATE=1禁用所有内部对话框(适用于有自有审批体验的宿主应用)
HUNCH_FORCE_SANDBOX=1Web 层使用一次性、未登录的浏览器配置文件
HUNCH_NOTIFY_FOCUS=0静默“Hunch 正在切换应用”通知(仅当切换未触发对话框时才会发送)

面向用户的桌面通知默认关闭。如需为个人 MCP 服务启用,可运行 hunch config set notifications.user_attention on。SDK 应用可传入 notify=True 以显示原生 macOS 横幅通知,或传入 notify(message, title) 回调以接入自有 UI;默认禁用。

常见问题

每次读取树结构都返回“(no window for …)”,且 AppleScript 报错“-25211 not allowed assistive access”。 一个可能的原因是,托管 Hunch 的应用缺少 辅助功能 权限。 没有此权限时,AX API 会静默返回空结果,因此即使应用已打开,也会看起来没有窗口。 请向宿主应用授予权限(见下一个问题);如果它已列在权限列表中,请将其关闭后再重新开启: macOS 会在应用更新时静默撤销权限。之后重启宿主应用。

应该向哪个应用授予权限? 启动 hunch serve 的应用:Claude Desktop、 Cursor 或你的终端应用(用于 Claude Code)。权限与该应用的身份绑定,而不是与 “hunch”本身绑定。这也是 hunch doctor 可能会产生误导的原因:它报告的是运行该命令的终端所拥有的权限,这些权限可能与 MCP 宿主应用的不同。

只有 screenshot 失败;其他功能都正常。 这是 屏幕录制 权限的问题,只有截图/视觉回退方案需要此权限。请在“系统设置”→ “隐私与安全性”→“屏幕录制”中向宿主应用授予权限,或者直接让 Agent 使用不需要此权限的 snapshot。

昨天还能用,今天却不行了。 宿主应用(或 macOS)更新后很可能重置了权限。请在“辅助功能”(以及使用屏幕录制时的“屏幕录制”)中关闭宿主应用的权限后再重新开启,然后重启宿主应用。

某个应用读取到的树结构为空,或只显示侧边栏。 覆盖范围取决于操作、进程、权限和窗口状态。snapshot 不会重启应用。使用 app_target 检查确切的进程/窗口,然后使用 app_capabilities 检查受限的恢复选项。app_recover 可以执行已获授权的辅助功能或调试恢复操作。 请验证操作结果;树结构为空并不能证明应用没有 AX。

无法连接 Web 层。 Chrome 136+ 会阻止在默认配置文件上使用 CDP 调试端口,因此 Hunch 会驱动自己的 Chrome(数据目录与日常使用的 Chrome 分开,位于 ~/.hunch/chrome-cdp),而不是你日常使用的 Chrome。 通过 hunch setup 或 web_login 将该配置文件登录到 Google 账号一次,Chrome Sync 便会同步你的登录信息;之后它就会一直保持登录状态。

对于 Safari,首次运行 hunch serve 时会安装已签名的伴侣应用,并提示你一次,在 Safari →“设置”→“扩展”中启用 Hunch 并授予网站访问权限。选择访问所有网站可减少提示;Hunch 仍会将每个操作绑定到确切的标签页、URL、来源和文档代次。Hunch 无法自行授予这些由 Apple 管理的权限。hunch setup 和 hunch doctor 也会完成相同的步骤。

我的宿主应用显示的服务说明被截断了。 这只是显示问题:某些宿主应用的界面会在服务器信息显示中缩短操作指南;模型收到的内容是完整的。

安全

请阅读 SECURITY.md:其中介绍了威胁模型(主要是提示词注入)、各项防护措施的覆盖范围与局限,以及漏洞报告方式。

项目状态

Hunch 目前作为个人开源项目维护。它可以控制 Mac 上的真实应用、文件、浏览器会话和凭据,因此请审查源代码、保持启用审批,并使用最小权限凭据。本软件按 “原样” 提供,不附带任何保证或条件,并遵循 Apache License 2.0。

许可证

Apache-2.0;请参阅 LICENSE。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。