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
JavaScript
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);
});