vmware-debug 2.1.0__tar.gz → 2.3.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 (98) hide show
  1. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/.claude-plugin/plugin.json +1 -1
  2. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/.mcp.json +1 -1
  3. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/PKG-INFO +68 -3
  4. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/README-CN.md +63 -0
  5. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/README.md +65 -0
  6. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/RELEASE_NOTES.md +36 -0
  7. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/openclaw.plugin.json +1 -1
  8. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/package.json +1 -1
  9. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/pyproject.toml +3 -3
  10. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/server.json +2 -2
  11. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/skills/vmware-debug/SKILL.md +1 -1
  12. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/skills/vmware-debug/references/setup-guide.md +38 -2
  13. vmware_debug-2.3.0/tests/test_policy_roles.py +32 -0
  14. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/uv.lock +6 -6
  15. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/vmware_debug/__init__.py +1 -1
  16. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/vmware_debug/cli.py +23 -2
  17. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/vmware_debug/mcp_server/server.py +21 -4
  18. vmware_debug-2.3.0/vmware_debug/policy_roles.py +27 -0
  19. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/.clawhubignore +0 -0
  20. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/.gitignore +0 -0
  21. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/SECURITY.md +0 -0
  22. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/docs/plans/2026-08-28-investigation-layer-design.md +0 -0
  23. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/skills/vmware-debug/references/agent-guardrails.md +0 -0
  24. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/skills/vmware-debug/references/capabilities.md +0 -0
  25. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/skills/vmware-debug/references/cli-reference.md +0 -0
  26. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/skills/vmware-debug/references/event-envelope.md +0 -0
  27. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/skills/vmware-debug/references/routing.md +0 -0
  28. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/__init__.py +0 -0
  29. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/conftest.py +0 -0
  30. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/eval/__init__.py +0 -0
  31. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/eval/capability/__init__.py +0 -0
  32. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/eval/capability/_family.py +0 -0
  33. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/eval/capability/_scores.json +0 -0
  34. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/eval/capability/_scoring.py +0 -0
  35. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/eval/capability/_skill.py +0 -0
  36. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/eval/capability/conftest.py +0 -0
  37. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/eval/capability/test_entity_reachability.py +0 -0
  38. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/eval/capability/test_error_actionability.py +0 -0
  39. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/eval/capability/test_tool_description_quality.py +0 -0
  40. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/eval/capability/test_tool_manifest_budget.py +0 -0
  41. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/eval/regression/__init__.py +0 -0
  42. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/eval/regression/_vsphere_event_vocabulary.py +0 -0
  43. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/eval/regression/test_audit_isolation.py +0 -0
  44. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/eval/regression/test_capability_grader.py +0 -0
  45. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/eval/regression/test_case_id_non_ascii.py +0 -0
  46. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/eval/regression/test_case_plan_max_steps.py +0 -0
  47. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/eval/regression/test_classification_against_vsphere_vocabulary.py +0 -0
  48. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/eval/regression/test_debug_regressions.py +0 -0
  49. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/eval/regression/test_environment_resolver_isolation.py +0 -0
  50. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/eval/regression/test_every_tool_parameter_is_documented.py +0 -0
  51. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/eval/regression/test_evidence_payload_contract.py +0 -0
  52. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/eval/regression/test_host_lifecycle_classification.py +0 -0
  53. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/eval/regression/test_investigation_metrics.py +0 -0
  54. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/eval/regression/test_real_alert_titles_classify.py +0 -0
  55. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/eval/regression/test_result_envelope.py +0 -0
  56. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/eval/regression/test_skill_name_aliases.py +0 -0
  57. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/eval/regression/test_spike_resolution.py +0 -0
  58. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/eval/regression/test_tool_annotations.py +0 -0
  59. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/test_case_conclusion.py +0 -0
  60. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/test_case_evidence.py +0 -0
  61. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/test_case_grading.py +0 -0
  62. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/test_case_grading_per_hypothesis.py +0 -0
  63. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/test_case_hypotheses.py +0 -0
  64. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/test_case_ids.py +0 -0
  65. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/test_case_ledger_concurrency.py +0 -0
  66. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/test_case_plan.py +0 -0
  67. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/test_case_readiness.py +0 -0
  68. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/test_case_store.py +0 -0
  69. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/test_case_timeline_close.py +0 -0
  70. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/test_case_tools.py +0 -0
  71. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/test_knowledge.py +0 -0
  72. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/test_mcp_audit.py +0 -0
  73. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/test_safe_error_passthrough.py +0 -0
  74. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/tests/test_timeline.py +0 -0
  75. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/vmware_debug/envelope.py +0 -0
  76. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/vmware_debug/mcp/__init__.py +0 -0
  77. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/vmware_debug/mcp/tools.py +0 -0
  78. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/vmware_debug/mcp_server/__init__.py +0 -0
  79. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/vmware_debug/ops/__init__.py +0 -0
  80. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/vmware_debug/ops/cases/__init__.py +0 -0
  81. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/vmware_debug/ops/cases/api.py +0 -0
  82. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/vmware_debug/ops/cases/conclusion.py +0 -0
  83. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/vmware_debug/ops/cases/evidence.py +0 -0
  84. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/vmware_debug/ops/cases/grading.py +0 -0
  85. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/vmware_debug/ops/cases/hypotheses.py +0 -0
  86. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/vmware_debug/ops/cases/ids.py +0 -0
  87. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/vmware_debug/ops/cases/knowledge.py +0 -0
  88. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/vmware_debug/ops/cases/model.py +0 -0
  89. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/vmware_debug/ops/cases/payloads.py +0 -0
  90. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/vmware_debug/ops/cases/plan.py +0 -0
  91. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/vmware_debug/ops/cases/readiness.py +0 -0
  92. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/vmware_debug/ops/cases/sources.py +0 -0
  93. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/vmware_debug/ops/cases/store.py +0 -0
  94. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/vmware_debug/ops/cases/timeline.py +0 -0
  95. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/vmware_debug/ops/skill_names.py +0 -0
  96. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/vmware_debug/ops/timeline.py +0 -0
  97. {vmware_debug-2.1.0 → vmware_debug-2.3.0}/vmware_debug/rules/evidence_sources.yaml +0 -0
  98. {vmware_debug-2.1.0 → vmware_debug-2.3.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.1.0",
5
+ "version": "2.3.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.1.0",
8
+ "vmware-debug==2.3.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.1.0
3
+ Version: 2.3.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.20.0
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 -->
@@ -145,6 +145,71 @@ pip wheel . -w dist # → dist/*.whl (or: uv build, for just this packa
145
145
  pip install --no-index --find-links dist vmware-debug
146
146
  ```
147
147
 
148
+ <!-- usage: remote-and-exposure -->
149
+ ## Remote access (HTTPS) and limiting tools
150
+
151
+ By default `vmware-debug mcp` speaks stdio to one local client and offers every tool. Two options change that
152
+ (vmware-policy ≥ 1.21.0).
153
+
154
+ **Serve over HTTPS** so clients on other machines can connect. Every caller needs a bearer token:
155
+
156
+ ```bash
157
+ vmware-audit token create alice # prints the token once; give it to alice
158
+ vmware-audit token list # names only
159
+ vmware-audit token revoke alice # refused from its next request, no restart
160
+ vmware-debug mcp --transport https --host 0.0.0.0 --port 8443 \
161
+ --cert /etc/vmware-mcp/server.pem --key /etc/vmware-mcp/server-key.pem \
162
+ --public-name mcp.example.com
163
+ ```
164
+
165
+ Connect a client (Claude Code shown; any MCP client that supports streamable HTTP and custom headers works):
166
+
167
+ ```bash
168
+ claude mcp add --transport http vmware-debug https://mcp.example.com:8443/mcp \
169
+ --header "Authorization: Bearer $VMWARE_MCP_TOKEN"
170
+ ```
171
+
172
+ ```json
173
+ {
174
+ "mcpServers": {
175
+ "vmware-debug": {
176
+ "type": "http",
177
+ "url": "https://mcp.example.com:8443/mcp",
178
+ "headers": { "Authorization": "Bearer ${VMWARE_MCP_TOKEN}" }
179
+ }
180
+ }
181
+ }
182
+ ```
183
+
184
+ - The server will not start without a token, refuses Host/Origin values outside `--public-name`, and checks
185
+ before it binds that unauthenticated requests get 401. Use a certificate your clients trust for those names.
186
+ - Behind a TLS-terminating reverse proxy on the same machine use `--transport http --host 127.0.0.1
187
+ --public-name mcp.example.com` and pass the `Authorization` header through.
188
+ - Behind a load balancer or gateway on another machine, keep `--transport https` (a self-signed certificate is
189
+ fine), list in `--public-name` the host name the balancer sends as `Host`, and have it forward `Authorization`.
190
+ Its health probe can use `GET /healthz`, which needs no token and returns only `{"status": "ok"}`
191
+ (vmware-policy ≥ 1.23.0).
192
+ - Send `traceparent` or `X-Request-ID` with each request to have it stored on the audit row;
193
+ `vmware-audit log --correlation-id ID` then finds the calls behind one platform request.
194
+ - The audit log records each caller as `token:<name>`. Calls naming different targets run in parallel; calls that
195
+ name no target run one at a time, so name the target when several people share a server.
196
+ - **Everyone who can reach the endpoint acts with this server's account.** Tokens identify callers; they grant
197
+ nothing on the platform. Run one endpoint per privilege level.
198
+ - **Several people or roles on one endpoint:** run `vmware-audit roles enable` once, then give each token a role (`vmware-audit token create NAME --role reader`, or a role in `roles.yaml` naming tools and targets; vmware-policy ≥ 1.24.0). A role limits what the token may call on this endpoint; it cannot grant more than the account has. See vmware-policy's README, "Roles for network callers".
199
+
200
+ **Offer only read tools, plus the writes you choose:**
201
+
202
+ ```bash
203
+ vmware-debug mcp --expose read --allow-write close_case
204
+ # or: VMWARE_DEBUG_MCP_EXPOSE=read VMWARE_DEBUG_MCP_ALLOW_WRITE=close_case vmware-debug mcp
205
+ ```
206
+
207
+ Tools not offered do not appear in the client's tool list. A bad value or an unknown write tool stops the server
208
+ (exit 2). This limits what clients are offered; it is not authorization, so the account itself should be
209
+ least-privilege.
210
+
211
+ Details: `skills/vmware-debug/references/setup-guide.md` ("Serving MCP over HTTPS", "Limiting which tools are offered").
212
+
148
213
  ## License
149
214
 
150
215
  MIT.
@@ -102,6 +102,69 @@ pip wheel . -w dist # → dist/*.whl (或:uv build,只构建本
102
102
  pip install --no-index --find-links dist vmware-debug
103
103
  ```
104
104
 
105
+ <!-- usage: remote-and-exposure -->
106
+ ## 远程访问(HTTPS)与限制工具
107
+
108
+ 默认情况下 `vmware-debug mcp` 通过 stdio 服务一个本地客户端,并提供全部工具。以下两个选项可以改变这一点
109
+ (需 vmware-policy ≥ 1.21.0)。
110
+
111
+ **通过 HTTPS 提供服务**,让其他机器上的客户端连接。每个调用者都需要一个 bearer token:
112
+
113
+ ```bash
114
+ vmware-audit token create alice # 只显示一次,交给 alice
115
+ vmware-audit token list # 只列名字
116
+ vmware-audit token revoke alice # 下一个请求起即拒绝,无需重启
117
+ vmware-debug mcp --transport https --host 0.0.0.0 --port 8443 \
118
+ --cert /etc/vmware-mcp/server.pem --key /etc/vmware-mcp/server-key.pem \
119
+ --public-name mcp.example.com
120
+ ```
121
+
122
+ 连接客户端(以 Claude Code 为例;任何支持 streamable HTTP 和自定义请求头的 MCP 客户端都可以):
123
+
124
+ ```bash
125
+ claude mcp add --transport http vmware-debug https://mcp.example.com:8443/mcp \
126
+ --header "Authorization: Bearer $VMWARE_MCP_TOKEN"
127
+ ```
128
+
129
+ ```json
130
+ {
131
+ "mcpServers": {
132
+ "vmware-debug": {
133
+ "type": "http",
134
+ "url": "https://mcp.example.com:8443/mcp",
135
+ "headers": { "Authorization": "Bearer ${VMWARE_MCP_TOKEN}" }
136
+ }
137
+ }
138
+ }
139
+ ```
140
+
141
+ - 没有 token 时服务不会启动;`--public-name` 之外的 Host/Origin 一律拒绝;绑定端口前会自检,确认未认证请求得到 401。
142
+ 证书要用客户端信任、且覆盖这些名字的证书。
143
+ - 在同一台机器上由反向代理终结 TLS 时,用 `--transport http --host 127.0.0.1 --public-name mcp.example.com`,
144
+ 并让代理透传 `Authorization` 头。
145
+ - 负载均衡或网关在另一台机器上时,保持 `--transport https`(自签证书也可以),在 `--public-name` 里写上负载均衡
146
+ 转发时带的 `Host` 名,并让它透传 `Authorization`。健康检查可以用 `GET /healthz`:不需要 token,只返回
147
+ `{"status": "ok"}`(需 vmware-policy ≥ 1.23.0)。
148
+ - 每个请求带上 `traceparent` 或 `X-Request-ID`,它会记进审计记录;用 `vmware-audit log --correlation-id ID`
149
+ 就能查到平台上某一次请求对应的调用。
150
+ - 审计日志把每个调用者记为 `token:<名字>`。指定不同 target 的调用并行执行;不指定 target 的调用逐个执行,
151
+ 所以多人共用一个 server 时请写明 target。
152
+ - **能连到这个端点的人,都以该 server 配置的账号操作。** token 只用来识别调用者,不在平台上授予任何权限。
153
+ 每个权限级别单独起一个端点。
154
+ - **一个端点给多人或多种角色用:** 先运行一次 `vmware-audit roles enable`,再给每个 token 指定角色(`vmware-audit token create 名字 --role reader`,或在 `roles.yaml` 里定义可用的工具和 target;需 vmware-policy ≥ 1.24.0)。角色只能限定这个 token 在本端点上能调用什么,不能超出账号本身的权限。详见 vmware-policy README 的「网络调用者的角色」一节。
155
+
156
+ **只提供读工具,加上你选定的写工具:**
157
+
158
+ ```bash
159
+ vmware-debug mcp --expose read --allow-write close_case
160
+ # 或:VMWARE_DEBUG_MCP_EXPOSE=read VMWARE_DEBUG_MCP_ALLOW_WRITE=close_case vmware-debug mcp
161
+ ```
162
+
163
+ 未提供的工具不会出现在客户端的工具列表里。取值错误或写工具名不存在时服务直接退出(exit 2)。
164
+ 这只限制提供给客户端的工具,不是授权;账号本身仍应遵循最小权限。
165
+
166
+ 详见 `skills/vmware-debug/references/setup-guide.md`("Serving MCP over HTTPS"、"Limiting which tools are offered")。
167
+
105
168
  ## 许可证
106
169
 
107
170
  MIT。
@@ -122,6 +122,71 @@ pip wheel . -w dist # → dist/*.whl (or: uv build, for just this packa
122
122
  pip install --no-index --find-links dist vmware-debug
123
123
  ```
124
124
 
125
+ <!-- usage: remote-and-exposure -->
126
+ ## Remote access (HTTPS) and limiting tools
127
+
128
+ By default `vmware-debug mcp` speaks stdio to one local client and offers every tool. Two options change that
129
+ (vmware-policy ≥ 1.21.0).
130
+
131
+ **Serve over HTTPS** so clients on other machines can connect. Every caller needs a bearer token:
132
+
133
+ ```bash
134
+ vmware-audit token create alice # prints the token once; give it to alice
135
+ vmware-audit token list # names only
136
+ vmware-audit token revoke alice # refused from its next request, no restart
137
+ vmware-debug mcp --transport https --host 0.0.0.0 --port 8443 \
138
+ --cert /etc/vmware-mcp/server.pem --key /etc/vmware-mcp/server-key.pem \
139
+ --public-name mcp.example.com
140
+ ```
141
+
142
+ Connect a client (Claude Code shown; any MCP client that supports streamable HTTP and custom headers works):
143
+
144
+ ```bash
145
+ claude mcp add --transport http vmware-debug https://mcp.example.com:8443/mcp \
146
+ --header "Authorization: Bearer $VMWARE_MCP_TOKEN"
147
+ ```
148
+
149
+ ```json
150
+ {
151
+ "mcpServers": {
152
+ "vmware-debug": {
153
+ "type": "http",
154
+ "url": "https://mcp.example.com:8443/mcp",
155
+ "headers": { "Authorization": "Bearer ${VMWARE_MCP_TOKEN}" }
156
+ }
157
+ }
158
+ }
159
+ ```
160
+
161
+ - The server will not start without a token, refuses Host/Origin values outside `--public-name`, and checks
162
+ before it binds that unauthenticated requests get 401. Use a certificate your clients trust for those names.
163
+ - Behind a TLS-terminating reverse proxy on the same machine use `--transport http --host 127.0.0.1
164
+ --public-name mcp.example.com` and pass the `Authorization` header through.
165
+ - Behind a load balancer or gateway on another machine, keep `--transport https` (a self-signed certificate is
166
+ fine), list in `--public-name` the host name the balancer sends as `Host`, and have it forward `Authorization`.
167
+ Its health probe can use `GET /healthz`, which needs no token and returns only `{"status": "ok"}`
168
+ (vmware-policy ≥ 1.23.0).
169
+ - Send `traceparent` or `X-Request-ID` with each request to have it stored on the audit row;
170
+ `vmware-audit log --correlation-id ID` then finds the calls behind one platform request.
171
+ - The audit log records each caller as `token:<name>`. Calls naming different targets run in parallel; calls that
172
+ name no target run one at a time, so name the target when several people share a server.
173
+ - **Everyone who can reach the endpoint acts with this server's account.** Tokens identify callers; they grant
174
+ nothing on the platform. Run one endpoint per privilege level.
175
+ - **Several people or roles on one endpoint:** run `vmware-audit roles enable` once, then give each token a role (`vmware-audit token create NAME --role reader`, or a role in `roles.yaml` naming tools and targets; vmware-policy ≥ 1.24.0). A role limits what the token may call on this endpoint; it cannot grant more than the account has. See vmware-policy's README, "Roles for network callers".
176
+
177
+ **Offer only read tools, plus the writes you choose:**
178
+
179
+ ```bash
180
+ vmware-debug mcp --expose read --allow-write close_case
181
+ # or: VMWARE_DEBUG_MCP_EXPOSE=read VMWARE_DEBUG_MCP_ALLOW_WRITE=close_case vmware-debug mcp
182
+ ```
183
+
184
+ Tools not offered do not appear in the client's tool list. A bad value or an unknown write tool stops the server
185
+ (exit 2). This limits what clients are offered; it is not authorization, so the account itself should be
186
+ least-privilege.
187
+
188
+ Details: `skills/vmware-debug/references/setup-guide.md` ("Serving MCP over HTTPS", "Limiting which tools are offered").
189
+
125
190
  ## License
126
191
 
127
192
  MIT.
@@ -1,3 +1,39 @@
1
+ ## v2.3.0 — roles for network callers (HLD §18)
2
+
3
+ * Declares the role metadata vmware-policy ≥ 1.24.0 needs to apply **roles** to this server over HTTPS
4
+ (HLD §18): that no tool takes a target. With an older vmware-policy nothing changes. Once an operator runs
5
+ `vmware-audit roles enable`, a token's role decides which tools and targets it may use here; a refused call is
6
+ audited as `denied`. See vmware-policy's README, "Roles for network callers".
7
+ * README and setup guide: one endpoint for several people or roles.
8
+
9
+ ## v2.2.0 — serve MCP over HTTPS
10
+
11
+ `vmware-debug mcp` can now serve the network as well as stdio (HLD §16, via vmware-policy 1.21.0):
12
+
13
+ ```bash
14
+ vmware-audit token create alice # once per caller; shown once
15
+ vmware-debug mcp --transport https --host 0.0.0.0 --port 8443 \
16
+ --cert server.pem --key server-key.pem --public-name mcp.example.com
17
+ ```
18
+
19
+ Connect a client and manage callers (Claude Code shown; any MCP client with streamable HTTP and custom headers works):
20
+
21
+ ```bash
22
+ claude mcp add --transport http vmware-debug https://mcp.example.com:8443/mcp \
23
+ --header "Authorization: Bearer $VMWARE_MCP_TOKEN"
24
+ vmware-audit token list # names only
25
+ vmware-audit token revoke alice # refused from its next request, no restart
26
+ ```
27
+
28
+ * Every request needs `Authorization: Bearer <token>`; the server will not start without a token, refuses Host or
29
+ Origin values outside `--public-name`, and checks itself (unauthenticated requests must get 401) before it
30
+ binds. `--transport http` binds loopback only, for a TLS-terminating reverse proxy.
31
+ * Audit rows record the caller as `token:<name>` and the surface as `mcp-https`. Calls naming different targets
32
+ run in parallel; calls naming no target run one at a time.
33
+ * stdio remains the default; the `vmware-debug-mcp` console script and `python -m` are unchanged.
34
+ * Everyone who can reach the endpoint acts with this server's account; run one endpoint per privilege level.
35
+ * Requires `vmware-policy>=1.21.0` and `mcp>=1.28`.
36
+
1
37
  ## v2.1.0 — offer only read tools, plus chosen write tools
2
38
 
3
39
  `vmware-debug mcp` can now offer a subset of this server's tools (HLD §17 D-16, via vmware-policy 1.20.0):
@@ -11,7 +11,7 @@
11
11
  "command": "uvx",
12
12
  "args": [
13
13
  "--from",
14
- "vmware-debug==2.1.0",
14
+ "vmware-debug==2.3.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.1.0",
3
+ "version": "2.3.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.1.0"
7
+ version = "2.3.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.20.0,<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.1.0",
10
+ "version": "2.3.0",
11
11
  "packages": [
12
12
  {
13
13
  "registryType": "pypi",
14
14
  "identifier": "vmware-debug",
15
- "version": "2.1.0",
15
+ "version": "2.3.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.1.0
54
+ uv tool install vmware-debug==2.3.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.1.0
9
+ uv tool install vmware-debug==2.3.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.1.0", "vmware-debug-mcp"]
18
+ "args": ["--from", "vmware-debug==2.3.0", "vmware-debug-mcp"]
19
19
  }
20
20
  ```
21
21
 
@@ -51,6 +51,42 @@ vmware-debug mcp --expose read --allow-write close_case
51
51
  - This limits what clients are offered. It is **not** authorization. This server's write tools change case records on this machine;
52
52
  deny rules in `~/.vmware/rules.yaml` still apply to every exposed tool.
53
53
 
54
+ ## Serving MCP over HTTPS
55
+
56
+ By default the MCP server speaks stdio to one local client. To let clients on other machines reach it, serve it over
57
+ HTTPS. Every caller then needs a bearer token.
58
+
59
+ ```bash
60
+ vmware-audit token create alice # prints the token once; give it to alice
61
+ vmware-debug mcp --transport https --host 0.0.0.0 --port 8443 \
62
+ --cert /etc/vmware-mcp/server.pem --key /etc/vmware-mcp/server-key.pem \
63
+ --public-name mcp.example.com
64
+ ```
65
+
66
+ - Clients connect to `https://mcp.example.com:8443/mcp` and send `Authorization: Bearer <token>`.
67
+ - `--public-name` lists every host name clients use (comma-separated); requests for any other Host or Origin are
68
+ refused. Use a certificate your clients trust for those names.
69
+ - Behind a reverse proxy that terminates TLS (Nginx, HAProxy) on the same machine, use
70
+ `--transport http --host 127.0.0.1 --public-name mcp.example.com` (the names the proxy forwards in `Host`), and
71
+ have the proxy pass the `Authorization` header through.
72
+ - Behind a load balancer or gateway on another machine, keep `--transport https` (a self-signed certificate is
73
+ fine: the balancer is the client that has to trust it), list in `--public-name` the host name the balancer sends
74
+ as `Host`, and have it forward `Authorization`. Point its health probe at `GET /healthz`: it needs no token, returns
75
+ only `{"status": "ok"}` and accepts any `Host` (vmware-policy ≥ 1.23.0). Every other path still needs the token.
76
+ - Correlation: each audit row stores the caller's `traceparent` trace-id, else its `X-Request-ID` /
77
+ `X-Correlation-ID`. Have the agent platform send one, and `vmware-audit log --correlation-id ID` lists the calls
78
+ behind one platform request.
79
+ - `vmware-audit token list` / `token revoke NAME` manage callers; a revoked token is refused from its next request.
80
+ Replace a leaked token under a new name.
81
+ - The server will not start without at least one token, and checks before it binds that unauthenticated requests
82
+ are refused.
83
+ - Each audit row records the caller as `token:<name>`. Calls naming different targets run in parallel; calls that
84
+ name no target run one at a time, so name the target when several people use one server.
85
+ - **Everyone who can reach the endpoint acts with this server's account.** Tokens identify callers; they grant
86
+ nothing on the platform. Run one endpoint per privilege level (for example a read-only account behind
87
+ `--expose read`, and a separate endpoint for operators).
88
+ - **Several people or roles on one endpoint:** run `vmware-audit roles enable` once, then give each token a role (`vmware-audit token create NAME --role reader`, or a role in `roles.yaml` naming tools and targets; vmware-policy ≥ 1.24.0). A role limits what the token may call on this endpoint; it cannot grant more than the account has. See vmware-policy's README, "Roles for network callers".
89
+
54
90
  ## Security
55
91
 
56
92
  > **Disclaimer**: Community-maintained open-source project, **not affiliated with,
@@ -0,0 +1,32 @@
1
+ """HLD §18: the role metadata this skill declares matches its real tools."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import asyncio
6
+
7
+ import pytest
8
+
9
+ from vmware_debug import policy_roles
10
+
11
+
12
+ def _registry() -> set[str]:
13
+ from vmware_debug.mcp_server.server import build_server
14
+
15
+ return {t.name for t in asyncio.run(build_server().list_tools())}
16
+
17
+
18
+ @pytest.mark.unit
19
+ def test_every_declared_name_is_a_real_tool():
20
+ named = set(policy_roles.ESCAPES) | set(getattr(policy_roles, "AKO_TOOLS", ()))
21
+ assert named - _registry() == set(), sorted(named - _registry())
22
+
23
+
24
+ @pytest.mark.unit
25
+ def test_metadata_is_declared_when_policy_has_roles():
26
+ roles = pytest.importorskip("vmware_policy.roles")
27
+ import vmware_debug.mcp_server.server # noqa: F401 (registers the metadata on import)
28
+
29
+ meta = roles.metadata("debug")
30
+ assert meta is not None and meta.version == 1
31
+ assert meta.escapes == policy_roles.ESCAPES
32
+ assert (meta.resolver is not None) is False
@@ -1293,7 +1293,7 @@ wheels = [
1293
1293
 
1294
1294
  [[package]]
1295
1295
  name = "vmware-debug"
1296
- version = "2.1.0"
1296
+ version = "2.3.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.20.0,<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.20.0"
1331
+ version = "1.24.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/66/f3/cae0e18d269bd4764d5f9b34a838174e9668f931e44d41effab620aeecf4/vmware_policy-1.20.0.tar.gz", hash = "sha256:eb9875d3e94435a18d1dd6cf2c71905c46e2e812808556db3fb741ef322bee99", size = 220048, upload-time = "2026-10-15T06:33:35.174Z" }
1338
+ sdist = { url = "https://files.pythonhosted.org/packages/4a/62/3a3cb83af77e3dd3c8fc92cb3b7968bfda04a2f71bf0d6f9b72ee3198441/vmware_policy-1.24.0.tar.gz", hash = "sha256:fba12732ccbd4371232c15d9fd014f9f5d697497210aedff2515d1d205ed3577", size = 361302, upload-time = "2026-10-16T07:18:28.317Z" }
1339
1339
  wheels = [
1340
- { url = "https://files.pythonhosted.org/packages/b2/cf/6c87f6b5439407c1c3b83b84a5ef53def7544b687efd6f16a6cb187acf78/vmware_policy-1.20.0-py3-none-any.whl", hash = "sha256:cea9451c70be96e3d7adc420a2ac001cf431c29b61350dd58c3771378058737a", size = 86684, upload-time = "2026-10-15T06:33:33.413Z" },
1340
+ { url = "https://files.pythonhosted.org/packages/3d/f2/fe3d9d384712023916e2cacddc385f14b095509c5e00aea417d1a9550e98/vmware_policy-1.24.0-py3-none-any.whl", hash = "sha256:cf615d0256134f01fb84c39b083649281a66d2c064c2eaa28786a0fa95ec6e58", size = 131460, upload-time = "2026-10-16T07:18:26.907Z" },
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.1.0"
9
+ __version__ = "2.3.0"
@@ -116,11 +116,32 @@ def mcp(
116
116
  "--allow-write",
117
117
  help="With --expose read: comma-separated write tools to offer as well.",
118
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
+ ),
119
137
  ) -> None:
120
- """Start the stdio MCP server (no network access; proxy-safe)."""
138
+ """Start the MCP server: stdio by default (proxy-safe), or --transport https."""
121
139
  from vmware_debug.mcp_server.server import main as _main
122
140
 
123
- _main(expose=expose, allow_write=allow_write)
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
+ )
124
145
 
125
146
 
126
147
  if __name__ == "__main__":
@@ -862,7 +862,17 @@ def build_server() -> FastMCP:
862
862
 
863
863
 
864
864
  return server
865
- def main(expose: Optional[str] = None, allow_write: Optional[str] = None) -> 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,11 +888,18 @@ def main(expose: Optional[str] = None, allow_write: Optional[str] = None) -> Non
878
888
  "Reinstall on a newer interpreter: "
879
889
  "uv tool install --python 3.12 --force vmware-debug"
880
890
  )
881
- from vmware_policy.exposure import apply_or_exit
891
+ from vmware_policy.serve import run_server
882
892
  server = build_server()
883
- apply_or_exit(server, skill="debug", expose=expose, allow_write=allow_write)
884
- server.run()
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
+ )
885
899
 
886
900
 
901
+ # Role metadata for network callers (HLD §18).
902
+ import vmware_debug.policy_roles # noqa: F401
903
+
887
904
  if __name__ == "__main__":
888
905
  main()
@@ -0,0 +1,27 @@
1
+ """What vmware-policy needs to apply roles to this skill (HLD §18 D-21/D-22).
2
+
3
+ Policy cannot see which tools escape a role or how a missing target resolves; this
4
+ module declares them. Imported by the MCP server (roles apply only to a network
5
+ MCP server). With a vmware-policy that has no roles module (< 1.24) nothing is
6
+ declared.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ from vmware_policy import skill_name
12
+
13
+ #: Tools that give their holder more than a role. Host-path tools are added by
14
+ #: policy while a file root is set.
15
+ ESCAPES = frozenset()
16
+
17
+
18
+ try:
19
+ from vmware_policy.roles import declare_role_metadata
20
+ except ImportError: # vmware-policy without roles: nothing to declare
21
+ declare_role_metadata = None
22
+
23
+ if declare_role_metadata is not None:
24
+ declare_role_metadata(
25
+ skill_name(__name__),
26
+ escapes=ESCAPES,
27
+ )
File without changes
File without changes