vmware-storage 2.4.2__tar.gz → 2.6.0__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 (125) hide show
  1. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/.claude-plugin/plugin.json +2 -2
  2. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/.mcp.json +1 -1
  3. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/PKG-INFO +18 -9
  4. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/README-CN.md +14 -7
  5. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/README.md +16 -7
  6. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/RELEASE_NOTES.md +17 -4
  7. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/SECURITY.md +2 -2
  8. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/openclaw.plugin.json +2 -2
  9. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/package.json +2 -2
  10. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/pyproject.toml +2 -2
  11. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/server.json +3 -3
  12. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/skills/vmware-storage/SKILL.md +10 -7
  13. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/skills/vmware-storage/references/agent-guardrails.md +1 -1
  14. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/skills/vmware-storage/references/capabilities.md +5 -4
  15. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/skills/vmware-storage/references/cli-reference.md +13 -0
  16. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/skills/vmware-storage/references/setup-guide.md +3 -3
  17. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/regression/test_audit_isolation.py +11 -4
  18. vmware_storage-2.6.0/tests/eval/regression/test_datastore_cli_json.py +62 -0
  19. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/regression/test_datastore_list_renders.py +3 -1
  20. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/regression/test_storage_hardening_fixes.py +12 -12
  21. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/regression/test_vsan_efficiency.py +17 -0
  22. vmware_storage-2.6.0/tests/test_datastore_vm_usage.py +106 -0
  23. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/test_iscsi_gate.py +25 -17
  24. vmware_storage-2.6.0/tests/test_request_error_hints.py +29 -0
  25. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/uv.lock +9 -9
  26. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/vmware_storage/__init__.py +1 -1
  27. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/vmware_storage/access_requirements.py +1 -0
  28. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/vmware_storage/cli.py +12 -6
  29. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/vmware_storage/mcp_server/server.py +70 -56
  30. vmware_storage-2.6.0/vmware_storage/ops/datastore_usage.py +136 -0
  31. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/vmware_storage/ops/iscsi_gate.py +8 -13
  32. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/vmware_storage/ops/vsan.py +6 -2
  33. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/vmware_storage/ops/vsan_efficiency.py +13 -0
  34. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/.clawhubignore +0 -0
  35. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/.env.example +0 -0
  36. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/.gitignore +0 -0
  37. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/Dockerfile +0 -0
  38. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/LICENSE +0 -0
  39. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/config.example.yaml +0 -0
  40. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/docker-compose.yml +0 -0
  41. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/examples/mcp-configs/README.md +0 -0
  42. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/examples/mcp-configs/claude-code.json +0 -0
  43. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/examples/mcp-configs/continue.yaml +0 -0
  44. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/examples/mcp-configs/cursor.json +0 -0
  45. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/examples/mcp-configs/goose.json +0 -0
  46. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/examples/mcp-configs/localcowork.json +0 -0
  47. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/examples/mcp-configs/mcp-agent.yaml +0 -0
  48. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/examples/mcp-configs/vscode-copilot.json +0 -0
  49. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/patterns/README.md +0 -0
  50. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/patterns/iscsi-target-stale-rescan.yaml +0 -0
  51. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/skills/vmware-storage/evals/evals.json +0 -0
  52. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/smithery.yaml +0 -0
  53. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/__init__.py +0 -0
  54. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/conftest.py +0 -0
  55. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/__init__.py +0 -0
  56. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/capability/__init__.py +0 -0
  57. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/capability/_family.py +0 -0
  58. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/capability/_scores.json +0 -0
  59. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/capability/_scoring.py +0 -0
  60. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/capability/_skill.py +0 -0
  61. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/capability/conftest.py +0 -0
  62. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/capability/test_entity_reachability.py +0 -0
  63. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/capability/test_error_actionability.py +0 -0
  64. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/capability/test_tool_description_quality.py +0 -0
  65. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/capability/test_tool_manifest_budget.py +0 -0
  66. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/regression/__init__.py +0 -0
  67. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/regression/test_atexit_handlers_do_not_accumulate.py +0 -0
  68. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/regression/test_browse_ds_path_join.py +0 -0
  69. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/regression/test_browse_sees_every_file.py +0 -0
  70. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/regression/test_cached_loader_agrees_with_the_resolver.py +0 -0
  71. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/regression/test_capability_grader.py +0 -0
  72. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/regression/test_cli_writes_guarded.py +0 -0
  73. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/regression/test_credential_env_override.py +0 -0
  74. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/regression/test_doctor_authenticates_every_target.py +0 -0
  75. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/regression/test_doctor_uses_the_config_the_tools_use.py +0 -0
  76. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/regression/test_env_secret_obfuscation.py +0 -0
  77. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/regression/test_error_hints_fit_the_surface.py +0 -0
  78. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/regression/test_fc_multipath.py +0 -0
  79. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/regression/test_image_registry_cross_process.py +0 -0
  80. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/regression/test_instructions_name_targets.py +0 -0
  81. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/regression/test_inventory_scale_n1.py +0 -0
  82. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/regression/test_iscsi_unreachable_host.py +0 -0
  83. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/regression/test_list_cached_images_target.py +0 -0
  84. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/regression/test_login_without_a_role.py +0 -0
  85. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/regression/test_release_blockers.py +0 -0
  86. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/regression/test_remedy_survives_a_long_home.py +0 -0
  87. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/regression/test_result_envelope.py +0 -0
  88. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/regression/test_returned_failure_is_audited.py +0 -0
  89. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/regression/test_scan_populates_image_cache.py +0 -0
  90. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/regression/test_session_probe_eviction.py +0 -0
  91. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/regression/test_storage_ops_behavior.py +0 -0
  92. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/regression/test_tool_names_2_0.py +0 -0
  93. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/regression/test_vim_attribute_conformance.py +0 -0
  94. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/regression/test_vsan_health_is_actually_queried.py +0 -0
  95. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/regression/test_vsan_reports_what_it_could_not_read.py +0 -0
  96. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/spec/__init__.py +0 -0
  97. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/spec/vsan_efficiency_endpoints.py +0 -0
  98. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/eval/spec/vsan_health_endpoints.py +0 -0
  99. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/test_access_info.py +0 -0
  100. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/test_filelock.py +0 -0
  101. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/test_init_and_onboarding.py +0 -0
  102. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/test_no_destructive_ops.py +0 -0
  103. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/test_no_destructive_vm_code.py +0 -0
  104. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/test_policy_roles.py +0 -0
  105. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/test_safe_error_passthrough.py +0 -0
  106. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/test_session_pool.py +0 -0
  107. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/tests/test_stop_signal_runs_atexit.py +0 -0
  108. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/vmware_storage/_filelock.py +0 -0
  109. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/vmware_storage/config.py +0 -0
  110. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/vmware_storage/connection.py +0 -0
  111. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/vmware_storage/doctor.py +0 -0
  112. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/vmware_storage/init_wizard.py +0 -0
  113. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/vmware_storage/mcp_server/__init__.py +0 -0
  114. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/vmware_storage/mcp_server/__main__.py +0 -0
  115. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/vmware_storage/notify/__init__.py +0 -0
  116. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/vmware_storage/notify/audit.py +0 -0
  117. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/vmware_storage/ops/__init__.py +0 -0
  118. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/vmware_storage/ops/datastore_browser.py +0 -0
  119. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/vmware_storage/ops/inventory.py +0 -0
  120. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/vmware_storage/ops/iscsi_config.py +0 -0
  121. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/vmware_storage/ops/multipath.py +0 -0
  122. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/vmware_storage/ops/storage_paths.py +0 -0
  123. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/vmware_storage/ops/vsan_sdk.py +0 -0
  124. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/vmware_storage/policy_environment.py +0 -0
  125. {vmware_storage-2.4.2 → vmware_storage-2.6.0}/vmware_storage/policy_roles.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.4.2",
