feat(catalog): cover Windows guest-mutating tools in the starter list #5

Merged
claude merged 1 commits from feat/windows-mutating-catalog into main 2026-09-21 15:06:41 -04:00
3 changed files with 44 additions and 1 deletions
+1 -1
View File
@@ -9,7 +9,7 @@ If the loop works, these tools are the delta to add to official ZVM MCP (`ZVM.MC
1. `zerto_find_protection` — VM name, hostname, or vmIdentifier to exactly one VM and every VPG. Zero or two-plus VMs: stop. 1. `zerto_find_protection` — VM name, hostname, or vmIdentifier to exactly one VM and every VPG. Zero or two-plus VMs: stop.
2. `zerto_create_tagged_checkpoint` / `zerto_guard_before_mutate` — same tag on every protecting VPG, wait until listed. The name records which agent and what it is doing: `ai:<agent> | <action> | vm=<vm> | change=<id> | <utc>`. 2. `zerto_create_tagged_checkpoint` / `zerto_guard_before_mutate` — same tag on every protecting VPG, wait until listed. The name records which agent and what it is doing: `ai:<agent> | <action> | vm=<vm> | change=<id> | <utc>`.
3. `zerto_recover_file` — FLR after a human sets `confirmed=true`. Linux and Windows guest paths. Locally replicated VPGs only: FLR runs at the VPG's recovery site. Reports its own unmount; `zerto_list_flr_sessions` / `zerto_end_flr_session` find and reap a mount orphaned by a crashed recovery. 3. `zerto_recover_file` — FLR after a human sets `confirmed=true`. Linux and Windows guest paths. Locally replicated VPGs only: FLR runs at the VPG's recovery site. Reports its own unmount; `zerto_list_flr_sessions` / `zerto_end_flr_session` find and reap a mount orphaned by a crashed recovery.
4. Mutating catalog — opt-in list of MCP tools that must be guarded. Unlisted tools pass through. Users add entries. 4. Mutating catalog — opt-in list of MCP tools that must be guarded. Unlisted tools pass through. Users add entries. The starter list covers Linux (`ssh`, `ansible`) and Windows (`winrm`, `powershell`, `smb`), and is illustrative, not exhaustive.
Official ZVM MCP already has inventory and failover test. It does not insert tagged checkpoints or run FLR. Official ZVM MCP already has inventory and failover test. It does not insert tagged checkpoints or run FLR.
+24
View File
@@ -17,6 +17,30 @@
"tool": "run_playbook", "tool": "run_playbook",
"vm_arg": "limit", "vm_arg": "limit",
"notes": "Playbook target host/group. Resolve to a single VM before guard." "notes": "Playbook target host/group. Resolve to a single VM before guard."
},
{
"server": "winrm",
"tool": "run_command",
"vm_arg": "host",
"notes": "Windows remote shell over WinRM. vm_arg is the hostname."
},
{
"server": "winrm",
"tool": "run_ps",
"vm_arg": "host",
"notes": "PowerShell over WinRM. Same blast radius as run_command."
},
{
"server": "powershell",
"tool": "invoke_command",
"vm_arg": "computer_name",
"notes": "Invoke-Command against a remote Windows guest."
},
{
"server": "smb",
"tool": "write_file",
"vm_arg": "host",
"notes": "Writes a file into a Windows share. Changes the guest without a shell."
} }
] ]
} }
+19
View File
@@ -31,3 +31,22 @@ def test_entry_requires_fields():
raise AssertionError("expected ValueError") raise AssertionError("expected ValueError")
except ValueError: except ValueError:
pass pass
def test_example_config_covers_windows_and_linux():
"""The starter catalog must not be Linux-only.
The catalog is opt-in: an unlisted tool passes through unguarded. A
Windows-only shop taking the shipped defaults would therefore mutate
protected guests with no checkpoint at all.
"""
example = Path(__file__).resolve().parent.parent / "config.example.json"
data = json.loads(example.read_text(encoding="utf-8"))
cat = MutatingCatalog.from_config(data)
assert cat.get("ssh", "exec") is not None
assert cat.get("winrm", "run_command") is not None
assert cat.get("winrm", "run_ps") is not None
assert cat.get("powershell", "invoke_command") is not None
# every entry must name the arg holding the VM, or the guard cannot resolve one
for entry in cat.list():
assert entry.vm_arg, f"{entry.server}/{entry.tool} has no vm_arg"