get_tenant
Retrieve detailed information about a specific tenant in VergeOS virtualization platforms by providing the tenant ID.
Instructions
Get detailed information about a specific tenant
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Tenant ID |
Implementation Reference
- src/index.js:159-161 (handler)Core handler function in the VergeOSAPI class that executes the tool logic by making an authenticated HTTP request to the VergeOS API endpoint for tenant details.async getTenant(id) { return this.request(`/api/v4/tenants/${id}?fields=most`); }
- src/index.js:417-430 (schema)Input schema definition for the get_tenant tool, specifying the required 'id' parameter as a number.{ name: "get_tenant", description: "Get detailed information about a specific tenant", inputSchema: { type: "object", properties: { id: { type: "number", description: "Tenant ID", }, }, required: ["id"], }, },
- src/index.js:579-581 (registration)Registration and dispatch logic within the MCP CallToolRequest handler switch statement that routes the tool call to the getTenant function.case "get_tenant": result = await api.getTenant(args.id); break;
- src/mcp-http-server.js:161-472 (handler)Identical handler function in the HTTP MCP server variant.return { vm_id: id, name: vm.name, machine: vm.machine, running: status.running, power_state: status.status, status_info: status.status_info || "", migratable: status.migratable, }; } async vmAction(id, action) { return this.request("/api/v4/vm_actions", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ vm: id, action }), }); } async powerOnVM(id) { const status = await this.getVMStatus(id); if (status.running) { return { success: false, error: `VM '${status.name}' is already running`, current_state: status.power_state }; } await this.vmAction(id, "poweron"); return { success: true, message: `Power on command sent to VM '${status.name}'`, previous_state: status.power_state }; } async powerOffVM(id, options = {}) { const { wait_timeout = 0, force_after_timeout = false } = options; const status = await this.getVMStatus(id); if (!status.running) { return { success: true, message: `VM '${status.name}' is already stopped`, current_state: status.power_state, was_running: false }; } // Send graceful shutdown await this.vmAction(id, "poweroff"); // If no wait requested, return immediately if (wait_timeout <= 0) { return { success: true, message: `Graceful shutdown command sent to VM '${status.name}'`, previous_state: status.power_state, note: "Use wait_timeout parameter to wait for shutdown completion" }; } // Poll for shutdown with timeout const startTime = Date.now(); const pollInterval = 3000; // 3 seconds const maxWait = Math.min(wait_timeout, 300) * 1000; // Cap at 5 minutes while (Date.now() - startTime < maxWait) { await new Promise(resolve => setTimeout(resolve, pollInterval)); const currentStatus = await this.getVMStatus(id); if (!currentStatus.running) { return { success: true, message: `VM '${status.name}' shut down gracefully`, final_state: currentStatus.power_state, elapsed_seconds: Math.round((Date.now() - startTime) / 1000) }; } } // Timeout reached - check if we should force if (force_after_timeout) { await this.vmAction(id, "kill"); // Wait a moment for kill to take effect await new Promise(resolve => setTimeout(resolve, 2000)); const finalStatus = await this.getVMStatus(id); return { success: true, message: `VM '${status.name}' did not shut down within ${wait_timeout}s - forced power off`, final_state: finalStatus.power_state, forced: true, elapsed_seconds: Math.round((Date.now() - startTime) / 1000) }; } // Timeout without force const currentStatus = await this.getVMStatus(id); return { success: false, error: `VM '${status.name}' did not shut down within ${wait_timeout}s`, current_state: currentStatus.power_state, elapsed_seconds: Math.round((Date.now() - startTime) / 1000), hint: "Use force_after_timeout=true to automatically force shutdown after timeout" }; } async forceOffVM(id) { const status = await this.getVMStatus(id); if (!status.running) { return { success: true, message: `VM '${status.name}' is already stopped`, current_state: status.power_state }; } await this.vmAction(id, "kill"); return { success: true, message: `Force power off (kill) command sent to VM '${status.name}'`, previous_state: status.power_state }; } async resetVM(id) { const status = await this.getVMStatus(id); if (!status.running) { return { success: false, error: `VM '${status.name}' is not running - cannot reset`, current_state: status.power_state }; } await this.vmAction(id, "reset"); return { success: true, message: `Reset command sent to VM '${status.name}'`, previous_state: status.power_state }; } async getVMNics(vmId) { // Get VM to find machine ID const vm = await this.getVM(vmId); const machineId = vm.machine; const nics = await this.request(`/api/v4/machine_nics?machine=${machineId}&fields=all`); return nics.filter((nic) => nic.machine === machineId).map(n => ({ id: n.$key, name: n.name, mac: n.macaddress, network_id: n.vnet, ip: n.ipaddress, interface: n.interface, enabled: n.enabled, })); } async getVMDrives(vmId) { // Get VM to find machine ID (same pattern as getVMNics) const vm = await this.getVM(vmId); const machineId = vm.machine; const drives = await this.request(`/api/v4/machine_drives?machine=${machineId}&fields=all`); // Filter by machine ID and return simplified info return drives .filter((d) => d.machine === machineId) .map((d) => ({ id: d.$key, name: d.name, interface: d.interface, size_gb: d.disksize ? Math.round(d.disksize / (1024 * 1024 * 1024)) : null, size_bytes: d.disksize || null, enabled: d.enabled, media_type: d.media_type, description: d.description || "", })); } async resizeDrive(driveId, newSizeGB) { // Get current drive info const drive = await this.request(`/api/v4/machine_drives/${driveId}?fields=all`); if (!drive) { return { success: false, error: `Drive ${driveId} not found` }; } const currentSizeGB = Math.round(drive.disksize / (1024 * 1024 * 1024)); const newSizeBytes = newSizeGB * 1024 * 1024 * 1024; if (newSizeGB <= currentSizeGB) { return { success: false, error: `New size (${newSizeGB} GB) must be larger than current size (${currentSizeGB} GB). Shrinking disks is not supported.`, current_size_gb: currentSizeGB }; } // Resize the drive await this.request(`/api/v4/machine_drives/${driveId}`, { method: "PUT", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ disksize: newSizeBytes }), }); return { success: true, message: `Drive '${drive.name}' resized from ${currentSizeGB} GB to ${newSizeGB} GB`, drive_id: driveId, previous_size_gb: currentSizeGB, new_size_gb: newSizeGB, note: "You may need to extend the partition/filesystem inside the VM to use the new space" }; } async addDrive(machineId, options = {}) { const { name, size_gb, interface_type = "virtio-scsi", description = "" } = options; if (!name) { return { success: false, error: "Drive name is required" }; } if (!size_gb || size_gb < 1) { return { success: false, error: "Size in GB is required and must be at least 1 GB" }; } const sizeBytes = size_gb * 1024 * 1024 * 1024; // Create the drive const result = await this.request("/api/v4/machine_drives", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ machine: machineId, name: name, disksize: sizeBytes, interface: interface_type, media: "disk", description: description, enabled: true, }), }); return { success: true, message: `Drive '${name}' (${size_gb} GB) added to machine ${machineId}`, drive_id: result.$key, name: name, size_gb: size_gb, interface: interface_type, note: "The VM may need to be restarted to detect the new drive" }; } async modifyVM(vmId, options = {}) { const { cpu_cores, ram_mb, shutdown_if_running = false, wait_timeout = 60, force_after_timeout = true } = options; if (!cpu_cores && !ram_mb) { return { success: false, error: "Must specify cpu_cores and/or ram_mb to modify" }; } // Get current VM info and status const vm = await this.getVM(vmId); const status = await this.getVMStatus(vmId); const changes = {}; if (cpu_cores) changes.cpu_cores = cpu_cores; if (ram_mb) changes.ram = ram_mb; // Check if VM is running if (status.running) { if (!shutdown_if_running) { return { success: false, error: `VM '${vm.name}' is currently running. CPU/RAM changes require the VM to be powered off.`, current_state: status.power_state, current_cpu: vm.cpu_cores, current_ram_mb: vm.ram, requested_cpu: cpu_cores || vm.cpu_cores, requested_ram_mb: ram_mb || vm.ram, hint: "Set shutdown_if_running=true to automatically shut down the VM, apply changes, and optionally restart it" }; } // Shut down the VM const shutdownResult = await this.powerOffVM(vmId, { wait_timeout, force_after_timeout }); if (!shutdownResult.success && !shutdownResult.message?.includes("already stopped")) { return { success: false, error: `Failed to shut down VM '${vm.name}': ${shutdownResult.error}`, shutdown_result: shutdownResult }; } } // Apply changes await this.request(`/api/v4/vms/${vmId}`, { method: "PUT", headers: { "Content-Type": "application/json" }, body: JSON.stringify(changes), }); return { success: true, message: `VM '${vm.name}' modified successfully`, vm_id: vmId, previous_cpu: vm.cpu_cores, previous_ram_mb: vm.ram, new_cpu: cpu_cores || vm.cpu_cores, new_ram_mb: ram_mb || vm.ram, was_running: status.running, note: status.running ? "VM was shut down to apply changes. Use power_on_vm to restart it." : "VM is stopped. Use power_on_vm to start it with new settings." }; } // Network Operations async listNetworks(options = {}) { const { type, name, enabled, limit = 100, offset = 0 } = options; const networks = await this.request("/api/v4/vnets?fields=most"); // Filter let filtered = networks; if (type) filtered = filtered.filter(n => n.type === type); if (name) filtered = filtered.filter(n => n.name?.toLowerCase().includes(name.toLowerCase())); if (enabled !== undefined) filtered = filtered.filter(n => n.enabled === enabled); // Paginate and return summary view return filtered.slice(offset, offset + limit).map(n => ({ id: n.$key, name: n.name, type: n.type, network: n.network, enabled: n.enabled, running: n.running, description: n.description || null, })); } async getNetwork(id) { return this.request(`/api/v4/vnets/${id}?fields=most`); } async networkAction(id, action) { return this.request("/api/v4/vnet_actions", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ vnet: id, action }), }); } // Tenant Operations async listTenants() { return this.request("/api/v4/tenants?fields=most"); } async getTenant(id) { return this.request(`/api/v4/tenants/${id}?fields=most`); }
- src/mcp-http-server.js:601-602 (schema)Schema in the HTTP MCP server's compact TOOLS array.{ name: "get_tenant", description: "Get tenant details", inputSchema: { type: "object", properties: { id: { type: "number" } }, required: ["id"] } }, { name: "tenant_action", description: "Perform tenant action", inputSchema: { type: "object", properties: { id: { type: "number" }, action: { type: "string", enum: ["poweron", "poweroff", "reset"] } }, required: ["id", "action"] } },