mirror of
https://github.com/czlonkowski/n8n-mcp.git
synced 2026-03-24 03:13:07 +00:00
fix: AI connection type propagation and get_node improvements (v2.28.1) (#461)
* fix: AI connection type propagation and get_node improvements (v2.28.1) Bug fixes: - Issue #458: addConnection now preserves AI connection types (ai_tool, ai_memory, ai_languageModel) instead of defaulting to 'main' - Fixed false positive "AI Agent has no tools connected" validation warning Enhancements: - Added expectedFormat field to resourceLocator properties in get_node output - Added versionNotice field to make typeVersion more prominent Conceived by Romuald Członkowski - https://www.aiadvisors.pl/en 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * test: add missing test coverage for PR #461 improvements - Added test for AI Agent validation positive case (tools properly connected) - Added 3 tests for expectedFormat on resourceLocator properties Conceived by Romuald Członkowski - https://www.aiadvisors.pl/en 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
committed by
GitHub
parent
33690c5650
commit
3188d209b7
@@ -2203,14 +2203,19 @@ Full documentation is being prepared. For now, use get_node_essentials for confi
|
||||
// Get operations (already parsed by repository)
|
||||
const operations = node.operations || [];
|
||||
|
||||
// Get the latest version - this is important for AI to use correct typeVersion
|
||||
const latestVersion = node.version ?? '1';
|
||||
|
||||
const result = {
|
||||
nodeType: node.nodeType,
|
||||
workflowNodeType: getWorkflowNodeType(node.package ?? 'n8n-nodes-base', node.nodeType),
|
||||
displayName: node.displayName,
|
||||
description: node.description,
|
||||
category: node.category,
|
||||
version: node.version ?? '1',
|
||||
version: latestVersion,
|
||||
isVersioned: node.isVersioned ?? false,
|
||||
// Prominent warning to use the correct typeVersion
|
||||
versionNotice: `⚠️ Use typeVersion: ${latestVersion} when creating this node`,
|
||||
requiredProperties: essentials.required,
|
||||
commonProperties: essentials.common,
|
||||
operations: operations.map((op: any) => ({
|
||||
|
||||
@@ -16,6 +16,11 @@ export interface SimplifiedProperty {
|
||||
placeholder?: string;
|
||||
showWhen?: Record<string, any>;
|
||||
usageHint?: string;
|
||||
expectedFormat?: {
|
||||
structure: Record<string, string>;
|
||||
modes?: string[];
|
||||
example: Record<string, any>;
|
||||
};
|
||||
}
|
||||
|
||||
export interface EssentialConfig {
|
||||
@@ -322,7 +327,18 @@ export class PropertyFilter {
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Add expectedFormat for resourceLocator types - critical for correct configuration
|
||||
if (prop.type === 'resourceLocator') {
|
||||
const modes = prop.modes?.map((m: any) => m.name || m) || ['list', 'id'];
|
||||
const defaultValue = prop.default?.value || 'your-resource-id';
|
||||
simplified.expectedFormat = {
|
||||
structure: { mode: 'string', value: 'string' },
|
||||
modes,
|
||||
example: { mode: 'id', value: defaultValue }
|
||||
};
|
||||
}
|
||||
|
||||
// Include simple display conditions (max 2 conditions)
|
||||
if (prop.displayOptions?.show) {
|
||||
const conditions = Object.keys(prop.displayOptions.show);
|
||||
|
||||
@@ -757,7 +757,8 @@ export class WorkflowDiffEngine {
|
||||
const { sourceOutput, sourceIndex } = this.resolveSmartParameters(workflow, operation);
|
||||
|
||||
// Use nullish coalescing to properly handle explicit 0 values
|
||||
const targetInput = operation.targetInput ?? 'main';
|
||||
// Default targetInput to sourceOutput to preserve connection type for AI connections (ai_tool, ai_memory, etc.)
|
||||
const targetInput = operation.targetInput ?? sourceOutput;
|
||||
const targetIndex = operation.targetIndex ?? 0;
|
||||
|
||||
// Initialize source node connections object
|
||||
|
||||
@@ -1137,16 +1137,23 @@ export class WorkflowValidator {
|
||||
}
|
||||
|
||||
// Check for AI Agent workflows
|
||||
const aiAgentNodes = workflow.nodes.filter(n =>
|
||||
n.type.toLowerCase().includes('agent') ||
|
||||
const aiAgentNodes = workflow.nodes.filter(n =>
|
||||
n.type.toLowerCase().includes('agent') ||
|
||||
n.type.includes('langchain.agent')
|
||||
);
|
||||
|
||||
|
||||
if (aiAgentNodes.length > 0) {
|
||||
// Check if AI agents have tools connected
|
||||
// Tools connect TO the agent, so we need to find connections where the target is the agent
|
||||
for (const agentNode of aiAgentNodes) {
|
||||
const connections = workflow.connections[agentNode.name];
|
||||
if (!connections?.ai_tool || connections.ai_tool.flat().filter(c => c).length === 0) {
|
||||
// Search all connections to find ones targeting this agent via ai_tool
|
||||
const hasToolConnected = Object.values(workflow.connections).some(sourceOutputs => {
|
||||
const aiToolConnections = sourceOutputs.ai_tool;
|
||||
if (!aiToolConnections) return false;
|
||||
return aiToolConnections.flat().some(conn => conn && conn.node === agentNode.name);
|
||||
});
|
||||
|
||||
if (!hasToolConnected) {
|
||||
result.warnings.push({
|
||||
type: 'warning',
|
||||
nodeId: agentNode.id,
|
||||
|
||||
Reference in New Issue
Block a user