关于 cli-anything-safari
面向无法直接使用 MCP 的 Agent 和脚本,提供 macOS Safari 自动化的 Python 命令行工具。它通过架构驱动的命令和 JSON 输出调用 safari-mcp 的工具。
主要功能
- 01通过命令行调用 safari-mcp 工具
- 02查看工具名称和架构
- 03浏览网页、读取页面并交互
- 04管理 Cookie 和浏览器存储
- 05采集网络与性能数据
- 06提供交互式 REPL 和 JSON 输出
适用场景
- 01通过 bash 脚本自动化 Safari
- 02在 CI/CD 中运行浏览器任务
- 03为不支持 MCP 的 Agent 使用 Safari 自动化
MCP 相关
该命令行工具封装了 safari-mcp Node.js MCP 服务,并将其工具作为命令提供。其工具注册表遵循服务端架构。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ hkuds/ cli-anything --skill cli-anything-safari安装后在 Claude Code 中输入/cli-anything-safari确认已加载。
详细介绍
cli-anything-safari
一个用于在 macOS 上自动化 Safari 浏览器的命令行界面。将
safari-mcp Node.js MCP
服务封装为一个 Python Click CLI。
功能对等性有保障。 每个 Click 命令都从 safari-mcp 的工具 schema
(打包为 resources/tools.json)自动生成。全部 84 个工具均可使用,
并采用 MCP 服务所期望的精确参数名称和类型。
何时使用此 CLI
每次 CLI 调用都会生成一个新的子进程,因此存在每次调用的开销。
如果你的 Agent 原生支持 MCP(Claude Code、Cursor、Cline
等),直接通过 MCP stdio 使用 safari-mcp 会更快。
在以下情况下使用此 CLI:
- 你的 Agent 框架不支持 MCP(Codex CLI、GitHub Copilot CLI、自定义脚本、较旧的 Agent 框架)。
- 你需要从 bash 脚本化浏览器自动化 —
cli-anything-safari --json tool snapshot | jq '...'。 - 你在 CI/CD 中运行,并且希望获得可通过 cron 调度、对子进程友好的输出。
- 你正在从终端进行交互式调试。
安装
前提条件
- macOS — Safari MCP 仅支持 macOS。
- Safari — 已预装在 macOS 上。
- Node.js 18+ —
brew install node或访问 https://nodejs.org/ - Python 3.10+
- 为 Safari 启用 Apple Events:Safari → 开发 → 允许来自 Apple Events 的 JavaScript
安装 CLI
cd safari/agent-harness
pip install -e .
首次调用 tool 时会下载 safari-mcp npm 包(一次性,几 MB)。
命令结构
此 CLI 有 5 个顶层命令:
| 命令 | 用途 |
|---|---|
tool | 调用 safari-mcp 的任意 84 个工具(动态、由 schema 驱动) |
tools | 检查打包的工具注册表(list、describe、count) |
raw | 逃生舱 — 使用完整名称和原始 JSON 参数调用工具 |
session | 内存中的会话状态(上次 URL、当前标签页) |
repl | 交互式 REPL(未给出子命令时的默认行为) |
用法示例
探索工具界面
# Count of tools (sanity check — must match safari-mcp's registered tools)
cli-anything-safari tools count
# → 84
# List every tool
cli-anything-safari tools list
cli-anything-safari tools list --filter click # filter by substring
# Full schema for one tool (JSON or human format)
cli-anything-safari tools describe safari_scroll
cli-anything-safari --json tools describe safari_click
调用工具(由 schema 驱动)
# Navigate
cli-anything-safari tool navigate --url https://example.com
# Take a snapshot (preferred over screenshot — structured text with ref IDs)
cli-anything-safari --json tool snapshot
# Click by ref (refs come from snapshot; they expire on the next snapshot!)
cli-anything-safari tool click --ref 0_5
# Click by selector or visible text
cli-anything-safari tool click --selector "#submit"
cli-anything-safari tool click --text "Log in"
# Fill a field
cli-anything-safari tool fill --selector "#email" --value "[email protected]"
# Scroll by direction/amount (NOT x/y — note the schema!)
cli-anything-safari tool scroll --direction down --amount 500
# Drag one element onto another
cli-anything-safari tool drag \
--source-selector ".card" \
--target-selector ".trash"
# Screenshot — returns base64 JPEG in stdout. Decode with:
cli-anything-safari --json tool screenshot --full-page \
| python3 -c "import sys,json,base64; \
d=json.load(sys.stdin); \
open('/tmp/shot.jpg','wb').write(base64.b64decode(d['data']))"
# Save as PDF (this one writes to disk directly)
cli-anything-safari tool save-pdf --path /tmp/page.pdf
# Evaluate JavaScript (note: parameter is --script, not --code)
cli-anything-safari tool evaluate --script "document.title"
一次性完成导航和读取
cli-anything-safari --json tool navigate-and-read --url https://example.com
表单填充(批量)
safari_fill_form 接受一个由 {selector, value} 对象组成的数组。
将其作为 JSON 字符串传入:
cli-anything-safari tool fill-form --fields '[
{"selector": "#email", "value": "[email protected]"},
{"selector": "#password", "value": "hunter2"}
]'
运行 cli-anything-safari tools describe safari_fill_form 查看
确切的 schema,包括 safari-mcp 在上游添加的任何新字段。
网络监控
cli-anything-safari tool start-network-capture
cli-anything-safari tool navigate --url https://example.com
cli-anything-safari --json tool network
cli-anything-safari tool performance-metrics
存储
cli-anything-safari tool get-cookies
cli-anything-safari tool set-cookie --name session --value abc123 --domain example.com
cli-anything-safari tool local-storage --key theme
# export-storage returns JSON to stdout — no --path arg. Pipe to a file:
cli-anything-safari --json tool export-storage > /tmp/storage.json
原始 JSON 逃生舱
当你需要传入复杂的嵌套对象,或想用预先构建好的 JSON blob 驱动 CLI 时:
cli-anything-safari raw safari_evaluate \
--json-args '{"code":"[...document.querySelectorAll(\"a\")].map(a => a.href)"}'
交互式 REPL
cli-anything-safari
REPL 横幅会打印此 SKILL.md 的绝对路径,以便 Agent 能够自行发现各项能力。
JSON 输出
所有命令都支持将 --json 作为全局标志:
cli-anything-safari --json tool snapshot
cli-anything-safari --json tool list-tabs
cli-anything-safari --json tools list
状态管理
CLI 维护少量仅供 REPL 显示的内存状态:
last_url— CLI 上次导航到的 URL(在每次 成功的tool navigate、tool navigate-and-read或tool new-tab之后更新)current_tab_index— 最后已知的活动标签页索引
没有持久化会话,没有撤销/重做,没有文档模型。
每次 CLI 调用都从全新状态开始。Safari MCP 本身
是每次调用无状态的:每个 tool 命令都会生成一个新的
npx safari-mcp 子进程,执行操作,然后退出。这是一个
有意的设计选择;有关偏离标准撤销/重做模式背后的
原因,请参阅 HARNESS.md 和 TEST.md。
输出格式
所有命令都支持两种输出模式:
- 人类可读(默认):对
dict结果使用缩进的键值文本,对数组使用项目符号列表,其他情况使用纯文本 - 机器可读(
--json标志):供 Agent 使用的结构化 JSON
# Human output
cli-anything-safari tool snapshot
# JSON output for agents
cli-anything-safari --json tool snapshot
cli-anything-safari --json tools list
cli-anything-safari --json tools describe safari_click
面向 AI Agent
以编程方式使用此命令行程序时:
- 始终使用
--json标志以获得可解析的输出。 - 检查返回码 — 0 表示成功,非零表示错误(URL 验证失败、MCP 调用失败、无效的 JSON 参数)。
- 解析 stderr 获取错误信息;使用 stdout 获取数据。
- 文件处理工具的参数名不一致 — 务必
先检查
tools describe <name>:tool save-pdf --path /tmp/x.pdftool upload-file --selector ... --file-path /tmp/x.txt(注意:是--file-path,不是--path)tool export-storage— 没有路径参数;将 JSON 输出通过管道写入文件tool import-storage --path /tmp/x.jsontool screenshot/screenshot-element— 在 JSON 响应中返回 base64,没有路径参数(自行解码)
- 点击前先快照 — 来自
tool snapshot的 ref 会在 下一次快照时失效。务必快照 → 查找 ref → 点击, 连续快速完成。 - 通过
tools list发现工具 — 内置注册表是 可用工具的唯一权威来源。不要硬编码可能在上游 发生变化的工具名。 - 使用
tools describe <name>了解确切的 schema(必需 参数、枚举选项、JSON 类型参数),然后再构造调用。 切勿根据描述臆测参数名 — 例如,safari_evaluate接受--script(不是--code), 尽管描述中写的是 "JavaScript code to execute"。
面向 Agent 的专门指引
找到正确的工具
使用内省命令。此命令行程序保证与 MCP 服务 1:1 对应:
# Find all click-related tools
cli-anything-safari tools list --filter click
# Get the full schema (including every argument with type, description,
# required/optional, enum choices, defaults)
cli-anything-safari --json tools describe safari_click
工具选择策略
tool snapshot优于tool screenshot— 带 ref ID 的结构化 文本成本低几个数量级,并且携带点击所需的 ref。tool click --ref优于tool click --selector— ref 在 单次快照内稳定,选择器可能脆弱。tool navigate-and-read优于navigate+read-page— 节省一次 往返。tool click-and-read优于click+read-page— 节省一次往返。tool native-click仅在普通点击因 405/403 失败时使用(WAF 拦截、G2、Cloudflare)— 它会物理移动光标。
Ref 会过期
来自 tool snapshot 的 ref 在你进行新快照时过期:
- 第一次快照:ref 为
0_1、0_2、0_3... - 第二次快照:ref 为
1_1、1_2、1_3...
务必快照 → 点击,连续快速完成。如有疑问,再次快照。
标签页归属安全
Safari MCP 按会话跟踪标签页归属。会修改标签页的
工具(navigate、click、fill)在会话未打开的标签页上会被阻止。
要对特定页面进行操作,始终以 tool new-tab --url ... 开始。
错误处理
常见错误:
npx not found→ 安装 Node.js 18+safari-mcp package not found on npm registry→ 检查网络Not macOS→ 测试环境仅支持 macOSAppleScript denied→ 在 Safari → Develop 中启用 "Allow JavaScript from Apple Events"Blocked URL scheme: file→ URL 验证拒绝了输入(设计如此)
URL 验证
此命令行程序在将 URL 传递给 safari_navigate、
safari_navigate_and_read 和 safari_new_tab 之前会验证它们。被阻止的 scheme:
file、javascript、data、vbscript、about、chrome、safari、
webkit、x-apple 以及其他浏览器内部 scheme。raw
命令在导航工具上同样强制执行此规则。
多会话警告
Safari MCP 通过终止超过 10 秒的陈旧 Node.js
进程来强制单活动会话。如果你同时运行两个命令行程序实例,
其中一个会终止另一个的后端。目前没有守护进程
模式 — 对于延迟敏感的工作流,请通过一个
长期运行的 Python 脚本驱动此命令行程序,该脚本直接导入
cli_anything.safari.utils.safari_backend.call(),以避免每次调用都重新生成子进程。
链接
安全注意事项
URL 校验
所有导航工具(tool navigate、tool navigate-and-read、tool new-tab 以及 raw safari_navigate*)都会将 url 参数传入
utils/security.py,该模块会拦截危险协议,并可选地拦截
私有网络(设置 CLI_ANYTHING_SAFARI_BLOCK_PRIVATE=1)。
标签页隔离
Safari MCP 在上游强制执行按会话的标签页归属 —— 工具无法 操作该会话未打开的标签页。
配置文件隔离
设置 SAFARI_PROFILE 环境变量,为自动化使用单独的 Safari 配置文件:
export SAFARI_PROFILE="Automation"
cli-anything-safari tool navigate --url https://example.com
这样可将 cookie/登录状态/历史记录与用户的主浏览活动隔离开来。
JavaScript 执行
tool evaluate 和 tool run-script 会在页面上下文中运行任意 JavaScript。
请像对待任何动态代码执行路径一样,谨慎处理不受信任的输入。
剪贴板
tool clipboard-read 和 tool clipboard-write 会访问系统
剪贴板。在用户的活动会话中运行时请务必小心 ——
在任务进行中覆盖剪贴板会造成干扰。
重新生成工具注册表
如果你升级了 safari-mcp,请重新生成捆绑的 schema:
python scripts/extract_tools.py \
"$(npm root -g)/safari-mcp/index.js" \
cli_anything/safari/resources/tools.json
一致性测试(test_parity.py)固定了预期的工具数量;当上游工具列表
发生变化时,请更新它。
更多信息
- 完整文档: 软件包中的
cli_anything/safari/README.md - 测试覆盖: 软件包中的
cli_anything/safari/tests/TEST.md - 架构分析:
safari/agent-harness/SAFARI.md - 方法论:
cli-anything-plugin/HARNESS.md - MCP 后端模式:
cli-anything-plugin/guides/mcp-backend.md
版本
1.0.0 —— 面向 safari-mcp 2.7.8(84 个工具)。当 safari-mcp 升级时,
捆绑的工具注册表会通过 scripts/extract_tools.py 重新生成。