Connect an agent
The installer already ran this for you. Run it again after installing a new agent, or pass client names to pick which ones to register:
$ agentpc mcp-install
$ agentpc mcp-install claude claude-desktop codex cursor gemini vscode
Supported: Claude Code, Claude Desktop, Codex, Cursor, Gemini CLI and VS Code.
Restart Claude Desktop after registering. For Codex it also raises the MCP timeouts
so slow builds and boots don't trip them. agentpc mcp-uninstall
removes the registration again.
Claude plugin
In Claude Code, the plugin bundles the MCP server with a skill that teaches Claude when
and how to use the VMs. It runs the installed agentpc binary,
so install that first.
/plugin marketplace add pawanpaudel93/agentpc
/plugin install agentpc@agentpc
With the plugin installed, agentpc mcp-install skips Claude
Code so the server isn't registered twice.
Client configs
For any other MCP client, add the server by hand. The standard shape:
{
"mcpServers": {
"agentpc": { "command": "agentpc", "args": ["mcp"] }
}
}
Codex
A first create_vm can take minutes while the image downloads, so
the server needs longer timeouts than Codex's defaults. agentpc mcp-install codex
adds these for you:
[mcp_servers.agentpc]
command = "agentpc"
args = ["mcp"]
startup_timeout_sec = 60
tool_timeout_sec = 900
VS Code
{
"servers": {
"agentpc": { "type": "stdio", "command": "agentpc", "args": ["mcp"] }
}
}
The agentpc repository ships these as project configs (.mcp.json,
.codex/config.toml, .cursor/mcp.json,
.gemini/settings.json, .vscode/mcp.json),
so an agent opened in a clone picks the server up automatically.
Tools
VMs
| Tool | Use |
|---|---|
list_vms |
VMs (owner, state, size, checkpoints, viewer) and the images they come from, with OS versions. Start here. |
create_vm |
New clone, returned once its desktop is ready: Ubuntu ~1 s, Windows ~4 s (the first
create of an image can take minutes). Takes os, and optionally
version (Ubuntu "22.04"; Windows
"11-25h2", "11-24h2",
"11-23h2"), name,
memory_gb (2–64, default 8 Windows / 4 Ubuntu),
cpus (1–16, default 4) and offline.
A non-default size boots cold (~25 s / ~15 s). Retrying in the same session returns the
VM it already made.
|
start_vm / stop_vm |
Boot a stopped VM, waiting until it's ready / shut one down cleanly. |
reset_vm |
Discard all changes: back to a fresh copy of the image, booted. |
delete_vm |
Stop a VM and delete it with its disk and checkpoints. |
Checkpoints
| Tool | Use |
|---|---|
checkpoint_vm |
Save a VM's disk and memory under a label (replacing an older one of that name) before a risky step. A running VM pauses for a few seconds. |
restore_vm |
Go back to a checkpoint exactly as it was and start it, in seconds. Port forwards must be set up again. |
delete_checkpoint |
Delete one checkpoint by label; the VM is untouched. |
Shell, files and ports
| Tool | Use |
|---|---|
run_command |
PowerShell on Windows, bash on Ubuntu, over SSH. Returns the exit code, stdout and
stderr, each trimmed to its first and last 10,000 characters. A foreground run is
killed at timeout (default 120 s) with partial output;
background: true returns a job id.
|
get_job_status |
A background job's state (running, or exited with its code) and the tail of its log (tail_lines, default 50). |
upload_file / download_file |
Copy files or folders between the Mac and a VM. |
forward_port |
Reach a server in the VM from the Mac at 127.0.0.1:<host_port>.
An SSH tunnel, so it reaches servers bound to the guest's own
127.0.0.1. Lasts until the VM stops.
|
list_forwards / delete_forward |
List a VM's forwards and whether each tunnel is alive / stop one by its host port. |
Screen and desktop
| Tool | Use |
|---|---|
take_screenshot |
PNG straight from the hypervisor, even while booting or hung. save_to also writes it to a path on the Mac. |
list_desktop_tools |
The desktop-control tools inside a VM, or one tool's full schema. |
use_desktop_tool |
Call one of them (tool plus arguments): click, type, launch apps, read the UI tree, and more. Gives up after 120 s. |
read_vm_log |
Tail a VM's qemu or serial log (tail_lines, default 100) when it won't boot or the desktop is unreachable. |
Desktop control
Both guests run cua-driver and are
1280×800. Work in a loop: look (take_screenshot or a
snapshot tool), act (use_desktop_tool), then look again to
verify. Prefer run_command for anything a shell can do.
| Guest | How to drive it |
|---|---|
| Windows |
launch_app takes a name such as notepad
and returns the pid and window_ids.
get_window_state(pid, window_id) returns numbered elements and a
snapshot_id; click and
type_text take that snapshot_id with an
element_index. Input goes in the background first; typing into the
focused field, scroll, drag and right-click often need
"delivery_mode": "foreground", which the driver asks for when
background input can't reach the target.
|
| Ubuntu |
XFCE on X11. get_desktop_state returns a screenshot plus window
pid/window_id values. Keyboard and mouse
tools need "delivery_mode": "foreground".
launch_app takes a command such as
xfce4-terminal. Google Chrome is installed for the
browser_* tools.
|
Windows images built by agentpc 0.1.0 use Windows-MCP instead: call
Snapshot first, Click takes
loc: [x, y], and Type needs
loc or label.
list_desktop_tools shows which one a VM has.
Open Notepad on Windows and type into it, as three use_desktop_tool calls. The pid and window_id come from launch_app; the snapshot_id and element_index from get_window_state:
{ "name": "windows-1", "tool": "launch_app", "arguments": { "name": "notepad" } }
{ "name": "windows-1", "tool": "get_window_state", "arguments": { "pid": 4120, "window_id": 65812 } }
{ "name": "windows-1", "tool": "type_text", "arguments": {
"pid": 4120, "window_id": 65812, "snapshot_id": "s1a2b3c4d",
"element_index": 7, "text": "Hello from the agent" } }
Typical session
Test an install script on a clean machine, keeping a checkpoint to retry from:
create_vm { "os": "ubuntu", "name": "install-test" }
upload_file { "name": "install-test", "host_path": "./install.sh", "guest_path": "/tmp/" }
checkpoint_vm { "name": "install-test", "label": "before-install" }
run_command { "name": "install-test", "command": "bash /tmp/install.sh" }
take_screenshot { "name": "install-test" }
restore_vm { "name": "install-test", "label": "before-install" } # retry from the same state
delete_vm { "name": "install-test" }
Some prompts to try:
- "Create an Ubuntu VM, open a terminal and run
uname -a." - "Reset ubuntu-1 and check that my install script works on a clean machine."
- "Open Notepad on windows-1, type a short note and show me a screenshot."
Long jobs and servers
A foreground run_command ends when the command returns, and is
killed at its timeout. Start builds, servers and GUI apps with
background: true, then poll:
run_command { "name": "ubuntu-1", "command": "npm run dev", "background": true } # → job id 1
get_job_status { "name": "ubuntu-1", "id": 1, "tail_lines": 40 }
forward_port { "name": "ubuntu-1", "guest_port": 3000 } # → 127.0.0.1:<port> on the Mac
Reboots (some installers) drop SSH. Call start_vm on the same VM,
which waits until the desktop is ready again even if it's already running, or retry
run_command.
Session lifecycle
- VMs a session created or started are stopped, never deleted, when the session ends. Set
AGENTPC_KEEP_RUNNING=1to keep them running. list_vmsshows each VM's owner. Agents should create their own uniquely named VM per task, and never reset, restore or delete one they didn't create.- Each running VM takes 4 GB (Ubuntu) or 8 GB (Windows) of RAM, so delete VMs when done.
- The guest login is
agent/agent.
Tool annotations
Tools carry MCP annotations so clients can auto-approve or confirm them:
list_vms, take_screenshot,
list_desktop_tools, get_job_status,
list_forwards and read_vm_log are read-only.
Tools that discard or overwrite state are marked destructive, including
download_file, which writes to your Mac.
start_vm and stop_vm are idempotent.