UNPKG

aios-core

Version:

Synkra AIOS: AI-Orchestrated System for Full Stack Development - Core Framework

552 lines (484 loc) 17.4 kB
tool: schema_version: 2.0 id: n8n type: mcp name: n8n Workflow Automation version: 1.0.0 description: n8n workflow management with execution validation and credential handling knowledge_strategy: executable executable_knowledge: validators: # Combined validator for execute_workflow - id: validate-execute-workflow validates: execute_workflow language: javascript checks: - required_fields: [workflow_id] function: | (function() { const errors = []; // 1. Required workflow_id if (!args.args.workflow_id && !args.args.workflowId) { errors.push("workflow_id is required"); } // 2. Validate data parameter structure if provided if (args.args.data) { if (typeof args.args.data !== 'object') { errors.push("data must be an object"); } } // 3. Validate wait_for_completion is boolean if (args.args.wait_for_completion !== undefined && typeof args.args.wait_for_completion !== 'boolean') { errors.push("wait_for_completion must be boolean"); } return { valid: errors.length === 0, errors: errors }; })(); # Validator for create_workflow - id: validate-create-workflow validates: create_workflow language: javascript function: | (function() { const errors = []; // 1. Required name field if (!args.args.name) { errors.push("name is required"); } // 2. Validate nodes structure if provided if (args.args.nodes) { if (!Array.isArray(args.args.nodes)) { errors.push("nodes must be an array"); } else { args.args.nodes.forEach((node, index) => { if (!node.type) { errors.push(`nodes[${index}] missing required 'type' field`); } if (!node.name) { errors.push(`nodes[${index}] missing required 'name' field`); } }); } } // 3. Validate connections structure if (args.args.connections) { if (typeof args.args.connections !== 'object') { errors.push("connections must be an object"); } } return { valid: errors.length === 0, errors: errors }; })(); # Validator for create_credential - id: validate-create-credential validates: create_credential language: javascript function: | (function() { const errors = []; if (!args.args.name) { errors.push("name is required for create_credential"); } if (!args.args.type) { errors.push("type is required for create_credential"); } if (!args.args.data) { errors.push("data is required for create_credential"); } else if (typeof args.args.data !== 'object') { errors.push("data must be an object"); } return { valid: errors.length === 0, errors: errors }; })(); # Validator for update_credential - id: validate-update-credential validates: update_credential language: javascript function: | (function() { const errors = []; if (!args.args.credential_id && !args.args.credentialId) { errors.push("credential_id is required for update_credential"); } return { valid: errors.length === 0, errors: errors }; })(); # Validator for delete_credential - id: validate-delete-credential validates: delete_credential language: javascript function: | (function() { const errors = []; if (!args.args.credential_id && !args.args.credentialId) { errors.push("credential_id is required for delete_credential"); } return { valid: errors.length === 0, errors: errors }; })(); helpers: - id: extract-workflow-state language: javascript runtime: isolated_vm description: "Extract current state from workflow execution" function: | (function() { const { execution } = args; if (!execution) return null; return { id: execution.id, status: execution.finished ? 'finished' : execution.stoppedAt ? 'stopped' : 'running', startedAt: execution.startedAt, finishedAt: execution.finishedAt, mode: execution.mode }; })(); - id: validate-node-connections language: javascript runtime: isolated_vm description: "Validate node connections in workflow" function: | (function() { const { nodes, connections } = args; if (!nodes || !connections) { return { valid: false, errors: ['Missing nodes or connections'] }; } const errors = []; const nodeNames = new Set(nodes.map(n => n.name)); // Check all connection sources exist for (const [sourceName, outputs] of Object.entries(connections)) { if (!nodeNames.has(sourceName)) { errors.push(`Connection source '${sourceName}' not found in nodes`); } // Check all connection targets exist // n8n structure: outputs = { main: [[{node, type, index}]], error: [[...]] } for (const outputConnections of Object.values(outputs || {})) { if (Array.isArray(outputConnections)) { // outputConnections is an array of arrays outputConnections.forEach(connectionGroup => { if (Array.isArray(connectionGroup)) { connectionGroup.forEach(conn => { if (conn.node && !nodeNames.has(conn.node)) { errors.push(`Connection target '${conn.node}' not found in nodes`); } }); } }); } } } return { valid: errors.length === 0, errors: errors }; })(); - id: format-workflow-data language: javascript runtime: isolated_vm description: "Format input data for workflow execution" function: | (function() { const { data, workflowData } = args; // If workflow expects specific input format, validate it if (workflowData && workflowData.nodes) { const triggerNode = workflowData.nodes.find(n => n.type.includes('trigger') || n.type.includes('webhook') || n.type === 'n8n-nodes-base.start' ); if (triggerNode && triggerNode.parameters !== undefined) { // Format data according to trigger expectations return { formatted: true, data: data || {}, triggerNode: triggerNode.name }; } } return { formatted: false, data: data || {} }; })(); - id: parse-execution-error language: javascript runtime: isolated_vm description: "Parse and format execution errors" function: | (function() { const { error, execution } = args; if (!error) return null; return { message: error.message || 'Unknown error', node: error.node || 'unknown', timestamp: error.timestamp || execution?.stoppedAt, stack: error.stack || null }; })(); - id: validate-credential-type language: javascript runtime: isolated_vm description: "Validate credential type is supported" function: | (function() { const { type } = args; // Common n8n credential types const validTypes = [ 'httpBasicAuth', 'httpHeaderAuth', 'oAuth2Api', 'apiKey', 'postgres', 'mysql', 'mongodb', 'redis', 'aws', 'googleApi', 'slackApi', 'githubApi', 'jwtAuth' ]; return validTypes.includes(type); })(); - id: build-workflow-structure language: javascript runtime: isolated_vm description: "Build workflow structure from nodes and connections" function: | (function() { const { name, nodes, connections } = args; if (!name) { return { error: 'Workflow name is required' }; } return { name: name, nodes: nodes || [], connections: connections || {}, active: false, settings: {}, staticData: null }; })(); - id: calculate-workflow-complexity language: javascript runtime: isolated_vm description: "Calculate workflow complexity score" function: | (function() { const { nodes, connections } = args; if (!nodes) return { complexity: 0 }; let complexity = nodes.length; // Base complexity from node count // Add complexity for connections if (connections) { const connectionCount = Object.values(connections).reduce((sum, outputs) => { return sum + Object.values(outputs || {}).reduce((s, conns) => { return s + (Array.isArray(conns) ? conns.length : 0); }, 0); }, 0); complexity += connectionCount * 0.5; } // Add complexity for certain node types const complexNodeTypes = ['n8n-nodes-base.if', 'n8n-nodes-base.switch', 'n8n-nodes-base.function']; const complexNodes = nodes.filter(n => complexNodeTypes.includes(n.type)).length; complexity += complexNodes * 2; return { complexity: Math.round(complexity), nodeCount: nodes.length, connectionCount: Object.keys(connections || {}).length, hasComplexLogic: complexNodes > 0 }; })(); api_complexity: workflow_execution_state: - state: waiting description: "Workflow is queued for execution" next_states: [running, failed] - state: running description: "Workflow is currently executing" next_states: [finished, stopped, error] - state: finished description: "Workflow completed successfully" terminal: true - state: stopped description: "Workflow was manually stopped" terminal: true - state: error description: "Workflow encountered an error" terminal: true retry_allowed: true credential_types: - type: httpBasicAuth fields: [username, password] description: "HTTP Basic Authentication" - type: httpHeaderAuth fields: [name, value] description: "HTTP Header Authentication" - type: oAuth2Api fields: [clientId, clientSecret, authUrl, accessTokenUrl] description: "OAuth 2.0 Authentication" - type: apiKey fields: [apiKey] description: "API Key Authentication" node_execution_patterns: - pattern: sequential description: "Nodes execute in order, one after another" use_case: "Simple linear workflows" - pattern: parallel description: "Multiple nodes execute simultaneously" use_case: "Independent data processing" - pattern: conditional description: "Execution path depends on node conditions" nodes: [n8n-nodes-base.if, n8n-nodes-base.switch] - pattern: loop description: "Repeated execution over data items" nodes: [n8n-nodes-base.splitInBatches] anti_patterns: - pattern: missing_error_handling description: "Not handling node execution errors" category: reliability severity: high wrong: | execute_workflow({ workflow_id: "123" // ❌ No error handling for failed execution }) correct: | const result = execute_workflow({ workflow_id: "123", wait_for_completion: true }) if (result.status === 'error') { // Handle error appropriately handle_execution_error(result) } rationale: "Always check execution status and handle errors gracefully." - pattern: invalid_node_connections description: "Creating workflows with disconnected or invalid nodes" category: workflow_structure severity: medium wrong: | create_workflow({ name: "Test", nodes: [{name: "Start", type: "trigger"}, {name: "End", type: "action"}], connections: { "NonExistent": { // ❌ Node doesn't exist main: [[{node: "End"}]] } } }) correct: | create_workflow({ name: "Test", nodes: [{name: "Start", type: "trigger"}, {name: "End", type: "action"}], connections: { "Start": { // ✅ Correct node name main: [[{node: "End", type: "main", index: 0}]] } } }) rationale: "Use validate-node-connections helper to verify connections before workflow creation." - pattern: missing_credentials description: "Referencing credentials that don't exist" category: authentication severity: high wrong: | create_workflow({ nodes: [{ type: "n8n-nodes-base.httpRequest", credentials: { httpBasicAuth: "nonexistent" // ❌ Credential not created } }] }) correct: | // First create credential const cred = create_credential({ type: "httpBasicAuth", name: "My API Auth", data: {username: "user", password: "pass"} }) // Then reference it create_workflow({ nodes: [{ type: "n8n-nodes-base.httpRequest", credentials: { httpBasicAuth: cred.id // Valid credential reference } }] }) rationale: "Always create and verify credentials before referencing them in workflows." examples: execute_workflow: - scenario: success description: "Execute workflow and wait for completion" input: workflow_id: "wf_abc123" wait_for_completion: true data: { key: "value" } output: execution_id: "exec_xyz789" status: "finished" data: { result: "success" } - scenario: failure_invalid_param description: "Missing required workflow_id" input: data: { key: "value" } error: code: VALIDATION_ERROR message: "workflow_id is required" validator: validate-execute-workflow create_workflow: - scenario: success description: "Create simple workflow" input: name: "Data Processor" nodes: - type: n8n-nodes-base.start name: Start parameters: {} - type: n8n-nodes-base.httpRequest name: Fetch Data parameters: url: "https://api.example.com/data" connections: Start: main: [[{node: "Fetch Data", type: "main", index: 0}]] output: workflow_id: "wf_new123" name: "Data Processor" active: false - scenario: failure_invalid_param description: "Invalid node structure" input: name: "Test Workflow" nodes: "not an array" error: code: VALIDATION_ERROR message: "nodes must be an array" validator: validate-create-workflow mcp_specific: server_command: "npx -y @illuminaresolutions/n8n-mcp-server" transport: stdio environment_variables: - name: N8N_HOST required: true description: "n8n instance URL (e.g., https://your-n8n-instance.com)" - name: N8N_API_KEY required: true description: "n8n API key for authentication" health_check: method: tool_call command: list_workflows expected_response: "Array of workflows" timeout_ms: 5000