6
- "description": "VMware vSphere storage with 15 MCP tools: datastores, iSCSI, vSAN, FC multipath.",
5
+ "version": "2.6.0",
6
+ "description": "VMware vSphere storage with 16 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.4.2",
8
+ "vmware-storage==2.6.0",
9
9
  "vmware-storage-mcp"
10
10
  ]
11
11
  }
@@ -1,12 +1,12 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: vmware-storage
3
- Version: 2.4.2
3
+ Version: 2.6.0
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
7
7
  Project-URL: Issues, https://github.com/vmware-skills/VMware-Storage/issues
8
8
  Project-URL: Changelog, https://github.com/vmware-skills/VMware-Storage/blob/main/RELEASE_NOTES.md
9
- Author-email: Wei Zhou <wei-wz.zhou@broadcom.com>
9
+ Author-email: Wei Zhou <zhouwei008@gmail.com>
10
10
  License-Expression: MIT
11
11
  License-File: LICENSE
12
12
  Requires-Python: >=3.10
@@ -22,13 +22,15 @@ Description-Content-Type: text/markdown
22
22
  <!-- mcp-name: io.github.vmware-skills/vmware-storage -->
23
23
  # VMware Storage
24
24
 
25
- > **Author**: Wei Zhou, VMware by Broadcom — wei-wz.zhou@broadcom.com
25
+ For a read-only check of this skill with your model and agent host, use the shared [model-fit self-test](https://github.com/vmware-skills/marketplace/blob/main/MODEL_FIT_SELF_TEST.md) in the marketplace root.
26
+
27
+ > **Author**: Wei Zhou, VMware by Broadcom — zhouwei008@gmail.com
26
28
  > This is a community-driven project by a VMware engineer, not an official VMware product.
27
29
  > For official VMware developer tools see [developer.broadcom.com](https://developer.broadcom.com).
28
30
 
29
31
  [English](README.md) | [中文](README-CN.md)
30
32
 
31
- VMware vSphere storage management: datastores, iSCSI, vSAN, and read-only Fibre Channel / multipath diagnostics — 15 MCP tools, domain-focused and lightweight.
33
+ VMware vSphere storage management: datastores, iSCSI, vSAN, and read-only Fibre Channel / multipath diagnostics — 16 MCP tools, domain-focused and lightweight.
32
34
 
33
35
  > Split from vmware-aiops for lighter context and local model compatibility.
34
36
 
@@ -109,11 +111,11 @@ chmod 600 ~/.vmware-storage/.env
109
111
  vmware-storage doctor
110
112
  ```
111
113
 
112
- ## MCP Tools (15)
114
+ ## MCP Tools (16)
113
115
 
114
116
  | Category | Tools | Type |
115
117
  |----------|-------|------|
116
- | Datastore | `list_all_datastores`, `browse_datastore`, `scan_datastore_images`, `list_cached_images` | Read |
118
+ | Datastore | `list_all_datastores`, `get_datastore_vm_usage`, `browse_datastore`, `scan_datastore_images`, `list_cached_images` | Read |
117
119
  | iSCSI | `enable_iscsi`, `get_iscsi_status`, `add_iscsi_target`, `remove_iscsi_target`, `rescan_storage` | Read/Write |
118
120
  | vSAN | `get_vsan_health`, `get_vsan_capacity`, `get_vsan_efficiency` | Read |
119
121
  | FC / multipath | `list_fc_adapters`, `list_storage_device_paths` | Read |
@@ -135,6 +137,13 @@ The `add-target` command automatically rescans storage. Use `--dry-run` to previ
135
137
 
136
138
  ### Find Deployable Images Across Datastores
137
139
 
140
+ For scripts, add `--json` to `datastore list`, `datastore browse`, or
141
+ `datastore scan-images`. Successful output is the complete result envelope,
142
+ including `items`, counts, truncation and any cache note. Without the flag,
143
+ list keeps its table and browse/scan-images keep their legacy JSON arrays.
144
+ Other read commands already output JSON by default. Failures still exit nonzero
145
+ with the existing CLI error message.
146
+
138
147
  1. List all datastores: `vmware-storage datastore list`
139
148
  2. Scan for images: `vmware-storage datastore scan-images datastore01`
140
149
  3. Browse with a pattern: `vmware-storage datastore browse datastore01 --pattern "*.iso"`
@@ -233,7 +242,7 @@ vmware-storage-mcp
233
242
 
234
243
  `vmware-aiops` has 61 MCP tools — too heavy for local LLMs (7B-14B). By splitting storage into its own skill:
235
244
 
236
- - **15 tools** — fits comfortably in small model context windows
245
+ - **16 tools** — fits comfortably in small model context windows
237
246
  - **Domain-focused** — storage admins get only what they need
238
247
  - **Least privilege** — can run under a vCenter service account with storage read-only permissions
239
248
  - **Composable** — use alongside vmware-monitor or vmware-aiops as needed
@@ -260,8 +269,8 @@ vmware-storage-mcp
260
269
 
261
270
  | Feature | Description |
262
271
  |---------|-------------|
263
- | Read-heavy | 11/15 tools are read-only |
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 |
272
+ | Read-heavy | 12/16 tools are read-only |
273
+ | 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. the old `dry_run` alias was removed in 2.4.3 and is refused as an unknown argument |
265
274
  | Input validation | IP addresses and ports validated before iSCSI operations |
266
275
  | Audit logging | All operations logged to `~/.vmware-storage/audit.log` |
267
276
  | No VM operations | Cannot create, delete, or modify VMs |
@@ -1,13 +1,15 @@
1
1
  <!-- mcp-name: io.github.vmware-skills/vmware-storage -->
2
2
  # VMware Storage
3
3
 
4
- > **作者**: Wei Zhou, VMware by Broadcom — wei-wz.zhou@broadcom.com
4
+ 要用自己的模型和 Agent 平台进行只读自测,请看 marketplace 根目录的[共享模型适配自测任务](https://github.com/vmware-skills/marketplace/blob/main/MODEL_FIT_SELF_TEST.md)。
5
+
6
+ > **作者**: Wei Zhou, VMware by Broadcom — zhouwei008@gmail.com
5
7
  > 本项目由 VMware 工程师维护的社区项目,非 VMware 官方产品。
6
8
  > VMware 官方开发者工具请访问 [developer.broadcom.com](https://developer.broadcom.com)。
7
9
 
8
10
  [English](README.md) | [中文](README-CN.md)
9
11
 
10
- VMware vSphere 存储管理:数据存储、iSCSI、vSAN,以及只读的光纤通道(FC)/ 多路径诊断 — 15 个 MCP 工具,领域专注、轻量级。
12
+ VMware vSphere 存储管理:数据存储、iSCSI、vSAN,以及只读的光纤通道(FC)/ 多路径诊断 — 16 个 MCP 工具,领域专注、轻量级。
11
13
 
12
14
  > 从 vmware-aiops 拆分,更轻量的上下文,兼容本地小模型。
13
15
 
@@ -99,11 +101,11 @@ targets:
99
101
  password_env: VMWARE_ESXIPROD_PASSWORD
100
102
  ```
101
103
 
102
- ## MCP 工具(15 个)
104
+ ## MCP 工具(16 个)
103
105
 
104
106
  | 类别 | 工具 | 类型 |
105
107
  |------|------|------|
106
- | 数据存储 | `list_all_datastores`、`browse_datastore`、`scan_datastore_images`、`list_cached_images` | 只读 |
108
+ | 数据存储 | `list_all_datastores`、`get_datastore_vm_usage`、`browse_datastore`、`scan_datastore_images`、`list_cached_images` | 只读 |
107
109
  | iSCSI | `enable_iscsi`、`get_iscsi_status`、`add_iscsi_target`、`remove_iscsi_target`、`rescan_storage` | 读/写 |
108
110
  | vSAN | `get_vsan_health`、`get_vsan_capacity`、`get_vsan_efficiency` | 只读 |
109
111
  | FC / 多路径 | `list_fc_adapters`、`list_storage_device_paths` | 只读 |
@@ -113,6 +115,7 @@ targets:
113
115
 
114
116
  **数据存储**
115
117
  - `list_all_datastores` — 列出所有数据存储,含容量、使用率、可达性
118
+ - `get_datastore_vm_usage` — 一个数据存储上哪些虚拟机占得最多(实际占用 GB,从大到小),以及不属于任何虚拟机的空间
116
119
  - `browse_datastore` — 浏览数据存储目录下的文件(支持 glob 过滤)
117
120
  - `scan_datastore_images` — 扫描可部署镜像(OVA、ISO、OVF、VMDK)
118
121
  - `list_cached_images` — 查询本地镜像注册表(支持按类型/数据存储/target 过滤)
@@ -149,6 +152,10 @@ targets:
149
152
 
150
153
  ### 查找可部署镜像
151
154
 
155
+ 脚本可为 `datastore list`、`datastore browse`、`datastore scan-images` 添加 `--json`。
156
+ 成功时输出完整结果封装,保留 `items`、数量、截断状态及缓存提示。省略该选项时,list 仍为表格,
157
+ browse/scan-images 仍为原有 JSON 数组。其他只读命令已默认输出 JSON;失败仍以非零退出码和现有 CLI 错误消息报告。
158
+
152
159
  1. 列出所有数据存储:`vmware-storage datastore list`
153
160
  2. 扫描镜像:`vmware-storage datastore scan-images datastore01`
154
161
  3. 按模式浏览:`vmware-storage datastore browse datastore01 --pattern "*.iso"`
@@ -251,7 +258,7 @@ vmware-storage-mcp
251
258
 
252
259
  `vmware-aiops` 有 61 个 MCP 工具——对本地小模型(7B-14B)来说上下文占用太重。独立拆分后:
253
260
 
254
- - **15 个工具** — 完全适合小模型上下文窗口
261
+ - **16 个工具** — 完全适合小模型上下文窗口
255
262
  - **领域专注** — 存储管理员只看到需要的工具
256
263
  - **最小权限** — 可以配置只有存储只读权限的 vCenter 服务账号
257
264
  - **可组合** — 可与 vmware-monitor 或 vmware-aiops 同时运行
@@ -270,8 +277,8 @@ vmware-storage-mcp
270
277
 
271
278
  | 功能 | 说明 |
272
279
  |------|------|
273
- | 只读为主 | 15 个工具中 11 个只读 |
274
- | 默认只预览(MCP) | 4 个写工具接受 `confirm`(默认 `false`):不带它的调用不做任何变更,只返回 `blast_radius`(主机、适配器;移除目标时还有该目标背后的路径、设备和数据存储)。某个数据存储会失去全部路径、或影响范围有任何部分读不到时,`confirm=true` 会被拒绝。`dry_run` 为已弃用的别名 |
280
+ | 只读为主 | 16 个工具中 12 个只读 |
281
+ | 默认只预览(MCP) | 4 个写工具接受 `confirm`(默认 `false`):不带它的调用不做任何变更,只返回 `blast_radius`(主机、适配器;移除目标时还有该目标背后的路径、设备和数据存储)。某个数据存储会失去全部路径、或影响范围有任何部分读不到时,`confirm=true` 会被拒绝。旧的 `dry_run` 别名已在 2.4.3 移除,仍传它会被当作未知参数拒绝 |
275
282
  | 输入验证 | iSCSI 操作前验证 IP 地址和端口 |
276
283
  | 审计日志 | 所有操作记录到 `~/.vmware-storage/audit.log`(JSON Lines) |
277
284
  | 双重确认 | CLI iSCSI 写操作需两次确认 |
@@ -1,13 +1,15 @@
1
1
  <!-- mcp-name: io.github.vmware-skills/vmware-storage -->
2
2
  # VMware Storage
3
3
 
4
- > **Author**: Wei Zhou, VMware by Broadcom — wei-wz.zhou@broadcom.com
4
+ For a read-only check of this skill with your model and agent host, use the shared [model-fit self-test](https://github.com/vmware-skills/marketplace/blob/main/MODEL_FIT_SELF_TEST.md) in the marketplace root.
5
+
6
+ > **Author**: Wei Zhou, VMware by Broadcom — zhouwei008@gmail.com
5
7
  > This is a community-driven project by a VMware engineer, not an official VMware product.
6
8
  > For official VMware developer tools see [developer.broadcom.com](https://developer.broadcom.com).
7
9
 
8
10
  [English](README.md) | [中文](README-CN.md)
9
11
 
10
- VMware vSphere storage management: datastores, iSCSI, vSAN, and read-only Fibre Channel / multipath diagnostics — 15 MCP tools, domain-focused and lightweight.
12
+ VMware vSphere storage management: datastores, iSCSI, vSAN, and read-only Fibre Channel / multipath diagnostics — 16 MCP tools, domain-focused and lightweight.
11
13
 
12
14
  > Split from vmware-aiops for lighter context and local model compatibility.
13
15
 
@@ -88,11 +90,11 @@ chmod 600 ~/.vmware-storage/.env
88
90
  vmware-storage doctor
89
91
  ```
90
92
 
91
- ## MCP Tools (15)
93
+ ## MCP Tools (16)
92
94
 
93
95
  | Category | Tools | Type |
94
96
  |----------|-------|------|
95
- | Datastore | `list_all_datastores`, `browse_datastore`, `scan_datastore_images`, `list_cached_images` | Read |
97
+ | Datastore | `list_all_datastores`, `get_datastore_vm_usage`, `browse_datastore`, `scan_datastore_images`, `list_cached_images` | Read |
96
98
  | iSCSI | `enable_iscsi`, `get_iscsi_status`, `add_iscsi_target`, `remove_iscsi_target`, `rescan_storage` | Read/Write |
97
99
  | vSAN | `get_vsan_health`, `get_vsan_capacity`, `get_vsan_efficiency` | Read |
98
100
  | FC / multipath | `list_fc_adapters`, `list_storage_device_paths` | Read |
@@ -114,6 +116,13 @@ The `add-target` command automatically rescans storage. Use `--dry-run` to previ
114
116
 
115
117
  ### Find Deployable Images Across Datastores
116
118
 
119
+ For scripts, add `--json` to `datastore list`, `datastore browse`, or
120
+ `datastore scan-images`. Successful output is the complete result envelope,
121
+ including `items`, counts, truncation and any cache note. Without the flag,
122
+ list keeps its table and browse/scan-images keep their legacy JSON arrays.
123
+ Other read commands already output JSON by default. Failures still exit nonzero
124
+ with the existing CLI error message.
125
+
117
126
  1. List all datastores: `vmware-storage datastore list`
118
127
  2. Scan for images: `vmware-storage datastore scan-images datastore01`
119
128
  3. Browse with a pattern: `vmware-storage datastore browse datastore01 --pattern "*.iso"`
@@ -212,7 +221,7 @@ vmware-storage-mcp
212
221
 
213
222
  `vmware-aiops` has 61 MCP tools — too heavy for local LLMs (7B-14B). By splitting storage into its own skill:
214
223
 
215
- - **15 tools** — fits comfortably in small model context windows
224
+ - **16 tools** — fits comfortably in small model context windows
216
225
  - **Domain-focused** — storage admins get only what they need
217
226
  - **Least privilege** — can run under a vCenter service account with storage read-only permissions
218
227
  - **Composable** — use alongside vmware-monitor or vmware-aiops as needed
@@ -239,8 +248,8 @@ vmware-storage-mcp
239
248
 
240
249
  | Feature | Description |
241
250
  |---------|-------------|
242
- | Read-heavy | 11/15 tools are read-only |
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 |
251
+ | Read-heavy | 12/16 tools are read-only |
252
+ | 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. the old `dry_run` alias was removed in 2.4.3 and is refused as an unknown argument |
244
253
  | Input validation | IP addresses and ports validated before iSCSI operations |
245
254
  | Audit logging | All operations logged to `~/.vmware-storage/audit.log` |
246
255
  | No VM operations | Cannot create, delete, or modify VMs |
@@ -1,3 +1,18 @@
1
+ ## v2.6.0 — complete datastore CLI JSON envelopes (2026-11-08)
2
+
3
+ * Update public author/project contact metadata to `zhouwei008@gmail.com`.
4
+
5
+ ### datastore CLI JSON envelopes
6
+ - Add `--json` to datastore list/browse/scan-images to preserve the complete
7
+ result envelope, including unknown totals, truncation and cache notes.
8
+ - Preserve the existing default table/JSON-array formats and error behavior.
9
+
10
+ ## v2.5.0 — per-VM datastore usage and clearer storage refusals (2026-11-01)
11
+
12
+ * New read-only `get_datastore_vm_usage(datastore_name, top_n=10)` reports per-VM committed, uncommitted and unshared space on one datastore, plus attributed/unattributed used space and VMs whose usage could not be measured. It uses one PropertyCollector pass, sorts largest committed usage first, and does not turn unknown into zero. The MCP surface now has 16 tools. Verified against a lab vCenter before this release branch.
13
+ * An unknown cluster or invalid storage path now returns the specific corrective hint instead of a generic connection hint. On a cluster without vSAN, `get_vsan_efficiency` reports both feature flags as unknown and says vSAN is disabled.
14
+ * Removed the deprecated MCP `dry_run` alias from the destructive tools. Use `confirm=False` for a no-write preview and `confirm=True` after reviewing its blast radius; clients still passing `dry_run` must update.
15
+
1
16
  ## v2.4.2 — a login refused for lack of a vSphere role says so (2026-10-19)
2
17
 
3
18
  * **A login vCenter refuses with `NoPermission` gets the role error, not the raw fault.** Found on a vCenter 8.0.3
@@ -8,8 +23,6 @@
8
23
  neutral text naming the (sanitized) privilege. A wrong password (`InvalidLogin`) is unchanged. Same text as
9
24
  vmware-monitor.
10
25
 
11
- ## Unreleased — follow-ups to the 2.4.1 review
12
-
13
26
  * **`list_cached_images(target=...)`** returns one target's cached images; without it, nothing changes.
14
27
  * The cache write takes a lock across processes, so a CLI and an MCP scan at the same time keep both sides' rows; a
15
28
  lock held for more than 10 s is reported in `cache_note` with the lock file's path.
@@ -1384,7 +1397,7 @@ This release tracks vmware-pilot v1.5.17 (new `investigate_alert` template + `re
1384
1397
  - **[READ]/[WRITE] tool prefixes**: All MCP tool descriptions now start with [READ] or [WRITE] to clearly indicate operation type
1385
1398
  - **Read/write split counts**: SKILL.md MCP Tools section header shows exact read vs write tool counts
1386
1399
  - **Negative routing**: Description frontmatter includes "Do NOT use when..." clause to prevent misrouting
1387
- - **Broadcom author attestation**: README.md, README-CN.md, and pyproject.toml include VMware by Broadcom author identity (wei-wz.zhou@broadcom.com) to resolve Snyk E005 brand warnings
1400
+ - **Broadcom author attestation**: README.md, README-CN.md, and pyproject.toml include VMware by Broadcom author identity (zhouwei008@gmail.com) to resolve Snyk E005 brand warnings
1388
1401
 
1389
1402
  ### Storage-specific
1390
1403
 
@@ -1512,4 +1525,4 @@ Domain-focused VMware storage skill, split from vmware-aiops for lighter context
1512
1525
 
1513
1526
  ### Datastore Management / 数据存储管理
1514
1527
 
1515
- - `list_all_datastores` — List all datastores with capacity, usage
1528
+ - `list_all_datastores` — List all datastores with capacity, usage
@@ -4,13 +4,13 @@
4
4
 
5
5
  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 Inc.
6
6
 
7
- **Author**: Wei Zhou, VMware by Broadcom — wei-wz.zhou@broadcom.com
7
+ **Author**: Wei Zhou, VMware by Broadcom — zhouwei008@gmail.com
8
8
 
9
9
  ## Reporting Vulnerabilities
10
10
 
11
11
  If you discover a security vulnerability, please report it privately:
12
12
 
13
- - **Email**: wei-wz.zhou@broadcom.com
13
+ - **Email**: zhouwei008@gmail.com
14
14
  - **GitHub**: Open a [private security advisory](https://github.com/vmware-skills/VMware-Storage/security/advisories/new)
15
15
 
16
16
  Do **not** open a public GitHub issue for security vulnerabilities.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "id": "vmware-storage",
3
3
  "name": "VMware Storage",
4
- "description": "VMware vSphere storage with 15 MCP tools: datastores, iSCSI, vSAN, FC multipath.",
4
+ "description": "VMware vSphere storage with 16 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.4.2",
14
+ "vmware-storage==2.6.0",
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.2",
4
- "description": "VMware vSphere storage with 15 MCP tools: datastores, iSCSI, vSAN, FC multipath.",
3
+ "version": "2.6.0",
4
+ "description": "VMware vSphere storage with 16 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,12 +4,12 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "vmware-storage"
7
- version = "2.4.2"
7
+ version = "2.6.0"
8
8
  description = "VMware vSphere storage management: datastores, iSCSI, vSAN. Domain-focused MCP skill."
9
9
  readme = "README.md"
10
10
  license = "MIT"
11
11
  requires-python = ">=3.10"
12
- authors = [{ name = "Wei Zhou", email = "wei-wz.zhou@broadcom.com" }]
12
+ authors = [{ name = "Wei Zhou", email = "zhouwei008@gmail.com" }]
13
13
  dependencies = [
14
14
  "pyvmomi>=8.0.3.0,<10.0",
15
15
  "pyaml>=24.0,<27.0",
@@ -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 15 MCP tools: datastores, iSCSI, vSAN, FC multipath.",
5
+ "description": "VMware vSphere storage with 16 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.4.2",
10
+ "version": "2.6.0",
11
11
  "packages": [
12
12
  {
13
13
  "registryType": "pypi",
14
14
  "identifier": "vmware-storage",
15
- "version": "2.4.2",
15
+ "version": "2.6.0",
16
16
  "runtimeHint": "uvx",
17
17
  "packageArguments": [
18
18
  {
@@ -19,9 +19,11 @@ compatibility: >
19
19
 
20
20
  # VMware Storage
21
21
 
22
+ > Self-test: [guide](https://github.com/vmware-skills/marketplace/blob/main/MODEL_FIT_SELF_TEST.md).
23
+
22
24
  > **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
25
 
24
- VMware vSphere storage management — 15 MCP tools for datastores, iSCSI, vSAN, Fibre Channel / multipath diagnostics, and an access self-check.
26
+ VMware vSphere storage management — 16 MCP tools for datastores, iSCSI, vSAN, Fibre Channel / multipath diagnostics, and an access self-check.
25
27
 
26
28
  > Split from vmware-aiops for lighter context and local model compatibility.
27
29
  > **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).
@@ -40,7 +42,7 @@ VMware vSphere storage management — 15 MCP tools for datastores, iSCSI, vSAN,
40
42
  ## Quick Install
41
43
 
42
44
  ```bash
43
- uv tool install vmware-storage==2.4.2
45
+ uv tool install vmware-storage==2.6.0
44
46
  vmware-storage init # guided setup: writes config + .env (chmod 600, password grep-safe), then verifies
45
47
  vmware-storage doctor
46
48
  ```
@@ -147,15 +149,16 @@ vmware-storage iscsi status esxi-lab --target lab-esxi
147
149
  | Cloud models (Claude, GPT-4o) | Either | MCP gives structured JSON I/O |
148
150
  | Automated pipelines | **MCP** | Type-safe parameters, structured output |
149
151
 
150
- ## MCP Tools (15 — 11 read, 4 write)
152
+ ## MCP Tools (16 — 12 read, 4 write)
151
153
 
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.
154
+ 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. the old `dry_run` alias was removed in 2.4.3 and is refused as an unknown argument.
153
155
 
154
156
  The four Datastore read tools return the family list envelope — `{items, returned, limit, total, truncated, hint}` — rather than a bare array. Read the rows from `items`; `truncated` says whether the listing is complete, so it never has to be guessed from the row count. All four enumerate their collection in full, so `total` is the real count and `truncated` is always `false`.
155
157
 
156
158
  | Category | Tool | Type | Description |
157
159
  |----------|------|:----:|-------------|
158
160
  | Datastore | `list_all_datastores` | Read | List datastores with capacity, usage %, VM count |
161
+ | | `get_datastore_vm_usage` | Read | Which VMs take the space on one datastore (committed GB, largest first) and how much no VM accounts for |
159
162
  | | `browse_datastore` | Read | Browse files with optional path and glob pattern |
160
163
  | | `scan_datastore_images` | Read | Find OVA/ISO/OVF/VMDK in a datastore |
161
164
  | | `list_cached_images` | Read | Query local image registry with type/datastore/target filters |
@@ -171,7 +174,7 @@ The four Datastore read tools return the family list envelope — `{items, retur
171
174
  | | `list_storage_device_paths` | Read | Per-device path state across a cluster/host/datastore; visibility and path-count differences |
172
175
  | Access | `get_access_info` | Read | Account in use and, per tool, whether its privileges are granted on the root folder |
173
176
 
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.
177
+ **Read/write split**: 12 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.
175
178
 
176
179
  Running with local or small models? See [`references/agent-guardrails.md`](references/agent-guardrails.md).
177
180
 
@@ -257,7 +260,7 @@ Corporate TLS proxies inject certificates that uv's bundled CA store doesn't tru
257
260
  ## Safety
258
261
 
259
262
  - **No VM operations**: This skill cannot power on/off, create, delete, or modify VMs — that scope belongs to `vmware-aiops`
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)
263
+ - **Read-heavy**: 12 of 16 tools are read-only (list, per-VM usage, browse, scan, cached images, status, health, capacity, efficiency, FC adapters, device paths, access info)
261
264
  - **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
262
265
  - **Double confirmation**: CLI write commands (iSCSI enable, add/remove target) require two separate "Are you sure?" prompts before executing
263
266
  - **Dry-run mode**: All write commands support `--dry-run` to preview API calls without executing
@@ -271,7 +274,7 @@ Corporate TLS proxies inject certificates that uv's bundled CA store doesn't tru
271
274
  ## Setup
272
275
 
273
276
  ```bash
274
- uv tool install vmware-storage==2.4.2
277
+ uv tool install vmware-storage==2.6.0
275
278
  mkdir -p ~/.vmware-storage
276
279
  cp config.example.yaml ~/.vmware-storage/config.yaml
277
280
  # Edit config.yaml with your vCenter/ESXi targets
@@ -14,7 +14,7 @@ vmware-monitor and vmware-aria against a production vSphere estate with Llama
14
14
  cross-skill rules are identical across this family; the parts below marked
15
15
  vmware-storage are specific to this skill.
16
16
 
17
- vmware-storage exposes 15 MCP tools, 4 of which change state. The write
17
+ vmware-storage exposes 16 MCP tools, 4 of which change state. The write
18
18
  surface is small but sharp: removing an iSCSI send target can make LUNs — and
19
19
  every VM living on them — inaccessible.
20
20
 
@@ -1,6 +1,6 @@
1
1
  # VMware Storage Capabilities
2
2
 
3
- All 15 MCP tools exposed by `vmware-storage-mcp`, organized by category.
3
+ All 16 MCP tools exposed by `vmware-storage-mcp`, organized by category.
4
4
 
5
5
  ## Automation Level Reference
6
6
 
@@ -8,7 +8,7 @@ Each operation is classified by autonomy level per the Enterprise Harness Engine
8
8
 
9
9
  | Level | Meaning | Agent autonomy | Examples in this skill |
10
10
  |:-:|---|---|---|
11
- | **L1** | Read-only, raw data | Always auto-run | `list_all_datastores`, `browse_datastore`, `scan_datastore_images`, `list_cached_images`, `get_iscsi_status`, vSAN status queries |
11
+ | **L1** | Read-only, raw data | Always auto-run | `list_all_datastores`, `get_datastore_vm_usage`, `browse_datastore`, `scan_datastore_images`, `list_cached_images`, `get_iscsi_status`, vSAN status queries |
12
12
  | **L2** | Read + analysis / recommendation | Always auto-run | datastore capacity analysis, image registry queries, iSCSI target health correlation |
13
13
  | **L3** | Single write — user must approve | Only after explicit confirmation; high-risk ops require double-confirm + `--dry-run` (see Confirm column) | `enable_iscsi`, `add_iscsi_target`, `remove_iscsi_target`, vSAN cluster ops |
14
14
  | **L4** | Multi-step plan / apply workflow | Plan generation auto; apply gated by user approval | *(roadmap — multi-host iSCSI rollout, vSAN expansion plans)* |
@@ -24,6 +24,7 @@ Each operation is classified by autonomy level per the Enterprise Harness Engine
24
24
  | Tool | Description | Parameters | Risk | Confirm |
25
25
  |------|-------------|------------|:----:|:-------:|
26
26
  | `list_all_datastores` | List datastores with capacity, usage %, VM count | `target` (string, optional), `limit` (int, optional; omit for all) | Low | No |
27
+ | `get_datastore_vm_usage` | Per-VM space on one datastore: committed / uncommitted / unshared GB, largest first, plus `unattributed_gb` (used space no VM accounts for) and `unmeasured_vms` | `datastore_name` (string, **required**), `top_n` (int, optional, default 10), `target` (string, optional) | Low | No |
27
28
  | `browse_datastore` | Browse files with optional path and glob pattern | `datastore_name` (string, **required**), `path` (string, optional), `pattern` (string, optional), `target` (string, optional) | Low | No |
28
29
  | `scan_datastore_images` | Find OVA/ISO/OVF/VMDK deployable images in a datastore | `datastore_name` (string, **required**), `target` (string, optional) | Low | No |
29
30
  | `list_cached_images` | Query local image registry with type/datastore/target filters | `image_type` (string, optional), `datastore` (string, optional), `target` (string, optional) | Low | No |
@@ -108,7 +109,7 @@ Source: each host's `config.storageDevice` (HBAs, SCSI LUNs, `multipathInfo`) an
108
109
 
109
110
  ## Audit Coverage
110
111
 
111
- All 15 tools are wrapped with `@vmware_tool` from vmware-policy, which provides:
112
+ All 16 tools are wrapped with `@vmware_tool` from vmware-policy, which provides:
112
113
 
113
114
  - **Pre-execution**: Policy rule check against `~/.vmware/rules.yaml` (deny rules, maintenance windows)
114
115
  - **Post-execution**: Audit log entry written to `~/.vmware/audit.db` (SQLite WAL mode)
@@ -118,7 +119,7 @@ All 15 tools are wrapped with `@vmware_tool` from vmware-policy, which provides:
118
119
 
119
120
  | Type | Count | Tools |
120
121
  |------|:-----:|-------|
121
- | Read | 10 | `list_all_datastores`, `browse_datastore`, `scan_datastore_images`, `list_cached_images`, `get_iscsi_status`, `get_vsan_health`, `get_vsan_capacity`, `get_vsan_efficiency`, `list_fc_adapters`, `list_storage_device_paths` |
122
+ | Read | 11 | `list_all_datastores`, `get_datastore_vm_usage`, `browse_datastore`, `scan_datastore_images`, `list_cached_images`, `get_iscsi_status`, `get_vsan_health`, `get_vsan_capacity`, `get_vsan_efficiency`, `list_fc_adapters`, `list_storage_device_paths` |
122
123
  | Write | 4 | `enable_iscsi`, `add_iscsi_target`, `remove_iscsi_target`, `rescan_storage` |
123
124
 
124
125
  > Write tools require explicit parameters (host name, IP address) and support `--dry-run` in CLI mode. Over MCP they preview by default: without `confirm: true` they return `blast_radius` and change nothing. All write operations are audit-logged with timestamp, user, target, operation, parameters, and result.
@@ -276,3 +276,16 @@ Privileges are checked on the root folder: `not_granted_at_root` may still be gr
276
276
  |----------|-------------|
277
277
  | `VMWARE_STORAGE_CONFIG` | Override config file path (used by MCP server) |
278
278
  | `VMWARE_<TARGET>_PASSWORD` | Password for a target (e.g., `VMWARE_MY_VCENTER_PASSWORD`) |
279
+
280
+ ### Datastore JSON envelopes
281
+
282
+ Add `--json` to `datastore list`, `datastore browse`, or `datastore scan-images`
283
+ for the full successful result envelope, matching the MCP operation's result:
284
+ `items`, `returned`, `limit`, `total`, `truncated`, `hint`, and any extra evidence
285
+ such as `cache_note`. Unknown/null values remain unknown, not zero or complete.
286
+ A successful image scan can carry a local-cache failure note; do not discard it.
287
+
288
+ Without this option list prints its table and browse/scan-images retain their
289
+ legacy JSON arrays. Other read commands already emit JSON by default. This flag
290
+ does not alter reads, local-cache writes, Policy or auditing. Errors retain the
291
+ existing text message and nonzero exit code; scripts must check the exit status.
@@ -13,19 +13,19 @@ Complete setup and security guide for `vmware-storage`.
13
13
  ### Via uv (recommended)
14
14
 
15
15
  ```bash
16
- uv tool install vmware-storage==2.4.2
16
+ uv tool install vmware-storage==2.6.0
17
17
  ```
18
18
 
19
19
  ### Via pip
20
20
 
21
21
  ```bash
22
- pip install vmware-storage==2.4.2
22
+ pip install vmware-storage==2.6.0
23
23
  ```
24
24
 
25
25
  ### From source
26
26
 
27
27
  ```bash
28
- git clone --branch v2.4.2 https://github.com/vmware-skills/VMware-Storage.git
28
+ git clone --branch v2.6.0 https://github.com/vmware-skills/VMware-Storage.git
29
29
  cd VMware-Storage
30
30
  pip install -e .
31
31
  ```
@@ -121,10 +121,17 @@ def test_an_audited_write_lands_in_the_sandbox_and_not_in_the_real_db() -> None:
121
121
  real_db = REAL_HOME / ".vmware" / "audit.db"
122
122
  if not real_db.exists():
123
123
  pytest.skip("no production audit database on this machine to check against")
124
- with sqlite3.connect(f"file:{real_db}?mode=ro", uri=True) as con:
125
- leaked = con.execute(
126
- "SELECT count(*) FROM audit_log WHERE tool = ?", (marker,)
127
- ).fetchone()[0]
124
+ try:
125
+ with sqlite3.connect(f"file:{real_db}?mode=ro", uri=True) as con:
126
+ leaked = con.execute(
127
+ "SELECT count(*) FROM audit_log WHERE tool = ?", (marker,)
128
+ ).fetchone()[0]
129
+ except sqlite3.OperationalError as exc:
130
+ # A restricted runner may see the file but have no permission to open it.
131
+ # The sandbox write assertion above still ran; this external check did not.
132
+ if "unable to open database file" in str(exc):
133
+ pytest.skip("production audit database is outside this runner's readable roots")
134
+ raise
128
135
  assert leaked == 0, (
129
136
  f"{leaked} row(s) from this test reached the operator's audit database "
130
137
  f"at {real_db}"
@@ -0,0 +1,62 @@
1
+ """Successful JSON output must preserve coverage and local-cache evidence."""
2
+ from __future__ import annotations
3
+
4
+ import json
5
+ from types import SimpleNamespace
6
+
7
+ import pytest
8
+ from typer.testing import CliRunner
9
+
10
+ from vmware_storage import cli
11
+ from vmware_storage.ops import datastore_browser, inventory
12
+
13
+
14
+ @pytest.fixture
15
+ def connection(monkeypatch):
16
+ si = object()
17
+ monkeypatch.setattr(cli, "_get_connection", lambda *a: si)
18
+ monkeypatch.setattr(cli, "load_config", lambda *a: object())
19
+ monkeypatch.setattr(cli, "ConnectionManager", lambda *a: SimpleNamespace(
20
+ resolve_target_name=lambda target: "lab", connect=lambda target: si))
21
+ return si
22
+
23
+
24
+ def _envelope(items):
25
+ return {"items": items, "returned": len(items), "limit": 2,
26
+ "total": None, "truncated": True, "hint": "incomplete evidence"}
27
+
28
+
29
+ @pytest.mark.parametrize("command,owner,operation", [
30
+ (["list"], inventory, "list_datastores"),
31
+ (["browse", "ds"], datastore_browser, "browse_datastore"),
32
+ (["scan-images", "ds"], datastore_browser, "scan_images"),
33
+ ])
34
+ @pytest.mark.parametrize("items", [[], [{"name": "[SSD] 数据", "usage_pct": None}]])
35
+ def test_json_preserves_envelope_even_when_empty_or_unknown(
36
+ monkeypatch, connection, command, owner, operation, items,
37
+ ):
38
+ envelope = _envelope(items)
39
+ envelope["cache_note"] = "Scan succeeded but the local cache was not updated"
40
+ calls = []
41
+
42
+ def read(si, *a, **kw):
43
+ assert si is connection
44
+ calls.append(kw)
45
+ return envelope
46
+
47
+ monkeypatch.setattr(owner, operation, read)
48
+ out = CliRunner().invoke(cli.app, ["datastore", *command, "--json"])
49
+ assert out.exit_code == 0, out.output
50
+ assert json.loads(out.stdout) == envelope
51
+ assert len(calls) == 1
52
+
53
+
54
+ @pytest.mark.parametrize("command,operation", [
55
+ (["browse", "ds"], "browse_datastore"), (["scan-images", "ds"], "scan_images"),
56
+ ])
57
+ def test_legacy_json_arrays_are_unchanged_without_flag(monkeypatch, connection, command, operation):
58
+ items = [{"name": "image.iso"}]
59
+ monkeypatch.setattr(datastore_browser, operation, lambda *a, **kw: _envelope(items))
60
+ out = CliRunner().invoke(cli.app, ["datastore", *command])
61
+ assert out.exit_code == 0, out.output
62
+ assert json.loads(out.stdout) == items
@@ -88,7 +88,9 @@ def test_a_datastore_over_the_threshold_is_still_styled_red() -> None:
88
88
  assert cool.style != "red"
89
89
 
90
90
  # ...and the style survives to the terminal, not just the object.
91
- console = Console(force_terminal=True, width=40)
91
+ # The runner may set TERM=dumb or NO_COLOR=1. Test Rich's colour rendering
92
+ # explicitly, independent of the surrounding terminal policy.
93
+ console = Console(force_terminal=True, color_system="standard", no_color=False, width=40)
92
94
  with console.capture() as cap:
93
95
  console.print(hot)
94
96
  assert "\x1b[31m" in cap.get()