mcpField
C
cli-anything-safari

cli-anything-safari

github.com/hkudsAgent 工作流57.6k492 次安装5 周前更新
代码仓库

关于 cli-anything-safari

面向无法直接使用 MCP 的 Agent 和脚本,提供 macOS Safari 自动化的 Python 命令行工具。它通过架构驱动的命令和 JSON 输出调用 safari-mcp 的工具。

主要功能

  1. 01通过命令行调用 safari-mcp 工具
  2. 02查看工具名称和架构
  3. 03浏览网页、读取页面并交互
  4. 04管理 Cookie 和浏览器存储
  5. 05采集网络与性能数据
  6. 06提供交互式 REPL 和 JSON 输出

适用场景

  1. 01通过 bash 脚本自动化 Safari
  2. 02在 CI/CD 中运行浏览器任务
  3. 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 调度、对子进程友好的输出。
  • 你正在从终端进行交互式调试。

安装

前提条件
  1. macOS — Safari MCP 仅支持 macOS。
  2. Safari — 已预装在 macOS 上。
  3. Node.js 18+ — brew install node 或访问 https://nodejs.org/
  4. Python 3.10+
  5. 为 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

以编程方式使用此命令行程序时:

  1. 始终使用 --json 标志以获得可解析的输出。
  2. 检查返回码 — 0 表示成功,非零表示错误(URL 验证失败、MCP 调用失败、无效的 JSON 参数)。
  3. 解析 stderr 获取错误信息;使用 stdout 获取数据。
  4. 文件处理工具的参数名不一致 — 务必 先检查 tools describe <name>:
    • tool save-pdf --path /tmp/x.pdf
    • tool upload-file --selector ... --file-path /tmp/x.txt(注意:是 --file-path,不是 --path)
    • tool export-storage — 没有路径参数;将 JSON 输出通过管道写入文件
    • tool import-storage --path /tmp/x.json
    • tool screenshot / screenshot-element — 在 JSON 响应中返回 base64,没有路径参数(自行解码)
  5. 点击前先快照 — 来自 tool snapshot 的 ref 会在 下一次快照时失效。务必快照 → 查找 ref → 点击, 连续快速完成。
  6. 通过 tools list 发现工具 — 内置注册表是 可用工具的唯一权威来源。不要硬编码可能在上游 发生变化的工具名。
  7. 使用 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
工具选择策略
  1. tool snapshot 优于 tool screenshot — 带 ref ID 的结构化 文本成本低几个数量级,并且携带点击所需的 ref。
  2. tool click --ref 优于 tool click --selector — ref 在 单次快照内稳定,选择器可能脆弱。
  3. tool navigate-and-read 优于 navigate + read-page — 节省一次 往返。
  4. tool click-and-read 优于 click + read-page — 节省一次往返。
  5. 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 → 测试环境仅支持 macOS
  • AppleScript 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 重新生成。

评论

支持 Markdown