This repository has been archived on 2026-08-13. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
droidfleet-visor/server.ts

1269 lines
46 KiB
TypeScript

import express from 'express';
import { createServer as createViteServer } from 'vite';
import path from 'path';
import { fileURLToPath } from 'url';
import dotenv from 'dotenv';
import {
AndroidVM,
UserSubscription,
AndroidVersion,
Architecture,
BootloaderConfig,
DeviceProfileId,
ProxyConfig,
ProxyType,
} from './src/types.js';
import { HardwareProfiles, DEFAULT_ANDROID_APPS } from './src/data/deviceProfiles.js';
dotenv.config();
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const app = express();
const PORT = 3000;
app.use(express.json({ limit: '50mb' }));
// In-Memory Database for Hypervisor & Rental Subscriptions
let userSubscription: UserSubscription = {
plan: 'free',
maxVms: 1, // 1 Free VM instance
pricePerMonth: 0,
activeVmCount: 1,
renewsAt: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString(),
paymentMethod: 'Free Tier Active',
};
let virtualMachines: AndroidVM[] = [
{
id: 'vm-cloud-001',
name: 'Pixel 8 Pro - Android 14 (AOSP)',
androidVersion: '14 (UpsideDownCake)',
arch: 'x86_64',
profile: HardwareProfiles.PIXEL_8_PRO,
ramGb: 8,
vcpu: 4,
storageGb: 64,
bootloader: {
isUnlocked: true,
rootMethod: 'magisk',
customRecovery: true,
selinuxMode: 'permissive',
kernelCmdline: 'console=ttyMSM0,115200 androidboot.hardware=qcom androidboot.selinux=permissive',
gpuAcceleration: 'swiftshader',
},
status: 'running',
ipAddress: '192.168.122.105',
adbPort: 5555,
vncPort: 5901,
batteryLevel: 94,
isCharging: true,
orientation: 'portrait',
location: {
latitude: 37.7749,
longitude: -122.4194,
addressName: 'San Francisco, CA, USA',
},
metrics: {
cpuUsagePct: 18.5,
ramUsageMb: 3420,
totalRamMb: 8192,
fps: 60,
networkRxKbps: 450,
networkTxKbps: 120,
uptimeSeconds: 14200,
},
installedApps: [...DEFAULT_ANDROID_APPS],
currentAppPackage: 'com.android.launcher3',
proxy: {
id: 'px-1',
enabled: true,
type: 'SOCKS5',
host: '104.28.19.42',
port: 1080,
country: 'United States',
countryCode: 'US',
anonymity: 'Elite',
latencyMs: 38,
externalIp: '104.28.19.42',
},
createdAt: new Date(Date.now() - 4 * 3600 * 1000).toISOString(),
snapshotCount: 2,
},
];
// Proxifly Master Proxy Pool Dataset
const PROXIFLY_PROXIES: ProxyConfig[] = [
{ id: 'px-1', enabled: true, type: 'SOCKS5', host: '104.28.19.42', port: 1080, country: 'United States', countryCode: 'US', anonymity: 'Elite', latencyMs: 38, externalIp: '104.28.19.42' },
{ id: 'px-2', enabled: true, type: 'HTTP', host: '185.220.101.5', port: 8080, country: 'Germany', countryCode: 'DE', anonymity: 'Elite', latencyMs: 62, externalIp: '185.220.101.5' },
{ id: 'px-3', enabled: true, type: 'SOCKS5', host: '139.162.24.11', port: 1080, country: 'Japan', countryCode: 'JP', anonymity: 'Elite', latencyMs: 110, externalIp: '139.162.24.11' },
{ id: 'px-4', enabled: true, type: 'HTTPS', host: '51.15.22.180', port: 3128, country: 'France', countryCode: 'FR', anonymity: 'Anonymous', latencyMs: 75, externalIp: '51.15.22.180' },
{ id: 'px-5', enabled: true, type: 'SOCKS5', host: '128.199.201.89', port: 1080, country: 'Singapore', countryCode: 'SG', anonymity: 'Elite', latencyMs: 145, externalIp: '128.199.201.89' },
{ id: 'px-6', enabled: true, type: 'HTTP', host: '198.244.180.20', port: 8000, country: 'United Kingdom', countryCode: 'GB', anonymity: 'Elite', latencyMs: 54, externalIp: '198.244.180.20' },
{ id: 'px-7', enabled: true, type: 'SOCKS5', host: '159.203.42.109', port: 1080, country: 'Canada', countryCode: 'CA', anonymity: 'Elite', latencyMs: 42, externalIp: '159.203.42.109' },
{ id: 'px-8', enabled: true, type: 'HTTP', host: '177.71.180.4', port: 8080, country: 'Brazil', countryCode: 'BR', anonymity: 'Anonymous', latencyMs: 168, externalIp: '177.71.180.4' },
{ id: 'px-9', enabled: true, type: 'SOCKS5', host: '103.214.112.50', port: 1080, country: 'India', countryCode: 'IN', anonymity: 'Elite', latencyMs: 195, externalIp: '103.214.112.50' },
{ id: 'px-10', enabled: true, type: 'HTTPS', host: '45.76.182.90', port: 8443, country: 'Australia', countryCode: 'AU', anonymity: 'Elite', latencyMs: 180, externalIp: '45.76.182.90' },
{ id: 'px-11', enabled: true, type: 'SOCKS5', host: '211.233.72.18', port: 1080, country: 'South Korea', countryCode: 'KR', anonymity: 'Elite', latencyMs: 128, externalIp: '211.233.72.18' },
{ id: 'px-12', enabled: true, type: 'HTTP', host: '94.23.148.10', port: 3128, country: 'Netherlands', countryCode: 'NL', anonymity: 'Elite', latencyMs: 49, externalIp: '94.23.148.10' },
];
// Synchronize Subscription Count
function syncActiveVmCount() {
userSubscription.activeVmCount = virtualMachines.length;
}
// Background simulation for VM metrics (CPU, RAM, FPS updates)
setInterval(() => {
virtualMachines.forEach((vm) => {
if (vm.status === 'running') {
vm.metrics.cpuUsagePct = Math.round((10 + Math.random() * 35) * 10) / 10;
vm.metrics.fps = Math.round(55 + Math.random() * 5);
vm.metrics.networkRxKbps = Math.round(100 + Math.random() * 800);
vm.metrics.networkTxKbps = Math.round(20 + Math.random() * 200);
vm.metrics.uptimeSeconds += 2;
}
});
}, 2000);
// ================= API ENDPOINTS ================= //
// 1. Health check
app.get('/api/health', (req, res) => {
res.json({
status: 'ok',
kvmAvailable: true,
hypervisorVersion: 'KVM/QEMU 8.2.0 (VirtIO-GPU Accelerated)',
vmsActive: virtualMachines.length,
timestamp: new Date().toISOString(),
});
});
// 2. Get User Rental Subscription Status
app.get('/api/user/subscription', (req, res) => {
syncActiveVmCount();
res.json(userSubscription);
});
// 3. Upgrade or Switch Subscription Tier ($5/mo for 5 VMs)
app.post('/api/user/subscription/upgrade', (req, res) => {
const { targetPlan, paymentMethod } = req.body;
if (targetPlan === 'pro') {
userSubscription = {
plan: 'pro',
maxVms: 5, // 5 VMs for $5/mo
pricePerMonth: 5,
activeVmCount: virtualMachines.length,
renewsAt: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString(),
paymentMethod: paymentMethod || 'Visa ending in 4242',
};
} else {
userSubscription = {
plan: 'free',
maxVms: 1, // 1 Free VM
pricePerMonth: 0,
activeVmCount: virtualMachines.length,
renewsAt: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString(),
paymentMethod: 'Free Tier Active',
};
}
res.json({
message: `Successfully updated subscription to ${userSubscription.plan.toUpperCase()} tier!`,
subscription: userSubscription,
});
});
// 4. List All Virtual Machines
app.get('/api/vms', (req, res) => {
res.json(virtualMachines);
});
// 5. Create / Deploy New Android Virtual Device
app.post('/api/vms/create', (req, res) => {
syncActiveVmCount();
// Enforce Rental Tier Limit
if (virtualMachines.length >= userSubscription.maxVms) {
return res.status(403).json({
error: 'SUBSCRIPTION_LIMIT_EXCEEDED',
message: `Your current ${userSubscription.plan.toUpperCase()} plan limit is ${userSubscription.maxVms} Android VM(s). Upgrade to Pro ($5/mo for 5 Android VMs) to deploy more instances!`,
currentPlan: userSubscription.plan,
maxVms: userSubscription.maxVms,
});
}
const {
name,
androidVersion = '14 (UpsideDownCake)',
arch = 'x86_64',
profileId = 'pixel-8-pro',
ramGb = 8,
vcpu = 4,
storageGb = 64,
bootloaderUnlocked = true,
rootMethod = 'magisk',
selinuxMode = 'permissive',
gpuAcceleration = 'swiftshader',
} = req.body;
let selectedProfile = HardwareProfiles.PIXEL_8_PRO;
if (profileId === 'galaxy-s24-ultra') selectedProfile = HardwareProfiles.GALAXY_S24_ULTRA;
if (profileId === 'oneplus-12') selectedProfile = HardwareProfiles.ONEPLUS_12;
if (profileId === 'aosp-tablet-10') selectedProfile = HardwareProfiles.AOSP_TABLET;
const newVmId = `vm-cloud-00${virtualMachines.length + 1}`;
const assignedAdbPort = 5555 + virtualMachines.length;
const assignedVncPort = 5901 + virtualMachines.length;
const newVm: AndroidVM = {
id: newVmId,
name: name || `${selectedProfile.name} - Android ${androidVersion.split(' ')[0]}`,
androidVersion: androidVersion as AndroidVersion,
arch: arch as Architecture,
profile: selectedProfile,
ramGb: Number(ramGb),
vcpu: Number(vcpu),
storageGb: Number(storageGb),
bootloader: {
isUnlocked: Boolean(bootloaderUnlocked),
rootMethod: rootMethod,
customRecovery: true,
selinuxMode: selinuxMode,
kernelCmdline: `console=ttyMSM0,115200 androidboot.hardware=qcom androidboot.selinux=${selinuxMode}`,
gpuAcceleration: gpuAcceleration,
},
status: 'running',
ipAddress: `192.168.122.${105 + virtualMachines.length}`,
adbPort: assignedAdbPort,
vncPort: assignedVncPort,
batteryLevel: 100,
isCharging: true,
orientation: 'portrait',
location: {
latitude: 37.7749,
longitude: -122.4194,
addressName: 'San Francisco, CA, USA',
},
metrics: {
cpuUsagePct: 12.0,
ramUsageMb: Math.round(Number(ramGb) * 1024 * 0.35),
totalRamMb: Number(ramGb) * 1024,
fps: 60,
networkRxKbps: 320,
networkTxKbps: 80,
uptimeSeconds: 10,
},
installedApps: [...DEFAULT_ANDROID_APPS],
currentAppPackage: 'com.android.launcher3',
createdAt: new Date().toISOString(),
snapshotCount: 1,
};
virtualMachines.push(newVm);
syncActiveVmCount();
res.status(201).json(newVm);
});
// 6. Delete / Terminate Android VM Instance
app.delete('/api/vms/:id', (req, res) => {
const { id } = req.params;
const initialLen = virtualMachines.length;
virtualMachines = virtualMachines.filter((vm) => vm.id !== id);
if (virtualMachines.length === initialLen) {
return res.status(404).json({ error: 'VM instance not found' });
}
syncActiveVmCount();
res.json({ message: `Terminated VM instance ${id}`, activeVms: virtualMachines.length });
});
// 7. Power Actions (Start, Reboot, Stop, Fastboot, Recovery, Reset)
app.post('/api/vms/:id/power', (req, res) => {
const { id } = req.params;
const { action } = req.body;
const vm = virtualMachines.find((v) => v.id === id);
if (!vm) {
return res.status(404).json({ error: 'VM not found' });
}
if (action === 'start') {
vm.status = 'running';
vm.metrics.uptimeSeconds = 0;
} else if (action === 'stop') {
vm.status = 'stopped';
} else if (action === 'reboot') {
vm.status = 'booting';
setTimeout(() => {
vm.status = 'running';
vm.metrics.uptimeSeconds = 0;
}, 2000);
} else if (action === 'boot_fastboot') {
vm.status = 'fastboot';
} else if (action === 'boot_recovery') {
vm.status = 'recovery';
} else if (action === 'reset') {
vm.installedApps = [...DEFAULT_ANDROID_APPS];
vm.currentAppPackage = 'com.android.launcher3';
vm.status = 'running';
}
res.json({ message: `Executed power action ${action} on ${vm.name}`, vm });
});
// 8. Execute ADB Shell Commands
app.post('/api/vms/:id/adb', (req, res) => {
const { id } = req.params;
const { command } = req.body;
const vm = virtualMachines.find((v) => v.id === id);
if (!vm) return res.status(404).json({ error: 'VM not found' });
const cmd = (command || '').trim();
let output = '';
if (cmd.includes('settings get global http_proxy')) {
output = vm.proxy && vm.proxy.enabled ? `${vm.proxy.host}:${vm.proxy.port}` : ':0';
} else if (cmd.includes('settings put global http_proxy')) {
const val = cmd.split('http_proxy')[1]?.trim() || '';
if (val === ':0' || val === 'none' || val === '""') {
if (vm.proxy) vm.proxy.enabled = false;
output = `Global HTTP proxy reset to direct WAN.`;
} else {
const [host, portStr] = val.split(':');
const port = parseInt(portStr || '8080');
vm.proxy = {
enabled: true,
type: 'HTTP',
host: host || '127.0.0.1',
port,
country: 'Configured Proxy',
countryCode: 'US',
externalIp: host,
latencyMs: 45,
};
output = `Global HTTP proxy set to ${host}:${port}`;
}
} else if (cmd.includes('curl ifconfig.me') || cmd.includes('myip') || cmd.includes('ip route')) {
if (vm.proxy && vm.proxy.enabled) {
output = `[Proxy Route Active via ${vm.proxy.type}]\nExit IP: ${vm.proxy.externalIp || vm.proxy.host}\nHost Port: ${vm.proxy.host}:${vm.proxy.port}\nLocation: ${vm.proxy.country || 'Global Proxy'} (${vm.proxy.countryCode || 'US'})\nAnonymity Level: ${vm.proxy.anonymity || 'Elite'}`;
} else {
output = `[Direct WAN Connection]\nPublic IP: ${vm.ipAddress}\nProxy: Disabled (Direct Connection)`;
}
} else if (cmd.startsWith('adb shell getprop') || cmd === 'getprop') {
output = `[ro.build.version.release]: [${vm.androidVersion.split(' ')[0]}]
[ro.build.version.sdk]: [34]
[ro.product.model]: [${vm.profile.name}]
[ro.product.brand]: [${vm.profile.manufacturer}]
[ro.boot.flash.locked]: [${vm.bootloader.isUnlocked ? '0' : '1'}]
[ro.boot.selinux]: [${vm.bootloader.selinuxMode}]
[ro.hardware]: [qcom]
[ro.sf.lcd_density]: [${vm.profile.densityDpi}]
[net.dns1]: [8.8.8.8]`;
} else if (cmd.includes('input tap')) {
const parts = cmd.split('input tap')[1]?.trim().split(/\s+/) || ['0', '0'];
const x = parts[0] || '100';
const y = parts[1] || '200';
output = `[Input Event] Simulated touch tap at (${x}, ${y}) on device screen display_id=0`;
} else if (cmd.includes('input text')) {
const text = cmd.split('input text')[1]?.trim() || '';
output = `[Input Event] Injected IME text string: "${text.replace(/^['"]|['"]$/g, '')}"`;
} else if (cmd.includes('input keyevent')) {
const key = cmd.split('input keyevent')[1]?.trim() || 'HOME';
output = `[Input Event] Injected hardware keyevent: ${key}`;
} else if (cmd.includes('input swipe')) {
output = `[Input Event] Simulated touch drag gesture ${cmd}`;
} else if (cmd.includes('am start')) {
const pkgMatch = cmd.match(/(com\.[a-zA-Z0-0_.]+)/);
const targetPkg = pkgMatch ? pkgMatch[1] : 'com.android.launcher3';
vm.currentAppPackage = targetPkg;
output = `Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] pkg=${targetPkg} }\nStatus: Activity launched successfully on VM display #0`;
} else if (cmd.includes('monkey')) {
const pkgMatch = cmd.match(/-p\s+(com\.[a-zA-Z0-0_.]+)/);
const targetPkg = pkgMatch ? pkgMatch[1] : vm.currentAppPackage;
output = `:Monkey: seed=1723328200 count=100
:AllowPackage: ${targetPkg}
:IncludeCategory: android.intent.category.LAUNCHER
// Event injected: 100 pseudo-random touch/drag/key gestures
// Activity: ${targetPkg} handled 100/100 events with 0 crashes or ANRs.
Events injected: 100
System appear to be: aOK (animator stops, top activity=${targetPkg})`;
} else if (cmd.startsWith('adb install') || cmd.includes('pm install')) {
const apkName = cmd.split('/').pop()?.replace('.apk', '') || 'CustomApp';
const pkgName = `com.custom.${apkName.toLowerCase().replace(/[^a-z0-0]/g, '')}`;
const exists = vm.installedApps.some((a) => a.packageName === pkgName);
if (!exists) {
vm.installedApps.push({
packageName: pkgName,
appName: apkName.toUpperCase(),
version: '1.0.0-release',
iconName: 'Smartphone',
isSystem: false,
sizeMb: 24.5,
});
}
output = `Performing Streamed Install\nSuccess: Package ${pkgName} installed on system storage`;
} else if (cmd.includes('pm list packages') || cmd === 'pm list') {
output = vm.installedApps.map((a) => `package:${a.packageName}`).join('\n');
} else if (cmd.startsWith('su')) {
if (vm.bootloader.rootMethod !== 'none') {
output = `# root@${vm.profile.id}:/# id\nuid=0(root) gid=0(root) groups=0(root) context=u:r:su:s0\nRoot privilege granted via ${vm.bootloader.rootMethod.toUpperCase()}`;
} else {
output = `Permission denied: Root privilege unavailable (Bootloader Root is NONE)`;
}
} else if (cmd.includes('cat /proc/cpuinfo')) {
output = `Processor\t: ARMv8 Processor rev 4 (v8l)
processor\t: 0..${vm.vcpu - 1}
BogoMIPS\t: 38.40
Features\t: fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp
CPU implementer\t: 0x51
CPU architecture: 8
CPU variant\t: 0x2
CPU part\t: 0x805
CPU revision\t: 1
Hardware\t: Hypervisor VirtIO QEMU`;
} else if (cmd.includes('dumpsys battery')) {
output = `Current Battery Service state:
AC powered: false
USB powered: ${vm.isCharging}
Wireless powered: false
level: ${vm.batteryLevel}
scale: 100
voltage: 4210
temperature: 284
technology: Li-ion`;
} else if (cmd.includes('dumpsys activity')) {
output = `ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
Display #0 (activities from top to bottom):
Stack #1: type=standard mode=fullscreen
Task id #12
* ActivityRecord{b4a12c u0 ${vm.currentAppPackage} t12}
running=true visible=true task=Task{b4a12c #12}`;
} else if (cmd.includes('logcat')) {
output = `08-10 18:00:12.102 1024 1024 I ActivityTaskManager: START u0 {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] pkg=${vm.currentAppPackage}}
08-10 18:00:12.145 1024 1240 D SurfaceFlinger: Layer ${vm.currentAppPackage} rendered at 60.0 FPS
08-10 18:00:12.210 512 512 I Magisk : [SU] Shell (uid: 2000) granted superuser permissions`;
} else {
output = `[adb shell @ ${vm.ipAddress}:${vm.adbPort}]\n$ ${cmd}\nCommand executed successfully with status 0.`;
}
res.json({ output, exitCode: 0, executionTimeMs: 38 });
});
// 8b. Execute Programmatic Automation Script Endpoint
app.post('/api/vms/:id/automation/run', (req, res) => {
const { id } = req.params;
const { steps } = req.body; // array of step objects or command strings
const vm = virtualMachines.find((v) => v.id === id);
if (!vm) return res.status(404).json({ error: 'VM not found' });
if (!Array.isArray(steps) || steps.length === 0) {
return res.status(400).json({ error: 'Invalid or empty automation steps array' });
}
const logs: string[] = [];
logs.push(`[Automation Engine] Initialized script execution on VM ${vm.name} (${vm.ipAddress}:${vm.adbPort})`);
steps.forEach((step: any, index: number) => {
const stepNum = index + 1;
if (typeof step === 'string') {
if (step.startsWith('START_APP') || step.startsWith('am start')) {
const pkg = step.split(/\s+/)[1] || 'com.facebook.katana';
vm.currentAppPackage = pkg;
logs.push(`Step ${stepNum}: [AM START] Launched target package -> ${pkg}`);
} else if (step.startsWith('TAP') || step.includes('input tap')) {
logs.push(`Step ${stepNum}: [INPUT TAP] Simulated touch tap at ${step.replace(/TAP|input tap/g, '').trim()}`);
} else if (step.startsWith('TEXT') || step.includes('input text')) {
logs.push(`Step ${stepNum}: [INPUT TEXT] Injected IME text: "${step.replace(/TEXT|input text/g, '').trim()}"`);
} else if (step.startsWith('INSTALL') || step.includes('adb install')) {
const pkg = step.split(/\s+/)[1] || 'com.app.newpackage';
const name = pkg.split('.').pop()?.toUpperCase() || 'NEW APP';
if (!vm.installedApps.some((a) => a.packageName === pkg)) {
vm.installedApps.push({
packageName: pkg,
appName: name,
version: '1.0.0',
iconName: 'Smartphone',
isSystem: false,
sizeMb: 32.0,
});
}
logs.push(`Step ${stepNum}: [PACKAGE MANAGER] Stream installed package -> ${pkg}`);
} else if (step.startsWith('SLEEP')) {
logs.push(`Step ${stepNum}: [SYSTEM DELAY] Paused thread execution for ${step.split(' ')[1] || '1000'}ms`);
} else {
logs.push(`Step ${stepNum}: [ADB COMMAND] Executed: ${step}`);
}
} else if (typeof step === 'object' && step.action) {
if (step.action === 'start_app') {
vm.currentAppPackage = step.package || 'com.facebook.katana';
logs.push(`Step ${stepNum}: [AM START] Launched ${vm.currentAppPackage}`);
} else if (step.action === 'install') {
const pkg = step.package || 'com.custom.app';
const name = step.appName || 'Custom App';
if (!vm.installedApps.some((a) => a.packageName === pkg)) {
vm.installedApps.push({
packageName: pkg,
appName: name,
version: '1.0.0',
iconName: 'Smartphone',
isSystem: false,
sizeMb: 45.0,
});
}
logs.push(`Step ${stepNum}: [INSTALL] Package ${pkg} (${name}) installed successfully`);
} else if (step.action === 'tap') {
logs.push(`Step ${stepNum}: [TAP] Coordinates X:${step.x || 150}, Y:${step.y || 300}`);
} else if (step.action === 'text') {
logs.push(`Step ${stepNum}: [TEXT] Typed: "${step.text || 'Hello'}"`);
} else {
logs.push(`Step ${stepNum}: [ACTION] Executed ${step.action}`);
}
}
});
logs.push(`[Automation Engine] Script finished successfully with 0 errors. All ${steps.length} steps executed.`);
res.json({
status: 'SUCCESS',
executedStepsCount: steps.length,
logs,
currentAppPackage: vm.currentAppPackage,
installedAppsCount: vm.installedApps.length,
});
});
// 9. Fastboot Commands
app.post('/api/vms/:id/fastboot', (req, res) => {
const { id } = req.params;
const { command } = req.body;
const vm = virtualMachines.find((v) => v.id === id);
if (!vm) return res.status(404).json({ error: 'VM not found' });
let output = 'OKAY [ 0.015s]';
if (command === 'fastboot oem unlock' || command === 'fastboot flashing unlock') {
vm.bootloader.isUnlocked = true;
output = `(...) Unlocking bootloader...\nOKAY [ 0.412s]\nBootloader unlocked successfully.`;
} else if (command === 'fastboot devices') {
output = `${vm.id.toUpperCase()}\tfastboot`;
} else if (command.includes('flash boot')) {
output = `sending 'boot' (32768 KB)... OKAY [ 0.812s]\nwriting 'boot'... OKAY [ 1.120s]\nFinished. Total time: 1.932s`;
}
res.json({ output, status: 'OKAY' });
});
// 10. Install APK Endpoint
app.post('/api/vms/:id/install-apk', (req, res) => {
const { id } = req.params;
const { appName, packageName, sizeMb } = req.body;
const vm = virtualMachines.find((v) => v.id === id);
if (!vm) return res.status(404).json({ error: 'VM not found' });
const newApp = {
packageName: packageName || `com.example.${appName.toLowerCase().replace(/\s+/g, '')}`,
appName: appName || 'Custom App',
version: '1.0.0',
iconName: 'Smartphone',
isSystem: false,
sizeMb: Number(sizeMb) || 18.5,
};
vm.installedApps.push(newApp);
res.json({ message: `Successfully installed ${newApp.appName} on ${vm.name}`, installedApp: newApp });
});
// 11. Launch App on VM Screen
app.post('/api/vms/:id/launch-app', (req, res) => {
const { id } = req.params;
const { packageName } = req.body;
const vm = virtualMachines.find((v) => v.id === id);
if (!vm) return res.status(404).json({ error: 'VM not found' });
vm.currentAppPackage = packageName;
res.json({ message: `Launched ${packageName} on ${vm.name}`, currentAppPackage: vm.currentAppPackage });
});
// 12. Proxifly Proxy Pool Endpoint
app.get('/api/proxies/proxifly', (req, res) => {
const { type, country } = req.query;
let list = [...PROXIFLY_PROXIES];
if (type && typeof type === 'string') {
list = list.filter((p) => p.type.toUpperCase() === type.toUpperCase());
}
if (country && typeof country === 'string') {
list = list.filter(
(p) =>
p.country.toLowerCase().includes(country.toLowerCase()) ||
p.countryCode.toLowerCase() === country.toLowerCase()
);
}
res.json({
source: 'Proxifly Developer Hub (https://proxifly.dev/tools/proxy-list)',
total: list.length,
proxies: list,
});
});
// 13. Test Proxy Endpoint
app.post('/api/proxies/test', (req, res) => {
const { host, port, type } = req.body;
if (!host || !port) {
return res.status(400).json({ error: 'Host and port required' });
}
const simulatedPing = Math.floor(25 + Math.random() * 60);
res.json({
status: 'ONLINE',
host,
port: Number(port),
type: type || 'SOCKS5',
latencyMs: simulatedPing,
anonymity: 'Elite',
ipExit: host,
message: `Proxy ${host}:${port} (${type || 'SOCKS5'}) connected successfully with ${simulatedPing}ms latency.`,
});
});
// 14. Assign or Update VM Proxy
app.post('/api/vms/:id/proxy', (req, res) => {
const { id } = req.params;
const { type, host, port, username, password, country, countryCode, anonymity, latencyMs } = req.body;
const vm = virtualMachines.find((v) => v.id === id);
if (!vm) return res.status(404).json({ error: 'VM not found' });
if (!host || !port) {
return res.status(400).json({ error: 'Proxy host and port are required' });
}
vm.proxy = {
id: `px-${Date.now()}`,
enabled: true,
type: type || 'SOCKS5',
host,
port: Number(port),
username,
password,
country: country || 'United States',
countryCode: countryCode || 'US',
anonymity: anonymity || 'Elite',
latencyMs: latencyMs || 42,
externalIp: host,
lastChecked: new Date().toISOString(),
};
res.json({
message: `Proxy ${vm.proxy.type}://${vm.proxy.host}:${vm.proxy.port} assigned to ${vm.name}`,
vm,
});
});
// 15. Delete / Remove VM Proxy
app.delete('/api/vms/:id/proxy', (req, res) => {
const { id } = req.params;
const vm = virtualMachines.find((v) => v.id === id);
if (!vm) return res.status(404).json({ error: 'VM not found' });
vm.proxy = undefined;
res.json({ message: `Proxy removed from ${vm.name}`, vm });
});
// 16. Auto-Assign Unique Proxies to All VMs
app.post('/api/vms/assign-proxies-auto', (req, res) => {
if (virtualMachines.length === 0) {
return res.status(400).json({ error: 'No active VMs found to assign proxies' });
}
const assignments: { vmName: string; proxy: string; country: string }[] = [];
virtualMachines.forEach((vm, index) => {
const proxyData = PROXIFLY_PROXIES[index % PROXIFLY_PROXIES.length];
vm.proxy = {
...proxyData,
enabled: true,
lastChecked: new Date().toISOString(),
};
assignments.push({
vmName: vm.name,
proxy: `${vm.proxy.type}://${vm.proxy.host}:${vm.proxy.port}`,
country: `${vm.proxy.country} (${vm.proxy.countryCode})`,
});
});
res.json({
message: `Successfully assigned unique Proxifly proxies to all ${virtualMachines.length} active VMs.`,
assignments,
virtualMachines,
});
});
// ==========================================
// API KEYS MANAGEMENT
// ==========================================
let apiKeys: { id: string; key: string; name: string; createdAt: string; lastUsedAt?: string; requestCount: number; permissions: 'full_control' | 'read_only' }[] = [
{
id: 'key-master-01',
key: 'sk_proxifly_live_mcp_master_key_8842',
name: 'Claude Desktop & AI Agent Master Key',
createdAt: new Date(Date.now() - 7 * 24 * 3600 * 1000).toISOString(),
lastUsedAt: new Date().toISOString(),
requestCount: 142,
permissions: 'full_control',
},
];
app.get('/api/keys', (req, res) => {
res.json({ keys: apiKeys });
});
app.post('/api/keys', (req, res) => {
const { name, permissions } = req.body;
const newKey = {
id: `key-${Date.now()}`,
key: `sk_proxifly_live_${Math.random().toString(36).substring(2, 12)}_${Math.random().toString(36).substring(2, 10)}`,
name: name || 'New AI Agent Key',
createdAt: new Date().toISOString(),
requestCount: 0,
permissions: permissions || 'full_control',
};
apiKeys.unshift(newKey);
res.json({ message: 'API key created successfully', apiKey: newKey });
});
app.delete('/api/keys/:id', (req, res) => {
const { id } = req.params;
apiKeys = apiKeys.filter((k) => k.id !== id);
res.json({ message: 'API key revoked' });
});
// ==========================================
// OPENAPI 3.0 SPECIFICATION
// ==========================================
app.get('/api/openapi.json', (req, res) => {
res.json({
openapi: '3.0.3',
info: {
title: 'Proxifly Android VM Cloud & MCP Control API',
version: '1.0.0',
description: 'Programmatic REST API & Model Context Protocol (MCP) Server to provision, manage, automate, and route Android Virtual Machines.',
},
servers: [{ url: '/api', description: 'Local Hypervisor Server' }],
paths: {
'/vms': {
get: { summary: 'List all active Android Virtual Machines', responses: { '200': { description: 'Success' } } },
post: { summary: 'Provision new Android VM instance', responses: { '200': { description: 'Success' } } },
},
'/vms/{id}/adb': {
post: { summary: 'Execute ADB shell command on VM', responses: { '200': { description: 'Success' } } },
},
'/vms/{id}/proxy': {
post: { summary: 'Assign Proxifly residential/datacenter proxy to VM', responses: { '200': { description: 'Success' } } },
delete: { summary: 'Remove proxy from VM', responses: { '200': { description: 'Success' } } },
},
'/mcp': {
post: { summary: 'MCP JSON-RPC 2.0 Server Protocol Endpoint for AI Agents', responses: { '200': { description: 'Success' } } },
},
},
});
});
// ==========================================
// MODEL CONTEXT PROTOCOL (MCP) SERVER ENGINE
// ==========================================
const MCP_TOOLS_DEFINITIONS = [
{
name: 'list_vms',
description: 'List all active Android Virtual Machines in the hypervisor, including state, IP, ADB ports, hardware profile, and assigned proxy.',
inputSchema: {
type: 'object',
properties: {},
},
},
{
name: 'create_vm',
description: 'Provision and launch a new Android Virtual Machine instance.',
inputSchema: {
type: 'object',
properties: {
name: { type: 'string', description: 'Name label for the VM instance' },
androidVersion: { type: 'string', description: 'Android OS Version (e.g. "14 (UpsideDownCake)", "13 (Tiramisu)", "11 (RedVelvetCake)")' },
profileId: { type: 'string', description: 'Hardware profile ID ("pixel-8-pro", "galaxy-s24-ultra", "oneplus-12", "aosp-tablet-10")' },
ramGb: { type: 'number', description: 'RAM size in GB (e.g. 4, 8, 12)' },
vcpu: { type: 'number', description: 'vCPU cores count (e.g. 2, 4, 8)' },
},
required: ['name'],
},
},
{
name: 'power_vm',
description: 'Change the power state of an Android VM (start, stop, reboot, recovery).',
inputSchema: {
type: 'object',
properties: {
vmId: { type: 'string', description: 'The ID of target Android VM (e.g. "vm-cloud-001")' },
action: { type: 'string', enum: ['start', 'stop', 'reboot', 'recovery'], description: 'Power action to execute' },
},
required: ['vmId', 'action'],
},
},
{
name: 'execute_adb_command',
description: 'Execute an arbitrary ADB shell command or input event on a target VM (e.g., "adb shell input tap 300 500", "adb shell input text hello", "adb shell dumpsys battery").',
inputSchema: {
type: 'object',
properties: {
vmId: { type: 'string', description: 'Target VM ID' },
command: { type: 'string', description: 'ADB command to execute (e.g. "input tap 500 800" or "getprop")' },
},
required: ['vmId', 'command'],
},
},
{
name: 'install_apk',
description: 'Sideload and install an APK application package on a specific Android VM.',
inputSchema: {
type: 'object',
properties: {
vmId: { type: 'string', description: 'Target VM ID' },
appName: { type: 'string', description: 'Human readable app name' },
packageName: { type: 'string', description: 'Android package name (e.g. "com.facebook.katana")' },
},
required: ['vmId', 'packageName'],
},
},
{
name: 'launch_app',
description: 'Launch an installed Android application package on target VM.',
inputSchema: {
type: 'object',
properties: {
vmId: { type: 'string', description: 'Target VM ID' },
packageName: { type: 'string', description: 'Package name to open (e.g. "com.whatsapp")' },
},
required: ['vmId', 'packageName'],
},
},
{
name: 'assign_proxy',
description: 'Assign a residential or datacenter HTTP/SOCKS5 proxy from Proxifly to route a target VM network traffic.',
inputSchema: {
type: 'object',
properties: {
vmId: { type: 'string', description: 'Target VM ID' },
type: { type: 'string', enum: ['HTTP', 'HTTPS', 'SOCKS4', 'SOCKS5'], description: 'Proxy Protocol' },
host: { type: 'string', description: 'Proxy IP or hostname' },
port: { type: 'number', description: 'Proxy port number' },
country: { type: 'string', description: 'Country location' },
},
required: ['vmId', 'host', 'port'],
},
},
{
name: 'run_automation_script',
description: 'Execute a multi-step macro automation workflow script (tap, swipe, delay, text input) on a VM.',
inputSchema: {
type: 'object',
properties: {
vmId: { type: 'string', description: 'Target VM ID' },
steps: {
type: 'array',
items: {
type: 'object',
properties: {
type: { type: 'string', enum: ['tap', 'swipe', 'delay', 'typeText', 'launchApp', 'keyEvent'] },
x: { type: 'number' },
y: { type: 'number' },
text: { type: 'string' },
durationMs: { type: 'number' },
packageName: { type: 'string' },
},
required: ['type'],
},
},
},
required: ['vmId', 'steps'],
},
},
{
name: 'get_vm_screenshot',
description: 'Capture current screenshot state and UI logcat output from target VM.',
inputSchema: {
type: 'object',
properties: {
vmId: { type: 'string', description: 'Target VM ID' },
},
required: ['vmId'],
},
},
{
name: 'instagram_orchestration',
description: 'Perform automated social orchestration actions on Instagram (comment on posts, send direct messages, like content, or verify Google account auth) on target VM.',
inputSchema: {
type: 'object',
properties: {
vmId: { type: 'string', description: 'Target Android VM ID' },
action: { type: 'string', enum: ['comment', 'send_dm', 'like_post', 'verify_google_account'], description: 'Instagram orchestration action' },
postId: { type: 'string', description: 'Post ID for comments or likes' },
commentText: { type: 'string', description: 'Comment text to publish' },
targetUsername: { type: 'string', description: 'Target user handle for direct messages' },
messageText: { type: 'string', description: 'DM text content' },
googleEmail: { type: 'string', description: 'Google account email for 2FA verification' },
},
required: ['vmId', 'action'],
},
},
];
// Helper to process MCP Tool Calls
async function handleMcpToolCall(toolName: string, args: any) {
switch (toolName) {
case 'list_vms':
return {
total: virtualMachines.length,
vms: virtualMachines.map((v) => ({
id: v.id,
name: v.name,
status: v.status,
androidVersion: v.androidVersion,
ipAddress: v.ipAddress,
adbPort: v.adbPort,
currentAppPackage: v.currentAppPackage,
proxy: v.proxy ? `${v.proxy.type}://${v.proxy.host}:${v.proxy.port}` : 'None (Direct)',
batteryLevel: v.batteryLevel,
})),
};
case 'create_vm': {
const { name, androidVersion, profileId, ramGb, vcpu } = args;
const profile = (HardwareProfiles as any)[profileId] || HardwareProfiles.PIXEL_8_PRO;
const newVm: AndroidVM = {
id: `vm-cloud-${Math.floor(100 + Math.random() * 900)}`,
name: name || 'New AI Managed VM',
androidVersion: (androidVersion as AndroidVersion) || '14 (UpsideDownCake)',
arch: 'x86_64',
profile,
ramGb: Number(ramGb) || 8,
vcpu: Number(vcpu) || 4,
storageGb: 64,
bootloader: {
isUnlocked: true,
rootMethod: 'magisk',
customRecovery: true,
selinuxMode: 'permissive',
kernelCmdline: 'console=ttyMSM0,115200 androidboot.hardware=qcom androidboot.selinux=permissive',
gpuAcceleration: 'swiftshader',
},
status: 'running',
ipAddress: `192.168.122.${Math.floor(10 + Math.random() * 200)}`,
adbPort: 5555,
vncPort: 5901,
batteryLevel: 100,
isCharging: true,
orientation: 'portrait',
location: { latitude: 37.7749, longitude: -122.4194, addressName: 'San Francisco, CA' },
metrics: { cpuUsagePct: 12, ramUsageMb: 1840, totalRamMb: 8192, fps: 60, networkRxKbps: 45, networkTxKbps: 18, uptimeSeconds: 10 },
installedApps: [...DEFAULT_ANDROID_APPS],
currentAppPackage: 'com.android.launcher3',
createdAt: new Date().toISOString(),
snapshotCount: 0,
};
virtualMachines.push(newVm);
syncActiveVmCount();
return { message: `VM ${newVm.name} created successfully`, vm: newVm };
}
case 'power_vm': {
const { vmId, action } = args;
const vm = virtualMachines.find((v) => v.id === vmId);
if (!vm) throw new Error(`VM ${vmId} not found`);
if (action === 'stop') vm.status = 'stopped';
else if (action === 'start') vm.status = 'running';
else if (action === 'reboot') vm.status = 'booting';
else if (action === 'recovery') vm.status = 'recovery';
return { message: `VM ${vm.name} power action executed: ${action}`, status: vm.status };
}
case 'execute_adb_command': {
const { vmId, command } = args;
const vm = virtualMachines.find((v) => v.id === vmId);
if (!vm) throw new Error(`VM ${vmId} not found`);
const cmd = (command || '').trim();
let output = `Executed ADB command: ${cmd}\n`;
if (cmd.includes('tap')) {
output += `[Input Event] Injected touch tap event on display layer.`;
} else if (cmd.includes('text')) {
output += `[Input Event] Injected keyboard text buffer into active focus field.`;
} else {
output += `Exit Code: 0 (OKAY)`;
}
return { vmId, command: cmd, output, exitCode: 0 };
}
case 'install_apk': {
const { vmId, appName, packageName } = args;
const vm = virtualMachines.find((v) => v.id === vmId);
if (!vm) throw new Error(`VM ${vmId} not found`);
const cleanPkg = packageName || 'com.example.app';
const cleanName = appName || cleanPkg.split('.').pop() || 'App';
if (!vm.installedApps.find((a) => a.packageName === cleanPkg)) {
vm.installedApps.push({
packageName: cleanPkg,
appName: cleanName,
version: '1.0.0',
iconName: 'Smartphone',
isSystem: false,
sizeMb: 42,
});
}
vm.currentAppPackage = cleanPkg;
return { message: `Successfully installed ${cleanName} (${cleanPkg}) on ${vm.name}`, installedAppsCount: vm.installedApps.length };
}
case 'launch_app': {
const { vmId, packageName } = args;
const vm = virtualMachines.find((v) => v.id === vmId);
if (!vm) throw new Error(`VM ${vmId} not found`);
vm.currentAppPackage = packageName;
return { message: `Launched ${packageName} on ${vm.name}`, currentAppPackage: vm.currentAppPackage };
}
case 'assign_proxy': {
const { vmId, type, host, port, country } = args;
const vm = virtualMachines.find((v) => v.id === vmId);
if (!vm) throw new Error(`VM ${vmId} not found`);
vm.proxy = {
id: `px-mcp-${Date.now()}`,
enabled: true,
type: (type as ProxyType) || 'SOCKS5',
host,
port: Number(port),
country: country || 'United States',
countryCode: 'US',
anonymity: 'Elite',
latencyMs: 38,
externalIp: host,
lastChecked: new Date().toISOString(),
};
return { message: `Assigned proxy ${vm.proxy.type}://${vm.proxy.host}:${vm.proxy.port} to ${vm.name}`, vmProxy: vm.proxy };
}
case 'run_automation_script': {
const { vmId, steps } = args;
const vm = virtualMachines.find((v) => v.id === vmId);
if (!vm) throw new Error(`VM ${vmId} not found`);
const logs: string[] = [];
for (let i = 0; i < (steps || []).length; i++) {
const step = steps[i];
if (step.type === 'tap') logs.push(`Step ${i + 1}: Tap at (${step.x}, ${step.y})`);
else if (step.type === 'typeText') logs.push(`Step ${i + 1}: Typed text "${step.text}"`);
else if (step.type === 'launchApp') {
vm.currentAppPackage = step.packageName || vm.currentAppPackage;
logs.push(`Step ${i + 1}: Launched ${step.packageName}`);
} else logs.push(`Step ${i + 1}: Executed ${step.type}`);
}
return { message: `Executed automation sequence (${(steps || []).length} steps) on ${vm.name}`, logs };
}
case 'get_vm_screenshot': {
const { vmId } = args;
const vm = virtualMachines.find((v) => v.id === vmId);
if (!vm) throw new Error(`VM ${vmId} not found`);
return {
vmId: vm.id,
vmName: vm.name,
currentAppPackage: vm.currentAppPackage,
status: vm.status,
timestamp: new Date().toISOString(),
screenshotCaptured: true,
resolution: vm.profile.screenResolution,
};
}
case 'instagram_orchestration': {
const { vmId, action, postId, commentText, targetUsername, messageText, googleEmail } = args;
const vm = virtualMachines.find((v) => v.id === vmId);
if (!vm) throw new Error(`VM ${vmId} not found`);
if (action === 'comment') {
return {
status: 'success',
vmId: vm.id,
action: 'comment',
postId: postId || 'ig-1',
commentText,
publishedAt: new Date().toISOString(),
proxyRoute: vm.proxy ? `${vm.proxy.type}://${vm.proxy.host}` : 'Direct',
message: `Successfully posted comment on Instagram post ${postId || 'ig-1'}: "${commentText}"`,
};
} else if (action === 'send_dm') {
return {
status: 'success',
vmId: vm.id,
action: 'send_dm',
targetUsername: targetUsername || '@android_dev_official',
messageText,
deliveredAt: new Date().toISOString(),
message: `Direct message sent to ${targetUsername || '@android_dev_official'}: "${messageText}"`,
};
} else if (action === 'like_post') {
return {
status: 'success',
vmId: vm.id,
action: 'like_post',
postId: postId || 'ig-1',
message: `Liked Instagram post ${postId || 'ig-1'}`,
};
} else if (action === 'verify_google_account') {
return {
status: 'success',
vmId: vm.id,
action: 'verify_google_account',
googleEmail: googleEmail || 'alex.dev.cloud@gmail.com',
verificationStatus: 'verified_2fa_code_passed',
codeReceived: '482910',
message: `Google Account ${googleEmail || 'alex.dev.cloud@gmail.com'} successfully authenticated with 2FA email verification code.`,
};
}
return { status: 'executed', action };
}
default:
throw new Error(`Unknown tool: ${toolName}`);
}
}
// MCP JSON-RPC 2.0 Handler
app.post('/api/mcp', async (req, res) => {
const { jsonrpc, id, method, params } = req.body || {};
try {
if (method === 'initialize') {
return res.json({
jsonrpc: '2.0',
id: id || 1,
result: {
protocolVersion: '2024-11-05',
capabilities: {
tools: {
listChanged: true,
},
},
serverInfo: {
name: 'proxifly-android-mcp-server',
version: '1.0.0',
},
},
});
}
if (method === 'tools/list') {
return res.json({
jsonrpc: '2.0',
id: id || 1,
result: {
tools: MCP_TOOLS_DEFINITIONS,
},
});
}
if (method === 'tools/call') {
const { name, arguments: toolArgs } = params || {};
const resultData = await handleMcpToolCall(name, toolArgs || {});
return res.json({
jsonrpc: '2.0',
id: id || 1,
result: {
content: [
{
type: 'text',
text: JSON.stringify(resultData, null, 2),
},
],
},
});
}
return res.status(400).json({
jsonrpc: '2.0',
id: id || 1,
error: {
code: -32601,
message: `Method not found: ${method}`,
},
});
} catch (err: any) {
return res.json({
jsonrpc: '2.0',
id: id || 1,
error: {
code: -32603,
message: err?.message || 'Internal MCP tool execution error',
},
});
}
});
// SSE Stream for MCP Client Agents
app.get('/api/mcp/sse', (req, res) => {
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');
res.write(`event: endpoint\ndata: /api/mcp\n\n`);
const keepAliveInterval = setInterval(() => {
res.write(`: keepalive\n\n`);
}, 15000);
req.on('close', () => {
clearInterval(keepAliveInterval);
});
});
// Start Express Server with Vite Middleware
async function startServer() {
if (process.env.NODE_ENV !== 'production') {
const vite = await createViteServer({
server: { middlewareMode: true },
appType: 'spa',
});
app.use(vite.middlewares);
} else {
app.use(express.static(path.resolve(__dirname, 'dist')));
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'dist', 'index.html'));
});
}
app.listen(PORT, '0.0.0.0', () => {
console.log(`Android Cloud Hypervisor Server running on http://0.0.0.0:${PORT}`);
});
}
startServer();