diff --git a/data/nodes.db b/data/nodes.db index d1dc9b9..62e504a 100644 Binary files a/data/nodes.db and b/data/nodes.db differ diff --git a/package-lock.json b/package-lock.json index d5cd34c..2f42013 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "n8n-mcp", - "version": "2.7.11", + "version": "2.7.17", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "n8n-mcp", - "version": "2.7.11", + "version": "2.7.17", "license": "MIT", "dependencies": { "@modelcontextprotocol/sdk": "^1.13.2", diff --git a/package.json b/package.json index 2485542..d425789 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "n8n-mcp", - "version": "2.7.16", + "version": "2.7.17", "description": "Integration between n8n workflow automation and Model Context Protocol (MCP)", "main": "dist/index.js", "bin": { diff --git a/src/mcp/server.ts b/src/mcp/server.ts index b039fa7..7f33d3e 100644 --- a/src/mcp/server.ts +++ b/src/mcp/server.ts @@ -13,7 +13,6 @@ import { logger } from '../utils/logger'; import { NodeRepository } from '../database/node-repository'; import { DatabaseAdapter, createDatabaseAdapter } from '../database/database-adapter'; import { PropertyFilter } from '../services/property-filter'; -import { ExampleGenerator } from '../services/example-generator'; import { TaskTemplates } from '../services/task-templates'; import { ConfigValidator } from '../services/config-validator'; import { EnhancedConfigValidator, ValidationMode, ValidationProfile } from '../services/enhanced-config-validator'; @@ -1061,9 +1060,6 @@ Full documentation is being prepared. For now, use get_node_essentials for confi // Get essential properties const essentials = PropertyFilter.getEssentials(allProperties, node.nodeType); - // Generate examples - const examples = ExampleGenerator.getExamples(node.nodeType, essentials); - // Get operations (already parsed by repository) const operations = node.operations || []; @@ -1082,7 +1078,7 @@ Full documentation is being prepared. For now, use get_node_essentials for confi action: op.action, resource: op.resource })), - examples, + // Examples removed - use validate_node_operation for working configurations metadata: { totalProperties: allProperties.length, isAITool: node.isAITool, diff --git a/src/mcp/tool-docs/configuration/get-node-essentials.ts b/src/mcp/tool-docs/configuration/get-node-essentials.ts index b3559d4..cc49df0 100644 --- a/src/mcp/tool-docs/configuration/get-node-essentials.ts +++ b/src/mcp/tool-docs/configuration/get-node-essentials.ts @@ -4,48 +4,54 @@ export const getNodeEssentialsDoc: ToolDocumentation = { name: 'get_node_essentials', category: 'configuration', essentials: { - description: 'Returns only the most commonly-used properties for a node (10-20 fields) with working examples. Response is 95% smaller than get_node_info (5KB vs 100KB+). Essential properties include required fields, common options, and authentication settings.', + description: 'Returns only the most commonly-used properties for a node (10-20 fields). Response is 95% smaller than get_node_info (5KB vs 100KB+). Essential properties include required fields, common options, and authentication settings. Use validate_node_operation for working configurations.', keyParameters: ['nodeType'], example: 'get_node_essentials({nodeType: "nodes-base.slack"})', performance: '<10ms, ~5KB response', tips: [ 'Always use this before get_node_info', - 'Includes ready-to-use examples', - 'Perfect for configuring nodes quickly' + 'Use validate_node_operation for examples', + 'Perfect for understanding node structure' ] }, full: { - description: 'Returns a curated subset of node properties focusing on the most commonly-used fields. Essential properties are hand-picked for each node type and include: required fields, primary operations, authentication options, and the most frequent configuration patterns. Each response includes working examples you can copy and modify.', + description: 'Returns a curated subset of node properties focusing on the most commonly-used fields. Essential properties are hand-picked for each node type and include: required fields, primary operations, authentication options, and the most frequent configuration patterns. NOTE: Examples have been removed to avoid confusion - use validate_node_operation to get working configurations with proper validation.', parameters: { nodeType: { type: 'string', description: 'Full node type with prefix, e.g., "nodes-base.slack", "nodes-base.httpRequest"', required: true } }, returns: `Object containing: { "nodeType": "nodes-base.slack", - "essentialProperties": { - "resource": ["channel", "message", "user"], - "operation": ["post", "update", "delete"], - "authentication": ["accessToken", "oAuth2"], - "channel": "Channel ID or name", - "text": "Message content", - "blocks": "Advanced formatting (optional)" - }, - "examples": { - "postMessage": { - "resource": "message", - "operation": "post", - "channel": "#general", - "text": "Hello from n8n!" + "displayName": "Slack", + "description": "Consume Slack API", + "category": "output", + "version": "2.3", + "requiredProperties": [], // Most nodes have no strictly required fields + "commonProperties": [ + { + "name": "resource", + "displayName": "Resource", + "type": "options", + "options": ["channel", "message", "user"], + "default": "message" }, - "withBlocks": { - "resource": "message", - "operation": "post", - "blocks": [{"type": "section", "text": {"type": "mrkdwn", "text": "Hello"}}] - } - }, - "authentication": { - "required": true, - "options": ["accessToken", "oAuth2"] + { + "name": "operation", + "displayName": "Operation", + "type": "options", + "options": ["post", "update", "delete"], + "default": "post" + }, + // ... 10-20 most common properties + ], + "operations": [ + {"name": "Post", "description": "Post a message"}, + {"name": "Update", "description": "Update a message"} + ], + "metadata": { + "totalProperties": 121, + "isAITool": false, + "hasCredentials": true } }`, examples: [ @@ -55,18 +61,18 @@ export const getNodeEssentialsDoc: ToolDocumentation = { '// Workflow: search → essentials → validate', 'const nodes = search_nodes({query: "database"});', 'const mysql = get_node_essentials({nodeType: "nodes-base.mySql"});', - 'validate_node_minimal("nodes-base.mySql", mysql.examples.select);' + 'validate_node_operation("nodes-base.mySql", {operation: "select"}, "minimal");' ], useCases: [ - 'Quickly configure nodes without information overload', - 'Get working examples for common operations', + 'Quickly understand node structure without information overload', + 'Identify which properties are most important', 'Learn node basics before diving into advanced features', 'Build workflows faster with curated property sets' ], performance: '<10ms response time, ~5KB payload (vs 100KB+ for full schema)', bestPractices: [ 'Always start with essentials, only use get_node_info if needed', - 'Copy examples as configuration starting points', + 'Use validate_node_operation to get working configurations', 'Check authentication requirements first', 'Use search_node_properties if specific property not in essentials' ], diff --git a/src/services/enhanced-config-validator.ts b/src/services/enhanced-config-validator.ts index 51bed40..db675af 100644 --- a/src/services/enhanced-config-validator.ts +++ b/src/services/enhanced-config-validator.ts @@ -7,7 +7,6 @@ import { ConfigValidator, ValidationResult, ValidationError, ValidationWarning } from './config-validator'; import { NodeSpecificValidators, NodeValidationContext } from './node-specific-validators'; -import { ExampleGenerator } from './example-generator'; export type ValidationMode = 'full' | 'operation' | 'minimal'; export type ValidationProfile = 'strict' | 'runtime' | 'ai-friendly' | 'minimal'; @@ -78,10 +77,7 @@ export class EnhancedConfigValidator extends ConfigValidator { // Deduplicate errors enhancedResult.errors = this.deduplicateErrors(enhancedResult.errors); - // Add examples from ExampleGenerator if there are errors - if (enhancedResult.errors.length > 0) { - this.addExamplesFromGenerator(nodeType, enhancedResult); - } + // Examples removed - use validate_node_operation for configuration guidance // Generate next steps based on errors enhancedResult.nextSteps = this.generateNextSteps(enhancedResult); @@ -253,16 +249,7 @@ export class EnhancedConfigValidator extends ConfigValidator { const { resource, operation } = result.operation || {}; if (resource === 'message' && operation === 'send') { - // Add example for sending a message - result.examples?.push({ - description: 'Send a simple text message to a channel', - config: { - resource: 'message', - operation: 'send', - channel: '#general', - text: 'Hello from n8n!' - } - }); + // Examples removed - validation focuses on error detection // Check for common issues if (!config.channel && !config.channelId) { @@ -274,15 +261,6 @@ export class EnhancedConfigValidator extends ConfigValidator { channelError.fix = 'Add channel: "#general" or use a channel ID like "C1234567890"'; } } - } else if (resource === 'user' && operation === 'get') { - result.examples?.push({ - description: 'Get user information by email', - config: { - resource: 'user', - operation: 'get', - user: 'user@example.com' - } - }); } } @@ -296,17 +274,7 @@ export class EnhancedConfigValidator extends ConfigValidator { const { operation } = result.operation || {}; if (operation === 'append') { - result.examples?.push({ - description: 'Append data to a spreadsheet', - config: { - operation: 'append', - sheetId: '1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms', - range: 'Sheet1!A:B', - options: { - valueInputMode: 'USER_ENTERED' - } - } - }); + // Examples removed - validation focuses on configuration correctness // Validate range format if (config.range && !config.range.includes('!')) { @@ -327,33 +295,7 @@ export class EnhancedConfigValidator extends ConfigValidator { config: Record, result: EnhancedValidationResult ): void { - // Add common examples based on method - if (config.method === 'GET') { - result.examples?.push({ - description: 'GET request with query parameters', - config: { - method: 'GET', - url: 'https://api.example.com/users', - queryParameters: { - parameters: [ - { name: 'page', value: '1' }, - { name: 'limit', value: '10' } - ] - } - } - }); - } else if (config.method === 'POST') { - result.examples?.push({ - description: 'POST request with JSON body', - config: { - method: 'POST', - url: 'https://api.example.com/users', - sendBody: true, - bodyContentType: 'json', - jsonBody: JSON.stringify({ name: 'John Doe', email: 'john@example.com' }) - } - }); - } + // Examples removed - validation provides error messages and fixes instead } /** @@ -383,56 +325,13 @@ export class EnhancedConfigValidator extends ConfigValidator { steps.push('Consider addressing warnings for better reliability'); } - if (result.examples && result.examples.length > 0 && result.errors.length > 0) { - steps.push('See examples above for working configurations'); + if (result.errors.length > 0) { + steps.push('Fix the errors above following the provided suggestions'); } return steps; } - /** - * Add examples from ExampleGenerator to help fix validation errors - */ - private static addExamplesFromGenerator( - nodeType: string, - result: EnhancedValidationResult - ): void { - const examples = ExampleGenerator.getExamples(nodeType); - - if (!examples) { - return; - } - - // Add minimal example if there are missing required fields - if (result.errors.some(e => e.type === 'missing_required')) { - result.examples?.push({ - description: 'Minimal working configuration', - config: examples.minimal - }); - } - - // Add common example if available - if (examples.common) { - // Check if the common example matches the operation context - const { operation } = result.operation || {}; - const commonOp = examples.common.operation || examples.common.action; - - if (!operation || operation === commonOp) { - result.examples?.push({ - description: 'Common configuration pattern', - config: examples.common - }); - } - } - - // Add advanced example for complex validation errors - if (examples.advanced && result.errors.length > 2) { - result.examples?.push({ - description: 'Advanced configuration with all options', - config: examples.advanced - }); - } - } /** * Deduplicate errors based on property and type