feat: add n8n workflow templates as MCP tools
- Add 4 new MCP tools for workflow templates - Integrate with n8n.io API to fetch community templates - Filter templates to last 6 months only - Store templates in SQLite with full workflow JSON - Manual fetch system (not part of regular rebuild) - Support search by nodes, keywords, and task categories - Add fetch:templates and test:templates npm scripts - Update to v2.4.1 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -17,6 +17,7 @@ import { TaskTemplates } from '../services/task-templates';
|
||||
import { ConfigValidator } from '../services/config-validator';
|
||||
import { PropertyDependencies } from '../services/property-dependencies';
|
||||
import { SimpleCache } from '../utils/simple-cache';
|
||||
import { TemplateService } from '../templates/template-service';
|
||||
|
||||
interface NodeRow {
|
||||
node_type: string;
|
||||
@@ -40,6 +41,7 @@ export class N8NDocumentationMCPServer {
|
||||
private server: Server;
|
||||
private db: DatabaseAdapter | null = null;
|
||||
private repository: NodeRepository | null = null;
|
||||
private templateService: TemplateService | null = null;
|
||||
private initialized: Promise<void>;
|
||||
private cache = new SimpleCache();
|
||||
|
||||
@@ -88,6 +90,7 @@ export class N8NDocumentationMCPServer {
|
||||
try {
|
||||
this.db = await createDatabaseAdapter(dbPath);
|
||||
this.repository = new NodeRepository(this.db);
|
||||
this.templateService = new TemplateService(this.db);
|
||||
logger.info(`Initialized database from: ${dbPath}`);
|
||||
} catch (error) {
|
||||
logger.error('Failed to initialize database:', error);
|
||||
@@ -188,6 +191,14 @@ export class N8NDocumentationMCPServer {
|
||||
return this.validateNodeConfig(args.nodeType, args.config);
|
||||
case 'get_property_dependencies':
|
||||
return this.getPropertyDependencies(args.nodeType, args.config);
|
||||
case 'list_node_templates':
|
||||
return this.listNodeTemplates(args.nodeTypes, args.limit);
|
||||
case 'get_template':
|
||||
return this.getTemplate(args.templateId);
|
||||
case 'search_templates':
|
||||
return this.searchTemplates(args.query, args.limit);
|
||||
case 'get_templates_for_task':
|
||||
return this.getTemplatesForTask(args.task);
|
||||
default:
|
||||
throw new Error(`Unknown tool: ${name}`);
|
||||
}
|
||||
@@ -927,6 +938,108 @@ Full documentation is being prepared. For now, use get_node_essentials for confi
|
||||
transportType: transport.constructor.name
|
||||
});
|
||||
}
|
||||
|
||||
// Template-related methods
|
||||
private async listNodeTemplates(nodeTypes: string[], limit: number = 10): Promise<any> {
|
||||
await this.ensureInitialized();
|
||||
if (!this.templateService) throw new Error('Template service not initialized');
|
||||
|
||||
const templates = await this.templateService.listNodeTemplates(nodeTypes, limit);
|
||||
|
||||
if (templates.length === 0) {
|
||||
return {
|
||||
message: `No templates found using nodes: ${nodeTypes.join(', ')}`,
|
||||
tip: "Try searching with more common nodes or run 'npm run fetch:templates' to update template database",
|
||||
templates: []
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
templates,
|
||||
count: templates.length,
|
||||
tip: `Use get_template(templateId) to get the full workflow JSON for any template`
|
||||
};
|
||||
}
|
||||
|
||||
private async getTemplate(templateId: number): Promise<any> {
|
||||
await this.ensureInitialized();
|
||||
if (!this.templateService) throw new Error('Template service not initialized');
|
||||
|
||||
const template = await this.templateService.getTemplate(templateId);
|
||||
|
||||
if (!template) {
|
||||
return {
|
||||
error: `Template ${templateId} not found`,
|
||||
tip: "Use list_node_templates or search_templates to find available templates"
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
template,
|
||||
usage: "Import this workflow JSON directly into n8n or use it as a reference for building workflows"
|
||||
};
|
||||
}
|
||||
|
||||
private async searchTemplates(query: string, limit: number = 20): Promise<any> {
|
||||
await this.ensureInitialized();
|
||||
if (!this.templateService) throw new Error('Template service not initialized');
|
||||
|
||||
const templates = await this.templateService.searchTemplates(query, limit);
|
||||
|
||||
if (templates.length === 0) {
|
||||
return {
|
||||
message: `No templates found matching: "${query}"`,
|
||||
tip: "Try different keywords or run 'npm run fetch:templates' to update template database",
|
||||
templates: []
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
templates,
|
||||
count: templates.length,
|
||||
query
|
||||
};
|
||||
}
|
||||
|
||||
private async getTemplatesForTask(task: string): Promise<any> {
|
||||
await this.ensureInitialized();
|
||||
if (!this.templateService) throw new Error('Template service not initialized');
|
||||
|
||||
const templates = await this.templateService.getTemplatesForTask(task);
|
||||
const availableTasks = this.templateService.listAvailableTasks();
|
||||
|
||||
if (templates.length === 0) {
|
||||
return {
|
||||
message: `No templates found for task: ${task}`,
|
||||
availableTasks,
|
||||
tip: "Try a different task or use search_templates for custom searches"
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
task,
|
||||
templates,
|
||||
count: templates.length,
|
||||
description: this.getTaskDescription(task)
|
||||
};
|
||||
}
|
||||
|
||||
private getTaskDescription(task: string): string {
|
||||
const descriptions: Record<string, string> = {
|
||||
'ai_automation': 'AI-powered workflows using OpenAI, LangChain, and other AI tools',
|
||||
'data_sync': 'Synchronize data between databases, spreadsheets, and APIs',
|
||||
'webhook_processing': 'Process incoming webhooks and trigger automated actions',
|
||||
'email_automation': 'Send, receive, and process emails automatically',
|
||||
'slack_integration': 'Integrate with Slack for notifications and bot interactions',
|
||||
'data_transformation': 'Transform, clean, and manipulate data',
|
||||
'file_processing': 'Handle file uploads, downloads, and transformations',
|
||||
'scheduling': 'Schedule recurring tasks and time-based automations',
|
||||
'api_integration': 'Connect to external APIs and web services',
|
||||
'database_operations': 'Query, insert, update, and manage database records'
|
||||
};
|
||||
|
||||
return descriptions[task] || 'Workflow templates for this task';
|
||||
}
|
||||
|
||||
async run(): Promise<void> {
|
||||
// Ensure database is initialized before starting server
|
||||
|
||||
@@ -215,6 +215,85 @@ export const n8nDocumentationToolsFinal: ToolDefinition[] = [
|
||||
required: ['nodeType'],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'list_node_templates',
|
||||
description: `List workflow templates that use specific node type(s). Returns ready-to-use workflows from n8n.io community. Templates are from the last 6 months only. Use node types like "n8n-nodes-base.httpRequest" or "@n8n/n8n-nodes-langchain.openAi". Great for finding proven workflow patterns.`,
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
nodeTypes: {
|
||||
type: 'array',
|
||||
items: { type: 'string' },
|
||||
description: 'Array of node types to search for (e.g., ["n8n-nodes-base.httpRequest", "n8n-nodes-base.openAi"])',
|
||||
},
|
||||
limit: {
|
||||
type: 'number',
|
||||
description: 'Maximum number of templates to return. Default 10.',
|
||||
default: 10,
|
||||
},
|
||||
},
|
||||
required: ['nodeTypes'],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'get_template',
|
||||
description: `Get a specific workflow template with complete JSON. Returns the full workflow definition ready to import into n8n. Use template IDs from list_node_templates or search_templates results.`,
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
templateId: {
|
||||
type: 'number',
|
||||
description: 'The template ID to retrieve',
|
||||
},
|
||||
},
|
||||
required: ['templateId'],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'search_templates',
|
||||
description: `Search workflow templates by keywords in name/description. Returns templates matching your search terms. All templates are from the last 6 months and include view counts to gauge popularity. Good for finding workflows for specific use cases.`,
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
query: {
|
||||
type: 'string',
|
||||
description: 'Search query (searches in template names and descriptions)',
|
||||
},
|
||||
limit: {
|
||||
type: 'number',
|
||||
description: 'Maximum number of results. Default 20.',
|
||||
default: 20,
|
||||
},
|
||||
},
|
||||
required: ['query'],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'get_templates_for_task',
|
||||
description: `Get recommended templates for common automation tasks. Returns curated templates that solve specific use cases. Available tasks: ai_automation, data_sync, webhook_processing, email_automation, slack_integration, data_transformation, file_processing, scheduling, api_integration, database_operations.`,
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
task: {
|
||||
type: 'string',
|
||||
enum: [
|
||||
'ai_automation',
|
||||
'data_sync',
|
||||
'webhook_processing',
|
||||
'email_automation',
|
||||
'slack_integration',
|
||||
'data_transformation',
|
||||
'file_processing',
|
||||
'scheduling',
|
||||
'api_integration',
|
||||
'database_operations'
|
||||
],
|
||||
description: 'The type of task to get templates for',
|
||||
},
|
||||
},
|
||||
required: ['task'],
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user