vmware-debug 2.0.0__tar.gz → 2.2.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 (96) hide show
  1. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/.claude-plugin/plugin.json +1 -1
  2. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/.mcp.json +1 -1
  3. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/PKG-INFO +40 -3
  4. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/README-CN.md +28 -1
  5. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/README.md +37 -0
  6. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/RELEASE_NOTES.md +36 -0
  7. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/openclaw.plugin.json +1 -1
  8. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/package.json +1 -1
  9. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/pyproject.toml +3 -3
  10. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/server.json +2 -2
  11. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/skills/vmware-debug/SKILL.md +1 -1
  12. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/skills/vmware-debug/references/setup-guide.md +27 -2
  13. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/eval/capability/_family.py +9 -7
  14. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/uv.lock +6 -6
  15. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/vmware_debug/__init__.py +1 -1
  16. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/vmware_debug/cli.py +36 -3
  17. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/vmware_debug/mcp_server/server.py +19 -2
  18. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/.clawhubignore +0 -0
  19. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/.gitignore +0 -0
  20. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/SECURITY.md +0 -0
  21. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/docs/plans/2026-08-28-investigation-layer-design.md +0 -0
  22. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/skills/vmware-debug/references/agent-guardrails.md +0 -0
  23. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/skills/vmware-debug/references/capabilities.md +0 -0
  24. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/skills/vmware-debug/references/cli-reference.md +0 -0
  25. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/skills/vmware-debug/references/event-envelope.md +0 -0
  26. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/skills/vmware-debug/references/routing.md +0 -0
  27. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/__init__.py +0 -0
  28. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/conftest.py +0 -0
  29. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/eval/__init__.py +0 -0
  30. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/eval/capability/__init__.py +0 -0
  31. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/eval/capability/_scores.json +0 -0
  32. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/eval/capability/_scoring.py +0 -0
  33. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/eval/capability/_skill.py +0 -0
  34. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/eval/capability/conftest.py +0 -0
  35. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/eval/capability/test_entity_reachability.py +0 -0
  36. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/eval/capability/test_error_actionability.py +0 -0
  37. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/eval/capability/test_tool_description_quality.py +0 -0
  38. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/eval/capability/test_tool_manifest_budget.py +0 -0
  39. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/eval/regression/__init__.py +0 -0
  40. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/eval/regression/_vsphere_event_vocabulary.py +0 -0
  41. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/eval/regression/test_audit_isolation.py +0 -0
  42. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/eval/regression/test_capability_grader.py +0 -0
  43. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/eval/regression/test_case_id_non_ascii.py +0 -0
  44. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/eval/regression/test_case_plan_max_steps.py +0 -0
  45. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/eval/regression/test_classification_against_vsphere_vocabulary.py +0 -0
  46. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/eval/regression/test_debug_regressions.py +0 -0
  47. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/eval/regression/test_environment_resolver_isolation.py +0 -0
  48. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/eval/regression/test_every_tool_parameter_is_documented.py +0 -0
  49. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/eval/regression/test_evidence_payload_contract.py +0 -0
  50. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/eval/regression/test_host_lifecycle_classification.py +0 -0
  51. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/eval/regression/test_investigation_metrics.py +0 -0
  52. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/eval/regression/test_real_alert_titles_classify.py +0 -0
  53. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/eval/regression/test_result_envelope.py +0 -0
  54. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/eval/regression/test_skill_name_aliases.py +0 -0
  55. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/eval/regression/test_spike_resolution.py +0 -0
  56. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/eval/regression/test_tool_annotations.py +0 -0
  57. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/test_case_conclusion.py +0 -0
  58. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/test_case_evidence.py +0 -0
  59. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/test_case_grading.py +0 -0
  60. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/test_case_grading_per_hypothesis.py +0 -0
  61. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/test_case_hypotheses.py +0 -0
  62. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/test_case_ids.py +0 -0
  63. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/test_case_ledger_concurrency.py +0 -0
  64. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/test_case_plan.py +0 -0
  65. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/test_case_readiness.py +0 -0
  66. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/test_case_store.py +0 -0
  67. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/test_case_timeline_close.py +0 -0
  68. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/test_case_tools.py +0 -0
  69. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/test_knowledge.py +0 -0
  70. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/test_mcp_audit.py +0 -0
  71. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/test_safe_error_passthrough.py +0 -0
  72. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/tests/test_timeline.py +0 -0
  73. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/vmware_debug/envelope.py +0 -0
  74. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/vmware_debug/mcp/__init__.py +0 -0
  75. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/vmware_debug/mcp/tools.py +0 -0
  76. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/vmware_debug/mcp_server/__init__.py +0 -0
  77. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/vmware_debug/ops/__init__.py +0 -0
  78. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/vmware_debug/ops/cases/__init__.py +0 -0
  79. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/vmware_debug/ops/cases/api.py +0 -0
  80. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/vmware_debug/ops/cases/conclusion.py +0 -0
  81. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/vmware_debug/ops/cases/evidence.py +0 -0
  82. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/vmware_debug/ops/cases/grading.py +0 -0
  83. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/vmware_debug/ops/cases/hypotheses.py +0 -0
  84. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/vmware_debug/ops/cases/ids.py +0 -0
  85. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/vmware_debug/ops/cases/knowledge.py +0 -0
  86. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/vmware_debug/ops/cases/model.py +0 -0
  87. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/vmware_debug/ops/cases/payloads.py +0 -0
  88. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/vmware_debug/ops/cases/plan.py +0 -0
  89. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/vmware_debug/ops/cases/readiness.py +0 -0
  90. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/vmware_debug/ops/cases/sources.py +0 -0
  91. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/vmware_debug/ops/cases/store.py +0 -0
  92. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/vmware_debug/ops/cases/timeline.py +0 -0
  93. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/vmware_debug/ops/skill_names.py +0 -0
  94. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/vmware_debug/ops/timeline.py +0 -0
  95. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/vmware_debug/rules/evidence_sources.yaml +0 -0
  96. {vmware_debug-2.0.0 → vmware_debug-2.2.0}/vmware_debug/rules/grading_rules.yaml +0 -0
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://anthropic.com/claude-code/plugin.schema.json",
3
3
  "name": "vmware-debug",
