Skip to main content
Glama

android_screenshot

Capture screenshots from Android devices or emulators to save locally for debugging, testing, or documentation purposes.

Instructions

Capture screenshot from Android device or emulator

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
serialYesDevice serial number (use android_devices_list to get available devices)
outputPathYesLocal path where screenshot will be saved (e.g., ./screenshot.png)
optionsNo

Implementation Reference

  • The handler function that implements the core logic for capturing Android screenshots using ADB screencap command, pulling the file locally, cleaning up temp files, and handling errors.
    handler: async (args: any) => { const parsed = AndroidScreenshotSchema.parse(args); try { // Ensure output directory exists const outputDir = path.dirname(parsed.outputPath); await fs.mkdir(outputDir, { recursive: true }); const adbArgs = ['-s', parsed.serial, 'exec-out', 'screencap']; if (parsed.options?.format === 'png') { adbArgs.push('-p'); // PNG format } if (parsed.options?.display !== undefined) { adbArgs.push('-d', parsed.options.display.toString()); } // Capture screenshot to temporary location first const tempPath = `/sdcard/screenshot_${Date.now()}.png`; const captureResult = await processExecutor.execute('adb', [ '-s', parsed.serial, 'shell', 'screencap', '-p', tempPath ], { timeout: 30000, }); if (captureResult.exitCode !== 0) { return { success: false, error: { code: 'SCREENSHOT_CAPTURE_FAILED', message: 'Failed to capture screenshot on device', details: captureResult.stderr } }; } // Pull screenshot to local machine const pullResult = await processExecutor.execute('adb', [ '-s', parsed.serial, 'pull', tempPath, parsed.outputPath ], { timeout: 30000, }); // Clean up temporary file await processExecutor.execute('adb', [ '-s', parsed.serial, 'shell', 'rm', tempPath ], { timeout: 10000, }); if (pullResult.exitCode === 0) { // Verify file was created let fileStats; try { fileStats = await fs.stat(parsed.outputPath); } catch { throw new Error(`Screenshot file was not created at ${parsed.outputPath}`); } return { success: true, data: { screenshotPath: parsed.outputPath, fileSize: fileStats.size, format: parsed.options?.format || 'png', device: parsed.serial, timestamp: new Date().toISOString() } }; } else { return { success: false, error: { code: 'SCREENSHOT_PULL_FAILED', message: 'Failed to pull screenshot from device', details: pullResult.stderr } }; } } catch (error: any) { return { success: false, error: { code: 'SCREENSHOT_ERROR', message: error.message, details: error } }; } }
  • Zod schema used for input validation and parsing within the android_screenshot handler.
    * Zod validation schema for android_screenshot tool. * * @type {z.ZodObject} */ const AndroidScreenshotSchema = z.object({ serial: z.string().min(1), outputPath: z.string().min(1), options: z.object({ format: z.enum(['png', 'raw']).default('png'), display: z.number().optional(), }).optional(), });
  • Tool registration in the Map, defining name, description, JSON inputSchema, and reference to the handler function.
    tools.set('android_screenshot', { name: 'android_screenshot', description: 'Capture screenshot from Android device or emulator', inputSchema: { type: 'object', properties: { serial: { type: 'string', description: 'Device serial number (use android_devices_list to get available devices)' }, outputPath: { type: 'string', description: 'Local path where screenshot will be saved (e.g., ./screenshot.png)' }, options: { type: 'object', properties: { format: { type: 'string', enum: ['png', 'raw'], description: 'Screenshot format', default: 'png' }, display: { type: 'number', description: 'Display ID for multi-display devices' } } } }, required: ['serial', 'outputPath'] }, handler: async (args: any) => { const parsed = AndroidScreenshotSchema.parse(args); try { // Ensure output directory exists const outputDir = path.dirname(parsed.outputPath); await fs.mkdir(outputDir, { recursive: true }); const adbArgs = ['-s', parsed.serial, 'exec-out', 'screencap']; if (parsed.options?.format === 'png') { adbArgs.push('-p'); // PNG format } if (parsed.options?.display !== undefined) { adbArgs.push('-d', parsed.options.display.toString()); } // Capture screenshot to temporary location first const tempPath = `/sdcard/screenshot_${Date.now()}.png`; const captureResult = await processExecutor.execute('adb', [ '-s', parsed.serial, 'shell', 'screencap', '-p', tempPath ], { timeout: 30000, }); if (captureResult.exitCode !== 0) { return { success: false, error: { code: 'SCREENSHOT_CAPTURE_FAILED', message: 'Failed to capture screenshot on device', details: captureResult.stderr } }; } // Pull screenshot to local machine const pullResult = await processExecutor.execute('adb', [ '-s', parsed.serial, 'pull', tempPath, parsed.outputPath ], { timeout: 30000, }); // Clean up temporary file await processExecutor.execute('adb', [ '-s', parsed.serial, 'shell', 'rm', tempPath ], { timeout: 10000, }); if (pullResult.exitCode === 0) { // Verify file was created let fileStats; try { fileStats = await fs.stat(parsed.outputPath); } catch { throw new Error(`Screenshot file was not created at ${parsed.outputPath}`); } return { success: true, data: { screenshotPath: parsed.outputPath, fileSize: fileStats.size, format: parsed.options?.format || 'png', device: parsed.serial, timestamp: new Date().toISOString() } }; } else { return { success: false, error: { code: 'SCREENSHOT_PULL_FAILED', message: 'Failed to pull screenshot from device', details: pullResult.stderr } }; } } catch (error: any) { return { success: false, error: { code: 'SCREENSHOT_ERROR', message: error.message, details: error } }; } } });

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

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