Skip to main content
Glama

VPS Initialize

by oxy-Op
mcp-server.ts10.8 kB
import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { CallToolRequestSchema, ListToolsRequestSchema, Tool, } from '@modelcontextprotocol/sdk/types.js'; import { z } from 'zod'; import { SSHService } from './ssh-service.js'; import { VPSInitializer } from '../tools/vps-initializer.js'; import { NginxManager } from '../tools/nginx-manager.js'; import { GitHubCICD } from '../tools/github-cicd.js'; import { logger } from '../utils/logger.js'; import { SSHConfig } from '../types/index.js'; // Zod schemas for tool parameters const SSHConfigSchema = z.object({ host: z.string().describe('The IP address or hostname of the VPS'), port: z.number().optional().default(22).describe('SSH port (default: 22)'), username: z.string().describe('SSH username'), password: z.string().optional().describe('SSH password (if not using key)'), privateKeyPath: z.string().optional().describe('Path to private key file'), passphrase: z.string().optional().describe('Passphrase for private key'), }); const VPSServicesSchema = z.object({ nodejs: z.boolean().optional().default(false).describe('Install Node.js'), pm2: z.boolean().optional().default(false).describe('Install PM2'), rust: z.boolean().optional().default(false).describe('Install Rust'), nginx: z.boolean().optional().default(false).describe('Install Nginx'), redis: z.boolean().optional().default(false).describe('Install Redis'), }); const NginxConfigSchema = z.object({ domain: z.string().describe('Domain name for Nginx configuration'), port: z.number().describe('Backend port to proxy to'), ssl: z.boolean().optional().default(true).describe('Enable SSL with Certbot'), }); const GitHubConfigSchema = z.object({ repoUrl: z.string().describe('GitHub repository URL'), deployPath: z.string().describe('Deployment path on the server'), }); export class MCPVPSServer { private server: Server; private sshService: SSHService | null = null; private vpsInitializer: VPSInitializer | null = null; private nginxManager: NginxManager | null = null; private githubCICD: GitHubCICD | null = null; constructor() { this.server = new Server( { name: 'mcp-vps-initialize', version: '1.0.0', }, { capabilities: { tools: {}, }, } ); this.setupTools(); } private setupTools(): void { // List available tools this.server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: 'ssh_connect', description: 'Connect to a VPS via SSH using password or private key', inputSchema: { type: 'object', properties: { host: { type: 'string', description: 'VPS IP address or hostname' }, port: { type: 'number', description: 'SSH port (default: 22)' }, username: { type: 'string', description: 'SSH username' }, password: { type: 'string', description: 'SSH password (optional)' }, privateKeyPath: { type: 'string', description: 'Private key file path (optional)' }, passphrase: { type: 'string', description: 'Private key passphrase (optional)' }, }, required: ['host', 'username'], }, }, { name: 'vps_initialize', description: 'Initialize a fresh VPS with basic setup and optional services', inputSchema: { type: 'object', properties: { services: { type: 'object', properties: { nodejs: { type: 'boolean', description: 'Install Node.js' }, pm2: { type: 'boolean', description: 'Install PM2' }, rust: { type: 'boolean', description: 'Install Rust' }, nginx: { type: 'boolean', description: 'Install Nginx' }, redis: { type: 'boolean', description: 'Install Redis' }, }, }, }, required: [], }, }, { name: 'nginx_setup', description: 'Configure Nginx with domain, reverse proxy, and SSL', inputSchema: { type: 'object', properties: { domain: { type: 'string', description: 'Domain name' }, port: { type: 'number', description: 'Backend port to proxy to' }, ssl: { type: 'boolean', description: 'Enable SSL with Certbot' }, }, required: ['domain', 'port'], }, }, { name: 'github_cicd_setup', description: 'Setup GitHub CI/CD with deploy keys and workflow', inputSchema: { type: 'object', properties: { repoUrl: { type: 'string', description: 'GitHub repository URL' }, deployPath: { type: 'string', description: 'Deployment path on server' }, }, required: ['repoUrl', 'deployPath'], }, }, { name: 'execute_command', description: 'Execute a command on the connected VPS', inputSchema: { type: 'object', properties: { command: { type: 'string', description: 'Command to execute' }, }, required: ['command'], }, }, ] satisfies Tool[], }; }); // Handle tool calls this.server.setRequestHandler(CallToolRequestSchema, async request => { const { name, arguments: args } = request.params; try { switch (name) { case 'ssh_connect': return await this.handleSSHConnect(args); case 'vps_initialize': return await this.handleVPSInitialize(args); case 'nginx_setup': return await this.handleNginxSetup(args); case 'github_cicd_setup': return await this.handleGitHubCICDSetup(args); case 'execute_command': return await this.handleExecuteCommand(args); default: throw new Error(`Unknown tool: ${name}`); } } catch (error) { logger.error('Tool execution failed', { tool: name, error: error instanceof Error ? error.message : 'Unknown error', }); return { content: [ { type: 'text', text: `Error: ${error instanceof Error ? error.message : 'Unknown error'}`, }, ], }; } }); } private async handleSSHConnect( args: unknown ): Promise<{ content: Array<{ type: 'text'; text: string }> }> { const parsedConfig = SSHConfigSchema.parse(args); const config: SSHConfig = { host: parsedConfig.host, port: parsedConfig.port, username: parsedConfig.username, password: parsedConfig.password || undefined, privateKeyPath: parsedConfig.privateKeyPath || undefined, passphrase: parsedConfig.passphrase || undefined, }; this.sshService = new SSHService(config); const connected = await this.sshService.connect(); if (connected) { // Initialize other services this.vpsInitializer = new VPSInitializer(this.sshService); this.nginxManager = new NginxManager(this.sshService); this.githubCICD = new GitHubCICD(this.sshService); return { content: [ { type: 'text', text: `Successfully connected to ${config.host} as ${config.username}`, }, ], }; } else { throw new Error('Failed to establish SSH connection'); } } private async handleVPSInitialize( args: unknown ): Promise<{ content: Array<{ type: 'text'; text: string }> }> { if (!this.vpsInitializer) { throw new Error('SSH connection not established. Please connect first.'); } const services = VPSServicesSchema.parse(args); const results = await this.vpsInitializer.initializeVPS(services); const output = results .map( result => `${result.service}: ${result.success ? 'Success' : 'Failed'} - ${result.message}` ) .join('\n'); return { content: [ { type: 'text', text: `VPS Initialization Results:\n${output}`, }, ], }; } private async handleNginxSetup( args: unknown ): Promise<{ content: Array<{ type: 'text'; text: string }> }> { if (!this.nginxManager) { throw new Error('SSH connection not established. Please connect first.'); } const config = NginxConfigSchema.parse(args); const result = await this.nginxManager.setupNginx(config); return { content: [ { type: 'text', text: result.success ? `Nginx configured successfully for ${config.domain}` : `Nginx setup failed: ${result.message}`, }, ], }; } private async handleGitHubCICDSetup( args: unknown ): Promise<{ content: Array<{ type: 'text'; text: string }> }> { if (!this.githubCICD) { throw new Error('SSH connection not established. Please connect first.'); } const config = GitHubConfigSchema.parse(args); const result = await this.githubCICD.setupCICD(config); return { content: [ { type: 'text', text: result.success ? `GitHub CI/CD setup completed. Deploy key and workflow generated.` : `GitHub CI/CD setup failed: ${result.message}`, }, ], }; } private async handleExecuteCommand( args: unknown ): Promise<{ content: Array<{ type: 'text'; text: string }> }> { if (!this.sshService) { throw new Error('SSH connection not established. Please connect first.'); } const { command } = z.object({ command: z.string() }).parse(args); const result = await this.sshService.executeCommand(command); return { content: [ { type: 'text', text: `Command: ${command}\nExit Code: ${result.exitCode}\nOutput:\n${result.stdout}\n${result.stderr ? `Error:\n${result.stderr}` : ''}`, }, ], }; } async start(): Promise<void> { const transport = new StdioServerTransport(); await this.server.connect(transport); logger.info('MCP VPS Initialize server started'); } async stop(): Promise<void> { if (this.sshService) { await this.sshService.disconnect(); } logger.info('MCP VPS Initialize server stopped'); } }

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/oxy-Op/DevPilot'

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