Skip to main content
Glama
mobile-next

Mobile Next MCP Server

Official
by mobile-next
mobilecli.ts3.77 kB
import { existsSync } from "node:fs"; import { dirname, join, sep } from "node:path"; import { execFileSync } from "node:child_process"; export interface MobilecliDevicesOptions { includeOffline?: boolean; platform?: "ios" | "android"; type?: "real" | "emulator" | "simulator"; } export interface MobilecliDevicesResponse { status: "ok"; data: { devices: Array<{ id: string; name: string; platform: "android" | "ios"; type: "real" | "emulator" | "simulator"; version: string; }>; }; } const TIMEOUT = 30000; const MAX_BUFFER_SIZE = 1024 * 1024 * 4; export class Mobilecli { private path: string | null = null; constructor() { } private getPath(): string { if (!this.path) { this.path = Mobilecli.getMobilecliPath(); } return this.path; } public executeCommand(args: string[]): string { const path = this.getPath(); return execFileSync(path, args, { encoding: "utf8" }).toString().trim(); } public executeCommandBuffer(args: string[]): Buffer { const path = this.getPath(); return execFileSync(path, args, { encoding: "buffer", maxBuffer: MAX_BUFFER_SIZE, timeout: TIMEOUT, }) as Buffer; } private static getMobilecliPath(): string { if (process.env.MOBILECLI_PATH) { return process.env.MOBILECLI_PATH; } const platform = process.platform; const arch = process.arch; const normalizedPlatform = platform === "win32" ? "windows" : platform; const normalizedArch = arch === "arm64" ? "arm64" : "amd64"; const ext = platform === "win32" ? ".exe" : ""; const binaryName = `mobilecli-${normalizedPlatform}-${normalizedArch}${ext}`; // Check if mobile-mcp is installed as a package const currentPath = __filename; const pathParts = currentPath.split(sep); const lastNodeModulesIndex = pathParts.lastIndexOf("node_modules"); if (lastNodeModulesIndex !== -1) { // We're inside node_modules, go to the last node_modules in the path const nodeModulesParts = pathParts.slice(0, lastNodeModulesIndex + 1); const lastNodeModulesPath = nodeModulesParts.join(sep); const mobilecliPath = join(lastNodeModulesPath, "@mobilenext", "mobilecli", "bin", binaryName); if (existsSync(mobilecliPath)) { return mobilecliPath; } } // Not in node_modules, look one directory up from current script const scriptDir = dirname(__filename); const parentDir = dirname(scriptDir); const mobilecliPath = join(parentDir, "node_modules", "@mobilenext", "mobilecli", "bin", binaryName); if (existsSync(mobilecliPath)) { return mobilecliPath; } throw new Error(`Could not find mobilecli binary for platform: ${platform}`); } getVersion(): string { try { const output = this.executeCommand(["--version"]); if (output.startsWith("mobilecli version ")) { return output.substring("mobilecli version ".length); } return "failed"; } catch (error: any) { return "failed " + error.message; } } getDevices(options?: MobilecliDevicesOptions): MobilecliDevicesResponse { const args = ["devices"]; if (options) { if (options.includeOffline) { args.push("--include-offline"); } if (options.platform) { if (options.platform !== "ios" && options.platform !== "android") { throw new Error(`Invalid platform: ${options.platform}. Must be "ios" or "android"`); } args.push("--platform", options.platform); } if (options.type) { if (options.type !== "real" && options.type !== "emulator" && options.type !== "simulator") { throw new Error(`Invalid type: ${options.type}. Must be "real", "emulator", or "simulator"`); } args.push("--type", options.type); } } const mobilecliOutput = this.executeCommand(args); return JSON.parse(mobilecliOutput) as MobilecliDevicesResponse; } }

Latest Blog Posts

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/mobile-next/mobile-mcp'

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