关于 Safari MCP
Safari MCP 是面向 macOS 的 MCP 服务,可让 AI Agent 自动操作正在使用且已登录的 Safari 会话。它提供浏览器交互工具,可在后台运行,且无需 Chrome 或浏览器自动化依赖。
主要功能
- 01网页导航、点击与表单填写
- 02截图和页面无障碍快照
- 03网络与存储访问
- 04Safari 后台运行
- 05按会话隔离标签页所有权
- 06stdio 与共享 HTTP 传输
适用场景
- 01自动处理已登录网站中的任务
- 02交互前检查页面结构
- 03填写 React、Vue、Angular 或 Svelte 页面表单
- 04通过隔离标签页状态运行多个 Agent
MCP 相关
通过 stdio 或共享 HTTP 守护进程向 MCP 客户端提供 Safari 浏览器自动化工具。按会话管理标签页所有权,帮助并发客户端各自操作独立标签页。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
🦁 Safari MCP
为编码 Agent 打造的浏览器。
你自己的 Safari,已登录——不用 Chrome,不发热,也不使用无头模式。
在 VS Code 中安装 · VS Code Insiders · 在 Cursor 中安装
98 个工具 · 无需 Chrome/Puppeteer/Playwright · 每条命令约 5 毫秒 · 比 Chrome 少占用 60% CPU
快速开始 · 全部 98 个工具 · 示例 · 为什么选择 Safari MCP? · 架构 · 更新日志

