From f78908ad889a8146b5bc43d6a729d1f0db8cc5f7 Mon Sep 17 00:00:00 2001 From: aserrador Date: Mon, 9 Mar 2026 20:46:16 -0500 Subject: [PATCH] feat: improve tool documentation and timezone handling --- src/naliiabot/bot/tools/naliia_tools.py | 152 +++++++++++++++--------- 1 file changed, 93 insertions(+), 59 deletions(-) diff --git a/src/naliiabot/bot/tools/naliia_tools.py b/src/naliiabot/bot/tools/naliia_tools.py index 220d10c..79ae1e3 100644 --- a/src/naliiabot/bot/tools/naliia_tools.py +++ b/src/naliiabot/bot/tools/naliia_tools.py @@ -16,7 +16,6 @@ _MCP_CLIENT = Client(MCP_SERVER_URL) class NaliiaTools: - def __init__(self): self._session_active = False @@ -27,122 +26,157 @@ class NaliiaTools: self.get_tomorrow_date, self.schedule_appointment, self.find_service_centers, - self.find_products_and_services + self.find_products_and_services, ] @tool def get_tomorrow_date() -> str: """ - Consulta la fecha y hora actual del sistema y calcula la fecha del dia de mañana. - Retorna la fecha en formato ISO 8601. No se aceptan fechas en el pasado con respecto a esta fecha. + Consulta la fecha actual del sistema y calcula la fecha del día de mañana. + + Returns: + str: Fecha del día siguiente en formato ISO 8601 (YYYY-MM-DD). + Ejemplo: "2026-03-10" + + Notes: + - No se aceptan fechas en el pasado con respecto a esta fecha. + - Utiliza la zona horaria de Colombia (America/Bogota, UTC-5). """ td = timedelta(days=1) tomorrow = datetime.now().date() + td + tomorrow_date_formated = tomorrow.isoformat() - return tomorrow.isoformat() + logger.info(tomorrow_date_formated) + + return tomorrow_date_formated @tool def get_current_datetime() -> str: """ Consulta la fecha y hora actual del sistema. - Retorna la fecha en formato ISO 8601. - No se aceptan fechas en el pasado con respecto a esta fecha. + + Returns: + str: Fecha y hora actual en formato ISO 8601 con zona horaria. + Ejemplo: "2026-03-09T17:30:00-05:00" + + Notes: + - No se aceptan fechas en el pasado con respecto a esta fecha. + - Utiliza la zona horaria de Colombia (America/Bogota, UTC-5). """ logger.info("Consultando fecha actual.") - return datetime.now(tz=ZoneInfo(TIMEZONE)).isoformat() + today_date_formated = datetime.now(tz=ZoneInfo(TIMEZONE)).isoformat() + + logger.info(today_date_formated) + + return today_date_formated @tool def find_service_centers(): """ - Obtiene los centros de servicios disponibles. + Obtiene la lista de centros de servicio disponibles para agendar citas. - Return: - response=[{ - 'id': 1, - 'name': Campo Amor - }, - { - 'id': 2, - 'name': Belen - } - ] + Returns: + str: JSON array con los centros de servicio disponibles. + Cada elemento contiene: + - id (int): Identificador único del centro de servicio + - name (str): Nombre del centro de servicio + + Example: + '[{"id": 1, "name": "Campo Amor"}, {"id": 2, "name": "Belen"}]' """ + async def call_tool(): async with _MCP_CLIENT: - result = await _MCP_CLIENT.call_tool( - "find_service_centers", None) + result = await _MCP_CLIENT.call_tool("find_service_centers", None) logger.info(result.content[0].text) return result + result = asyncio.run(call_tool()) return result.content[0].text - @tool def find_products_and_services(): """ - Obtiene los productos disponibles. + Obtiene la lista de productos y servicios disponibles para agendar. - Return: - response=[{ - 'id': 1, - 'name': Manicure, - 'price': 20000.00, - 'description': None - }, - { - 'id': 2, - 'name': Corte de Cabello, - 'price': 30000.00, - 'description': "Corte frances, aleman" - } - ] + Returns: + str: JSON array con los productos y servicios disponibles. + Cada elemento contiene: + - id (int): Identificador único del producto/servicio + - name (str): Nombre del producto o servicio + - price (float): Precio del servicio + - description (str | None): Descripción adicional del servicio + + Example: + '[{"id": 1, "name": "Manicure", "price": 20000.0, "description": null}, + {"id": 2, "name": "Corte de Cabello", "price": 30000.0, "description": "Corte frances, aleman"}]' """ + async def call_tool(): async with _MCP_CLIENT: - result = await _MCP_CLIENT.call_tool( - "find_products_and_services", None) + result = await _MCP_CLIENT.call_tool("find_products_and_services", None) logger.info(result.content[0].text) return result + result = asyncio.run(call_tool()) return result.content[0].text - + @tool(args_schema=ScheduleSchema) def schedule_appointment( - schedule_date, schedule_time, - service_center, customer, - professional, description + schedule_date, + schedule_time, + description, + service_center=11, + customer=4, + professional=6, ) -> bool: """ - Permite al Cliente al Agendar una Cita + Permite agendar una cita para un cliente en un centro de servicio específico. + + Args: + schedule_date: Fecha de la cita en formato YYYY-MM-DD. + schedule_time: Hora de la cita en formato HH:MM:SS. + description (str): Descripción o motivo de la cita. + service_center (int, optional): ID del centro de servicio. Por defecto es 11. + customer (int, optional): ID del cliente. Por defecto es 4. + professional (int, optional): ID del profesional. Por defecto es 6. + + Returns: + bool: True si la cita fue agendada exitosamente, False en caso contrario. + + Notes: + - La fecha y hora se almacenan en zona horaria America/Bogota (UTC-5). + - La fecha no puede ser en el pasado. """ logger.info("Agendando cita...") + logger.info([schedule_date, schedule_time]) if not schedule_date and schedule_time: return False - schedule = datetime.combine( - schedule_date, - schedule_time - ).replace( - tzinfo=timezone.utc - ).isoformat() - - example_schedule = { - 'professional': 6, - 'description': description, - 'customer': 4, - 'date': schedule, - 'service_center': 11 - } + schedule = ( + datetime.combine(schedule_date, schedule_time) + .replace(tzinfo=ZoneInfo(TIMEZONE)) + .isoformat() + ) async def call_tool(): async with _MCP_CLIENT: result = await _MCP_CLIENT.call_tool( - "create_schedule", example_schedule) + "create_schedule", + { + "professional": professional, + "description": description, + "customer": customer, + "date": schedule, + "service_center": service_center, + }, + ) + logger.info(result) asyncio.run(call_tool())