Skip to main content
Glama

mcp-vmware

CI CodeQL OpenSSF Scorecard License: MIT Python 3.12+ MCP

MCP server to pilot a VMware vCenter (vSphere 7/8) from Claude Code or any MCP client, with two deployment modes depending on your network topology:

  • Direct: the machine running the MCP client has a route to vCenter (homelab, admin workstation). Up and running in 2 minutes via Docker or pip.

  • Jump host: the workstation has no access to the management network (a common enterprise setup). The server runs on a bastion machine and the client talks to it over SSH stdio — vCenter credentials never leave the secured zone.

Highlights:

  • 39 tools covering VMs (inventory, power, snapshots, clone, migration), clusters (HA, DRS, affinity rules) and ESXi hosts (maintenance, services, firewall, storage, advanced settings — esxcli equivalent through the official API, no SSH to the hosts).

  • 4 roles with permission groups (viewer/operator/vm_admin/infra_admin): tools outside the active role are not even exposed to the LLM.

  • LLM ergonomics: compact markdown or structured JSON listings (structuredContent), uniform pagination, real-time progress for long operations.

  • API map versioned to the vCenter build: the full API surface (1409 SOAP methods, 1064 REST operations) is mapped and versioned; the coverage matrix drives the server's evolution.

Quick start (direct access to vCenter)

cp .vcenter.env.example .vcenter.env && chmod 600 .vcenter.env && vi .vcenter.env

# Docker / Podman (nothing else to install):
docker build -t mcp-vmware -f Containerfile .
docker run -i --rm --env-file .vcenter.env mcp-vmware

# or with Python (>= 3.12):
pip install . && MCP_VMWARE_ENV_FILE=./.vcenter.env python -m mcp_vmware

Declaration in .mcp.json (the MCP client talks stdio to the container):

{
  "mcpServers": {
    "vmware": {
      "command": "docker",
      "args": ["run", "-i", "--rm", "--env-file", "/path/.vcenter.env", "mcp-vmware"]
    }
  }
}

Building behind a corporate proxy (TLS interception included):

docker build --network=host \
  --build-arg http_proxy --build-arg https_proxy --build-arg no_proxy \
  --build-arg PIP_TRUSTED_HOST="pypi.org files.pythonhosted.org" \
  -t mcp-vmware -f Containerfile .

Related MCP server: vSphere MCP Server

Jump host mode (segmented enterprise networks)

When vCenter lives in a management network unreachable from workstations, the server installs on the official jump host. MCP speaks stdio over SSH natively: no tunnel, no exposed port.

Workstation (Claude Code / MCP client)
   |  spawn: ssh jumphost VMware/mcp-vmware/run.sh   (stdio = MCP protocol)
   v
jumphost (Linux, Python 3.12 venv)
   |  pyvmomi (SOAP vim25)
   v
vcenter.example.com (vSphere 8)

Benefits: network segmentation respected, credentials confined to the jump host (~/VMware/.vcenter.env, chmod 600, never in the repo nor on the workstation), single audit point.

# 1. Jump host: venv (once)
ssh jumphost 'mkdir -p ~/VMware && python3.12 -m venv ~/VMware/venv'

# 2. Credentials on the jump host
scp .vcenter.env.example jumphost:VMware/.vcenter.env
ssh jumphost 'chmod 600 ~/VMware/.vcenter.env && vi ~/VMware/.vcenter.env'

# 3. Deploy the server (rsync + pip install -e)
./deploy.sh

# 4. Adjust .mcp.json:
#    {"mcpServers": {"vmware": {"command": "ssh",
#                               "args": ["jumphost", "VMware/mcp-vmware/run.sh"]}}}

Quick check outside any MCP client:

ssh jumphost 'VMware/mcp-vmware/run.sh' <<'EOF'
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"0"}}}
EOF

Roles and permission groups

Access is driven by MCP_VMWARE_ROLE in .vcenter.env (see docs/roles.md for details and the matching vCenter privilege templates):

Role

Exposed tools

Scope

viewer (default)

20

read-only over everything (inventory + host config)

operator

24

+ VM power and snapshots

vm_admin

28

+ VM reconfiguration, clone, delete, migration

infra_admin

39

+ cluster HA/DRS/rules, host operations and fine-grained host config (esxcli equivalent)

Tools outside the role are not registered: the LLM never sees them in tools/list. Additional protections: vmware_delete_vm, vmware_host_maintenance (enter) and vmware_host_power require confirm=true; host reboot/shutdown is refused outside maintenance mode unless force=true.

Defense in depth: use a vCenter service account whose vSphere role matches the ceiling of the MCP role (templates in docs/roles.md), one env file per account (MCP_VMWARE_ENV_FILE).

Versioned API map (drives the evolution)

The server's evolution is driven by a complete map of the API, versioned to the vCenter build:

  • tools/build_api_map.py (run wherever vCenter is reachable) generates api-map/<version>-<build>/: the full vim25 SOAP surface (pyvmomi introspection) and the REST vAPI surface (live vCenter metamodel).

  • api-map/coverage.yaml links each API area to an MCP tool with a status (todo / in_progress / done / wontdo) and carries the v2 backlog.

  • On every vCenter upgrade: rerun the script, commit the new snapshot, and the git diff shows how the API evolved.

