DeskVNC DeskVNC

DeskVNC dvv MCP tool reference

The dvv server speaks the Model Context Protocol and exposes exactly 25 tools, asserted as TOOL_COUNT: usize = 25 in the manifest at crates/dvv/src/mcp/manifest.rs. Argument names, types, enums, and required fields below are quoted verbatim from that file. Any field not listed under "Required" is optional.

Two design choices appear on every tool. The selector trio (limbId, groupId, member) lets a tool stay the same whether the agent drives one machine or a hundred. The generation argument on every coordinate tool proves the coordinate was computed against the geometry on the wire; a click without it is refused.

Four codes come up on every agent loop: LIMB_GONE, GEOMETRY_CHANGED, SCREEN_CHANGED, and LEASE_REVOKED. Other codes are named next to the tool that raises them.

dvv_hosts

List saved machines and the machines discovery has found, with the protocol and whether a credential is stored. The reply never carries a secret.

Raises POLICY_DENIED without the hosts.read capability. Shell equivalent: dvv hosts.

dvv_limbs

Every limb this attachment can see: id, protocol, address, state, size, capabilities, and who holds the lease. A machine DeskVNCViewer already has open but this attachment has not attached is listed under available; passing one of those limbIds attaches it on the way in. No arguments. Shell equivalent: dvv limbs.

dvv_open

Opens a limb against a saved host (by hostId) or an endpoint (by address and protocol). The credential is read from the keychain inside the application. Returns as soon as the session task spawns; poll dvv_status or call dvv_wait with until: "connected".

Shell equivalent: dvv open <name or hostId> --perceive.

dvv_close

Closes a limb and releases anything it held. Idempotent: closing a limb that is already gone returns an ordinary success. Every intent in flight is withdrawn and settles first.

Shell equivalent: dvv close <limbId>.

dvv_reconnect

Drop the connection and dial the machine again, then wait for it to come back. The person at the remote end does nothing; the credential is applied as for any open.

Shell equivalent: dvv reconnect <limbId>.

dvv_status

State, protocol, size, geometry generation, lease holder, and the negotiated signals for one limb, as the full dvv.observation.v1 object. The cheapest call in the manifest, safe to call constantly. Reads no pixels, so it does not clear the typing fence. After a LEASE_REVOKED, read lease.human_took_over from this object: true means a person is driving and the right move is to stop.

Shell equivalent: dvv status <limbId>.

dvv_control

Acquire, release, or check the control lease. This is what lets an agent act at all when a person might be present.

Raises LEASE_NOT_HELD when an act needs the lease and the agent does not have it, and LEASE_REVOKED when the lease went away under the call. Shell equivalent: dvv control acquire <limbId>.

dvv_click

A pointer event at framebuffer pixel coordinates. Desktop limbs only; terminal limbs return a clean WRONG_PROTOCOL error.

Raises GEOMETRY_CHANGED when the screen resized since the coordinate was computed, UNFENCED when no generation is supplied, OUT_OF_BOUNDS for coordinates outside the framebuffer, and WRONG_PROTOCOL on a terminal limb. Shell equivalent: dvv click <limbId> <x> <y> and dvv click <limbId> <x> <y> --action double.

dvv_type

Types a string into whatever has focus. On a desktop limb this is refused with SCREEN_CHANGED unless the agent has called dvv_screen since the last large repaint, and refused outright on a limb that has never been read. Terminal limbs are not fenced, because a PTY echoes what it is sent into a stream you can read back.

Raises SCREEN_CHANGED and WRONG_PROTOCOL on a desktop limb. Shell equivalent: dvv type <limbId> "text to type".

dvv_key

One named key or a chord. Fenced exactly like dvv_type: on a screen holding a selection, Enter, Delete, and ctrl+v are as destructive as a letter, so this is refused with SCREEN_CHANGED until the agent has read the screen since the last repaint.

Raises SCREEN_CHANGED and UNKNOWN_KEY when the key name is not in the fixed table. Shell equivalent: dvv key <limbId> super+r.

dvv_screen

What the limb looks like now, with size, geometry generation, and coverage beside it. The call that clears the typing fence: only a call that comes back with pixels counts. form: "damage-crop" after a settled action is the cheapest useful answer on a desktop limb.

