@@ -568,7 +568,7 @@ async def check_all_systems_for_updates(ctx: Context) -> List[Dict[str, Any]]:
568568 return systems_with_updates
569569
570570@write_tool ()
571- async def schedule_apply_pending_updates_to_system (system_identifier : Union [str , int ], ctx : Context , confirm : bool = False ) -> str :
571+ async def schedule_apply_pending_updates_to_system (system_identifier : Union [str , int ], ctx : Context , confirm : Union [ bool , str ] = False ) -> str :
572572
573573 """
574574 Checks for pending updates on a system, schedules all of them to be applied,
@@ -580,7 +580,11 @@ async def schedule_apply_pending_updates_to_system(system_identifier: Union[str,
580580
581581 Args:
582582 system_identifier: The unique identifier of the system. It can be the system name (e.g. "buildhost") or the system ID (e.g. 1000010000).
583- confirm: False by default. Only set confirm to True if the user has explicetely confirmed. Ask the user for confirmation.
583+ confirm: User confirmation is required to execute this action. This parameter
584+ is `False` by default. To obtain the confirmation message that must
585+ be presented to the user, the model must first call the tool with
586+ `confirm=False`. If the user agrees, the model should call the tool
587+ a second time with `confirm=True`.
584588
585589 Returns:
586590 str: The action url if updates were successfully scheduled.
@@ -590,7 +594,10 @@ async def schedule_apply_pending_updates_to_system(system_identifier: Union[str,
590594 logger .info (log_string )
591595 await ctx .info (log_string )
592596
593- if not confirm :
597+ # Coerce string "false" to boolean False for models that send strings
598+ is_confirmed = str (confirm ).lower () == 'true'
599+
600+ if not is_confirmed :
594601 return f"CONFIRMATION REQUIRED: This will apply pending updates to the system { system_identifier } . Do you confirm?"
595602
596603 # 1. Use check_system_updates to get relevant errata
@@ -642,15 +649,19 @@ async def schedule_apply_pending_updates_to_system(system_identifier: Union[str,
642649 return ""
643650
644651@write_tool ()
645- async def schedule_apply_specific_update (system_identifier : Union [str , int ], errata_id : int , ctx : Context , confirm : bool = False ) -> str :
652+ async def schedule_apply_specific_update (system_identifier : Union [str , int ], errata_id : Union [ str , int ] , ctx : Context , confirm : Union [ bool , str ] = False ) -> str :
646653
647654 """
648655 Schedules a specific update (erratum) to be applied to a system.
649656
650657 Args:
651658 system_identifier: The unique identifier of the system. It can be the system name (e.g. "buildhost") or the system ID (e.g. 1000010000).
652- errata_id: The unique identifier of the erratum (also referred to as update ID) to be applied.
653- confirm: False by default. Only set confirm to True if the user has explicetely confirmed. Ask the user for confirmation.
659+ errata_id: The unique identifier of the erratum (also referred to as update ID) to be applied. It must be an integer.
660+ confirm: User confirmation is required to execute this action. This parameter
661+ is `False` by default. To obtain the confirmation message that must
662+ be presented to the user, the model must first call the tool with
663+ `confirm=False`. If the user agrees, the model should call the tool
664+ a second time with `confirm=True`.
654665
655666 Returns:
656667 str: The action URL if the update was successfully scheduled.
@@ -659,41 +670,52 @@ async def schedule_apply_specific_update(system_identifier: Union[str, int], err
659670 log_string = f"Attempting to apply specific update (errata ID: { errata_id } ) to system ID: { system_identifier } "
660671 logger .info (log_string )
661672 await ctx .info (log_string )
673+
674+ # Coerce string "false" to boolean False for models that send strings
675+ is_confirmed = str (confirm ).lower () == 'true'
676+
677+ try :
678+ # Coerce errata_id to an integer, as some models might pass it as a string.
679+ errata_id_int = int (errata_id )
680+ except (ValueError , TypeError ):
681+ return f"Invalid errata ID '{ errata_id } '. The ID must be an integer."
682+
683+
662684 system_id = await _resolve_system_id (system_identifier )
663685 if not system_id :
664686 return "" # Helper function already logged the reason for failure.
665687
666688 print (f"Attempting to apply specific update (errata ID: { errata_id } ) to system: { system_identifier } " )
667689
668- if not confirm :
690+ if not is_confirmed :
669691 return f"CONFIRMATION REQUIRED: This will apply specific update (errata ID: { errata_id } ) to the system { system_identifier } . Do you confirm?"
670692
671693 async with httpx .AsyncClient (verify = UYUNI_MCP_SSL_VERIFY ) as client :
672694 # The API expects a list of errata IDs, even if it's just one.
673- payload = {"sid" : int (system_id ), "errataIds" : [errata_id ]}
695+ payload = {"sid" : int (system_id ), "errataIds" : [errata_id_int ]}
674696 api_result = await _call_uyuni_api (
675697 client = client ,
676698 method = "POST" ,
677699 api_path = "/rhn/manager/api/system/scheduleApplyErrata" ,
678700 json_body = payload ,
679- error_context = f"scheduling specific update (errata ID: { errata_id } ) for system { system_identifier } " ,
701+ error_context = f"scheduling specific update (errata ID: { errata_id_int } ) for system { system_identifier } " ,
680702 default_on_error = None # Helper returns None on error
681703 )
682704
683705 if isinstance (api_result , list ) and api_result and isinstance (api_result [0 ], int ):
684706 action_id = api_result [0 ]
685- success_message = f"Update (errata ID: { errata_id } ) successfully scheduled for system { system_identifier } . Action URL: { UYUNI_SERVER } /rhn/schedule/ActionDetails.do?aid={ action_id } "
707+ success_message = f"Update (errata ID: { errata_id_int } ) successfully scheduled for system { system_identifier } . Action URL: { UYUNI_SERVER } /rhn/schedule/ActionDetails.do?aid={ action_id } "
686708 print (success_message )
687709 return success_message
688710 # Some schedule APIs might return int directly in result (though scheduleApplyErrata usually returns a list)
689711 elif isinstance (api_result , int ): # Defensive check
690712 action_id = api_result
691- success_message = f"Update (errata ID: { errata_id } ) successfully scheduled. Action URL: { UYUNI_SERVER } /rhn/schedule/ActionDetails.do?aid={ action_id } "
713+ success_message = f"Update (errata ID: { errata_id_int } ) successfully scheduled. Action URL: { UYUNI_SERVER } /rhn/schedule/ActionDetails.do?aid={ action_id } "
692714 print (success_message )
693715 return success_message
694716 else :
695717 if api_result is not None : # Log if not None but also not expected format
696- print (f"Failed to schedule specific update (errata ID: { errata_id } ) for system { system_identifier } or unexpected API result format. Result: { api_result } " )
718+ print (f"Failed to schedule specific update (errata ID: { errata_id_int } ) for system { system_identifier } or unexpected API result format. Result: { api_result } " )
697719 return ""
698720
699721@write_tool ()
@@ -705,7 +727,7 @@ async def add_system(
705727 ssh_user : str = "root" ,
706728 proxy_id : int = None ,
707729 salt_ssh : bool = False ,
708- confirm : bool = False ,
730+ confirm : Union [ bool , str ] = False ,
709731) -> str :
710732 """
711733 Adds a new system to be managed by Uyuni.
@@ -721,10 +743,11 @@ async def add_system(
721743 ssh_user: The user to connect with via SSH (default: 'root').
722744 proxy_id: The system ID of a Uyuni proxy to use (optional).
723745 salt_ssh: Manage the system with Salt SSH (default: False).
724- confirm: User confirmation is required to execute this action. Set to False
725- by default. If False, the tool returns a confirmation message. The
726- model must present this message to the user and, if they agree, call
727- the tool again with this parameter set to True.
746+ confirm: User confirmation is required to execute this action. This parameter
747+ is `False` by default. To obtain the confirmation message that must
748+ be presented to the user, the model must first call the tool with
749+ `confirm=False`. If the user agrees, the model should call the tool
750+ a second time with `confirm=True`.
728751
729752 Returns:
730753 A confirmation message if 'confirm' is False.
@@ -735,6 +758,10 @@ async def add_system(
735758 log_string = f"Attempting to add system ID: { host } "
736759 logger .info (log_string )
737760 await ctx .info (log_string )
761+
762+ # Coerce string "false" to boolean False for models that send strings
763+ is_confirmed = str (confirm ).lower () == 'true'
764+
738765 if ctx .session .check_client_capability (types .ClientCapabilities (elicitation = types .ElicitationCapability ())):
739766 # Check for activation key
740767 if not activation_key :
@@ -761,7 +788,7 @@ async def add_system(
761788 await ctx .info (message )
762789 return message
763790
764- if not confirm :
791+ if not is_confirmed :
765792 return f"CONFIRMATION REQUIRED: This will add system { host } with activation key { activation_key } to Uyuni. Do you confirm?"
766793
767794 ssh_priv_key_raw = os .environ .get ('UYUNI_SSH_PRIV_KEY' )
@@ -817,7 +844,7 @@ async def add_system(
817844
818845
819846@write_tool ()
820- async def remove_system (system_identifier : Union [str , int ], ctx : Context , cleanup : bool = True , confirm : bool = False ) -> str :
847+ async def remove_system (system_identifier : Union [str , int ], ctx : Context , cleanup : bool = True , confirm : Union [ bool , str ] = False ) -> str :
821848 """
822849 Removes/deletes a system from being managed by Uyuni.
823850
@@ -827,8 +854,11 @@ async def remove_system(system_identifier: Union[str, int], ctx: Context, cleanu
827854 system_identifier: The unique identifier of the system to remove. It can be the system name (e.g. "buildhost") or the system ID (e.g. 1000010000).
828855 cleanup: If True (default), Uyuni will attempt to run cleanup scripts on the client before deletion.
829856 If False, the system is deleted from Uyuni without attempting client-side cleanup.
830- confirm: User confirmation is required. If False, the tool returns a confirmation prompt. The
831- model must ask the user and call the tool again with confirm=True if they agree.
857+ confirm: User confirmation is required to execute this action. This parameter
858+ is `False` by default. To obtain the confirmation message that must
859+ be presented to the user, the model must first call the tool with
860+ `confirm=False`. If the user agrees, the model should call the tool
861+ a second time with `confirm=True`.
832862
833863 Returns:
834864 A confirmation message if 'confirm' is False.
@@ -837,6 +867,10 @@ async def remove_system(system_identifier: Union[str, int], ctx: Context, cleanu
837867 log_string = f"Attempting to remove system with id { system_identifier } "
838868 logger .info (log_string )
839869 await ctx .info (log_string )
870+
871+ # Coerce string "false" to boolean False for models that send strings
872+ is_confirmed = str (confirm ).lower () == 'true'
873+
840874 system_id = await _resolve_system_id (system_identifier )
841875 if not system_id :
842876 return "" # Helper function already logged the reason for failure.
@@ -848,7 +882,7 @@ async def remove_system(system_identifier: Union[str, int], ctx: Context, cleanu
848882 logger .warning (message )
849883 return message
850884
851- if not confirm :
885+ if not is_confirmed :
852886 return (f"CONFIRMATION REQUIRED: This will permanently remove system { system_id } from Uyuni. "
853887 f"Client-side cleanup is currently { 'ENABLED' if cleanup else 'DISABLED' } . Do you confirm?" )
854888
@@ -974,7 +1008,7 @@ async def get_systems_needing_security_update_for_cve(cve_identifier: str, ctx:
9741008 return list (affected_systems_map .values ())
9751009
9761010@mcp .tool ()
977- async def get_systems_needing_reboot (ctx : Context ) -> List [Dict [str , Any ]]:
1011+ async def get_systems_needing_reboot (ctx : Context ) -> List [Dict [str , Any ]]: # No change needed here
9781012 """
9791013 Fetches a list of systems from the Uyuni server that require a reboot.
9801014
@@ -1024,14 +1058,18 @@ async def get_systems_needing_reboot(ctx: Context) -> List[Dict[str, Any]]:
10241058 return systems_needing_reboot_list
10251059
10261060@write_tool ()
1027- async def schedule_system_reboot (system_identifier : Union [str , int ], ctx :Context , confirm : bool = False ) -> str :
1061+ async def schedule_system_reboot (system_identifier : Union [str , int ], ctx :Context , confirm : Union [ bool , str ] = False ) -> str :
10281062
10291063 """
10301064 Schedules an immediate reboot for a specific system on the Uyuni server.
10311065
10321066 Args:
10331067 system_identifier: The unique identifier of the system. It can be the system name (e.g. "buildhost") or the system ID (e.g. 1000010000).
1034- confirm: False by default. Only set confirm to True if the user has explicetely confirmed. Ask the user for confirmation.
1068+ confirm: User confirmation is required to execute this action. This parameter
1069+ is `False` by default. To obtain the confirmation message that must
1070+ be presented to the user, the model must first call the tool with
1071+ `confirm=False`. If the user agrees, the model should call the tool
1072+ a second time with `confirm=True`.
10351073
10361074 The reboot is scheduled to occur as soon as possible (effectively "now").
10371075 Returns:
@@ -1042,11 +1080,15 @@ async def schedule_system_reboot(system_identifier: Union[str, int], ctx:Context
10421080 log_string = f"Schedule system reboot for system { system_identifier } "
10431081 logger .info (log_string )
10441082 await ctx .info (log_string )
1083+
1084+ # Coerce string "false" to boolean False for models that send strings
1085+ is_confirmed = str (confirm ).lower () == 'true'
1086+
10451087 system_id = await _resolve_system_id (system_identifier )
10461088 if not system_id :
10471089 return "" # Helper function already logged the reason for failure.
10481090
1049- if not confirm :
1091+ if not is_confirmed :
10501092 return f"CONFIRMATION REQUIRED: This will reboot system { system_identifier } . Do you confirm?"
10511093
10521094 schedule_reboot_path = '/rhn/manager/api/system/scheduleReboot'
@@ -1126,7 +1168,7 @@ async def list_all_scheduled_actions(ctx: Context) -> List[Dict[str, Any]]:
11261168 return processed_actions_list
11271169
11281170@write_tool ()
1129- async def cancel_action (action_id : int , ctx : Context , confirm : bool = False ) -> str :
1171+ async def cancel_action (action_id : int , ctx : Context , confirm : Union [ bool , str ] = False ) -> str :
11301172 """
11311173 Cancels a specified action on the Uyuni server.
11321174
@@ -1135,7 +1177,11 @@ async def cancel_action(action_id: int, ctx: Context, confirm: bool = False) ->
11351177
11361178 Args:
11371179 action_id: The integer ID of the action to be canceled.
1138- confirm: False by default. Only set confirm to True if the user has explicetely confirmed. Ask the user for confirmation.
1180+ confirm: User confirmation is required to execute this action. This parameter
1181+ is `False` by default. To obtain the confirmation message that must
1182+ be presented to the user, the model must first call the tool with
1183+ `confirm=False`. If the user agrees, the model should call the tool
1184+ a second time with `confirm=True`.
11391185
11401186 Returns:
11411187 str: A success message if the action was canceled,
@@ -1148,12 +1194,15 @@ async def cancel_action(action_id: int, ctx: Context, confirm: bool = False) ->
11481194 logger .info (log_string )
11491195 await ctx .info (log_string )
11501196
1197+ # Coerce string "false" to boolean False for models that send strings
1198+ is_confirmed = str (confirm ).lower () == 'true'
1199+
11511200 cancel_actions_path = '/rhn/manager/api/schedule/cancelActions'
11521201
11531202 if not isinstance (action_id , int ): # Basic type check, though FastMCP might handle this
11541203 return "Invalid action ID provided. Must be an integer."
11551204
1156- if not confirm :
1205+ if not is_confirmed :
11571206 return f"CONFIRMATION REQUIRED: This will schedule action { action_id } to be canceled. Do you confirm?"
11581207
11591208 async with httpx .AsyncClient (verify = UYUNI_MCP_SSL_VERIFY ) as client :
0 commit comments