Skip to main content
Glama

VMware AIops

PyPI License: MIT

English | 中文

Maintainer: Wei Zhou · zhouwei008@gmail.com

Community-maintained open-source project; not an official VMware or Broadcom product.

Overview · Quick Start · MCP Configuration · Capabilities and Workflows · Safety and Audit · Troubleshooting · Companion Skills · Reference · License

Overview

Runs locally over stdio by default; configure required targets and credentials on your own machine.

AI-powered VMware vCenter/ESXi VM lifecycle and deployment tool — 61 tools.

Scope also includes datastore file browsing and deployment image discovery, alarm acknowledgment and reset, and an explicitly started scanning/TTL daemon with optional configured webhooks. Alarm reset can clear multiple matching alarms; guest commands and file transfers retain the account and file-access boundaries documented in the capabilities reference.

Companion skills handle everything else:

Skill

Scope

Install

vmware-monitor

Read-only: inventory, health, alarms, events, metrics

uv tool install vmware-monitor

vmware-storage

Datastores, iSCSI, vSAN management

uv tool install vmware-storage

vmware-vks

Tanzu Namespaces, TKC cluster lifecycle

uv tool install vmware-vks

Need read-only monitoring only? Use VMware-Monitor — zero destructive code in the codebase.

Destructive MCP tools preview by default and require confirm=True; this is a caller-supplied flag, not independent human approval. Other writes may execute on the first call. Guest execution and file transfers remain subject to their separate account and host-path boundaries.

Skills.sh examples pin skills@1.7.6 (Node.js >=22.20.0) separately from the repository release tag. These pins do not lock transitive dependencies.

Keep TLS verification enabled and trust private CAs with SSL_CERT_FILE. Disabling certificate/hostname checks is an isolated-lab exception and permits endpoint impersonation and credential interception.

Full agent instructions: skills/vmware-aiops/SKILL.md.

Related MCP server: VMware-Monitor

Quick Start

Requires Python >=3.10 and uv.

uv tool install vmware-aiops==2.4.6
vmware-aiops --help

Target, credential and local data setup: setup guide.

Installation

Step 0: Prerequisites

# Python 3.10+ required
python3 --version

# Node.js 18+ required for Gemini CLI and Codex CLI
node --version

Step 1: Clone & Install Python Backend

All platforms share the same Python backend.

git clone --branch v2.4.6 https://github.com/vmware-skills/VMware-AIops.git
cd VMware-AIops
python3 -m venv .venv
source .venv/bin/activate
pip install -e .

Step 2: Configure

mkdir -p ~/.vmware-aiops
cp config.example.yaml ~/.vmware-aiops/config.yaml
# Edit config.yaml with your vCenter/ESXi targets

Set passwords via .env file (recommended):

# Use the template
cp .env.example ~/.vmware-aiops/.env

# Edit and fill in your passwords, then lock permissions
chmod 600 ~/.vmware-aiops/.env

Security note: Prefer .env file over command-line export to avoid passwords appearing in shell history. The .env file should have chmod 600 (owner-only read/write).

Password environment variable naming convention:

VMWARE_{TARGET_NAME_UPPER}_PASSWORD
# Replace hyphens with underscores, UPPERCASE
# Example: target "home-esxi" → VMWARE_HOME_ESXI_PASSWORD
# Example: target "prod-vcenter" → VMWARE_PROD_VCENTER_PASSWORD

Security Best Practices

Scanner notification failures report an HTTP status or exception class. Raw webhook response bodies, transport errors and connection exceptions are excluded from notification diagnostics and audit summaries to keep endpoint tokens out of them.

  • NEVER hardcode passwords in scripts or config files

  • NEVER pass passwords as command-line arguments (visible in ps)

  • ALWAYS use ~/.vmware-aiops/.env with chmod 600

  • ALWAYS configure connections via config.yaml — credentials are loaded from .env automatically

  • Config File Contents: config.yaml stores target hostnames, ports, and a reference to the .env file. It does not contain passwords or tokens. All secrets are stored exclusively in .env

  • TLS: Enabled by default. Disable only for ESXi hosts with self-signed certificates in isolated lab environments

  • Webhook: Disabled by default. When enabled, the daemon posts to your own configured URL only — no third-party service — every critical issue (alarms, events, ESXi log lines matching critical/panic/corrupt, targets it could not connect to) and every alarm/event warning — host-log warnings stay in the scan log, and info rows are never sent. Payloads carry the full issue text (entity names, alarm names, event messages, ESXi log excerpts, connection errors), which can include host names, IP addresses, and user names; they carry no credentials from your config or .env

  • Least Privilege: Use a dedicated vCenter service account with minimal permissions. For monitoring-only use cases, prefer the read-only VMware-Monitor

  • Prompt Injection Protection: All vSphere-sourced content is truncated, stripped of control characters, and wrapped in boundary markers before output

  • Code Review: We recommend reviewing the source code and commit history before deploying in production

  • Production Safety: For production environments, use the read-only VMware-Monitor instead. AI agents can misinterpret context and execute unintended destructive operations — real-world incidents have shown that AI-driven infrastructure tools without proper isolation can delete production databases and entire environments. VMware-Monitor eliminates this risk at the code level: no destructive functions exist in its codebase

Step 3: Connect Your AI Tool

Choose one (or more) of the following:


Option A: Claude Code

Method 1: Skills.sh or ClawHub (recommended)

Either installer places the skill in Claude Code's skills directory for you:

npx skills@1.7.6 add vmware-skills/VMware-AIops#v2.4.6
# or
clawhub install @zw008/vmware-aiops --version 2.4.6

Method 2: Manual skill install

git clone --branch v2.4.6 https://github.com/vmware-skills/VMware-AIops.git
cd VMware-AIops

# Copy the skill into Claude Code's personal skills directory
mkdir -p ~/.claude/skills/vmware-aiops
cp -r skills/vmware-aiops/. ~/.claude/skills/vmware-aiops/

For tool access (not just skill context), also register the MCP server:

claude mcp add vmware-aiops -- vmware-aiops mcp

Restart Claude Code, then:

> Show me all VMs on esxi-lab.example.com

Submit to Official Marketplace

This plugin can also be submitted to the Anthropic official plugin directory for public discovery.


Option B: Gemini CLI
# Install Gemini CLI
npm install -g @google/gemini-cli

# Load the skill as project context (Gemini CLI reads GEMINI.md on startup)
cp skills/vmware-aiops/SKILL.md ./GEMINI.md

For tool access (not just context), register the MCP server in ~/.gemini/settings.json:

{
  "mcpServers": {
    "vmware-aiops": {
      "command": "vmware-aiops",
      "args": ["mcp"],
      "env": { "VMWARE_AIOPS_CONFIG": "~/.vmware-aiops/config.yaml" }
    }
  }
}

Then start Gemini CLI:

gemini
> Show me all VMs on my ESXi host

Option C: OpenAI Codex CLI
# Install Codex CLI
npm i -g @openai/codex
# Or on macOS:
# brew install --cask codex

# Copy skill to Codex skills directory
mkdir -p ~/.codex/skills/vmware-aiops
cp skills/vmware-aiops/SKILL.md ~/.codex/skills/vmware-aiops/SKILL.md

# Copy AGENTS.md to project root
cp skills/vmware-aiops/SKILL.md ./AGENTS.md

Then start Codex CLI:

codex --enable skills
> List all VMs on my ESXi

Option D: Aider (supports local models)
# Install Aider
pip install aider-chat

# Install Ollama for local models (optional)
# macOS:
brew install ollama
ollama pull qwen2.5-coder:32b

# Run with cloud API
aider --conventions skills/vmware-aiops/SKILL.md

# Or with local model via Ollama
aider --conventions skills/vmware-aiops/SKILL.md \
  --model ollama/qwen2.5-coder:32b

Option E: Continue CLI (supports local models)
# Install Continue CLI
npm i -g @continuedev/cli

# Copy rules file
mkdir -p .continue/rules
cp skills/vmware-aiops/SKILL.md .continue/rules/vmware-aiops.md

Configure ~/.continue/config.yaml for local model:

models:
  - name: local-coder
    provider: ollama
    model: qwen2.5-coder:32b

Then:

cn
> Check ESXi health and alarms

Option F: Trae IDE

Copy the rules file to your project's .trae/rules/ directory:

mkdir -p .trae/rules
cp skills/vmware-aiops/SKILL.md .trae/rules/project_rules.md

Trae IDE's Builder Mode reads .trae/rules/ Markdown files at startup.

Note: You can also install Claude Code extension in Trae IDE and use .claude/skills/ format directly.


Option G: Kimi Code CLI
# Copy skill file to Kimi skills directory
mkdir -p ~/.kimi/skills/vmware-aiops
cp skills/vmware-aiops/SKILL.md ~/.kimi/skills/vmware-aiops/SKILL.md

Option H: MCP Server (Glama / Claude Desktop)

The MCP server exposes VMware operations as tools via the Model Context Protocol. Works with any MCP-compatible client (Claude Desktop, Cursor, etc.).

After uv tool install vmware-aiops==2.4.6, start the MCP server with one command (v1.5.15+):

# Recommended — single command, no network re-resolve
vmware-aiops mcp

# With a custom config path
VMWARE_AIOPS_CONFIG=/path/to/config.yaml vmware-aiops mcp

Claude Desktop config (claude_desktop_config.json):

{
  "mcpServers": {
    "vmware-aiops": {
      "command": "vmware-aiops",
      "args": ["mcp"],
      "env": {
        "VMWARE_AIOPS_CONFIG": "/path/to/config.yaml"
      }
    }
  }
}
# Run without installing (requires PyPI access each launch)
uvx --from vmware-aiops==2.4.6 vmware-aiops mcp

# Legacy entry point (still works, kept for backward compatibility)
vmware-aiops-mcp

Behind a corporate TLS proxy? uvx may fail with invalid peer certificate: UnknownIssuer. Use the recommended vmware-aiops mcp form above (no network needed), or set UV_NATIVE_TLS=true.


Option I: Standalone CLI (no AI)
# Already installed in Step 1
source .venv/bin/activate

vmware-aiops vm power-on my-vm --target home-esxi
vmware-aiops deploy ova ./ubuntu.ova --name my-vm --target home-esxi
vmware-aiops datastore browse datastore1 --target home-esxi

Configuration

See config.example.yaml for all options.

Section

Key

Default

Description

targets

name

—

Friendly name

targets

host

—

vCenter/ESXi hostname or IP

targets

type

vcenter

vcenter or esxi

targets

port

443

Connection port

