cli-anything-safari 是做什麼的?
一個用於在 macOS 上自動化 Safari 瀏覽器的命令列介面。它透過 Python Click CLI 封裝了
safari-mcp Node.js MCP 伺服器。
功能完全一致。 每個 Click 命令都從 safari-mcp 的工具模式(捆綁在
resources/tools.json 中)自動生成。所有 84 種工具都可以使用與 MCP 伺服器預期完全相同的引數名稱和類型來呼叫。
何時使用此 CLI
每次 CLI 調用都會啟動一個新的子程序,因此會有每次呼叫的開銷。如果您的代理原生支援 MCP(Claude Code、Cursor、Cline 等),則直接透過 MCP stdio 使用 safari-mcp 會更快。
在以下情況下使用此 CLI:
- 您的代理框架不支援 MCP(Codex CLI、GitHub Copilot CLI、自訂腳本、較舊的代理框架)。
- 您需要從 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 事件:Safari → 開發 → 允許來自 Apple 事件的 JavaScript
安裝 CLI
cd safari/agent-harness
pip install -e .
第一次呼叫 tool 時,會下載 safari-mcp npm 套件(一次性,約數 MB)。
命令結構
CLI 有 5 個頂層命令:
| 命令 | 用途 |
|---|---|
tool | 呼叫 safari-mcp 的 84 種工具(動態、基於模式驅動) |
tools | 檢視捆綁的工具註冊表(list、describe、count) |
raw | 逃生口 — 使用完整名稱和原始 JSON 引數呼叫工具 |
session | 記憶體中的會話狀態(上一個 URL、當前分頁) |
repl | 互動式 REPL(未給子命令時的預設值) |
使用範例
探索工具表面
# 工具計數(合理性檢查 — 必須與 safari-mcp 註冊的工具數相符)
cli-anything-safari tools count
# → 84
# 列出每個工具
cli-anything-safari tools list
cli-anything-safari tools list --filter click # 依子字串過濾
# 檢視某個工具的完整模式(JSON 或人類可讀格式)
cli-anything-safari tools describe safari_scroll
cli-anything-safari --json tools describe safari_click
呼叫工具(基於模式驅動)
# 導航
cli-anything-safari tool navigate --url https://example.com
# 取得快照(優於截圖 — 結構化文字並包含參考 ID)
cli-anything-safari --json tool snapshot
# 依據參考 ID 點擊(參考 ID 來自快照;它們會在下一次快照時過期!)
cli-anything-safari tool click --ref 0_5
# 依據選擇器或可見文字點擊
cli-anything-safari tool click --selector "#submit"
cli-anything-safari tool click --text "Log in"
# 填入欄位
cli-anything-safari tool fill --selector "#email" --value "[email protected]"
# 依方向/數量滾動(不是 x/y — 注意模式!)
cli-anything-safari tool scroll --direction down --amount 500
# 將一個元素拖曳到另一個元素上
cli-anything-safari tool drag \
--source-selector ".card" \
--target-selector ".trash"
# 截圖 — 在標準輸出中傳回 base64 JPEG。使用以下命令解碼:
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']))"
# 另存為 PDF(此命令直接寫入磁碟)
cli-anything-safari tool save-pdf --path /tmp/page.pdf
# 執行 JavaScript(注意:參數是 --script,而不是 --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 以查看
確切的模式,包括 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 將 JSON 傳回標準輸出 — 沒有 --path 引數。將其導向檔案:
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 的絕對路徑,以便代理可以自我發現功能。
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旗標):結構化 JSON,供代理使用
# 人類可讀輸出
cli-anything-safari tool snapshot
# 供代理使用的 JSON 輸出
cli-anything-safari --json tool snapshot
cli-anything-safari --json tools list
cli-anything-safari --json tools describe safari_click
給 AI 代理的建議
以程式方式使用此 CLI 時:
- 始終使用
--json旗標以獲得可解析的輸出。 - 檢查回傳碼 — 0 表示成功,非零表示錯誤(URL 驗證失敗、MCP 呼叫失敗、JSON 引數無效)。
- 解析標準錯誤以獲取錯誤訊息;使用標準輸出獲取資料。
- 處理檔案的工具具有不一致的路徑引數名稱 — 始終先檢查
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的參考 ID 在下一次快照時過期。始終先快照 → 尋找參考 ID → 緊接在後點擊。 - 透過
tools list發現工具 — 捆綁的註冊表是了解可用工具的唯一事實來源。不要硬編碼可能在上游變更的工具名稱。 - 使用
tools describe <name>來了解確切的模式(必要引數、列舉選項、JSON 類型引數),然後再構建呼叫。切勿根據描述來假設參數名稱 — 例如,safari_evaluate接受--script(而不是--code),即使描述說「要執行的 JavaScript 程式碼」。
特定於代理的指導
尋找正確的工具
使用內省命令。CLI 保證與 MCP 伺服器 1:1 對應:
# 尋找所有與點擊相關的工具
cli-anything-safari tools list --filter click
# 取得完整模式(包括每個引數的類型、描述、
# 必要/可選、列舉選項、預設值)
cli-anything-safari --json tools describe safari_click
工具選擇策略
tool snapshot優於tool screenshot— 具有參考 ID 的結構化文字成本低得多,並且帶有點擊所需的參考 ID。tool click --ref優於tool click --selector— 參考 ID 在單次快照內是穩定的,而選擇器可能很脆弱。tool navigate-and-read優於navigate+read-page— 節省一次往返。tool click-and-read優於click+read-page— 節省一次往返。tool native-click僅在常規點擊失敗並出現 405/403 錯誤時使用(WAF 阻擋、G2、Cloudflare)— 它會實際移動游標。
參考 ID 會過期
來自 tool snapshot 的參考 ID 在您拍攝新快照時過期:
- 第一次快照:參考 ID
0_1、0_2、0_3... - 第二次快照:參考 ID
1_1、1_2、1_3...
始終在短時間內連續執行快照 → 點擊。如果不確定,請再次快照。
分頁擁有權安全性
Safari MCP 會追蹤每個會話的分頁擁有權。修改分頁的工具(導航、點擊、填寫)在未由該會話開啟的分頁上會被阻止。要在特定網頁上操作,請始終以 tool new-tab --url ... 開始。
錯誤處理
常見錯誤:
npx not found→ 安裝 Node.js 18+safari-mcp package not found on npm registry→ 檢查網路Not macOS→ 此工具僅限 macOSAppleScript denied→ 在 Safari → 開發中啟用「允許來自 Apple 事件的 JavaScript」Blocked URL scheme: file→ URL 驗證拒絕了輸入(設計如此)
URL 驗證
CLI 在將 URL 傳遞給 safari_navigate、safari_navigate_and_read 和 safari_new_tab 之前會驗證它們。被封鎖的協定:file、javascript、data、vbscript、about、chrome、safari、webkit、x-apple 以及其他瀏覽器內部協定。raw 命令也對導航工具執行此驗證。
多重會話警告
Safari MCP 透過終止超過 10 秒的舊 Node.js 程序來強制執行單一作用中會話。如果您同時執行兩個 CLI 實例,其中一個將會終止另一個的後端。目前沒有守護程序模式 — 對於延遲敏感的工作流程,請從長期執行的 Python 腳本驅動 CLI,該腳本直接匯入 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,請重新產生捆綁的模式:
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 重新產生。