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

129 lines (124 loc) 4.87 kB
#!/usr/bin/env node import { Server } from "@modelcontextprotocol/sdk/server/index.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js"; import dotenv from "dotenv"; import { existsSync } from "fs"; import { join } from "path"; import { homedir } from "os"; import { readFileSync } from "fs"; import { allTools, toolHandlers } from "./tools/index.js"; // Parse command line arguments function parseArgs() { const args = process.argv.slice(2); const result = {}; for (let i = 0; i < args.length; i++) { const arg = args[i]; if ((arg === '--endpoint' || arg === '-e') && i + 1 < args.length) { result.endpoint = args[i + 1]; i++; // Skip next arg since we consumed it } else if ((arg === '--token' || arg === '-t') && i + 1 < args.length) { result.token = args[i + 1]; i++; // Skip next arg since we consumed it } else if (arg === '--help' || arg === '-h') { console.log(`VME MCP Server - Natural Language Infrastructure Management Usage: vme-mcp-server [options] Options: -e, --endpoint <url> VME API endpoint URL -t, --token <token> VME API bearer token -h, --help Show this help message Environment Variables: VME_ENDPOINT VME API endpoint URL VME_TOKEN VME API bearer token Note: Command line arguments take precedence over environment variables. If no configuration is provided, the server will look for .env files.`); process.exit(0); } } return result; } // Get version from package.json function getPackageVersion() { const packagePath = new URL('../package.json', import.meta.url); const packageJson = JSON.parse(readFileSync(packagePath, 'utf8')); return packageJson.version; } // Load environment variables from multiple locations for global install support function loadEnvironmentConfig(cliArgs) { // Priority order for .env file locations: const envPaths = [ // 1. Current working directory (for local development) join(process.cwd(), '.env'), // 2. Home directory (for global installs) join(homedir(), '.env'), // 3. XDG config directory (Linux/Mac standard) join(homedir(), '.config', 'vme-mcp-server', '.env'), // 4. User's Documents folder (Windows-friendly) join(homedir(), 'Documents', '.env.vme-mcp-server') ]; // Try to load .env from the first available location for (const envPath of envPaths) { if (existsSync(envPath)) { dotenv.config({ path: envPath }); console.error(`VME MCP: Loaded config from ${envPath}`); break; } } // Command line arguments take highest priority - override any env vars if (cliArgs.endpoint) { process.env.VME_ENDPOINT = cliArgs.endpoint; console.error('VME MCP: Using endpoint from command line argument'); } if (cliArgs.token) { process.env.VME_TOKEN = cliArgs.token; console.error('VME MCP: Using token from command line argument'); } // If no configuration found at all, warn the user if (!process.env.VME_ENDPOINT || !process.env.VME_TOKEN) { console.error('VME MCP: Warning - Missing VME_ENDPOINT or VME_TOKEN configuration'); console.error('VME MCP: Use --endpoint and --token arguments or set environment variables'); } } // Parse CLI arguments and load configuration const cliArgs = parseArgs(); loadEnvironmentConfig(cliArgs); // Disable TLS verification for VME API (if needed) process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; // Create VME MCP server with modular architecture const server = new Server({ name: "vme-mcp-server", version: getPackageVersion(), }, { capabilities: { tools: {}, }, }); // Register all tools using the modular tool definitions server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: allTools, }; }); // Handle tool calls using the modular tool handlers server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; // Look up the handler for this tool const handler = toolHandlers[name]; if (!handler) { throw new Error(`Unknown tool: ${name}`); } // Call the appropriate handler return await handler(args); }); // Start the server async function main() { const transport = new StdioServerTransport(); await server.connect(transport); console.error(`VME MCP Server v${getPackageVersion()} running on stdio with modular architecture`); } main().catch((error) => { console.error("Failed to start server:", error); process.exit(1); });