Node Metadata Gap Analysis
Node Metadata Gap Analysis
CTO Assessment: node_metadata.json as Source of Truth
Date: 2025-10-31
File: C:\Working With AI\ai_sam\ai_sam\ai_sam\static\src\vendor_library\_registry\node_metadata.json
Total Nodes: 249
What node_metadata.json Provides
Available Fields (7 total):
{
"icon": "file:actionNetwork.svg",
"folder": "ActionNetwork",
"displayName": "actionNetwork",
"group": "transform",
"credential_group": "ActionNetwork",
"credential_pattern": "single",
"credential_type": "api_key"
}
What Odoo Models Need (Field Comparison)
Model: node_types (n8n_node_types.py)
| Odoo Field | node_metadata.json Field | Status | Notes |
|---|---|---|---|
display_name |
✅ displayName |
MATCH | Direct mapping |
n8n_type |
❌ MISSING | GAP | Need to construct: n8n-nodes-base.{displayName} |
category |
⚠️ group |
PARTIAL | Maps to "transform" but needs N8N categories ("AI", "Action in an app", etc.) |
description |
❌ MISSING | GAP | No description field in metadata |
icon_class |
⚠️ icon |
PARTIAL | Has SVG path, need to convert to Font Awesome class |
color |
❌ MISSING | GAP | No color field in metadata |
requires_credentials |
⚠️ credential_type |
PARTIAL | Can infer: if credential_type != null, then true |
default_credential_id |
❌ MISSING | GAP | No default credential in metadata |
connection_inputs |
❌ MISSING | GAP | No input count in metadata |
connection_outputs |
❌ MISSING | GAP | No output count in metadata |
parameters_json |
❌ MISSING | GAP | No parameter schema in metadata |
documentation_url |
❌ MISSING | GAP | No documentation URL in metadata |
example_workflow |
❌ MISSING | GAP | No example in metadata |
usage_count |
N/A | N/A | Runtime tracking (not in metadata) |
last_used |
N/A | N/A | Runtime tracking (not in metadata) |
Model: n8n.simple.node (n8n_simple_nodes.py)
| Odoo Field | node_metadata.json Field | Status | Notes |
|---|---|---|---|
node_id |
❌ MISSING | GAP | Need to construct: n8n-nodes-base.{displayName} |
display_name |
✅ displayName |
MATCH | Direct mapping |
description |
❌ MISSING | GAP | No description field |
supplier |
⚠️ folder |
PARTIAL | Folder name = supplier name (e.g., "ActionNetwork") |
service |
❌ MISSING | GAP | No service hierarchy in metadata |
is_trigger |
❌ MISSING | GAP | No trigger flag in metadata |
node_type |
⚠️ group |
PARTIAL | "transform" doesn't map to "Action" or "Trigger" |
categories |
⚠️ group |
PARTIAL | Only has "transform", need N8N categories |
subcategories |
❌ MISSING | GAP | No subcategories in metadata |
alias |
❌ MISSING | GAP | No search aliases in metadata |
Gap Summary
✅ Available (2 fields):
displayName→ Direct mappingicon→ SVG path (needs conversion)
⚠️ Partial (3 fields):
group→ Only "transform", need full N8N category mappingfolder→ Can extract supplier namecredential_type→ Can inferrequires_credentials
❌ Missing (10+ critical fields):
- n8n_type (CRITICAL) - Official N8N node identifier
- description - User-facing node description
- color - UI color coding
- connection_inputs - How many inputs node accepts
- connection_outputs - How many outputs node produces
- parameters_json - Node configuration schema
- documentation_url - Link to N8N docs
- is_trigger - Action vs Trigger classification
- categories - Full N8N category list
- subcategories - Detailed categorization
CTO Assessment: Can node_metadata.json Replace Models?
Answer: NO - Insufficient Metadata
Coverage: ~20% of required fields
Usability: Cannot populate Odoo models without significant data gaps
What's Missing:
1. Node Identity (CRITICAL)
# NEED:
n8n_type = "n8n-nodes-base.gmail" # Official identifier
# HAVE:
displayName = "gmail" # Just the name
# PROBLEM:
# Can't construct full n8n_type reliably (some nodes use different prefixes)
# Can't validate against N8N server without official identifier
2. Node Behavior (CRITICAL)
# NEED:
connection_inputs = 1 # How to connect nodes
connection_outputs = 2 # Support for branching logic
is_trigger = False # Action vs Trigger
# HAVE:
group = "transform" # Vague category
# PROBLEM:
# Can't render node connections in canvas without input/output counts
# Can't filter by Action vs Trigger without is_trigger flag
3. Node Configuration (IMPORTANT)
# NEED:
parameters_json = {...} # What fields does node accept?
description = "..." # What does this node do?
documentation_url = "..." # Where to learn more?
# HAVE:
(nothing)
# PROBLEM:
# Can't build node configuration UI without parameter schema
# Users don't know what nodes do without descriptions
Recommendations
Option 1: Enhance node_metadata.json (Best)
Extract additional fields from N8N .node.json files:
# Enhanced metadata structure:
{
"gmail": {
"displayName": "Gmail",
"n8n_type": "n8n-nodes-base.gmail", # ADD
"description": "Send and receive emails via Gmail", # ADD
"icon": "file:gmail.svg",
"folder": "Gmail",
"group": "transform",
"category": "Communication", # ADD (from N8N)
"subcategories": ["Email"], # ADD
"is_trigger": false, # ADD
"inputs": 1, # ADD
"outputs": 1, # ADD
"color": "#dd4b39", # ADD
"documentation_url": "https://docs.n8n.io/...", # ADD
"credential_group": "Gmail",
"credential_pattern": "oauth2",
"credential_type": "oauth2"
}
}
Script to generate enhanced metadata:
# C:\Working With AI\ai_sam\ai_sam\ai_sam\scripts\enhance_node_metadata.py
import json
import os
N8N_NODES_PATH = r"C:\path\to\n8n\nodes-base\nodes"
METADATA_PATH = r"C:\Working With AI\ai_sam\ai_sam\ai_sam\static\src\vendor_library\_registry\node_metadata.json"
def extract_full_metadata(node_folder):
"""Extract ALL fields from .node.json"""
node_json_path = os.path.join(N8N_NODES_PATH, node_folder, f"{node_folder}.node.json")
with open(node_json_path, 'r') as f:
node_data = json.load(f)
return {
'displayName': node_data.get('displayName'),
'n8n_type': node_data.get('name'), # CRITICAL FIELD
'description': node_data.get('description'),
'icon': node_data.get('icon'),
'category': node_data.get('codex', {}).get('categories', ['Uncategorized'])[0],
'subcategories': node_data.get('codex', {}).get('subcategories', {}),
'is_trigger': 'Trigger' in node_data.get('name', ''),
'inputs': len(node_data.get('inputs', [])),
'outputs': len(node_data.get('outputs', [])),
'color': node_data.get('defaults', {}).get('color'),
'documentation_url': node_data.get('documentationUrl'),
# ... existing fields ...
}
Option 2: Query N8N API Directly (Simplest)
Don't store node metadata in Odoo at all:
# ai_sam_workflows/controllers/node_registry.py
@http.route('/api/nodes/list', type='json', auth='user')
def list_nodes(self):
"""Fetch node list FROM N8N SERVER (real-time)"""
response = requests.get(f"{N8N_SERVER}/nodes/list")
return response.json() # Always fresh, always complete!
Pros:
- Zero sync burden
- Always up-to-date
- No metadata gaps
Cons:
- Requires N8N server to be running
- Network latency on node list fetch
Option 3: Hybrid Approach (Recommended)
Use enhanced node_metadata.json as offline fallback, query N8N API when available:
@http.route('/api/nodes/list', type='json', auth='user')
def list_nodes(self):
"""Get node list (N8N API first, fallback to local metadata)"""
try:
# Try N8N server first (real-time data)
response = requests.get(f"{N8N_SERVER}/nodes/list", timeout=2)
return response.json()
except:
# Fallback to local metadata (offline mode)
metadata_path = get_module_resource('ai_sam', 'static/src/vendor_library/_registry/node_metadata.json')
with open(metadata_path, 'r') as f:
return json.load(f)
Conclusion
node_metadata.json Coverage: 20%
Missing Critical Fields:
- ❌ n8n_type (official identifier)
- ❌ description (user-facing text)
- ❌ connection_inputs/outputs (canvas rendering)
- ❌ is_trigger (Action vs Trigger)
- ❌ parameters_json (node configuration)
- ❌ color (UI theming)
CTO Decision Required:
A. Enhance node_metadata.json (extract missing fields from N8N)?
B. Query N8N API directly (no local storage)?
C. Hybrid approach (API + fallback)?
Current state: Cannot replace Odoo models with existing metadata.
Next Steps:
1. Decide on approach (A/B/C)
2. If A: Write enhance_node_metadata.py script
3. If B: Delete all node models, implement API controller
4. If C: Implement hybrid query logic