UNPKG

n8n-nodes-mcp-eu

Version:
198 lines 10.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.McpNoticiasEuTool = void 0; const n8n_workflow_1 = require("n8n-workflow"); const generative_ai_1 = require("@google/generative-ai"); const index_js_1 = require("@modelcontextprotocol/sdk/client/index.js"); const stdio_js_1 = require("@modelcontextprotocol/sdk/client/stdio.js"); const MODEL_NAME = 'gemini-1.5-flash'; class McpNoticiasEuTool { constructor() { this.description = { displayName: 'MCP Noticias EU Tool', name: 'mcpNoticiasEuTool', icon: 'file:McpNoticiasEuTool.svg', group: ['transform'], version: 1, description: 'Conecta a un servidor MCP externo para obtener noticias de El Universal y las procesa con Gemini.', defaults: { name: 'MCP Noticias EU Tool', }, inputs: ["main"], outputs: ["main"], credentials: [ { name: 'geminiApi', required: true, }, { name: 'mcpNoticiasEuToolCmdApi', required: true, displayOptions: { show: {}, }, }, ], properties: [ { displayName: 'Connection Type', name: 'connectionType', type: 'hidden', default: 'cmd', }, { displayName: 'Cadena De Búsqueda De Noticias', name: 'queryString', type: 'string', default: 'últimas noticias de El Universal Cartagena', placeholder: 'Ej: noticias de hoy, clima Cartagena', description: 'La cadena de texto que se enviará al servidor MCP para buscar noticias', required: true, }, { displayName: 'Procesar Con Gemini', name: 'processWithGemini', type: 'boolean', default: true, description: 'Whether Gemini summarizes the response from the MCP tool for a more user-friendly format', }, ], }; } async execute() { var _a, _b, _c, _d, _e; const items = this.getInputData(); const returnData = []; const geminiCredentials = await this.getCredentials('geminiApi'); const geminiApiKey = geminiCredentials.apiKey; if (!geminiApiKey) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'La clave API de Gemini no está configurada.'); } const llm = new generative_ai_1.GoogleGenerativeAI(geminiApiKey); const model = llm.getGenerativeModel({ model: MODEL_NAME }); const chat = model.startChat(); const mcpCredentials = await this.getCredentials('mcpNoticiasEuToolCmdApi'); const args = ((_a = mcpCredentials.args) === null || _a === void 0 ? void 0 : _a.split(' ')) || []; const commandToExecute = process.execPath; const scriptPath = '/home/node/.n8n/custom-nodes/n8n-nodes-mcp-eu/dist/nodes/McpNoticiasEuTool/mcp_server.js'; const finalArgs = [scriptPath, ...args]; const env = { ...process.env }; if (mcpCredentials.environments) { try { const customEnvs = JSON.parse(mcpCredentials.environments); for (const key in customEnvs) { if (Object.prototype.hasOwnProperty.call(customEnvs, key)) { env[key] = customEnvs[key]; } } } catch (e) { this.logger.warn(`Could not parse environment variables JSON: ${e.message}`); } } this.logger.debug(`[MCP Node DEBUG] PATH completo que se pasa a spawn: ${env.PATH}`); this.logger.debug(`[MCP Node DEBUG] Comando completo a ejecutar: ${commandToExecute} ${finalArgs.join(' ')}`); this.logger.debug(`[MCP Node DEBUG] Objeto ENV completo que se pasa: ${JSON.stringify(env)}`); let transport = null; let mcpClient = null; try { transport = new stdio_js_1.StdioClientTransport({ command: commandToExecute, args: finalArgs, env: env, }); transport.onerror = (error) => { this.logger.error(`Error de transporte MCP: ${error.message}`); throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Error de transporte MCP: ${error.message}`); }; mcpClient = new index_js_1.Client({ name: 'n8n-mcp-noticias-tool-client', version: '1.0.0', timeout: 120000, }); this.logger.debug(`[MCP Node] Conectando a servidor MCP con comando FINAL: ${commandToExecute} ${finalArgs.join(' ')} con ENV: ${JSON.stringify(env)}`); await mcpClient.connect(transport); this.logger.debug('[MCP Node] Cliente MCP conectado.'); const toolsResult = await mcpClient.listTools({ timeout: 30000 }); const toolsDefinitions = toolsResult.tools; const functionDeclarations = toolsDefinitions.map((tool) => { var _a; return ({ name: tool.name, description: (_a = tool.description) !== null && _a !== void 0 ? _a : '', parameters: { type: generative_ai_1.SchemaType.OBJECT, properties: tool.inputSchema.properties, required: tool.inputSchema.required || [], }, }); }); model.tools = [{ functionDeclarations: functionDeclarations }]; this.logger.debug('[MCP Node] Herramientas del modelo Gemini configuradas.'); } catch (connectionError) { this.logger.error(`Error de conexión al servidor MCP: ${connectionError.message || String(connectionError)}`); throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Fallo al conectar al servidor MCP. Asegúrate de que el comando de las credenciales sea correcto. Detalles: ${connectionError.message || String(connectionError)}`); } for (let itemIndex = 0; itemIndex < items.length; itemIndex++) { const queryString = this.getNodeParameter('queryString', itemIndex); const processWithGemini = this.getNodeParameter('processWithGemini', itemIndex); if (!mcpClient) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'El cliente MCP no se inicializó correctamente.'); } const toolName = 'fetch_news'; const toolArgs = { queryString: queryString }; let mcpToolResult; try { this.logger.debug(`[MCP Node] Llamando a herramienta MCP: '${toolName}' con args: ${JSON.stringify(toolArgs)}`); mcpToolResult = await mcpClient.callTool({ name: toolName, arguments: toolArgs }, undefined, { timeout: 120000 }); this.logger.debug(`[MCP Node] Resultado bruto de MCP: ${JSON.stringify(mcpToolResult)}`); if (!mcpToolResult || !mcpToolResult.content || !Array.isArray(mcpToolResult.content) || mcpToolResult.content.length === 0) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), `La herramienta '${toolName}' no devolvió un formato de contenido válido para la cadena de búsqueda: "${queryString}".`); } } catch (toolCallError) { this.logger.error(`Error al ejecutar la herramienta MCP '${toolName}': ${toolCallError.message || String(toolCallError)}`); throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Fallo al llamar a la herramienta '${toolName}' para la cadena de búsqueda: "${queryString}". Detalles: ${toolCallError.message || String(toolCallError)}`); } let finalOutput = ((_b = mcpToolResult.content[0]) === null || _b === void 0 ? void 0 : _b.text) || JSON.stringify(mcpToolResult); let geminiSummary; if (processWithGemini) { const resultText = ((_c = mcpToolResult.content[0]) === null || _c === void 0 ? void 0 : _c.text) || JSON.stringify(mcpToolResult); const prompt = `Aquí están los resultados de la herramienta '${toolName}': ${resultText}. Con base en eso, genera un resumen conciso y amigable de las noticias para la búsqueda: "${queryString}".`; this.logger.debug(`[MCP Node] Enviando resultado a Gemini para resumen.`); try { const response = await chat.sendMessage(prompt); geminiSummary = (_d = response.response) === null || _d === void 0 ? void 0 : _d.text(); finalOutput = geminiSummary || 'No se pudo generar un resumen de Gemini.'; this.logger.debug(`[MCP Node] Resumen de Gemini generado.`); } catch (geminiError) { this.logger.error(`Error al procesar con Gemini: ${geminiError.message || String(geminiError)}`); geminiSummary = `Error al generar resumen con Gemini: ${geminiError.message || String(geminiError)}`; finalOutput = ((_e = mcpToolResult.content[0]) === null || _e === void 0 ? void 0 : _e.text) || JSON.stringify(mcpToolResult); } } returnData.push({ json: { queryString: queryString, toolName: toolName, toolArgs: toolArgs, mcpRawResult: mcpToolResult, geminiSummary: geminiSummary, finalOutput: finalOutput, }, }); } if (mcpClient) { this.logger.debug('[MCP Node] Cerrando conexión MCP.'); await mcpClient.close(); } return [returnData]; } } exports.McpNoticiasEuTool = McpNoticiasEuTool; //# sourceMappingURL=McpNoticiasEuTool.node.js.map