targets

verify_ssl

true

Verify the target's TLS certificate (set false only for self-signed lab hosts)

scanner

interval_minutes

15

Scan frequency

scanner

severity_threshold

warning

Min severity: critical/warning/info

scanner

lookback_hours

1

How far back to scan

scanner

log_types

—

Not read by any code — the daemon always reads the hostd, vmkernel and vpxa host logs. Setting it changes nothing

notify

log_file

~/.vmware-aiops/scan.log

JSONL log output

notify

webhook_url

—

Webhook endpoint (Slack, Discord, etc.)


MCP Configuration

Copy this configuration into your MCP client's local stdio settings. The client must be able to find uvx; the initial package installation requires access to a package index.

{
  "mcpServers": {
    "vmware-aiops": {
      "command": "uvx",
      "args": ["--from", "vmware-aiops==2.4.6", "vmware-aiops-mcp"],
      "env": {
        "VMWARE_AIOPS_CONFIG": "~/.vmware-aiops/config.yaml"
      }
    }
  }
}

Capabilities and Workflows

⚡ Quick Investigation Reports (read-only)

Triage → investigate → act, all in one conversation. Five opinionated read-only reports aggregate and correlate server-side and hand back a high-signal result (never raw inventory), so you can decide where to look before changing anything. Each renders a self-contained offline HTML snapshot with --html (no external assets; drill-down detail collapses in native <details>, zero JavaScript). All delegate to the vmware-monitor library using AIops's own vCenter connection.

Question

Command

What it correlates

"What needs attention now?" across all vCenters

vmware-aiops attention

Every vCenter merged into one globally-ranked issue list; unreachable targets degrade gracefully

"Is anything on fire?" across all clusters

vmware-aiops summary

Every cluster's hosts + VM power + live CPU/mem + alarms → ranked top-N issues + per-cluster status

"What's happening around this VM?"

vmware-aiops investigate vm <name>

VM state + host + cluster + backing datastores + snapshots + alarms + performance + a merged event timeline

"What's happening around this host?"

vmware-aiops investigate host <name>

Host state + cluster + the VMs it runs + mounted datastores + alarms + performance + correlated timeline

"What's happening around this datastore?"

vmware-aiops investigate datastore <name>

Capacity/free + mounting hosts + VMs it backs + alarms + correlated timeline

vmware-aiops attention                            # what needs attention now, all vCenters
vmware-aiops investigate vm web-01 --hours 72     # everything around a VM, then act on it
vmware-aiops investigate vm web-01 --html         # → offline snapshot in ~/vmware-health/

Via MCP these are the tools get_cluster_health_summary, get_cross_vcenter_attention, investigate_vm, investigate_host, investigate_datastore. (Requires vmware-monitor installed.)

Works with Claude Code, Cursor, Codex, Gemini CLI, Trae, and 30+ AI agents:

# Via Skills.sh
npx skills@1.7.6 add vmware-skills/VMware-AIops#v2.4.6

# Via ClawHub
clawhub install @zw008/vmware-aiops --version 2.4.6

PyPI Install (No GitHub Access Required)

# Install via uv (recommended)
uv tool install vmware-aiops==2.4.6

# Or via pip
pip install vmware-aiops==2.4.6

# China mainland mirror (faster)
pip install vmware-aiops==2.4.6 -i https://pypi.tuna.tsinghua.edu.cn/simple

Offline / Air-Gapped Install (from source)

This project uses the modern PEP 517 build system (hatchling), so there is no setup.py by design — that is expected, not a missing file. If you cloned the source and hit ERROR: File "setup.py" or "setup.cfg" not found ... editable mode currently requires a setuptools-based build, your pip is older than 21.3 and cannot do an editable (-e) install with a non-setuptools backend. Editable mode is a developer convenience, not needed to run the tool — do one of:

# From the source tree — a normal (non-editable) install builds a wheel:
pip install .              # NOT  pip install -e .

# ...or upgrade pip first, and editable works too:
pip install --upgrade pip && pip install -e .

For a truly air-gapped host, build the wheels on a connected machine and copy them over — the target then needs no network:

# On a connected machine, collect this package + its dependencies as wheels:
pip wheel . -w dist        # → dist/*.whl   (or: uv build, for just this package)

# Copy dist/ to the air-gapped host, then install offline:
pip install --no-index --find-links dist vmware-aiops

Capabilities Overview

What This Skill Does

Category

Tools

Count

VM Lifecycle

power on/off, TTL auto-delete, clean slate

6

Deployment

OVA, template, linked clone, batch clone/deploy

8

Guest Ops

exec commands, upload/download files, provision

5

Plan/Apply

multi-step planning with rollback

4

Cluster

create, delete, HA/DRS config, add/remove hosts

6

Datastore

browse files, scan for images

2

Network

dvSwitch portgroup list/create, host VMkernel list/add/remove, DF-bit MTU-path ping

6

Access

which account is in use, and whether it holds each tool's privileges (get_access_info, CLI access-info)

1

CLI vs MCP: Which Mode to Use

Scenario

Recommended

Why

Local/small models (Ollama, Qwen <32B)

CLI

~2K tokens context vs ~10K for MCP; small models struggle with many tool schemas

Token-sensitive workflows

CLI

SKILL.md + Bash tool = minimal overhead

Cloud models (Claude, GPT-4o)

Either

Both work; MCP gives structured JSON I/O

Automated pipelines / Agent chaining

MCP

Type-safe parameters, structured output, no shell parsing

Monitoring / storage / K8s

Companion skills

See vmware-monitor, vmware-storage, vmware-vks

Rule of thumb: Use CLI for cost efficiency and small models. Use MCP for structured automation with large models.

Architecture

User (Natural Language)
  ↓
AI CLI Tool (Claude Code / Gemini / Codex / Aider / Continue / Trae / Kimi)
  ↓ reads SKILL.md / AGENTS.md / rules
  ↓
vmware-aiops CLI
  ↓ pyVmomi (vSphere SOAP API)
  ↓
vCenter Server ──→ ESXi Cluster ──→ VM
    or
ESXi Standalone Host ──→ VM

Version Compatibility

vSphere / VCF Version

Support

Notes

VCF 9.1 / vSphere 9.1

✅ Full

Released 2026-05-12. pyVmomi <10.0 resolves and connects via SOAP; new REST-only features (PATCH /deployment/size, IPv6-only GOSC) not yet wrapped — see VCF Python SDK for those.

VCF 9.0 / vSphere 9.0

✅ Full

pyVmomi 8.0.3+ connects against vSphere 9 SOAP API. From VCF 9, pyVmomi is also bundled inside the unified VCF Python SDK.

8.0 / 8.0U1-U3

✅ Full

CreateSnapshot_Task deprecated → use CreateSnapshotEx_Task

7.0 / 7.0U1-U3

✅ Full

All APIs supported

6.7

✅ Compatible

Backward-compatible, tested

6.5

✅ Compatible

Backward-compatible, tested

pyVmomi auto-negotiates the API version during SOAP handshake — no manual configuration needed. The same codebase manages 7.0 / 8.0 / 9.0 / 9.1 environments seamlessly.

Official Broadcom References

Common Workflows

Deploy a Lab Environment

  1. Browse datastore for OVA images → vmware-aiops datastore browse <ds> --pattern "*.ova"

  2. Deploy VM from OVA → vmware-aiops deploy ova ./image.ova --name lab-vm --datastore ds1

  3. Install software inside VM → vmware-aiops vm guest-exec lab-vm --cmd /bin/bash --args "-c 'apt-get install -y nginx'" --user root

  4. Create baseline snapshot → vmware-aiops vm snapshot-create lab-vm --name baseline

  5. Set TTL for auto-cleanup → vmware-aiops vm set-ttl lab-vm --minutes 480

Batch Clone for Testing

  1. Create plan: create_vm_plan with multiple clone + reconfigure steps

  2. Review plan with user (shows affected VMs, irreversible warnings)

  3. Apply: apply_vm_plan executes sequentially, stops on failure

  4. If failed: rollback_vm_plan reverses executed steps

  5. Set TTL on all clones for auto-cleanup

Migrate VM to Another Host

  1. Check VM info via vmware-monitor → verify power state and current host

  2. Migrate: vmware-aiops vm migrate my-vm --to-host esxi-02

  3. Verify migration completed


VM Lifecycle

Operation

Command

Confirmation

vCenter

ESXi

Power On

vm power-on <name>

—

✅

✅

Graceful Shutdown

vm power-off <name>

Double

✅

✅

Force Power Off

vm power-off <name> --force

Double

✅

✅

Reset

plan action reset via create_vm_plan (MCP; no CLI command)

—

✅

✅

Suspend

plan action suspend via create_vm_plan (MCP; no CLI command)

—

✅

✅

Create VM

vm create <name> --cpu --memory --disk

—

✅

✅

Delete VM

vm delete <name>

Double

✅

✅

Reconfigure

vm reconfigure <name> --cpu --memory

Double

✅

✅

Create Snapshot

vm snapshot-create <name> --name <snap>

—

✅

✅

List Snapshots

vm snapshot-list <name>

—

✅

✅

Revert Snapshot

vm snapshot-revert <name> --name <snap>

Double

✅

✅

Delete Snapshot

vm snapshot-delete <name> --name <snap> [--no-wait]

Double

✅

✅

Task Status

vm task-status <task-id>

—

✅

✅

Clone VM

vm clone <name> --new-name <new>

Double

✅

✅

vMotion

vm migrate <name> --to-host <host>

Double

✅

❌

Set TTL

vm set-ttl <name> --minutes <n>

Double

✅

✅

Cancel TTL

vm cancel-ttl <name>

—

✅

✅

List TTLs

vm list-ttl

—

✅

✅

Clean Slate

vm clean-slate <name> [--snapshot baseline]

Double

✅

✅

Guest Exec

vm guest-exec <name> --cmd /bin/bash --args "..." --user <account>

Double

✅

✅

Guest Exec (with output)

MCP only: run_vm_guest_command_with_output (username required) — no CLI command

—

✅

✅

Guest Upload

vm guest-upload <name> --local f.sh --guest /tmp/f.sh --user <account>

Double

✅

✅

Guest Download

vm guest-download <name> --guest /var/log/syslog --local ./syslog --user <account>

—

✅

✅

Guest Operations require VMware Tools running inside the guest OS, and the guest account is always named explicitly — --user on the CLI, username over MCP. There is no default, so no call runs as root without choosing root. run_vm_guest_command_with_output (MCP only; the CLI has no equivalent) auto-detects Linux/Windows shell and captures stdout/stderr.

