Mains : agir sur l'écran
Les Mains produisent des entrées synthétiques : pointeur, clavier, défilement, fenêtres. Chaque action passe par la même chaîne : résolution du point, sonde de la cible, garde, porte du plafond, journal d'audit, puis exécution. Une action au-dessus du plafond est refusée.
Niveaux
| Outil | Niveau | Nom interne | Cible observée requise |
|---|---|---|---|
main_navigate | L1 | NONDESTRUCTIVE | non |
main_hover | L1 | NONDESTRUCTIVE | non |
main_activate | L1 | NONDESTRUCTIVE | non |
main_window_minimize | L1 | NONDESTRUCTIVE | non |
main_window_hide | L1 | NONDESTRUCTIVE | non |
main_window_show | L1 | NONDESTRUCTIVE | non |
main_click | L2 | INPUT | oui |
main_type | L2 | INPUT | non |
main_drag | L2 | INPUT | oui |
main_key | L2 | INPUT | non |
main_press | L3 | VALIDATION | oui |
main_mouse_down | L4 | AUTONOMOUS | oui |
main_mouse_up | L4 | AUTONOMOUS | oui |
main_key_down | L4 | AUTONOMOUS | non |
main_key_up | L4 | AUTONOMOUS | non |
Le niveau est nominal : la cible peut le relever selon la réversibilité de l'action, jamais l'abaisser. « Cible observée requise » signifie que l'action s'engage sur un élément d'écran qui doit être vérifié avant d'agir.
Forme des réponses
Tous les outils d'action renvoient un objet JSON de l'une de ces trois formes.
| Forme | Sens |
|---|---|
{"status": "refused", "reason": "..."} | L'action est refusée (plafond, garde, confirmation humaine non obtenue) |
{"status": "done", "result": ..., "focus": ...} | L'action a été exécutée ; focus n'est présent que si une mise au premier plan a eu lieu |
{"status": "error", "reason": "..."} | L'organe a échoué à exécuter l'action |
Les erreurs de préparation deviennent une erreur MCP structurée {"error": "<code>", "message": "..."} et ne plantent jamais le serveur :
| Code | Signification |
|---|---|
invalid_arguments | Argument invalide, par exemple space="image" sans display |
index_out_of_range | L'indice display n'existe pas |
capture_failed | L'énumération des écrans a échoué |
motor_unavailable | Les Mains ne sont pas disponibles sur cet hôte |
Sans Accessibilité, des échecs silencieux
Sans l'autorisation Accessibilité, main_type, main_key, main_hover et main_navigate renvoient status: "done" sans aucun effet, et main_click, main_press et main_drag attendent 30 secondes une boîte de confirmation. Appelez daimon_doctor avant de conclure qu'un outil est en panne.
Paramètres communs
Intention et réversibilité
Chaque outil d'action exige intent : une phrase qui déclare ce que vous voulez faire, consignée au journal d'audit. Les outils qui s'engagent portent aussi reversible : déclarez honnêtement si l'action peut être annulée.
Positionnement
Les outils positionnels (main_click, main_press, main_hover, main_navigate, main_drag, main_mouse_down, main_mouse_up) partagent ce bloc :
| Paramètre | Type | Défaut | Rôle |
|---|---|---|---|
space | chaîne | "global" | "global" : points du bureau global, l'unité que renvoie vue_find. "image" : pixels d'un vue_snapshot, résolus par Daimon |
display | entier | aucun | Indice d'écran ; obligatoire quand space="image" |
max_width | entier | 720 | Avec space="image" : le même plafond que le snapshot. Ignoré en global |
region | objet {x, y, width, height} | aucune | Avec space="image" : la même région que le snapshot, en points locaux à l'écran. Ignoré en global |
Fenêtre cible
main_click, main_press et main_drag portent aussi ce bloc. Les chaînes vides et 0 signifient « non précisé ».
| Paramètre | Type | Défaut | Rôle |
|---|---|---|---|
window_bundle | chaîne | "" | Identifiant de bundle de l'application cible |
window_title | chaîne | "" | Titre de la fenêtre cible |
window_pid | entier | 0 | Identifiant de processus cible |
ensure_focus | booléen | true | Active d'abord une fenêtre cible non frontale |
Ce que la description de l'outil dit
La description MCP de main_click écrit « window={bundle|title|pid} » ; les paramètres réels sont les trois champs à plat window_bundle, window_title et window_pid ci-dessus.
Modificateurs
Sous macOS : cmd, shift, opt, ctrl. Sous Windows : ctrl, shift, alt, win ; cmd et fn y sont refusés.
main_click
Clique sur un élément ou une coordonnée. Niveau L2. Refusé au-dessus du plafond.
| Paramètre | Type | Défaut | Obligatoire | Rôle |
|---|---|---|---|---|
x, y | entier | aucun | oui | Point à cliquer |
intent | chaîne | aucun | oui | Intention déclarée |
reversible | booléen | true | non | L'action est-elle annulable |
button | chaîne | "left" | non | left, right ou middle |
count | entier | 1 | non | 1 ou 2 (double-clic) |
modifiers | liste de chaînes | [] | non | Modificateurs tenus pendant le clic |
role | chaîne | "" | non | Rôle de l'élément (issu de Touché) |
label | chaîne | "" | non | Libellé de l'élément (issu de Touché) |
Plus les blocs Positionnement et Fenêtre cible.
Exemple d'appel
{
"x": 1210, "y": 84, "intent": "Ouvrir le menu Fichier",
"role": "AXMenuBarItem", "label": "Fichier", "reversible": true
}Pièges : fournissez role et label (relevés avec touche_probe) pour que Daimon puisse vérifier la réversibilité de la cible.
main_type
Saisit du texte dans le champ qui a le focus. Niveau L2.
| Paramètre | Type | Défaut | Obligatoire | Rôle |
|---|---|---|---|---|
text | chaîne | aucun | oui | Texte à saisir |
intent | chaîne | aucun | oui | Intention déclarée |
reversible | booléen | true | non | L'action est-elle annulable |
role | chaîne | "" | non | Rôle du champ visé |
label | chaîne | "" | non | Libellé du champ visé |
Exemple d'appel : { "text": "bonjour", "intent": "Remplir le champ nom" }
Pièges
- Le texte saisi n'est jamais écrit dans le journal d'audit.
main_typene choisit pas le champ : cliquez d'abord dessus.- Pour une touche ou un raccourci, utilisez
main_key, pasmain_type.
main_key
Envoie une touche discrète ou un raccourci (Return, Tab, Échap, flèches, touches de fonction, ou par exemple cmd+shift+r). Niveau L2.
| Paramètre | Type | Défaut | Obligatoire | Rôle |
|---|---|---|---|---|
key | chaîne | aucun | oui | Touche ou combinaison |
intent | chaîne | aucun | oui | Intention déclarée |
modifiers | liste de chaînes | [] | non | Modificateurs |
count | entier | 1 | non | Nombre de répétitions |
reversible | booléen | true | non | L'action est-elle annulable |
Exemple d'appel
{ "key": "r", "modifiers": ["cmd", "shift"], "intent": "Recharger la page sans cache" }Pièges: un caractère seul est tapé avec la touche que la disposition de clavier active utilise pour lui. Les combinaisons dangereuses exigent une confirmation.
main_press
Active un bouton engageant en (x, y) par l'API d'accessibilité (AXPress). Niveau L3. Les cibles qui ne sont pas des retours arrière exigent une confirmation humaine.
| Paramètre | Type | Défaut | Obligatoire | Rôle |
|---|---|---|---|---|
x, y | entier | aucun | oui | Point du bouton |
intent | chaîne | aucun | oui | Intention déclarée |
reversible | booléen | false | non | L'action est-elle annulable |
role | chaîne | "" | non | Rôle de l'élément |
label | chaîne | "" | non | Libellé de l'élément |
Plus les blocs Positionnement et Fenêtre cible.
Exemple d'appel
{ "x": 900, "y": 640, "intent": "Valider l'envoi du formulaire", "role": "AXButton", "label": "Envoyer" }Pièges : contrairement aux autres outils, reversible vaut false par défaut.
main_drag
Glisse de (from_x, from_y) à (to_x, to_y). Niveau L2. La destination du dépôt est classée pour sa réversibilité : déposer sur la Corbeille, par exemple, déclenche la porte.
| Paramètre | Type | Défaut | Obligatoire | Rôle |
|---|---|---|---|---|
from_x, from_y | entier | aucun | oui | Point de départ |
to_x, to_y | entier | aucun | oui | Point d'arrivée |
intent | chaîne | aucun | oui | Intention déclarée |
button | chaîne | "left" | non | Bouton de la souris |
reversible | booléen | true | non | L'action est-elle annulable |
Plus les blocs Positionnement et Fenêtre cible ; les deux points passent par la résolution.
Exemple d'appel
{ "from_x": 300, "from_y": 400, "to_x": 700, "to_y": 400, "intent": "Déplacer la vignette" }main_navigate
Fait défiler d'une valeur scroll_y. Niveau L1. La réversibilité est forcée à vrai.
| Paramètre | Type | Défaut | Obligatoire | Rôle |
|---|---|---|---|---|
intent | chaîne | aucun | oui | Intention déclarée |
scroll_y | entier | 0 | non | Amplitude ; positif = vers le haut |
x, y | entier | aucun | non | Point sur lequel le défilement atterrit |
Plus le bloc Positionnement (accepté pour x/y).
Exemple d'appel: { "intent": "Descendre dans la liste", "scroll_y": -300, "x": 700, "y": 500 }
Pièges
- L'amplitude dépend de la plateforme : pixels sous macOS ; sous Windows, 120 correspond à un cran de molette.
- Donnez un point
(x, y)pour que le défilement tombe sur la vue voulue ; sans point, il s'applique où se trouve le pointeur.
main_hover
Déplace le pointeur en (x, y) sans cliquer (révéler une infobulle ou un menu). Niveau L1. La réversibilité est forcée à vrai.
| Paramètre | Type | Défaut | Obligatoire | Rôle |
|---|---|---|---|---|
x, y | entier | aucun | oui | Point visé |
intent | chaîne | aucun | oui | Intention déclarée |
Plus le bloc Positionnement.
main_activate
Amène une application ou une fenêtre au premier plan. Niveau L1.
| Paramètre | Type | Défaut | Obligatoire | Rôle |
|---|---|---|---|---|
intent | chaîne | aucun | oui | Intention déclarée |
bundle | chaîne | "" | non | Identifiant de bundle |
title | chaîne | "" | non | Titre de la fenêtre |
pid | entier | 0 | non | Identifiant de processus |
Exemple d'appel: { "intent": "Passer sur le Finder", "bundle": "com.apple.finder" }
main_window_minimize
Réduit la fenêtre de premier plan de l'application cible, par l'accessibilité (insensible à un raccourci réaffecté, contrairement à Cmd+M). Niveau L1. Réversible : main_window_show restaure. Mêmes paramètres que main_activate.
main_window_hide
Masque l'application cible (insensible à un raccourci réaffecté, contrairement à Cmd+H). Niveau L1. Réversible : main_window_show restaure. Mêmes paramètres que main_activate.
main_window_show
Démasque, désréduit et remonte l'application cible : le retour arrière de main_window_minimize et main_window_hide. Niveau L1. Mêmes paramètres que main_activate.
main_mouse_down
Primitive bas niveau : presse et maintient le bouton gauche de la souris en (x, y). Niveau L4 uniquement.
| Paramètre | Type | Défaut | Obligatoire | Rôle |
|---|---|---|---|---|
x, y | entier | aucun | oui | Point |
intent | chaîne | aucun | oui | Intention déclarée |
Plus le bloc Positionnement.
Pièges : le bouton est relâché automatiquement après 10 secondes si main_mouse_up ne suit pas, même sans autre appel.
main_mouse_up
Relâche le bouton gauche maintenu, en (x, y). Niveau L4. Mêmes paramètres que main_mouse_down.
main_key_down
Primitive bas niveau : presse et maintient une touche. Niveau L4 uniquement.
| Paramètre | Type | Défaut | Obligatoire | Rôle |
|---|---|---|---|---|
key | chaîne | aucun | oui | Touche |
intent | chaîne | aucun | oui | Intention déclarée |
modifiers | liste de chaînes | [] | non | Modificateurs |
Pièges : la touche est relâchée automatiquement après 10 secondes si main_key_up ne suit pas, même sans autre appel.
main_key_up
Relâche une touche maintenue. Niveau L4.
| Paramètre | Type | Défaut | Obligatoire | Rôle |
|---|---|---|---|---|
key | chaîne | aucun | oui | Touche |
intent | chaîne | aucun | oui | Intention déclarée |