# kanboard_mcp.py """ 🚀 Servidor FastMCP para controlar Kanboard desde un LLM. Este módulo expone las funciones del paquete `kanboard_utils` como herramientas del protocolo MCP (Model Context Protocol), permitiendo a modelos de lenguaje (LLMs) listar, crear, mover y editar tareas en Kanboard de forma segura y programática. Requisitos: uv add fastmcp requests python-dotenv """ import os from fastmcp import FastMCP from kanboard_utils import ( listar_proyectos, listar_usuarios, listar_tareas, listar_subtareas, listar_tareas_por_columna, mover_tarea_columna, crear_tarea, editar_tarea, ) # ======================== # ⚙️ Configuración global # ======================== # Carga las variables de entorno automáticamente # (útil si usas un archivo .env con los valores) from dotenv import load_dotenv load_dotenv() # Lee las credenciales de Kanboard desde variables de entorno API_URL = os.getenv("KANBOARD_API_URL", "http://localhost:8080/jsonrpc.php") USER = os.getenv("KANBOARD_USER", "jsonrpc") TOKEN = os.getenv("KANBOARD_TOKEN", "792d8fdd6cbf69b3a32d800beaf48b958e4490dd9185c72c06c56061a591") # ======================== # 🧠 Inicializa el servidor # ======================== mcp = FastMCP( "Kanboard Controller", instructions=""" Controlador MCP para Kanboard que permite a un LLM gestionar tareas, proyectos y usuarios de un tablero Kanboard mediante JSON-RPC. """ ) # ===================================================== # 🧩 Herramientas disponibles para el agente LLM # ===================================================== @mcp.tool def list_projects() -> list[dict]: """📁 Listar todos los proyectos de Kanboard.""" return listar_proyectos(API_URL, USER, TOKEN) @mcp.tool def list_users() -> list[dict]: """👥 Listar todos los usuarios disponibles en Kanboard.""" return listar_usuarios(API_URL, USER, TOKEN) @mcp.tool def list_tasks(project_id: int) -> list[str]: """ 🗂️ Listar todas las tareas de un proyecto (solo nombres). Devuelve una lista simple de títulos de tareas, sin metadatos adicionales. Esto simplifica el contexto para modelos de lenguaje. """ tareas = listar_tareas(API_URL, USER, TOKEN, project_id) # 🧹 Extrae solo los títulos (ignorando otros campos) nombres = [t["title"] for t in tareas if "title" in t] # 🔢 Devuelve lista simple de strings return nombres @mcp.tool def list_subtasks(task_id: int) -> list[dict]: """📋 Listar las subtareas de una tarea específica.""" return listar_subtareas(API_URL, USER, TOKEN, task_id) @mcp.tool def list_tasks_by_column(project_id: int) -> dict: """🧩 Agrupar las tareas por columna del tablero Kanboard.""" return listar_tareas_por_columna(API_URL, USER, TOKEN, project_id) @mcp.tool def move_task(project_id: int, task_id: int, column_id: int, position: int = 1, swimlane_id: int = 0) -> bool: """🔄 Mover una tarea entre columnas del tablero.""" return mover_tarea_columna(API_URL, USER, TOKEN, project_id, task_id, column_id, position, swimlane_id) @mcp.tool def create_task(project_id: int, titulo: str, descripcion: str = "", swimlane_id: int | None = None, assignee_id: int | None = None, tags: list[str] | None = None, priority: int | None = None) -> dict: """➕ Crear una nueva tarea en un proyecto Kanboard.""" return crear_tarea(API_URL, USER, TOKEN, project_id, titulo, descripcion, swimlane_id, assignee_id, tags, priority) @mcp.tool def edit_task(task_id: int, titulo: str | None = None, descripcion: str | None = None, swimlane_id: int | None = None, assignee_id: int | None = None, tags: list[str] | None = None, priority: int | None = None) -> dict: """✏️ Editar una tarea existente en Kanboard.""" return editar_tarea(API_URL, USER, TOKEN, task_id, titulo, descripcion, swimlane_id, assignee_id, tags, priority) # ===================================================== # 🚀 Punto de entrada principal del servidor FastMCP # ===================================================== if __name__ == "__main__": print("✅ Kanboard MCP listo y conectado con:") print(f" 🌐 API_URL: {API_URL}") print(f" 👤 Usuario: {USER}") mcp.run()