Repository navigation
Breaking: the MCP tool surface is redesigned for AI callers. Tool names, parameters and result formats change without aliases, and the guest protocol moves to a new generation: the host refuses older agents with agent_outdated until vm_update_agent is run.
Migration from 0.2.0
-
Host. Install the new release over the old one with
hyperhand.exe install(one UAC prompt). -
Guest agents. Run
vm_update_agenton every VM. Until then every agent call to an old agent is refused withagent_outdated(fieldsagent_protocol,host_protocol,nextcall vm_update_agent);vm_status,vm_doctorandvm_update_agentkeep working on it, andvm_update_agentreplaces a 0.2.0 agent in place. If the agent does not answer, usevm_install_agent. A VM restored from an older checkpoint brings back the old agent and needsvm_update_agentagain. -
Every call names its VM. Pass
vm(a name fromvm_list) on every tool exceptvm_list; there is no default VM.vm_end_turnmay omitvmonly to end the whole task. -
Results and errors are JSON. Parse the single JSON text item of each result (an observation's PNG image comes before it) instead of
ok,handle: N,name<TAB>stateorexit_code:text. An error is anisErrorresult whose text is{"error", "reason", "next", ...}; follownext. -
Replace removed tools and parameters:
0.2.0 Now vm_screenshot(source,region, coordinate metadata)vm_observe(handleorpid,max_size); actions take image pixels with itsobservation_idvm_controlsvm_observewithcontrols: true(indexed text tree), orvm_find_controlsfor one controlvm_focus_windownothing: actions activate their target ( activate, defaulttrue)window,title,exacton any tool, title-selected waitshandle(fromvm_windows,vm_find_controls,vm_observe,vm_launchor an action result) orpid;vm_waitwindow and control kinds withhandle/pid,automation_id,control_nameorobservation_idandindexvm_typemode(clipboard paste)vm_typealways types key events;vm_clipboard_setthenvm_key ctrl+vto pastevm_clickdoublecount: 2vm_scrolldeltadelta_y(anddelta_x)vm_dragx1,y1,x2,y2from: {x, y},to: {x, y}vm_checkpointnamelabelandkeep; select checkpoints by the returnedidGUI programs started with vm_execvm_launch(vm_execwaits for the command to finish) -
Scripts.
scripts/restart-tray.ps1andscripts/dev-install.ps1are gone: development installs usego run ./cmd/hyperhand dev-install. Scripts without an MCP client can useclient/hyperhand_client.py; pass onetask_idper piece of work so that ownership and observations carry over between calls.
Removed
scripts/restart-tray.ps1, which installed a build with a UAC prompt. Development installs usego run ./cmd/hyperhand dev-install(no UAC, through the preauthorizedHyperHand Dev Installtask registered once withscripts/dev-install-setup.ps1).vm_screenshot: replaced byvm_observe. There is nosource,regionor coordinate metadata to apply; actions take image pixels of an observation.vm_controls: replaced byvm_observewithcontrols: true, which returns the tree as indexed text instead of JSON nodes.vm_focus_window: actions activate their target window themselves (activate, defaulttrue).- Legacy title-selected window waits; the new UI conditions use HWND/PID or observation/control identity instead.
- Title selectors: the
window,titleandexactparameters of every tool. Windows are selected byhandle(fromvm_windows,vm_find_controls,vm_observe,vm_launchor an action result) orpidonly. vm_typemode: the clipboard paste path is gone; text is injected as Unicode key events, with the Hyper-V keyboard for ASCII text when the agent is not available.vm_clickdouble(usecount),vm_scrolldelta(usedelta_y),vm_dragx1/y1/x2/y2(usefrom/to),vm_checkpointname(uselabelandkeep).- Free-text results:
ok,handle: Nlines,name<TAB>statelists andexit_code:blocks. - Guest op
screenshot: all screenshots are taken on the host.
Changed
vm_shutdownthat times out because a program blocks shutdown now says what the guest may look like: Windows may already be signing the user out, with the agent gone and the desktop ignoring input. The error carriesvmandstateand anextnamingvm_observe, raw input, andvm_turn_offorvm_restoreas the only way out of a stuck guest, instead of the genericfailedadvice. The tool description advises saving or closing such programs first, or usingvm_save.vm_execwithadmin: truewhosetimeout_mspasses before elevation completes (an unanswered UAC prompt) now fails withelevation_timeout(the command did not run;nextsays how to elevate without a prompt or answer it from the host) instead of returningtimed_out: truewith empty output, which looked like a command that ran too long. The guest protocol changes: runvm_update_agenton every VM.- Documentation:
README.mdis rewritten for human readers (what HyperHand is for, quick start with example requests, limitations, privacy); the tool list moves to the user guide, and building, testing, development installs and releasing move to the newdocs/building.md. - New icon for
hyperhand.exe, its tray icon, the settings window andhyperhand-agent.exe: a white monitor outline on a blue rounded square, replacing the gripper icon. - Success results that need a follow-up call carry
next: avm_pushmirror plan (status: "planned") says that nothing was written yet and names the apply call (phase: "apply", itsplan_id, the same paths,forceandtask_id, beforeexpires_at); a backgroundvm_execnames thevm_jobcall with itsjob_id. Callers had stopped after the plan, believing the mirror done. - Breaking:
vmis required on every tool exceptvm_list; there is no default VM any more ("the only running VM, or the only VM if none is running"). With several VMs on a host, a call meant for a VM that was off silently reached another one, includingvm_restore,vm_shutdown,vm_turn_offandvm_exec. A call withoutvmis refused before anything runs withinvalid_argument, reasonvm is required: there is no default VM,nextlisting the VM names and fieldvms; the input schemas markvmas required.vm_end_turnmay still omitvmto end the whole task (only the task's own waits, temporary checkpoints and ownership), butall_temp: truerequiresvm(reasonvm is required with all_temp: ...) instead of deleting temporary checkpoints on every VM.- Migration: pass
vm(a name fromvm_list) on every call; passvmwith everyvm_end_turnthat usesall_temp: true; Stop hooks that callvm_end_turnwithoutvm(such as the examples indocs/hooks/) keep working.
- Migration: pass
- Observed controls can be re-located using their previous screen bounds as a read-only hint. The guest verifies the exact runtime ID and control-view ancestry to the requested window before accepting a hit; covered, moved or mismatched hints fall back to the existing traversal. Actions and wait conditions still read current values and state, and scoped reads retain password-subtree protection.
- Semantic actions return readable post-action
stateand verify Toggle, Expand, Collapse, Select and ScrollIntoView outcomes. An immediate read is followed by up to 250 ms of read-only polling when needed; actions are never replayed. Unknown outcomes, password values and unobservable Invoke effects stayverified: null. - Every result is one JSON object in a single text item (
vm_observeand actions with an after-action screenshot put a PNG image item before it). Every error is anisErrorresult whose text is{"error": <code>, "reason", "next", "run_id", ...fields};nextnames the call that makes progress. Codes:invalid_argument,stale_observation,stale_element,session_unusable,activate_failed,target_disabled,covered,integrity_mismatch,target_not_responding,unsupported_pattern,partial_input,agent_required,agent_outdated,ambiguous_target,no_window,no_checkpoint,failed. - Tools carry MCP annotations: read-only (
vm_list,vm_status,vm_checkpoints,vm_pull,vm_clipboard_get,vm_wait,vm_windows,vm_find_controls,vm_observe,vm_doctor), destructive (vm_shutdown,vm_turn_off,vm_restore,vm_checkpoint_delete,vm_push,vm_update_agent,vm_end_turn) and idempotent hints;openWorldHintis false. vm_windowsreturns{windows, foreground, focused_control, session}; each window gainsgroup_root(the root of its owner chain within the process, at most 8 links) andintegrity(low,medium,high,system);focused_controlis the UI Automation focused element withwindow,name,control_type,automation_id,class_name,runtime_id,rect;sessionis the agent's session state.- Actions (
vm_click,vm_drag,vm_scroll,vm_set_value,vm_invoke,vm_type,vm_key) takeobservation_idwith image pixels or a controlindex; the host maps pixels to the screen, re-finds controls by runtime ID and refuses an observation whose window moved, resized, minimized or closed (stale_observation). The check chain before input is: session, freshness, target, activation, enabled, hit (covered), integrity, each with its code andnext. Actions default toactivate: trueand toobserve_after: screenshot(noneforvm_typeandvm_key;controls,both;settle_msdefault 300, max 5000), returning the receivingwindowand anafterobservation with a newobservation_id. Raw input (pointer actions withoutobservation_id,vm_keywithouthandle/pid) goes to the console with no checks at all, so the sign-in screen, the lock screen and UAC prompts stay reachable; anindexof a whole-screen observation's tree targets the foreground window the tree belongs to with the full chain. - Window groups: a target's own windows (top-level windows of its process that it owns, directly or through other owned windows, up to 8 links) count as the target: an AutoCAD main-window handle reaches its untitled command line and command history popup, and the result names the window reached. Refusals name the window to act on next (
act_on,foreground): a disabled window's own foreground dialog, another process's foreground window that probably blocks it, or the covering window described by class and process even whenvm_windowsdoes not list it (shell overlays). vm_clickgainscount(1 to 3) andmodifiers(ctrl,shift,alt, held on the Hyper-V keyboard around the click);vm_dragtakesfrom/toandmodifiers;vm_scrolltakesdelta_yanddelta_x(horizontal wheel through the agent).vm_typehas one mode: Unicode key events through the agent (type_keys); without a target, the Hyper-V keyboard for ASCII text when the agent is absent or its session is locked or on the secure desktop (agent_requiredorsession_unusablefor other text); it acceptshandle/pidorobservation_idwithindex(clicks the control first and reads it back afterwards:verifiedsays whethervaluecontains the typed text), returns{applied_chars, total_chars, window, after}and reports a stop after some characters aspartial_inputwith the same counts (failedwithapplied_chars: 0when nothing was typed).vm_keyaccepts the numeric keypad (num0-num9,numenter,numdot,numplus,numminus,nummul,numdiv),numlock,f13-f20,printscreen,scrolllock,pause,apps,capslockand X11-style aliases (Return,Escape,Control_L,Shift_L,Alt_L,Super_L,KP_0-KP_9,KP_Enter,KP_Decimal,KP_Add,KP_Subtract,KP_Multiply,KP_Divide,period,comma,slash,minus,equal,Prior,Next); a sequence stopped after at least one combination ispartial_inputwithappliedandtotal(a failure before the first keeps its own code); the result is{ok, combinations, window, after}.vm_checkpointtakeslabel(1 to 64 characters without\ / : * ? " < > |or line breaks; defaulthhmmss) andkeepand names the checkpoint<run_id>-temp-<label>or<run_id>-keep-<label>, returning{id, name, type, kind, state, parent, created_at}; a VM whose checkpoint setting isDisabledis refused withinvalid_argument.vm_checkpointsreturns the tree:{vm, checkpoint_type, current_parent, checkpoints: [{id, name, parent, created_at, type, run_id, label, kind, state, holds_memory, current, children}]}in creation order;parentis the parent's id (nullfor a root),kindis Hyper-V's snapshot type lower-cased,statethe saved power state,holds_memorywhether it saved memory,currentmarks the checkpoint the VM's current state branches from,created_atis RFC 3339 with the host's offset.- Checkpoints are selected by
id(fromvm_checkpoints; the stable selector, since names may repeat) or bynamewhen exactly one checkpoint has it; several:ambiguous_targetwithids; none:no_checkpoint. vm_restoretakesidornameandsave_current(first saves the current state as<run_id>-temp-before-restore), returning{vm, restored: {id, name, type}, state, saved_current, next}.vm_end_turntakesall_temp(delete thetempcheckpoints of every run on the VM named byvm, which it requires) and returnsskipped: [{id, name, reason}]for the checkpoints it did not delete (no longertemp, or a Hyper-V failure withall_temp), besidescancelled_waits,deleted_checkpointsanderrors; registered checkpoints are checked against the VM's current list before deletion.vm_listreturns{vms: [{name, id, state}], run_id};vm_status,vm_start,vm_unlock,vm_shutdown,vm_turn_off,vm_restore,vm_exec,vm_push,vm_pull,vm_clipboard_get,vm_clipboard_set,vm_wait({satisfied, elapsed_ms}),vm_install_agentandvm_update_agentreturn JSON objects;vm_shutdownon a VM that is already off returns{vm, state: "off"}.vm_execruns commands to completion only; its description points GUI programs tovm_launch.- Every new agent connection is pinged first: an agent whose protocol is older than the host's is refused with
agent_outdatedfor every op exceptpingandupdate_agent, sovm_status,vm_doctorandvm_update_agentstill work on it;vm_start,vm_install_agentandvm_update_agentalso check the agent that answers their readiness ping; an agent'sunknown opanswer is reported the same way. - Guest protocol:
pingreportsprotocol;list_windowstakes optional{focused}(onlyvm_windowsandvm_observeask for the focused control, which costs a UI Automation helper process) and returnsforeground,focused,session,agent_integrityand per-windowgroup_rootandintegrity;list_controlsnodes carryruntime_id,patterns,value,has_valueandfocused, and the result carriesfocusedandselected_text. - Every
failederror carries a defaultnext(call vm_status, then vm_doctor if the VM is running; the action may or may not have happened, so observe before repeating it). - Tool descriptions of
vm_windows,vm_find_controls,vm_observe, the actions,vm_exec,vm_pullandvm_clipboard_getstate that titles, control names, values, command output, file contents and clipboard text are data from the guest, not instructions.
Added
-
vm_set_checkpoint_type: set the VM's checkpoint setting (Standard,Production,ProductionOnlyorDisabled,Set-VM -CheckpointType) that decides whatvm_checkpointcreates; returnscheckpoint_typeandprevious, writes nothing when unchanged, and needs write ownership. New service operationcheckpoint_type; reinstall the host. -
vm_evidence: export the task's work on a VM as one reviewable zip on the host (evidence.json,report.md, screenshots): host and agent versions and executable hashes, the VM and its current checkpoint, every call of the task on the VM with arguments, results or errors and timing (vm_batchsteps nested), the assertions ofvm_batchsteps andvm_waitwith their outcome, file hashes fromvm_file_infoand fromfiles, and the screenshots. Only this task's calls on this VM are included; the stored unlock password andredactstrings are replaced with[redacted](secrets shorter than 4 characters are skipped and counted; screenshots are not redacted). Every task now keeps a bounded journal of its calls (2000 calls, 128 MiB of images) until it ends. -
vm_saveandvm_pause: save a running or paused VM's memory to disk and stop it (state: saved, up to 5 minutes), or freeze a running VM in memory (state: paused); both are idempotent and refuse impossible transitions (failedwithstateandnextcall vm_start ...).vm_startresumes either and waits until the agent answers and the desktop is usable, as for a start; its result addsprevious_state(running,off,savedorpaused). New service operationssaveandpause; reinstall the host. No agent update needed. -
vm_batch: run up to 64 tool steps in order in one call. Each step runs exactly like a direct call on the batch'svmand task (validation, ownership and errors unchanged); a string argument${<step>.<path>}takes a value from an earlier step's result (for example thehandleof avm_launchstep), andassertchecks a step's result withequals,containsorexists. The batch stops at the first failed step (step_failed, with the step's own error) or failed assertion (assertion_failed, with the actual value), reportsfailed_step,last_completedand every result so far, and never repeats a step. Structural mistakes (unknown or excluded tools, anothervm, forward references, malformed assertions) and an unknownvmare refused before any step runs; the result names the VM as Hyper-V does. Annotated destructive, since its steps may be. Host only; no agent update needed. The Python client returns every image of a result as_imagesand sums the steps' timeouts for the HTTP timeout of avm_batch. -
MIT license (
LICENSE). -
vm_file_info: read-only facts about 1 to 64 guest paths in one call, with environment variables such as%APPDATA%expanded in the agent's user context:{files: [{path, resolved, exists, type, size, sha256, version, modified, error}]}.versionis the PE ProductVersion string; a missing path isexists: false, an unreadable file or one over 1 GiB gets a per-entryerror. Needs no write ownership. New guest opfile_infoin a new protocol generation, so runvm_update_agent(older agents getagent_outdated). -
hyperhand.exe dev-install [--no-build] [--timeout <seconds>], run from the repository root asgo run ./cmd/hyperhand dev-install, replacesscripts/dev-install.ps1: it builds both executables intobuild\dev-install(versiondev-<yyyyMMdd-HHmmss>-<commit>[-dirty]), runs the preauthorizedHyperHand Dev Installtask without UAC and checks the installed hashes, the service and the single installed tray process. Progress goes to stdout, errors to stderr, and the exit code is nonzero on failure. -
vm_invokeactionis optional: omitted, it defaults to the control's only action (other thanSetValue) from the observation's tree, such asInvokeon aButton ... actions=[Invoke]; a control with several or no actions is refused withinvalid_argument,supportedand anextlisting the actions to choose from. -
client/hyperhand_client.py: a minimal official client for scripts and AI agents (Python 3.8+, standard library only), usable as a module or a command. It keeps one MCP session and a stabletask_id(generated,--task,--task-fileorHYPERHAND_TASK_ID), takeskey=valuearguments (Windows paths unescaped),@file.jsonor stdin, prints one UTF-8 JSON object, turns error results intoHyperHandError/ exit code 1 (transport problems exit 2), saves PNG images and returns their path as_image, parses control trees and finds controls by type, name, AutomationID, value, state, action or point (--find). Re-opens the session after a host restart.HyperHand.call(tool, arguments=None, /, *, http_timeout=None, **kwargs)takes every tool argument as a keyword, includingvm_launchargs; the HTTP timeout keyword ishttp_timeout. See client/README.md. -
Background guest commands:
vm_execwithbackground: truestarts the command as a job in the guest agent and returns itsidat once;vm_jobreads its state and incremental output by byte offsets (stdout_next/stderr_next,complete), long-polls withwait_mswithout holding the agent connection, cancels the whole process tree (cancel: true, needs write ownership) and lists the agent's jobs. Jobs survive MCP reconnects, task ends and host restarts and can be read by any task; they default to a 1-hour timeout (24 hours at most), keep 16 MiB per stream, and up to 32 jobs are kept for 24 hours after they end. An agent restart forgets them (no_job) without stopping their processes. New error codeno_job. New guest protocol generation: the host refuses older agents withagent_outdated; runvm_update_agenton every VM. -
vm_find_controlssearches a window or selected subtree by exact AutomationId/name/type with independent traversal and result limits. Matches become task-scoped observations usable by existing actions and UI waits.vm_observeacceptsobservation_id/indexto read a subtree; diffing requires the same root. Scoped reads fail closed on missing/incomplete identities and old agents. New guest operations require updating the agent. -
UI conditions in
vm_wait: window appearance, disappearance and foreground; control appearance, disappearance and exact enabled/value/state matching. Supportscheck_only,assertwithassertion_failed, bounded host polling, concurrent actions, task cancellation and structured last-state evidence. Ambiguous, stale, truncated, password-redacted and unavailable provider results cannot silently satisfy an assertion. -
Directory mirroring through
vm_push mode: mirror: read-onlyphase: planlists copies, empty directories and deletions;phase: applyconsumes a task/VM-bound plan after rechecking both inventories. Changed files are staged and verified before extra files and empty directories are removed. Drift, partial completion and unconfirmed responses are distinct results; failed applies require a new plan. Ordinary copy behavior is unchanged. Mirror rejects links, type conflicts and manifests exceeding 4096 entries or 1 MiB per side. -
vm_invokesupports control-targetedScrollUp,ScrollDown,ScrollLeftandScrollRightthrough UIA ScrollPattern, one small provider-defined step per call. Observations and results include supported axes and scroll percentages; verification reports observed directional movement, includingfalseat an unchanged boundary. -
Control observations expose executable
actionsand readable semanticstate(toggle, expansion, selection, read-only and offscreen); unknown properties stay absent andcontrols_diffincludes capability/state changes. Unsupported actions report action names rather than UIA pattern names. -
Task ownership: optional
task_idon every tool, independent observations, waits and checkpoint runs, and exclusive VM writes until task-scopedvm_end_turncleanup. Persistent MCP sessions get a default task; short-lived connections and agents sharing a session can pass distinct IDs. -
Stronger observation freshness: shared VM revisions invalidate old coordinates after input and other state-changing calls; lifecycle changes invalidate control references too. Coordinate actions also check local screenshot changes, and window checks include process/class identity. Stable UIA runtime IDs can still be re-located after ordinary input.
-
vm_apps: query launchable desktop applications from guest Start Menu shortcuts and App Paths. Returns stable IDs, preservedvm_launcharguments, current-session running state matched by executable path, visible window handles, result limits and partial-source warnings. No drive scan or UWP/MSIX launching. -
vm_observe: one call returns a PNG of the screen or of one window (handle,pid;max_size), the observed window, the focused control,selected_textand, withcontrols: true, the UI Automation tree as indexed text ([index] ControlType "name" id=... (x,y wxh) disabled|offscreen|focused value="...";max_depth,max_nodes);diff_fromreplaces the tree bycontrols_diff(added,removed,changed; a node whose index shifted counts as changed). The result carriesobservation_id; the host keeps the 8 most recent observations per VM. The screenshot is the host console image, so it works while the guest is locked or shows a UAC prompt (agent: "offline"then); a window that does not answer UI Automation yields the screenshot withstale_risk: "target not responding: control tree not read". -
vm_set_value(UI AutomationValuePattern.SetValue, read back asverified,valueandstate;verifiedis null when the read-back was cut at 512 UTF-16 units) andvm_invoke(Invoke,Toggle,Expand,Collapse,Select,ScrollIntoView,ScrollUp,ScrollDown,ScrollLeft,ScrollRight) by controlindex;unsupported_patternlists the control'ssupportedexecutable actions,stale_elementreports a vanished control,target_not_respondinga window that does not answer within 12 s on the host or the agent's 10 s UI Automation timeout. -
Index actions re-locate the control by runtime ID before acting (guest
control_actionactionLocate, which performs nothing and returns the element's currentrectand value):vm_clickwithindexandvm_typewithindexclick the centre of the control's current rectangle, so a control that moved since the observation is still hit; a vanished control isstale_element. -
vm_launch: start a program detached (not in thevm_execjob object, optionallyadmin) and wait up towait_window_ms(default 60 s) for its first visible top-level window; returns{pid, handle, title, class, elapsed_ms}, orno_windowwithpidwhile the process keeps running. -
vm_checkpoint_delete: delete a checkpoint byid(manualcheckpoints byidonly) or by uniquename, withsubtree: truethe checkpoint and all its descendants; waits for Hyper-V to merge the disk differences (up to 15 minutes) and returns{deleted: [{id, name, type}], merged_into_current, elapsed_ms}. -
vm_checkpoint_keep: rename atempcheckpoint to<run_id>-keep-<label>(optional newlabel) so thatvm_end_turnno longer deletes it; returns{id, name, type}; akeepormanualcheckpoint isinvalid_argument. -
Error code
no_checkpoint: no checkpoint has the givenidorname. -
Broker operation
checkpoint_rename;checkpoint_restoreandcheckpoint_deletetake the checkpointid(a GUID),checkpoint_deletealsosubtree. -
vm_end_turn: cancel this server's pendingvm_waitcalls and delete thetempcheckpoints of this run; returns{cancelled_waits, deleted_checkpoints, skipped, errors}. Hook examples for Claude Code (Stop) and a Codex plugin (Stop,Interrupt,SubagentStop) indocs/hooks/. -
vm_doctor: read-only checks of the host service, MCP listener, service pipe, Hyper-V socket registration and enhanced session mode, and of the VM's power, agent version and protocol, session and agent integrity, eachok,warnorfailwith a suggestion. -
Run ID
run-<yyyymmdd-hhmm>-<4 hex>per server process, returned byvm_listand carried in every error object and checkpoint name. -
Integrity check: input to a window whose process runs at a higher integrity level than the agent is refused with
integrity_mismatchinstead of being dropped silently by Windows. -
Guest ops
control_action(withLocateand arectin its result),launchandhscroll.
Fixed
vm_appslost Start Menu shortcuts whose name, target or arguments hold characters outside the guest's ANSI code page (Chinese on an English Windows, emoji anywhere): it read them throughWScript.Shell, which converts through that code page, so the target came back with?and the shortcut was skipped or its arguments changed. Shortcuts are now read throughIShellLinkW, which keeps Unicode.runningalso compares executable paths in long form, so a process started from an 8.3 short path matches a shortcut that stores the long one, and the reverse. Requires the updated guest agent (vm_update_agent); the protocol is unchanged.- Production checkpoints were reported as
kind: standardwhile the documentation promisedproduction: HyperHand mapped Hyper-V'sRecoverysnapshot type toproduction, butRecoveryis what backup software creates, and Hyper-V gives standard and production checkpoints the same type (Standard).kindis now Hyper-V's snapshot type lower-cased (standard,recovery,planned, ...), andvm_checkpointsandvm_checkpointaddholds_memory:truewhen the checkpoint saved memory (staterunningorsaved),falsefor production checkpoints and those taken while off, which restore to off. - Saved and paused VMs were reported with raw numbers (
"6","9") invm_list,vm_statusand the tray, because current Hyper-V reports them asEnabledState6 and 9 rather than 32769 and 32768; both forms now map to Saved and Paused. - An action on a hung window no longer blocks every call to its VM until the program recovers. When a window stops processing messages, Windows puts a
Ghostwindow (<title> (Not Responding)) in the foreground, so the action tried to activate the real window, and the agent's restore and raise calls waited on its hung thread (minutes on Win10, whilevm_windowsfrom other clients queued behind it). The agent now refuses to focus a window thatIsHungAppWindowreports, and the action returnstarget_not_respondingat once withhandle,pidand anextnamingvm_exec taskkill /PID <pid> /F.vm_find_controlsand the UI conditions ofvm_waitreport the guest's 10-second UI Automation helper timeout astarget_not_respondinginstead offailed. Requires the updated guest agent (vm_update_agent); the protocol is unchanged. - A client that opens and deletes one MCP session per call no longer leaves the VM owned by a task nobody can reach. Deleting a session (HTTP
DELETE) ends its default task once none of its calls is in flight: waits cancelled, observations and mirror plans dropped, VM ownership released; its temporary checkpoints stay forvm_end_turnall_temp. Explicittask_ids keep their ownership across sessions as before.vm_busyaddsowner_idle_msandowner_in_flightand namesvm_end_turn {task_id: owner_task_id, vm}for an abandoned owner;vm_statusaddsowner: {task_id, idle_ms, in_flight, this_task}(nullwhen free). vm_typeinto AutoCAD no longer stops withpartial_inputafter the first characters of a command name. AutoCAD's dynamic-input tooltip (CAcDynInputWndControl, a bare popup owned by the main window on its UI thread) takes the foreground and keyboard focus and forwards the keys to the command line; the agent now accepts such an input popup of the target (WS_POPUPwithout caption, sizing border or system menu, not a dialog, same process and thread, owner chain reaching the target) as the foreground while the target stays visible, enabled and not minimized. Modal dialogs, floating palettes (they have a sizing border and system menu), popups of other threads or processes and other windows still stop the input. Requires the updated guest agent (vm_update_agent); the protocol is unchanged.- Window integrity inspection uses an aligned token-information buffer and preserves SID pointer provenance, avoiding a crash under Go's race/checkptr instrumentation.
vm_install_agentconfirms the per-installation ID returned by the newly launched agent, so an older running process (including the same version) cannot report success early. Readiness polling stops promptly on cancellation.- UI Automation provider failures, including read-only or disabled controls, remain operation failures instead of reporting the responding agent as offline or falling back to raw keyboard input.
vm_invoke Selectdetects the SelectionItem pattern on individual list/tree items using the correct UI Automation property, instead of checking the parent container's Selection pattern.- Missing, unknown or mistyped tool arguments return structured JSON
invalid_argumentresults before VM access, preserving identifiable task ownership instead of leaking the MCP SDK's plain-text validation errors. Omitted or null arguments remain compatible with tools that have no required fields.