mirror of
https://github.com/czlonkowski/n8n-mcp.git
synced 2026-02-06 13:33:11 +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:
@@ -691,15 +691,12 @@ describe('ConfigValidator - Basic Validation', () => {
|
||||
name: 'model',
|
||||
type: 'resourceLocator',
|
||||
required: true,
|
||||
typeOptions: {
|
||||
resourceLocator: {
|
||||
modes: {
|
||||
list: { displayName: 'List' },
|
||||
id: { displayName: 'ID' },
|
||||
url: { displayName: 'URL' }
|
||||
}
|
||||
}
|
||||
}
|
||||
// In real n8n, modes are at top level, not in typeOptions
|
||||
modes: [
|
||||
{ name: 'list', displayName: 'List' },
|
||||
{ name: 'id', displayName: 'ID' },
|
||||
{ name: 'url', displayName: 'URL' }
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
@@ -726,15 +723,12 @@ describe('ConfigValidator - Basic Validation', () => {
|
||||
name: 'model',
|
||||
type: 'resourceLocator',
|
||||
required: true,
|
||||
typeOptions: {
|
||||
resourceLocator: {
|
||||
modes: [
|
||||
{ name: 'list', displayName: 'List' },
|
||||
{ name: 'id', displayName: 'ID' },
|
||||
{ name: 'custom', displayName: 'Custom' }
|
||||
]
|
||||
}
|
||||
}
|
||||
// Array format at top level (real n8n structure)
|
||||
modes: [
|
||||
{ name: 'list', displayName: 'List' },
|
||||
{ name: 'id', displayName: 'ID' },
|
||||
{ name: 'custom', displayName: 'Custom' }
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
@@ -757,11 +751,7 @@ describe('ConfigValidator - Basic Validation', () => {
|
||||
name: 'model',
|
||||
type: 'resourceLocator',
|
||||
required: true,
|
||||
typeOptions: {
|
||||
resourceLocator: {
|
||||
modes: 'invalid-string' // Malformed schema
|
||||
}
|
||||
}
|
||||
modes: 'invalid-string' // Malformed schema at top level
|
||||
}
|
||||
];
|
||||
|
||||
@@ -785,11 +775,7 @@ describe('ConfigValidator - Basic Validation', () => {
|
||||
name: 'model',
|
||||
type: 'resourceLocator',
|
||||
required: true,
|
||||
typeOptions: {
|
||||
resourceLocator: {
|
||||
modes: {} // Empty object
|
||||
}
|
||||
}
|
||||
modes: {} // Empty object at top level
|
||||
}
|
||||
];
|
||||
|
||||
@@ -800,7 +786,7 @@ describe('ConfigValidator - Basic Validation', () => {
|
||||
expect(result.errors.some(e => e.property === 'model.mode')).toBe(false);
|
||||
});
|
||||
|
||||
it('should skip mode validation when typeOptions not provided', () => {
|
||||
it('should skip mode validation when modes not provided', () => {
|
||||
const nodeType = '@n8n/n8n-nodes-langchain.lmChatOpenAi';
|
||||
const config = {
|
||||
model: {
|
||||
@@ -813,7 +799,7 @@ describe('ConfigValidator - Basic Validation', () => {
|
||||
name: 'model',
|
||||
type: 'resourceLocator',
|
||||
required: true
|
||||
// No typeOptions - schema doesn't define modes
|
||||
// No modes property - schema doesn't define modes
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user