cli-anything-safari은(는) 무엇을 하나요?
macOS에서 Safari 브라우저를 자동화하기 위한 명령줄 인터페이스입니다. Node.js MCP 서버인 safari-mcp를 Python Click CLI로 감쌉니다.
기능 패리티가 보장됩니다. 모든 Click 명령어는 safari-mcp의 도구 스키마(번들: resources/tools.json)에서 자동 생성됩니다. MCP 서버가 기대하는 정확한 인수 이름과 유형으로 84개 모든 도구에 접근할 수 있습니다.
이 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 Events 활성화: Safari → 개발 → Apple Events에서 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
# 참조로 클릭 (참조는 스냅샷에서 제공되며, 다음 스냅샷에서 만료됨!)
cli-anything-safari tool click --ref 0_5
# 선택자 또는 표시 텍스트로 클릭
cli-anything-safari tool click --selector "#submit"
cli-anything-safari tool click --text "로그인"
# 필드 채우기
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"
# 스크린샷 — stdout에 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 평가 (매개변수는 --code가 아닌 --script)
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는 stdout에 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은 성공, 0이 아니면 오류(URL 유효성 검사 실패, MCP 호출 실패, 잘못된 JSON 인수).
- stderr를 파싱하여 오류 메시지를 얻고, stdout을 데이터에 사용하세요.
- 파일 처리 도구는 일관되지 않은 경로 인수 이름을 가집니다 — 항상
tools describe <name>을 먼저 확인하세요:tool save-pdf --path /tmp/x.pdftool upload-file --selector ... --file-path /tmp/x.txt(참고:--path가 아닌--file-path)tool export-storage— 경로 인수 없음; JSON 출력을 파일로 파이프tool import-storage --path /tmp/x.jsontool screenshot/screenshot-element— JSON 응답에 base64 반환, 경로 인수 없음 (직접 디코딩)
- 클릭 전에 스냅샷 —
tool snapshot의 참조는 다음 스냅샷에서 만료됩니다. 항상 스냅샷 → 참조 찾기 → 클릭을 가까운 순서로 수행하세요. tools list로 도구를 탐색하세요 — 번들된 레지스트리가 사용 가능한 것의 진실 공급원입니다. 상류에서 변경될 수 있는 도구 이름을 하드 코딩하지 마세요.- **
tools describe <name>**을 사용하여 호출을 구성하기 전에 정확한 스키마(필수 인수, 열거형 선택, JSON 타입 인수)를 학습하세요. 설명에서 매개변수 이름을 추측하지 마세요 — 예를 들어safari_evaluate는 설명에 "실행할 JavaScript 코드"라고 되어 있지만--code가 아닌--script를 사용합니다.
에이전트별 지침
올바른 도구 찾기
내성 명령어를 사용하세요. CLI는 보장된 MCP 서버와의 1:1 대응을 반영합니다:
# 클릭 관련 도구 모두 찾기
cli-anything-safari tools list --filter click
# 전체 스키마 가져오기 (모든 인수의 유형, 설명,
# 필수/선택, 열거형 선택, 기본값 포함)
cli-anything-safari --json tools describe safari_click
도구 선택 전략
- **
tool snapshot**을tool screenshot보다 우선 — 참조 ID가 있는 구조화된 텍스트가 훨씬 저렴하고 클릭에 필요한 참조를 제공합니다. - **
tool click --ref**를tool click --selector보다 우선 — 참조는 단일 스냅샷 내에서 안정적이며, 선택자는 깨지기 쉬울 수 있습니다. - **
tool navigate-and-read**를navigate+read-page보다 우선 — 한 번의 왕복을 절약합니다. - **
tool click-and-read**를click+read-page보다 우선 — 한 번의 왕복을 절약합니다. - **
tool native-click**은 일반 클릭이 405/403으로 실패할 때만 사용하세요 (WAF 차단, G2, Cloudflare) — 물리적으로 커서를 움직입니다.
참조 만료
tool snapshot의 참조는 새 스냅샷을 찍을 때 만료됩니다:
- 첫 번째 스냅샷: 참조
0_1,0_2,0_3... - 두 번째 스냅샷: 참조
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→ macOS 전용AppleScript denied→ Safari → 개발에서 "Apple Events에서 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 인스턴스를 동시에 실행하면 하나가 다른 하나의 백엔드를 종료합니다. 현재 데몬 모드는 없습니다 — 지연 시간에 민감한 워크플로의 경우, 호출마다 하위 프로세스를 다시 생성하지 않도록 cli_anything.safari.utils.safari_backend.call()을 직접 가져오는 장기 실행 Python 스크립트에서 CLI를 구동하세요.
링크
보안 고려 사항
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 프로필을 사용하려면 SAFARI_PROFILE 환경 변수를 설정하세요:
export SAFARI_PROFILE="Automation"
cli-anything-safari tool navigate --url https://example.com
이렇게 하면 쿠키/로그인/기록이 사용자의 기본 브라우징과 분리됩니다.
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를 통해 재생성됩니다.