Skip to main content
Glama

ADB Screenshot MCP Server

index.ts6.88 kB
#!/usr/bin/env node import { Server } from "@modelcontextprotocol/sdk/server/index.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { CallToolRequestSchema, ErrorCode, ListToolsRequestSchema, McpError, } from "@modelcontextprotocol/sdk/types.js"; import { exec } from "child_process"; import { promisify } from "util"; const execAsync = promisify(exec); const server = new Server( { name: "adb-screenshot-mcp", version: "1.0.0", }, { capabilities: { tools: {}, }, } ); // ADB WiFi Connection Tool server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: "adb_connect_wifi", description: "Connect to an Android device over WiFi using ADB", inputSchema: { type: "object", properties: { ip_address: { type: "string", description: "IP address of the Android device", }, port: { type: "string", description: "Port number (default: 5555)", default: "5555", }, }, required: ["ip_address"], }, }, { name: "adb_screenshot", description: "Take a screenshot of the connected Android device", inputSchema: { type: "object", properties: { output_path: { type: "string", description: "Local path to save the screenshot (default: screenshot.png)", default: "screenshot.png", }, device_id: { type: "string", description: "Device ID/serial (optional, uses first device if not specified)", }, }, required: [], }, }, { name: "adb_list_devices", description: "List all connected ADB devices", inputSchema: { type: "object", properties: {}, required: [], }, }, { name: "adb_disconnect", description: "Disconnect from a WiFi ADB device", inputSchema: { type: "object", properties: { ip_address: { type: "string", description: "IP address of the device to disconnect from", }, port: { type: "string", description: "Port number (default: 5555)", default: "5555", }, }, required: ["ip_address"], }, }, { name: "adb_device_info", description: "Get information about a connected device", inputSchema: { type: "object", properties: { device_id: { type: "string", description: "Device ID/serial (optional, uses first device if not specified)", }, }, required: [], }, }, ], }; }); server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; try { switch (name) { case "adb_connect_wifi": { const { ip_address, port = "5555" } = args as { ip_address: string; port?: string; }; const { stdout, stderr } = await execAsync(`adb connect ${ip_address}:${port}`); if (stderr && stderr.includes("failed")) { throw new McpError(ErrorCode.InternalError, `ADB connection failed: ${stderr}`); } return { content: [ { type: "text", text: `Successfully connected to ${ip_address}:${port}\n${stdout}`, }, ], }; } case "adb_screenshot": { const { output_path = "screenshot.png", device_id } = args as { output_path?: string; device_id?: string; }; const deviceArg = device_id ? `-s ${device_id}` : ""; const tempPath = "/sdcard/screenshot.png"; // Take screenshot on device await execAsync(`adb ${deviceArg} shell screencap -p ${tempPath}`); // Pull screenshot to local machine const { stdout, stderr } = await execAsync(`adb ${deviceArg} pull ${tempPath} ${output_path}`); // Clean up temp file on device await execAsync(`adb ${deviceArg} shell rm ${tempPath}`); if (stderr && stderr.includes("error")) { throw new McpError(ErrorCode.InternalError, `Screenshot failed: ${stderr}`); } return { content: [ { type: "text", text: `Screenshot saved to ${output_path}`, }, ], }; } case "adb_list_devices": { const { stdout } = await execAsync("adb devices"); return { content: [ { type: "text", text: stdout, }, ], }; } case "adb_disconnect": { const { ip_address, port = "5555" } = args as { ip_address: string; port?: string; }; const { stdout, stderr } = await execAsync(`adb disconnect ${ip_address}:${port}`); return { content: [ { type: "text", text: `Disconnected from ${ip_address}:${port}\n${stdout}`, }, ], }; } case "adb_device_info": { const { device_id } = args as { device_id?: string; }; const deviceArg = device_id ? `-s ${device_id}` : ""; const [model, android, api] = await Promise.all([ execAsync(`adb ${deviceArg} shell getprop ro.product.model`), execAsync(`adb ${deviceArg} shell getprop ro.build.version.release`), execAsync(`adb ${deviceArg} shell getprop ro.build.version.sdk`), ]); const info = { model: model.stdout.trim(), android_version: android.stdout.trim(), api_level: api.stdout.trim(), }; return { content: [ { type: "text", text: `Device Information:\nModel: ${info.model}\nAndroid Version: ${info.android_version}\nAPI Level: ${info.api_level}`, }, ], }; } default: throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`); } } catch (error) { if (error instanceof McpError) { throw error; } throw new McpError(ErrorCode.InternalError, `Tool execution failed: ${error}`); } }); async function main() { const transport = new StdioServerTransport(); await server.connect(transport); } main().catch((error) => { console.error("Server error:", error); process.exit(1); });

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/desamtralized/adb-mcp'

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