Initial commit of n8n MCP Server

A Model Context Protocol (MCP) server that integrates with n8n, providing tools for workflow and execution management via the n8n API.
This commit is contained in:
leonardsellem
2025-03-12 17:12:35 +01:00
commit 2cd565cfa6
79 changed files with 19654 additions and 0 deletions

View File

@@ -0,0 +1,617 @@
# Advanced Scenarios
This page demonstrates more complex examples of using the n8n MCP Server with AI assistants.
## Workflow Analysis and Optimization
### User Prompt
"Analyze my workflows and suggest optimizations."
### Assistant Actions
```javascript
// Get all workflows
const workflows = await useMcpTool('n8n-mcp-server', 'workflow_list', {});
// Get execution statistics
const stats = await accessMcpResource('n8n-mcp-server', 'n8n://execution-stats');
// Analyze each workflow in detail
const analysisResults = [];
for (const workflow of workflows) {
// Get detailed workflow information
const details = await useMcpTool('n8n-mcp-server', 'workflow_get', {
id: workflow.id
});
// Get recent executions
const executions = await useMcpTool('n8n-mcp-server', 'execution_list', {
workflowId: workflow.id,
limit: 10
});
// Analyze workflow structure
const nodeCount = details.nodes.length;
const nodeTypes = new Set(details.nodes.map(node => node.type));
// Check for error patterns in executions
const errorRate = executions.length > 0
? executions.filter(e => e.status === "error").length / executions.length
: 0;
// Check execution times
const executionTimes = executions
.filter(e => e.status === "success" && e.finishedAt && e.startedAt)
.map(e => new Date(e.finishedAt) - new Date(e.startedAt));
const avgExecutionTime = executionTimes.length > 0
? executionTimes.reduce((sum, time) => sum + time, 0) / executionTimes.length / 1000
: 0;
// Generate optimization suggestions
const suggestions = [];
if (nodeCount > 15) {
suggestions.push("Consider splitting into multiple workflows for better maintainability");
}
if (errorRate > 0.2) {
suggestions.push("High error rate detected - review error handling and input validation");
}
if (avgExecutionTime > 30) {
suggestions.push("Long execution time - check for bottlenecks or inefficient operations");
}
if (nodeTypes.has("n8n-nodes-base.httpRequest") && !nodeTypes.has("n8n-nodes-base.errorTrigger")) {
suggestions.push("HTTP requests without error handling - consider adding error triggers");
}
analysisResults.push({
id: workflow.id,
name: workflow.name,
nodeCount,
errorRate,
avgExecutionTime,
suggestions
});
}
// Format and present the analysis
let response = "# Workflow Analysis and Optimization Suggestions\n\n";
analysisResults.forEach(result => {
response += `## ${result.name}\n\n`;
response += `**Nodes:** ${result.nodeCount}\n`;
response += `**Error Rate:** ${(result.errorRate * 100).toFixed(1)}%\n`;
response += `**Avg. Execution Time:** ${result.avgExecutionTime.toFixed(1)} seconds\n\n`;
if (result.suggestions.length > 0) {
response += "**Optimization Suggestions:**\n";
result.suggestions.forEach(suggestion => {
response += `- ${suggestion}\n`;
});
} else {
response += "No specific optimization suggestions for this workflow.\n";
}
response += "\n";
});
return response;
```
## Scheduled Workflow Management
### User Prompt
"Update all my scheduled workflows to run one hour later."
### Assistant Actions
```javascript
// Get all workflows
const workflows = await useMcpTool('n8n-mcp-server', 'workflow_list', {});
// Filter for scheduled workflows (those with a Schedule node)
const scheduledWorkflows = [];
for (const workflow of workflows) {
// Get detailed workflow information
const details = await useMcpTool('n8n-mcp-server', 'workflow_get', {
id: workflow.id
});
// Look for Schedule Trigger nodes
const scheduleNodes = details.nodes.filter(node =>
node.type === "n8n-nodes-base.scheduleTrigger" ||
node.type === "n8n-nodes-base.cron"
);
if (scheduleNodes.length > 0) {
scheduledWorkflows.push({
workflow: details,
scheduleNodes
});
}
}
if (scheduledWorkflows.length === 0) {
return "I couldn't find any workflows with scheduled triggers.";
}
// Process each scheduled workflow
const results = [];
for (const { workflow, scheduleNodes } of scheduledWorkflows) {
// Create a copy of the workflow for modification
const updatedWorkflow = { ...workflow };
// Update each schedule node
for (const scheduleNode of scheduleNodes) {
const nodeIndex = updatedWorkflow.nodes.findIndex(n => n.id === scheduleNode.id);
if (nodeIndex === -1) continue;
// Copy the node for modification
const updatedNode = { ...updatedWorkflow.nodes[nodeIndex] };
// Handle different types of schedule configurations
if (updatedNode.type === "n8n-nodes-base.scheduleTrigger") {
if (updatedNode.parameters.cronExpression) {
// Modify cron expression to run 1 hour later
const cronParts = updatedNode.parameters.cronExpression.split(' ');
if (cronParts.length === 5) {
// Standard cron format: minute hour day month dayOfWeek
const hour = parseInt(cronParts[1], 10);
cronParts[1] = ((hour + 1) % 24).toString();
updatedNode.parameters.cronExpression = cronParts.join(' ');
}
} else if (updatedNode.parameters.timeToRepeat) {
// Handle specific time scheduling
const time = updatedNode.parameters.timeToRepeat;
if (time && time.split(':').length === 2) {
const [hours, minutes] = time.split(':').map(part => parseInt(part, 10));
const newHours = (hours + 1) % 24;
updatedNode.parameters.timeToRepeat = `${newHours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`;
}
}
} else if (updatedNode.type === "n8n-nodes-base.cron") {
// Similar handling for cron node
if (updatedNode.parameters.cronExpression) {
const cronParts = updatedNode.parameters.cronExpression.split(' ');
if (cronParts.length === 5) {
const hour = parseInt(cronParts[1], 10);
cronParts[1] = ((hour + 1) % 24).toString();
updatedNode.parameters.cronExpression = cronParts.join(' ');
}
}
}
// Update the node in the workflow
updatedWorkflow.nodes[nodeIndex] = updatedNode;
}
// Save the updated workflow
const result = await useMcpTool('n8n-mcp-server', 'workflow_update', {
id: workflow.id,
nodes: updatedWorkflow.nodes,
connections: updatedWorkflow.connections
});
results.push({
name: workflow.name,
updated: result.updatedAt
});
}
// Format and present the results
let response = "# Updated Scheduled Workflows\n\n";
response += "I've updated the following workflows to run one hour later:\n\n";
results.forEach(result => {
response += `- **${result.name}** (Updated: ${new Date(result.updated).toLocaleString()})\n`;
});
return response;
```
## Error Handling and Notification System
### User Prompt
"Set up a notification system for any workflow that fails."
### Assistant Actions
```javascript
// This scenario demonstrates creating a monitoring workflow that checks for failures
// and sends notifications
// First, check if a monitoring workflow already exists
const workflows = await useMcpTool('n8n-mcp-server', 'workflow_list', {});
const existingMonitor = workflows.find(workflow =>
workflow.name.toLowerCase().includes('workflow monitor') ||
workflow.name.toLowerCase().includes('error notification')
);
if (existingMonitor) {
return `You already have a monitoring workflow: "${existingMonitor.name}" (ID: ${existingMonitor.id}). Would you like me to update it instead?`;
}
// Create a new monitoring workflow
const monitorWorkflow = await useMcpTool('n8n-mcp-server', 'workflow_create', {
name: "Workflow Error Notification System",
active: false, // Start inactive until configured
nodes: [
{
name: "Schedule Trigger",
type: "n8n-nodes-base.scheduleTrigger",
position: [100, 300],
parameters: {
cronExpression: "*/15 * * * *" // Run every 15 minutes
}
},
{
name: "Get Failed Executions",
type: "n8n-nodes-base.n8n",
position: [300, 300],
parameters: {
resource: "execution",
operation: "getAll",
filters: {
status: "error",
// Look for executions in the last 15 minutes
finished: {
$gt: "={{$now.minus({ minutes: 15 }).toISOString()}}"
}
}
}
},
{
name: "Filter Empty",
type: "n8n-nodes-base.filter",
position: [500, 300],
parameters: {
conditions: {
boolean: [
{
value1: "={{ $json.length > 0 }}",
operation: "equal",
value2: true
}
]
}
}
},
{
name: "Format Notification",
type: "n8n-nodes-base.function",
position: [700, 300],
parameters: {
functionCode: `
// Function to format error notifications
const executions = items;
const now = new Date();
// Group by workflow
const workflowErrors = {};
for (const execution of executions) {
const workflowId = execution.workflowId;
const workflowName = execution.workflowData.name;
if (!workflowErrors[workflowId]) {
workflowErrors[workflowId] = {
name: workflowName,
errors: []
};
}
workflowErrors[workflowId].errors.push({
id: execution.id,
time: execution.finished,
error: execution.error?.message || "Unknown error"
});
}
// Create notification text
let notificationText = "⚠️ Workflow Error Alert ⚠️\\n\\n";
notificationText += "The following workflows have failed:\\n\\n";
for (const [workflowId, data] of Object.entries(workflowErrors)) {
notificationText += \`👉 \${data.name} (ID: \${workflowId})\\n\`;
notificationText += \` Failed executions: \${data.errors.length}\\n\`;
// Add details about each failure
data.errors.forEach(error => {
const time = new Date(error.time).toLocaleString();
notificationText += \` - \${time}: \${error.error}\\n\`;
});
notificationText += "\\n";
}
notificationText += "Check your n8n dashboard for more details.";
return [{
json: {
text: notificationText,
subject: \`n8n Alert: \${Object.keys(workflowErrors).length} Workflow(s) Failed\`,
timestamp: now.toISOString()
}
}];
`
}
},
{
name: "Send Email",
type: "n8n-nodes-base.emailSend",
position: [900, 300],
parameters: {
to: "{{$env.EMAIL_RECIPIENT}}", // Will need to be configured
subject: "{{$json.subject}}",
text: "{{$json.text}}"
}
}
],
connections: {
"Schedule Trigger": {
main: [
[
{
node: "Get Failed Executions",
type: "main",
index: 0
}
]
]
},
"Get Failed Executions": {
main: [
[
{
node: "Filter Empty",
type: "main",
index: 0
}
]
]
},
"Filter Empty": {
main: [
[
{
node: "Format Notification",
type: "main",
index: 0
}
]
]
},
"Format Notification": {
main: [
[
{
node: "Send Email",
type: "main",
index: 0
}
]
]
}
}
});
return `
# Workflow Error Notification System Created
I've created a new workflow that will monitor for failed executions and send email notifications.
**Workflow ID:** ${monitorWorkflow.id}
## Configuration Needed:
1. The workflow is currently **inactive** - you'll need to activate it once configured
2. Set up the email configuration in n8n settings
3. Configure the "Send Email" node with your recipient email address
## How It Works:
- Runs every 15 minutes
- Checks for any workflows that failed in the last 15 minutes
- Groups failures by workflow and formats a notification
- Sends an email with details about the failures
You can customize the notification format, schedule, and notification method by editing the workflow in the n8n interface.
`;
```
## Data Migration Between Workflows
### User Prompt
"Help me move data from my 'Legacy CRM' workflow to my 'New CRM' workflow."
### Assistant Actions
```javascript
// Get all workflows
const workflows = await useMcpTool('n8n-mcp-server', 'workflow_list', {});
// Find the source and target workflows
const legacyWorkflow = workflows.find(w => w.name.toLowerCase().includes('legacy crm'));
const newWorkflow = workflows.find(w => w.name.toLowerCase().includes('new crm'));
if (!legacyWorkflow) {
return "I couldn't find a workflow with 'Legacy CRM' in the name. Please check the exact name of your source workflow.";
}
if (!newWorkflow) {
return "I couldn't find a workflow with 'New CRM' in the name. Please check the exact name of your target workflow.";
}
// Create a data migration workflow
const migrationWorkflow = await useMcpTool('n8n-mcp-server', 'workflow_create', {
name: "Data Migration: Legacy CRM to New CRM",
active: false, // Start inactive until confirmed
nodes: [
{
name: "Manual Trigger",
type: "n8n-nodes-base.manualTrigger",
position: [100, 300],
parameters: {}
},
{
name: "Execute Legacy Workflow",
type: "n8n-nodes-base.executeWorkflow",
position: [300, 300],
parameters: {
workflowId: legacyWorkflow.id,
options: {
includeData: true
}
}
},
{
name: "Transform Data",
type: "n8n-nodes-base.function",
position: [500, 300],
parameters: {
functionCode: `
// This is a placeholder transformation function that you'll need to customize
// based on the actual data structure of your workflows
const legacyData = items;
const transformedItems = [];
// Example transformation (modify based on your data structures)
for (const item of legacyData) {
transformedItems.push({
json: {
// Map legacy fields to new fields
customer_id: item.json.id,
customer_name: item.json.fullName || \`\${item.json.firstName || ''} \${item.json.lastName || ''}\`.trim(),
email: item.json.emailAddress || item.json.email,
phone: item.json.phoneNumber || item.json.phone,
notes: item.json.comments || item.json.notes || '',
// Add migration metadata
migrated_from_legacy: true,
migration_date: new Date().toISOString()
}
});
}
return transformedItems;
`
}
},
{
name: "Execute New Workflow",
type: "n8n-nodes-base.executeWorkflow",
position: [700, 300],
parameters: {
workflowId: newWorkflow.id,
options: {
includeData: true
}
}
},
{
name: "Migration Summary",
type: "n8n-nodes-base.function",
position: [900, 300],
parameters: {
functionCode: `
// Create a summary of the migration
const results = items;
const totalItems = items.length;
const successItems = items.filter(item => !item.json.error).length;
const errorItems = totalItems - successItems;
return [
{
json: {
summary: "Migration Complete",
total_records: totalItems,
successful_records: successItems,
failed_records: errorItems,
completion_time: new Date().toISOString()
}
}
];
`
}
}
],
connections: {
"Manual Trigger": {
main: [
[
{
node: "Execute Legacy Workflow",
type: "main",
index: 0
}
]
]
},
"Execute Legacy Workflow": {
main: [
[
{
node: "Transform Data",
type: "main",
index: 0
}
]
]
},
"Transform Data": {
main: [
[
{
node: "Execute New Workflow",
type: "main",
index: 0
}
]
]
},
"Execute New Workflow": {
main: [
[
{
node: "Migration Summary",
type: "main",
index: 0
}
]
]
}
}
});
return `
# Data Migration Workflow Created
I've created a new workflow to migrate data from "${legacyWorkflow.name}" to "${newWorkflow.name}".
**Migration Workflow ID:** ${migrationWorkflow.id}
## Important Notes:
1. The workflow is currently **inactive** - activate it only when you're ready to perform the migration
2. The data transformation is a placeholder - you'll need to edit the "Transform Data" function node to map fields correctly based on your specific data structures
3. This is a one-time migration workflow - run it manually when you're ready to migrate the data
## Next Steps:
1. Open the workflow in the n8n interface
2. Edit the "Transform Data" function to correctly map your data fields
3. Test the workflow with a small sample if possible
4. Activate and run the workflow to perform the migration
5. Check the migration summary for results
Would you like me to help you customize the data transformation based on the specific fields in your CRM workflows?
`;
```
These examples demonstrate more advanced usage patterns for the n8n MCP Server. For integration with other systems, see the [Integration Examples](./integration-examples.md) page.

View File

@@ -0,0 +1,258 @@
# Basic Examples
This page provides basic examples of using the n8n MCP Server with AI assistants.
## Listing Workflows
### User Prompt
"Show me all the workflows in my n8n instance."
### Assistant Actions
```javascript
// The assistant uses the workflow_list tool
const result = await useMcpTool('n8n-mcp-server', 'workflow_list', {});
// The assistant formats and presents the results
if (result.length === 0) {
return "You don't have any workflows in your n8n instance yet.";
} else {
let response = "Here are your workflows:\n\n";
result.forEach(workflow => {
response += `- ${workflow.name} (ID: ${workflow.id}) - ${workflow.active ? 'Active' : 'Inactive'}\n`;
});
return response;
}
```
## Getting Workflow Details
### User Prompt
"Tell me about my 'Email Processing' workflow."
### Assistant Actions
```javascript
// First list all workflows to find the one with matching name
const workflows = await useMcpTool('n8n-mcp-server', 'workflow_list', {});
// Find the workflow with a name containing "Email Processing"
const emailWorkflow = workflows.find(workflow =>
workflow.name.toLowerCase().includes('email processing')
);
if (!emailWorkflow) {
return "I couldn't find a workflow named 'Email Processing'. Would you like to see a list of all your workflows?";
}
// Get detailed information about the workflow
const details = await useMcpTool('n8n-mcp-server', 'workflow_get', {
id: emailWorkflow.id
});
// Format and present the workflow details
return `
# Email Processing Workflow
**Status:** ${details.active ? 'Active' : 'Inactive'}
**Created:** ${new Date(details.createdAt).toLocaleString()}
**Last Updated:** ${new Date(details.updatedAt).toLocaleString()}
## Nodes (${details.nodes.length})
${details.nodes.map(node => `- ${node.name} (${node.type})`).join('\n')}
## Settings
${Object.entries(details.settings || {}).map(([key, value]) => `- ${key}: ${value}`).join('\n')}
`;
```
## Executing a Workflow
### User Prompt
"Run my 'Data Sync' workflow."
### Assistant Actions
```javascript
// First list all workflows to find the one with matching name
const workflows = await useMcpTool('n8n-mcp-server', 'workflow_list', {});
// Find the workflow with a name containing "Data Sync"
const syncWorkflow = workflows.find(workflow =>
workflow.name.toLowerCase().includes('data sync')
);
if (!syncWorkflow) {
return "I couldn't find a workflow named 'Data Sync'. Would you like to see a list of all your workflows?";
}
// Check if the workflow is active
if (!syncWorkflow.active) {
return "The 'Data Sync' workflow is currently inactive. Would you like me to activate it before running it?";
}
// Execute the workflow
const execution = await useMcpTool('n8n-mcp-server', 'execution_run', {
workflowId: syncWorkflow.id
});
return `
I've started the 'Data Sync' workflow.
**Execution ID:** ${execution.executionId}
**Status:** ${execution.status}
**Started At:** ${new Date(execution.startedAt).toLocaleString()}
You can check the execution status later by asking me about it.
`;
```
## Checking Execution Status
### User Prompt
"Check the status of my last workflow execution."
### Assistant Actions
```javascript
// Get recent executions (this example assumes we've stored the last execution ID in context)
// In a real scenario, you might need to list recent executions first
const lastExecutionId = "exec123"; // In practice, this would come from context or a previous response
// Get execution details
const execution = await useMcpTool('n8n-mcp-server', 'execution_get', {
executionId: lastExecutionId
});
// Format and present the execution status
let response = `
# Execution Status for ${execution.workflowName}
**Status:** ${execution.status}
**Started:** ${new Date(execution.startedAt).toLocaleString()}
`;
if (execution.finishedAt) {
response += `**Finished:** ${new Date(execution.finishedAt).toLocaleString()}\n`;
response += `**Duration:** ${Math.round((new Date(execution.finishedAt) - new Date(execution.startedAt)) / 1000)} seconds\n`;
}
response += "\n## Execution Path\n";
execution.data.executionData.nodeExecutionOrder.forEach(nodeName => {
response += `- ${nodeName}\n`;
});
return response;
```
## Activating/Deactivating a Workflow
### User Prompt
"Deactivate my 'Daily Report' workflow."
### Assistant Actions
```javascript
// First list all workflows to find the one with matching name
const workflows = await useMcpTool('n8n-mcp-server', 'workflow_list', {});
// Find the workflow with a name containing "Daily Report"
const reportWorkflow = workflows.find(workflow =>
workflow.name.toLowerCase().includes('daily report')
);
if (!reportWorkflow) {
return "I couldn't find a workflow named 'Daily Report'. Would you like to see a list of all your workflows?";
}
// Check if the workflow is already inactive
if (!reportWorkflow.active) {
return "The 'Daily Report' workflow is already inactive.";
}
// Deactivate the workflow
const result = await useMcpTool('n8n-mcp-server', 'workflow_deactivate', {
id: reportWorkflow.id
});
return `
I've deactivated the 'Daily Report' workflow.
It was last updated on ${new Date(result.updatedAt).toLocaleString()}.
You can reactivate it at any time by asking me to activate it.
`;
```
## Creating a Simple Workflow
### User Prompt
"Create a new workflow that sends me a daily email reminder."
### Assistant Actions
```javascript
// Create a new workflow
const newWorkflow = await useMcpTool('n8n-mcp-server', 'workflow_create', {
name: "Daily Email Reminder",
active: false, // Start inactive until it's configured properly
nodes: [
{
name: "Schedule Trigger",
type: "n8n-nodes-base.scheduleTrigger",
position: [100, 300],
parameters: {
rule: {
interval: [
{
field: "hours",
minuteInterval: 24
}
]
}
}
},
{
name: "Send Email",
type: "n8n-nodes-base.emailSend",
position: [300, 300],
parameters: {
to: "{{$json.email}}",
subject: "Daily Reminder",
text: "This is your daily reminder!"
}
}
],
connections: {
"Schedule Trigger": {
main: [
[
{
node: "Send Email",
type: "main",
index: 0
}
]
]
}
}
});
return `
I've created a new workflow called "Daily Email Reminder".
This workflow is currently **inactive** and needs configuration:
1. You'll need to enter your email address in the "Send Email" node
2. You might want to customize the schedule and email content
You can view and edit this workflow in the n8n interface (ID: ${newWorkflow.id}), and then ask me to activate it when you're ready.
`;
```
These examples demonstrate the basic operations you can perform with the n8n MCP Server. For more complex scenarios, see the [Advanced Scenarios](./advanced-scenarios.md) page.

22
docs/examples/index.md Normal file
View File

@@ -0,0 +1,22 @@
# Usage Examples
This section provides practical examples of using the n8n MCP Server with AI assistants.
## Overview
The examples in this section demonstrate how AI assistants can interact with n8n workflows through the MCP server. They range from basic operations to complex integration scenarios.
## Examples Categories
- [Basic Examples](./basic-examples.md): Simple examples covering fundamental operations like listing workflows, retrieving workflow details, and executing workflows.
- [Advanced Scenarios](./advanced-scenarios.md): More complex examples showing how to chain operations, handle errors, and implement common workflow patterns.
- [Integration Examples](./integration-examples.md): Examples of integrating the n8n MCP Server with different AI assistant platforms and other tools.
## How to Use These Examples
The examples in this section show both:
1. **User Prompts**: What a user might ask an AI assistant to do
2. **Assistant Actions**: How the assistant would use the MCP tools and resources to accomplish the task
You can use these examples as inspiration for your own interactions with the n8n MCP Server or as templates for building more complex workflows.

File diff suppressed because it is too large Load Diff