Development

./.venv/bin/ruff check src tools tests && ./.venv/bin/ruff format src tools tests
./.venv/bin/mypy src
./.venv/bin/pytest          # local suite, mocked pyvmomi, no vCenter required

Adding a tool: implement it in the relevant tools_*.py module with the tool(name, title, group=...) decorator (write tools call _gate() first), update api-map/coverage.yaml in the same commit, deploy, smoke test.

See CONTRIBUTING.md and CODE_OF_CONDUCT.md.

Security & supply chain

Standard supply-chain hygiene, all with SHA-pinned GitHub Actions:

  • CodeQL static analysis (SAST) on every push/PR and weekly.

  • OpenSSF Scorecard weekly, results published.

  • Dependabot for Python and GitHub Actions updates.

  • Dependency Review on pull requests (fails on high-severity additions).

  • SPDX license headers on every source file.

  • Signed commits expected from contributors (see CONTRIBUTING.md).

  • Minimal workflow permissions (contents: read by default).

Report vulnerabilities privately: see SECURITY.md.

Disclaimer

This is a personal, independent project — my own take on an MCP server for vCenter. It is not an official product and is not affiliated with, endorsed by, or supported by VMware, Broadcom, Anthropic, or any employer.

  • Provided "as is", without warranty of any kind (see LICENSE). Use at your own risk.

  • No support and no SLA. Issues and pull requests are welcome and handled on a best-effort basis, on my own time — there is no guarantee of a response or a fix.

  • Not production-hardened. This server gives an LLM the ability to act on virtualization infrastructure. Review the code before running it, start with the viewer role, use a vCenter service account whose privileges match the chosen role (docs/roles.md), and only raise privileges after validating the write tools on a disposable test scope. You are responsible for any action it performs on your environment.

  • Trademarks (VMware, vSphere, vCenter, ESXi) belong to their respective owners and are used here for identification only.

Available Tools

20 tools
vmware_drs_recommendationsA
Read-only

Lists the pending DRS recommendations of a cluster (proposed migrations).

Returns a JSON {cluster, count, recommendations:[{key, type, reason, target, actions:[...]}]}. Apply afterwards with vmware_apply_drs_recommendation (cluster.ops).

Inputs: cluster (required), refresh. Returns: result

vmware_get_cluster_configA
Read-onlyIdempotent

Detailed HA (DAS) and DRS configuration of a cluster + failover capacity.

Returns a JSON {name, ha:{enabled, admission_control_enabled, failover_level, restart_priority, current_failover_level}, drs:{enabled, behavior, vmotion_rate}, rules_count}.

Inputs: cluster (required). Returns: result

vmware_get_hostA
Read-onlyIdempotent

Details of an ESXi host: state, uptime, hardware, hosted VMs, mounted datastores.

Returns a JSON {name, moid, connection_state, power_state, in_maintenance, in_quarantine, boot_time, uptime_hours, version, model, cpu, memory, vms:[...], datastores:[...], networks:[...]}.

Inputs: host (required). Returns: result

vmware_get_vmA
Read-onlyIdempotent

Full details of a VM: config, CPU/RAM, disks, NICs, guest IPs, snapshots.

Returns a structured object with uuid, path, hardware_version, disks[], nics[], guest_ips[], snapshots[] (tree), resource_pool, folder, on top of the standard summary.

Inputs: vm (required). Returns: result

vmware_host_advanced_settingsA
Read-onlyIdempotent

Advanced settings of a host (equivalent of esxcli system settings advanced list), filtered by key prefix.

Returns a structured object {host, filter, count, settings:[{key, value}]}. Modify with vmware_host_set_advanced_setting (host.config).

Inputs: host (required), filter_prefix (required). Returns: result

vmware_host_firewallA
Read-onlyIdempotent

Firewall of a host (equivalent of esxcli network firewall): default policy and rulesets.

Returns a structured object {host, default_policy, count, rulesets:[{key, label, enabled, all_ips_allowed, allowed_ips}]}. Toggle with vmware_host_firewall_ruleset.

Inputs: host (required), enabled_only. Returns: result

vmware_host_healthA
Read-only

Hardware health sensors of a host (equivalent of esxcli hardware): overall CPU/memory/storage state and alerting sensors.

Returns a structured object {host, sensor_count, summary:{green, yellow, red, unknown}, sensors:[{name, state, reading}]} — by default only non-green sensors are listed.

Inputs: host (required), all_sensors. Returns: result

vmware_host_network_configA
Read-onlyIdempotent

Network configuration of a host (equivalent of esxcli network): vSwitches, portgroups, vmkernel interfaces, physical NICs.

Returns a structured object {host, vswitches:[...], portgroups:[...], vmkernel_nics:[...], physical_nics:[...]}.

Inputs: host (required). Returns: result

vmware_host_servicesA
Read-onlyIdempotent

