search_nodes
Find n8n workflow nodes quickly by searching with keywords or phrases. Specify search mode (OR, AND, FUZZY) for precise results. Returns up to 20 nodes per query.
Instructions
Search n8n nodes by keyword. Pass query as string. Example: query="webhook" or query="database". Returns max 20 results.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Max results (default 20) | |
| mode | No | OR=any word, AND=all words, FUZZY=typo-tolerant | OR |
| query | Yes | Search terms. Use quotes for exact phrase. |
Implementation Reference
- src/mcp-tools-engine.ts:23-25 (handler)The main handler function for the 'search_nodes' MCP tool. It processes input arguments and delegates to the NodeRepository's searchNodes method with defaults for mode ('OR') and limit (20). This is the entry point for tool execution.async searchNodes(args: any) { return this.repository.searchNodes(args.query, args.mode || 'OR', args.limit || 20); }
- src/mcp/tools.ts:30-58 (schema)Tool definition and input schema validation for 'search_nodes', including parameters query (required), limit, mode (OR/AND/FUZZY), and includeExamples.name: 'search_nodes', description: `Search n8n nodes by keyword with optional real-world examples. Pass query as string. Example: query="webhook" or query="database". Returns max 20 results. Use includeExamples=true to get top 2 template configs per node.`, inputSchema: { type: 'object', properties: { query: { type: 'string', description: 'Search terms. Use quotes for exact phrase.', }, limit: { type: 'number', description: 'Max results (default 20)', default: 20, }, mode: { type: 'string', enum: ['OR', 'AND', 'FUZZY'], description: 'OR=any word, AND=all words, FUZZY=typo-tolerant', default: 'OR', }, includeExamples: { type: 'boolean', description: 'Include top 2 real-world configuration examples from popular templates (default: false)', default: false, }, }, required: ['query'], }, },
- Comprehensive documentation and parameter specifications for the search_nodes tool, including examples, use cases, performance notes, and best practices.export const searchNodesDoc: ToolDocumentation = { name: 'search_nodes', category: 'discovery', essentials: { description: 'Text search across node names and descriptions. Returns most relevant nodes first, with frequently-used nodes (HTTP Request, Webhook, Set, Code, Slack) prioritized in results. Searches all 500+ nodes in the database.', keyParameters: ['query', 'mode', 'limit'], example: 'search_nodes({query: "webhook"})', performance: '<20ms even for complex queries', tips: [ 'OR mode (default): Matches any search word', 'AND mode: Requires all words present', 'FUZZY mode: Handles typos and spelling errors', 'Use quotes for exact phrases: "google sheets"' ] }, full: { description: 'Full-text search engine for n8n nodes using SQLite FTS5. Searches across node names, descriptions, and aliases. Results are ranked by relevance with commonly-used nodes given priority. Common nodes include: HTTP Request, Webhook, Set, Code, IF, Switch, Merge, SplitInBatches, Slack, Google Sheets.', parameters: { query: { type: 'string', description: 'Search keywords. Use quotes for exact phrases like "google sheets"', required: true }, limit: { type: 'number', description: 'Maximum results to return. Default: 20, Max: 100', required: false }, mode: { type: 'string', description: 'Search mode: "OR" (any word matches, default), "AND" (all words required), "FUZZY" (typo-tolerant)', required: false } }, returns: 'Array of node objects sorted by relevance score. Each object contains: nodeType, displayName, description, category, relevance score. Common nodes appear first when relevance is similar.', examples: [ 'search_nodes({query: "webhook"}) - Returns Webhook node as top result', 'search_nodes({query: "database"}) - Returns MySQL, Postgres, MongoDB, Redis, etc.', 'search_nodes({query: "google sheets", mode: "AND"}) - Requires both words', 'search_nodes({query: "slak", mode: "FUZZY"}) - Finds Slack despite typo', 'search_nodes({query: "http api"}) - Finds HTTP Request, GraphQL, REST nodes', 'search_nodes({query: "transform data"}) - Finds Set, Code, Function, Item Lists nodes' ], useCases: [ 'Finding nodes when you know partial names', 'Discovering nodes by functionality (e.g., "email", "database", "transform")', 'Handling user typos in node names', 'Finding all nodes related to a service (e.g., "google", "aws", "microsoft")' ], performance: '<20ms for simple queries, <50ms for complex FUZZY searches. Uses FTS5 index for speed', bestPractices: [ 'Start with single keywords for broadest results', 'Use FUZZY mode when users might misspell node names', 'AND mode works best for 2-3 word searches', 'Combine with get_node after finding the right node' ], pitfalls: [ 'AND mode searches all fields (name, description) not just node names', 'FUZZY mode with very short queries (1-2 chars) may return unexpected results', 'Exact matches in quotes are case-sensitive' ], relatedTools: ['get_node to configure found nodes', 'search_templates to find workflow examples', 'validate_node to check configurations'] } };
- src/mcp/tools.ts:9-392 (registration)The array of all tool definitions where 'search_nodes' is registered among the n8n MCP documentation tools.export const n8nDocumentationToolsFinal: ToolDefinition[] = [ { name: 'tools_documentation', description: `Get documentation for n8n MCP tools. Call without parameters for quick start guide. Use topic parameter to get documentation for specific tools. Use depth='full' for comprehensive documentation.`, inputSchema: { type: 'object', properties: { topic: { type: 'string', description: 'Tool name (e.g., "search_nodes") or "overview" for general guide. Leave empty for quick reference.', }, depth: { type: 'string', enum: ['essentials', 'full'], description: 'Level of detail. "essentials" (default) for quick reference, "full" for comprehensive docs.', default: 'essentials', }, }, }, }, { name: 'search_nodes', description: `Search n8n nodes by keyword with optional real-world examples. Pass query as string. Example: query="webhook" or query="database". Returns max 20 results. Use includeExamples=true to get top 2 template configs per node.`, inputSchema: { type: 'object', properties: { query: { type: 'string', description: 'Search terms. Use quotes for exact phrase.', }, limit: { type: 'number', description: 'Max results (default 20)', default: 20, }, mode: { type: 'string', enum: ['OR', 'AND', 'FUZZY'], description: 'OR=any word, AND=all words, FUZZY=typo-tolerant', default: 'OR', }, includeExamples: { type: 'boolean', description: 'Include top 2 real-world configuration examples from popular templates (default: false)', default: false, }, }, required: ['query'], }, }, { name: 'get_node', description: `Get node info with progressive detail levels and multiple modes. Detail: minimal (~200 tokens), standard (~1-2K, default), full (~3-8K). Modes: info (default), docs (markdown documentation), search_properties (find properties), versions/compare/breaking/migrations (version info). Use format='docs' for readable documentation, mode='search_properties' with propertyQuery for finding specific fields.`, inputSchema: { type: 'object', properties: { nodeType: { type: 'string', description: 'Full node type: "nodes-base.httpRequest" or "nodes-langchain.agent"', }, detail: { type: 'string', enum: ['minimal', 'standard', 'full'], default: 'standard', description: 'Information detail level. standard=essential properties (recommended), full=everything', }, mode: { type: 'string', enum: ['info', 'docs', 'search_properties', 'versions', 'compare', 'breaking', 'migrations'], default: 'info', description: 'Operation mode. info=node schema, docs=readable markdown documentation, search_properties=find specific properties, versions/compare/breaking/migrations=version info', }, includeTypeInfo: { type: 'boolean', default: false, description: 'Include type structure metadata (type category, JS type, validation rules). Only applies to mode=info. Adds ~80-120 tokens per property.', }, includeExamples: { type: 'boolean', default: false, description: 'Include real-world configuration examples from templates. Only applies to mode=info with detail=standard. Adds ~200-400 tokens per example.', }, fromVersion: { type: 'string', description: 'Source version for compare/breaking/migrations modes (e.g., "1.0")', }, toVersion: { type: 'string', description: 'Target version for compare mode (e.g., "2.0"). Defaults to latest if omitted.', }, propertyQuery: { type: 'string', description: 'For mode=search_properties: search term to find properties (e.g., "auth", "header", "body")', }, maxPropertyResults: { type: 'number', description: 'For mode=search_properties: max results (default 20)', default: 20, }, }, required: ['nodeType'], }, }, { name: 'validate_node', description: `Validate n8n node configuration. Use mode='full' for comprehensive validation with errors/warnings/suggestions, mode='minimal' for quick required fields check. Example: nodeType="nodes-base.slack", config={resource:"channel",operation:"create"}`, inputSchema: { type: 'object', properties: { nodeType: { type: 'string', description: 'Node type as string. Example: "nodes-base.slack"', }, config: { type: 'object', description: 'Configuration as object. For simple nodes use {}. For complex nodes include fields like {resource:"channel",operation:"create"}', }, mode: { type: 'string', enum: ['full', 'minimal'], description: 'Validation mode. full=comprehensive validation with errors/warnings/suggestions, minimal=quick required fields check only. Default is "full"', default: 'full', }, profile: { type: 'string', enum: ['strict', 'runtime', 'ai-friendly', 'minimal'], description: 'Profile for mode=full: "minimal", "runtime", "ai-friendly", or "strict". Default is "ai-friendly"', default: 'ai-friendly', }, }, required: ['nodeType', 'config'], additionalProperties: false, }, outputSchema: { type: 'object', properties: { nodeType: { type: 'string' }, workflowNodeType: { type: 'string' }, displayName: { type: 'string' }, valid: { type: 'boolean' }, errors: { type: 'array', items: { type: 'object', properties: { type: { type: 'string' }, property: { type: 'string' }, message: { type: 'string' }, fix: { type: 'string' } } } }, warnings: { type: 'array', items: { type: 'object', properties: { type: { type: 'string' }, property: { type: 'string' }, message: { type: 'string' }, suggestion: { type: 'string' } } } }, suggestions: { type: 'array', items: { type: 'string' } }, missingRequiredFields: { type: 'array', items: { type: 'string' }, description: 'Only present in mode=minimal' }, summary: { type: 'object', properties: { hasErrors: { type: 'boolean' }, errorCount: { type: 'number' }, warningCount: { type: 'number' }, suggestionCount: { type: 'number' } } } }, required: ['nodeType', 'displayName', 'valid'] }, }, { name: 'get_template', description: `Get template by ID. Use mode to control response size: nodes_only (minimal), structure (nodes+connections), full (complete workflow).`, inputSchema: { type: 'object', properties: { templateId: { type: 'number', description: 'The template ID to retrieve', }, mode: { type: 'string', enum: ['nodes_only', 'structure', 'full'], description: 'Response detail level. nodes_only: just node list, structure: nodes+connections, full: complete workflow JSON.', default: 'full', }, }, required: ['templateId'], }, }, { name: 'search_templates', description: `Search templates with multiple modes. Use searchMode='keyword' for text search, 'by_nodes' to find templates using specific nodes, 'by_task' for curated task-based templates, 'by_metadata' for filtering by complexity/setup time/services.`, inputSchema: { type: 'object', properties: { searchMode: { type: 'string', enum: ['keyword', 'by_nodes', 'by_task', 'by_metadata'], description: 'Search mode. keyword=text search (default), by_nodes=find by node types, by_task=curated task templates, by_metadata=filter by complexity/services', default: 'keyword', }, // For searchMode='keyword' query: { type: 'string', description: 'For searchMode=keyword: search keyword (e.g., "chatbot")', }, fields: { type: 'array', items: { type: 'string', enum: ['id', 'name', 'description', 'author', 'nodes', 'views', 'created', 'url', 'metadata'], }, description: 'For searchMode=keyword: fields to include in response. Default: all fields.', }, // For searchMode='by_nodes' nodeTypes: { type: 'array', items: { type: 'string' }, description: 'For searchMode=by_nodes: array of node types (e.g., ["n8n-nodes-base.httpRequest", "n8n-nodes-base.slack"])', }, // For searchMode='by_task' task: { type: 'string', enum: [ 'ai_automation', 'data_sync', 'webhook_processing', 'email_automation', 'slack_integration', 'data_transformation', 'file_processing', 'scheduling', 'api_integration', 'database_operations' ], description: 'For searchMode=by_task: the type of task', }, // For searchMode='by_metadata' category: { type: 'string', description: 'For searchMode=by_metadata: filter by category (e.g., "automation", "integration")', }, complexity: { type: 'string', enum: ['simple', 'medium', 'complex'], description: 'For searchMode=by_metadata: filter by complexity level', }, maxSetupMinutes: { type: 'number', description: 'For searchMode=by_metadata: maximum setup time in minutes', minimum: 5, maximum: 480, }, minSetupMinutes: { type: 'number', description: 'For searchMode=by_metadata: minimum setup time in minutes', minimum: 5, maximum: 480, }, requiredService: { type: 'string', description: 'For searchMode=by_metadata: filter by required service (e.g., "openai", "slack")', }, targetAudience: { type: 'string', description: 'For searchMode=by_metadata: filter by target audience (e.g., "developers", "marketers")', }, // Common pagination limit: { type: 'number', description: 'Maximum number of results. Default 20.', default: 20, minimum: 1, maximum: 100, }, offset: { type: 'number', description: 'Pagination offset. Default 0.', default: 0, minimum: 0, }, }, }, }, { name: 'validate_workflow', description: `Full workflow validation: structure, connections, expressions, AI tools. Returns errors/warnings/fixes. Essential before deploy.`, inputSchema: { type: 'object', properties: { workflow: { type: 'object', description: 'The complete workflow JSON to validate. Must include nodes array and connections object.', }, options: { type: 'object', properties: { validateNodes: { type: 'boolean', description: 'Validate individual node configurations. Default true.', default: true, }, validateConnections: { type: 'boolean', description: 'Validate node connections and flow. Default true.', default: true, }, validateExpressions: { type: 'boolean', description: 'Validate n8n expressions syntax and references. Default true.', default: true, }, profile: { type: 'string', enum: ['minimal', 'runtime', 'ai-friendly', 'strict'], description: 'Validation profile for node validation. Default "runtime".', default: 'runtime', }, }, description: 'Optional validation settings', }, }, required: ['workflow'], additionalProperties: false, }, outputSchema: { type: 'object', properties: { valid: { type: 'boolean' }, summary: { type: 'object', properties: { totalNodes: { type: 'number' }, enabledNodes: { type: 'number' }, triggerNodes: { type: 'number' }, validConnections: { type: 'number' }, invalidConnections: { type: 'number' }, expressionsValidated: { type: 'number' }, errorCount: { type: 'number' }, warningCount: { type: 'number' } } }, errors: { type: 'array', items: { type: 'object', properties: { node: { type: 'string' }, message: { type: 'string' }, details: { type: 'string' } } } }, warnings: { type: 'array', items: { type: 'object', properties: { node: { type: 'string' }, message: { type: 'string' }, details: { type: 'string' } } } }, suggestions: { type: 'array', items: { type: 'string' } } }, required: ['valid', 'summary'] }, }, ];
- Core search logic in NodeRepository using SQL LIKE queries (legacy/fallback). Note indicates MCP server uses optimized FTS5 implementation.searchNodes(query: string, mode: 'OR' | 'AND' | 'FUZZY' = 'OR', limit: number = 20): any[] { let sql = ''; const params: any[] = []; if (mode === 'FUZZY') { // Simple fuzzy search sql = ` SELECT * FROM nodes WHERE node_type LIKE ? OR display_name LIKE ? OR description LIKE ? ORDER BY display_name LIMIT ? `; const fuzzyQuery = `%${query}%`; params.push(fuzzyQuery, fuzzyQuery, fuzzyQuery, limit); } else { // OR/AND mode const words = query.split(/\s+/).filter(w => w.length > 0); const conditions = words.map(() => '(node_type LIKE ? OR display_name LIKE ? OR description LIKE ?)' ); const operator = mode === 'AND' ? ' AND ' : ' OR '; sql = ` SELECT * FROM nodes WHERE ${conditions.join(operator)} ORDER BY display_name LIMIT ? `; for (const word of words) { const searchTerm = `%${word}%`; params.push(searchTerm, searchTerm, searchTerm); } params.push(limit); } const rows = this.db.prepare(sql).all(...params) as any[]; return rows.map(row => this.parseNodeRow(row)); }