From b9c411fdf94be21e82487f241d36be68e9dd049f Mon Sep 17 00:00:00 2001 From: Ryan Malloy Date: Fri, 26 Dec 2025 06:23:35 -0700 Subject: [PATCH] add idempotentHint to safe-to-retry vCenter tools Mark tools that handle already-in-target-state gracefully: - storage_vmotion: returns "no_migration_needed" if already on target - convert_to_template: returns "already_template" if already converted - convert_to_vm: returns "already_vm" if already a VM This signals to LLM clients that these operations are safe to retry. --- src/esxi_mcp_server/mixins/vcenter_ops.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/esxi_mcp_server/mixins/vcenter_ops.py b/src/esxi_mcp_server/mixins/vcenter_ops.py index a55b72d..11fb601 100644 --- a/src/esxi_mcp_server/mixins/vcenter_ops.py +++ b/src/esxi_mcp_server/mixins/vcenter_ops.py @@ -23,8 +23,8 @@ class VCenterOpsMixin(MCPMixin): @mcp_tool( name="storage_vmotion", - description="Move a VM's disks to a different datastore (Storage vMotion)", - annotations=ToolAnnotations(destructiveHint=True), + description="Move a VM's disks to a different datastore (Storage vMotion). Idempotent if already on target.", + annotations=ToolAnnotations(destructiveHint=True, idempotentHint=True), ) def storage_vmotion( self, @@ -161,8 +161,8 @@ class VCenterOpsMixin(MCPMixin): @mcp_tool( name="convert_to_template", - description="Convert a VM to a template", - annotations=ToolAnnotations(destructiveHint=True), + description="Convert a VM to a template (idempotent - safe to call on existing template)", + annotations=ToolAnnotations(destructiveHint=True, idempotentHint=True), ) def convert_to_template(self, vm_name: str) -> dict[str, Any]: """Convert a VM to a template. @@ -200,8 +200,8 @@ class VCenterOpsMixin(MCPMixin): @mcp_tool( name="convert_to_vm", - description="Convert a template back to a VM", - annotations=ToolAnnotations(destructiveHint=True), + description="Convert a template back to a VM (idempotent - safe to call on existing VM)", + annotations=ToolAnnotations(destructiveHint=True, idempotentHint=True), ) def convert_to_vm( self,