Skip to main content
Glama

n8n-MCP

by 88-888
MCP_QUICK_START_GUIDE.mdβ€’10.8 kB
# MCP Implementation Quick Start Guide ## Immediate Actions (Day 1) ### 1. Create Essential Properties Configuration Create `src/data/essential-properties.json`: ```json { "nodes-base.httpRequest": { "required": ["url"], "common": ["method", "authentication", "sendBody", "contentType", "sendHeaders"], "examples": { "minimal": { "url": "https://api.example.com/data" }, "getWithAuth": { "method": "GET", "url": "https://api.example.com/protected", "authentication": "genericCredentialType", "genericAuthType": "headerAuth" }, "postJson": { "method": "POST", "url": "https://api.example.com/create", "sendBody": true, "contentType": "json", "jsonBody": "{ \"name\": \"example\" }" } } }, "nodes-base.webhook": { "required": [], "common": ["path", "method", "responseMode", "responseData"], "examples": { "minimal": { "path": "webhook", "method": "POST" } } } } ``` ### 2. Implement get_node_essentials Tool Add to `src/mcp/server.ts`: ```typescript // Add to tool implementations case "get_node_essentials": { const { nodeType } = request.params.arguments as { nodeType: string }; // Load essential properties config const essentialsConfig = require('../data/essential-properties.json'); const nodeConfig = essentialsConfig[nodeType]; if (!nodeConfig) { // Fallback: extract from existing data const node = await service.getNodeByType(nodeType); if (!node) { return { error: `Node type ${nodeType} not found` }; } // Parse properties to find required ones const properties = JSON.parse(node.properties_schema || '[]'); const required = properties.filter((p: any) => p.required); const common = properties.slice(0, 5); // Top 5 as fallback return { nodeType, displayName: node.display_name, description: node.description, requiredProperties: required.map(simplifyProperty), commonProperties: common.map(simplifyProperty), examples: { minimal: {}, common: {} } }; } // Use configured essentials const node = await service.getNodeByType(nodeType); const properties = JSON.parse(node.properties_schema || '[]'); const requiredProps = nodeConfig.required.map((name: string) => { const prop = findPropertyByName(properties, name); return prop ? simplifyProperty(prop) : null; }).filter(Boolean); const commonProps = nodeConfig.common.map((name: string) => { const prop = findPropertyByName(properties, name); return prop ? simplifyProperty(prop) : null; }).filter(Boolean); return { nodeType, displayName: node.display_name, description: node.description, requiredProperties: requiredProps, commonProperties: commonProps, examples: nodeConfig.examples || {} }; } // Helper functions function simplifyProperty(prop: any) { return { name: prop.name, type: prop.type, description: prop.description || prop.displayName || '', default: prop.default, options: prop.options?.map((opt: any) => typeof opt === 'string' ? opt : opt.value ), placeholder: prop.placeholder }; } function findPropertyByName(properties: any[], name: string): any { for (const prop of properties) { if (prop.name === name) return prop; // Check in nested collections if (prop.type === 'collection' && prop.options) { const found = findPropertyByName(prop.options, name); if (found) return found; } } return null; } ``` ### 3. Add Tool Definition Add to tool definitions: ```typescript { name: "get_node_essentials", description: "Get only essential and commonly-used properties for a node - perfect for quick configuration", inputSchema: { type: "object", properties: { nodeType: { type: "string", description: "The node type (e.g., 'nodes-base.httpRequest')" } }, required: ["nodeType"] } } ``` ### 4. Create Property Parser Service Create `src/services/property-parser.ts`: ```typescript export class PropertyParser { /** * Parse nested properties and flatten to searchable format */ static parseProperties(properties: any[], path = ''): ParsedProperty[] { const results: ParsedProperty[] = []; for (const prop of properties) { const currentPath = path ? `${path}.${prop.name}` : prop.name; // Add current property results.push({ name: prop.name, path: currentPath, type: prop.type, description: prop.description || prop.displayName || '', required: prop.required || false, displayConditions: prop.displayOptions, default: prop.default, options: prop.options?.filter((opt: any) => typeof opt === 'string' || opt.value) }); // Recursively parse nested properties if (prop.type === 'collection' && prop.options) { results.push(...this.parseProperties(prop.options, currentPath)); } else if (prop.type === 'fixedCollection' && prop.options) { for (const option of prop.options) { if (option.values) { results.push(...this.parseProperties(option.values, `${currentPath}.${option.name}`)); } } } } return results; } /** * Find properties matching a search query */ static searchProperties(properties: ParsedProperty[], query: string): ParsedProperty[] { const lowerQuery = query.toLowerCase(); return properties.filter(prop => prop.name.toLowerCase().includes(lowerQuery) || prop.description.toLowerCase().includes(lowerQuery) || prop.path.toLowerCase().includes(lowerQuery) ); } /** * Categorize properties */ static categorizeProperties(properties: ParsedProperty[]): CategorizedProperties { const categories: CategorizedProperties = { authentication: [], request: [], response: [], advanced: [], other: [] }; for (const prop of properties) { if (prop.name.includes('auth') || prop.name.includes('credential')) { categories.authentication.push(prop); } else if (prop.name.includes('body') || prop.name.includes('header') || prop.name.includes('query') || prop.name.includes('url')) { categories.request.push(prop); } else if (prop.name.includes('response') || prop.name.includes('output')) { categories.response.push(prop); } else if (prop.path.includes('options.')) { categories.advanced.push(prop); } else { categories.other.push(prop); } } return categories; } } interface ParsedProperty { name: string; path: string; type: string; description: string; required: boolean; displayConditions?: any; default?: any; options?: any[]; } interface CategorizedProperties { authentication: ParsedProperty[]; request: ParsedProperty[]; response: ParsedProperty[]; advanced: ParsedProperty[]; other: ParsedProperty[]; } ``` ### 5. Quick Test Script Create `scripts/test-essentials.ts`: ```typescript import { MCPClient } from '../src/mcp/client'; async function testEssentials() { const client = new MCPClient(); console.log('Testing get_node_essentials...\n'); // Test HTTP Request node const httpEssentials = await client.call('get_node_essentials', { nodeType: 'nodes-base.httpRequest' }); console.log('HTTP Request Essentials:'); console.log(`- Required: ${httpEssentials.requiredProperties.map(p => p.name).join(', ')}`); console.log(`- Common: ${httpEssentials.commonProperties.map(p => p.name).join(', ')}`); console.log(`- Total properties: ${httpEssentials.requiredProperties.length + httpEssentials.commonProperties.length}`); // Compare with full response const fullInfo = await client.call('get_node_info', { nodeType: 'nodes-base.httpRequest' }); const fullSize = JSON.stringify(fullInfo).length; const essentialSize = JSON.stringify(httpEssentials).length; console.log(`\nSize comparison:`); console.log(`- Full response: ${(fullSize / 1024).toFixed(1)}KB`); console.log(`- Essential response: ${(essentialSize / 1024).toFixed(1)}KB`); console.log(`- Reduction: ${((1 - essentialSize / fullSize) * 100).toFixed(1)}%`); } testEssentials().catch(console.error); ``` ## Day 2-3: Implement search_node_properties ```typescript case "search_node_properties": { const { nodeType, query } = request.params.arguments as { nodeType: string; query: string; }; const node = await service.getNodeByType(nodeType); if (!node) { return { error: `Node type ${nodeType} not found` }; } const properties = JSON.parse(node.properties_schema || '[]'); const parsed = PropertyParser.parseProperties(properties); const matches = PropertyParser.searchProperties(parsed, query); return { query, matches: matches.map(prop => ({ name: prop.name, type: prop.type, path: prop.path, description: prop.description, visibleWhen: prop.displayConditions?.show })), totalMatches: matches.length }; } ``` ## Day 4-5: Implement get_node_for_task Create `src/data/task-templates.json`: ```json { "post_json_request": { "description": "Make a POST request with JSON data", "nodeType": "nodes-base.httpRequest", "configuration": { "method": "POST", "url": "", "sendBody": true, "contentType": "json", "specifyBody": "json", "jsonBody": "" }, "userMustProvide": [ { "property": "url", "description": "API endpoint URL" }, { "property": "jsonBody", "description": "JSON data to send" } ], "optionalEnhancements": [ { "property": "authentication", "description": "Add authentication if required" }, { "property": "sendHeaders", "description": "Add custom headers" } ] } } ``` ## Testing Checklist - [ ] Test get_node_essentials with HTTP Request node - [ ] Verify size reduction is >90% - [ ] Test with Webhook, Agent, and Code nodes - [ ] Validate examples work correctly - [ ] Test property search functionality - [ ] Verify task templates are valid - [ ] Check backward compatibility - [ ] Measure response times (<100ms) ## Success Indicators 1. **Immediate (Day 1)**: - get_node_essentials returns <5KB for HTTP Request - Response includes working examples - No errors with top 10 nodes 2. **Week 1**: - 90% reduction in response size - Property search working - 5+ task templates created - Positive AI agent feedback 3. **Month 1**: - All tools implemented - 50+ nodes optimized - Configuration time <1 minute - Error rate <10%

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/88-888/n8n-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server