fix: remove faulty auto-generated examples from MCP tools
- Remove examples from get_node_essentials responses - Remove examples from validate_node_operation when errors occur - Update documentation to reflect removal of examples - Keep helpful format hints in get_node_for_task (different purpose) The auto-generated examples were misleading AI agents with incorrect configurations (e.g., Slack "channel" vs "select" property). Tools now focus on validation and error messages instead of examples. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
BIN
data/nodes.db
BIN
data/nodes.db
Binary file not shown.
4
package-lock.json
generated
4
package-lock.json
generated
@@ -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",
|
||||
|
||||
@@ -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": {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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'
|
||||
],
|
||||
|
||||
@@ -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<string, any>,
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user