Files
n8n-mcp/docs/MCP_REVISED_IMPLEMENTATION_STRATEGY.md
czlonkowski 1884d5babf feat: implement AI-optimized MCP tools with 95% size reduction
- Add get_node_essentials tool for 10-20 essential properties only
- Add search_node_properties for targeted property search
- Add get_node_for_task with 14 pre-configured templates
- Add validate_node_config for comprehensive validation
- Add get_property_dependencies for visibility analysis
- Implement PropertyFilter service with curated essentials
- Implement ExampleGenerator with working examples
- Implement TaskTemplates for common workflows
- Implement ConfigValidator with security checks
- Implement PropertyDependencies for dependency analysis
- Enhance property descriptions to 100% coverage
- Add version information to essentials response
- Update documentation with new tools

Response sizes reduced from 100KB+ to <5KB for better AI agent usability.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-16 12:37:45 +02:00

381 lines
12 KiB
Markdown

# MCP Tools Implementation Strategy (Revised)
## Executive Summary
After analyzing the actual n8n-mcp implementation, the core issue isn't data extraction or storage - you already have excellent property extraction with complete schemas stored as JSON. The real problem is **information presentation** - returning all 200+ properties at once overwhelms AI agents. This revised strategy focuses on intelligent filtering and presentation layers on top of your existing data.
## Current System Strengths
1. **Comprehensive property extraction** - All properties with types, options, displayOptions, etc.
2. **Efficient storage** - JSON columns allow flexibility while maintaining query performance
3. **Complete metadata** - Operations, credentials, documentation all properly extracted
4. **Version handling** - Supports versioned nodes like HTTPRequest v1/v2/v3
## Revised Implementation Approach
### Core Principle: Filter, Don't Restructure
Instead of changing how data is stored, we'll add intelligent filtering layers:
```typescript
// Your current data flow:
n8n source PropertyExtractor JSON properties Database get_node_info 100KB response
// New data flow:
n8n source PropertyExtractor JSON properties Database PropertyFilter Smart Tools 5KB response
```
## Phase 1: Intelligent Property Filtering (Week 1)
### 1.1 Enhanced get_node_essentials
**Implementation** - Add to `src/mcp/server.ts`:
```typescript
case "get_node_essentials": {
const { nodeType } = request.params.arguments as { nodeType: string };
const node = await service.getNodeByType(nodeType);
if (!node) throw new Error(`Node type ${nodeType} not found`);
// Parse existing properties
const allProperties = JSON.parse(node.properties_schema || '[]');
// Filter to essentials using smart rules
const essentials = PropertyFilter.getEssentials(allProperties, nodeType);
return {
nodeType: node.node_type,
displayName: node.display_name,
description: node.description,
requiredProperties: essentials.required,
commonProperties: essentials.common,
examples: ExampleGenerator.getExamples(nodeType, essentials),
totalPropertiesAvailable: allProperties.length,
operations: JSON.parse(node.operations || '[]')
};
}
```
### 1.2 Create PropertyFilter Service
Create `src/services/property-filter.ts`:
```typescript
export class PropertyFilter {
// Curated lists of essential properties per node type
private static ESSENTIAL_PROPERTIES: Record<string, EssentialConfig> = {
'nodes-base.httpRequest': {
required: ['url'],
common: ['method', 'authentication', 'sendBody', 'contentType', 'sendHeaders'],
categoryPriority: ['basic', 'authentication', 'request', 'response', 'advanced']
},
'nodes-base.webhook': {
required: [],
common: ['httpMethod', 'path', 'responseMode', 'responseData'],
categoryPriority: ['basic', 'response', 'advanced']
}
// Add more nodes...
};
static getEssentials(properties: any[], nodeType: string): FilteredProperties {
const config = this.ESSENTIAL_PROPERTIES[nodeType] || this.inferEssentials(properties);
const required = properties.filter(p =>
config.required.includes(p.name) || p.required === true
);
const common = properties.filter(p =>
config.common.includes(p.name) && !required.find(r => r.name === p.name)
);
// Simplify property structure for AI consumption
return {
required: required.map(p => this.simplifyProperty(p)),
common: common.map(p => this.simplifyProperty(p))
};
}
private static simplifyProperty(prop: any): SimplifiedProperty {
return {
name: prop.name,
displayName: prop.displayName,
type: prop.type,
description: prop.description || '',
required: prop.required || false,
default: prop.default,
options: prop.options?.map((opt: any) => ({
value: typeof opt === 'string' ? opt : opt.value,
label: typeof opt === 'string' ? opt : opt.name
})),
// Only include display conditions if simple
showWhen: this.simplifyDisplayConditions(prop.displayOptions?.show),
// Add usage hint
usageHint: this.getUsageHint(prop)
};
}
private static inferEssentials(properties: any[]): EssentialConfig {
// Fallback logic for nodes without curated lists
const required = properties.filter(p => p.required).map(p => p.name);
const common = properties
.filter(p => !p.displayOptions && !p.required)
.slice(0, 5)
.map(p => p.name);
return { required, common, categoryPriority: [] };
}
}
```
### 1.3 Smart Property Search
Enhance the existing structure with property search:
```typescript
case "search_node_properties": {
const { nodeType, query, category } = request.params.arguments as {
nodeType: string;
query: string;
category?: string;
};
const node = await service.getNodeByType(nodeType);
if (!node) throw new Error(`Node type ${nodeType} not found`);
const allProperties = JSON.parse(node.properties_schema || '[]');
const matches = PropertySearch.search(allProperties, query, category);
return {
query,
category,
matches: matches.map(match => ({
...PropertyFilter.simplifyProperty(match.property),
path: match.path,
relevanceScore: match.score,
context: match.context
})),
totalMatches: matches.length
};
}
```
## Phase 2: Configuration Intelligence (Week 2)
### 2.1 Task-Based Configuration
Create `src/services/task-configurator.ts`:
```typescript
export class TaskConfigurator {
private static TASK_TEMPLATES: Record<string, TaskTemplate> = {
'post_json_request': {
nodeType: 'nodes-base.httpRequest',
description: 'Make a POST request with JSON data',
configuration: {
method: 'POST',
sendBody: true,
contentType: 'json',
specifyBody: 'json'
},
userMustProvide: ['url', 'jsonBody'],
conditionalProperties: {
'sendBody=true': ['contentType', 'specifyBody'],
'contentType=json': ['jsonBody']
}
}
// More templates...
};
static getTaskConfiguration(task: string): TaskConfiguration {
const template = this.TASK_TEMPLATES[task];
if (!template) throw new Error(`Unknown task: ${task}`);
// Resolve all properties needed for this configuration
const node = await service.getNodeByType(template.nodeType);
const allProperties = JSON.parse(node.properties_schema || '[]');
// Get properties mentioned in template
const relevantProperties = this.extractRelevantProperties(
allProperties,
template.configuration,
template.conditionalProperties
);
return {
task,
nodeType: template.nodeType,
description: template.description,
configuration: template.configuration,
properties: relevantProperties,
userMustProvide: template.userMustProvide,
propertyChain: this.buildPropertyChain(template.conditionalProperties)
};
}
}
```
### 2.2 Configuration Validator
```typescript
export class ConfigurationValidator {
static async validate(nodeType: string, config: any): Promise<ValidationResult> {
const node = await service.getNodeByType(nodeType);
const properties = JSON.parse(node.properties_schema || '[]');
const errors: ValidationError[] = [];
const warnings: ValidationWarning[] = [];
const suggestions: string[] = [];
// Check required properties
const requiredProps = properties.filter(p => p.required);
for (const prop of requiredProps) {
if (!(prop.name in config)) {
errors.push({
type: 'missing_required',
property: prop.name,
message: `Required property '${prop.displayName}' is missing`
});
}
}
// Check property visibility
const visibleProps = this.getVisibleProperties(properties, config);
const configuredButHidden = Object.keys(config).filter(
key => !visibleProps.find(p => p.name === key)
);
if (configuredButHidden.length > 0) {
warnings.push({
type: 'hidden_properties',
message: `Properties ${configuredButHidden.join(', ')} won't be used with current configuration`,
properties: configuredButHidden
});
}
// Smart suggestions based on config
if (config.method === 'POST' && !config.sendBody) {
suggestions.push('POST requests typically send a body - consider setting sendBody=true');
}
return {
valid: errors.length === 0,
errors,
warnings,
suggestions,
visibleProperties: visibleProps.map(p => p.name),
hiddenProperties: properties
.filter(p => !visibleProps.includes(p))
.map(p => p.name)
};
}
private static getVisibleProperties(properties: any[], config: any): any[] {
return properties.filter(prop => {
if (!prop.displayOptions) return true;
// Check show conditions
if (prop.displayOptions.show) {
return this.evaluateConditions(prop.displayOptions.show, config);
}
// Check hide conditions
if (prop.displayOptions.hide) {
return !this.evaluateConditions(prop.displayOptions.hide, config);
}
return true;
});
}
}
```
## Phase 3: Advanced Features (Week 3-4)
### 3.1 Property Resolution Helper
```typescript
case "resolve_property_visibility": {
const { nodeType, currentConfig, targetProperty } = request.params.arguments;
const resolver = new PropertyResolver();
const path = resolver.getPathToProperty(nodeType, currentConfig, targetProperty);
return {
targetProperty,
currentlyVisible: path.isVisible,
requiredChanges: path.changes,
steps: path.steps,
alternatives: path.alternatives
};
}
```
### 3.2 Workflow Pattern Analyzer
```typescript
export class WorkflowPatternAnalyzer {
// Analyze common patterns from existing workflows
static async suggestConfiguration(context: {
previousNode?: string;
nextNode?: string;
workflowObjective?: string;
}): Promise<ConfigurationSuggestion> {
// Use patterns to suggest optimal configuration
}
}
```
## Implementation Priority & Timeline
### Week 1: Core Filtering
- [x] Implement PropertyFilter service
- [x] Create get_node_essentials tool
- [x] Add curated essential lists for top 20 nodes
- [x] Implement property search within nodes
### Week 2: Intelligence Layer
- [ ] Build TaskConfigurator with 10 common templates
- [ ] Implement ConfigurationValidator
- [ ] Add property visibility resolver
- [ ] Create example generator
### Week 3: Testing & Refinement
- [ ] Test with all 525 nodes
- [ ] Refine essential property lists
- [ ] Add more task templates
- [ ] Performance optimization
### Week 4: Advanced Features
- [ ] Workflow pattern analysis
- [ ] Context-aware suggestions
- [ ] Property dependency graphs
- [ ] Auto-completion support
## Key Differences from Original Strategy
1. **No database schema changes needed** - Work with existing JSON structure
2. **Focus on filtering, not restructuring** - Properties are already well-structured
3. **Build intelligence layers** - Add smart filtering and validation on top
4. **Leverage existing extraction** - Don't duplicate the excellent work already done
5. **Progressive enhancement** - Each tool adds value independently
## Success Metrics
| Metric | Current | Target | How to Measure |
|--------|---------|--------|----------------|
| Properties returned | 200+ | 10-20 | get_node_essentials response |
| Response size | 100KB+ | <5KB | JSON.stringify().length |
| Time to find property | 30+ seconds | <5 seconds | Property search tool |
| Configuration errors | 40% | <10% | Validation success rate |
| AI success rate | Low | >90% | Successful workflow creation |
## Next Steps
1. **Implement PropertyFilter** with hardcoded essentials for HTTP Request node
2. **Test size reduction** with real AI agents
3. **Iterate on essential property lists** based on usage
4. **Add task templates** for common use cases
5. **Build validation layer** to catch errors early
This revised strategy works WITH your existing architecture rather than against it, delivering immediate value while building toward a comprehensive solution.