inspect_ui
Capture and analyze Android device UI hierarchy to identify elements, extract layout details, and enable automated testing or debugging of mobile applications.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| device | No | Specific device ID (optional) | |
| outputPath | No | Custom output path on device (default: /sdcard/window_dump.xml) | |
| asBase64 | No | Return XML content as base64 (default: false) |
Implementation Reference
- src/index.ts:424-473 (handler)The core handler function implementing the inspect_ui tool. Dumps current UI hierarchy using ADB uiautomator dump, pulls the XML to local temp file, returns as base64 or plain text, with proper cleanup and error handling.async (args: z.infer<typeof AdbUidumpSchema>, _extra: RequestHandlerExtra) => { log(LogLevel.INFO, "Dumping UI hierarchy"); const deviceArgs = buildDeviceArgs(args.device); const tempFilePath = createTempFilePath("adb-mcp", "window_dump.xml"); const remotePath = args.outputPath && args.outputPath.trim() ? args.outputPath.trim() : "/sdcard/window_dump.xml"; try { // Dump UI hierarchy on device await runAdb([...deviceArgs, "shell", "uiautomator", "dump", remotePath]); // Pull the UI dump from the device await runAdb([...deviceArgs, "pull", remotePath, tempFilePath]); // Clean up the remote file await runAdb([...deviceArgs, "shell", "rm", remotePath]); // Return the UI dump if (args.asBase64 !== false) { // Return as base64 (default) const xmlData = await readFilePromise(tempFilePath); const base64Xml = xmlData.toString('base64'); log(LogLevel.INFO, "UI hierarchy dumped successfully as base64"); return { content: [{ type: "text" as const, text: base64Xml }] }; } else { // Return as plain text const xmlData = await readFilePromise(tempFilePath, 'utf8'); log(LogLevel.INFO, "UI hierarchy dumped successfully as plain text"); return { content: [{ type: "text" as const, text: xmlData }] }; } } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); log(LogLevel.ERROR, `Error dumping UI hierarchy: ${errorMsg}`); return { content: [{ type: "text" as const, text: `Error dumping UI hierarchy: ${errorMsg}` }], isError: true }; } finally { // Clean up the temporary file await cleanupTempFile(tempFilePath); } },
- src/index.ts:421-475 (registration)The MCP server.tool registration for the inspect_ui tool, specifying name, input schema shape, handler function, and description.server.tool( "inspect_ui", AdbUidumpSchema.shape, async (args: z.infer<typeof AdbUidumpSchema>, _extra: RequestHandlerExtra) => { log(LogLevel.INFO, "Dumping UI hierarchy"); const deviceArgs = buildDeviceArgs(args.device); const tempFilePath = createTempFilePath("adb-mcp", "window_dump.xml"); const remotePath = args.outputPath && args.outputPath.trim() ? args.outputPath.trim() : "/sdcard/window_dump.xml"; try { // Dump UI hierarchy on device await runAdb([...deviceArgs, "shell", "uiautomator", "dump", remotePath]); // Pull the UI dump from the device await runAdb([...deviceArgs, "pull", remotePath, tempFilePath]); // Clean up the remote file await runAdb([...deviceArgs, "shell", "rm", remotePath]); // Return the UI dump if (args.asBase64 !== false) { // Return as base64 (default) const xmlData = await readFilePromise(tempFilePath); const base64Xml = xmlData.toString('base64'); log(LogLevel.INFO, "UI hierarchy dumped successfully as base64"); return { content: [{ type: "text" as const, text: base64Xml }] }; } else { // Return as plain text const xmlData = await readFilePromise(tempFilePath, 'utf8'); log(LogLevel.INFO, "UI hierarchy dumped successfully as plain text"); return { content: [{ type: "text" as const, text: xmlData }] }; } } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); log(LogLevel.ERROR, `Error dumping UI hierarchy: ${errorMsg}`); return { content: [{ type: "text" as const, text: `Error dumping UI hierarchy: ${errorMsg}` }], isError: true }; } finally { // Clean up the temporary file await cleanupTempFile(tempFilePath); } }, { description: INSPECT_UI_TOOL_DESCRIPTION } );
- src/types.ts:79-83 (schema)Input schema object for inspect_ui tool parameters: optional device ID, output path on device, and flag for base64 encoding.export const inspectUiInputSchema = { device: z.string().optional().describe("Specific device ID (optional)"), outputPath: z.string().optional().describe("Custom output path on device (default: /sdcard/window_dump.xml)"), asBase64: z.boolean().optional().default(false).describe("Return XML content as base64 (default: false)") };
- src/types.ts:109-109 (schema)Zod schema object wrapping inspectUiInputSchema, used in tool registration as AdbUidumpSchema.shape.export const AdbUidumpSchema = z.object(inspectUiInputSchema);
- src/index.ts:85-90 (helper)Detailed tool description string used in the inspect_ui tool registration.const INSPECT_UI_TOOL_DESCRIPTION = "Captures the complete UI hierarchy of the current screen as an XML document. " + "This provides structured XML data that can be parsed to identify UI elements and their properties. " + "Essential for UI automation, determining current app state, and identifying interactive elements. " + "Returns the UI structure including all elements, their IDs, text values, bounds, and clickable states. " + "This is significantly more useful than screenshots for AI processing and automation tasks.";