Skip to main content
Glama
revytechinc
by revytechinc
README.md
# vmrun-mcp

MCP server that wraps VMware **Workstation / Fusion / Player** `vmrun` so
Claude Code, Cursor, OpenCode, FreeGrok/Grok Computer Hub, and other MCP
clients can power VMs, snapshots, guest copies, and screen captures on the
**local desktop hypervisor** (not vCenter/ESXi).

## Requirements

- Python 3.11+
- `vmrun` on `PATH` (ships with VMware Workstation Pro / Fusion / Player)
- Linux, macOS, or Windows host where that product is installed

## Install

```bash
git clone https://github.com/revytechinc/vmrun-mcp.git
cd vmrun-mcp
python3 -m venv .venv
. .venv/bin/activate
pip install -e .
```

Smoke test:

```bash
vmrun list
python -m vmrun_mcp   # waits on stdio — Ctrl-C; clients launch this for you
```

## Environment

| Variable | Default | Meaning |
|----------|---------|---------|
| `VMRUN_BIN` | `vmrun` on `PATH` | Absolute path to `vmrun` |
| `VMRUN_HOSTTYPE` | `ws` | `ws` (Workstation), `fusion`, or `player` |
| `VMRUN_GUEST_USER` | unset | Guest OS user for Tools guest ops |
| `VMRUN_GUEST_PASSWORD` | unset | Guest OS password |
| `VMRUN_ALLOWED_PREFIXES` | unset | `:`-separated absolute dirs; `.vmx` must live under one |
| `VMRUN_VM_ROOTS` | common home dirs | `:`-separated dirs to scan for `list_registered_vms` |
| `VMRUN_MCP_TRANSPORT` | **`streamable-http`** | Default for MCPs we make (`mcp-streamable-http` skill). Use `stdio` when the client only spawns a child process. |
| `VMRUN_MCP_HOST` | `127.0.0.1` | Bind address for network transports |
| `VMRUN_MCP_PORT` | `8765` | Bind port for network transports |
| `VMRUN_MCP_ALLOW_REMOTE` | unset | Must be `1` to bind anything other than loopback |

### Bind security (no auth)

This server does **not** implement authentication.

**Default:** Streamable HTTP on loopback:

```bash
python -m vmrun_mcp
# → http://127.0.0.1:8765/mcp
```

For spawn-only clients (many Claude/Cursor `command` entries):

```bash
VMRUN_MCP_TRANSPORT=stdio python -m vmrun_mcp
```

See [`examples/STREAMABLE-HTTP.md`](examples/STREAMABLE-HTTP.md). Binding
`0.0.0.0` or a LAN IP exits unless `VMRUN_MCP_ALLOW_REMOTE=1` (warning still
printed). Do not expose this on a network without a reverse proxy and real auth.

## Tools

Inventory (call these **before** changing boot media — never assume one disk):

- `list_registered_vms` — discover `.vmx` under `VMRUN_VM_ROOTS` / common dirs
- `describe_vm` — **every** hard disk + CD/DVD, RAM, firmware, displayName
- `get_playbook` — cold-start playbook (also resource `vmrun://playbook`,
  prompt `inspect_before_boot`; server `instructions` point here on connect)

Power: `list_running_vms` (running only), `start_vm`, `stop_vm`, `reset_vm`,
`suspend_vm`, `pause_vm`, `unpause_vm`

Snapshots: `list_snapshots`, `snapshot`, `delete_snapshot`, `revert_to_snapshot`

Guest / media: `get_guest_ip`, `capture_screen`, `run_script_in_guest`,
`copy_file_host_to_guest`, `copy_file_guest_to_host`, `connect_named_device`,
`disconnect_named_device`

Escape hatch: `vmrun_raw`

## Client setup

Example snippets live in [`examples/`](examples/). Restart the client after
editing config.

### Cursor

User or project `mcp.json` (root key **`mcpServers`**):

```json
{
  "mcpServers": {
    "vmrun": {
      "command": "/absolute/path/to/vmrun-mcp/.venv/bin/python",
      "args": ["-m", "vmrun_mcp"],
      "env": {
        "VMRUN_HOSTTYPE": "ws",
        "VMRUN_ALLOWED_PREFIXES": "/home/you/vmware"
      }
    }
  }
}
```

Typical paths: `~/.cursor/mcp.json` or `<project>/.cursor/mcp.json`.

### Claude Code / Claude Desktop

`~/.claude.json` or project `.mcp.json`:

```json
{
  "mcpServers": {
    "vmrun": {
      "command": "/absolute/path/to/vmrun-mcp/.venv/bin/python",
      "args": ["-m", "vmrun_mcp"],
      "env": {
        "VMRUN_HOSTTYPE": "ws"
      }
    }
  }
}
```

### OpenCode

`opencode.json` / `~/.config/opencode/opencode.json` — root key **`mcp`**,
`command` as a **full array**:

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "vmrun": {
      "type": "local",
      "command": [
        "/absolute/path/to/vmrun-mcp/.venv/bin/python",
        "-m",
        "vmrun_mcp"
      ],
      "enabled": true,
      "environment": {
        "VMRUN_HOSTTYPE": "ws"
      }
    }
  }
}
```

(OpenCode v2 may nest under `mcp.servers`; use the shape your installed
OpenCode documents — both “flat `mcp.<name>`” and `mcp.servers.<name>` appear
in the wild.)

### Grok / FreeGrok (xAI Computer Hub)

FreeGrok’s Computer Hub speaks MCP over stdio. Register the same command as a
local MCP server in the hub / agent config (name `vmrun`, command =
`python -m vmrun_mcp` from the venv). Tool results are MCP content blocks.

If a given Grok build only has shell tools, install the shared skill
`vmware-workstation` from [revytechinc/skills](https://github.com/revytechinc/skills)
and call `vmrun` directly — same operations, no MCP required.

## Pair with the skill

Agents should also load **`vmware-workstation`** from `revytechinc/skills`
(when to use ISO vs VMDK, UEFI, pulling images to `~/Desktop`, safety). The MCP
is the control plane; the skill is the playbook.

## License

BSD-2-Clause. Copyright (c) 2026 REVYTECH, Inc.