vmware-storage 2.2.0__tar.gz → 2.3.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/.claude-plugin/plugin.json +2 -2
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/.mcp.json +1 -1
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/PKG-INFO +73 -8
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/README-CN.md +69 -6
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/README.md +71 -6
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/RELEASE_NOTES.md +44 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/openclaw.plugin.json +2 -2
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/package.json +2 -2
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/pyproject.toml +2 -2
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/server.json +3 -3
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/skills/vmware-storage/SKILL.md +14 -6
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/skills/vmware-storage/references/agent-guardrails.md +1 -1
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/skills/vmware-storage/references/capabilities.md +15 -3
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/skills/vmware-storage/references/cli-reference.md +17 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/skills/vmware-storage/references/setup-guide.md +37 -3
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_atexit_handlers_do_not_accumulate.py +14 -11
- vmware_storage-2.3.1/tests/eval/regression/test_login_without_a_role.py +215 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_session_probe_eviction.py +23 -9
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_storage_hardening_fixes.py +3 -3
- vmware_storage-2.3.1/tests/test_access_info.py +108 -0
- vmware_storage-2.3.1/tests/test_session_pool.py +219 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/uv.lock +5 -5
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/vmware_storage/__init__.py +1 -1
- vmware_storage-2.3.1/vmware_storage/access_requirements.py +46 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/vmware_storage/cli.py +38 -2
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/vmware_storage/connection.py +86 -37
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/vmware_storage/mcp_server/server.py +101 -20
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/.clawhubignore +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/.env.example +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/.gitignore +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/Dockerfile +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/LICENSE +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/SECURITY.md +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/config.example.yaml +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/docker-compose.yml +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/examples/mcp-configs/README.md +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/examples/mcp-configs/claude-code.json +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/examples/mcp-configs/continue.yaml +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/examples/mcp-configs/cursor.json +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/examples/mcp-configs/goose.json +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/examples/mcp-configs/localcowork.json +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/examples/mcp-configs/mcp-agent.yaml +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/examples/mcp-configs/vscode-copilot.json +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/patterns/README.md +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/patterns/iscsi-target-stale-rescan.yaml +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/skills/vmware-storage/evals/evals.json +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/smithery.yaml +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/__init__.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/conftest.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/__init__.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/capability/__init__.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/capability/_family.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/capability/_scores.json +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/capability/_scoring.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/capability/_skill.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/capability/conftest.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/capability/test_entity_reachability.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/capability/test_error_actionability.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/capability/test_tool_description_quality.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/capability/test_tool_manifest_budget.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/__init__.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_audit_isolation.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_cached_loader_agrees_with_the_resolver.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_capability_grader.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_cli_writes_guarded.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_credential_env_override.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_datastore_list_renders.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_doctor_authenticates_every_target.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_doctor_uses_the_config_the_tools_use.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_env_secret_obfuscation.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_fc_multipath.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_instructions_name_targets.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_inventory_scale_n1.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_iscsi_unreachable_host.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_release_blockers.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_remedy_survives_a_long_home.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_result_envelope.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_returned_failure_is_audited.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_storage_ops_behavior.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_tool_names_2_0.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_vim_attribute_conformance.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_vsan_efficiency.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_vsan_health_is_actually_queried.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_vsan_reports_what_it_could_not_read.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/spec/__init__.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/spec/vsan_efficiency_endpoints.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/spec/vsan_health_endpoints.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/test_init_and_onboarding.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/test_iscsi_gate.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/test_no_destructive_ops.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/test_no_destructive_vm_code.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/test_safe_error_passthrough.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/test_stop_signal_runs_atexit.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/vmware_storage/config.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/vmware_storage/doctor.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/vmware_storage/init_wizard.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/vmware_storage/mcp_server/__init__.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/vmware_storage/mcp_server/__main__.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/vmware_storage/notify/__init__.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/vmware_storage/notify/audit.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/vmware_storage/ops/__init__.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/vmware_storage/ops/datastore_browser.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/vmware_storage/ops/inventory.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/vmware_storage/ops/iscsi_config.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/vmware_storage/ops/iscsi_gate.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/vmware_storage/ops/multipath.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/vmware_storage/ops/storage_paths.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/vmware_storage/ops/vsan.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/vmware_storage/ops/vsan_efficiency.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/vmware_storage/ops/vsan_sdk.py +0 -0
- {vmware_storage-2.2.0 → vmware_storage-2.3.1}/vmware_storage/policy_environment.py +0 -0
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
"$schema": "https://anthropic.com/claude-code/plugin.schema.json",
|
|
3
3
|
"name": "vmware-storage",
|
|
4
4
|
"displayName": "VMware Storage",
|
|
5
|
-
"version": "2.
|
|
6
|
-
"description": "VMware vSphere storage with
|
|
5
|
+
"version": "2.3.1",
|
|
6
|
+
"description": "VMware vSphere storage with 15 MCP tools: datastores, iSCSI, vSAN, FC multipath.",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "Wei Zhou",
|
|
9
9
|
"email": "zhouwei008@gmail.com",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: vmware-storage
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.3.1
|
|
4
4
|
Summary: VMware vSphere storage management: datastores, iSCSI, vSAN. Domain-focused MCP skill.
|
|
5
5
|
Project-URL: Homepage, https://github.com/vmware-skills/VMware-Storage
|
|
6
6
|
Project-URL: Repository, https://github.com/vmware-skills/VMware-Storage
|
|
@@ -16,7 +16,7 @@ Requires-Dist: python-dotenv<2.0,>=1.0
|
|
|
16
16
|
Requires-Dist: pyvmomi<10.0,>=8.0.3.0
|
|
17
17
|
Requires-Dist: rich<15.0,>=13.0
|
|
18
18
|
Requires-Dist: typer<1.0,>=0.12
|
|
19
|
-
Requires-Dist: vmware-policy<2.0,>=1.
|
|
19
|
+
Requires-Dist: vmware-policy<2.0,>=1.23.0
|
|
20
20
|
Description-Content-Type: text/markdown
|
|
21
21
|
|
|
22
22
|
<!-- mcp-name: io.github.vmware-skills/vmware-storage -->
|
|
@@ -28,7 +28,7 @@ Description-Content-Type: text/markdown
|
|
|
28
28
|
|
|
29
29
|
[English](README.md) | [中文](README-CN.md)
|
|
30
30
|
|
|
31
|
-
VMware vSphere storage management: datastores, iSCSI, vSAN, and read-only Fibre Channel / multipath diagnostics —
|
|
31
|
+
VMware vSphere storage management: datastores, iSCSI, vSAN, and read-only Fibre Channel / multipath diagnostics — 15 MCP tools, domain-focused and lightweight.
|
|
32
32
|
|
|
33
33
|
> Split from vmware-aiops for lighter context and local model compatibility.
|
|
34
34
|
|
|
@@ -36,7 +36,7 @@ VMware vSphere storage management: datastores, iSCSI, vSAN, and read-only Fibre
|
|
|
36
36
|
|
|
37
37
|
## Upgrading to 2.0
|
|
38
38
|
|
|
39
|
-
2.0 renames 10 of its
|
|
39
|
+
2.0 renames 10 of its MCP tools (all but the four that already started with a verb) so every name starts with a verb (e.g. `fc_adapter_list` → `list_fc_adapters`, `storage_device_paths` → `list_storage_device_paths`, `storage_iscsi_add_target` → `add_iscsi_target`). The full old → new table is in
|
|
40
40
|
[RELEASE_NOTES.md](RELEASE_NOTES.md#v200--mcp-tools-renamed-verb-first). Three tools also change a parameter: `browse_datastore` and `scan_datastore_images` take
|
|
41
41
|
`datastore_name` (was `ds_name`, now the same as vmware-aiops' `browse_datastore`), and `list_all_datastores` gains an
|
|
42
42
|
optional `limit` (same as vmware-monitor's). Everything else stays: same tools, safety gates and CLI commands (the CLI
|
|
@@ -109,7 +109,7 @@ chmod 600 ~/.vmware-storage/.env
|
|
|
109
109
|
vmware-storage doctor
|
|
110
110
|
```
|
|
111
111
|
|
|
112
|
-
## MCP Tools (
|
|
112
|
+
## MCP Tools (15)
|
|
113
113
|
|
|
114
114
|
| Category | Tools | Type |
|
|
115
115
|
|----------|-------|------|
|
|
@@ -117,6 +117,7 @@ vmware-storage doctor
|
|
|
117
117
|
| iSCSI | `enable_iscsi`, `get_iscsi_status`, `add_iscsi_target`, `remove_iscsi_target`, `rescan_storage` | Read/Write |
|
|
118
118
|
| vSAN | `get_vsan_health`, `get_vsan_capacity`, `get_vsan_efficiency` | Read |
|
|
119
119
|
| FC / multipath | `list_fc_adapters`, `list_storage_device_paths` | Read |
|
|
120
|
+
| Access | `get_access_info` — which account the server uses and whether it holds each tool's vSphere privileges (root folder) | Read |
|
|
120
121
|
|
|
121
122
|
## Auto-Remediation Patterns (PoC)
|
|
122
123
|
|
|
@@ -230,9 +231,9 @@ vmware-storage-mcp
|
|
|
230
231
|
|
|
231
232
|
## Why a Separate Skill?
|
|
232
233
|
|
|
233
|
-
`vmware-aiops` has
|
|
234
|
+
`vmware-aiops` has 61 MCP tools — too heavy for local LLMs (7B-14B). By splitting storage into its own skill:
|
|
234
235
|
|
|
235
|
-
- **
|
|
236
|
+
- **15 tools** — fits comfortably in small model context windows
|
|
236
237
|
- **Domain-focused** — storage admins get only what they need
|
|
237
238
|
- **Least privilege** — can run under a vCenter service account with storage read-only permissions
|
|
238
239
|
- **Composable** — use alongside vmware-monitor or vmware-aiops as needed
|
|
@@ -259,7 +260,7 @@ vmware-storage-mcp
|
|
|
259
260
|
|
|
260
261
|
| Feature | Description |
|
|
261
262
|
|---------|-------------|
|
|
262
|
-
| Read-heavy |
|
|
263
|
+
| Read-heavy | 11/15 tools are read-only |
|
|
263
264
|
| Preview by default (MCP) | The 4 write tools take `confirm` (default `false`): a call without it changes nothing and returns `blast_radius` (host, adapters, and for target removal the paths, devices and datastores behind the target). `confirm=true` is refused when a datastore would lose every path or part of the blast radius could not be read. `dry_run` is a deprecated alias |
|
|
264
265
|
| Input validation | IP addresses and ports validated before iSCSI operations |
|
|
265
266
|
| Audit logging | All operations logged to `~/.vmware-storage/audit.log` |
|
|
@@ -275,9 +276,73 @@ vmware-storage-mcp
|
|
|
275
276
|
| `get_vsan_health` returns `overall_health: null` | `null` = not asked (see `health_not_queried_reason`), never a measurement; a string is always vSAN's own answer, including its own `"unknown"`. Usual cause: connected to standalone ESXi, but the health service runs in **vCenter**. |
|
|
276
277
|
| Rescan doesn't discover new LUNs | Wait 15-30 seconds after adding targets, then rescan again. Verify target IP is reachable from ESXi. |
|
|
277
278
|
| "Password not found" error | Variable names follow `VMWARE_<TARGET_UPPER>_PASSWORD` (hyphens → underscores). Check `~/.vmware-storage/.env`. |
|
|
279
|
+
| `doctor` fails with "no vSphere role", or every command fails with "session is not authenticated" | The login works but the account has no vSphere role. Assign one (Read-Only or higher) on the vCenter root folder (Administration > Access Control > Global Permissions). Mid-run, the same fault can be an expired session: run the command again. |
|
|
278
280
|
| Connection timeout to vCenter | Use `vmware-storage doctor --skip-auth` to bypass auth checks on high-latency networks. |
|
|
279
281
|
| "Datastore browse did not finish within Ns" | The datastore is very large or busy. Narrow the search with a sub-path and a specific pattern (e.g. `datastore browse ds01 --path templates --pattern "*.ova"`) instead of browsing the root — do not just retry the same broad browse. |
|
|
280
282
|
|
|
283
|
+
<!-- usage: remote-and-exposure -->
|
|
284
|
+
## Remote access (HTTPS) and limiting tools
|
|
285
|
+
|
|
286
|
+
By default `vmware-storage mcp` speaks stdio to one local client and offers every tool. Two options change that
|
|
287
|
+
(vmware-policy ≥ 1.21.0).
|
|
288
|
+
|
|
289
|
+
**Serve over HTTPS** so clients on other machines can connect. Every caller needs a bearer token:
|
|
290
|
+
|
|
291
|
+
```bash
|
|
292
|
+
vmware-audit token create alice # prints the token once; give it to alice
|
|
293
|
+
vmware-audit token list # names only
|
|
294
|
+
vmware-audit token revoke alice # refused from its next request, no restart
|
|
295
|
+
vmware-storage mcp --transport https --host 0.0.0.0 --port 8443 \
|
|
296
|
+
--cert /etc/vmware-mcp/server.pem --key /etc/vmware-mcp/server-key.pem \
|
|
297
|
+
--public-name mcp.example.com
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
Connect a client (Claude Code shown; any MCP client that supports streamable HTTP and custom headers works):
|
|
301
|
+
|
|
302
|
+
```bash
|
|
303
|
+
claude mcp add --transport http vmware-storage https://mcp.example.com:8443/mcp \
|
|
304
|
+
--header "Authorization: Bearer $VMWARE_MCP_TOKEN"
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
```json
|
|
308
|
+
{
|
|
309
|
+
"mcpServers": {
|
|
310
|
+
"vmware-storage": {
|
|
311
|
+
"type": "http",
|
|
312
|
+
"url": "https://mcp.example.com:8443/mcp",
|
|
313
|
+
"headers": { "Authorization": "Bearer ${VMWARE_MCP_TOKEN}" }
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
- The server will not start without a token, refuses Host/Origin values outside `--public-name`, and checks
|
|
320
|
+
before it binds that unauthenticated requests get 401. Use a certificate your clients trust for those names.
|
|
321
|
+
- Behind a TLS-terminating reverse proxy on the same machine use `--transport http --host 127.0.0.1
|
|
322
|
+
--public-name mcp.example.com` and pass the `Authorization` header through.
|
|
323
|
+
- Behind a load balancer or gateway on another machine, keep `--transport https` (a self-signed certificate is
|
|
324
|
+
fine), list in `--public-name` the host name the balancer sends as `Host`, and have it forward `Authorization`.
|
|
325
|
+
Its health probe can use `GET /healthz`, which needs no token and returns only `{"status": "ok"}`
|
|
326
|
+
(vmware-policy ≥ 1.23.0).
|
|
327
|
+
- Send `traceparent` or `X-Request-ID` with each request to have it stored on the audit row;
|
|
328
|
+
`vmware-audit log --correlation-id ID` then finds the calls behind one platform request.
|
|
329
|
+
- The audit log records each caller as `token:<name>`. Calls run side by side, also on the same target: the server keeps up to `VMWARE_MCP_POOL_SIZE` (default 2) sessions per target, each one a login on that target, and a call waits at most 300 s for a free session (vmware-policy ≥ 1.22.0).
|
|
330
|
+
- **Everyone who can reach the endpoint acts with this server's account.** Tokens identify callers; they grant
|
|
331
|
+
nothing on the platform. Run one endpoint per privilege level. `vmware-storage access-info` shows which account that is and what it may do.
|
|
332
|
+
|
|
333
|
+
**Offer only read tools, plus the writes you choose:**
|
|
334
|
+
|
|
335
|
+
```bash
|
|
336
|
+
vmware-storage mcp --expose read --allow-write enable_iscsi
|
|
337
|
+
# or: VMWARE_STORAGE_MCP_EXPOSE=read VMWARE_STORAGE_MCP_ALLOW_WRITE=enable_iscsi vmware-storage mcp
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
Tools not offered do not appear in the client's tool list. A bad value or an unknown write tool stops the server
|
|
341
|
+
(exit 2). This limits what clients are offered; it is not authorization, so the account itself should be
|
|
342
|
+
least-privilege.
|
|
343
|
+
|
|
344
|
+
Details: `skills/vmware-storage/references/setup-guide.md` ("Serving MCP over HTTPS", "Limiting which tools are offered").
|
|
345
|
+
|
|
281
346
|
## License
|
|
282
347
|
|
|
283
348
|
[MIT](LICENSE)
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
[English](README.md) | [中文](README-CN.md)
|
|
9
9
|
|
|
10
|
-
VMware vSphere 存储管理:数据存储、iSCSI、vSAN,以及只读的光纤通道(FC)/ 多路径诊断 —
|
|
10
|
+
VMware vSphere 存储管理:数据存储、iSCSI、vSAN,以及只读的光纤通道(FC)/ 多路径诊断 — 15 个 MCP 工具,领域专注、轻量级。
|
|
11
11
|
|
|
12
12
|
> 从 vmware-aiops 拆分,更轻量的上下文,兼容本地小模型。
|
|
13
13
|
|
|
@@ -15,7 +15,7 @@ VMware vSphere 存储管理:数据存储、iSCSI、vSAN,以及只读的光
|
|
|
15
15
|
|
|
16
16
|
## 升级到 2.0
|
|
17
17
|
|
|
18
|
-
2.0 把
|
|
18
|
+
2.0 把 MCP 工具名改成动词在前(已以动词开头的 4 个除外,共改名 10 处)(例如 `fc_adapter_list` → `list_fc_adapters`, `storage_device_paths` → `list_storage_device_paths`, `storage_iscsi_add_target` → `add_iscsi_target`),完整的新旧名对照表见
|
|
19
19
|
[RELEASE_NOTES.md](RELEASE_NOTES.md#v200--mcp-tools-renamed-verb-first)。另有三个工具改了参数:`browse_datastore` 和 `scan_datastore_images` 的参数 `ds_name` 改名为 `datastore_name`(与 vmware-aiops 的 `browse_datastore` 一致),`list_all_datastores` 新增可选参数 `limit`(与 vmware-monitor 一致)。其余不变:工具、安全确认门和 CLI 命令都一样(CLI 仍按原来的方式接收数据存储名)。
|
|
20
20
|
如果 agent 提示词、脚本或 `~/.vmware/rules.yaml` 里写了工具名,请改成新名——不过用旧名写的 deny 规则在
|
|
21
21
|
vmware-policy ≥ 1.18 下仍然生效(`vmware-audit policy` 会列出因改名而多匹配的规则),vmware-pilot ≥ 1.13 也会自动转换已保存工作流里的旧名。
|
|
@@ -99,7 +99,7 @@ targets:
|
|
|
99
99
|
password_env: VMWARE_ESXIPROD_PASSWORD
|
|
100
100
|
```
|
|
101
101
|
|
|
102
|
-
## MCP 工具(
|
|
102
|
+
## MCP 工具(15 个)
|
|
103
103
|
|
|
104
104
|
| 类别 | 工具 | 类型 |
|
|
105
105
|
|------|------|------|
|
|
@@ -107,6 +107,7 @@ targets:
|
|
|
107
107
|
| iSCSI | `enable_iscsi`、`get_iscsi_status`、`add_iscsi_target`、`remove_iscsi_target`、`rescan_storage` | 读/写 |
|
|
108
108
|
| vSAN | `get_vsan_health`、`get_vsan_capacity`、`get_vsan_efficiency` | 只读 |
|
|
109
109
|
| FC / 多路径 | `list_fc_adapters`、`list_storage_device_paths` | 只读 |
|
|
110
|
+
| 访问权限 | `get_access_info` — server 使用哪个账号,以及它在根文件夹上是否拥有各工具所需的 vSphere 权限 | 只读 |
|
|
110
111
|
|
|
111
112
|
### 工具说明
|
|
112
113
|
|
|
@@ -248,9 +249,9 @@ vmware-storage-mcp
|
|
|
248
249
|
|
|
249
250
|
## 为什么独立成一个 Skill?
|
|
250
251
|
|
|
251
|
-
`vmware-aiops` 有
|
|
252
|
+
`vmware-aiops` 有 61 个 MCP 工具——对本地小模型(7B-14B)来说上下文占用太重。独立拆分后:
|
|
252
253
|
|
|
253
|
-
- **
|
|
254
|
+
- **15 个工具** — 完全适合小模型上下文窗口
|
|
254
255
|
- **领域专注** — 存储管理员只看到需要的工具
|
|
255
256
|
- **最小权限** — 可以配置只有存储只读权限的 vCenter 服务账号
|
|
256
257
|
- **可组合** — 可与 vmware-monitor 或 vmware-aiops 同时运行
|
|
@@ -269,7 +270,7 @@ vmware-storage-mcp
|
|
|
269
270
|
|
|
270
271
|
| 功能 | 说明 |
|
|
271
272
|
|------|------|
|
|
272
|
-
| 只读为主 |
|
|
273
|
+
| 只读为主 | 15 个工具中 11 个只读 |
|
|
273
274
|
| 默认只预览(MCP) | 4 个写工具接受 `confirm`(默认 `false`):不带它的调用不做任何变更,只返回 `blast_radius`(主机、适配器;移除目标时还有该目标背后的路径、设备和数据存储)。某个数据存储会失去全部路径、或影响范围有任何部分读不到时,`confirm=true` 会被拒绝。`dry_run` 为已弃用的别名 |
|
|
274
275
|
| 输入验证 | iSCSI 操作前验证 IP 地址和端口 |
|
|
275
276
|
| 审计日志 | 所有操作记录到 `~/.vmware-storage/audit.log`(JSON Lines) |
|
|
@@ -289,8 +290,70 @@ vmware-storage-mcp
|
|
|
289
290
|
| `get_vsan_health` 返回 `overall_health: null` | `null` 表示**没有查询**(原因见 `health_not_queried_reason`),不是测量结果;只要是字符串就一定是 vSAN 自己给的答案,包括它自己的 `"unknown"`。常见原因:连的是独立 ESXi,而健康服务跑在 **vCenter** 上。 |
|
|
290
291
|
| 重扫后未发现新 LUN | 添加目标后等待 15-30 秒再重扫。确认 ESXi 能访问目标 IP。 |
|
|
291
292
|
| "Password not found" 错误 | 变量名规则:`VMWARE_<目标名大写>_PASSWORD`(连字符→下划线)。检查 `~/.vmware-storage/.env`。 |
|
|
293
|
+
| `doctor` 报 "no vSphere role",或每个命令都报 "session is not authenticated" | 能登录,但账号没有 vSphere 角色。在 vCenter 根文件夹上给它分配一个角色(Read-Only 或更高):Administration > Access Control > Global Permissions。运行中出现同一错误也可能是会话过期:重跑命令即可。 |
|
|
292
294
|
| 连接 vCenter 超时 | 使用 `vmware-storage doctor --skip-auth` 跳过高延迟网络的认证检查。 |
|
|
293
295
|
|
|
296
|
+
<!-- usage: remote-and-exposure -->
|
|
297
|
+
## 远程访问(HTTPS)与限制工具
|
|
298
|
+
|
|
299
|
+
默认情况下 `vmware-storage mcp` 通过 stdio 服务一个本地客户端,并提供全部工具。以下两个选项可以改变这一点
|
|
300
|
+
(需 vmware-policy ≥ 1.21.0)。
|
|
301
|
+
|
|
302
|
+
**通过 HTTPS 提供服务**,让其他机器上的客户端连接。每个调用者都需要一个 bearer token:
|
|
303
|
+
|
|
304
|
+
```bash
|
|
305
|
+
vmware-audit token create alice # 只显示一次,交给 alice
|
|
306
|
+
vmware-audit token list # 只列名字
|
|
307
|
+
vmware-audit token revoke alice # 下一个请求起即拒绝,无需重启
|
|
308
|
+
vmware-storage mcp --transport https --host 0.0.0.0 --port 8443 \
|
|
309
|
+
--cert /etc/vmware-mcp/server.pem --key /etc/vmware-mcp/server-key.pem \
|
|
310
|
+
--public-name mcp.example.com
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
连接客户端(以 Claude Code 为例;任何支持 streamable HTTP 和自定义请求头的 MCP 客户端都可以):
|
|
314
|
+
|
|
315
|
+
```bash
|
|
316
|
+
claude mcp add --transport http vmware-storage https://mcp.example.com:8443/mcp \
|
|
317
|
+
--header "Authorization: Bearer $VMWARE_MCP_TOKEN"
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
```json
|
|
321
|
+
{
|
|
322
|
+
"mcpServers": {
|
|
323
|
+
"vmware-storage": {
|
|
324
|
+
"type": "http",
|
|
325
|
+
"url": "https://mcp.example.com:8443/mcp",
|
|
326
|
+
"headers": { "Authorization": "Bearer ${VMWARE_MCP_TOKEN}" }
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
- 没有 token 时服务不会启动;`--public-name` 之外的 Host/Origin 一律拒绝;绑定端口前会自检,确认未认证请求得到 401。
|
|
333
|
+
证书要用客户端信任、且覆盖这些名字的证书。
|
|
334
|
+
- 在同一台机器上由反向代理终结 TLS 时,用 `--transport http --host 127.0.0.1 --public-name mcp.example.com`,
|
|
335
|
+
并让代理透传 `Authorization` 头。
|
|
336
|
+
- 负载均衡或网关在另一台机器上时,保持 `--transport https`(自签证书也可以),在 `--public-name` 里写上负载均衡
|
|
337
|
+
转发时带的 `Host` 名,并让它透传 `Authorization`。健康检查可以用 `GET /healthz`:不需要 token,只返回
|
|
338
|
+
`{"status": "ok"}`(需 vmware-policy ≥ 1.23.0)。
|
|
339
|
+
- 每个请求带上 `traceparent` 或 `X-Request-ID`,它会记进审计记录;用 `vmware-audit log --correlation-id ID`
|
|
340
|
+
就能查到平台上某一次请求对应的调用。
|
|
341
|
+
- 审计日志把每个调用者记为 `token:<名字>`。调用并行执行,同一 target 上也一样:server 为每个 target 最多保持 `VMWARE_MCP_POOL_SIZE`(默认 2)个会话,每个会话都是在该 target 上的一次登录;一个调用最多等 300 秒拿到空闲会话(vmware-policy ≥ 1.22.0)。
|
|
342
|
+
- **能连到这个端点的人,都以该 server 配置的账号操作。** token 只用来识别调用者,不在平台上授予任何权限。
|
|
343
|
+
每个权限级别单独起一个端点。`vmware-storage access-info` 可查看是哪个账号、它能做什么。
|
|
344
|
+
|
|
345
|
+
**只提供读工具,加上你选定的写工具:**
|
|
346
|
+
|
|
347
|
+
```bash
|
|
348
|
+
vmware-storage mcp --expose read --allow-write enable_iscsi
|
|
349
|
+
# 或:VMWARE_STORAGE_MCP_EXPOSE=read VMWARE_STORAGE_MCP_ALLOW_WRITE=enable_iscsi vmware-storage mcp
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
未提供的工具不会出现在客户端的工具列表里。取值错误或写工具名不存在时服务直接退出(exit 2)。
|
|
353
|
+
这只限制提供给客户端的工具,不是授权;账号本身仍应遵循最小权限。
|
|
354
|
+
|
|
355
|
+
详见 `skills/vmware-storage/references/setup-guide.md`("Serving MCP over HTTPS"、"Limiting which tools are offered")。
|
|
356
|
+
|
|
294
357
|
## 许可证
|
|
295
358
|
|
|
296
359
|
[MIT](LICENSE)
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
[English](README.md) | [中文](README-CN.md)
|
|
9
9
|
|
|
10
|
-
VMware vSphere storage management: datastores, iSCSI, vSAN, and read-only Fibre Channel / multipath diagnostics —
|
|
10
|
+
VMware vSphere storage management: datastores, iSCSI, vSAN, and read-only Fibre Channel / multipath diagnostics — 15 MCP tools, domain-focused and lightweight.
|
|
11
11
|
|
|
12
12
|
> Split from vmware-aiops for lighter context and local model compatibility.
|
|
13
13
|
|
|
@@ -15,7 +15,7 @@ VMware vSphere storage management: datastores, iSCSI, vSAN, and read-only Fibre
|
|
|
15
15
|
|
|
16
16
|
## Upgrading to 2.0
|
|
17
17
|
|
|
18
|
-
2.0 renames 10 of its
|
|
18
|
+
2.0 renames 10 of its MCP tools (all but the four that already started with a verb) so every name starts with a verb (e.g. `fc_adapter_list` → `list_fc_adapters`, `storage_device_paths` → `list_storage_device_paths`, `storage_iscsi_add_target` → `add_iscsi_target`). The full old → new table is in
|
|
19
19
|
[RELEASE_NOTES.md](RELEASE_NOTES.md#v200--mcp-tools-renamed-verb-first). Three tools also change a parameter: `browse_datastore` and `scan_datastore_images` take
|
|
20
20
|
`datastore_name` (was `ds_name`, now the same as vmware-aiops' `browse_datastore`), and `list_all_datastores` gains an
|
|
21
21
|
optional `limit` (same as vmware-monitor's). Everything else stays: same tools, safety gates and CLI commands (the CLI
|
|
@@ -88,7 +88,7 @@ chmod 600 ~/.vmware-storage/.env
|
|
|
88
88
|
vmware-storage doctor
|
|
89
89
|
```
|
|
90
90
|
|
|
91
|
-
## MCP Tools (
|
|
91
|
+
## MCP Tools (15)
|
|
92
92
|
|
|
93
93
|
| Category | Tools | Type |
|
|
94
94
|
|----------|-------|------|
|
|
@@ -96,6 +96,7 @@ vmware-storage doctor
|
|
|
96
96
|
| iSCSI | `enable_iscsi`, `get_iscsi_status`, `add_iscsi_target`, `remove_iscsi_target`, `rescan_storage` | Read/Write |
|
|
97
97
|
| vSAN | `get_vsan_health`, `get_vsan_capacity`, `get_vsan_efficiency` | Read |
|
|
98
98
|
| FC / multipath | `list_fc_adapters`, `list_storage_device_paths` | Read |
|
|
99
|
+
| Access | `get_access_info` — which account the server uses and whether it holds each tool's vSphere privileges (root folder) | Read |
|
|
99
100
|
|
|
100
101
|
## Auto-Remediation Patterns (PoC)
|
|
101
102
|
|
|
@@ -209,9 +210,9 @@ vmware-storage-mcp
|
|
|
209
210
|
|
|
210
211
|
## Why a Separate Skill?
|
|
211
212
|
|
|
212
|
-
`vmware-aiops` has
|
|
213
|
+
`vmware-aiops` has 61 MCP tools — too heavy for local LLMs (7B-14B). By splitting storage into its own skill:
|
|
213
214
|
|
|
214
|
-
- **
|
|
215
|
+
- **15 tools** — fits comfortably in small model context windows
|
|
215
216
|
- **Domain-focused** — storage admins get only what they need
|
|
216
217
|
- **Least privilege** — can run under a vCenter service account with storage read-only permissions
|
|
217
218
|
- **Composable** — use alongside vmware-monitor or vmware-aiops as needed
|
|
@@ -238,7 +239,7 @@ vmware-storage-mcp
|
|
|
238
239
|
|
|
239
240
|
| Feature | Description |
|
|
240
241
|
|---------|-------------|
|
|
241
|
-
| Read-heavy |
|
|
242
|
+
| Read-heavy | 11/15 tools are read-only |
|
|
242
243
|
| Preview by default (MCP) | The 4 write tools take `confirm` (default `false`): a call without it changes nothing and returns `blast_radius` (host, adapters, and for target removal the paths, devices and datastores behind the target). `confirm=true` is refused when a datastore would lose every path or part of the blast radius could not be read. `dry_run` is a deprecated alias |
|
|
243
244
|
| Input validation | IP addresses and ports validated before iSCSI operations |
|
|
244
245
|
| Audit logging | All operations logged to `~/.vmware-storage/audit.log` |
|
|
@@ -254,9 +255,73 @@ vmware-storage-mcp
|
|
|
254
255
|
| `get_vsan_health` returns `overall_health: null` | `null` = not asked (see `health_not_queried_reason`), never a measurement; a string is always vSAN's own answer, including its own `"unknown"`. Usual cause: connected to standalone ESXi, but the health service runs in **vCenter**. |
|
|
255
256
|
| Rescan doesn't discover new LUNs | Wait 15-30 seconds after adding targets, then rescan again. Verify target IP is reachable from ESXi. |
|
|
256
257
|
| "Password not found" error | Variable names follow `VMWARE_<TARGET_UPPER>_PASSWORD` (hyphens → underscores). Check `~/.vmware-storage/.env`. |
|
|
258
|
+
| `doctor` fails with "no vSphere role", or every command fails with "session is not authenticated" | The login works but the account has no vSphere role. Assign one (Read-Only or higher) on the vCenter root folder (Administration > Access Control > Global Permissions). Mid-run, the same fault can be an expired session: run the command again. |
|
|
257
259
|
| Connection timeout to vCenter | Use `vmware-storage doctor --skip-auth` to bypass auth checks on high-latency networks. |
|
|
258
260
|
| "Datastore browse did not finish within Ns" | The datastore is very large or busy. Narrow the search with a sub-path and a specific pattern (e.g. `datastore browse ds01 --path templates --pattern "*.ova"`) instead of browsing the root — do not just retry the same broad browse. |
|
|
259
261
|
|
|
262
|
+
<!-- usage: remote-and-exposure -->
|
|
263
|
+
## Remote access (HTTPS) and limiting tools
|
|
264
|
+
|
|
265
|
+
By default `vmware-storage mcp` speaks stdio to one local client and offers every tool. Two options change that
|
|
266
|
+
(vmware-policy ≥ 1.21.0).
|
|
267
|
+
|
|
268
|
+
**Serve over HTTPS** so clients on other machines can connect. Every caller needs a bearer token:
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
vmware-audit token create alice # prints the token once; give it to alice
|
|
272
|
+
vmware-audit token list # names only
|
|
273
|
+
vmware-audit token revoke alice # refused from its next request, no restart
|
|
274
|
+
vmware-storage mcp --transport https --host 0.0.0.0 --port 8443 \
|
|
275
|
+
--cert /etc/vmware-mcp/server.pem --key /etc/vmware-mcp/server-key.pem \
|
|
276
|
+
--public-name mcp.example.com
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
Connect a client (Claude Code shown; any MCP client that supports streamable HTTP and custom headers works):
|
|
280
|
+
|
|
281
|
+
```bash
|
|
282
|
+
claude mcp add --transport http vmware-storage https://mcp.example.com:8443/mcp \
|
|
283
|
+
--header "Authorization: Bearer $VMWARE_MCP_TOKEN"
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
```json
|
|
287
|
+
{
|
|
288
|
+
"mcpServers": {
|
|
289
|
+
"vmware-storage": {
|
|
290
|
+
"type": "http",
|
|
291
|
+
"url": "https://mcp.example.com:8443/mcp",
|
|
292
|
+
"headers": { "Authorization": "Bearer ${VMWARE_MCP_TOKEN}" }
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
- The server will not start without a token, refuses Host/Origin values outside `--public-name`, and checks
|
|
299
|
+
before it binds that unauthenticated requests get 401. Use a certificate your clients trust for those names.
|
|
300
|
+
- Behind a TLS-terminating reverse proxy on the same machine use `--transport http --host 127.0.0.1
|
|
301
|
+
--public-name mcp.example.com` and pass the `Authorization` header through.
|
|
302
|
+
- Behind a load balancer or gateway on another machine, keep `--transport https` (a self-signed certificate is
|
|
303
|
+
fine), list in `--public-name` the host name the balancer sends as `Host`, and have it forward `Authorization`.
|
|
304
|
+
Its health probe can use `GET /healthz`, which needs no token and returns only `{"status": "ok"}`
|
|
305
|
+
(vmware-policy ≥ 1.23.0).
|
|
306
|
+
- Send `traceparent` or `X-Request-ID` with each request to have it stored on the audit row;
|
|
307
|
+
`vmware-audit log --correlation-id ID` then finds the calls behind one platform request.
|
|
308
|
+
- The audit log records each caller as `token:<name>`. Calls run side by side, also on the same target: the server keeps up to `VMWARE_MCP_POOL_SIZE` (default 2) sessions per target, each one a login on that target, and a call waits at most 300 s for a free session (vmware-policy ≥ 1.22.0).
|
|
309
|
+
- **Everyone who can reach the endpoint acts with this server's account.** Tokens identify callers; they grant
|
|
310
|
+
nothing on the platform. Run one endpoint per privilege level. `vmware-storage access-info` shows which account that is and what it may do.
|
|
311
|
+
|
|
312
|
+
**Offer only read tools, plus the writes you choose:**
|
|
313
|
+
|
|
314
|
+
```bash
|
|
315
|
+
vmware-storage mcp --expose read --allow-write enable_iscsi
|
|
316
|
+
# or: VMWARE_STORAGE_MCP_EXPOSE=read VMWARE_STORAGE_MCP_ALLOW_WRITE=enable_iscsi vmware-storage mcp
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
Tools not offered do not appear in the client's tool list. A bad value or an unknown write tool stops the server
|
|
320
|
+
(exit 2). This limits what clients are offered; it is not authorization, so the account itself should be
|
|
321
|
+
least-privilege.
|
|
322
|
+
|
|
323
|
+
Details: `skills/vmware-storage/references/setup-guide.md` ("Serving MCP over HTTPS", "Limiting which tools are offered").
|
|
324
|
+
|
|
260
325
|
## License
|
|
261
326
|
|
|
262
327
|
[MIT](LICENSE)
|
|
@@ -1,3 +1,38 @@
|
|
|
1
|
+
## v2.3.1 — a login with no vSphere role is named as such (AIops#47)
|
|
2
|
+
|
|
3
|
+
* An account that logs in but has no vSphere role (vCenter shows no session for it) is now refused at connect time
|
|
4
|
+
with a message naming the missing role (assign Read-Only or higher), on the `doctor` auth row, the CLI and every
|
|
5
|
+
MCP tool. The session is logged out and never cached. Before, `doctor` passed and every call then failed with
|
|
6
|
+
"the session is not authenticated".
|
|
7
|
+
* Refused only when two signals agree: no session, **and** vCenter refuses a view of the root folder
|
|
8
|
+
(`NotAuthenticated` / `NoPermission`). An account scoped to one folder can also show no session, and still
|
|
9
|
+
connects; anything the check cannot read lets the login through.
|
|
10
|
+
* The MCP hint beside these two errors (tool errors and `get_access_info`) points at `doctor`'s role check
|
|
11
|
+
instead of "verify connectivity".
|
|
12
|
+
* `NotAuthenticated` raised later (session expired, or a role removed while running) now says both causes, on the
|
|
13
|
+
CLI (it was a raw traceback) and over MCP (it was `NotAuthenticated: operation failed.`).
|
|
14
|
+
* Requires vmware-policy 1.23.0.
|
|
15
|
+
|
|
16
|
+
## v2.3.0 — calls run side by side on one target; `get_access_info`
|
|
17
|
+
|
|
18
|
+
**Concurrent calls (HLD §16 D-13(2), issue #18).** On a shared HTTPS server, calls no longer wait for each other:
|
|
19
|
+
|
|
20
|
+
* Each call holds its own vCenter/ESXi session for as long as it runs, so two calls never share one connection.
|
|
21
|
+
Calls on the same target, or naming no target, now run side by side.
|
|
22
|
+
* The server keeps up to `VMWARE_MCP_POOL_SIZE` (default 2) sessions per target. Each session is a login on the
|
|
23
|
+
target, so raising it raises the logins the account holds. A call waits at most 300 s for a free session, then
|
|
24
|
+
fails with a message naming the setting.
|
|
25
|
+
* A dead session (expired token) is logged out and replaced on its next use, as before.
|
|
26
|
+
* The CLI and stdio are unchanged: one session per target.
|
|
27
|
+
|
|
28
|
+
**Check what the account may do (HLD §17 D-17).** New read tool `get_access_info` (CLI: `vmware-storage
|
|
29
|
+
access-info [--tool NAME] [--target T]`) reports which account the server uses on a target and, per tool, whether
|
|
30
|
+
that account holds the vSphere privileges the tool needs on the root folder. `not_granted_at_root` is not "no
|
|
31
|
+
access" (the privilege may be granted on a cluster, host or datastore); `undetermined` is never read as granted.
|
|
32
|
+
15 MCP tools (11 read, 4 write).
|
|
33
|
+
|
|
34
|
+
Requires `vmware-policy>=1.22.0`.
|
|
35
|
+
|
|
1
36
|
## v2.2.0 — serve MCP over HTTPS
|
|
2
37
|
|
|
3
38
|
`vmware-storage mcp` can now serve the network as well as stdio (HLD §16, via vmware-policy 1.21.0):
|
|
@@ -8,6 +43,15 @@ vmware-storage mcp --transport https --host 0.0.0.0 --port 8443 \
|
|
|
8
43
|
--cert server.pem --key server-key.pem --public-name mcp.example.com
|
|
9
44
|
```
|
|
10
45
|
|
|
46
|
+
Connect a client and manage callers (Claude Code shown; any MCP client with streamable HTTP and custom headers works):
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
claude mcp add --transport http vmware-storage https://mcp.example.com:8443/mcp \
|
|
50
|
+
--header "Authorization: Bearer $VMWARE_MCP_TOKEN"
|
|
51
|
+
vmware-audit token list # names only
|
|
52
|
+
vmware-audit token revoke alice # refused from its next request, no restart
|
|
53
|
+
```
|
|
54
|
+
|
|
11
55
|
* Every request needs `Authorization: Bearer <token>`; the server will not start without a token, refuses Host or
|
|
12
56
|
Origin values outside `--public-name`, and checks itself (unauthenticated requests must get 401) before it
|
|
13
57
|
binds. `--transport http` binds loopback only, for a TLS-terminating reverse proxy.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "vmware-storage",
|
|
3
3
|
"name": "VMware Storage",
|
|
4
|
-
"description": "VMware vSphere storage with
|
|
4
|
+
"description": "VMware vSphere storage with 15 MCP tools: datastores, iSCSI, vSAN, FC multipath.",
|
|
5
5
|
"skills": [
|
|
6
6
|
"./skills"
|
|
7
7
|
],
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"command": "uvx",
|
|
12
12
|
"args": [
|
|
13
13
|
"--from",
|
|
14
|
-
"vmware-storage==2.
|
|
14
|
+
"vmware-storage==2.3.1",
|
|
15
15
|
"vmware-storage-mcp"
|
|
16
16
|
]
|
|
17
17
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zw008/vmware-storage",
|
|
3
|
-
"version": "2.
|
|
4
|
-
"description": "VMware vSphere storage with
|
|
3
|
+
"version": "2.3.1",
|
|
4
|
+
"description": "VMware vSphere storage with 15 MCP tools: datastores, iSCSI, vSAN, FC multipath.",
|
|
5
5
|
"private": true,
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"homepage": "https://github.com/vmware-skills/VMware-Storage",
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "vmware-storage"
|
|
7
|
-
version = "2.
|
|
7
|
+
version = "2.3.1"
|
|
8
8
|
description = "VMware vSphere storage management: datastores, iSCSI, vSAN. Domain-focused MCP skill."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -17,7 +17,7 @@ dependencies = [
|
|
|
17
17
|
"rich>=13.0,<15.0",
|
|
18
18
|
"python-dotenv>=1.0,<2.0",
|
|
19
19
|
"mcp[cli]>=1.28,<2.0",
|
|
20
|
-
"vmware-policy>=1.
|
|
20
|
+
"vmware-policy>=1.23.0,<2.0",
|
|
21
21
|
]
|
|
22
22
|
|
|
23
23
|
|
|
@@ -2,17 +2,17 @@
|
|
|
2
2
|
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
|
|
3
3
|
"name": "io.github.vmware-skills/vmware-storage",
|
|
4
4
|
"title": "VMware Storage",
|
|
5
|
-
"description": "VMware vSphere storage with
|
|
5
|
+
"description": "VMware vSphere storage with 15 MCP tools: datastores, iSCSI, vSAN, FC multipath.",
|
|
6
6
|
"repository": {
|
|
7
7
|
"url": "https://github.com/vmware-skills/VMware-Storage",
|
|
8
8
|
"source": "github"
|
|
9
9
|
},
|
|
10
|
-
"version": "2.
|
|
10
|
+
"version": "2.3.1",
|
|
11
11
|
"packages": [
|
|
12
12
|
{
|
|
13
13
|
"registryType": "pypi",
|
|
14
14
|
"identifier": "vmware-storage",
|
|
15
|
-
"version": "2.
|
|
15
|
+
"version": "2.3.1",
|
|
16
16
|
"runtimeHint": "uvx",
|
|
17
17
|
"packageArguments": [
|
|
18
18
|
{
|
|
@@ -21,7 +21,7 @@ compatibility: >
|
|
|
21
21
|
|
|
22
22
|
> **Disclaimer**: This is a community-maintained open-source project and is **not affiliated with, endorsed by, or sponsored by VMware, Inc. or Broadcom Inc.** "VMware" and "vSphere" are trademarks of Broadcom. Source code is publicly auditable at [github.com/vmware-skills/VMware-Storage](https://github.com/vmware-skills/VMware-Storage) under the MIT license.
|
|
23
23
|
|
|
24
|
-
VMware vSphere storage management —
|
|
24
|
+
VMware vSphere storage management — 15 MCP tools for datastores, iSCSI, vSAN, Fibre Channel / multipath diagnostics, and an access self-check.
|
|
25
25
|
|
|
26
26
|
> Split from vmware-aiops for lighter context and local model compatibility.
|
|
27
27
|
> **Companion skills**: [vmware-aiops](https://github.com/vmware-skills/VMware-AIops) (VM lifecycle), [vmware-monitor](https://github.com/vmware-skills/VMware-Monitor) (read-only monitoring), [vmware-vks](https://github.com/vmware-skills/VMware-VKS) (Tanzu Kubernetes), [vmware-nsx](https://github.com/vmware-skills/VMware-NSX) (NSX networking), [vmware-nsx-security](https://github.com/vmware-skills/VMware-NSX-Security) (DFW/firewall), [vmware-aria](https://github.com/vmware-skills/VMware-Aria) (metrics/alerts/capacity), [vmware-avi](https://github.com/vmware-skills/VMware-AVI) (AVI/ALB/AKO), [vmware-harden](https://github.com/vmware-skills/VMware-Harden) (compliance baselines).
|
|
@@ -35,11 +35,12 @@ VMware vSphere storage management — 14 MCP tools for datastores, iSCSI, vSAN,
|
|
|
35
35
|
| **iSCSI** | enable adapter, show status, add target, remove target, rescan HBAs | 5 |
|
|
36
36
|
| **vSAN** | cluster health summary, capacity overview (total/used/free), data-efficiency (dedup/compression) | 3 |
|
|
37
37
|
| **FC / multipath** (read-only) | FC HBA inventory with WWPN/WWNN; per-device path state across hosts, datastore backing devices, path-count differences across hosts | 2 |
|
|
38
|
+
| **Access** (read-only) | which account the server uses and whether it holds each tool's vSphere privileges | 1 |
|
|
38
39
|
|
|
39
40
|
## Quick Install
|
|
40
41
|
|
|
41
42
|
```bash
|
|
42
|
-
uv tool install vmware-storage==2.
|
|
43
|
+
uv tool install vmware-storage==2.3.1
|
|
43
44
|
vmware-storage init # guided setup: writes config + .env (chmod 600, password grep-safe), then verifies
|
|
44
45
|
vmware-storage doctor
|
|
45
46
|
```
|
|
@@ -83,6 +84,7 @@ vmware-storage doctor
|
|
|
83
84
|
- Adapter sanity: `iscsi status` first — if already enabled, do not "re-enable"; just add the target.
|
|
84
85
|
- Idempotency: `add-target` is idempotent (re-adding same IP is a no-op), but `remove-target` is not safely reversible mid-IO. Always verify no LUNs from this target are in use before removing.
|
|
85
86
|
- Existing targets: list them first; some sites add targets one-per-host while others use cluster-wide. Check site convention.
|
|
87
|
+
- Account rights: `access-info --tool add_iscsi_target` checks Host.Config.Storage on the root folder; `not_granted_at_root` may still be granted on that host's cluster.
|
|
86
88
|
|
|
87
89
|
**Steps**:
|
|
88
90
|
1. `iscsi status esxi-01` → confirm adapter state and existing targets
|
|
@@ -145,7 +147,7 @@ vmware-storage iscsi status esxi-lab --target lab-esxi
|
|
|
145
147
|
| Cloud models (Claude, GPT-4o) | Either | MCP gives structured JSON I/O |
|
|
146
148
|
| Automated pipelines | **MCP** | Type-safe parameters, structured output |
|
|
147
149
|
|
|
148
|
-
## MCP Tools (
|
|
150
|
+
## MCP Tools (15 — 11 read, 4 write)
|
|
149
151
|
|
|
150
152
|
All MCP tools accept an optional `target` parameter to select which vCenter/ESXi to connect to. The 4 write tools take `confirm` (default false): without it they change nothing and return `blast_radius` — the host and adapters touched, and for `remove_iscsi_target` the paths, devices and datastores behind the target. Show it to the user; pass `confirm: true` only after they decide. `dry_run` is a deprecated alias.
|
|
151
153
|
|
|
@@ -167,8 +169,9 @@ The four Datastore read tools return the family list envelope — `{items, retur
|
|
|
167
169
|
| | `get_vsan_efficiency` | Read | Dedup + compression status (vSAN Management SDK) |
|
|
168
170
|
| FC / multipath | `list_fc_adapters` | Read | FC/FCoE HBAs per host: WWPN/WWNN, port type, status, reported speed |
|
|
169
171
|
| | `list_storage_device_paths` | Read | Per-device path state across a cluster/host/datastore; visibility and path-count differences |
|
|
172
|
+
| Access | `get_access_info` | Read | Account in use and, per tool, whether its privileges are granted on the root folder |
|
|
170
173
|
|
|
171
|
-
**Read/write split**:
|
|
174
|
+
**Read/write split**: 11 tools are read-only, 4 modify state. Write tools require explicit parameters (host name, IP address), preview unless `confirm: true`, refuse when a datastore would lose every path or the host's storage view cannot be read, and are audit-logged. `remove_iscsi_target` is classified `risk:high` (destructive — LUNs can become inaccessible) and goes through the policy confirmation gate.
|
|
172
175
|
|
|
173
176
|
Running with local or small models? See [`references/agent-guardrails.md`](references/agent-guardrails.md).
|
|
174
177
|
|
|
@@ -197,6 +200,7 @@ vmware-storage paths devices (--cluster <c> | --host <h> | --datastore <ds>) [--
|
|
|
197
200
|
|
|
198
201
|
# Diagnostics
|
|
199
202
|
vmware-storage doctor [--skip-auth]
|
|
203
|
+
vmware-storage access-info [--tool <name>] [--target <name>] # what may this account do?
|
|
200
204
|
```
|
|
201
205
|
|
|
202
206
|
> Full CLI reference with all options and output formats: see `references/cli-reference.md`
|
|
@@ -230,6 +234,10 @@ After adding iSCSI targets, the storage subsystem may need 10-30 seconds to enum
|
|
|
230
234
|
|
|
231
235
|
The password environment variable is missing. Variable names follow the pattern `VMWARE_<TARGET_NAME_UPPER>_PASSWORD` where hyphens become underscores. Example: target `my-vcenter` needs `VMWARE_MY_VCENTER_PASSWORD`. Check your `~/.vmware-storage/.env` file.
|
|
232
236
|
|
|
237
|
+
### "Session is not authenticated" or "no vSphere role" right after login
|
|
238
|
+
|
|
239
|
+
The password is right; the account has no vSphere role, so vCenter shows no session for it and every call fails. `doctor` now reports this on the auth row. Assign the account a role (Read-Only or higher) on the vCenter root folder under Administration > Access Control > Global Permissions. Seen mid-run, the same fault can also be an expired session: run the command again.
|
|
240
|
+
|
|
233
241
|
### Doctor reports ".env permissions too open"
|
|
234
242
|
|
|
235
243
|
The `.env` file contains passwords and must have owner-only permissions:
|
|
@@ -249,7 +257,7 @@ Corporate TLS proxies inject certificates that uv's bundled CA store doesn't tru
|
|
|
249
257
|
## Safety
|
|
250
258
|
|
|
251
259
|
- **No VM operations**: This skill cannot power on/off, create, delete, or modify VMs — that scope belongs to `vmware-aiops`
|
|
252
|
-
- **Read-heavy**:
|
|
260
|
+
- **Read-heavy**: 11 of 15 tools are read-only (list, browse, scan, cached images, status, health, capacity, efficiency, FC adapters, device paths, access info)
|
|
253
261
|
- **Audit logging**: All operations (including reads) are logged to `~/.vmware/audit.db` (SQLite WAL, via vmware-policy) with timestamp, user, target, operation, parameters, and result
|
|
254
262
|
- **Double confirmation**: CLI write commands (iSCSI enable, add/remove target) require two separate "Are you sure?" prompts before executing
|
|
255
263
|
- **Dry-run mode**: All write commands support `--dry-run` to preview API calls without executing
|
|
@@ -263,7 +271,7 @@ Corporate TLS proxies inject certificates that uv's bundled CA store doesn't tru
|
|
|
263
271
|
## Setup
|
|
264
272
|
|
|
265
273
|
```bash
|
|
266
|
-
uv tool install vmware-storage==2.
|
|
274
|
+
uv tool install vmware-storage==2.3.1
|
|
267
275
|
mkdir -p ~/.vmware-storage
|
|
268
276
|
cp config.example.yaml ~/.vmware-storage/config.yaml
|
|
269
277
|
# Edit config.yaml with your vCenter/ESXi targets
|