n8n-nodes-mcp-eu
Version:
Servicio MCP para consultar las noticias del periodico El Universal Cartagena
198 lines • 10.7 kB
JavaScript
;
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