MCP Agent — Asistente para consultas en Excel
Resumen
Este proyecto proporciona un asistente conversacional (interfaz Gradio) que permite hacer consultas en lenguaje natural sobre los datos de un archivo Excel. Usa la API de OpenAI (client openai) y un conjunto de "herramientas" (funciones) que exponen operaciones sobre un DataFrame (leer esquema, filas, estadísticas, valores de columna, etc.).
Principales componentes
main.py— punto de entrada que arranca la interfaz Gradio y crea la instancia deLlmServiceconExcelTools.services/llm_service.py— claseLlmServiceque orquesta las llamadas al cliente OpenAI y ejecuta funciones sobre el Excel.utils/excel_tools.py— claseExcelToolsque carga el archivo Excel en unpandas.DataFramey expone métodos serializables a JSON:
- get_schema() - get_all_data() - get_head(n) - get_statistics() - get_column_values(column)
mcp_server/mcp_tools.py— descripción (spec) de las funciones accesibles por la LLM (parámetros y descripciones).utils/config.py— construcción de la ruta absoluta al archivo Excel usado por defecto.data/— carpeta que contiene el Excel de prueba:cesancias_causadas.xlsx.requirements.txt— dependencias del proyecto.
Estructura del proyecto
agent_app/
├─ .env # variables de entorno (no versionar)
├─ README.md # este fichero
├─ requirements.txt # dependencias
├─ main.py # punto de entrada y UI Gradio
├─ data/
│ └─ cesancias_causadas.xlsx
├─ mcp_server/
│ ├─ __init__.py
│ └─ mcp_tools.py # especificación de herramientas (function-calling)
├─ services/
│ └─ llm_service.py # lógica de orquestación con OpenAI
└─ utils/
├─ __init__.py
├─ config.py # construcción de rutas y configuración local
├─ excel_tools.py # lectura y operaciones sobre el Excel
└─ execute_functions.py # adaptadores/ejecutores auxiliaresQué hace
- Carga un archivo Excel desde
data/cesancias_causadas.xlsxenExcelTools. - Expone una interfaz web (Gradio) donde el usuario escribe consultas en lenguaje natural.
LlmServiceenvía la consulta a OpenAI usando el mecanismo de "function-calling" (herramientas definidas enmcp_tools).- Si la LLM solicita ejecutar una función (por ejemplo
get_head), el servicio ejecuta el método correspondiente deExcelTools, serializa el resultado a JSON y lo pasa de vuelta a la LLM para generar la respuesta final.
Requisitos
- Python 3.10+ (preferible 3.11).
- Dependencias listadas en
requirements.txt. Principalmente:
- pandas - openai - gradio - python-dotenv - openpyxl
Instalación (sugerida)
- Clona o descarga el repositorio.
- Crea y activa un entorno virtual (ejemplo con venv):
python -m venv .venv
.\.venv\Scripts\Activate.ps1- Instala dependencias:
pip install -r requirements.txtConfiguración
- Crea un archivo
.enven la raíz deagent_appcon la variable de entorno de OpenAI:
OPENAI_API_KEY=sk-xxxxx- Asegúrate de que el archivo Excel existe en
agent_app/data/cesancias_causadas.xlsx. Si el nombre del archivo es distinto, actualizautils/config.pyo pásalo explícitamente al crearExcelTools.
Ejecución
Desde el directorio agent_app lanza:
python main.pyEsto abrirá la interfaz Gradio en el navegador (local). En la UI escribe preguntas y el sistema intentará responder usando las herramientas disponibles.
Notas de implementación
- Las funciones que la LLM puede llamar están definidas en
mcp_server/mcp_tools.pyusando la especificación esperada por el cliente OpenAI. LlmServiceinicializa un clienteOpenAIcon la API key y manda lasmessagesal endpoint de chat. Cuando la LLM solicita ejecutar una función,LlmServicellama a_execute_function()que mapea el nombre de la función a un método deExcelTools.ExcelToolsprocesa valores especiales (NaN,pd.Timestamp,pd.Timedelta) y los transforma a valores serializables (None o strings) antes de invocarjson.dumps().
Resolución de problemas comunes
- ModuleNotFoundError: No module named 'agent_app'
- Ejecuta el script desde el directorio agent_app (o ajusta PYTHONPATH). Las importaciones usan rutas relativas como from utils.excel_tools import ExcelTools.
- FileNotFoundError / pandas cannot read Excel
- Verifica que data/cesancias_causadas.xlsx existe y que la ruta en utils/config.py apunta correctamente al archivo. Si ejecutas desde otra carpeta, usa la ruta absoluta o modifica main.py para construir la ruta a partir de __file__.
- Error con serialización JSON de
Timestamp
- ExcelTools ya convierte pd.Timestamp a isoformat() y NaN a None. Si añades nuevas funciones que devuelvan objetos no serializables, conviértelos manualmente antes de json.dumps().
Sugerencias / siguientes pasos
- Añadir tests unitarios para los métodos de
ExcelTools. - Hacer más robusto el mapeo de funciones (validar parámetros entrantes).
- Añadir paginación o límites cuando se devuelve
get_all_data()para evitar respuestas muy grandes. - Mejorar manejo de errores y logging (por ejemplo con
loggingen lugar de prints).
Autor
Autor Hoover Serna Electronics Engineer | Contact: arleyserna@msn.com