Lists the services of an ESXi host (equivalent of esxcli system service list).

In json: {host, count, services:[{key, label, running, policy, required}]}. Act on them with vmware_host_service_action (host.config).

Inputs: host (required), response_format. Returns: result

vmware_host_storageA
Read-onlyIdempotent

Storage of a host (equivalent of esxcli storage): HBA adapters and paginated LUNs with multipath paths.

In json: {host, adapters:[...], total, count, offset, has_more, next_offset, luns:[{canonical_name, model, type, capacity, operational_state, paths}]}. Rescan with vmware_host_rescan_storage (host.config).

Inputs: host (required), limit, offset, response_format. Returns: result

vmware_host_vibsA
Read-onlyIdempotent

Software packages (VIBs) installed on a host (equivalent of esxcli software vib list) and image profile.

In json: {host, image_profile, total, count, offset, has_more, next_offset, vibs:[{name, version, vendor, acceptance_level}]}. In markdown: table.

Inputs: host (required), limit, offset, name_filter, +1 more. Returns: result

vmware_list_affinity_rulesA
Read-onlyIdempotent

Lists the affinity / anti-affinity / VM-host rules of a cluster.

Returns a JSON {cluster, count, rules:[{key, name, type, enabled, vms}]}.

Inputs: cluster (required). Returns: result

vmware_list_clustersA
Read-onlyIdempotent

Lists the clusters: HA/DRS, hosts, aggregated CPU/RAM capacity.

In json: {count, clusters:[{name, moid, hosts, ha_enabled, drs_enabled, drs_behavior, total_cpu_mhz, total_memory, effective_hosts}]}. In markdown: table.

Inputs: response_format. Returns: result

vmware_list_datastoresB
Read-onlyIdempotent

Lists the datastores: type, capacity, free space, accessibility.

In json: {total, count, ..., datastores:[{name, moid, type, capacity, free, free_pct, accessible, hosts, vms}]}. In markdown: table.

Inputs: limit, offset, response_format. Returns: result

vmware_list_eventsA
Read-only

Recent vCenter events, global or filtered on a VM.

In json: {total, count, offset, has_more, next_offset, events:[{time, type, user, target, message}]}, most recent first. In markdown: table.

Inputs: vm, limit, offset, response_format. Returns: result

vmware_list_hostsA
Read-onlyIdempotent

Lists the ESXi hosts: state, version, model, CPU/RAM load, VM count.

In json: {total, count, ..., hosts:[{name, moid, connection_state, power_state, in_maintenance, version, model, cpu_cores, cpu_usage_mhz, cpu_total_mhz, memory_total, memory_usage, vms}]}. In markdown: table.

Inputs: limit, offset, response_format. Returns: result

vmware_list_networksA
Read-onlyIdempotent

Lists the networks (standard and distributed portgroups).

In json: {total, count, ..., networks:[{name, moid, type, accessible, vms, vlan}]}. vlan is only filled in for distributed portgroups. In markdown: table.

Inputs: limit, offset, response_format. Returns: result

vmware_list_snapshotsA
Read-onlyIdempotent

Snapshot tree of a VM (name, description, date, children).

Returns a structured object {vm, count, current_snapshot_moid, snapshots:[...tree...]}.

Inputs: vm (required). Returns: result

vmware_list_vmsA
Read-onlyIdempotent

Lists the vCenter VMs with filters and pagination.

In json: {total, count, offset, has_more, next_offset, vms:[{name, moid, power_state, guest_os, ip, hostname, cpu, memory_mb, host, vmware_tools}]}. In markdown: table.

Inputs: limit, offset, name_filter, power_state, +1 more. Returns: result

vmware_recent_tasksA
Read-only

Latest vCenter tasks (running or recent operations) with state and target.

In json: {count, tasks:[{key, description, target, state, progress_pct, user, queued, started, completed, error}]}. In markdown: table, most recent first.

Inputs: limit, response_format. Returns: result

Tool Schema Changelog

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

    TDQS

    A3.8/5.0

    Scored across 20 tools

    Disambiguation5/5

    Each tool targets a distinct VMware resource or configuration aspect (clusters, hosts, VMs, storage, networking, etc.) with no overlapping purposes. The descriptions clearly differentiate their scopes.

    Naming Consistency4/5

    All tools use the 'vmware_' prefix, but verb usage is mixed: some use 'list_', some 'get_', and some are noun phrases (e.g., 'host_advanced_settings'). While readable and predictable, the pattern is not perfectly uniform.

    Tool Count5/5

    20 tools is well-scoped for a VMware management server, covering major resource types (clusters, hosts, VMs, datastores, networks, events, tasks) without being excessive.

    Completeness2/5

    The tool set is heavily read-only; there are no write/modify tools (create, update, delete) for any resource. Several descriptions reference missing action tools (e.g., apply DRS recommendation, toggle firewall ruleset, modify advanced settings), indicating significant gaps for operational use.

    Maintenance

    ActivityNo data
    ResponsivenessSyncing

    Related MCP Connectors

    Related MCP Servers