vmware-debug 1.8.0__tar.gz → 1.8.2__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 (32) hide show
  1. {vmware_debug-1.8.0 → vmware_debug-1.8.2}/.gitignore +0 -1
  2. {vmware_debug-1.8.0 → vmware_debug-1.8.2}/PKG-INFO +1 -1
  3. {vmware_debug-1.8.0 → vmware_debug-1.8.2}/RELEASE_NOTES.md +61 -0
  4. {vmware_debug-1.8.0 → vmware_debug-1.8.2}/SECURITY.md +1 -1
  5. {vmware_debug-1.8.0 → vmware_debug-1.8.2}/pyproject.toml +3 -3
  6. {vmware_debug-1.8.0 → vmware_debug-1.8.2}/server.json +2 -2
  7. {vmware_debug-1.8.0 → vmware_debug-1.8.2}/skills/vmware-debug/SKILL.md +12 -0
  8. vmware_debug-1.8.2/skills/vmware-debug/references/agent-guardrails.md +171 -0
  9. {vmware_debug-1.8.0 → vmware_debug-1.8.2}/skills/vmware-debug/references/capabilities.md +5 -0
  10. {vmware_debug-1.8.0 → vmware_debug-1.8.2}/skills/vmware-debug/references/setup-guide.md +41 -1
  11. {vmware_debug-1.8.0 → vmware_debug-1.8.2}/tests/eval/regression/test_debug_regressions.py +1 -1
  12. {vmware_debug-1.8.0 → vmware_debug-1.8.2}/tests/eval/regression/test_declared_environment.py +2 -2
  13. {vmware_debug-1.8.0 → vmware_debug-1.8.2}/tests/eval/regression/test_read_only_mode.py +2 -2
  14. {vmware_debug-1.8.0 → vmware_debug-1.8.2}/vmware_debug/__init__.py +1 -1
  15. {vmware_debug-1.8.0 → vmware_debug-1.8.2}/vmware_debug/cli.py +1 -1
  16. vmware_debug-1.8.2/vmware_debug/mcp/__init__.py +2 -0
  17. {vmware_debug-1.8.0 → vmware_debug-1.8.2/vmware_debug}/mcp_server/server.py +12 -4
  18. vmware_debug-1.8.0/vmware_debug/mcp/__init__.py +0 -2
  19. {vmware_debug-1.8.0 → vmware_debug-1.8.2}/README-CN.md +0 -0
  20. {vmware_debug-1.8.0 → vmware_debug-1.8.2}/README.md +0 -0
  21. {vmware_debug-1.8.0 → vmware_debug-1.8.2}/skills/vmware-debug/references/cli-reference.md +0 -0
  22. {vmware_debug-1.8.0 → vmware_debug-1.8.2}/skills/vmware-debug/references/event-envelope.md +0 -0
  23. {vmware_debug-1.8.0 → vmware_debug-1.8.2}/skills/vmware-debug/references/routing.md +0 -0
  24. {vmware_debug-1.8.0 → vmware_debug-1.8.2}/tests/eval/regression/__init__.py +0 -0
  25. {vmware_debug-1.8.0 → vmware_debug-1.8.2}/tests/eval/regression/test_result_envelope.py +0 -0
  26. {vmware_debug-1.8.0 → vmware_debug-1.8.2}/tests/test_timeline.py +0 -0
  27. {vmware_debug-1.8.0 → vmware_debug-1.8.2}/uv.lock +0 -0
  28. {vmware_debug-1.8.0 → vmware_debug-1.8.2}/vmware_debug/envelope.py +0 -0
  29. {vmware_debug-1.8.0 → vmware_debug-1.8.2}/vmware_debug/mcp/tools.py +0 -0
  30. {vmware_debug-1.8.0 → vmware_debug-1.8.2/vmware_debug}/mcp_server/__init__.py +0 -0
  31. {vmware_debug-1.8.0 → vmware_debug-1.8.2}/vmware_debug/ops/__init__.py +0 -0
  32. {vmware_debug-1.8.0 → vmware_debug-1.8.2}/vmware_debug/ops/timeline.py +0 -0
@@ -15,7 +15,6 @@ venv/
15
15
  htmlcov/
16
16
  .coverage
17
17
  config.yaml
18
- .agents/
19
18
  .claude/