4
4
  "displayName": "VMware Debug",
5
- "version": "2.0.0",
5
+ "version": "2.2.0",
6
6
  "description": "VMware incident timeline, root-cause routing, local case ledger; no vSphere access. 14 MCP tools.",
7
7
  "author": {
8
8
  "name": "Wei Zhou",
@@ -5,7 +5,7 @@
5
5
  "command": "uvx",
6
6
  "args": [
7
7
  "--from",
8
- "vmware-debug==2.0.0",
8
+ "vmware-debug==2.2.0",
9
9
  "vmware-debug-mcp"
10
10
  ]
11
11
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: vmware-debug
3
- Version: 2.0.0
3
+ Version: 2.2.0
4
4
  Summary: VMware diagnostic brain — offline incident triage, log/event correlation, and root-cause routing across the VMware skill family
5
5
  Project-URL: Homepage, https://github.com/vmware-skills/VMware-Debug
6
6
  Project-URL: Repository, https://github.com/vmware-skills/VMware-Debug
@@ -14,11 +14,11 @@ Classifier: License :: OSI Approved :: MIT License
14
14
  Classifier: Programming Language :: Python :: 3
15
15
  Classifier: Topic :: System :: Monitoring
16
16
  Requires-Python: >=3.10
17
- Requires-Dist: mcp[cli]<2.0,>=1.10
17
+ Requires-Dist: mcp[cli]<2.0,>=1.28
18
18
  Requires-Dist: pyyaml<7.0,>=6.0
19
19
  Requires-Dist: rich<15.0,>=13.0
20
20
  Requires-Dist: typer<1.0,>=0.12
21
- Requires-Dist: vmware-policy<2.0,>=1.18.1
21
+ Requires-Dist: vmware-policy<2.0,>=1.21.0
22
22
  Description-Content-Type: text/markdown
23
23
 
24
24
  <!-- mcp-name: io.github.vmware-skills/vmware-debug -->
@@ -52,6 +52,23 @@ renames widened), and vmware-pilot ≥ 1.13 translates old names in saved workfl
52
52
  If an install older than 2.0 shares that `rules.yaml`, give it vmware-policy ≥ 1.18.2 too: it matches each rule
53
53
  against both the old and the new name, so one file serves both.
54
54
 
55
+ ## Companion Skills
56
+
57
+ | Need | Skill |
58
+ |---|---|
59
+ | Incident correlation / root cause | **vmware-debug** (this project) |
60
+ | Centralized log search | vmware-log-insight (feed its `search_logs` results here) |
61
+ | vCenter events and alarms | vmware-monitor |
62
+ | Metrics / anomalies | vmware-aria |
63
+ | Executing a fix | vmware-aiops (single op) / vmware-pilot (multi-step, gated) |
64
+
65
+ ## Install
66
+
67
+ ```bash
68
+ uv tool install vmware-debug
69
+ vmware-debug categories # see which symptom categories it can diagnose
70
+ ```
71
+
55
72
  ## MCP tools (14 — 7 read, 7 write)
