Skip to main content
Glama

n8n MCP Server

MIT License
133
1,377
  • Apple
  • Linux
run.ts5.07 kB
/** * Run Execution via Webhook Tool Handler * * This module provides a tool for running n8n workflows via webhooks. */ import axios from 'axios'; import { z } from 'zod'; import { ToolCallResult } from '../../types/index.js'; import { BaseExecutionToolHandler } from './base-handler.js'; import { N8nApiError } from '../../errors/index.js'; import { getEnvConfig } from '../../config/environment.js'; import { URL } from 'url'; /** * Webhook execution input schema */ const runWebhookSchema = z.object({ workflowName: z.string().describe('Name of the workflow to execute (e.g., "hello-world")'), data: z.record(z.any()).optional().describe('Input data to pass to the webhook'), headers: z.record(z.string()).optional().describe('Additional headers to send with the request') }); /** * Handler for the run_webhook tool */ export class RunWebhookHandler extends BaseExecutionToolHandler { /** * Tool definition for execution via webhook */ public static readonly inputSchema = runWebhookSchema; /** * Extract N8N base URL from N8N API URL by removing /api/v1 * @returns N8N base URL */ private getN8nBaseUrl(): string { const config = getEnvConfig(); const apiUrl = new URL(config.n8nApiUrl); // Remove /api/v1 if it exists in the path let path = apiUrl.pathname; if (path.endsWith('/api/v1') || path.endsWith('/api/v1/')) { path = path.replace(/\/api\/v1\/?$/, ''); } // Create a new URL with the base path apiUrl.pathname = path; return apiUrl.toString(); } /** * Validate and execute webhook call * * @param args Tool arguments * @returns Tool call result */ async execute(args: Record<string, any>): Promise<ToolCallResult> { return this.handleExecution(async (args) => { // Parse and validate arguments const params = runWebhookSchema.parse(args); // Get environment config for auth credentials const config = getEnvConfig(); // Check if webhook credentials are provided, as they are required for this tool if (!config.n8nWebhookUsername || !config.n8nWebhookPassword) { throw new N8nApiError( 'Webhook username and password are required for run_webhook tool. ' + 'Please set N8N_WEBHOOK_USERNAME and N8N_WEBHOOK_PASSWORD environment variables.', 400 // Bad Request, as it's a client-side configuration issue for this specific tool ); } try { // Get the webhook URL with the proper prefix const baseUrl = this.getN8nBaseUrl(); const webhookPath = `webhook/${params.workflowName}`; const webhookUrl = new URL(webhookPath, baseUrl).toString(); // Prepare request config with basic auth from environment const requestConfig: any = { headers: { 'Content-Type': 'application/json', ...(params.headers || {}) }, auth: { username: config.n8nWebhookUsername, password: config.n8nWebhookPassword } }; // Make the request to the webhook const response = await axios.post( webhookUrl, params.data || {}, requestConfig ); // Return the webhook response return this.formatSuccess({ status: response.status, statusText: response.statusText, data: response.data }, 'Webhook executed successfully'); } catch (error) { // Handle error from the webhook request if (axios.isAxiosError(error)) { let errorMessage = `Webhook execution failed: ${error.message}`; if (error.response) { errorMessage = `Webhook execution failed with status ${error.response.status}: ${error.response.statusText}`; if (error.response.data) { return this.formatError(new N8nApiError( `${errorMessage}\n\n${JSON.stringify(error.response.data, null, 2)}`, error.response.status )); } } return this.formatError(new N8nApiError(errorMessage, error.response?.status || 500)); } throw error; // Re-throw non-axios errors for the handler to catch } }, args); } } /** * Get the tool definition for run_webhook * * @returns Tool definition object */ export function getRunWebhookToolDefinition() { return { name: 'run_webhook', description: 'Execute a workflow via webhook with optional input data', inputSchema: { type: 'object', properties: { workflowName: { type: 'string', description: 'Name of the workflow to execute (e.g., "hello-world")' }, data: { type: 'object', description: 'Input data to pass to the webhook' }, headers: { type: 'object', description: 'Additional headers to send with the request' } }, required: ['workflowName'] } }; }

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/leonardsellem/n8n-mcp-server'

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