const apiService = require('../services/api-service').getInstance(); /** * Tools MCP pour interagir avec les APIs WMS */ /** * Liste des tools disponibles * @returns {Array} - Liste des tools */ function listTools() { return [ { name: 'call_query_api', description: 'Appelle l\'API Query du WMS pour interroger des entités (Containers, Stocks, Tasks, Products, etc.)', inputSchema: { type: 'object', properties: { entity_type: { type: 'string', description: 'Type d\'entité (Containers, Stocks, ProductLocations, Tasks, Products, Accounts, Suppliers, Kits, Aliases, InboundOrders, Receptions, OutboundOrders)', }, expression: { type: 'string', description: 'Expression LINQ (ex: "z => z" pour tout, "z => z.Id" pour les IDs uniquement)', default: 'z => z', }, filter: { type: 'string', description: 'Filtre LINQ optionnel (ex: "z.Id > 100")', }, limit: { type: 'number', description: 'Limite de résultats (défaut: 100)', default: 100, }, }, required: ['entity_type'], }, }, { name: 'execute_command', description: 'Exécute une commande WMS (ATTENTION: peut modifier des données). Toujours récupérer la commande via get_ad_elements/get_ad_element_details avant d\'exécuter.', inputSchema: { type: 'object', properties: { command_name: { type: 'string', description: 'InternalCommandName exact tel que retourné par get_ad_element_details (ex: "Mecalux.ITSW.EasyWMS.Modules.MasterData.Contracts.Commands.SupplierCreateCommand"). Ne pas ajouter de suffix assembly — cela cause une FileLoadException.', }, properties: { type: 'object', description: 'Propriétés de la commande. Pour toute commande de création (Create), un champ Id de type GUID est requis et doit être généré à la volée (ex: crypto.randomUUID() ou uuidv4()). Ne jamais laisser Id vide ou null.', }, }, required: ['command_name', 'properties'], }, }, ]; } /** * Exécute un tool API * @param {string} name - Nom du tool * @param {Object} args - Arguments du tool * @returns {Promise} - Résultat du tool */ async function executeTool(name, args) { switch (name) { case 'call_query_api': return await callQueryAPI(args); case 'execute_command': return await executeCommand(args); default: throw new Error(`Unknown API tool: ${name}`); } } /** * Tool: call_query_api */ async function callQueryAPI(args) { const { entity_type, expression = 'z => z', filter, limit = 100 } = args; try { // Expression = Context.Entity + optional Where + OrderBy (required by EF when Take is used) let linqExpression = `Context.${entity_type}`; if (filter) { const whereExpr = /^\s*\w+\s*=>/.test(filter) ? filter : `z => ${filter}`; linqExpression += `.Where(${whereExpr})`; } linqExpression += `.OrderBy(z => z.Id)`; const result = await apiService.executeQuery(linqExpression, { take: limit || undefined, select: expression !== 'z => z' ? expression : undefined, }); return { content: [ { type: 'text', text: JSON.stringify( { success: true, entityType: entity_type, result, }, null, 2 ), }, ], }; } catch (err) { return { content: [ { type: 'text', text: JSON.stringify( { success: false, error: err.message, }, null, 2 ), }, ], isError: true, }; } } /** * Tool: execute_command */ async function executeCommand(args) { const { command_name, properties } = args; try { const result = await apiService.executeCommand(command_name, properties); return { content: [ { type: 'text', text: JSON.stringify( { success: true, command: command_name, result, }, null, 2 ), }, ], }; } catch (err) { return { content: [ { type: 'text', text: JSON.stringify( { success: false, error: err.message, }, null, 2 ), }, ], isError: true, }; } } module.exports = { listTools, executeTool, };