56
73
 
57
74
  The seven writes go to the local case ledger only; none reaches a VMware system.
@@ -80,6 +97,26 @@ The seven writes go to the local case ledger only; none reaches a VMware system.
80
97
  | `grade_case` | [WRITE] Recompute the conclusion grade from the ledger and record it |
81
98
  | `close_case` | [WRITE] Record the final grade, archive, and name what was left open |
82
99
 
100
+ **Event envelope**: `{ts, source, severity, entity, text, fields}`. The agent normalizes events from each source
101
+ into this shape before handing them to debug, so debug has zero runtime dependency on the other packages.
102
+ **Keep each event's `event_type` in `fields`** — the classifier matches it as well as the text, and most modern
103
+ vSphere events are `EventEx`: the text is a generic boilerplate sentence, and only `eventTypeId` says what the
104
+ event actually is.
105
+
106
+ ## Security
107
+
108
+ Offline and credential-free by construction: it connects to no vCenter/NSX/Aria, has no destructive surface on
109
+ VMware, and holds no secret to leak. The only writes are the local case ledger: evidence, gaps, hypotheses and
110
+ grade history are append-only; `timeline.md` is regenerated from the evidence, and `case.json` holds the current
111
+ grade and status. The same holds with several writers: every write to a case first takes that case's lock file
112
+ (`.ledger.lock`, exclusive create), so two processes writing the same case in a shared `$OPS_HOME` are serialized
113
+ instead of dropping each other's entries; every file is written under a temporary name and then moved into place,
114
+ so a reader never sees a half-written file (on a file system without hard links, a new evidence file is instead
115
+ created in place: still never overwritten, but it can be read half-written). A lock left behind by a crashed
116
+ process is reported together with its holder and never deleted automatically; delete it by hand once you have
117
+ confirmed no process is writing that case. Released versions 1.11.3 and earlier do not take this lock, so every
118
+ machine sharing a case directory must upgrade. See [SECURITY.md](SECURITY.md).
119
+
83
120
  ## Offline / Air-Gapped Install (from source)
84
121
 
85
122
  This project uses the modern PEP 517 build system (hatchling), so there is **no
