An MCP (Model Context Protocol) server for Hyper-V VM management and guest execution. Exposes 19 tools for VM lifecycle, checkpoint management, kernel debug setup (KDNET/KDCOM), and guest file transfer/command execution via PowerShell Direct (no WinRM required).
Designed to pair with kd-mcp, which wraps
kd.exefor kernel debugging.hyperv_configure_kdnetreturns akernel_attach_stringyou can pass directly to kd-mcp'skernel_attachtool — end-to-end VM snapshot → KDNET config → kernel attach in one workflow.
- Windows 10/11 Pro or Enterprise with Hyper-V enabled
- Python 3.10+
- The process running the server must be elevated (run as Administrator) or the user account must be a member of the Hyper-V Administrators local group
Install directly from GitHub:
pip install git+https://github.com/originsec/hyperv-mcp.gitThis installs the hyperv-mcp console script and pulls in the mcp dependency
automatically.
To install a specific revision (tag or commit):
pip install git+https://github.com/originsec/hyperv-mcp.git@v0.1.0hyperv_configure_kdnet, hyperv_configure_kdcom, and all hyperv_guest_* tools
connect to VM guests via PowerShell Direct and need local admin credentials.
Set them once as env vars:
$env:HYPERV_GUEST_USERNAME = "Administrator"
$env:HYPERV_GUEST_PASSWORD = "your_guest_password"The hyperv_victim_* tools use a separate unprivileged account for EoP testing:
$env:HYPERV_GUEST_VICTIM_USERNAME = "victim"
$env:HYPERV_GUEST_VICTIM_PASSWORD = "your_victim_password"claude mcp add hyperv -- hyperv-mcp{
"mcpServers": {
"hyperv": {
"command": "hyperv-mcp"
}
}
}If you need to pin guest credentials per-config:
{
"mcpServers": {
"hyperv": {
"command": "hyperv-mcp",
"env": {
"HYPERV_GUEST_USERNAME": "Administrator",
"HYPERV_GUEST_PASSWORD": "your_guest_password"
}
}
}
}You can also invoke the module directly without the console script:
python -m hyperv_mcpgit clone https://github.com/originsec/hyperv-mcp.git
cd hyperv-mcp
pip install -e .| Tool | Parameters | Returns |
|---|---|---|
hyperv_list_vms |
— | [{name, state, status, memory_mb, cpu_count, uptime_seconds}] |
hyperv_get_vm_info |
vm_name |
{name, state, generation, com_ports, network_adapters, hard_drives, ...} |
hyperv_start_vm |
vm_name |
{status, vm_name, state} |
hyperv_stop_vm |
vm_name, method |
{status, vm_name, method, state} |
hyperv_reset_vm |
vm_name |
{status, vm_name, state} |
hyperv_stop_vm method values:
"shutdown"(default) — graceful guest OS shutdown via Integration Services"save"— suspend and save VM state to disk"turnoff"— hard power-off (equivalent to pulling the power cord)
| Tool | Parameters | Returns |
|---|---|---|
hyperv_checkpoint_create |
vm_name, checkpoint_name |
{status, vm_name, checkpoint_name} |
hyperv_checkpoint_list |
vm_name |
[{name, type, created, parent_name}] |
hyperv_checkpoint_restore |
vm_name, checkpoint_name |
{status, vm_name, checkpoint_name} |
hyperv_checkpoint_remove |
vm_name, checkpoint_name, include_subtree |
{status, vm_name, checkpoint_name} |
checkpoint_name is auto-generated from the current timestamp if omitted.
checkpoint_restore powers off the VM; call hyperv_start_vm to bring it back up.
| Tool | Parameters | Returns |
|---|---|---|
hyperv_configure_kdnet |
vm_name, host_ip, port, key, reboot, username, password |
{status, kernel_attach_string, key, ...} |
hyperv_configure_kdcom |
vm_name, pipe_name, com_port, reboot, username, password |
{status, kernel_attach_string, ...} |
hyperv_configure_kdnet — Default kernel debug method. Runs bcdedit inside
the guest via PowerShell Direct to configure KDNET. No host-side Hyper-V changes
needed. Returns kernel_attach_string to pass directly to kd-mcp's kernel_attach.
hyperv_configure_kdcom — Use when KDNET is unavailable (no NIC, or early-boot
debugging needed). Maps a VM COM port to a named pipe, then configures the guest
via bcdedit. VM must be Off or Saved before calling this.
Credentials are resolved from arguments first, then HYPERV_GUEST_USERNAME /
HYPERV_GUEST_PASSWORD env vars.
All hyperv_guest_* tools communicate over the VMBus channel, so the guest
network does not need to be configured. Credentials follow the same env-var
resolution as the KD setup tools.
| Tool | Parameters | Returns |
|---|---|---|
hyperv_guest_run |
vm_name, command, args[], cwd?, timeout_ms, elevated, username, password |
{ok, exit_code, stdout, stderr} |
hyperv_guest_run_ps |
vm_name, script, timeout_ms, elevated, username, password |
{ok, exit_code, stdout, stderr} |
hyperv_guest_put |
vm_name, local_path, remote_path, username, password |
{ok, bytes_copied} |
hyperv_guest_get |
vm_name, remote_path, local_path, username, password |
{ok, bytes_copied} |
hyperv_guest_read_file |
vm_name, remote_path, max_bytes?, username, password |
{ok, content_b64, bytes_read, truncated} |
hyperv_guest_list_dir |
vm_name, remote_path, username, password |
{ok, entries[]} |
hyperv_guest_run_ps and hyperv_guest_run run the script/binary in a child
powershell.exe process inside the guest; stdout and stderr are merged and
returned in stdout.
elevated=True launches the script/binary via Start-Process -Verb RunAs -Wait
so binaries that need High IL (e.g. bcdedit.exe, anything with a
highestAvailable / requireAdministrator manifest) run correctly and their
exit code is captured. This works without UAC prompts when the guest credential
is the built-in Administrator account; for other admin accounts the guest
must have UAC auto-elevation enabled (ConsentPromptBehaviorAdmin=0) or UAC
disabled.
hyperv_guest_put creates destination parent directories automatically.
hyperv_guest_read_file returns base64-encoded content; use hyperv_guest_get
for files larger than ~1 MB.
| Tool | Parameters | Returns |
|---|---|---|
hyperv_victim_run |
vm_name, command, args[], cwd?, timeout_ms |
{ok, exit_code, stdout, stderr} |
hyperv_victim_run_ps |
vm_name, script, timeout_ms |
{ok, exit_code, stdout, stderr} |
These tools use HYPERV_GUEST_VICTIM_USERNAME / HYPERV_GUEST_VICTIM_PASSWORD instead of
the admin credentials. The session runs at Medium IL (non-elevated), making them the
correct trigger path for EoP vulnerability testing where the bug must be reached from an
unprivileged context.
# 1. Take a clean snapshot
hyperv_checkpoint_create(vm_name="debug-vm", checkpoint_name="pre-kd")
# 2. Configure KDNET and reboot the guest
result = hyperv_configure_kdnet(
vm_name="debug-vm",
host_ip="192.0.2.1", # host IP on the same vSwitch as the VM
reboot=True,
)
# result["kernel_attach_string"] => "net:port=50000,key=a1b2c.d3e4f.5a6b7.c8d9e"
# 3. In kd-mcp, attach using the returned string
kernel_attach(connect_string=result["kernel_attach_string"])
# 4. When done, restore to clean state
hyperv_checkpoint_restore(vm_name="debug-vm", checkpoint_name="pre-kd")
hyperv_start_vm(vm_name="debug-vm")
KDCOM (no NIC / early boot):
hyperv_stop_vm(vm_name="debug-vm", method="save")
result = hyperv_configure_kdcom(vm_name="debug-vm", reboot=True)
# result["kernel_attach_string"] => "com:pipe,port=\\.\pipe\kd_debug-vm,resets=0,reconnect"
Host IP for KDNET — Use the IP of the host adapter on the same Hyper-V virtual
switch as the VM. Run Get-VMNetworkAdapter -VMName "YourVM" and match against
ipconfig output.
Auto-generated key — If you omit key, hyperv_configure_kdnet generates a
cryptographically random key and returns it. Save it — you need it each time you call
kernel_attach.
Get-VM and all Hyper-V PowerShell cmdlets require either UAC elevation or membership
in the Hyper-V Administrators local group.
Do not run the server or the MCP client as Administrator. With the stdio MCP transport, the client (Claude Code, Claude Desktop) spawns the server process, so the server inherits the client's token. Elevating one without the other does nothing useful.
The correct fix is to add your account to the Hyper-V Administrators group. This grants access to Hyper-V cmdlets from a normal non-elevated session — no UAC anywhere:
# Run once in an elevated session, then log out and back in
Add-LocalGroupMember -Group "Hyper-V Administrators" -Member "$env:USERNAME"After re-logging in, verify membership and confirm Get-VM works from a normal session:
Get-LocalGroupMember -Group "Hyper-V Administrators"
Get-VMRe-run the install so mcp is pulled in:
pip install git+https://github.com/originsec/hyperv-mcp.gitIssues and PRs welcome. This is a research tool, not a product — expect rough edges and breaking changes between versions.
Apache 2.0 — see LICENSE and NOTICE
Built by Origin for security research and red team operations.