A desktop limb returns an image content block with an imageSpace line beside it giving the region, both dimensions, and the scale: read that line to turn a point on the picture back into a coordinate on the remote. Without perceive: true on dvv_open, a desktop limb refuses rather than hand back a blank picture. Shell equivalent: dvv screen <limbId> --scale 0.5 --out ./dvv-screen.png.

dvv_wait

Blocks server side until something happens, up to timeoutMs, clamped to 25000 so a wait can never outlive the agent's own call timeout. A timeout is an ordinary success with settled: false and the observation, never an error.

Raises NOT_READY or NOT_CONNECTED when the limb has not reached the state asked for, and a plain TIMEOUT when the deadline passed without settling. Shell equivalent: dvv wait <limbId> --until connected and dvv wait <limbId> --until screen-stable.

dvv_clipboard

Reads or writes the remote clipboard. get reads whatever the person at the machine last copied, which is a password more often than anyone would like, and set puts text on the remote clipboard.

get is not served on this build and returns NOT_IMPLEMENTED; the plane does not subscribe to the event stream that carries the answer. set works. Raises POLICY_DENIED without the corresponding capability.

dvv_run

Runs one command on a terminal limb and returns stdout, stderr, and the exit code. The exit status is never invented: a command killed by a signal reports the signal and no code, a command still running when the deadline passes reports no status at all and says the deadline was what ended it. The channel starts in the home directory with a fresh environment.

Raises POLICY_DENIED without the exec capability, which is in no role bundle and must be named on the token. Shell equivalent: dvv run <limbId> --timeoutMs 5000 "command".

dvv_term_read

Terminal output since a cursor, or since the limb opened, plus a new cursor. Not served on this build, because the plane keeps no scrollback ring: inventing one from the visible grid would silently lose whatever scrolled off. Returns NOT_IMPLEMENTED; use dvv_run instead.

dvv_term_send

Raw bytes to the terminal, for the cases a command cannot express: answering a prompt, sending Ctrl+C, driving a full screen program. This is the terminal path that works in this build. Does not wait and does not know whether what was sent worked: pair it with dvv_wait.

dvv_files

File transfer over the machine's own SFTP sidecar, a second SSH connection alongside the screen. Reading needs files.read and writing needs files.write; neither implies the other, because holding the keyboard on a machine is not authority over its disk.

Raises FILES_UNAVAILABLE for a machine with no SSH server, for one the application cannot authenticate to, and for a host key that has not been trusted yet. Transfers are synchronous: a get or a put moves the whole file in windows inside this one call and answers when it is done.

dvv_transfer

Nothing to report, by design, and not a build that is missing something. dvv_files does not queue anything on this surface: a get or a put runs to completion inside its own tool call and answers with what it moved, so there is no transfer id to look up with status and nothing in flight for cancel to stop. The tool exists so a name mentioned in a document does not leave an agent guessing.

dvv_group_open

Opens several limbs at once and returns a groupId to address them together (dvv_group_run) or one at a time (any tool's groupId plus member). Every member is a real connection that stays open until dvv_group_close. If any member fails, the ones this call opened are closed again.

dvv_group_list

Open groups, or one group's members with their index, limbId, host, and state. Cheap and local: reads the server's own registry, no round trip.

dvv_group_grow

Opens more limbs and appends them to a group. New members get the next index; existing members are untouched.

dvv_group_shrink

Closes the n most recently added members and drops them from the group. Fails rather than clamping when n is larger than the group holds, because a clamp turns close three into close everything.

dvv_group_close

Closes every limb in a group and forgets it. A member that has already gone is not an error.

dvv_group_run

Runs one action on every member of a group, concurrently and not in a loop: every member starts before any finishes. One member failing is reported for that member and never stops the others.

dvv_signals

Which negotiated signals this session has, and what each absence means. Every entry is live, absent, or unknown with a reason, and never a default: absent means the far side does not do it and it is permanent for this session, unknown means nothing has arrived yet and may resolve.

Read led_state before typing a password: a defaulted Caps Lock of false is a lie that costs an account lockout. window_structure is always absent on every protocol this build speaks, and that entry exists so the negative is stated rather than inferred from a missing field. Shell equivalent: dvv signals <limbId>.

How the four codes fit the loop