@makafeli/n8n-workflow-builder
Version:
Model Context Protocol server for n8n workflow management
694 lines • 25.2 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
const zod_1 = require("zod");
const axios_1 = __importDefault(require("axios"));
// Configuration
const N8N_HOST = process.env.N8N_HOST || 'http://localhost:5678';
const N8N_API_KEY = process.env.N8N_API_KEY || '';
console.error("N8N API Configuration:");
console.error("Host:", N8N_HOST);
console.error("API Key:", N8N_API_KEY ? `${N8N_API_KEY.substring(0, 4)}****` : 'Not set');
// Create axios instance for n8n API
const n8nApi = axios_1.default.create({
baseURL: N8N_HOST,
headers: {
'X-N8N-API-KEY': N8N_API_KEY,
'Content-Type': 'application/json'
}
});
// Create MCP server with modern SDK 1.17.0 API
const server = new mcp_js_1.McpServer({
name: "n8n-workflow-builder",
version: "0.10.3"
});
// Register workflow management tools using modern MCP SDK 1.17.0 API
server.tool("list_workflows", "List all workflows from n8n instance", {}, async () => {
try {
const response = await n8nApi.get('/workflows');
return {
content: [{
type: "text",
text: JSON.stringify(response.data, null, 2)
}]
};
}
catch (error) {
return {
content: [{
type: "text",
text: `Error: ${error instanceof Error ? error.message : String(error)}`
}],
isError: true
};
}
});
server.tool("create_workflow", "Create a new workflow in n8n", {
workflow: zod_1.z.object({
name: zod_1.z.string().describe("Name of the workflow"),
nodes: zod_1.z.array(zod_1.z.any()).describe("Array of workflow nodes"),
connections: zod_1.z.record(zod_1.z.string(), zod_1.z.any()).optional().describe("Node connections"),
settings: zod_1.z.record(zod_1.z.string(), zod_1.z.any()).optional().describe("Workflow settings"),
tags: zod_1.z.array(zod_1.z.any()).optional().describe("Workflow tags")
}).describe("Workflow configuration")
}, async ({ workflow }) => {
try {
const response = await n8nApi.post('/workflows', workflow);
return {
content: [{
type: "text",
text: JSON.stringify(response.data, null, 2)
}]
};
}
catch (error) {
return {
content: [{
type: "text",
text: `Error: ${error instanceof Error ? error.message : String(error)}`
}],
isError: true
};
}
});
server.tool("get_workflow", "Get a workflow by ID", {
id: zod_1.z.string().describe("Workflow ID")
}, async ({ id }) => {
try {
const response = await n8nApi.get(`/workflows/${id}`);
return {
content: [{
type: "text",
text: JSON.stringify(response.data, null, 2)
}]
};
}
catch (error) {
return {
content: [{
type: "text",
text: `Error: ${error instanceof Error ? error.message : String(error)}`
}],
isError: true
};
}
});
server.tool("update_workflow", "Update an existing workflow by ID", {
id: zod_1.z.string().describe("Workflow ID"),
workflow: zod_1.z.object({
name: zod_1.z.string().optional().describe("Name of the workflow"),
nodes: zod_1.z.array(zod_1.z.any()).optional().describe("Array of workflow nodes"),
connections: zod_1.z.record(zod_1.z.string(), zod_1.z.any()).optional().describe("Node connections"),
settings: zod_1.z.record(zod_1.z.string(), zod_1.z.any()).optional().describe("Workflow settings"),
tags: zod_1.z.array(zod_1.z.any()).optional().describe("Workflow tags")
}).describe("Updated workflow configuration")
}, async ({ id, workflow }) => {
try {
const response = await n8nApi.put(`/workflows/${id}`, workflow);
return {
content: [{
type: "text",
text: JSON.stringify(response.data, null, 2)
}]
};
}
catch (error) {
return {
content: [{
type: "text",
text: `Error: ${error instanceof Error ? error.message : String(error)}`
}],
isError: true
};
}
});
server.tool("delete_workflow", "Delete a workflow by ID", {
id: zod_1.z.string().describe("Workflow ID")
}, async ({ id }) => {
try {
const response = await n8nApi.delete(`/workflows/${id}`);
return {
content: [{
type: "text",
text: JSON.stringify({
success: true,
message: `Workflow ${id} deleted successfully`,
deletedWorkflow: response.data
}, null, 2)
}]
};
}
catch (error) {
return {
content: [{
type: "text",
text: `Error: ${error instanceof Error ? error.message : String(error)}`
}],
isError: true
};
}
});
server.tool("activate_workflow", "Activate a workflow by ID", {
id: zod_1.z.string().describe("Workflow ID")
}, async ({ id }) => {
try {
const response = await n8nApi.post(`/workflows/${id}/activate`);
return {
content: [{
type: "text",
text: JSON.stringify({
success: true,
message: `Workflow ${id} activated successfully`,
workflow: response.data
}, null, 2)
}]
};
}
catch (error) {
return {
content: [{
type: "text",
text: `Error: ${error instanceof Error ? error.message : String(error)}`
}],
isError: true
};
}
});
server.tool("deactivate_workflow", "Deactivate a workflow by ID", {
id: zod_1.z.string().describe("Workflow ID")
}, async ({ id }) => {
try {
const response = await n8nApi.post(`/workflows/${id}/deactivate`);
return {
content: [{
type: "text",
text: JSON.stringify({
success: true,
message: `Workflow ${id} deactivated successfully`,
workflow: response.data
}, null, 2)
}]
};
}
catch (error) {
return {
content: [{
type: "text",
text: `Error: ${error instanceof Error ? error.message : String(error)}`
}],
isError: true
};
}
});
server.tool("execute_workflow", "Execute a workflow manually", {
id: zod_1.z.string().describe("Workflow ID")
}, async ({ id }) => {
try {
const response = await n8nApi.post(`/workflows/${id}/execute`);
return {
content: [{
type: "text",
text: JSON.stringify({
success: true,
message: `Workflow ${id} executed successfully`,
execution: response.data
}, null, 2)
}]
};
}
catch (error) {
return {
content: [{
type: "text",
text: `Error: ${error instanceof Error ? error.message : String(error)}`
}],
isError: true
};
}
});
server.tool("create_workflow_and_activate", "Create a new workflow and immediately activate it", {
workflow: zod_1.z.object({
name: zod_1.z.string().describe("Name of the workflow"),
nodes: zod_1.z.array(zod_1.z.any()).describe("Array of workflow nodes"),
connections: zod_1.z.record(zod_1.z.string(), zod_1.z.any()).optional().describe("Node connections"),
settings: zod_1.z.record(zod_1.z.string(), zod_1.z.any()).optional().describe("Workflow settings"),
tags: zod_1.z.array(zod_1.z.any()).optional().describe("Workflow tags")
}).describe("Workflow configuration")
}, async ({ workflow }) => {
try {
// First create the workflow
const createResponse = await n8nApi.post('/workflows', workflow);
const workflowId = createResponse.data.id;
// Then activate it
const activateResponse = await n8nApi.post(`/workflows/${workflowId}/activate`);
return {
content: [{
type: "text",
text: JSON.stringify({
success: true,
message: `Workflow created and activated successfully`,
workflow: activateResponse.data
}, null, 2)
}]
};
}
catch (error) {
return {
content: [{
type: "text",
text: `Error: ${error instanceof Error ? error.message : String(error)}`
}],
isError: true
};
}
});
// Execution Management Tools
server.tool("list_executions", "List workflow executions with filtering and pagination support", {
includeData: zod_1.z.boolean().optional().describe("Include execution's detailed data"),
status: zod_1.z.enum(["error", "success", "waiting"]).optional().describe("Filter by execution status"),
workflowId: zod_1.z.string().optional().describe("Filter by specific workflow ID"),
projectId: zod_1.z.string().optional().describe("Filter by project ID"),
limit: zod_1.z.number().min(1).max(250).optional().describe("Number of executions to return (max: 250)"),
cursor: zod_1.z.string().optional().describe("Pagination cursor for next page")
}, async ({ includeData, status, workflowId, projectId, limit, cursor }) => {
try {
const params = new URLSearchParams();
if (includeData !== undefined)
params.append('includeData', includeData.toString());
if (status)
params.append('status', status);
if (workflowId)
params.append('workflowId', workflowId);
if (projectId)
params.append('projectId', projectId);
if (limit)
params.append('limit', limit.toString());
if (cursor)
params.append('cursor', cursor);
const response = await n8nApi.get(`/executions?${params.toString()}`);
return {
content: [{
type: "text",
text: JSON.stringify(response.data, null, 2)
}]
};
}
catch (error) {
return {
content: [{
type: "text",
text: `Error: ${error instanceof Error ? error.message : String(error)}`
}],
isError: true
};
}
});
server.tool("get_execution", "Get detailed information about a specific workflow execution", {
id: zod_1.z.string().describe("Execution ID"),
includeData: zod_1.z.boolean().optional().describe("Include detailed execution data")
}, async ({ id, includeData }) => {
try {
const params = new URLSearchParams();
if (includeData !== undefined)
params.append('includeData', includeData.toString());
const url = `/executions/${id}${params.toString() ? `?${params.toString()}` : ''}`;
const response = await n8nApi.get(url);
return {
content: [{
type: "text",
text: JSON.stringify(response.data, null, 2)
}]
};
}
catch (error) {
return {
content: [{
type: "text",
text: `Error: ${error instanceof Error ? error.message : String(error)}`
}],
isError: true
};
}
});
server.tool("delete_execution", "Delete a workflow execution record from the n8n instance", {
id: zod_1.z.string().describe("Execution ID to delete")
}, async ({ id }) => {
try {
const response = await n8nApi.delete(`/executions/${id}`);
return {
content: [{
type: "text",
text: JSON.stringify({
success: true,
message: `Execution ${id} deleted successfully`,
deletedExecution: response.data
}, null, 2)
}]
};
}
catch (error) {
return {
content: [{
type: "text",
text: `Error: ${error instanceof Error ? error.message : String(error)}`
}],
isError: true
};
}
});
// Tag Management Tools
server.tool("list_tags", "List all workflow tags with pagination support", {
limit: zod_1.z.number().min(1).max(250).optional().describe("Number of tags to return (max: 250)"),
cursor: zod_1.z.string().optional().describe("Pagination cursor for next page")
}, async ({ limit, cursor }) => {
try {
const params = new URLSearchParams();
if (limit)
params.append('limit', limit.toString());
if (cursor)
params.append('cursor', cursor);
const response = await n8nApi.get(`/tags?${params.toString()}`);
return {
content: [{
type: "text",
text: JSON.stringify(response.data, null, 2)
}]
};
}
catch (error) {
return {
content: [{
type: "text",
text: `Error: ${error instanceof Error ? error.message : String(error)}`
}],
isError: true
};
}
});
server.tool("create_tag", "Create a new workflow tag for organization and categorization", {
name: zod_1.z.string().describe("Name of the tag to create")
}, async ({ name }) => {
try {
const response = await n8nApi.post('/tags', { name });
return {
content: [{
type: "text",
text: JSON.stringify({
success: true,
message: `Tag '${name}' created successfully`,
tag: response.data
}, null, 2)
}]
};
}
catch (error) {
return {
content: [{
type: "text",
text: `Error: ${error instanceof Error ? error.message : String(error)}`
}],
isError: true
};
}
});
server.tool("get_tag", "Retrieve individual tag details by ID", {
id: zod_1.z.string().describe("Tag ID")
}, async ({ id }) => {
try {
const response = await n8nApi.get(`/tags/${id}`);
return {
content: [{
type: "text",
text: JSON.stringify({
success: true,
tag: response.data,
message: `Tag ${id} retrieved successfully`
}, null, 2)
}]
};
}
catch (error) {
return {
content: [{
type: "text",
text: `Error: ${error instanceof Error ? error.message : String(error)}`
}],
isError: true
};
}
});
server.tool("update_tag", "Modify tag names for better organization", {
id: zod_1.z.string().describe("Tag ID"),
name: zod_1.z.string().describe("New name for the tag")
}, async ({ id, name }) => {
try {
const response = await n8nApi.put(`/tags/${id}`, { name });
return {
content: [{
type: "text",
text: JSON.stringify({
success: true,
message: `Tag ${id} updated successfully`,
tag: response.data
}, null, 2)
}]
};
}
catch (error) {
return {
content: [{
type: "text",
text: `Error: ${error instanceof Error ? error.message : String(error)}`
}],
isError: true
};
}
});
server.tool("delete_tag", "Remove unused tags from the system", {
id: zod_1.z.string().describe("Tag ID to delete")
}, async ({ id }) => {
try {
const response = await n8nApi.delete(`/tags/${id}`);
return {
content: [{
type: "text",
text: JSON.stringify({
success: true,
message: `Tag ${id} deleted successfully`,
deletedTag: response.data
}, null, 2)
}]
};
}
catch (error) {
return {
content: [{
type: "text",
text: `Error: ${error instanceof Error ? error.message : String(error)}`
}],
isError: true
};
}
});
server.tool("get_workflow_tags", "Get all tags associated with a specific workflow", {
workflowId: zod_1.z.string().describe("Workflow ID")
}, async ({ workflowId }) => {
try {
const response = await n8nApi.get(`/workflows/${workflowId}/tags`);
return {
content: [{
type: "text",
text: JSON.stringify({
success: true,
workflowId,
tags: response.data,
message: `Tags for workflow ${workflowId} retrieved successfully`
}, null, 2)
}]
};
}
catch (error) {
return {
content: [{
type: "text",
text: `Error: ${error instanceof Error ? error.message : String(error)}`
}],
isError: true
};
}
});
server.tool("update_workflow_tags", "Assign or remove tags from workflows", {
workflowId: zod_1.z.string().describe("Workflow ID"),
tagIds: zod_1.z.array(zod_1.z.string()).describe("Array of tag IDs to assign to the workflow")
}, async ({ workflowId, tagIds }) => {
try {
const response = await n8nApi.put(`/workflows/${workflowId}/tags`, { tagIds });
return {
content: [{
type: "text",
text: JSON.stringify({
success: true,
message: `Tags for workflow ${workflowId} updated successfully`,
workflowId,
assignedTags: response.data
}, null, 2)
}]
};
}
catch (error) {
return {
content: [{
type: "text",
text: `Error: ${error instanceof Error ? error.message : String(error)}`
}],
isError: true
};
}
});
// Credential Management Tools
server.tool("create_credential", "Create a new credential for workflow authentication. Use get_credential_schema first to understand required fields for the credential type.", {
name: zod_1.z.string().describe("Name for the credential"),
type: zod_1.z.string().describe("Credential type (e.g., 'httpBasicAuth', 'httpHeaderAuth', 'oAuth2Api', etc.)"),
data: zod_1.z.record(zod_1.z.string(), zod_1.z.any()).describe("Credential data object with required fields for the credential type")
}, async ({ name, type, data }) => {
try {
const response = await n8nApi.post('/credentials', {
name,
type,
data
});
return {
content: [{
type: "text",
text: JSON.stringify({
success: true,
message: `Credential '${name}' created successfully`,
credential: {
id: response.data.id,
name: response.data.name,
type: response.data.type,
createdAt: response.data.createdAt
}
}, null, 2)
}]
};
}
catch (error) {
return {
content: [{
type: "text",
text: `Error: ${error instanceof Error ? error.message : String(error)}`
}],
isError: true
};
}
});
server.tool("get_credential_schema", "Get the schema for a specific credential type to understand what fields are required when creating credentials.", {
credentialType: zod_1.z.string().describe("Credential type name (e.g., 'httpBasicAuth', 'httpHeaderAuth', 'oAuth2Api', 'githubApi', 'slackApi', etc.)")
}, async ({ credentialType }) => {
try {
const response = await n8nApi.get(`/credentials/schema/${credentialType}`);
return {
content: [{
type: "text",
text: JSON.stringify({
success: true,
credentialType,
schema: response.data,
message: `Schema for credential type '${credentialType}' retrieved successfully`
}, null, 2)
}]
};
}
catch (error) {
return {
content: [{
type: "text",
text: `Error: ${error instanceof Error ? error.message : String(error)}`
}],
isError: true
};
}
});
server.tool("delete_credential", "Delete a credential by ID. This will remove the credential and make it unavailable for workflows. Use with caution as this action cannot be undone.", {
id: zod_1.z.string().describe("Credential ID to delete")
}, async ({ id }) => {
try {
const response = await n8nApi.delete(`/credentials/${id}`);
return {
content: [{
type: "text",
text: JSON.stringify({
success: true,
message: `Credential ${id} deleted successfully`,
deletedCredential: response.data
}, null, 2)
}]
};
}
catch (error) {
return {
content: [{
type: "text",
text: `Error: ${error instanceof Error ? error.message : String(error)}`
}],
isError: true
};
}
});
// Security Audit Tool
server.tool("generate_audit", "Generate a comprehensive security audit report for the n8n instance", {
additionalOptions: zod_1.z.object({
daysAbandonedWorkflow: zod_1.z.number().optional().describe("Number of days to consider a workflow abandoned"),
categories: zod_1.z.array(zod_1.z.enum(["credentials", "database", "nodes", "filesystem", "instance"])).optional().describe("Audit categories to include")
}).optional().describe("Additional audit configuration options")
}, async ({ additionalOptions }) => {
try {
const auditPayload = {};
if (additionalOptions) {
if (additionalOptions.daysAbandonedWorkflow !== undefined) {
auditPayload.daysAbandonedWorkflow = additionalOptions.daysAbandonedWorkflow;
}
if (additionalOptions.categories) {
auditPayload.categories = additionalOptions.categories;
}
}
const response = await n8nApi.post('/audit', auditPayload);
return {
content: [{
type: "text",
text: JSON.stringify({
success: true,
message: "Security audit generated successfully",
audit: response.data
}, null, 2)
}]
};
}
catch (error) {
return {
content: [{
type: "text",
text: `Error: ${error instanceof Error ? error.message : String(error)}`
}],
isError: true
};
}
});
// Start the server
async function main() {
const transport = new stdio_js_1.StdioServerTransport();
await server.connect(transport);
console.error("N8N Workflow Builder MCP server v0.10.3 running on stdio");
console.error("Modern SDK 1.17.0 with 23 tools: 9 workflow + 3 execution + 7 tag + 3 credential + 1 audit");
}
main().catch((error) => {
console.error("Server error:", error);
process.exit(1);
});
//# sourceMappingURL=server.js.map