Skip to content

Mains (Hands): acting on the screen ​

Mains produces synthetic input: pointer, keyboard, scrolling, windows. Every action goes through the same chain: point resolution, target probe, guard, ceiling gate, audit log, then execution. An action above the ceiling is refused.

Levels ​

ToolLevelInternal nameObserved target required
main_navigateL1NONDESTRUCTIVEno
main_hoverL1NONDESTRUCTIVEno
main_activateL1NONDESTRUCTIVEno
main_window_minimizeL1NONDESTRUCTIVEno
main_window_hideL1NONDESTRUCTIVEno
main_window_showL1NONDESTRUCTIVEno
main_clickL2INPUTyes
main_typeL2INPUTno
main_dragL2INPUTyes
main_keyL2INPUTno
main_pressL3VALIDATIONyes
main_mouse_downL4AUTONOMOUSyes
main_mouse_upL4AUTONOMOUSyes
main_key_downL4AUTONOMOUSno
main_key_upL4AUTONOMOUSno

The level is nominal: the target can raise it depending on the reversibility of the action, but never lower it. "Observed target required" means that the action commits on a screen element that must be checked before acting.

Response shape ​

All action tools return a JSON object of one of these three shapes.

ShapeMeaning
{"status": "refused", "reason": "..."}The action is refused (ceiling, guard, human confirmation not obtained)
{"status": "done", "result": ..., "focus": ...}The action was executed; focus is present only if a bring-to-front took place
{"status": "error", "reason": "..."}The organ failed to execute the action

Preparation errors become a structured MCP error {"error": "<code>", "message": "..."} and never crash the server:

CodeMeaning
invalid_argumentsInvalid argument, for example space="image" without display
index_out_of_rangeThe display index does not exist
capture_failedEnumerating the displays failed
motor_unavailableMains is not available on this host

Without Accessibility, silent failures

Without the Accessibility permission, main_type, main_key, main_hover and main_navigate return status: "done" with no effect at all, and main_click, main_press and main_drag wait 30 seconds for a confirmation dialog. Call daimon_doctor before concluding that a tool is broken.

Common parameters ​

Intent and reversibility ​

Every action tool requires intent: a sentence declaring what you want to do, recorded in the audit log. The tools that commit also carry reversible: declare honestly whether the action can be undone.

Positioning ​

The positional tools (main_click, main_press, main_hover, main_navigate, main_drag, main_mouse_down, main_mouse_up) share this block:

ParameterTypeDefaultRole
spacestring"global""global": points of the global desktop, the unit returned by vue_find. "image": pixels of a vue_snapshot, resolved by Daimon
displayintegernoneDisplay index; required when space="image"
max_widthinteger720With space="image": the same cap as the snapshot. Ignored in global
regionobject {x, y, width, height}noneWith space="image": the same region as the snapshot, in points local to the display. Ignored in global

Target window ​

main_click, main_press and main_drag also carry this block. Empty strings and 0 mean "not specified".

ParameterTypeDefaultRole
window_bundlestring""Bundle identifier of the target application
window_titlestring""Title of the target window
window_pidinteger0Target process identifier
ensure_focusbooleantrueFirst activates a target window that is not in front

What the tool description says

The MCP description of main_click reads "window={bundle|title|pid}"; the actual parameters are the three flat fields window_bundle, window_title and window_pid above.

Modifiers ​

On macOS: cmd, shift, opt, ctrl. On Windows: ctrl, shift, alt, win; cmd and fn are refused there.

main_click ​

Clicks on an element or a coordinate. Level L2. Refused above the ceiling.

ParameterTypeDefaultRequiredRole
x, yintegernoneyesPoint to click
intentstringnoneyesDeclared intent
reversiblebooleantruenoWhether the action can be undone
buttonstring"left"noleft, right or middle
countinteger1no1 or 2 (double-click)
modifierslist of strings[]noModifiers held during the click
rolestring""noRole of the element (from Touché (Touch))
labelstring""noLabel of the element (from Touché)

Plus the Positioning and Target window blocks.

Example call

json
{
  "x": 1210, "y": 84, "intent": "Ouvrir le menu Fichier",
  "role": "AXMenuBarItem", "label": "Fichier", "reversible": true
}

Pitfalls: provide role and label (read with touche_probe) so that Daimon can check the reversibility of the target.

main_type ​

Types text into the field that has focus. Level L2.

ParameterTypeDefaultRequiredRole
textstringnoneyesText to type
intentstringnoneyesDeclared intent
reversiblebooleantruenoWhether the action can be undone
rolestring""noRole of the targeted field
labelstring""noLabel of the targeted field

Example call: { "text": "bonjour", "intent": "Remplir le champ nom" }

Pitfalls

  • The typed text is never written to the audit log.
  • main_type does not choose the field: click on it first.
  • For a key or a shortcut, use main_key, not main_type.