❌ 不使用 Safari MCP
你的 AI Agent 需要浏览网页,因此它只能:
- 通过 Playwright 启动 Chromium——没有登录信息、Cookie 或会话
- 使用 Chrome DevTools MCP——再运行一个浏览器,让风扇全速运转
- 依赖无头爬虫——被 Cloudflare、reCAPTCHA 和机器人检测拦截
✅ 使用 Safari MCP
你的 AI 可以操控你已登录的 Safari——Gmail、GitHub、Ahrefs、Slack、网银。
原生 WebKit。CPU 占用降低约 60%。后台运行。98 个工具。一条 npx 命令。仅限 macOS。
📰 freeCodeCamp 专题报道:如何在 macOS 上将 AI 编码 Agent 连接到浏览器 · HackerNoon:逆向分析 React、Shadow DOM 和 CSP
🍎 Apple 推出了官方 Safari MCP——
safaridriver --mcp,于 Safari Technology Preview 247(2026 年 7 月)首次推出,并已包含在稳定版 Safari 27.0 中。它通过隔离的自动化会话执行调试操作。safari-mcp 操控的是你已登录的真实 Safari——使用你的 Cookie 和会话,在后台运行,并提供 98 个工具。完整对比请见下文。
亮点
- 98 个工具——导航、点击、表单、截图、网络、存储、无障碍等
- 不发热——在 Apple Silicon 上运行原生 WebKit,CPU 占用比 Chrome 低约 60%
- 你自己的浏览器——保留所有登录信息、Cookie 和会话(Gmail、GitHub、Ahrefs 等)
- 后台运行——Safari 始终在后台,不会抢占窗口焦点
- 无需浏览器依赖——无需 Puppeteer、Playwright、WebDriver 或 Chrome
- 持久进程——复用单个 osascript 进程(每条命令约 5 毫秒,而非约 80 毫秒)
- 兼容框架——通过原生 setter 填充 React、Vue、Angular 和 Svelte 表单
用户自己的评价
并非征集的推荐语——这些引言摘自公开问题跟踪器,每条都链接到对应的讨论串。
“我会在正常使用的 Safari 配置中并行运行多个 Pi 会话/子 Agent。有意共享 Cookie 和登录状态。” — @maxim,谈在真实浏览器中运行并发 Agent
“该服务采用了刻意设计的标签页所有权模型……代码对此处理得很谨慎,对于默认情况来说,这是正确的安全姿态。” — @turner-moore,谈这些防护为何拒绝操作你的标签页
“直接从软件包进行本地验证:Safari MCP doctor 6/6。” — @jrepp,发现并修复了焦点辅助工具中的队列对齐错误
快速开始
前置条件
- macOS(任何支持 Safari 的版本)
- Node.js 20+
- Safari → 设置 → 高级 → 显示网页开发者功能 ✓
- Safari → 设置 → 开发者 → 允许来自 Apple Events 的 JavaScript ✓
安装(一个命令)
npx safari-mcp
就这么简单——无需全局安装。或者永久安装:
npm install -g safari-mcp
配置 MCP 客户端
所有客户端都以相同的方式运行 Safari MCP——npx safari-mcp。选择你的编辑器:
Claude Code
claude mcp add safari -- npx safari-mcp
或者编辑 ~/.mcp.json:
{
"mcpServers": {
"safari": {
"command": "npx",
"args": ["safari-mcp"]
}
}
}
Claude Desktop
编辑 ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"safari": {
"command": "npx",
"args": ["safari-mcp"]
}
}
}
保存后重启 Claude Desktop。
Cursor
一键安装:在 Cursor 中安装
或者编辑项目中的 .cursor/mcp.json:
{
"mcpServers": {
"safari": {
"command": "npx",
"args": ["safari-mcp"]
}
}
}
VS Code / VS Code Insiders
一键安装:在 VS Code 中安装
或者编辑 .vscode/mcp.json:
{
"servers": {
"safari": {
"type": "stdio",
"command": "npx",
"args": ["safari-mcp"]
}
}
}
Windsurf
编辑项目中的 .windsurf/mcp.json(或全局配置文件 ~/.codeium/windsurf/mcp_config.json):
{
"mcpServers": {
"safari": {
"command": "npx",
"args": ["safari-mcp"]
}
}
}
Cline
在 VS Code 中打开 Cline → 点击 MCP 图标 → 编辑 MCP 设置 → 添加:
{
"mcpServers": {
"safari": {
"command": "npx",
"args": ["safari-mcp"]
}
}
}
Continue
编辑 ~/.continue/config.yaml(或工作区中的 .continue/config.yaml):
mcpServers:
- name: safari
command: npx
args:
- safari-mcp
Goose
编辑 ~/.config/goose/config.yaml:
extensions:
safari:
name: safari
type: stdio
cmd: npx
args:
- safari-mcp
enabled: true
LM Studio
打开 LM Studio → 设置 → MCP 服务 → 添加服务:
- 名称:
safari - 命令:
npx - 参数:
safari-mcp
Zed
打开 Zed → 设置 → 搜索“Context Servers”并添加:
{
"context_servers": {
"safari": {
"command": {
"path": "npx",
"args": ["safari-mcp"]
}
}
}
}
替代方案:Homebrew
brew install achiya-automation/tap/safari-mcp
替代方案:从源代码安装
git clone https://github.com/achiya-automation/safari-mcp.git
cd safari-mcp && npm install
使用工作流
AI Agent 使用 Safari MCP 时推荐采用以下模式:
1. safari_snapshot → Get page state (accessibility tree)
2. safari_click/fill/... → Interact with elements by ref
3. safari_snapshot → Verify the result
元素定位——工具支持多种定位策略:
| 策略 | 示例 | 最适用场景 |
|---|---|---|
| CSS 选择器 | #login-btn、.submit | 唯一元素 |
| 可见文本 | "Sign In"、"Submit" | 按钮、链接 |
| 坐标 | x: 100, y: 200 | 画布、自定义小组件 |
| 快照中的引用 | ref: "e42" | 无障碍树中的任意元素 |
提示: 先使用
safari_snapshot获取元素引用,再用引用进行精确定位。这样比 CSS 选择器更快、更可靠。
同时运行多个 Agent
多个 Agent 或子 Agent 同时操控一个 Safari 时,会争抢当前活动标签页——除非让它们连接到共享 HTTP 守护进程,而不是每个客户端各运行一个进程:
SAFARI_MCP_HTTP=1 SAFARI_MCP_HTTP_PORT=9225 npx safari-mcp
然后让每个客户端都连接到它:
{ "mcpServers": { "safari-mcp": { "type": "http", "url": "http://127.0.0.1:9225/mcp" } } }
一个守护进程,多个会话——每个会话都有自己的标签页状态。服务器根据 MCP 会话 ID,为 activeTabIndex、所有权标记和唯一标签页标记设置键,因此会话 A 无法读取或操控会话 B 的标签页。
有两个特性让这种方式真正安全,而不只是整洁:
-
标签页身份由标记确定,而非索引。 每个会话都会在自己打开的页面中写入唯一 ID,因此即使发生导航,或者用户重新排序或关闭其他标签页,所有权也能保持不变。单靠索引会悄无声息地指向错误的标签页。
-
出错时会安全拒绝操作。 如果无法重新找到会话标记的标签页,每个工具都会拒绝操作,而不会退回到当前最前面的标签页——因为那通常是你的标签页:
Tab tracking lost — refusing to fall back to "current tab of window" (would target the user's active tab). Call safari_new_tab to reopen.
这也大幅减少了进程数量:17 个并发会话原本需要约 17 个 node 进程,现在只需 1 个。
SAFARI_PROFILE 仍为可选项——不设置时,会话会使用你常规的 Safari 窗口、Cookie 和登录状态。docs/http-transport-design.md 中有详细说明。
更喜欢使用 stdio(每个 Agent 一个进程),而不是持久守护进程?也可以——此时隔离由进程边界本身提供。需要注意的是:如果客户端通过 mcporter 复用多个 Agent,mcporter 会为所有 Agent 缓存同一个 MCP 客户端——无论你选择哪种传输方式——因此服务器无法看到不同的会话,也无法启用按会话隔离。mcporter-lanes(由 @maxim 开发的 pi 扩展,源于 #76)在上游解决了这个问题:每个 Agent 会话都有自己的守护进程目录——因此也有自己的 safari-mcp——并设有空闲超时,避免进程不断累积。
操作已打开的标签页
默认情况下,服务器只会操作自己打开的标签页。如果让它操作你打开的标签页,它会拒绝:
Tab safety: refusing "click" — current tab (https://mail.example.com/inbox) was not
opened by this MCP session. Use safari_new_tab or safari_switch_tab to target your own tab.
设置这个默认行为,是因为早期版本确实会点开并关闭用户的标签页。但“阅读我正在看的文章”和“填写我屏幕上的表单”都是实际需求,而且重新打开页面会丢失当前标签页中有用的会话状态。设置 SAFARI_MCP_ALLOW_USER_TABS=1 后,明确调用 safari_switch_tab 就会接管指定的标签页,而不是拒绝操作;此后会话便能像操作自己打开的标签页一样操作它,并会明确说明:
{ "tabIndex": 3, "safeUrl": "https://mail.example.com/inbox", "note": "(user tab, opted-in)" }
这个标记有意不会改变以下行为:
- 它允许接管标签页,但不会解除防护。 只有
safari_switch_tab可以接管,而且只能接管你指定的标签页。普通点击或导航仍不会跳转到碰巧处于最前面的标签页——服务器操作的是你指定的标签页,而不是你切换到的那个。 safari_close_tab仍会拒绝操作。 关闭是唯一无法撤销的操作,因此被接管的标签页可以修改,但不会被关闭。请自行关闭。- 接管仅限当前会话。 共享所有权文件中不会写入任何信息,因此接管会随着会话结束,不会泄漏到这台机器上的下一个进程。
safari_doctor 会显示该标记的状态,对被接管标签页的每次操作都会记录 (user tab, opted-in)——这样“它为什么操作我的标签页”就有据可查,不再是个谜。默认关闭;仅为你希望在自己的浏览会话中工作的 Agent 启用。设计详见 #92。
环境变量
| 变量 | 默认值 | 功能说明 |
|---|---|---|
SAFARI_MCP_HTTP | 关闭 | 运行一个共享的 HTTP 守护进程,而不是为每个客户端单独运行进程(见上文)。 |
SAFARI_MCP_HTTP_PORT | 9225 | 该守护进程使用的端口。 |
SAFARI_PROFILE | 未设置 | 将会话绑定到指定名称的 Safari 配置文件。未设置 = 使用普通窗口。 |
SAFARI_MCP_ALLOW_USER_TABS | 关闭 | 允许 safari_switch_tab 接管你已经打开的标签页,而不是拒绝接管(见下文)。 |
MCP_MAX_TABS | 6 | 单个会话最多可保持打开的标签页数。再打开一个标签页时,会关闭该会话中最早打开的标签页,并在 evictedTab(其回执)中由 safari_new_tab 标明。 |
SAFARI_MCP_RAISE_ON_NAVIGATE | 关闭 | 允许导航时将 Safari 调到前台,并阻止焦点保护机制切回你之前使用的应用。 |
SAFARI_MCP_SCREENSHOT_MAX_WIDTH | 未设置 | 将每张 safari_screenshot 截图缩小到此像素宽度(Retina 截图的尺寸是视口的 2 倍)。单次调用的 maxWidth 会覆盖此设置。 |
SAFARI_MCP_KEEPALIVE_TAB | 关闭 | 在配置文件窗口中保持打开一个由守护进程提供服务的页面,这样 Safari 就不会在命令之间挂起扩展工作线程。 |
SAFARI_MCP_OPEN_WINDOW_CMD | 未设置 | 配置文件窗口不存在时(例如重启后),使用配置文件名称运行此命令。命令必须打开窗口,但不能让 Safari 获得焦点。 |
SAFARI_MCP_RAISE_ON_NAVIGATE=1 适用于主要目的在于向你展示网页的 Agent,例如回答“打开 YouTube”的语音助手或演示驱动程序。其他情况都应关闭此选项:默认情况下,Safari MCP 会在后台运行,并将焦点交还给你正在使用的应用,因此 Agent 可以操作网页,而你可以继续在其他地方输入。
工具(98 个)
点击展开完整工具列表 — 按类别整理
导航(4 个)
| 工具 | 描述 |
|---|---|
safari_navigate | 导航至 URL(自动使用 HTTPS,并等待加载完成) |
safari_go_back | 返回上一页 |
safari_go_forward | 前进到下一页 |
safari_reload | 重新加载页面(可选强制重新加载) |
页面读取(3 个)
| 工具 | 描述 |
|---|---|
safari_read_page | 获取标题、URL 和文本内容 |
safari_get_source | 获取完整 HTML 源代码 |
safari_navigate_and_read | 一次调用即可导航并读取 |
点击与交互(6 个)
| 工具 | 描述 |
|---|---|
safari_click | 按 CSS 选择器、可见文本或坐标点击 |
safari_double_click | 双击(选择单词等) |
safari_right_click | 右键点击(打开上下文菜单) |
safari_hover | 将鼠标悬停在元素上 |
safari_click_and_wait | 点击并等待导航 |
safari_click_and_read | 点击后返回更新后的页面 — 减少一次往返调用(React Router + 完整页面加载) |
表单输入(11 个)
| 工具 | 描述 |
|---|---|
safari_fill | 填写输入框(兼容 React/Vue/Angular) |
safari_clear_field | 清空输入框 |
safari_select_option | 选择下拉选项 |
safari_fill_form | 批量填写多个字段 |
safari_fill_and_submit | 一次调用即可填写并提交表单 |
safari_type_text | 输入真实按键(基于 JS,无需 System Events) |
safari_press_key | 按下带修饰键的按键 |
safari_react_select_set | 通过 React fiber 设置 react-select v5 的值 — 绕过菜单界面 |
safari_react_select_list_options | 列出 react-select v5 下拉菜单的选项,无需打开菜单 |
safari_replace_editor | 替换代码编辑器中的全部内容(Monaco、CodeMirror、Ace、ProseMirror) |
safari_verify_state | 验证编辑器的框架层状态是否与预期一致 — 在提交前发现过时的 DOM |
截图与 PDF(3 个)
| 工具 | 描述 |
|---|---|
safari_screenshot | 将页面截取为 PNG(视口或完整页面) |
safari_screenshot_element | 截取指定元素 |
safari_save_pdf | 将页面导出为 PDF |
滚动(3)
| 工具 | 描述 |
|---|---|
safari_scroll | 按像素向上/向下滚动 |
safari_scroll_to | 滚动到指定位置 |
safari_scroll_to_element | 平滑滚动到元素 |
标签页管理(5)
| 工具 | 描述 |
|---|---|
safari_list_tabs | 列出所有标签页(索引、标题、URL) |
safari_new_tab | 打开新标签页(在后台打开,不抢占焦点) |
safari_close_tab | 关闭标签页 |
safari_switch_tab | 根据索引切换标签页 |
safari_wait_for_new_tab | 等待新标签页(例如 OAuth 弹窗)并自动切换到该标签页 |
等待(2)
| 工具 | 描述 |
|---|---|
safari_wait_for | 等待元素、文本或 URL 发生变化 |
safari_wait | 等待指定的毫秒数 |
JavaScript(3)
| 工具 | 描述 |
|---|---|
safari_evaluate | 执行任意 JavaScript 并返回结果 |
safari_eval_file | 执行从文件路径读取的 JavaScript(避免使用超大的内联脚本) |
safari_list_frames | 列出标签页中的每个文档(主页面和各个 iframe),包括 frameId、URL 和文本长度 — 将 frameId 传递给 safari_evaluate 的 frame,即可在跨域 iframe 中运行 |
元素检查(4)
| 工具 | 描述 |
|---|---|
safari_get_element | 元素详情(标签、rect、属性、可见性) |
safari_query_all | 查找所有匹配的元素 |
safari_get_computed_style | 计算后的 CSS 样式 |
safari_detect_forms | 自动检测所有表单及其字段选择器 |
无障碍(2)
| 工具 | 描述 |
|---|---|
safari_accessibility_snapshot | 完整的无障碍树:角色、ARIA、可聚焦元素 |
safari_snapshot | 为每个交互元素提供 ref ID 的无障碍树 — 查看页面状态的首选方式 |
拖放(1)
| 工具 | 描述 |
|---|---|
safari_drag | 在元素或坐标之间拖动 |
文件操作(2)
| 工具 | 描述 |
|---|---|
safari_upload_file | 通过 JS DataTransfer 上传文件(无需文件对话框!) |
safari_paste_image | 将图像粘贴到编辑器中(无需操作剪贴板!) |
对话框和窗口(2)
| 工具 | 描述 |
|---|---|
safari_handle_dialog | 处理 alert/confirm/prompt |
safari_resize | 调整浏览器窗口大小 |
设备模拟(2)
| 工具 | 描述 |
|---|---|
safari_emulate | 模拟设备(iPhone、iPad、Pixel、Galaxy) |
safari_reset_emulation | 重置为桌面模式 |
Cookie 和存储(11)
| 工具 | 描述 |
|---|---|
safari_get_cookies | 获取所有 Cookie |
safari_set_cookie | 设置 Cookie 及所有选项 |
safari_delete_cookies | 删除一个或所有 Cookie |
safari_local_storage | 读取 localStorage |
safari_set_local_storage | 写入 localStorage |
safari_delete_local_storage | 删除/清除 localStorage |
safari_session_storage | 读取 sessionStorage |
safari_set_session_storage | 写入 sessionStorage |
safari_delete_session_storage | 删除/清除 sessionStorage |
safari_export_storage | 将所有存储导出为 JSON(备份/恢复会话) |
safari_import_storage | 从 JSON 导入存储状态 |
剪贴板(2)
| 工具 | 描述 |
|---|---|
safari_clipboard_read | 读取剪贴板文本 |
safari_clipboard_write | 将文本写入剪贴板 |
网络(6)
| 工具 | 描述 |
|---|---|
safari_network | 通过 Performance API 快速发起网络请求 |
safari_start_network_capture | 开始详细捕获(fetch + XHR) |
safari_network_details | 获取捕获的请求及其标头/耗时信息 |
safari_clear_network | 清除捕获的请求 |
safari_mock_route | 模拟网络响应(拦截 fetch/XHR) |
safari_clear_mocks | 移除所有网络模拟 |
控制台(4)
| 工具 | 描述 |
|---|---|
safari_start_console | 开始捕获控制台消息 |
safari_get_console | 获取所有已捕获的消息 |
safari_clear_console | 清除已捕获的消息 |
safari_console_filter | 按级别筛选(log/warn/error) |
性能(2)
| 工具 | 描述 |
|---|---|
safari_performance_metrics | 导航计时、Web Vitals、内存 |
safari_throttle_network | 模拟 slow-3g/fast-3g/4g/离线 |
数据提取(4)
| 工具 | 描述 |
|---|---|
safari_extract_tables | 将表格提取为结构化 JSON |
safari_extract_meta | 提取所有元数据:OG、Twitter、JSON-LD、规范链接 |
safari_extract_images | 提取图片及其尺寸和加载信息 |
safari_extract_links | 提取链接及其 rel 属性,并检测外部链接和 nofollow 链接 |
高级功能(7)
| 工具 | 描述 |
|---|---|
safari_override_geolocation | 覆盖浏览器地理位置 |
safari_list_indexed_dbs | 列出 IndexedDB 数据库 |
safari_get_indexed_db | 读取 IndexedDB 记录 |
safari_css_coverage | 查找未使用的 CSS 规则 |
safari_analyze_page | 一次调用完成完整的页面分析 |
safari_doctor | 诊断 macOS 权限和守护进程链(Apple Events、Accessibility、Screen Recording、codesign),并针对每种故障提供修复方法 |
safari_reload_extension | 热重载 Safari MCP Bridge 扩展,无需手动切换 |
自动化(1)
| 工具 | 描述 |
|---|---|
safari_run_script | 在一次调用中运行多个操作(批量执行) |
原生输入 — CGEvent(4)
| 工具 | 描述 |
|---|---|
safari_native_click | 操作系统级鼠标点击(CGEvent,isTrusted: true)——当 safari_click 被拦截(405/403)时,可绕过 WAF/机器人检测 |
safari_native_hover | 操作系统级光标悬停——触发真实的 :hover/mouseenter,适用于工具提示和混淆 UI |
safari_native_type | 通过真实粘贴流程插入文本——ProseMirror/Slate/Draft.js 会原生处理文本,因此点击 Submit 会发送真实数据 |
safari_native_keyboard | 向 Safari 发送操作系统级按键和修饰键,不会夺取焦点——可触发 React 的信任门控处理程序(Discord/Slack 发送) |
iOS 和 WebKit 验证(4)
| 工具 | 描述 |
|---|---|
safari_inspect_viewport | 验证 iOS Safari 的 <meta name=viewport> 标签(device-width、缩放/WCAG、viewport-fit) |
safari_safe_area_insets | 读取实时 safe-area-inset 值以及 viewport-fit / env() 的用法(刘海屏 / Dynamic Island) |
safari_check_pwa | 检查 iOS“添加到主屏幕”/PWA 的就绪情况(apple-touch-icon、manifest、theme-color、启动画面) |
safari_webkit_compat | 使用 CSS.supports() 检查页面 CSS 在此 Safari 中的兼容性——不支持的属性、缺失的 -webkit- 前缀、已知问题 |
安全性
Safari MCP 在你的 Mac 本地运行,攻击面极小:
| 方面 | 详情 |
|---|---|
| 网络 | 无远程连接——所有通信均在本地进行(stdio + localhost) |
| 权限 | 需要 macOS 系统权限(截屏需要 Screen Recording) |
| 数据 | 无遥测、无分析数据,不会向任何地方发送数据 |
| 扩展 | 仅与本地配置文件桥接服务(localhost:9224/9228/9232/9236)通信,并由 Safari 验证 |
| 代码 | 完全开源(MIT)——可审查每一行代码 |
Safari MCP 与替代方案
| 功能 | Safari MCP | Chrome DevTools MCP | Playwright MCP |
|---|---|---|---|
| CPU/发热 | 🟢 极低 | 🔴 高 | 🟡 中等 |
| 你的登录信息 | ✅ 有 | ✅ 有 | ❌ 无 |
| macOS 原生 | ✅ WebKit | ❌ Chromium | ❌ Chromium/WebKit |
| 浏览器依赖项 | 无 | Chrome + 调试端口 | Playwright 运行时 |
| 工具 | 98 | ~30 | ~25 |
| 文件上传 | JS(无需对话框) | CDP | Playwright API |
| 粘贴图像 | JS(无需剪贴板) | CDP | Playwright API |
| 抢占焦点 | ❌ 后台运行 | ❌ 后台运行 | ❌ 无头模式 |
| 网络模拟 | ✅ | ❌ | ✅ |
| Lighthouse | ❌ | ✅ | ❌ |
| 性能跟踪 | ❌ | ✅ | ❌ |
提示: 日常浏览任务(95% 的工作)使用 Safari MCP,仅在进行 Lighthouse/Performance 审计时使用 Chrome DevTools MCP。
与 Apple 官方 Safari MCP(safaridriver)的比较
2026 年 7 月,Apple 发布了基于 safaridriver 构建的官方 Safari MCP 服务——先是在 Safari Technology Preview 247 中,之后在稳定版 Safari 27.0 中推出。这充分验证了这一类别的价值——但它针对的是另一种用途。Apple 的服务驱动的是用于调试的隔离 WebDriver 自动化会话;safari-mcp 驱动的是你已登录的真实 Safari。
在 macOS 27.0 和 Safari 27.0 上,safaridriver --help 会列出 --mcp,其 tools/list 返回 17 个条目(已于 2026-09-15 验证);Safari 26.5.2 没有 --mcp(已于 2026-07-23 验证)。可用 safaridriver --help | grep mcp 检查你自己的设备。
同时运行两者? Apple 的设置指南会将其服务注册为
safari-mcp(claude mcp add safari-mcp -- /usr/bin/safaridriver --mcp)——与此软件包同名。请为其中一个使用其他名称,例如claude mcp add safari-webdriver -- /usr/bin/safaridriver --mcp,以免客户端用一个覆盖另一个,或让你无法分辨是哪个服务作出了响应。
| 🦁 safari-mcp (此仓库) | Apple safaridriver --mcp | |
|---|---|---|
| 你的真实登录信息 / Cookie | ✅ 你的实际 Safari | ⚠️ 隔离的自动化会话——无法访问自动填充或浏览活动 |
| 运行环境 | ✅ 所有 Mac 上的稳定版 Safari | ⚠️ Safari 27 或更高版本,或 Safari Technology Preview 247+ |
| 后台运行(不抢占焦点) | ✅ 是 | ❌ 使用专用窗口,并显示“受自动化控制”横幅 |
页面能看到 navigator.webdriver | ✅ false——普通标签页 | ⚠️ true——所有 WebDriver 会话都必须如此 |
| 工具 | 98 | 17 |
| 存储(Cookie、localStorage、IndexedDB) | ✅ 10 个工具 | ❌ |
| 网络模拟 + 限速 | ✅ 有 | ❌ 只读网络检查 |
| 设备模拟(iPhone、iPad) | ✅ 有 | ⚠️ 仅限视口 + 媒体类型 |
| 设置 | npx safari-mcp | 在 Safari 的开发者设置中启用“允许远程自动化和外部 Agent”,然后将客户端指向 safaridriver --mcp |
| Apple 官方支持 | ❌ 社区维护(MIT) | ✅ Apple,符合 WebDriver 标准 |
关于
navigator.webdriver这一行: WebDriver 标准要求每个远程控制的会话都报告true,因此 Apple 的服务会这样做。safari-mcp 在普通标签页中执行 JavaScript,因此读取到的是false(已在 Safari 27.0 上于 2026-09-17 验证)。如果某个网站拒绝 WebDriver 流量,这就是两者的区别。这并不是反检测功能——浏览器的其他方面都没有伪装,而且使用的是真实登录信息,因此请假设每个页面都清楚地知道你的身份。
适合选择 Apple 服务的情况: 你明确需要一个干净隔离、符合 WebDriver 标准的会话,以便在 Safari 27 或更高版本上进行兼容性调试。其他所有情况——在你已登录的浏览器上进行日常后台自动化——safari-mcp 正是为此而构建的。
为什么选择 Safari MCP,而不是其他 Safari MCP 项目?
目前有几个名为 “safari-mcp” 的项目。下面是它们的对比:
| 功能 | 🦁 safari-mcp (本仓库) | lxman/safari-mcp-server | Epistates/MCPSafari | HayoDev/safari-devtools-mcp |
|---|---|---|---|---|
| 工具 | 98 | ~10 | 23 | ~15 |
| 安装 | npx safari-mcp | 手动 | 二进制文件 | npx |
| 引擎 | 双引擎(扩展 + AppleScript) | WebDriver | 仅扩展 | DevTools Protocol |
| 保留你在真实 Safari 中的登录状态 | ✅ 是 | ⚠️ 有限 | ✅ 是 | ❌ 调试会话 |
| 后台运行(不抢占焦点) | ✅ 是 | ❌ 否 | ⚠️ 有时 | ✅ 是 |
| 存储工具(Cookie、localStorage、IndexedDB) | 10 | 0 | 0 | 2 |
| 数据提取(表格、元信息、图片、链接) | 4 | 0 | 0 | 0 |
| 网络模拟 | ✅ 是 | ❌ 否 | ❌ 否 | ❌ 否 |
| 设备模拟(iPhone、iPad、Pixel) | ✅ 是 | ❌ 否 | ❌ 否 | ❌ 否 |
| 文件上传(无需对话框) | ✅ JS DataTransfer | ❌ 否 | ❌ 否 | ❌ 否 |
| 粘贴图片(不触碰剪贴板) | ✅ 是 | ❌ 否 | ❌ 否 | ❌ 否 |
| 导出 PDF | ✅ 是 | ❌ 否 | ❌ 否 | ❌ 否 |
| 控制台捕获 | 4 个工具 | 0 | 1 | 1 |
| 性能指标 + Web Vitals | ✅ 是 | ❌ 否 | ❌ 否 | ⚠️ 部分支持 |
| 积极维护 | ✅ 每周发布多个版本 | 🟡 偶尔 | 🟡 缓慢 | 🟡 缓慢 |
| 许可证 | MIT | MIT | 未指定 | MIT |
| 收录于 MCP Registry | ✅ | ❌ | ❌ | ✅ |
| 收录于 Awesome MCP | ✅ | ❌ | ❌ | ❌ |
简而言之——如果你想要功能最全面、安装最顺畅、工具最多且积极维护的 Safari MCP,选这个就对了。
架构
Safari MCP 采用双引擎架构——优先使用扩展,以获得更快速度和高级功能;同时将 AppleScript 作为始终可用的备用方案:
Claude/Cursor/AI Agent
↓ MCP Protocol (stdio)
Safari MCP Server (Node.js)
↓ ↓
Extension (HTTP) AppleScript + Swift daemon
(~5-20ms/cmd) (~5ms/cmd, always available)
↓ ↓
Content Script do JavaScript in tab N
↓ ↓
Page DOM ←←←←←←←←←← Page DOM
关键设计决策:
- 带自动回退的双引擎——优先使用扩展;如果未连接,则由 AppleScript 无缝处理所有操作
- 持久运行的 Swift 辅助程序——使用一个长期运行的进程,而不是为每条命令启动新进程(速度快 16 倍)
- 按标签页索引执行操作——所有 JS 都在指定索引的标签页上运行,绝不抢占视觉焦点
- 优先使用 JS——输入、点击和文件上传都使用 JavaScript 事件(不会与 System Events 的键盘操作冲突)
- 不调用
activate——Safari 永远不会被置于前台
Safari 扩展(可选)
Safari MCP 扩展可选但推荐安装。不安装扩展时,仍可单独通过 AppleScript 使用约 80% 的功能。扩展提供了 AppleScript 无法实现的能力:
扩展新增功能
| 能力 | 使用扩展 | 仅使用 AppleScript |
|---|---|---|
| 封闭式 Shadow DOM(Reddit、Web Components) | ✅ 完全访问 | ❌ 不可见 |
| 严格的 CSP 网站 | ✅ 通过 MAIN world 绕过限制 | ❌ 通常受阻 |
| 操控 React/Vue/Angular 状态 | ✅ 深度支持(Fiber、ProseMirror) | ⚠️ 基础支持 |
| 加载状态检测(加载动画、骨架屏) | ✅ 智能检测 | ❌ 不支持 |
| 对话框处理(alert/confirm) | ❌ | ✅ 仅 AppleScript 支持 |
| 原生系统级点击(CGEvent) | ❌ | ✅ 仅 AppleScript 支持 |
| 导出 PDF | ❌ | ✅ 仅 AppleScript 支持 |
什么时候需要扩展? 如果你要自动化操作使用封闭式 Shadow DOM 的现代 SPA(例如 Reddit)、采用严格内容安全策略的网站,或大量依赖框架的编辑器(Draft.js、ProseMirror、Slate),就需要扩展。
安装扩展
该扩展需要使用 Xcode(免费,随 macOS 提供)进行一次性构建。
npm 用户须知: npm 软件包中不包含
xcode/目录。 请克隆 GitHub 仓库以从源代码构建。
前置条件: Xcode(从 App Store 安装,免费)
# 1. Clone the repo (the npm package does not include the Xcode project)
git clone https://github.com/achiya-automation/safari-mcp.git
cd safari-mcp
# 2. Build a clean, Apple Development-signed app
# If needed, first choose your Team in Xcode → Signing & Capabilities.
xcodebuild -project "xcode/Safari MCP/Safari MCP.xcodeproj" \
-scheme "Safari MCP (macOS)" -configuration Release \
-allowProvisioningUpdates clean build
# 3. Locate the signed app
APP_PATH=$(find ~/Library/Developer/Xcode/DerivedData/Safari_MCP-*/Build/Products/Release -name "Safari MCP.app" -maxdepth 2 | head -1)
# 4. Re-sign safari-helper with the Apple Events entitlement
# (helps macOS surface the TCC Automation prompt reliably).
# Keep the stable identifier: macOS keys the Accessibility grant to it.
codesign --sign - --force --identifier com.achiya-automation.safari-mcp \
--entitlements safari-helper.entitlements safari-helper
# 5. Open the app (needed once so Safari registers the extension)
open "$APP_PATH"
请勿使用
codesign --deep --sign -对Safari MCP.app进行临时重签名。 这会替换封装应用和内嵌扩展上的 Apple Development 身份;当前版本的 Safari 可能会因此静默停用扩展或将其标记为已移除。如果先前的构建曾进行临时签名,请再次运行上面的clean build命令。
也可以直接在 Xcode 中打开 xcode/Safari MCP/Safari MCP.xcodeproj,在“Signing & Capabilities”下选择你的 Apple ID,然后点击 Run。免费的个人 Apple Developer 帐户足以满足本地使用需求。
然后在 Safari 中:
- Safari → 设置 → 高级 → 启用 显示网页开发者功能
- Safari → 设置 → 开发 → 允许未签名的扩展(每次重启 Safari 后都需要启用)
- Safari → 设置 → 扩展 → 启用 Safari MCP Bridge
扩展会自动连接到第一个声明的 Safari 配置文件与自身匹配的本地桥接服务。默认桥接端口为 9224、9228、9232 和 9236;单配置文件设置通常使用 9224。
注意: 每次 Safari 重启后,“允许未签名的扩展”都会重置。你需要在每次重启后前往 Safari → 设置 → 开发重新启用该选项。扩展本身仍会保持安装状态。
工具栏图标状态:
- ON — 已连接到 MCP 服务
- OFF — 已通过弹出窗口手动停用
- (无徽标) — 服务未运行,将自动重新连接
macOS 权限
Safari MCP 需要以下一次性权限:
| 权限 | 位置 | 用途 |
|---|---|---|
| 来自 Apple Events 的 JavaScript | Safari → 设置 → 开发 | do JavaScript 所必需 |
| 自动化 → Safari | 系统设置 → 隐私与安全性 → 自动化 | 所有由 AppleScript 支持的工具所必需 |
| 屏幕录制 | 系统设置 → 隐私与安全性 → 屏幕与系统音频录制 | 不使用扩展时运行 safari_screenshot 以及运行 safari_save_pdf 所必需 |
| 辅助功能(safari-helper) | 系统设置 → 隐私与安全性 → 辅助功能(macOS 27 中名为 设备控制与数据访问) | safari_native_click、safari_native_keyboard、safari_native_hover 和 safari_save_pdf 所必需 |
授予 safari-helper 辅助功能权限(运行 safari_native_* 所必需)
safari_native_click、safari_native_keyboard 和 safari_native_hover 工具会向 Safari 注入操作系统级别的 CGEvent 事件,而不会抢占焦点。macOS 要求先在辅助功能中批准底层 helper 二进制文件,这些事件才能发送到非前台窗口。
- 打开系统设置 → 隐私与安全性 → 辅助功能(在 macOS 27 中,该面板名为设备控制与数据访问)。
- 点击
+(如有需要,请使用密码解锁)。 - 找到 helper 二进制文件并添加:
- npm 全局安装:
$(npm root -g)/safari-mcp/safari-helper - npx / 项目安装:
./node_modules/safari-mcp/safari-helper - 从源代码克隆:
/path/to/safari-mcp/safari-helper
- npm 全局安装:
- 确保其旁边的开关处于 ON 状态。
postinstall 脚本会使用稳定标识符(com.achiya-automation.safari-mcp)重新签署 helper,使此权限在后续升级后仍然有效——如果没有这一步,每次 npm update 都会静默撤销批准,因为二进制文件的临时签名标识符会随每次构建而改变。
如果 safari_native_click 报告成功,但页面没有反应(未触发任何 isTrusted: true 点击事件),helper 很可能尚未获得此批准。safari_*(非 native_)工具不需要此权限。
授予自动化权限 → Safari(IDE 用户须知)
macOS TCC 会将自动化权限授予启动 MCP 服务的父进程,而不是 safari-mcp 本身。因此,你需要向运行 Claude Code / Cursor / Windsurf 的应用授予自动化 → Safari权限——通常是 Visual Studio Code 或 Terminal。
如果权限对话框没有自动出现,请在已获得自动化权限的 Terminal 中运行一次此命令:
osascript -e 'tell application "Safari" to get URL of current tab of window 1'
此调用会将 Terminal 应用注册到自动化数据库中,然后触发 Safari 的权限提示。批准后,后续来自任何子进程链的 MCP 调用都将正常工作。
故障排除
| 问题 | 解决方法 |
|---|---|
| "AppleScript error" | 在 Safari → 设置 → 开发者中启用 "允许来自 Apple 事件的 JavaScript" |
| "Not authorized to send Apple events to Safari" | 向你的 IDE 授予自动化 → Safari 权限(见上文) |
npm update 后出现 "Not authorized" | 更新会更改二进制文件的 cdhash — macOS 会静默撤销自动化权限。重新运行上文的 osascript 单行命令以重新授予权限 |
safari_native_click 报告成功,但页面没有反应 | 将 safari-helper 添加到系统设置 → 隐私与安全性 → 辅助功能(见上文授予辅助功能权限)。可在页面控制台中添加带有 {capture:true} 的 click 监听器来确认——如果没有授予权限,就不会触发 isTrusted: true 事件 |
| 截图为空 | 向 Terminal/VS Code 授予“屏幕与系统音频录制”权限——如果 safari-mcp 作为 LaunchAgent 运行,则向 node 二进制文件本身授予权限(Homebrew 的 node 升级会更改其路径,因此升级后需要重新授予)。safari_doctor 会显示确切的二进制文件 |
| 启用 "允许未签名扩展" 后找不到扩展(macOS 27) | 已知的 macOS 27.0 问题(183044008):启用此设置后,重新构建扩展应用(见安装扩展),扩展便会出现 |
| 找不到标签页 | 调用 safari_list_tabs 刷新标签页索引 |
| 希伯来语键盘问题 | 所有输入都使用 JS 事件,不受键盘布局影响 |
| HTTPS 被阻止 | safari_navigate 会自动先尝试 HTTPS,失败后再回退到 HTTP |
| Safari 抢占焦点 | 确保使用最新版本——newTab 会恢复你当前活动的标签页 |
常见问题
能与 Safari Technology Preview 配合使用吗?
不能。每条 AppleScript 路径都指向 application "Safari",而原生辅助程序会查找捆绑包 ID com.apple.Safari,因此 STP(com.apple.SafariTechnologyPreview)是另一个应用,safari-mcp 不会对其执行操作。请在正式版 Safari 中运行。
请注意,需要 STP 247+(或 Safari 27+)的是 Apple 自带的 safaridriver --mcp 服务——见 Safari MCP 与替代方案。两者互不相关。
能处理隐私/无痕标签页吗?
这不是受支持的模式,也未经测试。没有任何工具会打开隐私窗口,而且 Safari 默认会在“无痕浏览”中停用扩展,除非你逐个明确启用。因此,扩展桥接——以及Safari 扩展(可选)中“使用扩展”列的所有功能——默认在隐私浏览中不可用。
如果你想使用隔离的身份,请改用单独的 Safari 配置文件:配置文件窗口是此处的一等概念(见同时运行多个 Agent)。
能与多个 Safari 窗口配合使用吗?
可以。标签页查找会遍历 every window,而不是假定窗口 1;由于打开两个窗口后单独的索引会有歧义,因此标签页会通过其窗口的 (index, tabCount) 对来定位。Safari 会根据 ProfileName — Tab Title 窗口名称识别配置文件窗口。
可靠的句柄仍然是 safari_new_tab 返回的 收据:将它传给后续的每次调用,就能直接定位该标签页,无论周围有多少窗口在移动。
支持哪些 macOS 版本?
任何装有 Safari 的 macOS 均可使用——软件包声明了 "os": ["darwin"],没有最低操作系统版本要求,代码中也没有版本限制。硬性要求是 Node.js 20+("engines": { "node": ">=20" })。
在实际使用中,有两处与操作系统版本有关:
- 在 macOS 27 中,「辅助功能」面板更名为「设备控制与数据访问」——授权相同,只是名称不同(参见 macOS 权限)。
- Safari 26 和 27 更改了若干 Web 平台行为,部分工具已针对这些变化进行适配;这些变化会得到处理,不会导致功能被禁用。
可以同时运行多个实例吗?
可以——同时运行多个 Agent 介绍的就是这种用法。每个会话拥有自己的标签页,所有权按会话而非标签页索引进行跟踪,因此一个 Agent 无法操作(或关闭)另一个 Agent 拥有的标签页。
一个进程会绑定扩展桥接端口;其他进程通过它代理请求,并在该进程退出时接管端口。
必须让 Safari 保持在前台吗?
不需要。safari_new_tab 会打开后台标签页,绝不会抢占焦点;对于少数 macOS 强制在恢复时隐式激活应用的命令,系统会在操作后恢复你之前位于最前面的应用——同时设有保护机制:如果你刚刚还在 Safari 中输入内容,就不会更改焦点。
两个例外是特意设计为原生操作的工具——safari_native_click、safari_native_keyboard、safari_native_hover——它们会发送真实的操作系统事件,因此事件会作用于当前最前面的窗口。当你正在使用另一个 Safari 标签页时,请勿使用这些工具。
它如何与 Safari 扩展交互?
你现有的扩展会照常运行;safari-mcp 驱动的就是你平时使用的 Safari,因此内容拦截器和密码管理器的行为与你平时完全相同。
safari-mcp 还附带自己的可选扩展。不安装该扩展时,仍有约 80% 的工具可仅通过 AppleScript 工作;安装后,还可支持封闭式 Shadow DOM、严格 CSP 网站、深层框架状态以及加载状态检测。对话框处理、原生点击和 PDF 导出则恰好相反——这些功能仅通过 AppleScript 实现。完整的功能划分见 Safari 扩展(可选)。
如果未启用“允许来自 Apple Events 的 JavaScript”会怎样?
所有需要执行 JavaScript 的功能都会失败——包括 safari_evaluate、safari_read_page、表单填写和内容提取;而打开或切换标签页等纯 AppleScript 操作仍可正常工作。这通常就是“标签页能打开,但什么都读不到”的原因。
请前往 Safari → 设置 → 高级 → 显示网页开发者功能,然后前往 Safari → 设置 → 开发者 → 允许来自 Apple Events 的 JavaScript,启用该选项。这两项都列在前置要求中。safari_doctor 会检查后续各环节(自动化、原生辅助程序、辅助功能、屏幕录制),并在修复提示中指出此设置——但其 Apple Events 检查只会统计窗口,而仅有自动化权限就足以通过这项检查,因此它不会替你检测此项设置是否已启用。
适用客户端
Safari MCP 适用于任何兼容 MCP 的客户端:
| 客户端 | 状态 |
|---|---|
| Claude Code | ✅ 每日测试 |
| Claude Desktop | ✅ 已测试 |
| Cursor | ✅ 已测试 |
| Windsurf | ✅ 兼容 |
| VS Code + Continue | ✅ 兼容 |
贡献
欢迎提交 PR!设置说明请参阅 CONTRIBUTING.md。
代码库由两个文件组成:
safari.js— Safari 自动化层(AppleScript + JavaScript)index.js— 含工具定义的 MCP 服务
赞助
Safari MCP 免费且开源。如果它为你节省了时间或 CPU 资源,不妨支持其开发:
你的支持将用于:
- 🧪 在不同 macOS 版本和 Safari 版本上进行测试
- 🛠️ 开发新工具和功能
- 📖 编写文档和示例
商业支持
需要将 Safari MCP 集成到你的产品或 Agent 技术栈中? Achiya Automation 可提供:
- 优先修复 Bug,并根据你的使用场景定制开发工具
- 集成咨询 — 将 Safari MCP 接入生产环境中的 Agent 系统(Claude、Cursor、n8n、自定义系统)
- 私有部署支持 — 多用户 Safari MCP、非标准 macOS 环境、CI/CD
- 为采用基于 MCP 的自动化的工程团队提供培训工作坊
由 Safari MCP 的作者打造。开始交流 →
Safari MCP 为 Agent 解锁的能力
当 AI Agent 驱动 Safari MCP 时,它可以实现无头浏览器无法做到的事:
- 真实的已认证会话 — Gmail、GitHub、Ahrefs、Slack、银行控制面板都已登录
- 感知框架的表单填写 —
safari_fill_and_submit原生调用 React/Vue/Angular setter,无需猜测input事件是否已触发 - 后台运行 — Agent 可并行工作,同时你继续使用 Mac
- 每个工作流只需调用一次 MCP —
safari_run_script将导航、点击和提取批量处理为一次往返
这种模式适用于各种模型:驱动人类已经信任的浏览器 — 一步即可继承登录状态、Cookie、扩展程序和用户的确切环境。
社区
每月 npm 下载量超过 6,000 次 — 开发者正在 macOS 上使用 Safari MCP 构建 AI Agent。
- GitHub 讨论区 — 提问、分享使用场景
- 问题 — Bug 报告和功能请求
— 开始参与贡献
生态系统
其他可与 Safari MCP 搭配使用的 macOS MCP 服务:
| 项目 | 功能 | 适用场景 |
|---|---|---|
| mcp-server-macos-use | 操作系统级 macOS 自动化(辅助功能、屏幕控制) | Safari 之外的全系统交互 |
| chrome-devtools-mcp | Chrome DevTools Protocol | Lighthouse 审计、Chrome 专属性能跟踪 |
同时使用 Safari MCP 和 Chrome DevTools MCP?Safari 可处理日常浏览的 95%(零开销),Chrome 则负责需要 Lighthouse 或 Chrome 专属跟踪的 5%。
收录于
许可证
MIT — 随你使用。
由 Achiya Automation 构建 — 为企业提供自动化与 AI Agent。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。