UNPKG

vme-mcp-server

Version:

An intelligent Model Context Protocol (MCP) server that transforms HPE VM Essentials (VME) infrastructure management into natural language conversations. Provision VMs, manage resources, and control your infrastructure through simple English commands with

156 lines (155 loc) 6.2 kB
import { parseVMNames } from "./vm-parsing.js"; // Intent recognition system for natural language processing export function parseVMIntent(naturalLanguageInput) { const input = naturalLanguageInput.toLowerCase().trim(); const result = { action: 'unknown', confidence: 0, entities: {}, originalText: naturalLanguageInput }; // Intent Classification with confidence scoring const intentPatterns = { create: [ /\b(create|provision|deploy|launch|start|build|make|setup)\b/, /\bneed\s+(\d+\s+)?(vm|server|machine)/, /\bcan\s+you\s+(create|provision|deploy)/ ], modify: [ /\b(modify|change|update|edit|alter|resize|scale)\b/, /\badd\s+(more\s+)?(cpu|memory|disk|storage)/, /\bchange\s+the\s+(size|plan|configuration)/ ], monitor: [ /\b(show|list|display|check|status|monitor|view)\b(?!.*\b(available|options|resources|templates|plans)\b)/, /\bwhat\s+(vm|server|machine)/, /\bhow\s+many\s+(vm|server|machine)/ ], destroy: [ /\b(delete|remove|destroy|terminate|stop|kill)\b/, /\btear\s+down/, /\bshut\s+down/ ], discover: [ /\b(available|options|resources|templates|plans)\b/, /\bshow\s+me\s+(all|available)/, /\bwhat\s+(are|is)\s+(available|possible)/, /\bwhat\s+can\s+i\s+(create|do)/ ] }; // Calculate confidence for each intent let maxConfidence = 0; let detectedAction = 'unknown'; for (const [action, patterns] of Object.entries(intentPatterns)) { let matches = 0; for (const pattern of patterns) { if (pattern.test(input)) { matches++; } } const confidence = patterns.length > 0 ? matches / patterns.length : 0; if (confidence > maxConfidence) { maxConfidence = confidence; detectedAction = action; } } result.action = detectedAction; result.confidence = maxConfidence; // Entity Extraction for VM creation if (result.action === 'create') { // Extract VM names and count const namePatterns = [ /\b(?:vm|server|machine)s?\s+(?:named\s+)?["']?([a-zA-Z0-9\-_]+(?:\s*->\s*[a-zA-Z0-9\-_]+)?)["']?/, /\b(?:named\s+)?["']?([a-zA-Z0-9\-_]+(?:\s*->\s*[a-zA-Z0-9\-_]+)?)["']?\s+(?:vm|server|machine)/, /\bcreate\s+(?:(?:vm|server|machine)s?\s+)?["']?([a-zA-Z0-9\-_]+(?:\s*->\s*[a-zA-Z0-9\-_]+)?)["']?/, /\b(?:vm|server|machine)\s+named\s+["']?([a-zA-Z0-9\-_]+(?:\s*->\s*[a-zA-Z0-9\-_]+)?)["']?/ ]; for (const pattern of namePatterns) { const match = input.match(pattern); if (match) { const nameInput = match[1] || match[2]; result.entities.vmNames = parseVMNames(nameInput); break; } } // Extract count const countMatch = input.match(/\b(\d+)\s+(?:vm|server|machine)/); if (countMatch) { result.entities.count = parseInt(countMatch[1]); } // Extract OS template const osPatterns = [ /\b(ubuntu|rocky|centos|debian|rhel|red\s*hat|alma|almalinux)(?:\s+(\d+(?:\.\d+)?))?/, /\busing\s+([a-zA-Z0-9\-_]+)\s+(?:template|os|operating)/, /\b(?:template|os|operating)\s+([a-zA-Z0-9\-_]+)/ ]; for (const pattern of osPatterns) { const match = input.match(pattern); if (match) { result.entities.osTemplate = match[0]; break; } } // Extract size/memory const sizePatterns = [ /\b(small|medium|large|tiny)\b/, /\b(\d+)\s*gb\s+(?:memory|ram)\b/, /\b(\d+)\s*cpu[s]?\s*,?\s*(\d+)\s*gb/, /\bwith\s+(\d+(?:gb|cpu))\b/, /\b(\d+gb)\b/ ]; for (const pattern of sizePatterns) { const match = input.match(pattern); if (match) { result.entities.size = match[0]; break; } } // Extract group/environment const groupPatterns = [ /\bin\s+(?:the\s+)?([a-zA-Z0-9\-_]+)\s+(?:group|environment|site)/, /\b(?:group|environment|site)\s+([a-zA-Z0-9\-_]+)/, /\bfor\s+([a-zA-Z0-9\-_]+)\s+(?:environment|testing|production)/ ]; for (const pattern of groupPatterns) { const match = input.match(pattern); if (match) { result.entities.group = match[1]; break; } } // Extract zone/cloud const zonePatterns = [ /\bon\s+([a-zA-Z0-9\-_]+)\s+(?:zone|cloud)/, /\b(?:zone|cloud)\s+([a-zA-Z0-9\-_]+)/, /\bin\s+([a-zA-Z0-9\-_]+)\s+(?:zone|cloud)/, /\b(?:deploy|launch|create)\s+(?:in\s+)?([a-zA-Z0-9\-_]+)\s+zone/ ]; for (const pattern of zonePatterns) { const match = input.match(pattern); if (match) { result.entities.zone = match[1]; break; } } // Extract distribution strategy if (input.includes('spread') || input.includes('distribute') || input.includes('across')) { result.entities.distribution = 'spread'; } else if (input.includes('each node') || input.includes('all nodes')) { result.entities.distribution = 'spread'; } else if (input.includes('node') && input.match(/node[s]?\s*[\d,\s]+/)) { const nodeMatch = input.match(/node[s]?\s*([\d,\s]+)/); if (nodeMatch) { result.entities.distribution = nodeMatch[1].replace(/\s+/g, ''); } } // Boost confidence if we extracted entities const entityCount = Object.keys(result.entities).length; if (entityCount > 0) { result.confidence = Math.min(0.95, result.confidence + (entityCount * 0.1)); } } return result; }