20
19
  .trae/
21
20
  skills-lock.json
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vmware-debug
3
- Version: 1.8.0
3
+ Version: 1.8.2
4
4
  Summary: VMware diagnostic brain — read-only incident triage, log/event correlation, and root-cause routing across the VMware skill family
5
5
  Author-email: Wei Zhou <wei-wz.zhou@broadcom.com>
6
6
  License-Expression: MIT
@@ -1,3 +1,64 @@
1
+ ## v1.8.2 (2026-07-20) — the MCP server moves into the package namespace
2
+
3
+ ### Fixed — co-installing two skills broke all but the last one
4
+
5
+ Every skill shipped its MCP server as a **top-level `mcp_server` package**. Python
6
+ has one top-level namespace, so installing any two of them into one environment let
7
+ the second overwrite the first — silently, with no error and no warning.
8
+
9
+ uv tool install vmware-aiops -> 49 tools (correct)
10
+ uv pip install vmware-aiops -> 27 tools (Monitor's read-only server)
11
+
12
+ vmware-aiops depends on vmware-monitor, so this was not an edge case: **every pip
13
+ install hit it**, and the operator got 27 read-only tools where 49 were expected,
14
+ with all 35 write tools missing. Docker images, shared MCP hosts and CI runners that
15
+ install more than one skill were affected the same way.
16
+
17
+ The server now lives at `vmware_<skill>/mcp_server/`, a name only this package can
18
+ claim. Introduced 2026-02-26; it survived 70 releases because every test ran against
19
+ a single package in its own repo, where the local directory shadows site-packages —
20
+ the conflict was invisible by construction.
21
+
22
+ **Migration.** Console scripts are unchanged: `vmware-<skill>` and
23
+ `vmware-<skill>-mcp` work exactly as before, as does `"command": "vmware-<skill>",
24
+ "args": ["mcp"]` in an MCP client config. Only a direct `python -m mcp_server`
25
+ breaks; use `python -m vmware_<skill>.mcp_server`.
26
+
27
+ ### Added — `references/agent-guardrails.md` in every skill
28
+
29
+ The operating rules for local and small models (Llama 3.3 70B, Qwen, Mistral via
30
+ Goose / Ollama / OpenShift AI) existed in two skills. They now ship in all 13, each
31
+ with its own tool counts and failure modes, and are linked from every SKILL.md.
32
+
33
+ ### Changed — Python floor is 3.10 across the family
34
+
35
+ vmware-debug and vmware-log-insight demanded 3.11 on the grounds that FastMCP schema
36
+ reflection was unreliable on 3.10. That was the symptom of PEP 604 `X | None` in the
37
+ server's own signatures, fixed in 1.8.0. 3.10 was verified end to end on 2026-07-19 —
38
+ every tool's schema built, zero failures — so the stricter floor was rejecting a
39
+ version that works.
40
+
41
+ ## v1.8.1 (2026-07-19) — read-only mode reaches the surfaces that teach it
42
+
43
+ v1.8.0 put read-only mode in the code and documented it in the README only.
44
+ Every other layer was empty, and each serves a different reader: SKILL.md is what
45
+ the agent loads, setup-guide is what an operator reads while configuring, `doctor`
46
+ is where they verify it took. The gap had two concrete costs.
47
+
48
+ An agent read SKILL.md, called a write tool the gate had withheld, and got nothing
49
+ back — with no way to learn that the absence was a deliberate lockdown rather than
50
+ a fault. It reads as a broken tool, so the model retries or hunts for a workaround.
51
+
52
+ An operator who set the switch had no way to confirm it. The only signal was a line
53
+ in the MCP server's start-up log.
54
+
55
+ ### Added — the feature is now documented where each reader looks
56
+
57
+ SKILL.md, setup-guide and capabilities now cover read-only mode. Both tools here
58
+ are reads, so nothing is withheld — the gate instead verifies that at start-up
59
+ rather than taking this documentation's word for it. Env vars are the only switch;
60
+ this package has no config file.
61
+
1
62
  ## v1.8.0 (2026-07-18) — read-only mode, working policy defaults, declared environments
2
63
 
3
64
  Family release driven by [VMware-AIops#31](https://github.com/zw008/VMware-AIops/issues/31),
@@ -38,7 +38,7 @@ anything based on event content.
38
38
  ## Static Analysis
39
39
 
40
40
  ```bash
41
- uvx bandit -r vmware_debug/ mcp_server/
41
+ uvx bandit -r vmware_debug/
42
42
  ```
43
43
 
44
44
  Release bar: 0 Medium-or-higher severity findings.
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "vmware-debug"
7
- version = "1.8.0"
7
+ version = "1.8.2"
8
8
  description = "VMware diagnostic brain — read-only incident triage, log/event correlation, and root-cause routing across the VMware skill family"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -26,10 +26,10 @@ dependencies = [
26
26
 
27
27
  [project.scripts]
28
28
  vmware-debug = "vmware_debug.cli:app"
29
- vmware-debug-mcp = "mcp_server.server:main"
29
+ vmware-debug-mcp = "vmware_debug.mcp_server.server:main"
30
30
 
31
31
  [tool.hatch.build.targets.wheel]
32
- packages = ["vmware_debug", "mcp_server"]
32
+ packages = ["vmware_debug"]
33
33
 
34
34
  [dependency-groups]
35
35
  dev = [
@@ -7,12 +7,12 @@
7
7
  "url": "https://github.com/zw008/VMware-Debug",
8
8
  "source": "github"
9
9
  },
10
- "version": "1.8.0",
10
+ "version": "1.8.2",
11
11
  "packages": [
12
12
  {
13
13
  "registryType": "pypi",
14
14
  "identifier": "vmware-debug",
15
- "version": "1.8.0",
15
+ "version": "1.8.2",
16
16
  "transport": {
17
17
  "type": "stdio"
18
18
  }
@@ -113,6 +113,18 @@ a recommended plan.
113
113
  See `references/event-envelope.md`. The agent normalises each source's events into this
114
114
  shape; debug stays source-agnostic and has no dependency on the other packages.
115
115
 
116
+ ## Read-Only Mode
117
+
118
+ Both tools here are reads, so read-only mode withholds nothing — but
119
+ `VMWARE_DEBUG_READ_ONLY=true` or the family-wide `VMWARE_READ_ONLY=true` still applies, and
120
+ the gate verifies at start-up that zero write tools are exposed rather than taking this
121
+ document's word for it. Debug has no config file, so the env vars are the only switch. The
122
+ same family variable withholds write tools across every companion skill, so a whole-estate
123
+ audit posture is one setting — and when you route a fix to vmware-aiops or vmware-pilot and
124
+ the tool is missing from *their* `list_tools()`, that is the lockdown, not a fault. Do not
125
+ retry or hunt for another route: name the blocked operation and say an operator must clear
126
+ the switch and restart that server. Running with local or small models? See [`references/agent-guardrails.md`](references/agent-guardrails.md).
127
+
116
128
  ## CLI Quick Reference
117
129
 
118
130
  ```bash
@@ -0,0 +1,171 @@
1
+ # Operating vmware-debug with a local / small model
2
+
3
+ Claude-class models drive this skill without special instruction. Smaller and
4
+ locally-hosted models — Llama 3.3 70B, Qwen, Mistral, and similar, served
5
+ through Goose, Ollama, or OpenShift AI — need explicit operating rules to call
6
+ tools reliably.
7
+
8
+ This page exists because an operator wrote those rules by hand first. The
9
+ guardrails below are adapted, with thanks, from the working configuration
10
+ [@juanpf-ha](https://github.com/juanpf-ha) developed while running
11
+ vmware-monitor and vmware-aria against a production vSphere estate with Llama
12
+ 3.3 70B FP8 on an on-prem H100
13
+ ([VMware-AIops#31](https://github.com/zw008/VMware-AIops/issues/31)). The
14
+ cross-skill rules are identical across this family; the parts below marked
15
+ vmware-debug are specific to this skill.
16
+
17
+ vmware-debug exposes 2 MCP tools and both are reads. It connects to nothing:
18
+ the calling agent gathers events from the other skills, normalises them, and
19
+ hands them over for correlation. That makes it the safest skill in the family
20
+ to point a small model at — and the one most exposed to the model's reasoning,
21
+ because its output *is* an interpretation.
22
+
23
+ > **Disclaimer**: This is a community-maintained open-source project and is
24
+ > **not affiliated with, endorsed by, or sponsored by VMware, Inc. or Broadcom
25
+ > Inc.** "VMware" and "vSphere" are trademarks of Broadcom.
26
+
27
+ ---
28
+
29
+ ## First: the rules you no longer need to write
30
+
31
+ Several guardrails from the original configuration are now enforced by the
32
+ skill itself. Prompt instructions are advisory — a model can ignore them.
33
+ These are structural, so it cannot.
34
+
35
+ | Guardrail you would otherwise prompt for | Now enforced by |
36
+ |---|---|
37
+ | "Work exclusively in read-only mode and never modify anything" | **The tool surface, and the gate that proves it.** Both tools are reads, so read-only mode withholds nothing here — but setting it makes the guarantee checkable: the gate verifies at start-up that zero write tools are exposed rather than taking this document's word for it. |
38
+ | "Diagnose only — never apply the fix you propose" | **Structural.** This skill has no tool that changes anything, and it holds no connection to vCenter, NSX or anything else. Remediation is routed to vmware-aiops or vmware-pilot by the calling agent. |
39
+ | "Do not fabricate a timeline — build it from the events I gave you" | **`incident_timeline` correlates only its input.** It is source-agnostic and has no way to fetch anything, so the timeline cannot contain an event the agent did not supply. |
40
+ | "Tell me when the symptom is outside what you can recognise" | **`list_symptom_categories`** states the catalogue, and unmatched symptoms come back as `uncategorized` rather than being forced into the nearest signature. |
41
+ | "Use explicit limits for queries that may return large amounts of data" | **The list envelope.** `list_symptom_categories` returns `{items, returned, limit, total, truncated, hint}` with `truncated` always `false` — which is the point: it states that the catalogue is complete instead of leaving you to infer it. |
42
+ | "Log everything you looked at" | **The `@vmware_tool` decorator.** Every call is recorded to `~/.vmware/audit.db`, reads included. |
43
+
44
+ ### Turning read-only mode on
45
+
46
+ One variable covers every skill in the family:
47
+
48
+ ```json
49
+ {
50
+ "mcpServers": {
51
+ "vmware-debug": {
52
+ "command": "vmware-debug",
53
+ "args": ["mcp"],
54
+ "env": { "VMWARE_READ_ONLY": "true" }
55
+ }
56
+ }
57
+ }
58
+ ```
59
+
60
+ Per-skill override:
61
+
62
+ ```bash
63
+ VMWARE_READ_ONLY=true # whole family read-only
64
+ VMWARE_DEBUG_READ_ONLY=false # …except this skill
65
+ ```
66
+
67
+ **This skill has no `config.yaml`**, so the two environment variables are the
68
+ only switch — there is no `read_only:` configuration setting to fall back on.
69
+ Precedence is per-skill env → family env → off. An unparseable value
70
+ (`VMWARE_READ_ONLY=ture`) enables read-only mode rather than silently ignoring
71
+ the typo.
72
+
73
+ Setting it here is worth doing even though nothing is withheld: the same
74
+ variable withholds write tools across every companion skill, so a whole-estate
75
+ diagnostic posture is one setting. That matters especially in this skill's
76
+ workflow — you gather signals read-only, correlate, and then route a fix. When
77
+ the fix tool is missing from vmware-aiops's or vmware-pilot's `list_tools()`,
78
+ that is the lockdown working, not a fault: name the blocked operation and stop,
79
+ rather than retrying or hunting for another route.
80
+
81
+ ---
82
+
83
+ ## The system prompt
84
+
85
+ Everything below still benefits from being stated explicitly. Copy this into
86
+ your agent's instruction block.
87
+
88
+ ```text
89
+ ## Tool use
90
+
91
+ - Gather real events with the companion skills' read tools before calling
92
+ incident_timeline. Never answer from memory or assumption, and never
93
+ hand-write events to represent what you believe happened.
94
+ - Never describe a tool call, and never output a JSON example, instead of
95
+ executing the tool. If you intend to call a tool, call it.
96
+ - If a tool fails, report the actual error text. Do not complete the answer
97
+ with assumptions about what the result would have been.
98
+ - Use explicit limits and time windows when gathering events. Do not request
99
+ unlimited results unless the user asks for them.
100
+
101
+ ## Skill routing
102
+
103
+ - vmware-debug: correlate pre-fetched events into a timeline, detect spikes,
104
+ rank root-cause hypotheses, suggest next checks.
105
+ - Gather the events from: vmware-monitor (alarms, events, host logs),
106
+ vmware-log-insight (centralised logs), vmware-aria (metrics, anomalies),
107
+ vmware-nsx / vmware-nsx-security (network and firewall), vmware-storage.
108
+ - Route the fix to vmware-aiops, or to vmware-pilot when it needs approval
109
+ gating. This skill executes nothing.
110
+
111
+ ## Building the event set
112
+
113
+ - Every event needs ts (ISO-8601, epoch seconds, or millis), and the envelope
114
+ shape {ts, source, severity, entity, text, fields}. An event that cannot be
115
+ normalised is rejected by index — fix that event, do not drop the batch.
116
+ - Carry each event's original source and severity through unchanged. Do not
117
+ re-grade a severity to make a story cohere.
118
+ - Pull from more than one source before concluding. A single source's view of
119
+ an incident is not a correlation.
120
+ - Widen the window before concluding "no spike": spike detection needs at least
121
+ three time bins, so a short window or a large bin_seconds can hide a burst.
122
+
123
+ ## Data fidelity
124
+
125
+ - Never invent events, timestamps, entities, or relationships between them. If
126
+ an event was not in the input, it does not exist for this answer.
127
+ - Preserve the exact severity and source values. Do not translate, normalise,
128
+ or prettify them.
129
+ - Report the timeline in the order the tool returned it.
130
+ - If a requested field was not returned, show it as "not available".
131
+ - When a response is long, report every item it contains.
132
+
133
+ ## Analysis discipline
134
+
135
+ - Separate observed data from interpretation. State which is which. In this
136
+ skill that separation is the deliverable.
137
+ - Report the ranked hypotheses the tool returned, with its ranking. Do not
138
+ promote your own preferred explanation above them, and do not present the
139
+ top hypothesis as a diagnosis.
140
+ - Report next_checks as checks still to be run, not as findings.
141
+ - Do not claim a root cause is confirmed. The tool ranks; it does not conclude.
142
+ - Avoid generic recommendations that are not directly supported by the results.
143
+ ```
144
+
145
+ ---
146
+
147
+ ## Known failure modes on small models
148
+
149
+ Observed with Llama 3.3 70B FP8 (Goose, on-prem H100), and useful as a
150
+ checklist when evaluating any local model against these skills:
151
+
152
+ | Symptom | Mitigation |
153
+ |---|---|
154
+ | Describes a tool call, or emits a JSON example, instead of executing it | The "never describe a tool call" rule above. This skill is unusually exposed to it: its input *is* JSON, so a model that has just been shown an event envelope will sometimes emit a fabricated one instead of gathering real events. Check that the events came from tool calls. |
155
+ | Long tool responses: omits items, or reports "no data returned" when data was present | Ask for explicit limits and narrow windows when gathering. `list_symptom_categories` states `truncated: false`, so a "no categories" claim is checkable against `returned`. |
156
+ | Adds generic recommendations unsupported by results | The "analysis discipline" rules. Root-cause output attracts invented advice more than any other shape of result in this family. |
157
+ | Drops requested fields or reorders results | State the required fields and ordering in the request itself. A reordered timeline is a different incident. |
158
+ | Multi-tool workflows take 30–50s end to end | Unavoidable in part — this skill's whole premise is a fan-out gather. Narrow each source's window before widening, and prefer the companion skills' aggregate tools when gathering. |
159
+ | Presents the top-ranked hypothesis as the confirmed cause | The "the tool ranks, it does not conclude" rule. |
160
+ | Re-grades an event's severity so the narrative fits | The "carry severity through unchanged" rule. |
161
+ | Concludes from one source because the others were slow to query | The "pull from more than one source" rule. |
162
+ | Reports "no spike" from a window too short to have a baseline | Three bins minimum. Widen the window or shrink `bin_seconds` before concluding. |
163
+ | Offers to apply the fix it proposed | It cannot. Route to vmware-aiops or vmware-pilot. |
164
+
165
+ ## Reporting results
166
+
167
+ Local-model compatibility is an explicit design constraint for this family, and
168
+ the evidence base is small. If you evaluate a model against this skill —
169
+ Qwen, Mistral, Granite, or anything else — a report of what worked and what did
170
+ not is genuinely useful:
171
+ [github.com/zw008/VMware-Debug/issues](https://github.com/zw008/VMware-Debug/issues).
@@ -7,6 +7,11 @@ Read-only, offline incident correlation. No network, no credentials, no writes.
7
7
  | `incident_timeline` | `{event_count, window, spikes:[{start,end,count,zscore}], hypotheses:[{category, score, summary, evidence_count, first_seen, last_seen, sample_text, suggested_check}], next_checks:[...]}` | 300–2000 (scales with hypotheses) |
8
8
  | `list_symptom_categories` | `{items: [{category, example_keywords, suggested_check}], returned, limit, total, truncated, hint}` | ~400 |
9
9
 
10
+ > Read-only mode (`VMWARE_DEBUG_READ_ONLY=true` or the family-wide `VMWARE_READ_ONLY=true`;
11
+ > debug has no config file) removes nothing from this table — both tools are `[READ]`, and
12
+ > the gate proves that at start-up rather than trusting the marker. Classification comes
13
+ > from the `[READ]`/`[WRITE]` docstring marker — see README.
14
+
10
15
  `list_symptom_categories` returns the family list envelope — read the rows from
11
16
  `items`. It has no `limit` parameter, which is exactly why the envelope matters:
12
17
  `truncated: false` states that this is every category there is, rather than
@@ -26,6 +26,46 @@ 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
+ ## Read-Only Mode
30
+
31
+ Off by default. Both of debug's tools are reads, so turning it on withholds nothing here —
32
+ the value is that the gate *verifies* at start-up that no write tool is exposed, instead of
33
+ trusting this document, and that the same family variable locks down every other installed
34
+ skill in one setting.
35
+
36
+ **Debug has no config file, so the environment is the only switch.** There is no
37
+ `read_only:` setting to write. Precedence:
38
+
39
+ | Priority | Signal | Scope |
40
+ |---|---|---|
41
+ | 1 | `VMWARE_DEBUG_READ_ONLY` | This skill only |
42
+ | 2 | `VMWARE_READ_ONLY` | Every installed VMware skill |
43
+ | 3 | (nothing set) | Off |
44
+
45
+ ```json
46
+ {
47
+ "mcpServers": {
48
+ "vmware-debug": {
49
+ "command": "vmware-debug",
50
+ "args": ["mcp"],
51
+ "env": { "VMWARE_READ_ONLY": "true" }
52
+ }
53
+ }
54
+ }
55
+ ```
56
+
57
+ **Fail-closed.** If the mode is requested but cannot be *proven*, the server refuses to
58
+ start with `ReadOnlyGateError`: the FastMCP tool registry cannot be enumerated (usually an
59
+ incompatible `mcp` version), or a removal did not take effect. One case does *not* abort —
60
+ an unparseable value (`VMWARE_DEBUG_READ_ONLY=ture`) resolves to **on** with a warning
61
+ naming the accepted values, so a typo locks the deployment down rather than leaving it
62
+ open.
63
+
64
+ **Verifying.** Debug ships no `doctor` command; the start-up log is the record — the server
65
+ logs every withheld tool when the mode engages, and logs nothing to withhold here. Skills
66
+ that do ship one (e.g. `vmware-log-insight doctor`) report their resolved state and where it
67
+ came from.
68
+
29
69
  ## Security
30
70
 
31
71
  > **Disclaimer**: Community-maintained open-source project, **not affiliated with,
@@ -46,5 +86,5 @@ routes fixes to (vmware-aiops, vmware-pilot).
46
86
  warning — the next major release will refuse them. debug has no config and
47
87
  no connection to declare one about, so it reports a constant `local`. Since
48
88
  it ships no operation above read risk, nothing here is gated either way.
49
- 7. **Static analysis** — `uvx bandit -r vmware_debug/ mcp_server/` (release bar:
89
+ 7. **Static analysis** — `uvx bandit -r vmware_debug/` (release bar:
50
90
  0 Medium+).
@@ -9,7 +9,7 @@ import asyncio
9
9
  import json
10
10
  from pathlib import Path
11
11
 
12
- from mcp_server.server import build_server
12
+ from vmware_debug.mcp_server.server import build_server
13
13
  from vmware_debug.envelope import Event
14
14
  from vmware_debug.ops.timeline import category_routing, incident_timeline, known_categories
15
15
 
@@ -26,7 +26,7 @@ import importlib
26
26
  import pytest
27
27
 
28
28
  import vmware_policy.environment as env_mod
29
- from mcp_server import server
29
+ from vmware_debug.mcp_server import server
30
30
  from vmware_policy.environment import resolve_environment, set_environment_resolver
31
31
 
32
32
 
@@ -90,7 +90,7 @@ class TestConstantResolverIsRegistered:
90
90
  importlib.reload(server)
91
91
 
92
92
  assert env_mod._resolver is not None, (
93
- "mcp_server.server must call set_environment_resolver() at import."
93
+ "vmware_debug.mcp_server.server must call set_environment_resolver() at import."
94
94
  )
95
95
  assert env_mod._resolver is server._environment_for
96
96
 
@@ -24,7 +24,7 @@ import asyncio
24
24
  import pytest
25
25
  from vmware_policy import apply_read_only_gate
26
26
 
27
- from mcp_server import server as server_module
27
+ from vmware_debug.mcp_server import server as server_module
28
28
 
29
29
  EXPECTED_TOOLS = {"incident_timeline", "list_symptom_categories"}
30
30
 
@@ -144,7 +144,7 @@ def test_build_server_actually_applies_the_gate(monkeypatch):
144
144
  trivially true of a gate that never runs — and a grep for the symbol found
145
145
  the unused import. Only observing the factory invoke it closes that gap.
146
146
  """
147
- import mcp_server.server as server
147
+ import vmware_debug.mcp_server.server as server
148
148
 
149
149
  calls = []
150
150
  real = server.apply_read_only_gate
@@ -5,4 +5,4 @@ into a unified timeline, detect spikes, rank root-cause hypotheses, and route
5
5
  remediation to vmware-aiops / vmware-pilot. Never writes; never executes fixes.
6
6
  """
7
7
 
8
- __version__ = "1.8.0"
8
+ __version__ = "1.8.2"
@@ -76,7 +76,7 @@ def triage(
76
76
  @app.command()
77
77
  def mcp() -> None:
78
78
  """Start the stdio MCP server (no network access; proxy-safe)."""
79
- from mcp_server.server import main as _main
79
+ from vmware_debug.mcp_server.server import main as _main
80
80
 
81
81
  _main()
82
82
 
@@ -0,0 +1,2 @@
1
+ """MCP tool implementations for vmware-debug (kept here so audit logs see
2
+ skill=debug). The stdio server in vmware_debug/mcp_server/ wires these into FastMCP."""
@@ -137,11 +137,19 @@ def build_server() -> FastMCP:
137
137
 
138
138
  def main() -> None:
139
139
  """Entry point for `vmware-debug-mcp` (stdio transport)."""
140
- if sys.version_info < (3, 11):
140
+ # Floor is 3.10, matching `requires-python` and the other eleven skills.
141
+ # This guard used to demand 3.11 on the grounds that FastMCP schema
142
+ # reflection was unreliable on 3.10 (踩坑 #33). That was the symptom; the
143
+ # cause was PEP 604 `X | None` in the server's own signatures, fixed by
144
+ # converting them to `Optional[X]`. 3.10 was then verified end to end on
145
+ # 2026-07-19 — every tool's schema built, zero failures, pydantic 2.13.4 —
146
+ # so the stricter floor was rejecting a version that works.
147
+ if sys.version_info < (3, 10):
141
148
  sys.exit(
142
- "vmware-debug-mcp requires Python >= 3.11 (FastMCP schema reflection "
143
- "is unreliable on 3.10). Reinstall under 3.11+: "
144
- "uv tool install --python 3.11 vmware-debug"
149
+ "vmware-debug-mcp requires Python >= 3.10 "
150
+ f"(got {sys.version_info.major}.{sys.version_info.minor}). "
151
+ "Reinstall on a newer interpreter: "
152
+ "uv tool install --python 3.12 --force vmware-debug"
145
153
  )
146
154
  build_server().run()
147
155
 
@@ -1,2 +0,0 @@
1
- """MCP tool implementations for vmware-debug (kept here so audit logs see
2
- skill=debug). The stdio server in mcp_server/ wires these into FastMCP."""
File without changes
File without changes
File without changes