Skip to main content
Glama
WorkflowManagerTool.ts9.88 kB
import { MCPTool } from "mcp-framework"; import axios from "axios"; import fs from "fs"; import path from "path"; import { z } from "zod"; interface WorkflowManagerInput { action: "list" | "get" | "create" | "update" | "delete" | "export" | "import"; workflowId?: string; workflowPath?: string; workflowData?: any; tags?: string[]; } class WorkflowManagerTool extends MCPTool<WorkflowManagerInput> { private apiUrl = process.env.N8N_API_URL || "http://localhost:5678/api/v1"; private apiKey = process.env.N8N_API_KEY || ""; name = "workflow_manager"; description = "Gère les workflows n8n (liste, récupère, crée, met à jour, supprime, exporte, importe)"; schema = { action: { type: z.enum(["list", "get", "create", "update", "delete", "export", "import"]), description: "Action à effectuer sur les workflows" }, workflowId: { type: z.string().optional(), description: "ID du workflow (requis pour get, update, delete, export)" }, workflowPath: { type: z.string().optional(), description: "Chemin du fichier de workflow (requis pour export, import)" }, workflowData: { type: z.any().optional(), description: "Données du workflow (requis pour create, update)" }, tags: { type: z.array(z.string()).optional(), description: "Tags pour filtrer les workflows (optionnel pour list)" } }; private getAxiosConfig() { return { headers: { "X-N8N-API-KEY": this.apiKey, "Content-Type": "application/json", }, }; } private logApiCall(method: string, url: string, data?: any) { console.log(`[WorkflowManagerTool] Appel API: ${method} ${url}`); if (data) { console.log(`[WorkflowManagerTool] Données: ${JSON.stringify(data).substring(0, 200)}...`); } } private handleApiError(error: any, action: string) { console.error(`[WorkflowManagerTool] Erreur lors de l'action '${action}':`, error); if (error.response) { console.error(`[WorkflowManagerTool] Statut: ${error.response.status}`); console.error(`[WorkflowManagerTool] Données: ${JSON.stringify(error.response.data)}`); } else if (error.request) { console.error('[WorkflowManagerTool] Aucune réponse reçue du serveur'); console.error(error.request); } else { console.error(`[WorkflowManagerTool] Erreur: ${error.message}`); } return { success: false, error: error.message, details: error.response?.data || "Erreur inconnue", }; } async execute(options: WorkflowManagerInput): Promise<any> { const { action, workflowId, workflowPath, workflowData, tags } = options; try { console.log(`[WorkflowManagerTool] Exécution de l'action: ${action}`); switch (action) { case "list": return this.listWorkflows(tags); case "get": if (!workflowId) throw new Error("workflowId est requis pour l'action get"); return this.getWorkflow(workflowId); case "create": if (!workflowData) throw new Error("workflowData est requis pour l'action create"); return this.createWorkflow(workflowData); case "update": if (!workflowId) throw new Error("workflowId est requis pour l'action update"); if (!workflowData) throw new Error("workflowData est requis pour l'action update"); return this.updateWorkflow(workflowId, workflowData); case "delete": if (!workflowId) throw new Error("workflowId est requis pour l'action delete"); return this.deleteWorkflow(workflowId); case "export": if (!workflowId) throw new Error("workflowId est requis pour l'action export"); if (!workflowPath) throw new Error("workflowPath est requis pour l'action export"); return this.exportWorkflow(workflowId, workflowPath); case "import": if (!workflowPath) throw new Error("workflowPath est requis pour l'action import"); return this.importWorkflow(workflowPath); default: throw new Error(`Action non reconnue: ${action}`); } } catch (error: any) { console.error(`[WorkflowManagerTool] Erreur lors de l'exécution de l'action '${action}':`, error); return { success: false, error: error.message, details: "Erreur lors de l'exécution de l'action", }; } } private async listWorkflows(tags?: string[]) { try { const url = `${this.apiUrl}/workflows`; this.logApiCall('GET', url); const response = await axios.get(url, this.getAxiosConfig()); console.log(`[WorkflowManagerTool] ${response.data.data.length} workflows récupérés`); let workflows = response.data.data; // Filtrer par tags si spécifié if (tags && tags.length > 0) { console.log(`[WorkflowManagerTool] Filtrage par tags: ${tags.join(', ')}`); workflows = workflows.filter((workflow: any) => { if (!workflow.tags) return false; return tags.some(tag => workflow.tags.includes(tag)); }); console.log(`[WorkflowManagerTool] ${workflows.length} workflows après filtrage`); } return { success: true, count: workflows.length, workflows: workflows.map((wf: any) => ({ id: wf.id, name: wf.name, active: wf.active, tags: wf.tags || [], createdAt: wf.createdAt, updatedAt: wf.updatedAt, })), }; } catch (error: any) { return this.handleApiError(error, 'listWorkflows'); } } private async getWorkflow(workflowId: string) { try { const url = `${this.apiUrl}/workflows/${workflowId}`; this.logApiCall('GET', url); const response = await axios.get(url, this.getAxiosConfig()); console.log(`[WorkflowManagerTool] Workflow récupéré: ${response.data.name}`); return { success: true, workflow: response.data, }; } catch (error: any) { return this.handleApiError(error, 'getWorkflow'); } } private async createWorkflow(workflowData: any) { try { const url = `${this.apiUrl}/workflows`; this.logApiCall('POST', url, workflowData); const response = await axios.post(url, workflowData, this.getAxiosConfig()); console.log(`[WorkflowManagerTool] Workflow créé: ${response.data.name}`); return { success: true, workflow: response.data, }; } catch (error: any) { return this.handleApiError(error, 'createWorkflow'); } } private async updateWorkflow(workflowId: string, workflowData: any) { try { const url = `${this.apiUrl}/workflows/${workflowId}`; this.logApiCall('PUT', url, workflowData); const response = await axios.put(url, workflowData, this.getAxiosConfig()); console.log(`[WorkflowManagerTool] Workflow mis à jour: ${response.data.name}`); return { success: true, workflow: response.data, }; } catch (error: any) { return this.handleApiError(error, 'updateWorkflow'); } } private async deleteWorkflow(workflowId: string) { try { const url = `${this.apiUrl}/workflows/${workflowId}`; this.logApiCall('DELETE', url); await axios.delete(url, this.getAxiosConfig()); console.log(`[WorkflowManagerTool] Workflow supprimé: ${workflowId}`); return { success: true, message: `Workflow ${workflowId} supprimé avec succès`, }; } catch (error: any) { return this.handleApiError(error, 'deleteWorkflow'); } } private async exportWorkflow(workflowId: string, workflowPath: string) { try { // Récupérer le workflow const getResult = await this.getWorkflow(workflowId); if (!getResult.success || !('workflow' in getResult)) { return getResult; } // Créer le répertoire de destination si nécessaire const dir = path.dirname(workflowPath); if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true }); } // Écrire le workflow dans le fichier fs.writeFileSync(workflowPath, JSON.stringify(getResult.workflow, null, 2)); console.log(`[WorkflowManagerTool] Workflow exporté vers: ${workflowPath}`); return { success: true, message: `Workflow exporté avec succès vers ${workflowPath}`, path: workflowPath, }; } catch (error: any) { console.error(`[WorkflowManagerTool] Erreur lors de l'exportation du workflow:`, error); return { success: false, error: error.message, details: "Erreur lors de l'exportation du workflow", }; } } private async importWorkflow(workflowPath: string) { try { // Vérifier que le fichier existe if (!fs.existsSync(workflowPath)) { throw new Error(`Le fichier ${workflowPath} n'existe pas`); } // Lire le contenu du fichier const workflowContent = fs.readFileSync(workflowPath, 'utf8'); const workflowData = JSON.parse(workflowContent); console.log(`[WorkflowManagerTool] Workflow lu depuis: ${workflowPath}`); // Supprimer l'ID pour créer un nouveau workflow const { id, ...newWorkflowData } = workflowData; // Créer le workflow return this.createWorkflow(newWorkflowData); } catch (error: any) { console.error(`[WorkflowManagerTool] Erreur lors de l'importation du workflow:`, error); return { success: false, error: error.message, details: "Erreur lors de l'importation du workflow", }; } } } export default WorkflowManagerTool;

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/lowprofix/n8n-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server