diff --git a/data/nodes.db b/data/nodes.db index ecec469..0f0e8cc 100644 Binary files a/data/nodes.db and b/data/nodes.db differ diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 8130fa1..355be56 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -23,6 +23,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **Node type utilities** in `src/utils/node-utils.ts` - `normalizeNodeType()` - Converts full package names to database format - `getNodeTypeAlternatives()` - Provides fallback options for edge cases + - `getWorkflowNodeType()` - Constructs proper n8n workflow format from database values +- **workflowNodeType field** in all MCP tool responses that return node information + - AI agents now receive both `nodeType` (internal format) and `workflowNodeType` (n8n format) + - Example: `nodeType: "nodes-base.webhook"`, `workflowNodeType: "n8n-nodes-base.webhook"` + - Prevents confusion where AI agents would search nodes and use wrong format in workflows + - Added to: `search_nodes`, `get_node_info`, `get_node_essentials`, `get_node_as_tool_info`, `validate_node_operation` ## [2.7.17] - 2025-07-17 diff --git a/src/mcp/server.ts b/src/mcp/server.ts index b0fc431..ccb0334 100644 --- a/src/mcp/server.ts +++ b/src/mcp/server.ts @@ -25,7 +25,7 @@ import * as n8nHandlers from './handlers-n8n-manager'; import { handleUpdatePartialWorkflow } from './handlers-workflow-diff'; import { getToolDocumentation, getToolsOverview } from './tools-documentation'; import { PROJECT_VERSION } from '../utils/version'; -import { normalizeNodeType, getNodeTypeAlternatives } from '../utils/node-utils'; +import { normalizeNodeType, getNodeTypeAlternatives, getWorkflowNodeType } from '../utils/node-utils'; interface NodeRow { node_type: string; @@ -383,6 +383,7 @@ export class N8NDocumentationMCPServer { return { ...node, + workflowNodeType: getWorkflowNodeType(node.package, node.nodeType), aiToolCapabilities }; } @@ -517,6 +518,7 @@ export class N8NDocumentationMCPServer { query, results: scoredNodes.map(node => ({ nodeType: node.node_type, + workflowNodeType: getWorkflowNodeType(node.package_name, node.node_type), displayName: node.display_name, description: node.description, category: node.category, @@ -596,6 +598,7 @@ export class N8NDocumentationMCPServer { mode: 'FUZZY', results: matchingNodes.map(node => ({ nodeType: node.node_type, + workflowNodeType: getWorkflowNodeType(node.package_name, node.node_type), displayName: node.display_name, description: node.description, category: node.category, @@ -719,6 +722,7 @@ export class N8NDocumentationMCPServer { query, results: rankedNodes.map(node => ({ nodeType: node.node_type, + workflowNodeType: getWorkflowNodeType(node.package_name, node.node_type), displayName: node.display_name, description: node.description, category: node.category, @@ -757,6 +761,7 @@ export class N8NDocumentationMCPServer { query, results: rankedNodes.map(node => ({ nodeType: node.node_type, + workflowNodeType: getWorkflowNodeType(node.package_name, node.node_type), displayName: node.display_name, description: node.description, category: node.category, @@ -1093,6 +1098,7 @@ Full documentation is being prepared. For now, use get_node_essentials for confi const result = { nodeType: node.nodeType, + workflowNodeType: getWorkflowNodeType(node.package, node.nodeType), displayName: node.displayName, description: node.description, category: node.category, @@ -1328,6 +1334,7 @@ Full documentation is being prepared. For now, use get_node_essentials for confi // Add node context to result return { nodeType: node.nodeType, + workflowNodeType: getWorkflowNodeType(node.package, node.nodeType), displayName: node.displayName, ...validationResult, summary: { @@ -1453,6 +1460,7 @@ Full documentation is being prepared. For now, use get_node_essentials for confi return { nodeType: node.nodeType, + workflowNodeType: getWorkflowNodeType(node.package, node.nodeType), displayName: node.displayName, description: node.description, package: node.package, diff --git a/src/utils/node-utils.ts b/src/utils/node-utils.ts index d02335e..8ab8073 100644 --- a/src/utils/node-utils.ts +++ b/src/utils/node-utils.ts @@ -43,4 +43,31 @@ export function getNodeTypeAlternatives(nodeType: string): string[] { } return alternatives; +} + +/** + * Constructs the workflow node type from package name and normalized node type + * This creates the format that n8n expects in workflow definitions + * + * Examples: + * - ('n8n-nodes-base', 'nodes-base.webhook') → 'n8n-nodes-base.webhook' + * - ('@n8n/n8n-nodes-langchain', 'nodes-langchain.agent') → '@n8n/n8n-nodes-langchain.agent' + * + * @param packageName The package name from the database + * @param nodeType The normalized node type from the database + * @returns The workflow node type for use in n8n workflows + */ +export function getWorkflowNodeType(packageName: string, nodeType: string): string { + // Extract just the node name from the normalized type + const nodeName = nodeType.split('.').pop() || nodeType; + + // Construct the full workflow type based on package + if (packageName === 'n8n-nodes-base') { + return `n8n-nodes-base.${nodeName}`; + } else if (packageName === '@n8n/n8n-nodes-langchain') { + return `@n8n/n8n-nodes-langchain.${nodeName}`; + } + + // Fallback for unknown packages - return as is + return nodeType; } \ No newline at end of file