Que fait cli-anything-safari ?
Interface en ligne de commande pour l'automatisation du navigateur Safari sur macOS. Encapsule le serveur MCP Node.js safari-mcp dans un CLI Python Click.
La parité fonctionnelle est garantie. Chaque commande Click est générée automatiquement à partir du schéma d'outils de safari-mcp (intégré sous resources/tools.json). Les 84 outils sont accessibles avec les noms et types d'arguments exacts attendus par le serveur MCP.
Quand utiliser ce CLI
Chaque appel CLI lance un sous-processus, ce qui entraîne un surcoût par appel. Si votre agent parle nativement MCP (Claude Code, Cursor, Cline, etc.), l'utilisation directe de safari-mcp via MCP stdio sera plus rapide.
Utilisez ce CLI quand :
- Votre framework d'agent ne parle pas MCP (Codex CLI, GitHub Copilot CLI, scripts personnalisés, frameworks d'agents plus anciens).
- Vous avez besoin de scripter l'automatisation du navigateur depuis bash —
cli-anything-safari --json tool snapshot | jq '...'. - Vous travaillez en CI/CD et souhaitez une sortie compatible sous-processus et cron.
- Vous déboguez de manière interactive depuis le Terminal.
Installation
Prérequis
- macOS — Safari MCP est exclusif à macOS.
- Safari — déjà installé sur macOS.
- Node.js 18+ —
brew install nodeou depuis https://nodejs.org/ - Python 3.10+
- Activer les Apple Events pour Safari : Safari → Développement → Autoriser JavaScript depuis les Apple Events
Installer le CLI
cd safari/agent-harness
pip install -e .
Le premier appel de tool téléchargera le paquet npm safari-mcp (une seule fois, quelques Mo).
Structure des commandes
Le CLI dispose de 5 commandes principales :
| Commande | Objectif |
|---|---|
tool | Appeler l'un des 84 outils de safari-mcp (dynamique, piloté par le schéma) |
tools | Inspecter le registre d'outils intégré (list, describe, count) |
raw | Échappatoire — appeler un outil par son nom complet avec des arguments JSON bruts |
session | État de session en mémoire (dernière URL, onglet actuel) |
repl | REPL interactif (par défaut quand aucune sous-commande n'est donnée) |
Exemples d'utilisation
Découvrir la surface d'outils
# Nombre d'outils (vérification de cohérence — doit correspondre aux outils enregistrés de safari-mcp)
cli-anything-safari tools count
# → 84
# Lister tous les outils
cli-anything-safari tools list
cli-anything-safari tools list --filter click # filtrer par sous-chaîne
# Schéma complet pour un outil (JSON ou format lisible)
cli-anything-safari tools describe safari_scroll
cli-anything-safari --json tools describe safari_click
Appeler un outil (piloté par le schéma)
# Naviguer
cli-anything-safari tool navigate --url https://example.com
# Prendre un instantané (préféré à la capture d'écran — texte structuré avec IDs de référence)
cli-anything-safari --json tool snapshot
# Cliquer par référence (les références proviennent de l'instantané ; elles expirent au prochain instantané !)
cli-anything-safari tool click --ref 0_5
# Cliquer par sélecteur ou texte visible
cli-anything-safari tool click --selector "#submit"
cli-anything-safari tool click --text "Connexion"
# Remplir un champ
cli-anything-safari tool fill --selector "#email" --value "[email protected]"
# Faire défiler par direction/montant (PAS x/y — notez le schéma !)
cli-anything-safari tool scroll --direction down --amount 500
# Glisser un élément sur un autre
cli-anything-safari tool drag \
--source-selector ".card" \
--target-selector ".trash"
# Capture d'écran — renvoie du JPEG en base64 sur stdout. Décoder avec :
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']))"
# Enregistrer en PDF (celui-ci écrit directement sur le disque)
cli-anything-safari tool save-pdf --path /tmp/page.pdf
# Évaluer du JavaScript (note : le paramètre est --script, pas --code)
cli-anything-safari tool evaluate --script "document.title"
Naviguer et lire en un seul aller-retour
cli-anything-safari --json tool navigate-and-read --url https://example.com
Remplissage de formulaire (en bloc)
safari_fill_form prend un tableau d'objets {selector, value}.
Passez-le sous forme de chaîne JSON :
cli-anything-safari tool fill-form --fields '[
{"selector": "#email", "value": "[email protected]"},
{"selector": "#password", "value": "hunter2"}
]'
Exécutez cli-anything-safari tools describe safari_fill_form pour voir le schéma exact, y compris les nouveaux champs que safari-mcp pourrait ajouter en amont.
Surveillance réseau
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
Stockage
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 renvoie du JSON sur stdout — pas d'argument --path. Rediriger vers un fichier :
cli-anything-safari --json tool export-storage > /tmp/storage.json
Échappatoire JSON brut
Lorsque vous devez passer un objet imbriqué complexe ou piloter le CLI à partir d'un bloc JSON pré-construit :
cli-anything-safari raw safari_evaluate \
--json-args '{"code":"[...document.querySelectorAll(\"a\")].map(a => a.href)"}'
REPL interactif
cli-anything-safari
La bannière du REPL affiche le chemin absolu de ce SKILL.md afin que les agents puissent découvrir leurs capacités.
Sortie JSON
Toutes les commandes prennent en charge --json comme indicateur global :
cli-anything-safari --json tool snapshot
cli-anything-safari --json tool list-tabs
cli-anything-safari --json tools list
Gestion de l'état
Le CLI maintient une petite quantité d'état en mémoire pour l'affichage du REPL uniquement :
last_url— dernière URL vers laquelle le CLI a navigué (mise à jour après chaquetool navigate,tool navigate-and-readoutool new-tabréussi)current_tab_index— dernier index d'onglet actif connu
Il n'y a pas de session persistante, pas d'annulation/rétablissement, pas de modèle de document. Chaque appel CLI démarre avec un état frais. Safari MCP lui-même est sans état par appel : chaque commande tool lance un nouveau sous-processus npx safari-mcp, effectue l'action et se termine. C'est un choix de conception délibéré ; voir HARNESS.md et TEST.md pour le raisonnement derrière cette déviation du modèle standard d'annulation/rétablissement.
Formats de sortie
Toutes les commandes prennent en charge deux modes de sortie :
- Lisible par l'humain (par défaut) : texte clé-valeur indenté pour les résultats de type
dict, listes à puces pour les tableaux, texte brut sinon - Lisible par machine (indicateur
--json) : JSON structuré pour la consommation par les agents
# Sortie humaine
cli-anything-safari tool snapshot
# Sortie JSON pour les agents
cli-anything-safari --json tool snapshot
cli-anything-safari --json tools list
cli-anything-safari --json tools describe safari_click
Pour les agents IA
Lorsque vous utilisez ce CLI par programmation :
- Utilisez toujours l'indicateur
--jsonpour une sortie analysable. - Vérifiez les codes de retour — 0 pour succès, non nul pour les erreurs (échecs de validation d'URL, échecs d'appel MCP, arguments JSON invalides).
- Analysez stderr pour les messages d'erreur ; utilisez stdout pour les données.
- Les outils de gestion de fichiers ont des noms d'arguments de chemin incohérents — vérifiez toujours
tools describe <nom>en premier :tool save-pdf --path /tmp/x.pdftool upload-file --selector ... --file-path /tmp/x.txt(note :--file-path, pas--path)tool export-storage— pas d'argument path ; redirigez la sortie JSON vers un fichiertool import-storage --path /tmp/x.jsontool screenshot/screenshot-element— renvoient du base64 dans la réponse JSON, pas d'argument path (décodez-le vous-même)
- Instantané avant de cliquer — les références de
tool snapshotexpirent au prochain instantané. Faites toujours instantané → trouver référence → cliquer en succession rapide. - Découvrez les outils via
tools list— le registre intégré est la source de vérité pour ce qui est disponible. Ne codez pas en dur les noms d'outils qui peuvent changer en amont. - Utilisez
tools describe <nom>pour apprendre le schéma exact (arguments obligatoires, choix d'énumération, arguments typés JSON) avant de construire un appel. Ne supposez jamais les noms de paramètres à partir de la description — par exemple,safari_evaluateprend--script(pas--code) même si la description dit « code JavaScript à exécuter ».
Conseils spécifiques aux agents
Trouver le bon outil
Utilisez les commandes d'introspection. Le CLI est garanti pour refléter le serveur MCP 1:1 :
# Trouver tous les outils liés au clic
cli-anything-safari tools list --filter click
# Obtenir le schéma complet (y compris chaque argument avec type, description,
# obligatoire/facultatif, choix d'énumération, valeurs par défaut)
cli-anything-safari --json tools describe safari_click
Stratégie de sélection d'outils
tool snapshotplutôt quetool screenshot— un texte structuré avec des IDs de référence est des ordres de grandeur moins cher et contient les références nécessaires aux clics.tool click --refplutôt quetool click --selector— les références sont stables dans un même instantané, les sélecteurs peuvent être fragiles.tool navigate-and-readplutôt quenavigate+read-page— économise un aller-retour.tool click-and-readplutôt queclick+read-page— économise un aller-retour.tool native-clickuniquement lorsque le clic normal échoue avec 405/403 (blocages WAF, G2, Cloudflare) — il déplace physiquement le curseur.
Les références expirent
Les références de tool snapshot expirent lorsque vous prenez un nouvel instantané :
- Premier instantané : références
0_1,0_2,0_3... - Deuxième instantané : références
1_1,1_2,1_3...
Faites toujours instantané → cliquer en succession rapide. En cas de doute, refaites un instantané.
Sécurité de la propriété des onglets
Safari MCP suit la propriété des onglets par session. Les outils qui modifient un onglet (naviguer, cliquer, remplir) sont bloqués sur les onglets que la session n'a pas ouverts. Pour opérer sur une page spécifique, commencez toujours par tool new-tab --url ....
Gestion des erreurs
Erreurs courantes :
npx not found→ installez Node.js 18+safari-mcp package not found on npm registry→ vérifiez le réseauNot macOS→ le harnais est exclusif à macOSAppleScript denied→ activez « Autoriser JavaScript depuis les Apple Events » dans Safari → DéveloppementBlocked URL scheme: file→ la validation d'URL a rejeté l'entrée (par conception)
Validation d'URL
Le CLI valide les URLs avant de les passer à safari_navigate, safari_navigate_and_read et safari_new_tab. Schémas bloqués : file, javascript, data, vbscript, about, chrome, safari, webkit, x-apple, et autres schémas internes du navigateur. La commande raw applique également cette règle pour les outils de navigation.
Avertissement multi-session
Safari MCP impose une session active unique en tuant les processus Node.js obsolètes de plus de 10 secondes. Si vous exécutez deux instances du CLI en même temps, l'une tuera le backend de l'autre. Il n'y a actuellement pas de mode démon — pour les workflows sensibles à la latence, pilotez le CLI à partir d'un script Python long qui importe directement cli_anything.safari.utils.safari_backend.call() pour éviter de relancer le sous-processus à chaque appel.
Liens
Considérations de sécurité
Validation d'URL
Tous les outils de navigation (tool navigate, tool navigate-and-read, tool new-tab, et raw safari_navigate*) passent l'argument url à travers utils/security.py qui bloque les schémas dangereux et bloque optionnellement les réseaux privés (définissez CLI_ANYTHING_SAFARI_BLOCK_PRIVATE=1).
Isolation des onglets
Safari MCP impose la propriété des onglets par session en amont — les outils ne peuvent pas opérer sur les onglets que la session n'a pas ouverts.
Isolation de profil
Définissez la variable d'environnement SAFARI_PROFILE pour utiliser un profil Safari séparé pour l'automatisation :
export SAFARI_PROFILE="Automation"
cli-anything-safari tool navigate --url https://example.com
Cela permet de garder les cookies/connexions/historique séparés de la navigation principale de l'utilisateur.
Exécution de JavaScript
tool evaluate et tool run-script exécutent du JavaScript arbitraire dans le contexte de la page. Traitez toute entrée non fiable avec la même prudence que tout chemin d'exécution de code dynamique.
Presse-papiers
tool clipboard-read et tool clipboard-write touchent le presse-papiers système. Soyez prudent lorsque vous travaillez dans une session utilisateur active — écraser le presse-papiers en pleine tâche est perturbant.
Régénération du registre d'outils
Si vous mettez à niveau safari-mcp, régénérez le schéma intégré :
python scripts/extract_tools.py \
"$(npm root -g)/safari-mcp/index.js" \
cli_anything/safari/resources/tools.json
Le test de parité (test_parity.py) épingle le nombre d'outils attendu ; mettez-le à jour lorsque la liste des outils en amont change.
Plus d'informations
- Documentation complète :
cli_anything/safari/README.mddans le paquet - Couverture de test :
cli_anything/safari/tests/TEST.mddans le paquet - Analyse d'architecture :
safari/agent-harness/SAFARI.md - Méthodologie :
cli-anything-plugin/HARNESS.md - Modèle MCP backend :
cli-anything-plugin/guides/mcp-backend.md
Version
1.0.0 — cible safari-mcp 2.7.8 (84 outils). Le registre d'outils intégré est régénéré via scripts/extract_tools.py lorsque safari-mcp est mis à niveau.