Skip to main content
Glama
deviceTools.ts5.69 kB
import { z } from "zod"; import { ToolRegistry, ProgressCallback } from "./toolRegistry"; import { DeviceUtils } from "../utils/deviceUtils"; import { createJSONToolResponse } from "../utils/toolUtils"; import { ActionableError, BootedDevice, DeviceInfo, SomePlatform } from "../models"; // Schema definitions export const listDeviceImagesSchema = z.object({ platform: z.enum(["android", "ios"]).describe("Target platform") }); export const listDevicesSchema = z.object({ platform: z.enum(["android", "ios"]).describe("Target platform") }); export const startDeviceSchema = z.object({ localDevice: z.object({ name: z.string().describe("The device name to start"), deviceId: z.string().optional().describe("The device ID") }), platform: z.enum(["android", "ios"]).describe("Target platform") }); export const killDeviceSchema = z.object({ device: z.object({ name: z.string().describe("The device image name to kill"), deviceId: z.string().describe("The device unique ID"), platform: z.enum(["android", "ios"]).describe("Target platform") }) }); // Export interfaces for type safety export interface startDeviceArgs { device: DeviceInfo; timeoutMs?: number; } export interface KillDeviceArgs { device: BootedDevice; } export interface ListDevicesArgs { platform: SomePlatform; } export interface listDeviceImagesArgs { platform: SomePlatform; } export function registerDeviceTools() { // List all connected devices (physical and emulators) handler const listBootedDevicesHandler = async (args: ListDevicesArgs) => { try { const deviceUtils = new DeviceUtils(); const bootedDevices = await deviceUtils.getBootedDevices(args.platform); // Categorize devices by type const devices = bootedDevices.map(device => { // For Android: emulator devices have deviceId starting with "emulator-" // For iOS: simulator devices typically have deviceId as UUID format or contain "simulator" const isVirtual = args.platform === "android" ? device.deviceId.startsWith("emulator-") : device.deviceId.includes("-") && device.deviceId.length > 30; // iOS simulators typically have long UUID-like IDs return { ...device, isVirtual }; }); const virtualCount = devices.filter(d => d.isVirtual).length; const physicalCount = devices.filter(d => !d.isVirtual).length; return createJSONToolResponse({ message: `Found ${devices.length} connected ${args.platform} devices`, devices: devices, totalCount: devices.length, virtualCount: virtualCount, physicalCount: physicalCount, platform: args.platform }); } catch (error) { throw new ActionableError(`Failed to list ${args.platform} devices: ${error}`); } }; // List AVDs handler const listDeviceImagesHandler = async (args: listDeviceImagesArgs) => { try { const deviceUtils = new DeviceUtils(); const imageList = await deviceUtils.listDeviceImages(args.platform); return createJSONToolResponse({ message: `Found ${imageList.length} available ${args.platform} AVDs`, images: imageList, count: imageList.length, platform: args.platform }); } catch (error) { throw new ActionableError(`Failed to list ${args.platform} AVDs: ${error}`); } }; // Start emulator handler const startDeviceHandler = async (args: startDeviceArgs, progress?: ProgressCallback) => { try { const deviceUtils = new DeviceUtils(); const childProcess = await deviceUtils.startDevice(args.device); if (progress) { await progress(60, 100, "Device started, waiting for readiness..."); } // Wait for device to be ready const readyDevice = await deviceUtils.waitForDeviceReady(args.device, args.timeoutMs); if (progress) { await progress(100, 100, "Device is ready for use"); } return createJSONToolResponse({ message: `${args.device.platform} '${args.device.name}' started and is ready`, name: readyDevice.name, processId: childProcess.pid, isReady: true, deviceId: readyDevice.deviceId, source: args.device.source, platform: args.device.platform }); } catch (error) { throw new ActionableError(`Failed to start ${args.device.platform} device: ${error}`); } }; const killDeviceHandler = async (args: KillDeviceArgs) => { try { const deviceUtils = new DeviceUtils(); await deviceUtils.killDevice(args.device); return createJSONToolResponse({ message: `${args.device.platform} '${args.device.name}' shutdown successfully`, udid: args.device.name, name: args.device.name, platform: args.device.platform }); } catch (error) { throw new ActionableError(`Failed to kill ${args.device.platform} device: ${error}`); } }; // Register with the tool registry ToolRegistry.register( "listDevices", "List all connected devices (both physical and virtual devices)", listDevicesSchema, listBootedDevicesHandler ); ToolRegistry.register( "listDeviceImages", "List all available device images for the specified platform", listDeviceImagesSchema, listDeviceImagesHandler ); ToolRegistry.register( "startDevice", "Start a device with the specified device image", startDeviceSchema, startDeviceHandler, true // Supports progress notifications ); ToolRegistry.register( "killDevice", "Kill a running device", killDeviceSchema, killDeviceHandler ); }

Implementation Reference

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/zillow/auto-mobile'

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