How to Filter n8n-MCP Templates by Complexity, Target Audience, and Setup Time Using Metadata
n8n-MCP stores workflow templates with structured metadata in SQLite, enabling precise filtering by complexity level, target audience, and setup time using the TemplateService.searchTemplatesByMetadata method and SQLite's json_extract function.
The czlonkowski/n8n-mcp repository provides a metadata-driven template catalog that allows developers and AI assistants to discover n8n workflows matching specific technical requirements. By leveraging automatically generated JSON metadata and a type-safe filtering layer, you can quickly identify templates suited to your skill level and time constraints without downloading entire workflow payloads.
Understanding the Metadata Architecture
Every workflow template in n8n-MCP includes a metadata JSON document generated by the MetadataGenerator class. This document describes categories, implementation complexity, typical use-cases, estimated setup time, required external services, and the intended target audience.
Metadata Generation and Schema
The metadata generation logic resides in src/templates/metadata-generator.ts. The MetadataGenerator class uses a Zod schema (TemplateMetadataSchema) to validate and structure the metadata, ensuring consistency across the catalog. When a template is fetched from n8n.io, the generateSingle method (or the batch API) produces a TemplateMetadata object that conforms to this schema.
Database Storage Strategy
Metadata persists in the SQLite templates table within the metadata_json column. The TemplateRepository class in src/templates/template-repository.ts handles persistence through saveTemplate, which stores the JSON string alongside compressed workflow data. This separation allows the system to query metadata efficiently without decompressing full workflow payloads until necessary.
How Metadata Filtering Works
Filtering occurs entirely inside the TemplateService layer, which delegates database operations to TemplateRepository. The implementation uses SQLite's native JSON functions combined with parameterized queries to ensure both precision and security.
Building Filter Conditions with buildMetadataFilterConditions
The TemplateRepository.buildMetadataFilterConditions method (lines 654-702 in src/templates/template-repository.ts) creates a safe, parameterized list of SQL conditions based on supplied filters. Because metadata lives in a JSON column, the method uses SQLite's json_extract function for precise field extraction. All values inject via prepared-statement parameters, eliminating SQL-injection risk while supporting filters for complexity, target audience, minimum/maximum setup minutes, and categories.
The Two-Phase Query Strategy
The searchTemplatesByMetadata implementation employs a two-phase query for optimal performance:
- ID Selection Phase – Executes the metadata-filter SQL to retrieve only matching template IDs without fetching large workflow payloads
- Data Retrieval Phase – Retrieves full rows in the exact order found, decompressing stored workflows only when required
This approach minimizes memory usage and query latency, particularly when filtering large template catalogs.
Practical Implementation Examples
Filtering by Complexity, Audience, and Setup Time
To find templates matching specific criteria, initialize the DatabaseAdapter and TemplateService, then call searchTemplatesByMetadata with your filter object:
import { DatabaseAdapter } from '../database/database-adapter';
import { TemplateService } from '../templates/template-service';
const db = new DatabaseAdapter();
const service = new TemplateService(db);
async function findSimpleDevTemplates() {
const results = await service.searchTemplatesByMetadata(
{
complexity: 'simple',
targetAudience: 'developers',
maxSetupMinutes: 30,
},
20, // limit
0 // offset
);
console.log('Found', results.items.length, 'templates');
results.items.forEach(t => {
console.log(`- ${t.name} (≈${t.metadata?.estimated_setup_minutes} min)`);
});
}
findSimpleDevTemplates();
This example queries for simple workflows targeting developers with setup times under 30 minutes. The method signature and filter logic reside in src/templates/template-service.ts (lines 220-250), while the underlying SQL construction appears in src/templates/template-repository.ts.
Retrieving Available Target Audiences
To populate UI selectors or discover available filter values, use the convenience methods exposed by TemplateService:
import { DatabaseAdapter } from '../database/database-adapter';
import { TemplateService } from '../templates/template-service';
const db = new DatabaseAdapter();
const service = new TemplateService(db);
async function listAudiences() {
const audiences = await service.getAvailableTargetAudiences();
console.log('Target audiences in the catalog:', audiences);
}
listAudiences();
The getAvailableTargetAudiences method delegates to TemplateRepository.getAvailableTargetAudiences (lines 822-831 in src/templates/template-repository.ts), which queries distinct values from the metadata JSON column.
Combining Categories with Pagination
For catalog browsing with pagination, pass limit and offset parameters alongside category and complexity filters:
import { DatabaseAdapter } from '../database/database-adapter';
import { TemplateService } from '../templates/template-service';
const db = new DatabaseAdapter();
const service = new TemplateService(db);
async function fetchAutomationTemplates(page = 0) {
const limit = 10;
const offset = page * limit;
const response = await service.searchTemplatesByMetadata(
{
category: 'automation',
complexity: 'medium',
},
limit,
offset
);
console.log(`Page ${page + 1}:`);
response.items.forEach(t => console.log(`• ${t.name}`));
}
fetchAutomationTemplates(0);
Pagination parameters pass directly through to TemplateRepository.searchTemplatesByMetadata (lines 707-783), maintaining the two-phase query strategy for consistent performance across result pages.
Available Filter Methods in TemplateService
The service layer exposes several convenience methods that wrap the core filtering functionality:
getTemplatesByComplexity(complexity, limit, offset)– Retrieves templates matching a specific complexity level (e.g., "simple", "medium", "advanced")getAvailableCategories()– Returns all distinct category values present in the metadata cataloggetAvailableTargetAudiences()– Returns all distinct target audience identifiers for filtering UI generationsearchTemplatesByMetadata(filter, limit, offset)– The primary filtering interface accepting complex filter objects with multiple criteria
These methods reside in src/templates/template-service.ts and connect to the MCP server's tool definitions in src/mcp/tools.ts, enabling AI assistants and HTTP clients to request filtered templates without retrieving the entire dataset.
Summary
- Metadata Generation: The
MetadataGeneratorclass insrc/templates/metadata-generator.tscreates validated JSON metadata using Zod schemas when templates are fetched from n8n.io - Secure Storage: Metadata persists in the SQLite
templatestablemetadata_jsoncolumn, separate from compressed workflow payloads - Safe Filtering:
TemplateRepository.buildMetadataFilterConditionsuses parameterized SQL withjson_extractto prevent injection while filtering by complexity, audience, and setup time - Performance Optimization: The two-phase query strategy selects matching IDs first, then retrieves full records only when necessary
- Developer API:
TemplateServiceprovides high-level methods likesearchTemplatesByMetadataandgetAvailableTargetAudiencesfor easy integration
Frequently Asked Questions
How is template metadata generated in n8n-mcp?
The MetadataGenerator class processes each template using AI analysis to produce structured metadata. Located in src/templates/metadata-generator.ts, it validates output against TemplateMetadataSchema using Zod, ensuring fields like complexity, target_audience, and estimated_setup_minutes conform to expected types before storage.
What database functions enable metadata filtering?
The system uses SQLite's native json_extract function within the TemplateRepository.buildMetadataFilterConditions method to query specific JSON fields. All filter values pass through prepared statement parameters, ensuring type-safe, injection-proof queries against the metadata_json column in the templates table.
How does the two-phase query improve performance?
searchTemplatesByMetadata first executes a lightweight query returning only template IDs that match the metadata filters. In the second phase, it retrieves full rows—including decompressed workflow data—only for those specific IDs. This prevents loading and decompressing large workflow payloads for templates that do not match the filter criteria.
Can I combine multiple filter criteria in a single query?
Yes. The searchTemplatesByMetadata method accepts a filter object containing complexity, targetAudience, category, minSetupMinutes, and maxSetupMinutes simultaneously. The repository builds a compound SQL WHERE clause combining these criteria with AND logic, returning only templates matching all specified conditions.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →