# Screen MCP — screenshot + input injection for GUI agents. # # Auto-activated when `hyperhive.gui.enable = true`. Wires the # `hive-screen-mcp` stdio bridge as `extraMcpServers.screen` so claude # gets five tools: `screenshot`, `type_text`, `key_press`, `mouse_move`, # and `mouse_click`. # # `screenshot` and `type_text` work out of the box (grim + wtype, both # pure Wayland clients). `key_press`, `mouse_move`, and `mouse_click` # require the ydotoold daemon, which injects events via `/dev/uinput` # at the kernel level — enable it by setting # `hyperhive.gui.screenInput = true`. { pkgs, lib, config, ... }: { options.hyperhive.gui.screenInput = lib.mkOption { type = lib.types.bool; default = false; description = '' Enable mouse and keyboard injection via ydotool + the ydotoold daemon. Requires `/dev/uinput` device access inside the container (the host must bind it in via `extraSystemdProperties` or `systemd.nspawn..filesConfig.Bind`). When false, `screenshot` and `type_text` still work; `key_press`, `mouse_move`, and `mouse_click` return an error from ydotool until ydotoold is running and `/dev/uinput` is accessible. ''; }; config = lib.mkIf config.hyperhive.gui.enable { # Register the screen MCP bridge so claude gets the screen tools. hyperhive.extraMcpServers.screen = { command = "${config.hyperhive.packages.hive-screen-mcp}/bin/hive-screen-mcp"; args = [ ]; }; # grim: Wayland screenshot; wtype: text/key input (no daemon). # ydotool: mouse + key injection via uinput (needs screenInput). environment.systemPackages = [ pkgs.grim pkgs.wtype ] ++ lib.optional config.hyperhive.gui.screenInput pkgs.ydotool; # ydotoold — uinput event injection daemon. The socket lands at # /tmp/.ydotool_socket by default; ydotool picks it up # automatically. Only started when screenInput is enabled. systemd.services.ydotoold = lib.mkIf config.hyperhive.gui.screenInput { description = "ydotool input injection daemon"; wantedBy = [ "multi-user.target" ]; after = [ "local-fs.target" ]; serviceConfig = { ExecStart = "${pkgs.ydotool}/bin/ydotoold"; Restart = "on-failure"; RestartSec = "2s"; SyslogIdentifier = "ydotoold"; }; }; }; }