adb_shell
Execute shell commands on Android devices via ADB, enabling direct interaction for tasks like app management, file operations, and UI analysis. Supports specific device targeting for precision.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| command | Yes | Shell command to execute on the device | |
| device | No | Specific device ID (optional) |
Implementation Reference
- src/index.ts:481-496 (handler)The async handler function that executes the adb shell command. Logs the command, builds device arguments if specified, trims and validates the command input, then invokes the shared executeAdbCommand helper to run the ADB shell command.async (args: z.infer<typeof AdbShellSchema>, _extra: RequestHandlerExtra) => { log(LogLevel.INFO, `Executing shell command: ${args.command}`); const deviceArgs = buildDeviceArgs(args.device); const trimmedCommand = args.command.trim(); if (!trimmedCommand) { const message = "Shell command must not be empty"; log(LogLevel.ERROR, message); return { content: [{ type: "text" as const, text: message }], isError: true }; } return executeAdbCommand([...deviceArgs, "shell", trimmedCommand], "Error executing shell command"); },
- src/index.ts:478-498 (registration)Registers the 'adb_shell' tool with the MCP server, providing the tool name, input schema shape, the handler function, and tool description.server.tool( "adb_shell", AdbShellSchema.shape, async (args: z.infer<typeof AdbShellSchema>, _extra: RequestHandlerExtra) => { log(LogLevel.INFO, `Executing shell command: ${args.command}`); const deviceArgs = buildDeviceArgs(args.device); const trimmedCommand = args.command.trim(); if (!trimmedCommand) { const message = "Shell command must not be empty"; log(LogLevel.ERROR, message); return { content: [{ type: "text" as const, text: message }], isError: true }; } return executeAdbCommand([...deviceArgs, "shell", trimmedCommand], "Error executing shell command"); }, { description: ADB_SHELL_TOOL_DESCRIPTION } );
- src/types.ts:46-49 (schema)Defines the raw input schema object for the adb_shell tool parameters: required 'command' string and optional 'device' string.export const adbShellInputSchema = { command: z.string().describe("Shell command to execute on the device"), device: z.string().optional().describe("Specific device ID (optional)") };
- src/types.ts:103-103 (schema)Zod schema constructor that wraps the adbShellInputSchema into the full AdbShellSchema used by the tool registration.export const AdbShellSchema = z.object(adbShellInputSchema);
- src/index.ts:197-251 (helper)Shared helper function used by adb_shell handler to execute ADB commands safely, handling stdout/stderr, errors, and specific non-error warnings.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 }; } }