@@ -10,6 +10,8 @@ VMware skill 家族的**诊断大脑**。你给出症状(报错、日志、变
10
10
  它**从不触碰 vSphere**——不连接任何东西,也从不执行修复;唯一的写入是 `$OPS_HOME` 下的本地案卷。修复一律路由给 vmware-aiops(单步)或
11
11
  vmware-pilot(多步、带审批门控),完全复刻 vmware-harden → vmware-pilot 的「顾问/执行」分工。
12
12
 
13
+ 完整的方法论、事件信封约定和症状路由见 [`skills/vmware-debug/SKILL.md`](skills/vmware-debug/SKILL.md)。
14
+
13
15
  ## 升级到 2.0
14
16
 
15
17
  2.0 把 14 个 MCP 工具中的 13 个改成动词在前(例如 `case_close` → `close_case`, `case_get` → `get_case`, `case_grade` → `grade_case`),完整的新旧名对照表见
@@ -42,7 +44,7 @@ vmware-debug categories # 看它能诊断哪些症状类别
42
44
  **关联**——无状态,看一眼用:
43
45
 
44
46
  - `build_incident_timeline`:[READ] 把已取到的事件关联成 时间线 + 突刺 + 排序后的根因假设 + 下一步检查建议
45
- - `list_symptom_categories`:[READ] 症状类别及对应的排查路由(不知道查什么时用它)
47
+ - `list_symptom_categories`:[READ] 列出能识别的症状类别 + 每类该查什么
46
48
 
47
49
  **调查案卷**——需要持续推理的事件:
48
50
 
@@ -75,6 +77,31 @@ debug;debug 因此与其它包零运行时依赖。**请把每条事件的 `ev
75
77
  确认没有进程在写该案卷后再手动删除。已发布的 1.11.3 及更早版本不拿这个锁,共享案卷目录的每台机器都要升级。
76
78
  详见 [SECURITY.md](SECURITY.md)。
77
79
 
80
+ ## 离线 / 隔离网络安装(从源码)
81
+
82
+ 本项目使用现代 PEP 517 构建系统(hatchling),所以**按设计就没有 `setup.py`**——这是预期行为,不是缺文件。
83
+ 如果你克隆了源码后遇到 `ERROR: File "setup.py" or "setup.cfg" not found ... editable mode
84
+ currently requires a setuptools-based build`,说明你的 `pip` 低于 21.3,无法对非 setuptools 后端做*可编辑*(`-e`)安装。
85
+ 可编辑模式只是开发便利,运行这个工具并不需要——任选其一:
86
+
87
+ ```bash
88
+ # 在源码目录里——普通(非可编辑)安装会构建 wheel:
89
+ pip install . # 不是 pip install -e .
90
+
91
+ # ……或者先升级 pip,可编辑安装也能用:
92
+ pip install --upgrade pip && pip install -e .
93
+ ```
94
+
95
+ 对于**真正隔离网络的主机**,在联网机器上构建 wheel 再拷过去——目标主机就不需要网络:
96
+
97
+ ```bash
98
+ # 在联网机器上,把本包及其依赖收集成 wheel:
99
+ pip wheel . -w dist # → dist/*.whl (或:uv build,只构建本包)
100
+
101
+ # 把 dist/ 拷到隔离主机,然后离线安装:
102
+ pip install --no-index --find-links dist vmware-debug
103
+ ```
104
+
78
105
  ## 许可证
79
106
 
80
107
  MIT。
@@ -29,6 +29,23 @@ renames widened), and vmware-pilot ≥ 1.13 translates old names in saved workfl
29
29
  If an install older than 2.0 shares that `rules.yaml`, give it vmware-policy ≥ 1.18.2 too: it matches each rule
30
30
  against both the old and the new name, so one file serves both.
31
31
 
32
+ ## Companion Skills
33
+
34
+ | Need | Skill |
35
+ |---|---|
36
+ | Incident correlation / root cause | **vmware-debug** (this project) |
37
+ | Centralized log search | vmware-log-insight (feed its `search_logs` results here) |
38
+ | vCenter events and alarms | vmware-monitor |
39
+ | Metrics / anomalies | vmware-aria |
40
+ | Executing a fix | vmware-aiops (single op) / vmware-pilot (multi-step, gated) |
41
+
42
+ ## Install
43
+
44
+ ```bash
45
+ uv tool install vmware-debug
46
+ vmware-debug categories # see which symptom categories it can diagnose
47
+ ```
48
+
32
49
  ## MCP tools (14 — 7 read, 7 write)
33
50
 
34
51
  The seven writes go to the local case ledger only; none reaches a VMware system.
@@ -57,6 +74,26 @@ The seven writes go to the local case ledger only; none reaches a VMware system.
57
74
  | `grade_case` | [WRITE] Recompute the conclusion grade from the ledger and record it |
58
75
  | `close_case` | [WRITE] Record the final grade, archive, and name what was left open |
59
76
 
77
+ **Event envelope**: `{ts, source, severity, entity, text, fields}`. The agent normalizes events from each source
78
+ into this shape before handing them to debug, so debug has zero runtime dependency on the other packages.
79
+ **Keep each event's `event_type` in `fields`** — the classifier matches it as well as the text, and most modern
80
+ vSphere events are `EventEx`: the text is a generic boilerplate sentence, and only `eventTypeId` says what the
81
+ event actually is.
82
+
83
+ ## Security
84
+
85
+ Offline and credential-free by construction: it connects to no vCenter/NSX/Aria, has no destructive surface on
86
+ VMware, and holds no secret to leak. The only writes are the local case ledger: evidence, gaps, hypotheses and
87
+ grade history are append-only; `timeline.md` is regenerated from the evidence, and `case.json` holds the current
88
+ grade and status. The same holds with several writers: every write to a case first takes that case's lock file
89
+ (`.ledger.lock`, exclusive create), so two processes writing the same case in a shared `$OPS_HOME` are serialized
90
+ instead of dropping each other's entries; every file is written under a temporary name and then moved into place,
91
+ so a reader never sees a half-written file (on a file system without hard links, a new evidence file is instead
92
+ created in place: still never overwritten, but it can be read half-written). A lock left behind by a crashed
93
+ process is reported together with its holder and never deleted automatically; delete it by hand once you have
94
+ confirmed no process is writing that case. Released versions 1.11.3 and earlier do not take this lock, so every
95
+ machine sharing a case directory must upgrade. See [SECURITY.md](SECURITY.md).
96
+
60
97
  ## Offline / Air-Gapped Install (from source)
61
98
 
62
99
  This project uses the modern PEP 517 build system (hatchling), so there is **no
@@ -1,3 +1,39 @@
1
+ ## v2.2.0 — serve MCP over HTTPS
2
+
3
+ `vmware-debug mcp` can now serve the network as well as stdio (HLD §16, via vmware-policy 1.21.0):
4
+
5
+ ```bash
6
+ vmware-audit token create alice # once per caller; shown once
7
+ vmware-debug mcp --transport https --host 0.0.0.0 --port 8443 \
8
+ --cert server.pem --key server-key.pem --public-name mcp.example.com
9
+ ```
10
+
11
+ * Every request needs `Authorization: Bearer <token>`; the server will not start without a token, refuses Host or
12
+ Origin values outside `--public-name`, and checks itself (unauthenticated requests must get 401) before it
13
+ binds. `--transport http` binds loopback only, for a TLS-terminating reverse proxy.
14
+ * Audit rows record the caller as `token:<name>` and the surface as `mcp-https`. Calls naming different targets
15
+ run in parallel; calls naming no target run one at a time.
16
+ * stdio remains the default; the `vmware-debug-mcp` console script and `python -m` are unchanged.
17
+ * Everyone who can reach the endpoint acts with this server's account; run one endpoint per privilege level.
18
+ * Requires `vmware-policy>=1.21.0` and `mcp>=1.28`.
19
+
20
+ ## v2.1.0 — offer only read tools, plus chosen write tools
21
+
22
+ `vmware-debug mcp` can now offer a subset of this server's tools (HLD §17 D-16, via vmware-policy 1.20.0):
23
+
24
+ ```bash
25
+ vmware-debug mcp --expose read --allow-write close_case
26
+ ```
27
+
28
+ * `--expose read` (or `VMWARE_DEBUG_MCP_EXPOSE=read`) keeps only tools annotated `readOnlyHint: true`; `--allow-write a,b`
29
+ (or `VMWARE_DEBUG_MCP_ALLOW_WRITE`) keeps chosen write tools on top. The default is unchanged: every tool.
30
+ * A bad value, or a name that is not a write tool of this server, stops the server before it serves (exit 2).
31
+ Flags and environment variables are not mixed; a blank flag counts as not given. Pre-2.0 names are accepted.
32
+ * This limits what clients are offered; it is not authorization. See "Limiting which tools are offered" in
33
+ `references/setup-guide.md`, which also notes that an agent with a shell can bypass MCP, so the account itself
34
+ must be least-privilege.
35
+ * Requires `vmware-policy>=1.20.0`.
36
+
1
37
  ## v2.0.0 — MCP tools renamed verb-first
2
38
 
3
39
  Every MCP tool in the VMware skill family now follows one naming convention: the verb comes first
@@ -11,7 +11,7 @@
11
11
  "command": "uvx",
12
12
  "args": [
13
13
  "--from",
14
- "vmware-debug==2.0.0",
14
+ "vmware-debug==2.2.0",
15
15
  "vmware-debug-mcp"
16
16
  ]
17
17
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zw008/vmware-debug",
3
- "version": "2.0.0",
3
+ "version": "2.2.0",
4
4
  "description": "VMware incident timeline, root-cause routing, local case ledger; no vSphere access. 14 MCP tools.",
5
5
  "private": true,
6
6
  "license": "MIT",
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "vmware-debug"
7
- version = "2.0.0"
7
+ version = "2.2.0"
8
8
  description = "VMware diagnostic brain — offline incident triage, log/event correlation, and root-cause routing across the VMware skill family"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -20,8 +20,8 @@ classifiers = [
20
20
  dependencies = [
21
21
  "typer>=0.12,<1.0",
22
22
  "rich>=13.0,<15.0",
23
- "mcp[cli]>=1.10,<2.0",
24
- "vmware-policy>=1.18.1,<2.0",
23
+ "mcp[cli]>=1.28,<2.0",
24
+ "vmware-policy>=1.21.0,<2.0",
25
25
  # Imported directly by ops/cases/grading.py for the rules file. It has
26
26
  # always arrived transitively via vmware-policy; a package should
27
27
  # declare what it imports rather than rely on a dependency's dependency.
@@ -7,12 +7,12 @@
7
7
  "url": "https://github.com/vmware-skills/VMware-Debug",
8
8
  "source": "github"
9
9
  },
10
- "version": "2.0.0",
10
+ "version": "2.2.0",
11
11
  "packages": [
12
12
  {
13
13
  "registryType": "pypi",
14
14
  "identifier": "vmware-debug",
15
- "version": "2.0.0",
15
+ "version": "2.2.0",
16
16
  "runtimeHint": "uvx",
17
17
  "packageArguments": [
18
18
  {
@@ -51,7 +51,7 @@ write tools touch only the local case ledger.
51
51
  ## Quick Install
52
52
 
53
53
  ```bash
54
- uv tool install vmware-debug==2.0.0
54
+ uv tool install vmware-debug==2.2.0
55
55
  vmware-debug categories # see what it can diagnose
56
56
  ```
57
57
 
@@ -6,7 +6,7 @@ is a pure, offline correlation engine. There is no `config.yaml` and no `.env`.
6
6
  ## Install
7
7
 
8
8
  ```bash
9
- uv tool install vmware-debug==2.0.0
9
+ uv tool install vmware-debug==2.2.0
10
10
  vmware-debug categories # verify it runs
11
11
  ```
12
12
 
@@ -15,7 +15,7 @@ vmware-debug categories # verify it runs
15
15
  ```json
16
16
  {
17
17
  "command": "uvx",
18
- "args": ["--from", "vmware-debug==2.0.0", "vmware-debug-mcp"]
18
+ "args": ["--from", "vmware-debug==2.2.0", "vmware-debug-mcp"]
19
19
  }
20
20
  ```
21
21
 
@@ -26,6 +26,31 @@ For full cross-skill diagnosis, also install the data-source skills it correlate
26
26
  (vmware-monitor, vmware-log-insight, vmware-aria, vmware-nsx) and the executors it
27
27
  routes fixes to (vmware-aiops, vmware-pilot).
28
28
 
29
+ ## Limiting which tools are offered
30
+
31
+ By default the MCP server offers every tool. To offer only read tools, start it with `--expose read`, or set
32
+ `VMWARE_DEBUG_MCP_EXPOSE=read` in the MCP client's `env` block (useful when the client launches `vmware-debug mcp` itself). To offer
33
+ chosen write tools as well, add `--allow-write` with a comma-separated list (or `VMWARE_DEBUG_MCP_ALLOW_WRITE`):
34
+
35
+ ```bash
36
+ vmware-debug mcp --expose read --allow-write close_case
37
+ ```
38
+
39
+ - A read tool is one annotated `readOnlyHint: true`; every other tool counts as a write.
40
+ - An unknown setting, or a name that is not a write tool of this server, stops the server before it serves (exit
41
+ code 2), so it never offers more than you asked for. Pre-2.0 tool names are accepted.
42
+ - With `--expose read`, the server prints one line to stderr saying what it exposes.
43
+ - Flags and environment variables are not mixed: if either flag is given, both environment variables are
44
+ ignored, so a leftover `_ALLOW_WRITE` in the shell cannot widen `--expose read`. A blank flag value counts as
45
+ not given.
46
+ - A tool that runs other steps (a plan, workflow or batch tool) carries every write it can execute, including
47
+ writes this setting hides. Expose such a tool only if you would expose those writes too.
48
+ - A launcher that imports the server object can call
49
+ `vmware_policy.exposure.restrict_tools(mcp, skill="debug", expose="read", allow_write=[...])` before running it,
50
+ instead of editing the SDK's tool registry.
51
+ - This limits what clients are offered. It is **not** authorization. This server's write tools change case records on this machine;
52
+ deny rules in `~/.vmware/rules.yaml` still apply to every exposed tool.
53
+
29
54
  ## Security
30
55
 
31
56
  > **Disclaimer**: Community-maintained open-source project, **not affiliated with,
@@ -104,9 +104,10 @@ FAMILY_TOOLS: dict[str, frozenset[str]] = {
104
104
  'update_dfw_policy', 'update_dfw_rule',
105
105
  }),
106
106
  'vmware-pilot': frozenset({
107
- 'approve', 'cancel_workflow', 'confirm_draft', 'create_workflow', 'design_workflow',
108
- 'get_skill_catalog', 'get_workflow_status', 'list_workflows', 'plan_workflow',
109
- 'review_workflow', 'rollback', 'run_workflow', 'update_draft',
107
+ 'approve', 'cancel_workflow', 'confirm_draft', 'create_workflow',
108
+ 'create_workflow_from_template', 'design_workflow', 'get_skill_catalog',
109
+ 'get_workflow_status', 'list_workflows', 'review_workflow', 'rollback',
110
+ 'run_workflow', 'update_draft',
110
111
  }),
111
112
  'vmware-storage': frozenset({
112
113
  'add_iscsi_target', 'browse_datastore', 'enable_iscsi', 'get_iscsi_status',
@@ -118,10 +119,11 @@ FAMILY_TOOLS: dict[str, frozenset[str]] = {
118
119
  'vmware-vks': frozenset({
119
120
  'check_vks_compatibility', 'create_namespace', 'create_tkc_cluster',
120
121
  'delete_namespace', 'delete_tkc_cluster', 'get_harbor_info', 'get_namespace',
121
- 'get_supervisor_kubeconfig', 'get_supervisor_status', 'get_tkc_available_versions',
122
- 'get_tkc_cluster', 'get_tkc_kubeconfig', 'list_namespace_storage_usage',
123
- 'list_namespaces', 'list_supervisor_storage_policies', 'list_tkc_clusters',
124
- 'list_vm_classes', 'list_vm_service_groups', 'list_vm_service_network_interfaces',
122
+ 'get_supervisor_status', 'get_tkc_available_versions', 'get_tkc_cluster',
123
+ 'issue_supervisor_kubeconfig', 'issue_tkc_kubeconfig',
124
+ 'list_namespace_storage_usage', 'list_namespaces',
125
+ 'list_supervisor_storage_policies', 'list_tkc_clusters', 'list_vm_classes',
126
+ 'list_vm_service_groups', 'list_vm_service_network_interfaces',
125
127
  'list_vm_service_snapshots', 'scale_tkc_cluster', 'update_namespace',
126
128
  'upgrade_tkc_cluster',
127
129
  }),
@@ -1293,7 +1293,7 @@ wheels = [
1293
1293
 
1294
1294
  [[package]]
1295
1295
  name = "vmware-debug"
1296
- version = "2.0.0"
1296
+ version = "2.2.0"
1297
1297
  source = { editable = "." }
1298
1298
  dependencies = [
1299
1299
  { name = "mcp", extra = ["cli"] },
@@ -1312,11 +1312,11 @@ dev = [
1312
1312
 
1313
1313
  [package.metadata]
1314
1314
  requires-dist = [
1315
- { name = "mcp", extras = ["cli"], specifier = ">=1.10,<2.0" },
1315
+ { name = "mcp", extras = ["cli"], specifier = ">=1.28,<2.0" },
1316
1316
  { name = "pyyaml", specifier = ">=6.0,<7.0" },
1317
1317
  { name = "rich", specifier = ">=13.0,<15.0" },
1318
1318
  { name = "typer", specifier = ">=0.12,<1.0" },
1319
- { name = "vmware-policy", specifier = ">=1.18.1,<2.0" },
1319
+ { name = "vmware-policy", specifier = ">=1.21.0,<2.0" },
1320
1320
  ]
1321
1321
 
1322
1322
  [package.metadata.requires-dev]
@@ -1328,14 +1328,14 @@ dev = [
1328
1328
 
1329
1329
  [[package]]
1330
1330
  name = "vmware-policy"
1331
- version = "1.18.2"
1331
+ version = "1.21.0"
1332
1332
  source = { registry = "https://pypi.org/simple" }
1333
1333
  dependencies = [
1334
1334
  { name = "pyyaml" },
1335
1335
  { name = "rich" },
1336
1336
  { name = "typer" },
1337
1337
  ]
1338
- sdist = { url = "https://files.pythonhosted.org/packages/5d/ce/a4f31330f983f411051ab0f42dcbd3c7174670541fa5cdb7faaf22991b24/vmware_policy-1.18.2.tar.gz", hash = "sha256:8e52629bf4a0d355a6841f1d9d5fb4ac1e69bbc7ae22d3843dd7cf3426b30e4c", size = 208412, upload-time = "2026-10-14T06:08:54.124Z" }
1338
+ sdist = { url = "https://files.pythonhosted.org/packages/87/5d/4221ea4a344ec33d6b54903682ce8ae2013bb0a2d6137c94ac769690ea8b/vmware_policy-1.21.0.tar.gz", hash = "sha256:f42b794ea69e52e1fa13aff8b5bc07631d82683b1c12872f2f2ec744e3853549", size = 303862, upload-time = "2026-10-15T10:13:33.719Z" }
1339
1339
  wheels = [
1340
- { url = "https://files.pythonhosted.org/packages/6b/cc/0ad37c57ee902819efc1c193b363df9a7c762794e7dff3318577c17743de/vmware_policy-1.18.2-py3-none-any.whl", hash = "sha256:6e7414f6cc7d783f486db858fd99dd7123ddefc0e823a8b319756e17ece03455", size = 80791, upload-time = "2026-10-14T06:08:52.267Z" },
1340
+ { url = "https://files.pythonhosted.org/packages/b3/b4/feb7015ae5f7870e8058ad713050f7fe3ddefa57aa7bdd4a83f2e3b9abb4/vmware_policy-1.21.0-py3-none-any.whl", hash = "sha256:a10c26816be09f9a2823cc58bc4eacb9b5eff8b6df49dfc5b504b3d76cb3b7ec", size = 99818, upload-time = "2026-10-15T10:13:31.67Z" },
1341
1341
  ]
@@ -6,4 +6,4 @@ remediation to vmware-aiops / vmware-pilot. Never writes to any VMware system
6
6
  and never executes fixes; its only writes go to the local case ledger.
7
7
  """
8
8
 
9
- __version__ = "2.0.0"
9
+ __version__ = "2.2.0"
@@ -104,11 +104,44 @@ def triage(
104
104
 
105
105
  @app.command()
106
106
  @cli_local("starts the MCP server; its tools audit themselves")
107
- def mcp() -> None:
108
- """Start the stdio MCP server (no network access; proxy-safe)."""
107
+ def mcp(
108
+ expose: Optional[str] = typer.Option(
109
+ None,
110
+ "--expose",
111
+ help="Which tools to offer: all (default) or read. Limits what clients see; "
112
+ "not authorization: the account's permissions still decide.",
113
+ ),
114
+ allow_write: Optional[str] = typer.Option(
115
+ None,
116
+ "--allow-write",
117
+ help="With --expose read: comma-separated write tools to offer as well.",
118
+ ),
119
+ transport: Optional[str] = typer.Option(
120
+ None,
121
+ "--transport",
122
+ help="stdio (default), https, or http (loopback only, behind a TLS reverse proxy). "
123
+ "https/http need a token: 'vmware-audit token create NAME'.",
124
+ ),
125
+ host: Optional[str] = typer.Option(None, "--host", help="Bind address (default 127.0.0.1)."),
126
+ port: Optional[int] = typer.Option(None, "--port", help="Port (default 8443)."),
127
+ cert: Optional[str] = typer.Option(None, "--cert", help="TLS certificate (PEM) for https."),
128
+ key: Optional[str] = typer.Option(None, "--key", help="TLS private key (PEM) for https."),
129
+ public_name: Optional[str] = typer.Option(
130
+ None,
131
+ "--public-name",
132
+ help="Host names clients use, comma-separated; other Host/Origin values are refused.",
133
+ ),
134
+ token_file: Optional[str] = typer.Option(
135
+ None, "--token-file", help="Token hash file (default $OPS_HOME/mcp-tokens)."
136
+ ),
137
+ ) -> None:
138
+ """Start the MCP server: stdio by default (proxy-safe), or --transport https."""
109
139
  from vmware_debug.mcp_server.server import main as _main
110
140
 
111
- _main()
141
+ _main(
142
+ expose=expose, allow_write=allow_write, transport=transport, host=host, port=port,
143
+ cert=cert, key=key, public_name=public_name, token_file=token_file,
144
+ )
112
145
 
113
146
 
114
147
  if __name__ == "__main__":
@@ -862,7 +862,17 @@ def build_server() -> FastMCP:
862
862
 
863
863
 
864
864
  return server
865
- def main() -> None:
865
+ def main(
866
+ expose: Optional[str] = None,
867
+ allow_write: Optional[str] = None,
868
+ transport: Optional[str] = None,
869
+ host: Optional[str] = None,
870
+ port: Optional[int] = None,
871
+ cert: Optional[str] = None,
872
+ key: Optional[str] = None,
873
+ public_name: Optional[str] = None,
874
+ token_file: Optional[str] = None,
875
+ ) -> None:
866
876
  """Entry point for `vmware-debug-mcp` (stdio transport)."""
867
877
  # Floor is 3.10, matching `requires-python` and the other eleven skills.
868
878
  # This guard used to demand 3.11 on the grounds that FastMCP schema
@@ -878,7 +888,14 @@ def main() -> None:
878
888
  "Reinstall on a newer interpreter: "
879
889
  "uv tool install --python 3.12 --force vmware-debug"
880
890
  )
881
- build_server().run()
891
+ from vmware_policy.serve import run_server
892
+ server = build_server()
893
+ run_server(
894
+ server,
895
+ skill="debug",
896
+ expose=expose, allow_write=allow_write, transport=transport, host=host, port=port,
897
+ cert=cert, key=key, public_name=public_name, token_file=token_file,
898
+ )
882
899
 
883
900
 
884
901
  if __name__ == "__main__":
File without changes
File without changes