Plan → Apply (Multi-step Operations)

For complex operations involving 2+ steps or 2+ VMs, use the plan/apply workflow instead of executing individually:

Step

What Happens

1. Create Plan

AI calls create_vm_plan — validates actions, checks targets in vSphere, generates plan with rollback info

2. Review

AI shows plan to user: steps, affected VMs, irreversible warnings

3. Apply

apply_vm_plan previews first; with confirm=True executes sequentially and stops on failure. Each gated step is checked as its own tool checks it; iSCSI/rescan steps are refused (use vmware-storage)

4. Rollback (if failed)

Asks user whether to rollback, then rollback_vm_plan reverses executed steps (irreversible steps skipped); each destructive rollback step is checked first, and a refused check stops the rollback

Plans stored in ~/.vmware-aiops/plans/, auto-deleted on success, auto-cleaned after 24h.

VM Deployment & Provisioning

Operation

Command

Speed

vCenter

ESXi

Deploy from OVA

deploy ova <path> --name <vm>

Minutes

✅

✅

Deploy from Template

deploy template <tmpl> --name <vm>

Minutes

✅

✅

Linked Clone

deploy linked-clone --source <vm> --snapshot <snap> --name <new>

Seconds

✅

✅

Attach ISO

deploy iso <vm> --iso "[ds] path/to.iso"

Instant

✅

✅

Convert to Template

deploy mark-template <vm>

Instant

✅

✅

Batch Clone

deploy batch-clone --source <vm> --count <n>

Minutes

✅

✅

Batch Deploy (YAML)

deploy batch spec.yaml

Auto

✅

✅

Cluster Management

Operation

Command

Confirmation

vCenter

ESXi

Cluster Info

cluster info <name>

—

✅

❌

Create Cluster

cluster create <name> [--ha] [--drs]

—

✅

❌

Delete Cluster

cluster delete <name>

Double

✅

❌

Add Host

cluster add-host <cluster> --host <host>

Double

✅

❌

Remove Host

cluster remove-host <cluster> --host <host>

Double

✅

❌

Configure HA/DRS

cluster configure <name> [--ha/--no-ha] [--drs/--no-drs]

Double

✅

❌

remove-host requires the host to be in maintenance mode first; the host is moved out of the cluster into the datacenter's host folder as a standalone host.

Alarm Management

Operation

Command

Confirmation

vCenter

ESXi

List Triggered Alarms

alarm list [--target <t>]

—

✅

❌

Acknowledge Alarm

alarm acknowledge <entity> <alarm>

—

✅

❌

Clear (Reset) Alarms

alarm reset <entity> <alarm>

Double

✅

❌

Blast radius: vSphere has no per-alarm clear API. alarm reset uses AlarmManager.ClearTriggeredAlarms, which clears all triggered alarms matching the named alarm's entity type (host/VM/all) and current status (red/yellow) — not just the named one. The named alarm is looked up first (typos fail fast), and the output's scope field reports exactly what was cleared. Cleared alarms re-trigger automatically if their underlying condition persists.

Datastore Browser

Feature

vCenter

ESXi

Details

Browse Files

✅

✅

List files/folders in any datastore path

Scan Images

✅

✅

Discover ISO, OVA, OVF, VMDK across all datastores

Scheduled Scanning & Notifications

Feature

Details

Daemon

APScheduler-based, configurable interval (default 15 min)

Multi-target Scan

Sequentially scan all configured vCenter/ESXi targets

Scan Content

Each cycle: triggered alarms, vCenter events from the last lookback_hours, and new lines in the ESXi host logs hostd, vmkernel, vpxa

Host Logs

