Skip to main content
Glama

search_templates

Read-onlyIdempotent

Search n8n workflow templates by keyword, node types, tasks, or metadata filters to find automation solutions for specific needs.

Instructions

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.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
searchModeNoSearch mode. keyword=text search (default), by_nodes=find by node types, by_task=curated task templates, by_metadata=filter by complexity/serviceskeyword
queryNoFor searchMode=keyword: search keyword (e.g., "chatbot")
fieldsNoFor searchMode=keyword: fields to include in response. Default: all fields.
nodeTypesNoFor searchMode=by_nodes: array of node types (e.g., ["n8n-nodes-base.httpRequest", "n8n-nodes-base.slack"])
taskNoFor searchMode=by_task: the type of task
categoryNoFor searchMode=by_metadata: filter by category (e.g., "automation", "integration")
complexityNoFor searchMode=by_metadata: filter by complexity level
maxSetupMinutesNoFor searchMode=by_metadata: maximum setup time in minutes
minSetupMinutesNoFor searchMode=by_metadata: minimum setup time in minutes
requiredServiceNoFor searchMode=by_metadata: filter by required service (e.g., "openai", "slack")
targetAudienceNoFor searchMode=by_metadata: filter by target audience (e.g., "developers", "marketers")
limitNoMaximum number of results. Default 20.
offsetNoPagination offset. Default 0.

