A Model Context Protocol (MCP) server that integrates with n8n, providing tools for workflow and execution management via the n8n API.
2116 lines
52 KiB
Markdown
2116 lines
52 KiB
Markdown
# Integration Examples
|
|
|
|
This page provides examples of integrating the n8n MCP Server with other systems and AI assistant platforms.
|
|
|
|
## AI Assistant Integration Examples
|
|
|
|
### Claude AI Assistant Integration
|
|
|
|
#### Example: Setting Up n8n MCP Server with Claude
|
|
|
|
```javascript
|
|
// Register the n8n MCP Server with Claude using the MCP Installer
|
|
const installationResult = await useMcpTool('mcp-installer', 'install_repo_mcp_server', {
|
|
name: 'n8n-mcp-server',
|
|
env: [
|
|
"N8N_API_URL=http://localhost:5678/api/v1",
|
|
"N8N_API_KEY=your_n8n_api_key_here",
|
|
"DEBUG=false"
|
|
]
|
|
});
|
|
|
|
// Once registered, Claude can interact with n8n
|
|
// Here's an example conversation:
|
|
|
|
// User: "Show me my active workflows in n8n"
|
|
// Claude: (uses workflow_list tool to retrieve and display active workflows)
|
|
|
|
// User: "Execute my 'Daily Report' workflow"
|
|
// Claude: (uses execution_run tool to start the workflow and provide status)
|
|
```
|
|
|
|
#### Example: Using n8n to Extend Claude's Capabilities
|
|
|
|
```javascript
|
|
// Using n8n as a bridge to external systems
|
|
// This example shows how Claude can access a database through n8n
|
|
|
|
// User: "Show me the top 5 customers from my database"
|
|
// Claude would:
|
|
|
|
// 1. Find the appropriate workflow
|
|
const workflows = await useMcpTool('n8n-mcp-server', 'workflow_list', {});
|
|
const dbQueryWorkflow = workflows.find(w =>
|
|
w.name.toLowerCase().includes('database query') ||
|
|
w.name.toLowerCase().includes('db query')
|
|
);
|
|
|
|
if (!dbQueryWorkflow) {
|
|
return "I couldn't find a database query workflow. Would you like me to help you create one?";
|
|
}
|
|
|
|
// 2. Execute the workflow with the appropriate parameters
|
|
const execution = await useMcpTool('n8n-mcp-server', 'execution_run', {
|
|
workflowId: dbQueryWorkflow.id,
|
|
data: {
|
|
query: "SELECT * FROM customers ORDER BY total_purchases DESC LIMIT 5",
|
|
format: "table"
|
|
},
|
|
waitForCompletion: true
|
|
});
|
|
|
|
// 3. Present the results to the user
|
|
if (execution.status !== "success") {
|
|
return "There was an error querying the database. Error: " + (execution.error || "Unknown error");
|
|
}
|
|
|
|
// Format the results as a table
|
|
const customers = execution.data.resultData.runData.lastNode[0].data.json;
|
|
let response = "# Top 5 Customers\n\n";
|
|
response += "| Customer Name | Email | Total Purchases |\n";
|
|
response += "|--------------|-------|----------------|\n";
|
|
|
|
customers.forEach(customer => {
|
|
response += `| ${customer.name} | ${customer.email} | $${customer.total_purchases.toFixed(2)} |\n`;
|
|
});
|
|
|
|
return response;
|
|
```
|
|
|
|
### OpenAI Assistant Integration
|
|
|
|
#### Example: Connecting n8n MCP Server to OpenAI Assistant
|
|
|
|
```javascript
|
|
// This is a conceptual example of how an OpenAI Assistant might interact with the n8n MCP Server
|
|
|
|
// In an OpenAI Assistant Function definition:
|
|
{
|
|
"name": "n8n_workflow_list",
|
|
"description": "List all workflows in n8n",
|
|
"parameters": {
|
|
"type": "object",
|
|
"properties": {
|
|
"active": {
|
|
"type": "boolean",
|
|
"description": "Filter by active status (optional)"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// The function would call the n8n MCP Server:
|
|
async function n8n_workflow_list(params) {
|
|
// Call the n8n MCP Server API
|
|
const response = await fetch('http://localhost:3000/n8n-mcp/tools/workflow_list', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'Authorization': 'Bearer YOUR_AUTH_TOKEN'
|
|
},
|
|
body: JSON.stringify(params)
|
|
});
|
|
|
|
return await response.json();
|
|
}
|
|
|
|
// The OpenAI Assistant would then use this function when asked about n8n workflows
|
|
```
|
|
|
|
## Integration with External Systems
|
|
|
|
### n8n to Git Integration
|
|
|
|
#### Example: Using n8n MCP Server to Manage Workflow Versioning in Git
|
|
|
|
```javascript
|
|
// User request: "Backup all my workflows to my Git repository"
|
|
|
|
// The assistant first creates a workflow for Git backup
|
|
const backupWorkflow = await useMcpTool('n8n-mcp-server', 'workflow_create', {
|
|
name: "Workflow Git Backup",
|
|
active: false,
|
|
nodes: [
|
|
{
|
|
name: "Manual Trigger",
|
|
type: "n8n-nodes-base.manualTrigger",
|
|
position: [100, 300],
|
|
parameters: {}
|
|
},
|
|
{
|
|
name: "Get All Workflows",
|
|
type: "n8n-nodes-base.n8n",
|
|
position: [300, 300],
|
|
parameters: {
|
|
resource: "workflow",
|
|
operation: "getAll"
|
|
}
|
|
},
|
|
{
|
|
name: "Format For Git",
|
|
type: "n8n-nodes-base.function",
|
|
position: [500, 300],
|
|
parameters: {
|
|
functionCode: `
|
|
// Convert workflows to individual JSON files
|
|
const workflows = items;
|
|
const outputItems = [];
|
|
|
|
for (const workflow of workflows) {
|
|
// Create a sanitized filename
|
|
const filename = workflow.json.name
|
|
.replace(/[^a-zA-Z0-9]/g, '_')
|
|
.toLowerCase() + '.json';
|
|
|
|
outputItems.push({
|
|
json: {
|
|
filename: filename,
|
|
content: JSON.stringify(workflow.json, null, 2),
|
|
commit_message: \`Backup workflow: \${workflow.json.name}\`
|
|
}
|
|
});
|
|
}
|
|
|
|
return outputItems;
|
|
`
|
|
}
|
|
},
|
|
{
|
|
name: "Git Commit",
|
|
type: "n8n-nodes-base.git",
|
|
position: [700, 300],
|
|
parameters: {
|
|
repository: "{{$env.GIT_REPO_PATH}}",
|
|
directory: "workflows",
|
|
operation: "commit",
|
|
message: "Automated workflow backup {{$now.format('YYYY-MM-DD HH:mm')}}",
|
|
filePath: "={{$json.filename}}",
|
|
fileContent: "={{$json.content}}"
|
|
}
|
|
},
|
|
{
|
|
name: "Git Push",
|
|
type: "n8n-nodes-base.git",
|
|
position: [900, 300],
|
|
parameters: {
|
|
repository: "{{$env.GIT_REPO_PATH}}",
|
|
operation: "push"
|
|
}
|
|
}
|
|
],
|
|
connections: {
|
|
"Manual Trigger": {
|
|
main: [
|
|
[
|
|
{
|
|
node: "Get All Workflows",
|
|
type: "main",
|
|
index: 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Get All Workflows": {
|
|
main: [
|
|
[
|
|
{
|
|
node: "Format For Git",
|
|
type: "main",
|
|
index: 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Format For Git": {
|
|
main: [
|
|
[
|
|
{
|
|
node: "Git Commit",
|
|
type: "main",
|
|
index: 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Git Commit": {
|
|
main: [
|
|
[
|
|
{
|
|
node: "Git Push",
|
|
type: "main",
|
|
index: 0
|
|
}
|
|
]
|
|
]
|
|
}
|
|
}
|
|
});
|
|
|
|
return `
|
|
# Git Backup Workflow Created
|
|
|
|
I've created a new workflow that will backup all your n8n workflows to Git.
|
|
|
|
**Workflow ID:** ${backupWorkflow.id}
|
|
|
|
## Configuration Needed:
|
|
1. The workflow is currently **inactive** - activate it once configured
|
|
2. Set the environment variable \`GIT_REPO_PATH\` to point to your Git repository
|
|
3. Ensure the Git repository is properly configured with credentials
|
|
|
|
## How It Works:
|
|
- When executed, this workflow retrieves all n8n workflows
|
|
- Converts each workflow to a JSON file
|
|
- Commits each file to the specified Git repository
|
|
- Pushes the changes to the remote repository
|
|
|
|
## Usage:
|
|
You can run this workflow manually whenever you want to backup your workflows,
|
|
or add a Schedule Trigger to automate regular backups.
|
|
`;
|
|
```
|
|
|
|
### CRM Integration
|
|
|
|
#### Example: Setting Up a Two-Way Sync Between n8n and a CRM
|
|
|
|
```javascript
|
|
// User request: "Help me set up a sync between n8n and my HubSpot CRM"
|
|
|
|
// First check for existing credentials
|
|
const workflows = await useMcpTool('n8n-mcp-server', 'workflow_list', {});
|
|
const hubspotWorkflows = workflows.filter(w =>
|
|
w.name.toLowerCase().includes('hubspot')
|
|
);
|
|
|
|
let credentialsMessage = "";
|
|
if (hubspotWorkflows.length > 0) {
|
|
credentialsMessage = "I noticed you already have HubSpot workflows. I'll assume you have HubSpot credentials set up.";
|
|
} else {
|
|
credentialsMessage = "You'll need to set up HubSpot credentials in n8n before activating this workflow.";
|
|
}
|
|
|
|
// Create the sync workflow
|
|
const syncWorkflow = await useMcpTool('n8n-mcp-server', 'workflow_create', {
|
|
name: "HubSpot Two-Way Sync",
|
|
active: false,
|
|
nodes: [
|
|
{
|
|
name: "Schedule Trigger",
|
|
type: "n8n-nodes-base.scheduleTrigger",
|
|
position: [100, 300],
|
|
parameters: {
|
|
cronExpression: "0 */2 * * *" // Every 2 hours
|
|
}
|
|
},
|
|
{
|
|
name: "Get HubSpot Contacts",
|
|
type: "n8n-nodes-base.hubspot",
|
|
position: [300, 200],
|
|
parameters: {
|
|
resource: "contact",
|
|
operation: "getAll",
|
|
returnAll: true,
|
|
additionalFields: {
|
|
formattedDate: true
|
|
}
|
|
}
|
|
},
|
|
{
|
|
name: "Get n8n Contacts",
|
|
type: "n8n-nodes-base.function",
|
|
position: [300, 400],
|
|
parameters: {
|
|
functionCode: `
|
|
// This function would retrieve contacts from your internal database
|
|
// For example purposes, we're using a placeholder
|
|
// In reality, you might use another n8n node to fetch from your database
|
|
|
|
return [
|
|
{
|
|
json: {
|
|
internalContacts: [
|
|
// Example internal contacts
|
|
// In a real scenario, these would come from your database
|
|
]
|
|
}
|
|
}
|
|
];
|
|
`
|
|
}
|
|
},
|
|
{
|
|
name: "Compare & Identify Changes",
|
|
type: "n8n-nodes-base.function",
|
|
position: [500, 300],
|
|
parameters: {
|
|
functionCode: `
|
|
const hubspotContacts = $input.first();
|
|
const internalContacts = $input.last().json.internalContacts;
|
|
|
|
// Identify new/updated contacts in HubSpot
|
|
const hubspotUpdates = hubspotContacts.json.map(contact => {
|
|
// Find matching internal contact by email
|
|
const internalMatch = internalContacts.find(
|
|
ic => ic.email === contact.properties.email
|
|
);
|
|
|
|
if (!internalMatch) {
|
|
return {
|
|
json: {
|
|
type: 'new_in_hubspot',
|
|
contact: contact,
|
|
action: 'create_in_internal'
|
|
}
|
|
};
|
|
}
|
|
|
|
// Check if HubSpot contact is newer
|
|
const hubspotUpdated = new Date(contact.properties.lastmodifieddate);
|
|
const internalUpdated = new Date(internalMatch.updated_at);
|
|
|
|
if (hubspotUpdated > internalUpdated) {
|
|
return {
|
|
json: {
|
|
type: 'updated_in_hubspot',
|
|
contact: contact,
|
|
action: 'update_in_internal'
|
|
}
|
|
};
|
|
}
|
|
|
|
return null;
|
|
}).filter(item => item !== null);
|
|
|
|
// Identify new/updated contacts in internal system
|
|
const internalUpdates = internalContacts.map(contact => {
|
|
// Find matching HubSpot contact by email
|
|
const hubspotMatch = hubspotContacts.json.find(
|
|
hc => hc.properties.email === contact.email
|
|
);
|
|
|
|
if (!hubspotMatch) {
|
|
return {
|
|
json: {
|
|
type: 'new_in_internal',
|
|
contact: contact,
|
|
action: 'create_in_hubspot'
|
|
}
|
|
};
|
|
}
|
|
|
|
// Check if internal contact is newer
|
|
const internalUpdated = new Date(contact.updated_at);
|
|
const hubspotUpdated = new Date(hubspotMatch.properties.lastmodifieddate);
|
|
|
|
if (internalUpdated > hubspotUpdated) {
|
|
return {
|
|
json: {
|
|
type: 'updated_in_internal',
|
|
contact: contact,
|
|
action: 'update_in_hubspot'
|
|
}
|
|
};
|
|
}
|
|
|
|
return null;
|
|
}).filter(item => item !== null);
|
|
|
|
// Combine all changes
|
|
return [...hubspotUpdates, ...internalUpdates];
|
|
`
|
|
}
|
|
},
|
|
{
|
|
name: "Route Updates",
|
|
type: "n8n-nodes-base.switch",
|
|
position: [700, 300],
|
|
parameters: {
|
|
rules: {
|
|
conditions: [
|
|
{
|
|
value1: "={{$json.action}}",
|
|
operation: "equal",
|
|
value2: "update_in_hubspot"
|
|
},
|
|
{
|
|
value1: "={{$json.action}}",
|
|
operation: "equal",
|
|
value2: "create_in_hubspot"
|
|
},
|
|
{
|
|
value1: "={{$json.action}}",
|
|
operation: "equal",
|
|
value2: "update_in_internal"
|
|
},
|
|
{
|
|
value1: "={{$json.action}}",
|
|
operation: "equal",
|
|
value2: "create_in_internal"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
},
|
|
{
|
|
name: "Update HubSpot Contact",
|
|
type: "n8n-nodes-base.hubspot",
|
|
position: [900, 100],
|
|
parameters: {
|
|
resource: "contact",
|
|
operation: "update",
|
|
contactId: "={{$json.contact.hubspot_id || $json.hubspotId}}",
|
|
additionalFields: {
|
|
properties: {
|
|
firstname: "={{$json.contact.first_name}}",
|
|
lastname: "={{$json.contact.last_name}}",
|
|
email: "={{$json.contact.email}}",
|
|
phone: "={{$json.contact.phone}}",
|
|
// Add additional fields as needed
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
name: "Create HubSpot Contact",
|
|
type: "n8n-nodes-base.hubspot",
|
|
position: [900, 250],
|
|
parameters: {
|
|
resource: "contact",
|
|
operation: "create",
|
|
additionalFields: {
|
|
properties: {
|
|
firstname: "={{$json.contact.first_name}}",
|
|
lastname: "={{$json.contact.last_name}}",
|
|
email: "={{$json.contact.email}}",
|
|
phone: "={{$json.contact.phone}}",
|
|
// Add additional fields as needed
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
name: "Update Internal Contact",
|
|
type: "n8n-nodes-base.function",
|
|
position: [900, 400],
|
|
parameters: {
|
|
functionCode: `
|
|
// This function would update contacts in your internal database
|
|
// In reality, you might use another n8n node like a database connector
|
|
const contact = $input.first().json.contact;
|
|
|
|
// Process the HubSpot contact into internal format
|
|
const internalFormat = {
|
|
first_name: contact.properties.firstname,
|
|
last_name: contact.properties.lastname,
|
|
email: contact.properties.email,
|
|
phone: contact.properties.phone,
|
|
hubspot_id: contact.id,
|
|
updated_at: new Date().toISOString()
|
|
};
|
|
|
|
// In a real implementation, you would update your database
|
|
// For this example, we just return what would be updated
|
|
return [{
|
|
json: {
|
|
action: "updated_internal_contact",
|
|
contact: internalFormat
|
|
}
|
|
}];
|
|
`
|
|
}
|
|
},
|
|
{
|
|
name: "Create Internal Contact",
|
|
type: "n8n-nodes-base.function",
|
|
position: [900, 550],
|
|
parameters: {
|
|
functionCode: `
|
|
// This function would create new contacts in your internal database
|
|
// In reality, you might use another n8n node like a database connector
|
|
const contact = $input.first().json.contact;
|
|
|
|
// Process the HubSpot contact into internal format
|
|
const internalFormat = {
|
|
first_name: contact.properties.firstname,
|
|
last_name: contact.properties.lastname,
|
|
email: contact.properties.email,
|
|
phone: contact.properties.phone,
|
|
hubspot_id: contact.id,
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString()
|
|
};
|
|
|
|
// In a real implementation, you would insert into your database
|
|
// For this example, we just return what would be created
|
|
return [{
|
|
json: {
|
|
action: "created_internal_contact",
|
|
contact: internalFormat
|
|
}
|
|
}];
|
|
`
|
|
}
|
|
},
|
|
{
|
|
name: "Sync Report",
|
|
type: "n8n-nodes-base.function",
|
|
position: [1100, 300],
|
|
parameters: {
|
|
functionCode: `
|
|
// Collect all results from previous nodes
|
|
const updateHubspot = $input.itemsFrom('Update HubSpot Contact');
|
|
const createHubspot = $input.itemsFrom('Create HubSpot Contact');
|
|
const updateInternal = $input.itemsFrom('Update Internal Contact');
|
|
const createInternal = $input.itemsFrom('Create Internal Contact');
|
|
|
|
// Generate sync summary
|
|
return [{
|
|
json: {
|
|
summary: "Sync Complete",
|
|
timestamp: new Date().toISOString(),
|
|
stats: {
|
|
hubspot_updated: updateHubspot.length,
|
|
hubspot_created: createHubspot.length,
|
|
internal_updated: updateInternal.length,
|
|
internal_created: createInternal.length,
|
|
total_changes: updateHubspot.length + createHubspot.length +
|
|
updateInternal.length + createInternal.length
|
|
}
|
|
}
|
|
}];
|
|
`
|
|
}
|
|
}
|
|
],
|
|
connections: {
|
|
"Schedule Trigger": {
|
|
main: [
|
|
[
|
|
{
|
|
node: "Get HubSpot Contacts",
|
|
type: "main",
|
|
index: 0
|
|
},
|
|
{
|
|
node: "Get n8n Contacts",
|
|
type: "main",
|
|
index: 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Get HubSpot Contacts": {
|
|
main: [
|
|
[
|
|
{
|
|
node: "Compare & Identify Changes",
|
|
type: "main",
|
|
index: 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Get n8n Contacts": {
|
|
main: [
|
|
[
|
|
{
|
|
node: "Compare & Identify Changes",
|
|
type: "main",
|
|
index: 1
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Compare & Identify Changes": {
|
|
main: [
|
|
[
|
|
{
|
|
node: "Route Updates",
|
|
type: "main",
|
|
index: 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Route Updates": {
|
|
main: [
|
|
[
|
|
{
|
|
node: "Update HubSpot Contact",
|
|
type: "main",
|
|
index: 0
|
|
}
|
|
],
|
|
[
|
|
{
|
|
node: "Create HubSpot Contact",
|
|
type: "main",
|
|
index: 0
|
|
}
|
|
],
|
|
[
|
|
{
|
|
node: "Update Internal Contact",
|
|
type: "main",
|
|
index: 0
|
|
}
|
|
],
|
|
[
|
|
{
|
|
node: "Create Internal Contact",
|
|
type: "main",
|
|
index: 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Update HubSpot Contact": {
|
|
main: [
|
|
[
|
|
{
|
|
node: "Sync Report",
|
|
type: "main",
|
|
index: 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Create HubSpot Contact": {
|
|
main: [
|
|
[
|
|
{
|
|
node: "Sync Report",
|
|
type: "main",
|
|
index: 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Update Internal Contact": {
|
|
main: [
|
|
[
|
|
{
|
|
node: "Sync Report",
|
|
type: "main",
|
|
index: 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Create Internal Contact": {
|
|
main: [
|
|
[
|
|
{
|
|
node: "Sync Report",
|
|
type: "main",
|
|
index: 0
|
|
}
|
|
]
|
|
]
|
|
}
|
|
}
|
|
});
|
|
|
|
return `
|
|
# HubSpot Two-Way Sync Workflow Created
|
|
|
|
I've created a new workflow that will synchronize contacts between HubSpot and your internal system.
|
|
|
|
**Workflow ID:** ${syncWorkflow.id}
|
|
|
|
## Configuration Needed:
|
|
1. The workflow is currently **inactive** - activate it once configured
|
|
2. ${credentialsMessage}
|
|
3. You'll need to customize the "Get n8n Contacts", "Update Internal Contact", and "Create Internal Contact" nodes to work with your specific database or storage system
|
|
|
|
## How It Works:
|
|
- Runs every 2 hours (configurable)
|
|
- Retrieves contacts from both HubSpot and your internal system
|
|
- Compares the data to identify new or updated contacts in either system
|
|
- Creates or updates contacts to keep both systems in sync
|
|
- Generates a sync report with statistics
|
|
|
|
## Customization:
|
|
You may need to modify the field mappings in the function nodes to match your specific data structure
|
|
and add any additional fields that need to be synchronized between the systems.
|
|
`;
|
|
```
|
|
|
|
### Slack Integration
|
|
|
|
#### Example: Creating a Workflow to Send n8n Notifications to Slack
|
|
|
|
```javascript
|
|
// User request: "Create a workflow that sends n8n execution notifications to Slack"
|
|
|
|
// Create the notification workflow
|
|
const notificationWorkflow = await useMcpTool('n8n-mcp-server', 'workflow_create', {
|
|
name: "n8n Execution Notifications to Slack",
|
|
active: false,
|
|
nodes: [
|
|
{
|
|
name: "Webhook",
|
|
type: "n8n-nodes-base.webhook",
|
|
position: [100, 300],
|
|
parameters: {
|
|
path: "n8n-notification",
|
|
responseMode: "onReceived",
|
|
options: {
|
|
responseData: "noData"
|
|
}
|
|
}
|
|
},
|
|
{
|
|
name: "Format Slack Message",
|
|
type: "n8n-nodes-base.function",
|
|
position: [300, 300],
|
|
parameters: {
|
|
functionCode: `
|
|
// Parse webhook data from n8n
|
|
const data = $input.first().json;
|
|
const workflow = data.workflow;
|
|
const execution = data.execution;
|
|
|
|
// Determine status color
|
|
let color = "#36a64f"; // Green for success
|
|
let icon = "✅";
|
|
|
|
if (execution.status === "error") {
|
|
color = "#ff0000"; // Red for error
|
|
icon = "❌";
|
|
} else if (execution.status === "warning") {
|
|
color = "#ffcc00"; // Yellow for warning
|
|
icon = "⚠️";
|
|
}
|
|
|
|
// Create Slack message blocks
|
|
const blocks = [
|
|
{
|
|
"type": "header",
|
|
"text": {
|
|
"type": "plain_text",
|
|
"text": \`\${icon} Workflow \${execution.status === "success" ? "Succeeded" : "Failed"}: \${workflow.name}\`,
|
|
"emoji": true
|
|
}
|
|
},
|
|
{
|
|
"type": "divider"
|
|
},
|
|
{
|
|
"type": "section",
|
|
"fields": [
|
|
{
|
|
"type": "mrkdwn",
|
|
"text": \`*Status:*\\n\${execution.status}\`
|
|
},
|
|
{
|
|
"type": "mrkdwn",
|
|
"text": \`*Execution Time:*\\n\${new Date(execution.startedAt).toLocaleString()}\`
|
|
},
|
|
{
|
|
"type": "mrkdwn",
|
|
"text": \`*Duration:*\\n\${Math.round((new Date(execution.finishedAt) - new Date(execution.startedAt)) / 1000)} seconds\`
|
|
},
|
|
{
|
|
"type": "mrkdwn",
|
|
"text": \`*Mode:*\\n\${execution.mode}\`
|
|
}
|
|
]
|
|
}
|
|
];
|
|
|
|
// Add error details if present
|
|
if (execution.status === "error" && execution.error) {
|
|
blocks.push(
|
|
{
|
|
"type": "divider"
|
|
},
|
|
{
|
|
"type": "section",
|
|
"text": {
|
|
"type": "mrkdwn",
|
|
"text": "*Error Details:*"
|
|
}
|
|
},
|
|
{
|
|
"type": "section",
|
|
"text": {
|
|
"type": "mrkdwn",
|
|
"text": \`\\\`\\\`\${execution.error.message || "Unknown error"}\\\`\\\`\`
|
|
}
|
|
}
|
|
);
|
|
}
|
|
|
|
// Add link to n8n execution
|
|
blocks.push(
|
|
{
|
|
"type": "divider"
|
|
},
|
|
{
|
|
"type": "section",
|
|
"text": {
|
|
"type": "mrkdwn",
|
|
"text": \`<\${data.n8nUrl}/workflow/\${workflow.id}|View Workflow> | <\${data.n8nUrl}/execution/\${execution.id}|View Execution>\`
|
|
}
|
|
}
|
|
);
|
|
|
|
return [{
|
|
json: {
|
|
blocks: blocks,
|
|
text: \`\${icon} Workflow \${execution.status === "success" ? "Succeeded" : "Failed"}: \${workflow.name}\`,
|
|
channel: "#n8n-notifications"
|
|
}
|
|
}];
|
|
`
|
|
}
|
|
},
|
|
{
|
|
name: "Send to Slack",
|
|
type: "n8n-nodes-base.slack",
|
|
position: [500, 300],
|
|
parameters: {
|
|
token: "{{$env.SLACK_TOKEN}}",
|
|
text: "={{$json.text}}",
|
|
channel: "={{$json.channel}}",
|
|
otherOptions: {
|
|
blocks: "={{$json.blocks}}"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
connections: {
|
|
"Webhook": {
|
|
main: [
|
|
[
|
|
{
|
|
node: "Format Slack Message",
|
|
type: "main",
|
|
index: 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Format Slack Message": {
|
|
main: [
|
|
[
|
|
{
|
|
node: "Send to Slack",
|
|
type: "main",
|
|
index: 0
|
|
}
|
|
]
|
|
]
|
|
}
|
|
}
|
|
});
|
|
|
|
// Create workflow to set up webhook in n8n settings
|
|
const setupWorkflow = await useMcpTool('n8n-mcp-server', 'workflow_create', {
|
|
name: "Configure n8n Execution Notifications",
|
|
active: false,
|
|
nodes: [
|
|
{
|
|
name: "Manual Trigger",
|
|
type: "n8n-nodes-base.manualTrigger",
|
|
position: [100, 300],
|
|
parameters: {}
|
|
},
|
|
{
|
|
name: "n8n Settings",
|
|
type: "n8n-nodes-base.n8n",
|
|
position: [300, 300],
|
|
parameters: {
|
|
resource: "settings",
|
|
operation: "update",
|
|
values: {
|
|
executionTimeout: 120,
|
|
saveManualExecutions: true,
|
|
saveDataErrorExecution: "all",
|
|
saveDataSuccessExecution: "all",
|
|
saveExecutionProgress: true,
|
|
executeTimeout: 120,
|
|
maxExecutionTimeout: 300,
|
|
workflowCallerIdsAllowed: [],
|
|
timezone: "UTC",
|
|
executionMode: "regular",
|
|
pushBackend: "websocket",
|
|
webhookDebugEnabled: false,
|
|
webhookUrl: "={{$json.webhookUrl}}",
|
|
logLevel: "info"
|
|
}
|
|
}
|
|
},
|
|
{
|
|
name: "Create Instructions",
|
|
type: "n8n-nodes-base.function",
|
|
position: [500, 300],
|
|
parameters: {
|
|
functionCode: `
|
|
const webhookNode = $input.itemsFrom('Webhook')? $input.itemsFrom('Webhook')[0] : { json: { webhookUrl: "unknown" } };
|
|
const webhookUrl = webhookNode.json.webhookUrl;
|
|
|
|
return [{
|
|
json: {
|
|
instructions: \`
|
|
# n8n to Slack Notification Setup
|
|
|
|
I've created two workflows:
|
|
|
|
1. **n8n Execution Notifications to Slack** - This workflow receives execution notifications from n8n and sends them to Slack
|
|
- ID: ${notificationWorkflow.id}
|
|
- Webhook URL: \${webhookUrl}
|
|
|
|
2. **Configure n8n Execution Notifications** - This workflow configures n8n settings to send notifications
|
|
- ID: ${setupWorkflow.id}
|
|
|
|
## Next Steps:
|
|
|
|
1. Create a Slack app and obtain a token with the following permissions:
|
|
- chat:write
|
|
- chat:write.public
|
|
|
|
2. Set the environment variable \`SLACK_TOKEN\` with your Slack token
|
|
|
|
3. Run the "Configure n8n Execution Notifications" workflow after setting the \`webhookUrl\` parameter to:
|
|
\${webhookUrl}
|
|
|
|
4. Activate the "n8n Execution Notifications to Slack" workflow
|
|
|
|
5. Customize the channel in the "Format Slack Message" node if needed (default is #n8n-notifications)
|
|
|
|
Once completed, you'll receive Slack notifications whenever a workflow execution succeeds or fails!
|
|
\`
|
|
}
|
|
}];
|
|
`
|
|
}
|
|
}
|
|
],
|
|
connections: {
|
|
"Manual Trigger": {
|
|
main: [
|
|
[
|
|
{
|
|
node: "n8n Settings",
|
|
type: "main",
|
|
index: 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"n8n Settings": {
|
|
main: [
|
|
[
|
|
{
|
|
node: "Create Instructions",
|
|
type: "main",
|
|
index: 0
|
|
}
|
|
]
|
|
]
|
|
}
|
|
}
|
|
});
|
|
|
|
// Execute the workflow to get the webhook URL
|
|
const execution = await useMcpTool('n8n-mcp-server', 'execution_run', {
|
|
workflowId: notificationWorkflow.id,
|
|
waitForCompletion: true
|
|
});
|
|
|
|
// Extract webhook URL from the execution
|
|
let webhookUrl = "undefined";
|
|
if (execution.status === "success" && execution.data?.resultData?.runData?.Webhook?.[0]?.data?.webhookUrl) {
|
|
webhookUrl = execution.data.resultData.runData.Webhook[0].data.webhookUrl;
|
|
}
|
|
|
|
return `
|
|
# n8n to Slack Notification Setup
|
|
|
|
I've created two workflows:
|
|
|
|
1. **n8n Execution Notifications to Slack** - This workflow receives execution notifications from n8n and sends them to Slack
|
|
- ID: ${notificationWorkflow.id}
|
|
- Webhook URL: ${webhookUrl}
|
|
|
|
2. **Configure n8n Execution Notifications** - This workflow configures n8n settings to send notifications
|
|
- ID: ${setupWorkflow.id}
|
|
|
|
## Next Steps:
|
|
|
|
1. Create a Slack app and obtain a token with the following permissions:
|
|
- chat:write
|
|
- chat:write.public
|
|
|
|
2. Set the environment variable \`SLACK_TOKEN\` with your Slack token
|
|
|
|
3. Run the "Configure n8n Execution Notifications" workflow after setting the \`webhookUrl\` parameter to:
|
|
${webhookUrl}
|
|
|
|
4. Activate the "n8n Execution Notifications to Slack" workflow
|
|
|
|
5. Customize the channel in the "Format Slack Message" node if needed (default is #n8n-notifications)
|
|
|
|
Once completed, you'll receive Slack notifications whenever a workflow execution completes!
|
|
```
|
|
# Integration Examples
|
|
|
|
This page provides examples of integrating the n8n MCP Server with other systems and AI assistant platforms.
|
|
|
|
## AI Assistant Integration Examples
|
|
|
|
### Claude AI Assistant Integration
|
|
|
|
#### Example: Setting Up n8n MCP Server with Claude
|
|
|
|
```javascript
|
|
// Register the n8n MCP Server with Claude using the MCP Installer
|
|
const installationResult = await useMcpTool('mcp-installer', 'install_repo_mcp_server', {
|
|
name: 'n8n-mcp-server',
|
|
env: [
|
|
"N8N_API_URL=http://localhost:5678/api/v1",
|
|
"N8N_API_KEY=your_n8n_api_key_here",
|
|
"DEBUG=false"
|
|
]
|
|
});
|
|
|
|
// Once registered, Claude can interact with n8n
|
|
// Here's an example conversation:
|
|
|
|
// User: "Show me my active workflows in n8n"
|
|
// Claude: (uses workflow_list tool to retrieve and display active workflows)
|
|
|
|
// User: "Execute my 'Daily Report' workflow"
|
|
// Claude: (uses execution_run tool to start the workflow and provide status)
|
|
```
|
|
|
|
#### Example: Using n8n to Extend Claude's Capabilities
|
|
|
|
```javascript
|
|
// Using n8n as a bridge to external systems
|
|
// This example shows how Claude can access a database through n8n
|
|
|
|
// User: "Show me the top 5 customers from my database"
|
|
// Claude would:
|
|
|
|
// 1. Find the appropriate workflow
|
|
const workflows = await useMcpTool('n8n-mcp-server', 'workflow_list', {});
|
|
const dbQueryWorkflow = workflows.find(w =>
|
|
w.name.toLowerCase().includes('database query') ||
|
|
w.name.toLowerCase().includes('db query')
|
|
);
|
|
|
|
if (!dbQueryWorkflow) {
|
|
return "I couldn't find a database query workflow. Would you like me to help you create one?";
|
|
}
|
|
|
|
// 2. Execute the workflow with the appropriate parameters
|
|
const execution = await useMcpTool('n8n-mcp-server', 'execution_run', {
|
|
workflowId: dbQueryWorkflow.id,
|
|
data: {
|
|
query: "SELECT * FROM customers ORDER BY total_purchases DESC LIMIT 5",
|
|
format: "table"
|
|
},
|
|
waitForCompletion: true
|
|
});
|
|
|
|
// 3. Present the results to the user
|
|
if (execution.status !== "success") {
|
|
return "There was an error querying the database. Error: " + (execution.error || "Unknown error");
|
|
}
|
|
|
|
// Format the results as a table
|
|
const customers = execution.data.resultData.runData.lastNode[0].data.json;
|
|
let response = "# Top 5 Customers\n\n";
|
|
response += "| Customer Name | Email | Total Purchases |\n";
|
|
response += "|--------------|-------|----------------|\n";
|
|
|
|
customers.forEach(customer => {
|
|
response += `| ${customer.name} | ${customer.email} | $${customer.total_purchases.toFixed(2)} |\n`;
|
|
});
|
|
|
|
return response;
|
|
```
|
|
|
|
### OpenAI Assistant Integration
|
|
|
|
#### Example: Connecting n8n MCP Server to OpenAI Assistant
|
|
|
|
```javascript
|
|
// This is a conceptual example of how an OpenAI Assistant might interact with the n8n MCP Server
|
|
|
|
// In an OpenAI Assistant Function definition:
|
|
{
|
|
"name": "n8n_workflow_list",
|
|
"description": "List all workflows in n8n",
|
|
"parameters": {
|
|
"type": "object",
|
|
"properties": {
|
|
"active": {
|
|
"type": "boolean",
|
|
"description": "Filter by active status (optional)"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// The function would call the n8n MCP Server:
|
|
async function n8n_workflow_list(params) {
|
|
// Call the n8n MCP Server API
|
|
const response = await fetch('http://localhost:3000/n8n-mcp/tools/workflow_list', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'Authorization': 'Bearer YOUR_AUTH_TOKEN'
|
|
},
|
|
body: JSON.stringify(params)
|
|
});
|
|
|
|
return await response.json();
|
|
}
|
|
|
|
// The OpenAI Assistant would then use this function when asked about n8n workflows
|
|
```
|
|
|
|
## Integration with External Systems
|
|
|
|
### n8n to Git Integration
|
|
|
|
#### Example: Using n8n MCP Server to Manage Workflow Versioning in Git
|
|
|
|
```javascript
|
|
// User request: "Backup all my workflows to my Git repository"
|
|
|
|
// The assistant first creates a workflow for Git backup
|
|
const backupWorkflow = await useMcpTool('n8n-mcp-server', 'workflow_create', {
|
|
name: "Workflow Git Backup",
|
|
active: false,
|
|
nodes: [
|
|
{
|
|
name: "Manual Trigger",
|
|
type: "n8n-nodes-base.manualTrigger",
|
|
position: [100, 300],
|
|
parameters: {}
|
|
},
|
|
{
|
|
name: "Get All Workflows",
|
|
type: "n8n-nodes-base.n8n",
|
|
position: [300, 300],
|
|
parameters: {
|
|
resource: "workflow",
|
|
operation: "getAll"
|
|
}
|
|
},
|
|
{
|
|
name: "Format For Git",
|
|
type: "n8n-nodes-base.function",
|
|
position: [500, 300],
|
|
parameters: {
|
|
functionCode: `
|
|
// Convert workflows to individual JSON files
|
|
const workflows = items;
|
|
const outputItems = [];
|
|
|
|
for (const workflow of workflows) {
|
|
// Create a sanitized filename
|
|
const filename = workflow.json.name
|
|
.replace(/[^a-zA-Z0-9]/g, '_')
|
|
.toLowerCase() + '.json';
|
|
|
|
outputItems.push({
|
|
json: {
|
|
filename: filename,
|
|
content: JSON.stringify(workflow.json, null, 2),
|
|
commit_message: \`Backup workflow: \${workflow.json.name}\`
|
|
}
|
|
});
|
|
}
|
|
|
|
return outputItems;
|
|
`
|
|
}
|
|
},
|
|
{
|
|
name: "Git Commit",
|
|
type: "n8n-nodes-base.git",
|
|
position: [700, 300],
|
|
parameters: {
|
|
repository: "{{$env.GIT_REPO_PATH}}",
|
|
directory: "workflows",
|
|
operation: "commit",
|
|
message: "Automated workflow backup {{$now.format('YYYY-MM-DD HH:mm')}}",
|
|
filePath: "={{$json.filename}}",
|
|
fileContent: "={{$json.content}}"
|
|
}
|
|
},
|
|
{
|
|
name: "Git Push",
|
|
type: "n8n-nodes-base.git",
|
|
position: [900, 300],
|
|
parameters: {
|
|
repository: "{{$env.GIT_REPO_PATH}}",
|
|
operation: "push"
|
|
}
|
|
}
|
|
],
|
|
connections: {
|
|
"Manual Trigger": {
|
|
main: [
|
|
[
|
|
{
|
|
node: "Get All Workflows",
|
|
type: "main",
|
|
index: 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Get All Workflows": {
|
|
main: [
|
|
[
|
|
{
|
|
node: "Format For Git",
|
|
type: "main",
|
|
index: 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Format For Git": {
|
|
main: [
|
|
[
|
|
{
|
|
node: "Git Commit",
|
|
type: "main",
|
|
index: 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Git Commit": {
|
|
main: [
|
|
[
|
|
{
|
|
node: "Git Push",
|
|
type: "main",
|
|
index: 0
|
|
}
|
|
]
|
|
]
|
|
}
|
|
}
|
|
});
|
|
|
|
return `
|
|
# Git Backup Workflow Created
|
|
|
|
I've created a new workflow that will backup all your n8n workflows to Git.
|
|
|
|
**Workflow ID:** ${backupWorkflow.id}
|
|
|
|
## Configuration Needed:
|
|
1. The workflow is currently **inactive** - activate it once configured
|
|
2. Set the environment variable \`GIT_REPO_PATH\` to point to your Git repository
|
|
3. Ensure the Git repository is properly configured with credentials
|
|
|
|
## How It Works:
|
|
- When executed, this workflow retrieves all n8n workflows
|
|
- Converts each workflow to a JSON file
|
|
- Commits each file to the specified Git repository
|
|
- Pushes the changes to the remote repository
|
|
|
|
## Usage:
|
|
You can run this workflow manually whenever you want to backup your workflows,
|
|
or add a Schedule Trigger to automate regular backups.
|
|
`;
|
|
```
|
|
|
|
### CRM Integration
|
|
|
|
#### Example: Setting Up a Two-Way Sync Between n8n and a CRM
|
|
|
|
```javascript
|
|
// User request: "Help me set up a sync between n8n and my HubSpot CRM"
|
|
|
|
// First check for existing credentials
|
|
const workflows = await useMcpTool('n8n-mcp-server', 'workflow_list', {});
|
|
const hubspotWorkflows = workflows.filter(w =>
|
|
w.name.toLowerCase().includes('hubspot')
|
|
);
|
|
|
|
let credentialsMessage = "";
|
|
if (hubspotWorkflows.length > 0) {
|
|
credentialsMessage = "I noticed you already have HubSpot workflows. I'll assume you have HubSpot credentials set up.";
|
|
} else {
|
|
credentialsMessage = "You'll need to set up HubSpot credentials in n8n before activating this workflow.";
|
|
}
|
|
|
|
// Create the sync workflow
|
|
const syncWorkflow = await useMcpTool('n8n-mcp-server', 'workflow_create', {
|
|
name: "HubSpot Two-Way Sync",
|
|
active: false,
|
|
nodes: [
|
|
{
|
|
name: "Schedule Trigger",
|
|
type: "n8n-nodes-base.scheduleTrigger",
|
|
position: [100, 300],
|
|
parameters: {
|
|
cronExpression: "0 */2 * * *" // Every 2 hours
|
|
}
|
|
},
|
|
{
|
|
name: "Get HubSpot Contacts",
|
|
type: "n8n-nodes-base.hubspot",
|
|
position: [300, 200],
|
|
parameters: {
|
|
resource: "contact",
|
|
operation: "getAll",
|
|
returnAll: true,
|
|
additionalFields: {
|
|
formattedDate: true
|
|
}
|
|
}
|
|
},
|
|
{
|
|
name: "Get n8n Contacts",
|
|
type: "n8n-nodes-base.function",
|
|
position: [300, 400],
|
|
parameters: {
|
|
functionCode: `
|
|
// This function would retrieve contacts from your internal database
|
|
// For example purposes, we're using a placeholder
|
|
// In reality, you might use another n8n node to fetch from your database
|
|
|
|
return [
|
|
{
|
|
json: {
|
|
internalContacts: [
|
|
// Example internal contacts
|
|
// In a real scenario, these would come from your database
|
|
]
|
|
}
|
|
}
|
|
];
|
|
`
|
|
}
|
|
},
|
|
{
|
|
name: "Compare & Identify Changes",
|
|
type: "n8n-nodes-base.function",
|
|
position: [500, 300],
|
|
parameters: {
|
|
functionCode: `
|
|
const hubspotContacts = $input.first();
|
|
const internalContacts = $input.last().json.internalContacts;
|
|
|
|
// Identify new/updated contacts in HubSpot
|
|
const hubspotUpdates = hubspotContacts.json.map(contact => {
|
|
// Find matching internal contact by email
|
|
const internalMatch = internalContacts.find(
|
|
ic => ic.email === contact.properties.email
|
|
);
|
|
|
|
if (!internalMatch) {
|
|
return {
|
|
json: {
|
|
type: 'new_in_hubspot',
|
|
contact: contact,
|
|
action: 'create_in_internal'
|
|
}
|
|
};
|
|
}
|
|
|
|
// Check if HubSpot contact is newer
|
|
const hubspotUpdated = new Date(contact.properties.lastmodifieddate);
|
|
const internalUpdated = new Date(internalMatch.updated_at);
|
|
|
|
if (hubspotUpdated > internalUpdated) {
|
|
return {
|
|
json: {
|
|
type: 'updated_in_hubspot',
|
|
contact: contact,
|
|
action: 'update_in_internal'
|
|
}
|
|
};
|
|
}
|
|
|
|
return null;
|
|
}).filter(item => item !== null);
|
|
|
|
// Identify new/updated contacts in internal system
|
|
const internalUpdates = internalContacts.map(contact => {
|
|
// Find matching HubSpot contact by email
|
|
const hubspotMatch = hubspotContacts.json.find(
|
|
hc => hc.properties.email === contact.email
|
|
);
|
|
|
|
if (!hubspotMatch) {
|
|
return {
|
|
json: {
|
|
type: 'new_in_internal',
|
|
contact: contact,
|
|
action: 'create_in_hubspot'
|
|
}
|
|
};
|
|
}
|
|
|
|
// Check if internal contact is newer
|
|
const internalUpdated = new Date(contact.updated_at);
|
|
const hubspotUpdated = new Date(hubspotMatch.properties.lastmodifieddate);
|
|
|
|
if (internalUpdated > hubspotUpdated) {
|
|
return {
|
|
json: {
|
|
type: 'updated_in_internal',
|
|
contact: contact,
|
|
action: 'update_in_hubspot'
|
|
}
|
|
};
|
|
}
|
|
|
|
return null;
|
|
}).filter(item => item !== null);
|
|
|
|
// Combine all changes
|
|
return [...hubspotUpdates, ...internalUpdates];
|
|
`
|
|
}
|
|
},
|
|
{
|
|
name: "Route Updates",
|
|
type: "n8n-nodes-base.switch",
|
|
position: [700, 300],
|
|
parameters: {
|
|
rules: {
|
|
conditions: [
|
|
{
|
|
value1: "={{$json.action}}",
|
|
operation: "equal",
|
|
value2: "update_in_hubspot"
|
|
},
|
|
{
|
|
value1: "={{$json.action}}",
|
|
operation: "equal",
|
|
value2: "create_in_hubspot"
|
|
},
|
|
{
|
|
value1: "={{$json.action}}",
|
|
operation: "equal",
|
|
value2: "update_in_internal"
|
|
},
|
|
{
|
|
value1: "={{$json.action}}",
|
|
operation: "equal",
|
|
value2: "create_in_internal"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
},
|
|
{
|
|
name: "Update HubSpot Contact",
|
|
type: "n8n-nodes-base.hubspot",
|
|
position: [900, 100],
|
|
parameters: {
|
|
resource: "contact",
|
|
operation: "update",
|
|
contactId: "={{$json.contact.hubspot_id || $json.hubspotId}}",
|
|
additionalFields: {
|
|
properties: {
|
|
firstname: "={{$json.contact.first_name}}",
|
|
lastname: "={{$json.contact.last_name}}",
|
|
email: "={{$json.contact.email}}",
|
|
phone: "={{$json.contact.phone}}",
|
|
// Add additional fields as needed
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
name: "Create HubSpot Contact",
|
|
type: "n8n-nodes-base.hubspot",
|
|
position: [900, 250],
|
|
parameters: {
|
|
resource: "contact",
|
|
operation: "create",
|
|
additionalFields: {
|
|
properties: {
|
|
firstname: "={{$json.contact.first_name}}",
|
|
lastname: "={{$json.contact.last_name}}",
|
|
email: "={{$json.contact.email}}",
|
|
phone: "={{$json.contact.phone}}",
|
|
// Add additional fields as needed
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
name: "Update Internal Contact",
|
|
type: "n8n-nodes-base.function",
|
|
position: [900, 400],
|
|
parameters: {
|
|
functionCode: `
|
|
// This function would update contacts in your internal database
|
|
// In reality, you might use another n8n node like a database connector
|
|
const contact = $input.first().json.contact;
|
|
|
|
// Process the HubSpot contact into internal format
|
|
const internalFormat = {
|
|
first_name: contact.properties.firstname,
|
|
last_name: contact.properties.lastname,
|
|
email: contact.properties.email,
|
|
phone: contact.properties.phone,
|
|
hubspot_id: contact.id,
|
|
updated_at: new Date().toISOString()
|
|
};
|
|
|
|
// In a real implementation, you would update your database
|
|
// For this example, we just return what would be updated
|
|
return [{
|
|
json: {
|
|
action: "updated_internal_contact",
|
|
contact: internalFormat
|
|
}
|
|
}];
|
|
`
|
|
}
|
|
},
|
|
{
|
|
name: "Create Internal Contact",
|
|
type: "n8n-nodes-base.function",
|
|
position: [900, 550],
|
|
parameters: {
|
|
functionCode: `
|
|
// This function would create new contacts in your internal database
|
|
// In reality, you might use another n8n node like a database connector
|
|
const contact = $input.first().json.contact;
|
|
|
|
// Process the HubSpot contact into internal format
|
|
const internalFormat = {
|
|
first_name: contact.properties.firstname,
|
|
last_name: contact.properties.lastname,
|
|
email: contact.properties.email,
|
|
phone: contact.properties.phone,
|
|
hubspot_id: contact.id,
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString()
|
|
};
|
|
|
|
// In a real implementation, you would insert into your database
|
|
// For this example, we just return what would be created
|
|
return [{
|
|
json: {
|
|
action: "created_internal_contact",
|
|
contact: internalFormat
|
|
}
|
|
}];
|
|
`
|
|
}
|
|
},
|
|
{
|
|
name: "Sync Report",
|
|
type: "n8n-nodes-base.function",
|
|
position: [1100, 300],
|
|
parameters: {
|
|
functionCode: `
|
|
// Collect all results from previous nodes
|
|
const updateHubspot = $input.itemsFrom('Update HubSpot Contact');
|
|
const createHubspot = $input.itemsFrom('Create HubSpot Contact');
|
|
const updateInternal = $input.itemsFrom('Update Internal Contact');
|
|
const createInternal = $input.itemsFrom('Create Internal Contact');
|
|
|
|
// Generate sync summary
|
|
return [{
|
|
json: {
|
|
summary: "Sync Complete",
|
|
timestamp: new Date().toISOString(),
|
|
stats: {
|
|
hubspot_updated: updateHubspot.length,
|
|
hubspot_created: createHubspot.length,
|
|
internal_updated: updateInternal.length,
|
|
internal_created: createInternal.length,
|
|
total_changes: updateHubspot.length + createHubspot.length +
|
|
updateInternal.length + createInternal.length
|
|
}
|
|
}
|
|
}];
|
|
`
|
|
}
|
|
}
|
|
],
|
|
connections: {
|
|
"Schedule Trigger": {
|
|
main: [
|
|
[
|
|
{
|
|
node: "Get HubSpot Contacts",
|
|
type: "main",
|
|
index: 0
|
|
},
|
|
{
|
|
node: "Get n8n Contacts",
|
|
type: "main",
|
|
index: 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Get HubSpot Contacts": {
|
|
main: [
|
|
[
|
|
{
|
|
node: "Compare & Identify Changes",
|
|
type: "main",
|
|
index: 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Get n8n Contacts": {
|
|
main: [
|
|
[
|
|
{
|
|
node: "Compare & Identify Changes",
|
|
type: "main",
|
|
index: 1
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Compare & Identify Changes": {
|
|
main: [
|
|
[
|
|
{
|
|
node: "Route Updates",
|
|
type: "main",
|
|
index: 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Route Updates": {
|
|
main: [
|
|
[
|
|
{
|
|
node: "Update HubSpot Contact",
|
|
type: "main",
|
|
index: 0
|
|
}
|
|
],
|
|
[
|
|
{
|
|
node: "Create HubSpot Contact",
|
|
type: "main",
|
|
index: 0
|
|
}
|
|
],
|
|
[
|
|
{
|
|
node: "Update Internal Contact",
|
|
type: "main",
|
|
index: 0
|
|
}
|
|
],
|
|
[
|
|
{
|
|
node: "Create Internal Contact",
|
|
type: "main",
|
|
index: 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Update HubSpot Contact": {
|
|
main: [
|
|
[
|
|
{
|
|
node: "Sync Report",
|
|
type: "main",
|
|
index: 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Create HubSpot Contact": {
|
|
main: [
|
|
[
|
|
{
|
|
node: "Sync Report",
|
|
type: "main",
|
|
index: 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Update Internal Contact": {
|
|
main: [
|
|
[
|
|
{
|
|
node: "Sync Report",
|
|
type: "main",
|
|
index: 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Create Internal Contact": {
|
|
main: [
|
|
[
|
|
{
|
|
node: "Sync Report",
|
|
type: "main",
|
|
index: 0
|
|
}
|
|
]
|
|
]
|
|
}
|
|
}
|
|
});
|
|
|
|
return `
|
|
# HubSpot Two-Way Sync Workflow Created
|
|
|
|
I've created a new workflow that will synchronize contacts between HubSpot and your internal system.
|
|
|
|
**Workflow ID:** ${syncWorkflow.id}
|
|
|
|
## Configuration Needed:
|
|
1. The workflow is currently **inactive** - activate it once configured
|
|
2. ${credentialsMessage}
|
|
3. You'll need to customize the "Get n8n Contacts", "Update Internal Contact", and "Create Internal Contact" nodes to work with your specific database or storage system
|
|
|
|
## How It Works:
|
|
- Runs every 2 hours (configurable)
|
|
- Retrieves contacts from both HubSpot and your internal system
|
|
- Compares the data to identify new or updated contacts in either system
|
|
- Creates or updates contacts to keep both systems in sync
|
|
- Generates a sync report with statistics
|
|
|
|
## Customization:
|
|
You may need to modify the field mappings in the function nodes to match your specific data structure
|
|
and add any additional fields that need to be synchronized between the systems.
|
|
`;
|
|
```
|
|
|
|
### Slack Integration
|
|
|
|
#### Example: Creating a Workflow to Send n8n Notifications to Slack
|
|
|
|
```javascript
|
|
// User request: "Create a workflow that sends n8n execution notifications to Slack"
|
|
|
|
// Create the notification workflow
|
|
const notificationWorkflow = await useMcpTool('n8n-mcp-server', 'workflow_create', {
|
|
name: "n8n Execution Notifications to Slack",
|
|
active: false,
|
|
nodes: [
|
|
{
|
|
name: "Webhook",
|
|
type: "n8n-nodes-base.webhook",
|
|
position: [100, 300],
|
|
parameters: {
|
|
path: "n8n-notification",
|
|
responseMode: "onReceived",
|
|
options: {
|
|
responseData: "noData"
|
|
}
|
|
}
|
|
},
|
|
{
|
|
name: "Format Slack Message",
|
|
type: "n8n-nodes-base.function",
|
|
position: [300, 300],
|
|
parameters: {
|
|
functionCode: `
|
|
// Parse webhook data from n8n
|
|
const data = $input.first().json;
|
|
const workflow = data.workflow;
|
|
const execution = data.execution;
|
|
|
|
// Determine status color
|
|
let color = "#36a64f"; // Green for success
|
|
let icon = "✅";
|
|
|
|
if (execution.status === "error") {
|
|
color = "#ff0000"; // Red for error
|
|
icon = "❌";
|
|
} else if (execution.status === "warning") {
|
|
color = "#ffcc00"; // Yellow for warning
|
|
icon = "⚠️";
|
|
}
|
|
|
|
// Create Slack message blocks
|
|
const blocks = [
|
|
{
|
|
"type": "header",
|
|
"text": {
|
|
"type": "plain_text",
|
|
"text": \`\${icon} Workflow \${execution.status === "success" ? "Succeeded" : "Failed"}: \${workflow.name}\`,
|
|
"emoji": true
|
|
}
|
|
},
|
|
{
|
|
"type": "divider"
|
|
},
|
|
{
|
|
"type": "section",
|
|
"fields": [
|
|
{
|
|
"type": "mrkdwn",
|
|
"text": \`*Status:*\\n\${execution.status}\`
|
|
},
|
|
{
|
|
"type": "mrkdwn",
|
|
"text": \`*Execution Time:*\\n\${new Date(execution.startedAt).toLocaleString()}\`
|
|
},
|
|
{
|
|
"type": "mrkdwn",
|
|
"text": \`*Duration:*\\n\${Math.round((new Date(execution.finishedAt) - new Date(execution.startedAt)) / 1000)} seconds\`
|
|
},
|
|
{
|
|
"type": "mrkdwn",
|
|
"text": \`*Mode:*\\n\${execution.mode}\`
|
|
}
|
|
]
|
|
}
|
|
];
|
|
|
|
// Add error details if present
|
|
if (execution.status === "error" && execution.error) {
|
|
blocks.push(
|
|
{
|
|
"type": "divider"
|
|
},
|
|
{
|
|
"type": "section",
|
|
"text": {
|
|
"type": "mrkdwn",
|
|
"text": "*Error Details:*"
|
|
}
|
|
},
|
|
{
|
|
"type": "section",
|
|
"text": {
|
|
"type": "mrkdwn",
|
|
"text": \`\\\`\\\`\${execution.error.message || "Unknown error"}\\\`\\\`\`
|
|
}
|
|
}
|
|
);
|
|
}
|
|
|
|
// Add link to n8n execution
|
|
blocks.push(
|
|
{
|
|
"type": "divider"
|
|
},
|
|
{
|
|
"type": "section",
|
|
"text": {
|
|
"type": "mrkdwn",
|
|
"text": \`<\${data.n8nUrl}/workflow/\${workflow.id}|View Workflow> | <\${data.n8nUrl}/execution/\${execution.id}|View Execution>\`
|
|
}
|
|
}
|
|
);
|
|
|
|
return [{
|
|
json: {
|
|
blocks: blocks,
|
|
text: \`\${icon} Workflow \${execution.status === "success" ? "Succeeded" : "Failed"}: \${workflow.name}\`,
|
|
channel: "#n8n-notifications"
|
|
}
|
|
}];
|
|
`
|
|
}
|
|
},
|
|
{
|
|
name: "Send to Slack",
|
|
type: "n8n-nodes-base.slack",
|
|
position: [500, 300],
|
|
parameters: {
|
|
token: "{{$env.SLACK_TOKEN}}",
|
|
text: "={{$json.text}}",
|
|
channel: "={{$json.channel}}",
|
|
otherOptions: {
|
|
blocks: "={{$json.blocks}}"
|
|
}
|
|
}
|
|
}
|
|
],
|
|
connections: {
|
|
"Webhook": {
|
|
main: [
|
|
[
|
|
{
|
|
node: "Format Slack Message",
|
|
type: "main",
|
|
index: 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Format Slack Message": {
|
|
main: [
|
|
[
|
|
{
|
|
node: "Send to Slack",
|
|
type: "main",
|
|
index: 0
|
|
}
|
|
]
|
|
]
|
|
}
|
|
}
|
|
});
|
|
|
|
// Create workflow to set up webhook in n8n settings
|
|
const setupWorkflow = await useMcpTool('n8n-mcp-server', 'workflow_create', {
|
|
name: "Configure n8n Execution Notifications",
|
|
active: false,
|
|
nodes: [
|
|
{
|
|
name: "Manual Trigger",
|
|
type: "n8n-nodes-base.manualTrigger",
|
|
position: [100, 300],
|
|
parameters: {}
|
|
},
|
|
{
|
|
name: "n8n Settings",
|
|
type: "n8n-nodes-base.n8n",
|
|
position: [300, 300],
|
|
parameters: {
|
|
resource: "settings",
|
|
operation: "update",
|
|
values: {
|
|
executionTimeout: 120,
|
|
saveManualExecutions: true,
|
|
saveDataErrorExecution: "all",
|
|
saveDataSuccessExecution: "all",
|
|
saveExecutionProgress: true,
|
|
executeTimeout: 120,
|
|
maxExecutionTimeout: 300,
|
|
workflowCallerIdsAllowed: [],
|
|
timezone: "UTC",
|
|
executionMode: "regular",
|
|
pushBackend: "websocket",
|
|
webhookDebugEnabled: false,
|
|
webhookUrl: "={{$json.webhookUrl}}",
|
|
logLevel: "info"
|
|
}
|
|
}
|
|
},
|
|
{
|
|
name: "Create Instructions",
|
|
type: "n8n-nodes-base.function",
|
|
position: [500, 300],
|
|
parameters: {
|
|
functionCode: `
|
|
const webhookNode = $input.itemsFrom('Webhook')? $input.itemsFrom('Webhook')[0] : { json: { webhookUrl: "unknown" } };
|
|
const webhookUrl = webhookNode.json.webhookUrl;
|
|
|
|
return [{
|
|
json: {
|
|
instructions: \`
|
|
# n8n to Slack Notification Setup
|
|
|
|
I've created two workflows:
|
|
|
|
1. **n8n Execution Notifications to Slack** - This workflow receives execution notifications from n8n and sends them to Slack
|
|
- ID: ${notificationWorkflow.id}
|
|
- Webhook URL: \${webhookUrl}
|
|
|
|
2. **Configure n8n Execution Notifications** - This workflow configures n8n settings to send notifications
|
|
- ID: ${setupWorkflow.id}
|
|
|
|
## Next Steps:
|
|
|
|
1. Create a Slack app and obtain a token with the following permissions:
|
|
- chat:write
|
|
- chat:write.public
|
|
|
|
2. Set the environment variable \`SLACK_TOKEN\` with your Slack token
|
|
|
|
3. Run the "Configure n8n Execution Notifications" workflow after setting the \`webhookUrl\` parameter to:
|
|
\${webhookUrl}
|
|
|
|
4. Activate the "n8n Execution Notifications to Slack" workflow
|
|
|
|
5. Customize the channel in the "Format Slack Message" node if needed (default is #n8n-notifications)
|
|
|
|
Once completed, you'll receive Slack notifications whenever a workflow execution succeeds or fails!
|
|
\`
|
|
}
|
|
}];
|
|
`
|
|
}
|
|
}
|
|
],
|
|
connections: {
|
|
"Manual Trigger": {
|
|
main: [
|
|
[
|
|
{
|
|
node: "n8n Settings",
|
|
type: "main",
|
|
index: 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"n8n Settings": {
|
|
main: [
|
|
[
|
|
{
|
|
node: "Create Instructions",
|
|
type: "main",
|
|
index: 0
|
|
}
|
|
]
|
|
]
|
|
}
|
|
}
|
|
});
|
|
|
|
// Execute the workflow to get the webhook URL
|
|
const execution = await useMcpTool('n8n-mcp-server', 'execution_run', {
|
|
workflowId: notificationWorkflow.id,
|
|
waitForCompletion: true
|
|
});
|
|
|
|
// Extract webhook URL from the execution
|
|
let webhookUrl = "undefined";
|
|
if (execution.status === "success" && execution.data?.resultData?.runData?.Webhook?.[0]?.data?.webhookUrl) {
|
|
webhookUrl = execution.data.resultData.runData.Webhook[0].data.webhookUrl;
|
|
}
|
|
|
|
return `
|
|
# n8n to Slack Notification Setup
|
|
|
|
I've created two workflows:
|
|
|
|
1. **n8n Execution Notifications to Slack** - This workflow receives execution notifications from n8n and sends them to Slack
|
|
- ID: ${notificationWorkflow.id}
|
|
- Webhook URL: ${webhookUrl}
|
|
|
|
2. **Configure n8n Execution Notifications** - This workflow configures n8n settings to send notifications
|
|
- ID: ${setupWorkflow.id}
|
|
|
|
## Next Steps:
|
|
|
|
1. Create a Slack app and obtain a token with the following permissions:
|
|
- chat:write
|
|
- chat:write.public
|
|
|
|
2. Set the environment variable \`SLACK_TOKEN\` with your Slack token
|
|
|
|
3. Run the "Configure n8n Execution Notifications" workflow after setting the \`webhookUrl\` parameter to:
|
|
${webhookUrl}
|
|
|
|
4. Activate the "n8n Execution Notifications to Slack" workflow
|
|
|
|
5. Customize the channel in the "Format Slack Message" node if needed (default is #n8n-notifications)
|
|
|
|
Once completed, you
|