Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ Copy `src/WinDbgMCP.Server/appsettings.example.json` to `appsettings.json` and e
"Vm": {
"VmxPath": "C:\\path\\to\\your\\vm.vmx",
"VmrunPath": "C:\\Program Files (x86)\\VMware\\VMware Workstation\\vmrun.exe",
"HostType": "ws",
"HostUrl": "",
"HostUsername": "",
"HostPassword": "",
"VmPassword": "",
"GuestUsername": "YourUser",
"GuestPassword": "YourPass"
Expand All @@ -84,6 +88,8 @@ Copy `src/WinDbgMCP.Server/appsettings.example.json` to `appsettings.json` and e
}
```

**Remote hypervisors (ESXi / vCenter / shared Workstation):** VM and guest operations can target a VM on another machine. Set `HostType` to `esx`, `vc`, or `ws-shared`, point `HostUrl` at the hypervisor API (e.g. `https://esxi-host/sdk`), and provide `HostUsername`/`HostPassword`. For esx/vc, `VmxPath` is a datastore path like `[datastore1] win10/win10.vmx`. vmrun still runs locally, so VMware Workstation (or VIX) must be installed on this machine. All of this can also be switched at runtime via `vm_set_target`. Note that kernel debugging is independent of this: the KDNET target must be able to reach this host over UDP regardless of where the VM runs.

</details>

### 3. Add to Your MCP Client
Expand Down Expand Up @@ -138,7 +144,7 @@ dotnet run --project src/WinDbgMCP.Server/WinDbgMCP.Server.csproj
| `vm_snapshot_restore` | Restore a named snapshot (debug sessions are cleanly torn down and can reconnect after) |
| `vm_snapshot_list` | List available snapshots |
| `vm_screenshot` | Capture VM display as PNG |
| `vm_set_target` | Switch the active VM target at runtime (VMX path + credentials) |
| `vm_set_target` | Switch the active VM target at runtime (VMX path + credentials, optionally a remote ESXi/vCenter host) |

### Kernel Debug Tools (7)
| Tool | Description |
Expand Down
21 changes: 21 additions & 0 deletions src/WinDbgMCP.Server/Configuration/ServerConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,27 @@ public sealed class VmConfig
{
public string VmxPath { get; set; } = string.Empty;
public string VmrunPath { get; set; } = @"C:\Program Files (x86)\VMware\VMware Workstation\vmrun.exe";

/// <summary>
/// vmrun host type (-T flag): "ws" (local Workstation, default), "esx" (ESXi),
/// "vc" (vCenter), "ws-shared" (shared Workstation), "fusion", "player".
/// </summary>
public string HostType { get; set; } = "ws";

/// <summary>
/// Remote hypervisor URL (-h flag), e.g. "https://esxi-host/sdk".
/// Leave empty for local Workstation. For esx/vc, VmxPath must be a
/// datastore path like "[datastore1] win10/win10.vmx".
/// </summary>
public string HostUrl { get; set; } = string.Empty;

/// <summary>
/// Hypervisor login (-u / -p flags). Required when HostUrl is set.
/// Note: vmrun only accepts these on the command line, so the password
/// is visible in the local process list while a vmrun command runs.
/// </summary>
public string HostUsername { get; set; } = string.Empty;
public string HostPassword { get; set; } = string.Empty;
/// <summary>
/// VM encryption password (for encrypted VMs). Used as -vp flag in vmrun.
/// </summary>
Expand Down
18 changes: 16 additions & 2 deletions src/WinDbgMCP.Server/Tools/VmTools.cs
Original file line number Diff line number Diff line change
Expand Up @@ -209,15 +209,21 @@ public static async Task<string> VmSnapshotRestore(
"Switch the active VM target at runtime. " +
"All VM, guest, and snapshot operations will target the new VM after this call. " +
"If the kernel debugger is connected, it is cleanly disconnected first. " +
"Supports remote hypervisors: pass hostType/hostUrl/host credentials to target " +
"a VM on ESXi, vCenter, or shared Workstation instead of the local machine. " +
"Note: kd_connect uses its own connection string — this only affects guest/VM operations.")]
public static async Task<string> VmSetTarget(
StateCoordinator state,
VmwareManager vmware,
DbgEngManager dbgEng,
[Description("Absolute path to the .vmx file of the target VM")] string vmxPath,
[Description("Path to the .vmx file. For esx/vc hosts use a datastore path like \"[datastore1] win10/win10.vmx\"")] string vmxPath,
[Description("Guest OS username")] string guestUsername,
[Description("Guest OS password")] string guestPassword,
[Description("VM encryption password (leave empty if VM is not encrypted)")] string vmPassword = "",
[Description("Hypervisor type: ws (local Workstation), esx, vc, ws-shared, fusion, player. Omit to keep current.")] string? hostType = null,
[Description("Remote hypervisor URL, e.g. https://esxi-host/sdk. Pass empty string to switch back to local. Omit to keep current.")] string? hostUrl = null,
[Description("Hypervisor login username (required when hostUrl is set). Omit to keep current.")] string? hostUsername = null,
[Description("Hypervisor login password. Omit to keep current.")] string? hostPassword = null,
CancellationToken ct = default)
{
var precheck = await state.ValidatePreconditionsAsync("vm_set_target");
Expand All @@ -233,7 +239,15 @@ public static async Task<string> VmSetTarget(
}

// Switch the target
vmware.UpdateTarget(vmxPath, guestUsername, guestPassword, vmPassword);
try
{
vmware.UpdateTarget(vmxPath, guestUsername, guestPassword, vmPassword,
hostType, hostUrl, hostUsername, hostPassword);
}
catch (InvalidOperationException ex)
{
return $"vm_set_target failed: {ex.Message}";
}

// Reset all state — power state of the new VM is unknown until we check
var powerState = await vmware.GetPowerStateAsync(ct);
Expand Down
Loading