Read-Only vSphere MCP Server
# Read-Only vSphere MCP Server
This project lets Codex read inventory from VMware vCenter. It exposes seven
approved MCP tools and cannot create, update, delete, clone, power, or move
anything.
## Caveman Explanation
```text
You -> Codex -> this MCP server -> vCenter
|
+-> read information only
```
Codex asks a question. The MCP server logs in to vCenter, performs an approved
REST request, and returns the answer. The MCP server runs locally through
standard input/output (`stdio`); it does not open a network port.
## What You Need
You need:
1. The HTTPS address of your **vCenter Server**, such as
`https://vcenter.company.com`.
2. A vCenter username.
3. That user's password.
4. The built-in **Read-only** role assigned at the inventory level you need,
with propagation enabled.
5. Network or VPN access from your computer to vCenter.
6. Python 3.10 or newer, Git, and Codex.
The address alone is not enough. You need a username and password. You do not
need a Broadcom developer API key. After login, vCenter returns a temporary
session token automatically.
Send this request to your VMware administrator:
> Please provide the HTTPS vCenter Server address and a dedicated service
> account with the built-in Read-only role. Assign it at the required inventory
> scope with propagation enabled. Please also provide the company CA certificate
> in PEM format if vCenter uses an internally signed certificate.
This project supports username/password authentication. If your company forces
browser-only SSO or MFA, ask for a non-interactive read-only service account.
## Install on macOS or Linux
```bash
git clone https://github.com/arjungowdal4601/vcenter_mcp.git
cd vcenter_mcp
python3 --version
python3 -m venv .venv
source .venv/bin/activate
python -m pip install -e .
cp .env.example .env
chmod 600 .env
```
The version command must show Python 3.10 or newer. If `python3` is older, use
the newer executable installed on your computer, such as `python3.13`, for the
virtual-environment command.
Open `.env` in a local text editor and replace the example values with your
credentials. Do not paste the password into an AI chat.
## Install on Windows PowerShell
```powershell
git clone https://github.com/arjungowdal4601/vcenter_mcp.git
cd vcenter_mcp
py -3 --version
py -3 -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install -e .
Copy-Item .env.example .env
```
The version command must show Python 3.10 or newer.
Open `.env` locally and replace the examples. If PowerShell blocks activation,
you can still use `.\.venv\Scripts\python.exe` in the remaining commands.
## Configure `.env`
Minimum configuration:
```dotenv
VSPHERE_HOST="https://vcenter.company.com"
VSPHERE_USERNAME="codex-readonly@vsphere.local"
VSPHERE_PASSWORD="your-real-password"
VSPHERE_VERIFY_SSL="true"
VSPHERE_TIMEOUT_SECONDS="30"
```
`VSPHERE_HOST` is the address used to open vCenter Server. Do not use an ESXi
host address, the Broadcom documentation website, or an address ending in an
API path such as `/api` or `/sdk`.
`VSPHERE_USERNAME` is the read-only vCenter account. Depending on your company,
it may look like `user@vsphere.local`, `DOMAIN\\user`, or an email address.
`VSPHERE_PASSWORD` is that account's password. `.env` is ignored by Git and
must never be committed.
`VSPHERE_VERIFY_SSL` should remain `true`. Turning verification off makes it
possible to send credentials to an impostor server.
If your company uses a private certificate authority, add the absolute path to
its PEM bundle:
```dotenv
VSPHERE_CA_BUNDLE="/Users/you/certificates/company-ca.pem"
```
On Windows, use a quoted absolute path:
```dotenv
VSPHERE_CA_BUNDLE="C:\\Certificates\\company-ca.pem"
```
Process environment variables override values in `.env`.
## Connect the Server to Codex
Run the command from the repository directory after filling `.env`.
macOS or Linux:
```bash
codex mcp add vsphere -- "$(pwd)/.venv/bin/python" -m vsphere_mcp --env-file "$(pwd)/.env"
```
Windows PowerShell:
```powershell
$root = (Get-Location).Path
codex mcp add vsphere -- "$root\.venv\Scripts\python.exe" -m vsphere_mcp --env-file "$root\.env"
```
The Codex registration stores only the Python command and `.env` path. It does
not store the vCenter username or password.
Check the registration:
```bash
codex mcp get vsphere
```
Restart Codex after registering the server. Then ask:
```text
Use the vSphere tools to list my virtual machines.
```
To replace an old registration:
```bash
codex mcp remove vsphere
```
Then run the appropriate `codex mcp add` command again.
Other MCP-compatible coding agents can run the same executable and arguments
as a local `stdio` server. Their configuration format is agent-specific.
## Available Tools
| Tool | What it reads | REST endpoint |
| --- | --- | --- |
| `vsphere_list_vms` | Visible virtual machines | `GET /api/vcenter/vm` |
| `vsphere_get_vm` | Details for one VM ID | `GET /api/vcenter/vm/{vm}` |
| `vsphere_list_hosts` | ESXi hosts | `GET /api/vcenter/host` |
| `vsphere_list_clusters` | Clusters | `GET /api/vcenter/cluster` |
| `vsphere_list_datastores` | Datastores | `GET /api/vcenter/datastore` |
| `vsphere_list_datacenters` | Datacenters | `GET /api/vcenter/datacenter` |
| `vsphere_list_networks` | Networks | `GET /api/vcenter/network` |
`vsphere_list_vms` can filter by VM IDs, names, folders, datacenters, hosts,
clusters, resource pools, and power states. Allowed power states are
`POWERED_ON`, `POWERED_OFF`, and `SUSPENDED`.
Example prompts:
```text
Use vSphere to list all VMs.
Show only powered-on VMs named web-server.
Get details for VM vm-42.
List my ESXi hosts and clusters.
List all datastores and datacenters visible to this account.
List the available vCenter networks.
```
The returned inventory depends on the account's vCenter permissions. An empty
list can mean the login worked but the Read-only role was assigned at the wrong
inventory scope.
## Authentication
The MCP server performs this flow internally:
1. It sends the username and password to `POST /api/session` using HTTPS Basic
authentication.
2. vCenter returns a temporary session token.
3. The server sends that token in the `vmware-api-session-id` header for REST
reads.
4. If the token expires and vCenter returns HTTP 401, the server logs in once
more and retries the read once.
The password is not an API key. The temporary session token is not something
you obtain manually.
## Security
- Only explicit read tools are registered with MCP.
- Every tool is marked read-only, non-destructive, and idempotent.
- There is no generic `call_api` tool.
- vCenter addresses must use HTTPS.
- Redirects are not followed, preventing credentials from being forwarded to
another host.
- IDs and filters are validated before requests are sent.
- Passwords are excluded from configuration representations and errors.
- Real enforcement also comes from the vCenter account's Read-only role.
For stronger protection, create a dedicated service account instead of using a
personal administrator account.
## Troubleshooting
### HTTP 401
vCenter rejected the username, password, or expired session. Confirm the
credentials by signing in to the same `VSPHERE_HOST`. Browser-only MFA accounts
will not work.
### HTTP 403
The login worked, but the account lacks permission. Ask the administrator to
assign the Read-only role at the correct inventory scope with propagation.
### Certificate verification failed
Ask the administrator for the company CA certificate in PEM format and set
`VSPHERE_CA_BUNDLE`. Do not solve production certificate errors by disabling
verification.
### Connection timeout or name error
Confirm the address, DNS, VPN, firewall, and port 443 access from your computer.
### Codex cannot see the tools
Run `codex mcp get vsphere`, confirm the displayed Python and `.env` paths still
exist, and restart Codex. Absolute paths break if the repository is moved;
remove and add the registration again after moving it.
### Tools return no inventory
The account may have the Read-only role at the wrong scope. vCenter only returns
objects visible to that account.
## Sharing
Share the GitHub repository, not your `.env` file. Each user should clone the
project, create their own `.env`, and register their local copy with Codex.
Never send vCenter passwords through Git, email, chat, screenshots, or tickets.
This version intentionally supports only local `stdio`. It does not provide a
central HTTP MCP service.
## Development
Install development dependencies and run the tests:
```bash
python -m pip install -e '.[dev]'
python -m pytest
```
Show the command-line help:
```bash
python -m vsphere_mcp --help
```
The automated tests use mocked vCenter responses. A real integration test
requires a non-production vCenter address and read-only credentials.
## Official References
- [vSphere Automation API](https://developer.broadcom.com/xapis/vsphere-automation-api/latest/)
- [Create a vCenter REST session](https://developer.broadcom.com/xapis/vsphere-automation-api/latest/api/session/post/)
- [vSphere VM REST API](https://developer.broadcom.com/xapis/vsphere-automation-api/latest/vcenter/vm/)
- [Codex MCP documentation](https://developers.openai.com/codex/mcp/)
TDQS
Scored across 9 tools
Tools are mostly distinct with clear purposes. The slight overlap between vsphere_get_vm and vsphere_get_vm_summary could cause confusion, but descriptions differentiate them (full VM details vs. summary property). All other tools target unique resource types.
All tools start with 'vsphere_' and follow a verb_noun pattern. Verbs are consistently 'list' for enumeration and 'get' for single resources, except 'query_properties' which uses 'query' instead of 'get', introducing minor inconsistency.
9 tools cover the core read-only operations for vSphere (listing main resources and retrieving VM details). The count is well-scoped for the server's purpose, not excessive or sparse.
The set covers listing for most resources and VM detail retrieval, but lacks ways to get detailed properties for clusters, datastores, or hosts beyond listing. The generic 'query_properties' tool may partially fill gaps but is limited to allowlisted properties and requires specific input.