mirror of
https://github.com/czlonkowski/n8n-mcp.git
synced 2026-03-20 01:13:07 +00:00
fix: enable schema-based resourceLocator mode validation
Root cause analysis revealed validator was looking at wrong path for modes data. n8n stores modes at top level of properties, not nested in typeOptions. Changes: - config-validator.ts: Changed from prop.typeOptions?.resourceLocator?.modes to prop.modes (lines 273-310) - property-extractor.ts: Added modes field to normalizeProperties to capture mode definitions from n8n nodes - Updated all test cases to match real n8n schema structure with modes at property top level - Rebuilt database with modes field Results: - 100% coverage: All 70 resourceLocator nodes now have modes defined - Schema-based validation now ACTIVE (was being skipped before) - False positive eliminated: Google Sheets "name" mode now validates - Helpful error messages showing actual allowed modes from schema Testing: - All 33 unit tests pass - Verified with n8n-mcp-tester: valid "name" mode passes, invalid modes fail with clear error listing allowed options [list, url, id, name] Fixes #304 (Google Sheets false positive) Related to #306 (validator improvements) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -270,12 +270,13 @@ export class ConfigValidator {
|
||||
message: `resourceLocator '${key}.mode' must be a string, got ${typeof value.mode}`,
|
||||
fix: `Set mode to a valid string value`
|
||||
});
|
||||
} else if (prop.typeOptions?.resourceLocator?.modes) {
|
||||
} else if (prop.modes) {
|
||||
// Schema-based validation: Check if mode exists in the modes definition
|
||||
// In n8n, modes are defined at the top level of resourceLocator properties
|
||||
// Modes can be defined in different ways:
|
||||
// 1. Object with mode keys: { list: {...}, id: {...}, url: {...}, name: {...} }
|
||||
// 2. Array of mode objects: [{name: 'list', ...}, {name: 'id', ...}]
|
||||
const modes = prop.typeOptions.resourceLocator.modes;
|
||||
// 1. Array of mode objects: [{name: 'list', ...}, {name: 'id', ...}, {name: 'name', ...}]
|
||||
// 2. Object with mode keys: { list: {...}, id: {...}, url: {...}, name: {...} }
|
||||
const modes = prop.modes;
|
||||
|
||||
// Validate modes structure before processing to prevent crashes
|
||||
if (!modes || typeof modes !== 'object') {
|
||||
@@ -286,7 +287,7 @@ export class ConfigValidator {
|
||||
let allowedModes: string[] = [];
|
||||
|
||||
if (Array.isArray(modes)) {
|
||||
// Array format: extract name property from each mode object
|
||||
// Array format (most common in n8n): extract name property from each mode object
|
||||
allowedModes = modes
|
||||
.map(m => (typeof m === 'object' && m !== null) ? m.name : m)
|
||||
.filter(m => typeof m === 'string' && m.length > 0);
|
||||
@@ -305,7 +306,7 @@ export class ConfigValidator {
|
||||
});
|
||||
}
|
||||
}
|
||||
// If no typeOptions.resourceLocator.modes defined, skip mode validation
|
||||
// If no modes defined at property level, skip mode validation
|
||||
// This prevents false positives for nodes with dynamic/runtime-determined modes
|
||||
|
||||
if (value.value === undefined) {
|
||||
|
||||
Reference in New Issue
Block a user