main_key ​

Sends a discrete key or a shortcut (Return, Tab, Escape, arrows, function keys, or for example cmd+shift+r). Level L2.

ParameterTypeDefaultRequiredRole
keystringnoneyesKey or combination
intentstringnoneyesDeclared intent
modifierslist of strings[]noModifiers
countinteger1noNumber of repetitions
reversiblebooleantruenoWhether the action can be undone

Example call

json
{ "key": "r", "modifiers": ["cmd", "shift"], "intent": "Recharger la page sans cache" }

Pitfalls: a single character is typed with the key that the active keyboard layout uses for it. Dangerous combinations require confirmation.

main_press ​

Activates a committing button at (x, y) through the accessibility API (AXPress). Level L3. Targets that are not back-navigation require human confirmation.

ParameterTypeDefaultRequiredRole
x, yintegernoneyesPoint of the button
intentstringnoneyesDeclared intent
reversiblebooleanfalsenoWhether the action can be undone
rolestring""noRole of the element
labelstring""noLabel of the element

Plus the Positioning and Target window blocks.

Example call

json
{ "x": 900, "y": 640, "intent": "Valider l'envoi du formulaire", "role": "AXButton", "label": "Envoyer" }

Pitfalls: unlike the other tools, reversible defaults to false.

main_drag ​

Drags from (from_x, from_y) to (to_x, to_y). Level L2. The drop destination is classified for its reversibility: dropping onto the Trash, for example, triggers the gate.

ParameterTypeDefaultRequiredRole
from_x, from_yintegernoneyesStart point
to_x, to_yintegernoneyesEnd point
intentstringnoneyesDeclared intent
buttonstring"left"noMouse button
reversiblebooleantruenoWhether the action can be undone

Plus the Positioning and Target window blocks; both points go through resolution.

Example call

json
{ "from_x": 300, "from_y": 400, "to_x": 700, "to_y": 400, "intent": "Déplacer la vignette" }

Scrolls by a scroll_y value. Level L1. Reversibility is forced to true.

ParameterTypeDefaultRequiredRole
intentstringnoneyesDeclared intent
scroll_yinteger0noAmount; positive = upward
x, yintegernonenoPoint where the scroll lands

Plus the Positioning block (accepted for x/y).

Example call: { "intent": "Descendre dans la liste", "scroll_y": -300, "x": 700, "y": 500 }

Pitfalls

  • The amount depends on the platform: pixels on macOS; on Windows, 120 corresponds to one wheel notch.
  • Give a point (x, y) so that the scroll lands on the intended view; without a point, it applies wherever the pointer is.

main_hover ​

Moves the pointer to (x, y) without clicking (to reveal a tooltip or a menu). Level L1. Reversibility is forced to true.

ParameterTypeDefaultRequiredRole
x, yintegernoneyesTargeted point
intentstringnoneyesDeclared intent

Plus the Positioning block.

main_activate ​

Brings an application or a window to the foreground. Level L1.

ParameterTypeDefaultRequiredRole
intentstringnoneyesDeclared intent
bundlestring""noBundle identifier
titlestring""noWindow title
pidinteger0noProcess identifier

Example call: { "intent": "Passer sur le Finder", "bundle": "com.apple.finder" }

main_window_minimize ​

Minimizes the foreground window of the target application, through accessibility (unaffected by a remapped shortcut, unlike Cmd+M). Level L1. Reversible: main_window_show restores it. Same parameters as main_activate.

main_window_hide ​

Hides the target application (unaffected by a remapped shortcut, unlike Cmd+H). Level L1. Reversible: main_window_show restores it. Same parameters as main_activate.

main_window_show ​

Unhides, unminimizes and raises the target application: the undo of main_window_minimize and main_window_hide. Level L1. Same parameters as main_activate.

main_mouse_down ​

Low-level primitive: presses and holds the left mouse button at (x, y). Level L4 only.

ParameterTypeDefaultRequiredRole
x, yintegernoneyesPoint
intentstringnoneyesDeclared intent

Plus the Positioning block.

Pitfalls: the button is released automatically after 10 seconds if main_mouse_up does not follow, even with no other call.

main_mouse_up ​

Releases the held left button, at (x, y). Level L4. Same parameters as main_mouse_down.

main_key_down ​

Low-level primitive: presses and holds a key. Level L4 only.

ParameterTypeDefaultRequiredRole
keystringnoneyesKey
intentstringnoneyesDeclared intent
modifierslist of strings[]noModifiers

Pitfalls: the key is released automatically after 10 seconds if main_key_up does not follow, even with no other call.

main_key_up ​

Releases a held key. Level L4.

ParameterTypeDefaultRequiredRole
keystringnoneyesKey
intentstringnoneyesDeclared intent