adb_install
Install APK files on Android devices via ADB commands by specifying the local APK path and optional device ID using the ADB MCP Server.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| apkPath | Yes | Local path to the APK file | |
| device | No | Specific device ID (optional) |
Implementation Reference
- src/index.ts:504-528 (handler)The main execution logic for the adb_install tool: trims APK path, builds device args, runs 'adb install -r' via executeAdbCommand, logs success/error, and returns formatted response.async (args: z.infer<typeof AdbInstallSchema>, _extra: RequestHandlerExtra) => { log(LogLevel.INFO, `Installing APK file from path: ${args.apkPath}`); try { // Install the APK using the provided file path const deviceArgs = buildDeviceArgs(args.device); const apkPath = args.apkPath.trim(); if (!apkPath) { throw new Error("APK path must not be empty"); } const result = await executeAdbCommand([...deviceArgs, "install", "-r", apkPath], "Error installing APK"); if (!result.isError) { log(LogLevel.INFO, "APK installed successfully"); } return result; } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); log(LogLevel.ERROR, `Error installing APK: ${errorMsg}`); return { content: [{ type: "text" as const, text: `Error installing APK: ${errorMsg}` }], isError: true }; } },
- src/index.ts:501-530 (registration)Registers the adb_install tool with the MCP server, providing the tool name, input schema shape, inline handler function, and tool description.server.tool( "adb_install", AdbInstallSchema.shape, async (args: z.infer<typeof AdbInstallSchema>, _extra: RequestHandlerExtra) => { log(LogLevel.INFO, `Installing APK file from path: ${args.apkPath}`); try { // Install the APK using the provided file path const deviceArgs = buildDeviceArgs(args.device); const apkPath = args.apkPath.trim(); if (!apkPath) { throw new Error("APK path must not be empty"); } const result = await executeAdbCommand([...deviceArgs, "install", "-r", apkPath], "Error installing APK"); if (!result.isError) { log(LogLevel.INFO, "APK installed successfully"); } return result; } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); log(LogLevel.ERROR, `Error installing APK: ${errorMsg}`); return { content: [{ type: "text" as const, text: `Error installing APK: ${errorMsg}` }], isError: true }; } }, { description: ADB_INSTALL_TOOL_DESCRIPTION } );
- src/types.ts:51-54 (schema)Defines the raw input schema fields for adb_install: apkPath (string, local APK path) and optional device ID.export const adbInstallInputSchema = { apkPath: z.string().describe("Local path to the APK file"), device: z.string().optional().describe("Specific device ID (optional)") };
- src/types.ts:104-104 (schema)Constructs the full Zod validation schema AdbInstallSchema from the input schema object, used in tool registration.export const AdbInstallSchema = z.object(adbInstallInputSchema);
- src/index.ts:197-251 (helper)Key helper utility used by adb_install (and other tools) to run ADB commands, parse output/errors, handle common warnings, log operations, and return standardized MCP responses.async function executeAdbCommand(args: string[], errorMessage: string) { const commandString = ["adb", ...args].join(" "); try { log(LogLevel.DEBUG, `Executing command: ${commandString}`); const { stdout, stderr } = await runAdb(args); const stderrText = stderr.trim(); // Some ADB commands output to stderr but are not errors if (stderrText && !stdout.includes("List of devices attached") && !stdout.includes("Success")) { const nonErrorWarnings = [ "Warning: Activity not started, its current task has been brought to the front", "Warning: Activity not started, intent has been delivered to currently running top-most instance." ]; if (nonErrorWarnings.some((warning) => stderrText.includes(warning))) { log(LogLevel.WARN, `Command warning (not error): ${stderrText}`); return { content: [{ type: "text" as const, text: stderrText.replace(/^Error: /, "") // Remove any 'Error: ' prefix if present }] // Do NOT set isError }; } log(LogLevel.ERROR, `Command error: ${stderrText}`); return { content: [{ type: "text" as const, text: `Error: ${stderrText}` }], isError: true }; } log(LogLevel.DEBUG, `Command successful: ${commandString}`); const commandSummary = args[0] ? `${args[0]}` : commandString; log(LogLevel.INFO, `ADB command executed successfully: ${commandSummary}`); return { content: [{ type: "text" as const, text: stdout || "Command executed successfully" }] }; } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); log(LogLevel.ERROR, `${errorMessage}: ${errorMsg}`); return { content: [{ type: "text" as const, text: `${errorMessage}: ${errorMsg}` }], isError: true }; } }