mcp-vmware
# mcp-vmware
[](https://github.com/Hokonoken/mcp-vmware/actions/workflows/ci.yml)
[](https://github.com/Hokonoken/mcp-vmware/actions/workflows/codeql.yml)
[](https://scorecard.dev/viewer/?uri=github.com/Hokonoken/mcp-vmware)
[](LICENSE)
[](pyproject.toml)
[](https://modelcontextprotocol.io)
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)
```bash
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):
```json
{
"mcpServers": {
"vmware": {
"command": "docker",
"args": ["run", "-i", "--rm", "--env-file", "/path/.vcenter.env", "mcp-vmware"]
}
}
}
```
Building behind a corporate proxy (TLS interception included):
```bash
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 .
```
## 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.
```bash
# 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:
```bash
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
```bash
./.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](CONTRIBUTING.md) and
[CODE_OF_CONDUCT.md](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](CONTRIBUTING.md)).
- Minimal workflow permissions (`contents: read` by default).
Report vulnerabilities privately: see [SECURITY.md](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](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.
TDQS
Scored across 20 tools
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.
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.
20 tools is well-scoped for a VMware management server, covering major resource types (clusters, hosts, VMs, datastores, networks, events, tasks) without being excessive.
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.