mirror of
https://github.com/czlonkowski/n8n-mcp.git
synced 2026-03-22 02:13:09 +00:00
fix: address code review Priority 1 fixes for AI validation
Improvements:
1. **Type Safety**: Replaced unsafe type casting in validateAIToolSubNode()
- Changed from `(validator as any)(node)` to explicit switch statement
- All 13 validators now called with proper type safety
- Eliminates TypeScript type bypass warnings
2. **Input Validation**: Added empty string checks in buildReverseConnectionMap()
- Validates source node names are non-empty strings
- Validates target node names are non-empty strings
- Prevents invalid connections from corrupting validation
3. **Magic Numbers Eliminated**: Extracted all hardcoded thresholds to constants
- MIN_DESCRIPTION_LENGTH_SHORT = 10
- MIN_DESCRIPTION_LENGTH_MEDIUM = 15
- MIN_DESCRIPTION_LENGTH_LONG = 20
- MIN_SYSTEM_MESSAGE_LENGTH = 20
- MAX_ITERATIONS_WARNING_THRESHOLD = 50
- MAX_TOPK_WARNING_THRESHOLD = 20
- Updated 12+ validation messages to reference constants
4. **URL Protocol Validation**: Added security check for HTTP Request Tool
- Validates URLs use http:// or https:// protocols only
- Gracefully handles n8n expressions ({{ }})
- Prevents potentially unsafe protocols (ftp, file, etc.)
Code Quality Improvements:
- Better error messages now include threshold values
- More maintainable - changing thresholds only requires updating constants
- Improved type safety throughout validation layer
- Enhanced input validation prevents edge case failures
Files Changed:
- src/services/ai-tool-validators.ts: Constants, URL validation, switch statement
- src/services/ai-node-validator.ts: Constants, empty string validation
Build Status: ✅ TypeScript compiles cleanly
Lint Status: ✅ No type errors
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -21,6 +21,10 @@ import {
|
||||
validateAIToolSubNode
|
||||
} from './ai-tool-validators';
|
||||
|
||||
// Validation constants
|
||||
const MIN_SYSTEM_MESSAGE_LENGTH = 20;
|
||||
const MAX_ITERATIONS_WARNING_THRESHOLD = 50;
|
||||
|
||||
/**
|
||||
* AI Connection Types
|
||||
* From spec lines 551-596
|
||||
@@ -60,6 +64,11 @@ export function buildReverseConnectionMap(
|
||||
|
||||
// Iterate through all connections
|
||||
for (const [sourceName, outputs] of Object.entries(workflow.connections)) {
|
||||
// Validate source name is not empty
|
||||
if (!sourceName || typeof sourceName !== 'string' || sourceName.trim() === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!outputs || typeof outputs !== 'object') continue;
|
||||
|
||||
// Iterate through all output types (main, error, ai_tool, ai_languageModel, etc.)
|
||||
@@ -72,6 +81,11 @@ export function buildReverseConnectionMap(
|
||||
for (const conn of connArray) {
|
||||
if (!conn || !conn.node) continue;
|
||||
|
||||
// Validate target node name is not empty
|
||||
if (typeof conn.node !== 'string' || conn.node.trim() === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Initialize array for target node if not exists
|
||||
if (!map.has(conn.node)) {
|
||||
map.set(conn.node, []);
|
||||
@@ -222,12 +236,12 @@ export function validateAIAgent(
|
||||
nodeName: node.name,
|
||||
message: `AI Agent "${node.name}" has no systemMessage. Consider adding one to define the agent's role, capabilities, and constraints.`
|
||||
});
|
||||
} else if (node.parameters.systemMessage.trim().length < 20) {
|
||||
} else if (node.parameters.systemMessage.trim().length < MIN_SYSTEM_MESSAGE_LENGTH) {
|
||||
issues.push({
|
||||
severity: 'info',
|
||||
nodeId: node.id,
|
||||
nodeName: node.name,
|
||||
message: `AI Agent "${node.name}" systemMessage is very short. Provide more detail about the agent's role and capabilities.`
|
||||
message: `AI Agent "${node.name}" systemMessage is very short (minimum ${MIN_SYSTEM_MESSAGE_LENGTH} characters recommended). Provide more detail about the agent's role and capabilities.`
|
||||
});
|
||||
}
|
||||
|
||||
@@ -291,12 +305,12 @@ export function validateAIAgent(
|
||||
message: `AI Agent "${node.name}" has maxIterations=${node.parameters.maxIterations}. Must be at least 1.`,
|
||||
code: 'MAX_ITERATIONS_TOO_LOW'
|
||||
});
|
||||
} else if (node.parameters.maxIterations > 50) {
|
||||
} else if (node.parameters.maxIterations > MAX_ITERATIONS_WARNING_THRESHOLD) {
|
||||
issues.push({
|
||||
severity: 'warning',
|
||||
nodeId: node.id,
|
||||
nodeName: node.name,
|
||||
message: `AI Agent "${node.name}" has maxIterations=${node.parameters.maxIterations}. Very high iteration counts may cause long execution times and high costs.`
|
||||
message: `AI Agent "${node.name}" has maxIterations=${node.parameters.maxIterations}. Very high iteration counts (>${MAX_ITERATIONS_WARNING_THRESHOLD}) may cause long execution times and high costs.`
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user