mirror of
https://github.com/czlonkowski/n8n-mcp.git
synced 2026-02-08 14:23:08 +00:00
When n8n connects any node to an AI Agent's tool slot, it creates a dynamic Tool variant at runtime (e.g., googleDrive → googleDriveTool). These don't exist in npm packages, causing false "unknown node type" errors. Added validation-time inference: when a *Tool node type is not found, check if the base node exists. If yes, treat as valid with warning. Changes: - workflow-validator.ts: Add INFERRED_TOOL_VARIANT logic - node-similarity-service.ts: Add 98% confidence for valid Tool variants - Added 7 unit tests for inferred tool variant functionality Fixes #522 Conceived by Romuald Członkowski - https://www.aiadvisors.pl/en 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Romuald Członkowski <romualdczlonkowski@MacBook-Pro-Romuald.local> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
committed by
GitHub
parent
861005eeed
commit
ce2c94c1a5
@@ -398,7 +398,39 @@ export class WorkflowValidator {
|
||||
const normalizedType = NodeTypeNormalizer.normalizeToFullForm(node.type);
|
||||
|
||||
// Get node definition using normalized type (needed for typeVersion validation)
|
||||
const nodeInfo = this.nodeRepository.getNode(normalizedType);
|
||||
let nodeInfo = this.nodeRepository.getNode(normalizedType);
|
||||
|
||||
// Check if this is a dynamic Tool variant (e.g., googleDriveTool, googleSheetsTool)
|
||||
// n8n creates these at runtime when ANY node is used in an AI Agent's tool slot,
|
||||
// but they don't exist in npm packages. We infer validity if the base node exists.
|
||||
// See: https://github.com/czlonkowski/n8n-mcp/issues/522
|
||||
if (!nodeInfo && ToolVariantGenerator.isToolVariantNodeType(normalizedType)) {
|
||||
const baseNodeType = ToolVariantGenerator.getBaseNodeType(normalizedType);
|
||||
if (baseNodeType) {
|
||||
const baseNodeInfo = this.nodeRepository.getNode(baseNodeType);
|
||||
if (baseNodeInfo) {
|
||||
// Valid inferred tool variant - base node exists
|
||||
result.warnings.push({
|
||||
type: 'warning',
|
||||
nodeId: node.id,
|
||||
nodeName: node.name,
|
||||
message: `Node type "${node.type}" is inferred as a dynamic AI Tool variant of "${baseNodeType}". ` +
|
||||
`This Tool variant is created by n8n at runtime when connecting "${baseNodeInfo.displayName}" to an AI Agent.`,
|
||||
code: 'INFERRED_TOOL_VARIANT'
|
||||
});
|
||||
|
||||
// Create synthetic nodeInfo for validation continuity
|
||||
nodeInfo = {
|
||||
...baseNodeInfo,
|
||||
nodeType: normalizedType,
|
||||
displayName: `${baseNodeInfo.displayName} Tool`,
|
||||
isToolVariant: true,
|
||||
toolVariantOf: baseNodeType,
|
||||
isInferred: true
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!nodeInfo) {
|
||||
|
||||
@@ -494,6 +526,13 @@ export class WorkflowValidator {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip PARAMETER validation for inferred tool variants (Issue #522)
|
||||
// They have a different property structure (toolDescription added at runtime)
|
||||
// that doesn't match the base node's schema. TypeVersion validation above still runs.
|
||||
if ((nodeInfo as any).isInferred) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Validate node configuration
|
||||
// Add @version to parameters for displayOptions evaluation (supports _cnd operators)
|
||||
const paramsWithVersion = {
|
||||
|
||||
Reference in New Issue
Block a user