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.
Files changed (111) hide show
  1. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/.claude-plugin/plugin.json +2 -2
  2. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/.mcp.json +1 -1
  3. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/PKG-INFO +73 -8
  4. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/README-CN.md +69 -6
  5. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/README.md +71 -6
  6. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/RELEASE_NOTES.md +44 -0
  7. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/openclaw.plugin.json +2 -2
  8. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/package.json +2 -2
  9. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/pyproject.toml +2 -2
  10. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/server.json +3 -3
  11. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/skills/vmware-storage/SKILL.md +14 -6
  12. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/skills/vmware-storage/references/agent-guardrails.md +1 -1
  13. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/skills/vmware-storage/references/capabilities.md +15 -3
  14. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/skills/vmware-storage/references/cli-reference.md +17 -0
  15. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/skills/vmware-storage/references/setup-guide.md +37 -3
  16. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_atexit_handlers_do_not_accumulate.py +14 -11
  17. vmware_storage-2.3.1/tests/eval/regression/test_login_without_a_role.py +215 -0
  18. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_session_probe_eviction.py +23 -9
  19. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_storage_hardening_fixes.py +3 -3
  20. vmware_storage-2.3.1/tests/test_access_info.py +108 -0
  21. vmware_storage-2.3.1/tests/test_session_pool.py +219 -0
  22. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/uv.lock +5 -5
  23. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/vmware_storage/__init__.py +1 -1
  24. vmware_storage-2.3.1/vmware_storage/access_requirements.py +46 -0
  25. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/vmware_storage/cli.py +38 -2
  26. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/vmware_storage/connection.py +86 -37
  27. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/vmware_storage/mcp_server/server.py +101 -20
  28. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/.clawhubignore +0 -0
  29. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/.env.example +0 -0
  30. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/.gitignore +0 -0
  31. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/Dockerfile +0 -0
  32. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/LICENSE +0 -0
  33. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/SECURITY.md +0 -0
  34. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/config.example.yaml +0 -0
  35. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/docker-compose.yml +0 -0
  36. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/examples/mcp-configs/README.md +0 -0
  37. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/examples/mcp-configs/claude-code.json +0 -0
  38. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/examples/mcp-configs/continue.yaml +0 -0
  39. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/examples/mcp-configs/cursor.json +0 -0
  40. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/examples/mcp-configs/goose.json +0 -0
  41. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/examples/mcp-configs/localcowork.json +0 -0
  42. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/examples/mcp-configs/mcp-agent.yaml +0 -0
  43. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/examples/mcp-configs/vscode-copilot.json +0 -0
  44. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/patterns/README.md +0 -0
  45. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/patterns/iscsi-target-stale-rescan.yaml +0 -0
  46. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/skills/vmware-storage/evals/evals.json +0 -0
  47. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/smithery.yaml +0 -0
  48. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/__init__.py +0 -0
  49. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/conftest.py +0 -0
  50. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/__init__.py +0 -0
  51. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/capability/__init__.py +0 -0
  52. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/capability/_family.py +0 -0
  53. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/capability/_scores.json +0 -0
  54. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/capability/_scoring.py +0 -0
  55. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/capability/_skill.py +0 -0
  56. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/capability/conftest.py +0 -0
  57. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/capability/test_entity_reachability.py +0 -0
  58. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/capability/test_error_actionability.py +0 -0
  59. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/capability/test_tool_description_quality.py +0 -0
  60. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/capability/test_tool_manifest_budget.py +0 -0
  61. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/__init__.py +0 -0
  62. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_audit_isolation.py +0 -0
  63. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_cached_loader_agrees_with_the_resolver.py +0 -0
  64. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_capability_grader.py +0 -0
  65. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_cli_writes_guarded.py +0 -0
  66. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_credential_env_override.py +0 -0
  67. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_datastore_list_renders.py +0 -0
  68. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_doctor_authenticates_every_target.py +0 -0
  69. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_doctor_uses_the_config_the_tools_use.py +0 -0
  70. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_env_secret_obfuscation.py +0 -0
  71. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_fc_multipath.py +0 -0
  72. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_instructions_name_targets.py +0 -0
  73. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_inventory_scale_n1.py +0 -0
  74. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_iscsi_unreachable_host.py +0 -0
  75. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_release_blockers.py +0 -0
  76. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_remedy_survives_a_long_home.py +0 -0
  77. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_result_envelope.py +0 -0
  78. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_returned_failure_is_audited.py +0 -0
  79. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_storage_ops_behavior.py +0 -0
  80. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_tool_names_2_0.py +0 -0
  81. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_vim_attribute_conformance.py +0 -0
  82. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_vsan_efficiency.py +0 -0
  83. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_vsan_health_is_actually_queried.py +0 -0
  84. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/regression/test_vsan_reports_what_it_could_not_read.py +0 -0
  85. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/spec/__init__.py +0 -0
  86. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/spec/vsan_efficiency_endpoints.py +0 -0
  87. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/eval/spec/vsan_health_endpoints.py +0 -0
  88. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/test_init_and_onboarding.py +0 -0
  89. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/test_iscsi_gate.py +0 -0
  90. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/test_no_destructive_ops.py +0 -0
  91. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/test_no_destructive_vm_code.py +0 -0
  92. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/test_safe_error_passthrough.py +0 -0
  93. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/tests/test_stop_signal_runs_atexit.py +0 -0
  94. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/vmware_storage/config.py +0 -0
  95. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/vmware_storage/doctor.py +0 -0
  96. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/vmware_storage/init_wizard.py +0 -0
  97. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/vmware_storage/mcp_server/__init__.py +0 -0
  98. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/vmware_storage/mcp_server/__main__.py +0 -0
  99. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/vmware_storage/notify/__init__.py +0 -0
  100. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/vmware_storage/notify/audit.py +0 -0
  101. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/vmware_storage/ops/__init__.py +0 -0
  102. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/vmware_storage/ops/datastore_browser.py +0 -0
  103. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/vmware_storage/ops/inventory.py +0 -0
  104. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/vmware_storage/ops/iscsi_config.py +0 -0
  105. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/vmware_storage/ops/iscsi_gate.py +0 -0
  106. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/vmware_storage/ops/multipath.py +0 -0
  107. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/vmware_storage/ops/storage_paths.py +0 -0
  108. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/vmware_storage/ops/vsan.py +0 -0
  109. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/vmware_storage/ops/vsan_efficiency.py +0 -0
  110. {vmware_storage-2.2.0 → vmware_storage-2.3.1}/vmware_storage/ops/vsan_sdk.py +0 -0
  111. {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.2.0",
6
- "description": "VMware vSphere storage with 14 MCP tools: datastores, iSCSI, vSAN, FC multipath.",
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",
@@ -5,7 +5,7 @@
5
5
  "command": "uvx",
6
6
  "args": [
7
7
  "--from",
8
- "vmware-storage==2.2.0",
8
+ "vmware-storage==2.3.1",
9
9
  "vmware-storage-mcp"
10
10
  ]
11
11
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: vmware-storage
3
- Version: 2.2.0
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.21.0
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 — 14 MCP tools, domain-focused and lightweight.
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 14 MCP tools 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
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 (14)
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 60 MCP tools — too heavy for local LLMs (7B-14B). By splitting storage into its own skill:
234
+ `vmware-aiops` has 61 MCP tools — too heavy for local LLMs (7B-14B). By splitting storage into its own skill:
234
235
 
235
- - **14 tools** — fits comfortably in small model context windows
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 | 10/14 tools are read-only |
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)/ 多路径诊断 — 14 个 MCP 工具,领域专注、轻量级。
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 把 14 个 MCP 工具中的 10 个改成动词在前(例如 `fc_adapter_list` → `list_fc_adapters`, `storage_device_paths` → `list_storage_device_paths`, `storage_iscsi_add_target` → `add_iscsi_target`),完整的新旧名对照表见
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 工具(14 个)
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` 有 60 个 MCP 工具——对本地小模型(7B-14B)来说上下文占用太重。独立拆分后:
252
+ `vmware-aiops` 有 61 个 MCP 工具——对本地小模型(7B-14B)来说上下文占用太重。独立拆分后:
252
253
 
253
- - **14 个工具** — 完全适合小模型上下文窗口
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
- | 只读为主 | 14 个工具中 10 个只读 |
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 — 14 MCP tools, domain-focused and lightweight.
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 14 MCP tools 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
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 (14)
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 60 MCP tools — too heavy for local LLMs (7B-14B). By splitting storage into its own skill:
213
+ `vmware-aiops` has 61 MCP tools — too heavy for local LLMs (7B-14B). By splitting storage into its own skill:
213
214
 
214
- - **14 tools** — fits comfortably in small model context windows
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 | 10/14 tools are read-only |
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 14 MCP tools: datastores, iSCSI, vSAN, FC multipath.",
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.2.0",
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.2.0",
4
- "description": "VMware vSphere storage with 14 MCP tools: datastores, iSCSI, vSAN, FC multipath.",
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.2.0"
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.21.0,<2.0",
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 14 MCP tools: datastores, iSCSI, vSAN, FC multipath.",
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.2.0",
10
+ "version": "2.3.1",
11
11
  "packages": [
12
12
  {
13
13
  "registryType": "pypi",
14
14
  "identifier": "vmware-storage",
15
- "version": "2.2.0",
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 — 14 MCP tools for datastores, iSCSI, vSAN, and Fibre Channel / multipath diagnostics.
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.2.0
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 (14 — 10 read, 4 write)
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**: 10 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.
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**: 10 of 14 tools are read-only (list, browse, scan, cached images, status, health, capacity, efficiency, FC adapters, device paths)
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.2.0
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