Implementation Reference

  • Primary input/output schema definition for the search_templates MCP tool, including all parameters and validation rules.
    {
        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',
                },
                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.',
                },
                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"])',
                },
                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',
                },
                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")',
                },
                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,
                },
            },
        },
    },
  • Detailed documentation object for search_templates tool, used by tools_documentation tool to provide usage examples and parameter descriptions.
    import { ToolDocumentation } from '../types';
    
    export const searchTemplatesDoc: ToolDocumentation = {
      name: 'search_templates',
      category: 'templates',
      essentials: {
        description: 'Unified template search with multiple modes: keyword search, by node types, by task type, or by metadata. 2,700+ templates available.',
        keyParameters: ['searchMode', 'query', 'nodeTypes', 'task', 'limit'],
        example: 'search_templates({searchMode: "by_task", task: "webhook_processing"})',
        performance: 'Fast (<100ms) - FTS5 full-text search',
        tips: [
          'searchMode="keyword" (default): Search by name/description',
          'searchMode="by_nodes": Find templates using specific nodes',
          'searchMode="by_task": Get curated templates for common tasks',
          'searchMode="by_metadata": Filter by complexity, services, audience'
        ]
      },
      full: {
        description: `**Search Modes:**
    - keyword (default): Full-text search across template names and descriptions
    - by_nodes: Find templates that use specific node types
    - by_task: Get curated templates for predefined task categories
    - by_metadata: Filter by complexity, setup time, required services, or target audience
    
    **Available Task Types (for searchMode="by_task"):**
    ai_automation, data_sync, webhook_processing, email_automation, slack_integration, data_transformation, file_processing, scheduling, api_integration, database_operations`,
        parameters: {
          searchMode: {
            type: 'string',
            required: false,
            description: 'Search mode: "keyword" (default), "by_nodes", "by_task", "by_metadata"'
          },
          query: {
            type: 'string',
            required: false,
            description: 'For searchMode=keyword: Search keywords (e.g., "chatbot", "automation")'
          },
          nodeTypes: {
            type: 'array',
            required: false,
            description: 'For searchMode=by_nodes: Array of node types (e.g., ["n8n-nodes-base.httpRequest", "n8n-nodes-base.slack"])'
          },
          task: {
            type: 'string',
            required: false,
            description: 'For searchMode=by_task: Task type (ai_automation, data_sync, webhook_processing, email_automation, slack_integration, data_transformation, file_processing, scheduling, api_integration, database_operations)'
          },
          complexity: {
            type: 'string',
            required: false,
            description: 'For searchMode=by_metadata: Filter by complexity ("simple", "medium", "complex")'
          },
          maxSetupMinutes: {
            type: 'number',
            required: false,
            description: 'For searchMode=by_metadata: Maximum setup time in minutes (5-480)'
          },
          minSetupMinutes: {
            type: 'number',
            required: false,
            description: 'For searchMode=by_metadata: Minimum setup time in minutes (5-480)'
          },
          requiredService: {
            type: 'string',
            required: false,
            description: 'For searchMode=by_metadata: Filter by required service (e.g., "openai", "slack", "google")'
          },
          targetAudience: {
            type: 'string',
            required: false,
            description: 'For searchMode=by_metadata: Filter by target audience (e.g., "developers", "marketers")'
          },
          category: {
            type: 'string',
            required: false,
            description: 'For searchMode=by_metadata: Filter by category (e.g., "automation", "integration")'
          },
          fields: {
            type: 'array',
            required: false,
            description: 'For searchMode=keyword: Fields to include (id, name, description, author, nodes, views, created, url, metadata)'
          },
          limit: {
            type: 'number',
            required: false,
            description: 'Maximum results (default 20, max 100)'
          },
          offset: {
            type: 'number',
            required: false,
            description: 'Pagination offset (default 0)'
          }
        },
        returns: `Returns an object containing:
    - templates: Array of matching templates
      - id: Template ID for get_template()
      - name: Template name
      - description: What the workflow does
      - author: Creator information
      - nodes: Array of node types used
      - views: Popularity metric
      - created: Creation date
      - url: Link to template
      - metadata: AI-generated metadata (complexity, services, etc.)
    - totalFound: Total matching templates
    - searchMode: The mode used`,
        examples: [
          '// Keyword search (default)\nsearch_templates({query: "chatbot"})',
          '// Find templates using specific nodes\nsearch_templates({searchMode: "by_nodes", nodeTypes: ["n8n-nodes-base.httpRequest", "n8n-nodes-base.slack"]})',
          '// Get templates for a task type\nsearch_templates({searchMode: "by_task", task: "webhook_processing"})',
          '// Filter by metadata\nsearch_templates({searchMode: "by_metadata", complexity: "simple", requiredService: "openai"})',
          '// Combine metadata filters\nsearch_templates({searchMode: "by_metadata", maxSetupMinutes: 30, targetAudience: "developers"})'
        ],
        useCases: [
          'Find workflows by business purpose (keyword search)',
          'Find templates using specific integrations (by_nodes)',
          'Get pre-built solutions for common tasks (by_task)',
          'Filter by complexity for team skill level (by_metadata)',
          'Find templates requiring specific services (by_metadata)'
        ],
        performance: `Fast performance across all modes:
    - keyword: <50ms with FTS5 indexing
    - by_nodes: <100ms with indexed lookups
    - by_task: <50ms from curated cache
    - by_metadata: <100ms with filtered queries`,
        bestPractices: [
          'Use searchMode="by_task" for common automation patterns',
          'Use searchMode="by_nodes" when you know which integrations you need',
          'Use searchMode="keyword" for general discovery',
          'Combine by_metadata filters for precise matching',
          'Use get_template(id) to get the full workflow JSON'
        ],
        pitfalls: [
          'searchMode="keyword" searches names/descriptions, not node types',
          'by_nodes requires full node type with prefix (n8n-nodes-base.xxx)',
          'by_metadata filters may return fewer results',
          'Not all templates have complete metadata'
        ],
        relatedTools: ['get_template', 'search_nodes', 'validate_workflow']
      }
    };
  • Core handler logic for keyword-based template search, delegating to repository and formatting results with pagination.
    async searchTemplates(query, limit = 20, offset = 0, fields) {
        const templates = this.repository.searchTemplates(query, limit, offset);
        const total = this.repository.getSearchCount(query);
        const items = fields
            ? templates.map(t => this.formatTemplateWithFields(t, fields))
            : templates.map(t => this.formatTemplateInfo(t));
        return {
            items,
            total,
            limit,
            offset,
            hasMore: offset + limit < total
        };
    }
  • Fallback LIKE-based search implementation for templates when FTS5 is unavailable.
    searchTemplatesLIKE(query, limit = 20, offset = 0) {
        const likeQuery = `%${query}%`;
        logger_1.logger.debug(`Using LIKE search with pattern: ${likeQuery}`);
        const results = this.db.prepare(`
      SELECT * FROM templates 
      WHERE name LIKE ? OR description LIKE ?
      ORDER BY views DESC, created_at DESC
      LIMIT ? OFFSET ?
    `).all(likeQuery, likeQuery, limit, offset);
        logger_1.logger.debug(`LIKE search returned ${results.length} results`);
        return results.map(t => this.decompressWorkflow(t));
    }
  • Advanced metadata-based search using JSON queries on template metadata, with optimization for ordering and pagination.
    searchTemplatesByMetadata(filters, limit = 20, offset = 0) {
        const startTime = Date.now();
        const { conditions, params } = this.buildMetadataFilterConditions(filters);
        const idsQuery = `
      SELECT id FROM templates
      WHERE ${conditions.join(' AND ')}
      ORDER BY views DESC, created_at DESC, id ASC
      LIMIT ? OFFSET ?
    `;
        params.push(limit, offset);
        const ids = this.db.prepare(idsQuery).all(...params);
        const phase1Time = Date.now() - startTime;
        if (ids.length === 0) {
            logger_1.logger.debug('Metadata search found 0 results', { filters, phase1Ms: phase1Time });
            return [];
        }
        const idValues = ids.map(r => r.id).filter(id => typeof id === 'number' && id > 0 && Number.isInteger(id));
        if (idValues.length === 0) {
            logger_1.logger.warn('No valid IDs after filtering', { filters, originalCount: ids.length });
            return [];
        }
        if (idValues.length !== ids.length) {
            logger_1.logger.warn('Some IDs were filtered out as invalid', {
                original: ids.length,
                valid: idValues.length,
                filtered: ids.length - idValues.length
            });
        }
        const phase2Start = Date.now();
        const orderedQuery = `
      WITH ordered_ids(id, sort_order) AS (
        VALUES ${idValues.map((id, idx) => `(${id}, ${idx})`).join(', ')}
      )
      SELECT t.* FROM templates t
      INNER JOIN ordered_ids o ON t.id = o.id
      ORDER BY o.sort_order
    `;
        const results = this.db.prepare(orderedQuery).all();
        const phase2Time = Date.now() - phase2Start;
        logger_1.logger.debug(`Metadata search found ${results.length} results`, {
            filters,
            count: results.length,
            phase1Ms: phase1Time,
            phase2Ms: phase2Time,
            totalMs: Date.now() - startTime,
            optimization: 'two-phase-with-ordering'
        });
        return results.map(t => this.decompressWorkflow(t));
    }
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and idempotentHint=true, so the agent knows this is a safe, repeatable read operation. The description adds useful context about the four distinct search modes, which helps the agent understand behavioral variations. However, it doesn't describe pagination behavior, rate limits, or authentication requirements beyond what annotations provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is perfectly concise - a single sentence that efficiently explains the core functionality (multiple search modes) followed by a clear enumeration of those modes. Every word earns its place with zero wasted text.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a search tool with rich annotations (readOnly, idempotent) and comprehensive schema coverage, the description provides adequate context about the different search modes. However, without an output schema, the description could benefit from mentioning what kind of results to expect (template objects with fields like id, name, etc.).

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 100% schema description coverage, the input schema already documents all 13 parameters thoroughly. The description adds marginal value by summarizing the four search modes, but doesn't provide additional parameter semantics beyond what's already in the schema descriptions. The baseline of 3 is appropriate when the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose as 'Search templates with multiple modes', which is a specific verb+resource combination. However, it doesn't explicitly differentiate this search functionality from sibling tools like 'search_nodes' or explain why one would search templates versus nodes or workflows.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context about when to use each search mode (keyword for text search, by_nodes for node-based filtering, etc.), which helps the agent understand the different use cases. However, it doesn't explicitly state when NOT to use this tool or mention alternatives like browsing templates through other means.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/czlonkowski/n8n-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server