Read incrementally: each line is reported once per daemon run (a restarted daemon re-reads each log's last 500 lines once). A rotated log, or more than 500 new lines between cycles, adds an info row saying which lines were not scanned. Reading host logs needs the Global.Diagnostics privilege, which vCenter's Read-Only role does not include; a log that cannot be read becomes an info row with the reason, never a silent "all clear"

Log Analysis

Host-log lines matching error, fail, critical, panic, lost access, cannot, timeout, refused, corrupt — lines with critical/panic/corrupt are critical, the rest warning

Structured Log

JSONL output to ~/.vmware-aiops/scan.log — every issue, info rows included

Webhook

Slack, Discord, or any HTTP endpoint. Receives every critical issue and every alarm/event warning; host-log warnings go to the scan log only, and info rows are never sent

Cycle Summary

One line per cycle in the daemon's log output: findings (and how many went to the webhook), unreadable host logs, logs with unscanned lines, failed passes. If any pass failed or a target could not be reached it reads Scan INCOMPLETE, never "all clear"

Daemon Management

daemon start/stop/status, PID file, graceful shutdown

CLI Reference

# Diagnostics
vmware-aiops doctor                   # Check environment, config, connectivity
vmware-aiops doctor --skip-auth       # Skip vSphere auth check (faster)
vmware-aiops access-info [--tool <mcp-tool>] [--target <name>]  # Account in use + privileges per tool

# MCP Config Generator
vmware-aiops mcp-config generate --agent goose        # Generate config for Goose
vmware-aiops mcp-config generate --agent claude-code  # Generate config for Claude Code
vmware-aiops mcp-config list                          # List all supported agents

# VM operations
vmware-aiops vm power-on my-vm                                 # Power on
vmware-aiops vm power-off my-vm                                # Graceful shutdown (2x confirm)
vmware-aiops vm power-off my-vm --force                        # Force power off (2x confirm)
vmware-aiops vm create my-new-vm --cpu 4 --memory 8192 --disk 100  # Create VM
vmware-aiops vm delete my-vm                                   # Delete VM (asks twice; --dry-run previews)
vmware-aiops vm reconfigure my-vm --cpu 4 --memory 8192        # Reconfigure (2x confirm)
vmware-aiops vm snapshot-create my-vm --name "before-upgrade"  # Create snapshot
vmware-aiops vm snapshot-list my-vm                            # List snapshots
vmware-aiops vm snapshot-revert my-vm --name "before-upgrade"  # Revert snapshot
vmware-aiops vm snapshot-delete my-vm --name "before-upgrade"  # Delete snapshot (waits ≤30 min for consolidation)
vmware-aiops vm snapshot-delete my-vm --name "old-big" --no-wait  # Fire async, return a task id
vmware-aiops vm task-status task-1234                          # Poll an async task by id
vmware-aiops vm clone my-vm --new-name my-vm-clone             # Clone VM
vmware-aiops vm migrate my-vm --to-host esxi-02                # vMotion
vmware-aiops vm set-ttl my-vm --minutes 60                     # Auto-delete in 60 min
vmware-aiops vm cancel-ttl my-vm                               # Cancel TTL
vmware-aiops vm list-ttl                                       # Show all TTLs
vmware-aiops vm clean-slate my-vm --snapshot baseline          # Revert to baseline (2x confirm)

# Guest Operations (requires VMware Tools in guest)
vmware-aiops vm guest-exec my-vm --cmd /bin/bash --args "-c 'whoami'" --user root
vmware-aiops vm guest-upload my-vm --local ./script.sh --guest /tmp/script.sh --user root
vmware-aiops vm guest-download my-vm --guest /var/log/syslog --local ./syslog.txt --user root

# Plan → Apply (multi-step operations)
vmware-aiops plan list                                        # List pending/failed plans

# Deploy
vmware-aiops deploy ova ./ubuntu.ova --name my-vm --datastore ds1      # Deploy from OVA
vmware-aiops deploy template golden-ubuntu --name new-vm               # Deploy from template
vmware-aiops deploy linked-clone --source base-vm --snapshot clean --name test-vm  # Linked clone (seconds)
vmware-aiops deploy iso my-vm --iso "[datastore1] iso/ubuntu-22.04.iso"  # Attach ISO
vmware-aiops deploy mark-template golden-vm                            # Convert VM to template
vmware-aiops deploy batch-clone --source base-vm --count 5 --prefix lab  # Batch clone
vmware-aiops deploy batch deploy.yaml                                  # Batch deploy from YAML spec

# Cluster
vmware-aiops cluster info my-cluster                                   # Cluster details (HA/DRS status)
vmware-aiops cluster create my-cluster --ha --drs                      # Create cluster with HA+DRS
vmware-aiops cluster delete my-cluster                                 # Delete cluster (2x confirm)
vmware-aiops cluster add-host my-cluster --host esxi-03                # Add host to cluster (2x confirm)
vmware-aiops cluster remove-host my-cluster --host esxi-03             # Remove host (2x confirm)
vmware-aiops cluster configure my-cluster --ha --drs                   # Configure HA/DRS (2x confirm)

# Alarm management
vmware-aiops alarm list                                                # List triggered alarms
vmware-aiops alarm acknowledge esxi-01 "Host memory usage"             # Acknowledge alarm
vmware-aiops alarm reset esxi-01 "Host memory usage"                   # Clear alarms (2x confirm; clears ALL matching entity type + status)

# Datastore (browse and scan only — iSCSI/vSAN moved to vmware-storage)
vmware-aiops datastore browse datastore1 --path "iso/"                 # Browse datastore
vmware-aiops datastore scan-images --target home-esxi                  # Scan all datastores for images

# Scan
vmware-aiops scan now              # One-time scan of alarms and events (host logs: daemon only)

# Daemon
vmware-aiops daemon start          # Start scanner
vmware-aiops daemon status         # Check status
vmware-aiops daemon stop           # Stop daemon

# Companion skills for other operations:
#   vmware-monitor: inventory, alarms, events, sensors
#   vmware-storage: datastores, iSCSI, vSAN
#   vmware-vks:     Tanzu/TKC cluster lifecycle

API Coverage

Built on pyVmomi (vSphere Web Services API / SOAP).

API Object

Usage

vim.VirtualMachine

VM lifecycle, snapshots, clone, migrate

vim.HostSystem

ESXi host info, sensors, services

vim.Datastore

Storage capacity, type, accessibility

vim.host.DatastoreBrowser

File browsing, image discovery (ISO/OVA/VMDK)

vim.OvfManager

OVA import and deployment

vim.ClusterComputeResource

Cluster, DRS, HA

vim.Network

Network listing

vim.alarm.AlarmManager

Active alarm monitoring

vim.event.EventManager

Event/log queries

Safety and Audit

Safety Features

Feature

Details

Dry-Run Mode (CLI only)

--dry-run prints the exact API call without executing, on every CLI write except deploy iso, deploy mark-template, vm cancel-ttl and vm guest-download

Plan → Confirm → Execute → Log

CLI workflow: show current state, confirm changes, execute, audit log

Double Confirmation (CLI only)

Destructive and deploy CLI commands (vm power-off, delete, reconfigure, snapshot-revert/delete, clone, migrate, set-ttl, clean-slate, guest-exec, guest-upload; deploy ova, template, linked-clone, batch, batch-clone, mark-template; cluster delete, add-host, remove-host, configure, drs-rule-set/create/delete; alarm reset) require 2 sequential prompts and take no bypass flag

Only destructive MCP tools confirm

23 of the 43 write tools an agent sees over MCP — every tool annotated destructive, plus migrate_vm and the network/DRS authoring tools — preview first and need confirm=True; the other 20 (creates, clones, deploys, power-on, reconfigure, snapshot create, host add, template and ISO operations, guest download, plan creation, alarm acknowledge) act on the first call. There is no approval tier and no read-only switch. What decides whether a write lands is the privilege of the vCenter account, and what records it is the audit trail. See What protects you

Rejection Logging

Declined CLI confirmations are recorded in the audit trail

Audit Trail

All operations logged to ~/.vmware-aiops/audit.log (JSONL) with before/after state

Input Validation

VM name, CPU (1-128), memory (128-1048576 MB), disk (1-65536 GB) validated

Password Protection

.env file loading with permission check; never in shell history

SSL Self-signed Support

verify_ssl: false — only for ESXi with self-signed certs in isolated labs; production should use CA-signed certificates

Prompt Injection Protection

vSphere event messages and host logs are truncated, stripped of control characters, and wrapped in boundary markers before output

Webhook Data Scope

Disabled by default. When configured, the daemon posts to your URL only: every critical issue (alarms, events, ESXi log lines matching critical/panic/corrupt, targets it could not connect to) and every alarm/event warning — host-log warnings stay in the scan log, and info rows are never sent. Each issue carries its entity name and message: sanitized alarm, event, or ESXi log text, or a generic connection failure class; operational text can include host names, IP addresses, and user names. No credentials from the skill's config or .env are sent

Task Waiting

All async operations wait for completion and report result

State Validation

Pre-operation checks (VM exists, power state correct)

vCenter vs ESXi Comparison

Capability

vCenter

ESXi Standalone

vMotion migration

✅

❌

Cross-host clone

✅

❌

Cluster management

✅

❌

All VM lifecycle ops

✅

✅

OVA/Template/Linked Clone deploy

✅

✅

Datastore browsing & image scan

✅

✅

Snapshots

✅

✅

Guest operations

✅

✅

Inventory, alarms, events, sensors, host services, and scanning are now in vmware-monitor.

What protects you

The table above lists two different surfaces and it is worth being blunt about which protections apply to which, because getting this wrong is worse than having no protection at all — a guardrail you believe in is one you stop compensating for.

On the CLI, a destructive command asks twice and takes no bypass flag, and --dry-run previews every write except deploy iso, deploy mark-template, vm cancel-ttl and vm guest-download. That defends a mistyped command typed by a human. It does not defend against an agent, which satisfies both prompts with yes |.

Over MCP, every tool annotated destructive, plus migrate_vm and the network/DRS authoring tools — 23 of the 43 write tools, including power_off_vm, migrate_vm, delete_cluster, the snapshot, guest, TTL, Clean Slate and plan tools, and reset_vcenter_alarm — takes one argument, confirm, whose default is a no-write preview: a bare call returns its blast radius and changes nothing. confirm=True re-measures and is refused, with a teaching error audited as a failure, if the preview found a blocker (a VM without running VMware Tools, a target host in maintenance mode, a cluster that still has hosts, a missing or duplicated snapshot) or could not read something. delete_vm also takes the preview's acknowledge_with echoed back, and is refused if the VM changed since, is powered on or suspended. The other 20 write tools — creates, clones, deploys, power-on, reconfigure, snapshot create, host add, template and ISO operations, guest download, plan creation, alarm acknowledge — act on the first call. A confirmation is not authorization, which is why the VMWARE_READ_ONLY switch stays removed (it was enforced on the MCP path only, and any agent with a shell walked around it via the CLI). What the preview buys is narrower: an agent does not destroy something it has not looked at.

What actually decides whether a write lands is the vCenter/ESXi service account. Give the skill an account with the privileges the work needs and no more; vCenter refuses the rest itself, on every surface, with no way around it from inside this skill. To run an agent read-only, give it a read-only vCenter role — one decision, enforced where it is made. Every call is then recorded in ~/.vmware/audit.db before the caller sees a result, which is how you find out what happened. Optional deny rules in ~/.vmware/rules.yaml, checked before every MCP call, can refuse operations — for example, writes to targets labelled environment: production. The shipped baseline denies nothing, and the rules run inside the same process: a guardrail on top of RBAC, not a replacement.

run_vm_guest_command is the one to think hardest about. It runs a caller-supplied command inside the guest OS with the credentials handed to it — its username is required (no default account); nothing bounds what the command may be. The guest account is a separate authorization boundary from the vCenter one — a read-only vCenter role does not constrain what this tool does inside a VM. The skill stores no guest credentials: over MCP they are tool arguments the agent sees (the audit row redacts the password). Pass a least-privilege guest account, and do not hand the agent guest credentials it does not need. upload_vm_guest_file applies Policy host-path checks before reading: protected skill config/credentials, policy/audit/token files, registered TLS files and device/process paths are refused. Over HTTPS, host-file access is disabled unless VMWARE_MCP_FILE_ROOT is set, then limited to that root. Other permitted uploads and guest execution remain sensitive administrative operations.

The full inventory of which tools are gated and which are not is in references/capabilities.md, where the numbers are checked against the live tool registry by the test suite rather than maintained by hand.


Remote access (HTTPS) and limiting tools

By default vmware-aiops mcp speaks stdio to one local client and offers every tool. Two options change that (vmware-policy ≥ 1.21.0).

Serve over HTTPS so clients on other machines can connect. Every caller needs a bearer token:

vmware-audit token create alice          # prints the token once; give it to alice
vmware-audit token list                  # names only
vmware-audit token revoke alice          # refused from its next request, no restart
vmware-aiops mcp --transport https --host 0.0.0.0 --port 8443 \
    --cert /etc/vmware-mcp/server.pem --key /etc/vmware-mcp/server-key.pem \
    --public-name mcp.example.com

Connect a client (Claude Code shown; any MCP client that supports streamable HTTP and custom headers works):

claude mcp add --transport http vmware-aiops https://mcp.example.com:8443/mcp \
    --header "Authorization: Bearer $VMWARE_MCP_TOKEN"
{
  "mcpServers": {
    "vmware-aiops": {
      "type": "http",
      "url": "https://mcp.example.com:8443/mcp",
      "headers": { "Authorization": "Bearer ${VMWARE_MCP_TOKEN}" }
    }
  }
}
  • The server will not start without a token, refuses Host/Origin values outside --public-name, and checks before it binds that unauthenticated requests get 401. Use a certificate your clients trust for those names.

  • Behind a TLS-terminating reverse proxy on the same machine use --transport http --host 127.0.0.1 --public-name mcp.example.com and pass the Authorization header through.

  • Behind a load balancer or gateway on another machine, keep --transport https (a self-signed certificate is fine), list in --public-name the host name the balancer sends as Host, and have it forward Authorization. Its health probe can use GET /healthz, which needs no token and returns only {"status": "ok"} (vmware-policy ≥ 1.23.0).

  • Send traceparent or X-Request-ID with each request to have it stored on the audit row; vmware-audit log --correlation-id ID then finds the calls behind one platform request.

  • Tools that read or write files on this server (here: guest file upload/download, OVA and deployment-spec files) never touch its configuration, tokens, audit log or TLS key, and over the network they are off unless VMWARE_MCP_FILE_ROOT names a directory for them (vmware-policy ≥ 1.23.1).

  • The audit log records each caller as token:<name>. Calls run side by side, with up to VMWARE_MCP_POOL_SIZE (default 2) sessions per target; each session is a login on the target, and a call waits at most 300 s for one.

  • Everyone who can reach the endpoint acts with this server's account. Tokens identify callers; they grant nothing on the platform. Run one endpoint per privilege level.

  • Several people or roles on one endpoint: run vmware-audit roles enable once, then give each token a role (vmware-audit token create NAME --role reader, or a role in roles.yaml naming tools and targets; vmware-policy ≥ 1.24.0). A role limits what the token may call on this endpoint; it cannot grant more than the account has. See vmware-policy's README, "Roles for network callers".

Offer only read tools, plus the writes you choose:

vmware-aiops mcp --expose read --allow-write acknowledge_vcenter_alarm
# or: VMWARE_AIOPS_MCP_EXPOSE=read VMWARE_AIOPS_MCP_ALLOW_WRITE=acknowledge_vcenter_alarm vmware-aiops mcp

Tools not offered do not appear in the client's tool list. A bad value or an unknown write tool stops the server (exit 2). This limits what clients are offered; it is not authorization, so the account itself should be least-privilege.

Details: skills/vmware-aiops/references/setup-guide.md ("Serving MCP over HTTPS", "Limiting which tools are offered").

Troubleshooting

Troubleshooting

"VM not found" error

VM names are case-sensitive in vSphere. Use exact name from vmware-monitor inventory vms.

Guest exec returns empty output

Use run_vm_guest_command_with_output instead of run_vm_guest_command — it auto-captures stdout/stderr. Basic run_vm_guest_command only returns exit code.

Deploy OVA times out

Large OVA files (>10GB) may exceed the default 120s timeout. The upload happens via HTTP NFC lease — ensure network between the machine running vmware-aiops and ESXi is stable.

Plan apply fails mid-way

Run vmware-aiops plan list to see failed plan status. Ask user if they want to rollback with rollback_vm_plan. Irreversible steps (delete_vm) are skipped during rollback.

Connection refused / SSL error

  1. Verify target is reachable: vmware-aiops doctor

  2. For self-signed certs: set verify_ssl: false in config.yaml (lab environments only)

doctor reports "no vSphere role", or every command fails with "session is not authenticated"

The account logs in but has no vSphere role, so vCenter gives it no session (AIops#47). Assign it a role (Read-Only or higher) on the vCenter root folder: Administration > Access Control > Global Permissions. Changing the password will not help. vmware-aiops doctor reports this case by name, and attention counts such a target as unread (overall at least WARN).


Troubleshooting & Contributing

If you encounter any errors or issues, please send the error message, logs, or screenshots to zhouwei008@gmail.com. Contributions are welcome — feel free to join us in maintaining and improving this project!

Companion Skills

The VMware Skills family contains 14 MCP servers and the shared Policy library. Choose tools by responsibility: vmware-skills.

Skill

Scope

Tools

Install

vmware-aiops

VM lifecycle, deployment, guest ops, cluster, datastore browse, triage

49

uv tool install vmware-aiops==2.4.6

vmware-monitor

Read-only monitoring, alarms, events, investigation bundles

27

uv tool install vmware-monitor

vmware-storage

Datastores, iSCSI, vSAN

11

uv tool install vmware-storage

vmware-vks

Tanzu Namespaces, TKC cluster lifecycle

20

uv tool install vmware-vks

vmware-nsx

NSX networking: segments, gateways, NAT, routing, IPAM

33

uv tool install vmware-nsx-mgmt

vmware-nsx-security

DFW policies/rules, security groups, Traceflow, IDS/IPS

21

uv tool install vmware-nsx-security

vmware-aria

Aria Operations metrics, alerts, capacity, anomalies

28

uv tool install vmware-aria

vmware-avi

AVI (NSX ALB) load balancing, AKO Kubernetes ops

28

uv tool install vmware-avi

vmware-harden

Compliance baselines (CIS / vSphere SCG / 等保 / PCI-DSS), drift detection

6

uv tool install vmware-harden


Reference

Release history: RELEASE_NOTES.md.

Read-only self-test with your own model and agent host: model-fit self-test.

Upgrading to 2.0

2.0 renames 38 of its MCP tools so every name starts with a verb (e.g. cluster_add_host → add_cluster_host, cluster_configure → configure_cluster, cluster_create → create_cluster). The full old → new table is in RELEASE_NOTES.md. Nothing else changes: same tools, parameters, safety gates and CLI commands. If an agent prompt, script or ~/.vmware/rules.yaml names a tool, update it (but not the action words in saved plan files — cluster_add_host, storage_rescan and the like are plan actions, not tool names, and keep their spelling) — though deny rules written with the old names keep working with vmware-policy ≥ 1.18 (vmware-audit policy lists any rule the renames widened), and vmware-pilot ≥ 1.13 translates old names in saved workflows. If an install older than 2.0 shares that rules.yaml, give it vmware-policy ≥ 1.18.2 too: it matches each rule against both the old and the new name, so one file serves both.

Why this over other VMware MCP servers

Most open-source VMware MCP servers (e.g. bright8192/esxi-mcp-server, giuliolibrando/vmware-vsphere-mcp-server) are single-vCenter VM wrappers: list/power/snapshot a VM, basic monitoring, a confirm=True flag. They explicitly do not cover networking, storage, Kubernetes, ops analytics, load balancing, or compliance — and "logging is documented" is not an audit trail.

This is one skill in an 14-server family with a shared Policy library that covers the whole estate and runs every tool through a governed harness:

Other VMware MCP servers

This family

VM lifecycle + monitoring

✅

✅

NSX networking (segments/gateways/NAT/routing/IPAM)

❌

✅ vmware-nsx

NSX security (DFW/groups/IDS-IPS/traceflow)

❌

✅ vmware-nsx-security

Storage (datastore/iSCSI/vSAN)

❌

✅ vmware-storage

Tanzu Kubernetes (Supervisor/Namespace/TKC)

❌

✅ vmware-vks

Aria Operations (metrics/alerts/capacity)

❌

✅ vmware-aria

AVI / NSX ALB load balancing + AKO

❌

✅ vmware-avi

Compliance baselines + drift (CIS/SCG/等保/PCI)

❌

✅ vmware-harden

Governed harness (unified audit, policy engine, token budget + runaway breaker, graduated risk tiers, undo-token, prompt-injection sanitize)

❌

✅ vmware-policy on every tool

If you only ever power-cycle VMs in one vCenter, a single-file server is fine. If you run a real (regulated, NSX-segmented, multi-domain) VMware estate and need an AI operator an auditor can sign off on, that's what this family is for — see docs/compliance-ready.md.

Supported AI Platforms

Platform

Status

Config File

AI Model

Claude Code

✅ Native Skill

skills/vmware-aiops/SKILL.md

Anthropic Claude

Gemini CLI

✅ Context file + MCP

skills/vmware-aiops/SKILL.md

Google Gemini

OpenAI Codex CLI

✅ Skill + AGENTS.md

skills/vmware-aiops/SKILL.md

OpenAI GPT

Aider

✅ Conventions

skills/vmware-aiops/SKILL.md

Any (cloud + local)

Continue CLI

✅ Rules

skills/vmware-aiops/SKILL.md

Any (cloud + local)

Trae IDE

✅ Rules

skills/vmware-aiops/SKILL.md

Claude/DeepSeek/GPT-4o/Doubao

Kimi Code CLI

✅ Skill

skills/vmware-aiops/SKILL.md

Moonshot Kimi

MCP Server

✅ MCP Protocol

vmware_aiops/mcp_server/

Any MCP client

Python CLI

✅ Standalone

N/A

N/A

Platform Comparison

Feature

Claude Code

Gemini CLI

Codex CLI

Aider

Continue

Trae IDE

Kimi CLI

Cloud AI

Anthropic

Google

OpenAI

Any

Any

Multi

Moonshot

Local models

—

—

—

Ollama

Ollama

—

—

Skill system

SKILL.md

Context file

SKILL.md

—

Rules

Rules

SKILL.md

MCP support

Native

Native

Via Skills

Third-party

Native

—

—

Free tier

—

60 req/min

—

Self-hosted

Self-hosted

—

—

MCP Server Integrations

The vmware-aiops MCP server works with any MCP-compatible agent or tool. Ready-to-use configuration templates are in examples/mcp-configs/.

Agent / Tool

Local Model Support

Config Template

Integration Guide

Xiaoguai (小怪)

✅ Self-hosted, any LLM

MCP setup

Guide

Goose

✅ Ollama, LM Studio

goose.json

Guide

LocalCowork

✅ Fully offline

localcowork.json

Guide

mcp-agent

✅ Ollama, vLLM

mcp-agent.yaml

Guide

VS Code Copilot

—

vscode-copilot.json

Guide

Cursor

—

cursor.json

Guide

Continue

✅ Ollama

continue.yaml

Guide

Claude Code

—

claude-code.json

—

Xiaoguai (小怪) — a self-hostable, audit-first agent platform (Rust, single binary + embedded SQLite) from the same maintainer. It runs the vmware-aiops MCP server as one of its toolboxes; being both an MCP consumer and an MCP server, its HMAC-chained audit log and human-on-the-loop approval gates line up with this skill's own audit + confirm design. See its MCP integration guide.

Fully local operation (no cloud API required):

# Aider + Ollama + vmware-aiops (via SKILL.md)
aider --conventions skills/vmware-aiops/SKILL.md --model ollama/qwen2.5-coder:32b

# Any MCP agent + local model + vmware-aiops MCP server
# See examples/mcp-configs/ for your agent's config format

Update / Upgrade

Already installed? Re-run the install command for your channel to get the latest version:

Install Channel

Update Command

ClawHub

clawhub install @zw008/vmware-aiops --version 2.4.6

Skills.sh

npx skills@1.7.6 add vmware-skills/VMware-AIops#v2.4.6

Git clone

cd VMware-AIops && git pull origin main && uv pip install --no-sources -e . (without --no-sources, uv looks for a sibling ../VMware-Monitor checkout)

uv

uv tool install vmware-aiops==2.4.6 --force

Check your current version: vmware-aiops --version


Chinese Cloud Models

For users in China who prefer domestic cloud APIs or have limited access to overseas services.

DeepSeek

Cost-effective, strong coding capability.

# Set DeepSeek API key (get from https://platform.deepseek.com)
export DEEPSEEK_API_KEY="your-key"

# Run with Aider
aider --conventions skills/vmware-aiops/SKILL.md \
  --model deepseek/deepseek-coder

Persistent config ~/.aider.conf.yml:

model: deepseek/deepseek-coder
conventions: skills/vmware-aiops/SKILL.md

Qwen (Alibaba Cloud)

Alibaba Cloud's coding model, free tier available.

# Set DashScope API key (get from https://dashscope.console.aliyun.com)
export DASHSCOPE_API_KEY="your-key"

aider --conventions skills/vmware-aiops/SKILL.md \
  --model qwen/qwen-coder-plus

Or via OpenAI-compatible endpoint:

export OPENAI_API_BASE="https://dashscope.aliyuncs.com/compatible-mode/v1"
export OPENAI_API_KEY="your-dashscope-key"

aider --conventions skills/vmware-aiops/SKILL.md \
  --model qwen-coder-plus-latest

Doubao (ByteDance)

export OPENAI_API_BASE="https://ark.cn-beijing.volces.com/api/v3"
export OPENAI_API_KEY="your-ark-key"

aider --conventions skills/vmware-aiops/SKILL.md \
  --model your-doubao-endpoint-id

With Continue CLI

Configure ~/.continue/config.yaml:

# DeepSeek
models:
  - name: deepseek-coder
    provider: openai-compatible
    apiBase: https://api.deepseek.com/v1
    apiKey: your-deepseek-key
    model: deepseek-coder

# Qwen
models:
  - name: qwen-coder
    provider: openai-compatible
    apiBase: https://dashscope.aliyuncs.com/compatible-mode/v1
    apiKey: your-dashscope-key
    model: qwen-coder-plus-latest

Local Models (Aider + Ollama)

For fully offline operation — no cloud API, no internet, full privacy.

Aider + Ollama + local Qwen/DeepSeek is ideal for air-gapped environments.

Step 1: Install Ollama

# macOS
brew install ollama

# Linux — download from https://ollama.com/download and install manually
# See https://github.com/ollama/ollama for platform-specific instructions

Step 2: Pull a model

Model

Command

Size

Note

Qwen 2.5 Coder 32B

ollama pull qwen2.5-coder:32b

~20GB

Best local coding model

Qwen 2.5 Coder 7B

ollama pull qwen2.5-coder:7b

~4.5GB

Low-memory option

DeepSeek Coder V2

ollama pull deepseek-coder-v2

~8.9GB

Strong reasoning

CodeLlama 34B

ollama pull codellama:34b

~19GB

Meta coding model

Hardware: 32B → ~20GB VRAM (or 32GB RAM for CPU). 7B → 8GB RAM.

Step 3: Run with Aider

pip install aider-chat
ollama serve

# Aider + local Qwen (recommended)
aider --conventions skills/vmware-aiops/SKILL.md \
  --model ollama/qwen2.5-coder:32b

# Aider + local DeepSeek
aider --conventions skills/vmware-aiops/SKILL.md \
  --model ollama/deepseek-coder-v2

# Low-memory option
aider --conventions skills/vmware-aiops/SKILL.md \
  --model ollama/qwen2.5-coder:7b

Persistent config ~/.aider.conf.yml:

model: ollama/qwen2.5-coder:32b
conventions: skills/vmware-aiops/SKILL.md

Local Architecture

User → Aider CLI → Ollama (localhost:11434) → Qwen / DeepSeek local model
  │                                                    ↓
  │                                          reads AGENTS.md instructions
  │                                                    ↓
  └──────────────────────────────→ vmware-aiops CLI ──→ ESXi / vCenter

Tip: Local models are fully offline — perfect for air-gapped environments or strict data compliance.


Project Structure

VMware-AIops/
├── skills/                        # Skills index (npx skills add)
│   └── vmware-aiops/
│       ├── SKILL.md               # Slimmed-down skill (progressive disclosure)
│       └── references/            # Detailed docs loaded on-demand
│           ├── capabilities.md    # Full capabilities tables
│           ├── cli-reference.md   # Complete CLI reference
│           └── setup-guide.md     # Install, security, AI platforms
├── vmware_aiops/                  # Python backend
│   ├── config.py                  # YAML + .env config
│   ├── connection.py              # Multi-target pyVmomi
│   ├── cli/                       # Typer CLI (double confirm)
│   ├── ops/                       # Operations
│   │   ├── inventory.py           # VMs, hosts, datastores, clusters
│   │   ├── health.py              # Alarms, events, sensors
│   │   ├── vm_lifecycle.py        # VM CRUD, snapshots, clone, migrate
│   │   ├── vm_deploy.py           # OVA, template, linked clone, batch deploy
│   │   └── datastore_browser.py   # Datastore browsing, image discovery
│   ├── scanner/                   # Log scanning daemon
│   ├── notify/                    # Notifications (JSONL + webhook)
│   └── mcp_server/                # MCP server wrapper
│       ├── server.py              # FastMCP server with tools
│       └── __main__.py
├── examples/mcp-configs/          # MCP client config templates
├── tests/                         # Test suite
├── smithery.yaml                  # Smithery marketplace config
├── RELEASE_NOTES.md
├── config.example.yaml
└── pyproject.toml

License

MIT

Available Tools

44 tools
acknowledge_vcenter_alarmA

[WRITE] Acknowledge a triggered vCenter alarm — marks it as seen WITHOUT clearing it.

The alarm stays in the active list with acknowledged=true until its condition clears or it is reset. To remove the alarm entirely after fixing the root cause, use reset_vcenter_alarm instead. Get exact entity_name and alarm_name values from list_vcenter_alarms first; an unknown pair returns a not-found error. Audited to ~/.vmware/audit.db.

Args: entity_name: Name of the VM, ESXi host, or cluster the alarm fired on (from list_vcenter_alarms output). alarm_name: Exact alarm definition name, e.g. "Virtual machine CPU usage". target: vCenter target name from config.yaml; omit to use the default target.

Returns: Dict: entity_name, alarm_name, action ("acknowledged"), acknowledged (true).

Inputs: alarm_name (required), entity_name (required), target.

attach_iso_to_vmA

[WRITE] Mount a datastore ISO into a VM's virtual CD-ROM drive.

Reconfigures the existing CD-ROM (replacing any currently mounted ISO) or adds a new CD-ROM on the VM's IDE controller if none exists; fails with a clear message if the VM has no IDE controller. Works whether the VM is powered on or off — the device is set connected and start-connected. Find ISO files first with browse_datastore using pattern "*.iso". Audited to ~/.vmware/audit.db.

Args: vm_name: Exact VM name as shown in vCenter inventory. iso_ds_path: Full datastore path in bracket format, e.g. "[datastore1] iso/ubuntu-22.04.iso" (datastore name in brackets, then the path relative to the datastore root). target: vCenter/ESXi target name from config.yaml; omit to use the default target.

Returns: Status string confirming attachment, or a VM-not-found / no-IDE-controller error.

Inputs: vm_name (required), iso_ds_path (required), target. Returns: result

batch_clone_vmsA

[WRITE] Batch clone multiple VMs from a source VM (gold image).

Each clone: full copy → optional reconfigure → optional snapshot → optional power on.

Args: source_vm_name: Source VM to clone from. vm_names: List of names for the new VMs. cpu: Override CPU count for all clones (optional). memory_mb: Override memory for all clones (optional). snapshot_name: Create a baseline snapshot on each clone (optional). power_on: Power on each clone after creation. target: Optional vCenter/ESXi target name from config.

Inputs: vm_names (required), source_vm_name (required), cpu, target, +3 more. Returns: result

batch_deploy_from_specA

[WRITE] Deploy multiple VMs in one call from a declarative YAML spec file.

Use for fleet provisioning (several VMs, shared defaults); for a single VM prefer deploy_vm_from_template, vm_clone, deploy_vm_from_ova, or deploy_linked_clone. The provisioning channel is chosen by spec keys: top-level "source" (full clone), "template", "linked_clone: {source, snapshot}", per-VM "ova", else empty-VM creation (optionally with "iso"). A "defaults" block sets cpu/memory_mb/disk_gb/network/ datastore/snapshot/power_on, overridable per VM. VMs deploy sequentially; one VM's failure is recorded and the rest continue. Audited to ~/.vmware/audit.db.

Args: spec_path: Local filesystem path to the deploy.yaml specification file. target: vCenter/ESXi target name from config.yaml; omit to use the default target.

Returns: One dict per VM: name, status ("ok" or "error"), and messages with per-step results.

Inputs: spec_path (required), target. Returns: result

batch_linked_clone_vmsA

[WRITE] Batch create linked clones from a VM snapshot (fastest batch provisioning).

Each clone shares the source disk via copy-on-write.

Args: source_vm_name: Source VM to clone from. snapshot_name: Snapshot to use as clone base. vm_names: List of names for the new linked clones. cpu: Override CPU count (optional). memory_mb: Override memory (optional). power_on: Power on each clone. baseline_snapshot: Create a new snapshot on each clone (optional). target: Optional vCenter/ESXi target name from config.

Inputs: vm_names (required), snapshot_name (required), source_vm_name (required), cpu, +4 more. Returns: result

browse_datastoreA
Read-onlyIdempotent

[READ] Browse files in a vSphere datastore directory.

Use this to discover OVA, ISO, VMDK, and other files on datastores before deploying VMs.

Args: datastore_name: Name of the datastore to browse. path: Subdirectory path (empty string for root). pattern: Glob pattern to filter files (e.g. ".ova", ".iso", "*"). target: Optional vCenter/ESXi target name from config.

Inputs: datastore_name (required), path, target, pattern. Returns: result

cluster_add_hostA

[WRITE] Move an ESXi host that vCenter already manages into a cluster.

The host must already be in vCenter inventory (standalone or in another cluster) — this tool does NOT register brand-new hosts and takes no host credentials; use the vCenter UI for first-time host registration. Idempotent: a host already in the cluster returns success without change. Maintenance mode is not required to join (it IS required by cluster_remove_host). Check membership with cluster_info. Audited to ~/.vmware/audit.db.

Args: cluster_name: Existing destination cluster name (create with cluster_create). host_name: Host name exactly as shown in vCenter inventory, typically the FQDN, e.g. "esxi-01.lab.local". target: vCenter target name from config.yaml; omit to use the default target.

Returns: Status string: moved, already-in-cluster, or host/cluster-not-found error.

Inputs: host_name (required), cluster_name (required), target. Returns: result

cluster_configureA

[WRITE] Reconfigure cluster HA/DRS settings.

Args: name: Cluster name. ha: Enable (True) or disable (False) HA, or None to leave unchanged. drs: Enable (True) or disable (False) DRS, or None to leave unchanged. drs_behavior: DRS behavior: "fullyAutomated", "partiallyAutomated", or "manual". target: Optional vCenter target name from config.

Inputs: name (required), ha, drs, target, +1 more. Returns: result

cluster_createA

[WRITE] Create a new empty cluster in a datacenter, optionally enabling HA and DRS.

Fails with a clear error (no partial state) if a cluster with that name already exists or drs_behavior is invalid. After creation, add hosts with cluster_add_host; change HA/DRS later with cluster_configure; verify with cluster_info. Audited to ~/.vmware/audit.db.

Args: name: Name for the new cluster; must be unique in the datacenter. datacenter: Datacenter name; omit to use the first datacenter on the target. ha: True enables vSphere HA (default False). drs: True enables DRS (default False). drs_behavior: "fullyAutomated" (default), "partiallyAutomated", or "manual". Only takes effect when drs=True. target: vCenter target name from config.yaml; omit to use the default target.

Returns: Status string confirming creation and which features (HA/DRS) were enabled.

Inputs: name (required), ha, drs, target, +2 more. Returns: result

cluster_deleteA
Destructive

[WRITE] Delete an empty cluster (no hosts must remain).

Args: name: Name of the cluster to delete. target: Optional vCenter target name from config.

Inputs: name (required), target. Returns: result

cluster_infoA
Read-onlyIdempotent

[READ] Get detailed cluster information: member hosts, HA/DRS config, resource capacity.

Read-only, no side effects. Use before cluster_add_host / cluster_remove_host (shows membership and per-host maintenance mode) and to verify cluster_configure changes.

Args: name: Exact cluster name. target: vCenter target name from config.yaml; omit to use the default target.

Returns: Dict with name, host_count, hosts (each: name, connection_state, power_state, maintenance_mode), ha_enabled, ha_admission_control, drs_enabled, drs_behavior, total/effective CPU (MHz) and memory (GB). Errors return a dict with "error" + hint.

Inputs: name (required), target.

cluster_remove_hostA
Destructive

[WRITE] Remove a host from a cluster (host must be in maintenance mode).

Args: cluster_name: Cluster to remove the host from. host_name: ESXi host name to remove. target: Optional vCenter target name from config.

Inputs: host_name (required), cluster_name (required), target. Returns: result

convert_vm_to_templateA

[WRITE] Convert a powered-off VM to a vSphere template.

After conversion the VM cannot be powered on — it serves as a clone source for deploy_vm_from_template.

Args: vm_name: Name of the VM to convert (must be powered off). target: Optional vCenter/ESXi target name from config.

Inputs: vm_name (required), target. Returns: result

deploy_linked_cloneA

[WRITE] Create a linked clone from a VM snapshot — near-instant, minimal disk usage.

The clone shares the source's base disk and writes changes to a copy-on-write delta disk, so it depends on the source VM staying intact. Fastest provisioning method for test/dev fleets; use vm_clone or deploy_vm_from_template for fully independent copies. Requires the source VM to have the named snapshot — run vm_list_snapshots first; unknown names return the available list. Audited to ~/.vmware/audit.db.

Args: source_vm_name: Exact name of the source VM (must have at least one snapshot). snapshot_name: Snapshot on the source to use as the clone base (from vm_list_snapshots). new_name: Name for the new linked clone; must not already exist. cpu: Override vCPU count; omit to keep the source's value. memory_mb: Override memory in MB; omit to keep the source's value. power_on: True powers the clone on after creation (default False). baseline_snapshot: If set, creates a snapshot with this name on the new clone. target: vCenter/ESXi target name from config.yaml; omit to use the default target.

Returns: Status string with the new clone name, or a snapshot/VM-not-found error.

Inputs: new_name (required), snapshot_name (required), source_vm_name (required), cpu, +4 more. Returns: result

deploy_vm_from_ovaA

[WRITE] Create a new VM by importing a local .ova file (OVF parse + VMDK upload).

Use for OVA appliance files on the local machine. For vSphere templates use deploy_vm_from_template; to copy an existing VM use vm_clone or deploy_linked_clone. Upload time scales with OVA size. Fails before creating anything if the datastore is not found. Audited to ~/.vmware/audit.db.

Args: ova_path: Local filesystem path to the .ova file (must be readable by this server). vm_name: Name for the new VM; must not already exist. datastore_name: Target datastore name; discover with browse_datastore. network_name: Port group for the VM's NICs (default "VM Network"). folder_path: vCenter VM folder path; omit to use the datacenter's root VM folder. power_on: True powers the VM on after import (default False). snapshot_name: If set, creates a baseline snapshot with this name after deploy. target: vCenter/ESXi target name from config.yaml; omit to use the default target.

Returns: Status string with the deployed VM name, or an error naming the missing resource.

Inputs: vm_name (required), ova_path (required), datastore_name (required), target, +4 more. Returns: result

deploy_vm_from_templateA

[WRITE] Deploy a new VM by cloning from a vSphere template.

Args: template_name: Name of the source vSphere template. new_name: Name for the new VM. datastore_name: Target datastore (uses template's datastore if omitted). cpu: Override CPU count (optional). memory_mb: Override memory in MB (optional). power_on: Power on after deployment. snapshot_name: Create a baseline snapshot with this name (optional). target: Optional vCenter/ESXi target name from config.

Inputs: new_name (required), template_name (required), cpu, target, +4 more. Returns: result

list_vcenter_alarmsA
Read-onlyIdempotent

[READ] List active/triggered alarms across the vCenter inventory.

Returns alarms with severity (critical/warning/info), entity name and type, alarm name, acknowledged flag, and trigger time.

Args: target: Optional vCenter target name from config. Uses default if omitted. limit: Max number of alarms to return (None = all). Use when many alarms are active.

Inputs: limit, target. Returns: result

reset_vcenter_alarmA

[WRITE] Clear triggered vCenter alarms back to normal state.

Uses AlarmManager.ClearTriggeredAlarms. The named alarm no longer appears in the active alarm list. Use this after resolving the underlying issue. Use list_vcenter_alarms to find entity_name and alarm_name values.

Gotcha: vSphere has no per-alarm clear — this clears ALL triggered alarms matching the named alarm's entity type (host/VM/all) and current status (red/yellow). The response's 'scope' field states exactly what was cleared.

Args: entity_name: Name of the entity with the alarm (VM name, host name, or cluster name). alarm_name: Exact alarm definition name from list_vcenter_alarms output. target: Optional vCenter target name from config.

Inputs: alarm_name (required), entity_name (required), target.

scan_datastore_imagesA
Read-onlyIdempotent

[READ] Scan all accessible datastores for deployable images (OVA/ISO/OVF/VMDK).

Results are cached locally in ~/.vmware-aiops/image_registry.json for fast lookup via list_cached_images. Run this to refresh the cache.

Args: target: Optional vCenter/ESXi target name from config.

Inputs: target.

vm_apply_planA

[WRITE] Execute a previously created plan step by step.

Steps run sequentially. On failure: stops immediately, keeps the plan file with per-step results, and returns rollback_available flag. On success: deletes the plan file.

If a step fails and rollback_available is true, ask the user whether to rollback, then call vm_rollback_plan if confirmed.

Args: plan_id: The plan ID returned by vm_create_plan. target: Optional vCenter/ESXi target name from config.

Inputs: plan_id (required), target.

vm_cancel_ttlA
Destructive

[WRITE] Cancel an existing TTL for a VM (prevents auto-deletion).

Args: vm_name: Name of the VM whose TTL should be cancelled.

Inputs: vm_name (required). Returns: result

vm_clean_slateA
Destructive

[WRITE] Revert a VM to its baseline snapshot (Clean Slate).

Powers off the VM first if it is running, then reverts to the named snapshot. Use this to reset a lab/dev VM to a clean starting state after a task completes.

Args: vm_name: Name of the VM to revert. snapshot_name: Snapshot name to revert to (default: "baseline"). target: Optional vCenter/ESXi target name from config.

Inputs: vm_name (required), target, snapshot_name. Returns: result

vm_cloneA

[WRITE] Clone a VM. Without to_host/to_datastore the clone lands on the source's host+datastore.

Args: vm_name: Source VM (or template) name. new_name: Name for the new clone. to_host: Target ESXi host name (default: source's host). to_datastore: Target datastore name (default: source's datastore). power_on: Power on the clone after creation. target: vCenter/ESXi target name from config.

Inputs: vm_name (required), new_name (required), target, to_host, +2 more. Returns: result

vm_createA

[WRITE] Create a new empty VM with the given hardware sizing.

Creates a powered-off VM with one disk and one NIC. To populate it, attach an ISO (attach_iso_to_vm) and power it on, or use deploy_vm_from_ova / deploy_vm_from_template / vm_clone for a ready-to-run guest. Fails before creating anything if the datastore is not found. Audited to ~/.vmware/audit.db.

Args: vm_name: Name for the new VM; must not already exist. cpu: vCPU count (default 2). memory_mb: Memory in MB (default 4096). disk_gb: Primary disk size in GB (default 40). network_name: Port group for the VM's NIC (default "VM Network"). datastore_name: Target datastore name; omit to use the first accessible datastore. folder_path: vCenter VM folder path; omit to use the datacenter's root VM folder. target: vCenter/ESXi target name from config.yaml; omit to use the default target.

Returns: Status string with the new VM name, or an error naming the missing resource.

Inputs: vm_name (required), cpu, target, disk_gb, +4 more. Returns: result

vm_create_planA

[WRITE] Create an execution plan for multi-step VM operations.

Auto-triggered when operations involve 2+ steps or 2+ VMs. Validates actions, checks target existence in vSphere, and generates a plan with rollback info for each step.

Each operation is a dict with "action" key plus action-specific params. Allowed actions: power_on, power_off, reset, suspend, create_vm, delete_vm, reconfigure, create_snapshot, delete_snapshot, revert_snapshot, clone, migrate, deploy_ova, deploy_template, linked_clone, attach_iso, convert_to_template.

Example: operations=[ {"action": "power_off", "vm_name": "test-1"}, {"action": "revert_snapshot", "vm_name": "test-1", "snapshot_name": "baseline"}, {"action": "power_on", "vm_name": "test-1"} ]

Returns plan dict with plan_id, steps, summary (vms_affected, irreversible_steps, rollback_available). Show to user for confirmation before calling vm_apply_plan.

Args: operations: List of operation dicts, each with "action" + params. target: Optional vCenter/ESXi target name from config.

Inputs: operations (required), target.

vm_create_snapshotA
Idempotent

[WRITE] Create a snapshot of a VM.

Args: vm_name: VM to snapshot. snapshot_name: Snapshot name. description: Optional description. memory: Include memory state (heavier, allows resume). quiesce: Quiesce guest filesystem (requires running VMware Tools). target: vCenter/ESXi target name from config.

Inputs: vm_name (required), snapshot_name (required), memory, target, +2 more. Returns: result

vm_deleteA
Destructive

[WRITE] Delete a VM (irreversible). VM must be powered off.

Args: vm_name: VM to delete. Must be powered off. target: vCenter/ESXi target name from config.

Inputs: vm_name (required), target. Returns: result

vm_delete_snapshotA
Destructive

[WRITE] Permanently delete a named snapshot, consolidating its delta disk into the parent.

Frees disk space and does NOT change the VM's current state (unlike vm_revert_snapshot, which discards changes since the snapshot). Works while the VM is powered on. Run vm_list_snapshots first for exact names — unknown names return the available list. Irreversible: confirm with the user before calling. Audited to ~/.vmware/audit.db.

Snapshot consolidation is slow for old/large delta disks (often minutes). By default (wait=False) this fires the delete and returns a task id immediately so it does not block your context — poll completion with vm_task_status. Set wait=True only for small snapshots where you want the final confirmation inline (blocks up to 30 min, then returns the task id).

Args: vm_name: Exact name of the VM owning the snapshot. snapshot_name: Exact snapshot name from vm_list_snapshots output. remove_children: False (default) = children are kept and consolidated; True = delete the entire snapshot subtree below this one as well. wait: False (default) = async, return task id immediately; True = block on consolidation. target: vCenter/ESXi target name from config.yaml; omit to use the default target.

Returns: Status string with a task id (poll via vm_task_status), or a not-found message.

Inputs: vm_name (required), snapshot_name (required), wait, target, +1 more. Returns: result

vm_guest_downloadA
Read-onlyIdempotent

[READ] Download a file from a VM to local machine via VMware Tools.

Requires VMware Tools running in the guest OS.

Args: vm_name: Target VM name. guest_path: File path inside the guest to download. local_path: Local destination path. username: Guest OS username (default "root"). password: Guest OS password. target: Optional vCenter/ESXi target name from config.

Inputs: vm_name (required), guest_path (required), local_path (required), target, +2 more. Returns: result

vm_guest_execA

[WRITE] Execute a command inside a VM via VMware Tools.

Requires VMware Tools running in the guest OS. Returns exit_code, stdout, stderr, and timed_out flag.

Note: VMware Guest Ops API does not capture stdout/stderr directly. To capture output, redirect to a file and use vm_guest_download: command="/bin/bash", arguments="-c 'ls -la /tmp > /tmp/output.txt'" Then download /tmp/output.txt.

Args: vm_name: Target VM name. command: Full path to program (e.g. "/bin/bash", "C:\Windows\System32\cmd.exe"). arguments: Command arguments (e.g. "-c 'whoami'"). username: Guest OS username (default "root"). password: Guest OS password. working_directory: Working directory inside guest (optional). target: Optional vCenter/ESXi target name from config.

Inputs: command (required), vm_name (required), target, password, +3 more.

vm_guest_exec_outputA

[WRITE] Execute a shell command inside a VM and capture stdout + stderr.

Automatically detects guest OS (Linux/Windows) and selects the correct shell. Output is captured by redirecting to a temp file, downloading it, then cleaning up — no manual redirection needed.

Returns exit_code, stdout, stderr, timed_out, os_family.

Args: vm_name: Target VM name. command: Shell command (e.g. "df -h", "ls /etc", "ipconfig"). username: Guest OS username (default "root"). password: Guest OS password. timeout: Max wait seconds (default 300). target: Optional vCenter/ESXi target name from config.

Inputs: command (required), vm_name (required), target, timeout, +2 more.

vm_guest_provisionA

[WRITE] Provision a VM by running a sequence of guest operations (exec / upload / service).

Combines key injection, software installation, and service startup into a single call. Steps execute in order; stops on first failure.

Step types:

  • exec: {"type": "exec", "command": "apt-get install -y nginx"}

  • upload: {"type": "upload", "local_path": "/tmp/id_rsa.pub", "guest_path": "/root/.ssh/authorized_keys"}

  • service: {"type": "service", "name": "nginx", "action": "start"}

Args: vm_name: Target VM name. username: Guest OS username. password: Guest OS password. steps: Ordered list of step dicts. timeout: Per-step timeout in seconds (default 300). target: Optional vCenter/ESXi target name from config.

Returns: dict with success, completed_steps, total_steps, results, error.

Example: steps = [ {"type": "upload", "local_path": "~/.ssh/id_rsa.pub", "guest_path": "/root/.ssh/authorized_keys"}, {"type": "exec", "command": "chmod 600 /root/.ssh/authorized_keys"}, {"type": "exec", "command": "apt-get install -y nginx"}, {"type": "service", "name": "nginx", "action": "enable"}, {"type": "service", "name": "nginx", "action": "start"}, ]

Inputs: steps (required), vm_name (required), password (required), username (required), +2 more.

vm_guest_uploadA

[WRITE] Upload a file from local machine to a VM via VMware Tools.

Requires VMware Tools running in the guest OS.

Args: vm_name: Target VM name. local_path: Local file path to upload. guest_path: Destination path inside the guest. username: Guest OS username (default "root"). password: Guest OS password. target: Optional vCenter/ESXi target name from config.

Inputs: vm_name (required), guest_path (required), local_path (required), target, +2 more. Returns: result

vm_list_plansA
Read-onlyIdempotent

[READ] List all pending/failed plans.

Returns plan summaries (plan_id, created_at, status, steps count, VMs affected). Stale plans (>24h) are auto-cleaned.

Inputs: no named parameters. Returns: result

vm_list_snapshotsA
Read-onlyIdempotent

[READ] List the full snapshot tree of a VM, including nested child snapshots.

Read-only, no side effects. Call this before vm_revert_snapshot, vm_delete_snapshot, or deploy_linked_clone to get exact snapshot names. Returns an empty list when the VM has no snapshots.

Args: vm_name: Exact VM name as shown in vCenter inventory. target: vCenter/ESXi target name from config.yaml; omit to use the default target.

Returns: One dict per snapshot: name, description, created (timestamp), state (poweredOn/poweredOff at snapshot time), level (0 = root, higher = nesting depth). No pagination — snapshot trees are small.

Inputs: vm_name (required), target. Returns: result

vm_list_ttlA
Read-onlyIdempotent

[READ] List all VMs with TTLs registered, including expiry time and status.

Returns a list of TTL entries with remaining_minutes and expired flag.

Inputs: no named parameters. Returns: result

vm_migrateA

[WRITE] Migrate (vMotion) a VM to another host, optionally with storage vMotion.

If the target host has no access to the VM's current datastore, you MUST pass to_datastore — vCenter rejects cross-host vMotion without shared storage.

Args: vm_name: VM to migrate. to_host: Target ESXi host name. to_datastore: Target datastore (required for cross-storage hosts). target: vCenter/ESXi target name from config.

Inputs: to_host (required), vm_name (required), target, to_datastore. Returns: result

vm_power_offA
Destructive

[WRITE] Power off a VM — graceful guest shutdown by default, hard power-off with force=True.

Graceful mode calls VMware Tools guest shutdown and waits up to 120s; if Tools is not running or shutdown stalls, the response tells you to retry with force=True. An already-off VM returns success without change. Audited to ~/.vmware/audit.db. Use vm_power_on to start a VM; vm_delete requires the VM to be off first.

Args: vm_name: Exact VM name as shown in vCenter inventory (case-sensitive). force: False (default) = graceful guest shutdown via VMware Tools; True = immediate hard power-off (risks guest filesystem damage). target: vCenter/ESXi target name from config.yaml; omit to use the default target.

Returns: Status string: shut down, force powered off, already off, or a Tools-unavailable hint.

Inputs: vm_name (required), force, target. Returns: result

vm_power_onA
Idempotent

[WRITE] Power on a virtual machine.

Args: vm_name: Exact name of the virtual machine. target: Optional vCenter/ESXi target name from config. Uses default if omitted.

Inputs: vm_name (required), target. Returns: result

vm_reconfigureA

[WRITE] Change a VM's vCPU count and/or memory.

Pass only the fields you want to change; omitted fields are left untouched. Hot-add of CPU/memory requires it to be enabled on the VM and a running guest; otherwise power the VM off first (vm_power_off). Audited to ~/.vmware/audit.db.

Args: vm_name: Exact name of the VM to reconfigure. cpu: New vCPU count; omit to leave unchanged. memory_mb: New memory in MB; omit to leave unchanged. target: vCenter/ESXi target name from config.yaml; omit to use the default target.

Returns: Status string describing the applied change, or a VM-not-found error.

Inputs: vm_name (required), cpu, target, memory_mb. Returns: result

vm_revert_snapshotA
Destructive

[WRITE] Revert a VM to a named snapshot (loses changes since snapshot).

Args: vm_name: VM to revert. snapshot_name: Snapshot to revert to. target: vCenter/ESXi target name from config.

Inputs: vm_name (required), snapshot_name (required), target. Returns: result

vm_rollback_planA
Destructive

[WRITE] Rollback executed steps of a failed plan in reverse order.

Only call this after vm_apply_plan returns status='failed' and the user confirms they want to rollback. Irreversible steps (delete_vm, revert_snapshot, etc.) are skipped with a warning.

Args: plan_id: The plan ID of the failed plan. target: Optional vCenter/ESXi target name from config.

Inputs: plan_id (required), target.

vm_set_ttlA

[WRITE] Set a Time-To-Live (TTL) for a VM. The daemon auto-deletes it when expired.

The scheduler daemon must be running (vmware-aiops daemon start) for automatic deletion. TTLs are persisted in ~/.vmware-aiops/ttl.json.

Args: vm_name: Name of the VM to auto-delete. minutes: Minutes until deletion (minimum 1). target: Optional vCenter/ESXi target name from config.

Inputs: minutes (required), vm_name (required), target. Returns: result

vm_task_statusA
Read-onlyIdempotent

[READ] Poll a long-running vSphere task by its id (from an async vm_delete_snapshot).

Use after vm_delete_snapshot returns a task id to check whether the consolidation has finished, instead of re-running the delete. Returns state (queued/running/success/error/ gone), progress percent, and the entity name. 'gone' means vCenter already garbage-collected a completed task — re-list the resource to confirm the final state.

Args: task_id: The task id string returned by an async write operation. target: vCenter/ESXi target name from config.yaml; omit to use the default target.

Returns: Dict with task_id, state, progress_pct, operation, entity, and error/note when relevant.

Inputs: task_id (required), target.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

    TDQS

    A4.1/5.0

    Scored across 44 tools

    Disambiguation4/5

    Most tools have clear, distinct purposes (e.g., deploy_vm_from_ova vs deploy_vm_from_template vs vm_clone). However, some overlap exists between vm_guest_exec and vm_guest_exec_output (both execute commands in a guest), and deploy_vm_from_template vs vm_clone (both clone a template/VM), which could cause misselection.

    Naming Consistency4/5

    Naming is mostly consistent with a verb_noun pattern (e.g., list_vcenter_alarms, vm_power_on, cluster_create). Minor deviations: vm_set_ttl vs vm_cancel_ttl (inconsistent verb placement), and batch_clone_vms vs batch_linked_clone_vms (not starting with vm_ despite being VM operations).

    Tool Count3/5

    At 44 tools, this is on the heavy side but covers a broad domain (VM lifecycle, clustering, guest operations, snapshot management). It feels excessive for a single server, but each tool addresses a specific need. The count is borderline, leaning toward too many.

    Completeness4/5

    Covers a very comprehensive VM lifecycle: create, deploy, clone, snapshot, power, guest ops, cluster management, alarm handling, and TTL management. Minor gaps: no direct VM rename or NIC management tool, and no datastore management (e.g., create datastore) but these are not core to the server's primary purpose.

    Maintenance

    ActivityActive
    ResponsivenessUsually handled

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      C
      maintenance
      Enables AI agents to manage VMware vSphere infrastructure through 55 typed tools built on the govc CLI. It supports comprehensive operations including VM lifecycle management, snapshot control, datastore navigation, and networking configuration.
      48 npm
      5
      MIT
    • A
      license
      A
      quality
      B
      maintenance
      Read-only VMware vCenter/ESXi monitoring. 8 MCP tools for VM inventory, host status, datastore capacity, cluster info, alarms, events, and VM details. Code-level enforced safety — no destructive operations exist in the codebase. Supports vSphere 6.5–8.0. Works with local models via Ollama/LM Studio.
      33
      839 PyPI
      18
      MIT
    • A
      license
      Not graded
      quality
      D
      maintenance
      Enables management of VMware vCenter and ESXi environments, including VM operations, resource management, and automation with Ollama AI and n8n workflows.
      4
      MIT
    • A
      license
      Not graded
      quality
      D
      maintenance
      An MCP server that gives AI agents direct access to VMware vSphere infrastructure, enabling VM lifecycle management, snapshots, datastore operations, networking, and more via 55 typed tools built on govc.
      48 npm
      MIT