Skip to main content
Glama
README.md
# vm-lab-agent

> ## 🚧 Status: Work in Progress
> This is an active, incomplete project — parts of it are tested and
> working, parts are unverified against a real server, and there's a
> known dependency bug not yet fixed (see **Known Issues** below).
> Read `SECURITY.md` before running this against a lab you care about.

A small, sandboxed [MCP](https://modelcontextprotocol.io) server for
students running network engineering / SOC analyst home labs (PNETLab,
VMware Workstation, Wazuh, Kali, etc.). It lets an AI agent power VMs
on/off, manage snapshots, build and control PNETLab topologies, and
verify device configuration -- **within an explicit allowlist you
control**, with every destructive action gated behind a confirmation
step and every action logged.

Built for hands-on CCNP / Security+ / SOC-analyst practice: spin up a
topology, configure it yourself in PNETLab's own console (the actual
exam-relevant skill), and let the agent check your work with real
`show` command output afterward.

**Compatible with any MCP client** -- Claude Code, or any other tool that
speaks the Model Context Protocol. Not locked to a single AI provider.

![vm-lab-agent architecture](architecture.svg)

> This project was designed and built with the assistance of Claude
> (Anthropic). See CREDITS.md. It is not an official
> Anthropic product and isn't endorsed by Anthropic.

## Known issues (honest, not hidden)

- **requirements.txt has a real, currently-unresolved dependency
  conflict.** netmiko==4.7.0 requires paramiko<5.0; the two aren't
  simultaneously installable as currently pinned in this repo without
  manual adjustment. Workaround until fixed: pin paramiko==4.0.0
  instead of whatever's currently in the file.
- **pnetlab_lab_add_network and pnetlab_lab_connect_interface** are
  built from an inferred API pattern, not a directly-observed working
  trace -- see SECURITY.md.
- **dynamips and docker image types** aren't supported by
  pnetlab_delete_image -- their directory layout wasn't confirmed
  with enough confidence to build against safely.
- **VMware control tools aren't containerized** the way the PNETLab SSH
  tools are -- vmrun needs to talk to VMware Workstation running on
  your actual host. See SECURITY.md for the full explanation.

None of these block basic use (VM power/snapshot/backup, PNETLab image
search/install/delete, and node power/status on an existing topology
all work and are tested) -- they're specifically the rough edges left
from finishing this in one long build session.

## Before you do anything else: read SECURITY.md

Seriously. SECURITY.md explains exactly what this agent
can and can't touch. It also covers a real, dated MCP vulnerability
(OX Security's April 2026 disclosure) and exactly why this project's
design does and doesn't fall inside that exposure.

See REFERENCES.md for the primary sources behind every
non-obvious design decision, and LEARNING.md if you want
this project to double as CCNP/Security+/SOC-analyst study material
rather than just a tool you install and forget.

## What it does

| Tool | Confirm required? | What it does |
|---|---|---|
| list_managed_vms | No (read-only) | Lists VMs on your allowlist |
| vm_status | No (read-only) | Checks if a VM is running |
| vm_power_on | Yes | Powers on a VM |
| vm_power_off_soft | Yes | Graceful guest OS shutdown |
| vm_power_off_hard | Yes, + per-VM allow_destructive | Force power-off |
| vm_snapshot_create | Yes | Takes a snapshot |
| vm_snapshot_revert | Yes, + per-VM allow_destructive | Reverts to a snapshot |
| vm_clone_create | Yes | Creates a new VM by cloning an allowlisted one; new VM is not auto-allowlisted |
| vm_backup_to_location | Yes | Copies a VM's entire folder to a location you choose |
| vm_delete_permanently | Yes, + 3 more gates | Permanently deletes a VM. Not registered as a tool unless enable_vm_deletion: true. |
| pnetlab_search_image | No (read-only) | Searches PNETLab's ishare2 catalog |
| pnetlab_list_installed | No (read-only) | Lists images already installed, by type |
| pnetlab_pull_image | Yes | Downloads/installs an image |
| pnetlab_delete_image | Yes | Deletes an installed image (qemu + iol/bin only) |
| pnetlab_fix_permissions | Yes | Runs the standard post-install permission fix |
| device_read_config | No (read-only) | Runs a show command against a lab device -- only show commands accepted |
| pnetlab_lab_topology | No (read-only) | Reads a managed lab's current nodes |
| pnetlab_lab_node_status | No (read-only) | Reads running/stopped status of every node |
| pnetlab_lab_node_power | Yes | Starts or stops a specific node |
| pnetlab_lab_create | Yes | Creates a new empty lab; not auto-allowlisted |
| pnetlab_lab_add_node | Yes | Adds a router/switch/etc. to a lab's topology |
| pnetlab_lab_add_network | Yes | Adds a network/switch object (moderate confidence) |
| pnetlab_lab_connect_interface | Yes | Connects a node's interface to a network (moderate confidence) |

## Setup

### 1. Prerequisites

- Python 3.12+
- VMware Workstation Pro/Player with vmrun installed
- A PNETLab server (optional -- only needed for PNETLab-related tools)

### 2. Install

    git clone https://github.com/vikramjeet8105-engg/vm-lab-agent.git
    cd vm-lab-agent
    pip install -r requirements.txt

If this fails on a paramiko/netmiko conflict, open requirements.txt and
change the paramiko line to paramiko==4.0.0, then retry.

### 3. Configure

    cp config.example.yaml config.yaml
    cp .env.example .env

Edit config.yaml: list the exact VMs (and optionally labs) you want the
agent to touch. Anything not listed here is invisible to the agent --
read SECURITY.md for why this matters.

### 4. Test it locally

    python -m pytest tests/ -v

### 5. Connect it to your MCP client

    claude mcp add --transport stdio vm-lab-agent -- python -m src.server

## Contributing

Issues and PRs welcome, especially fixes for anything in Known Issues
above.

## License

MIT -- see LICENSE.