prepare_device
Prepares the active device for a test session: dismisses keyboard, clears clipboard, resets status bar override, and forces QWERTY layout. Opt out of any action via flags.
Instructions
Prépare le device actif pour une session de test propre : dismiss keyboard, clear clipboard, reset status bar overrides, force keyboard QWERTY (iOS). Tout est opt-out via flags. Auto-appelé par set_device sauf si skip_setup=true.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| dismiss_keyboard | No | Dismiss le clavier s'il est visible (default: true) | |
| clear_clipboard | No | Vide le clipboard du device (default: true) | |
| clear_status_bar | No | Reset les overrides de status bar iOS (default: true) | |
| force_qwerty | No | Force keyboard QWERTY sur iOS, sécurité contre AZERTY (default: true) |
Implementation Reference
- src/utils/device-prepare.ts:50-130 (handler)Core handler: `prepareDevice()` function that executes the device preparation logic (dismiss keyboard, clear clipboard, clear status bar, force QWERTY) for both iOS and Android. This is the shared implementation used by both the explicit `prepare_device` tool and the auto-trigger in `set_device`.
export async function prepareDevice( dev: DeviceInfo, opts: PrepareDeviceOptions = {}, ): Promise<PrepareDeviceResult> { const o = { ...DEFAULT_OPTIONS, ...opts }; const steps: string[] = []; const failures: string[] = []; if (dev.platform === "ios") { if (o.clearClipboard) { try { await iosClearClipboard(dev.id); steps.push("clipboard cleared"); } catch (e) { failures.push(`clipboard: ${e instanceof Error ? e.message : e}`); } } if (o.clearStatusBar) { try { await iosClearStatusBar(dev.id); steps.push("status bar cleared"); } catch (e) { failures.push(`status_bar: ${e instanceof Error ? e.message : e}`); } } if (o.forceQwerty) { try { await iosForceKeyboardQwerty(dev.id); steps.push("keyboard QWERTY enforced"); } catch (e) { failures.push(`qwerty: ${e instanceof Error ? e.message : e}`); } } if (o.dismissKeyboard) { try { const wda = await ensureWdaRunning(dev); if (!wda.ready) { if (!o.skipKeyboardIfWdaNotReady) { failures.push(`dismiss_keyboard: WDA not ready (${wda.message ?? "unknown"})`); } else { steps.push("keyboard check skipped (WDA not ready, opt-in skip)"); } } else if (await iosIsKeyboardVisible()) { const dismissed = await iosDismissKeyboard(); steps.push(dismissed ? "keyboard dismissed" : "keyboard dismiss attempted (still visible)"); } else { steps.push("keyboard not visible"); } } catch (e) { failures.push(`dismiss_keyboard: ${e instanceof Error ? e.message : e}`); } } } else { // Android if (o.clearClipboard) { try { await androidClearClipboard(); steps.push("clipboard cleared"); } catch (e) { failures.push(`clipboard: ${e instanceof Error ? e.message : e}`); } } if (o.dismissKeyboard) { try { const dismissed = await androidDismissKeyboard(); steps.push(dismissed ? "keyboard dismissed" : "keyboard not visible"); } catch (e) { failures.push(`dismiss_keyboard: ${e instanceof Error ? e.message : e}`); } } if (o.clearStatusBar) steps.push("status bar override: skipped on Android (iOS-only)"); if (o.forceQwerty) steps.push("force QWERTY: skipped on Android (iOS-only)"); } return { steps, failures }; } - src/utils/device-prepare.ts:20-32 (schema)Input options interface `PrepareDeviceOptions` defining configurable flags (dismissKeyboard, clearClipboard, clearStatusBar, forceQwerty, skipKeyboardIfWdaNotReady).
export interface PrepareDeviceOptions { dismissKeyboard?: boolean; clearClipboard?: boolean; clearStatusBar?: boolean; forceQwerty?: boolean; /** * If true, skip launching WDA just to check the keyboard. Used by the * auto-trigger path inside `set_device` to avoid blocking up to 120s * when WDA isn't already up. The explicit `prepare_device` tool leaves * this false to do the full job. */ skipKeyboardIfWdaNotReady?: boolean; } - src/utils/device-prepare.ts:34-37 (schema)Result interface `PrepareDeviceResult` with steps (successful actions) and failures (non-fatal errors).
export interface PrepareDeviceResult { steps: string[]; failures: string[]; } - src/tools/prepare-device.ts:23-61 (handler)MCP tool registration and handler: `registerPrepareDevice()` registers the 'prepare_device' tool with schema (zod) and async callback that resolves the active device, calls the core `prepareDevice()` helper, and formats the response.
export function registerPrepareDevice(server: McpServer): void { server.tool( "prepare_device", "Prépare le device actif pour une session de test propre : dismiss keyboard, clear clipboard, reset status bar overrides, force keyboard QWERTY (iOS). Tout est opt-out via flags. Auto-appelé par set_device sauf si skip_setup=true.", { dismiss_keyboard: z.boolean().optional().default(true).describe("Dismiss le clavier s'il est visible (default: true)"), clear_clipboard: z.boolean().optional().default(true).describe("Vide le clipboard du device (default: true)"), clear_status_bar: z.boolean().optional().default(true).describe("Reset les overrides de status bar iOS (default: true)"), force_qwerty: z.boolean().optional().default(true).describe("Force keyboard QWERTY sur iOS, sécurité contre AZERTY (default: true)"), }, async ({ dismiss_keyboard, clear_clipboard, clear_status_bar, force_qwerty }) => { const result = await resolveDevice(); if ("error" in result) return { content: [{ type: "text", text: result.error }], isError: true }; const dev = result.device; try { const { steps, failures } = await prepareDevice(dev, { dismissKeyboard: dismiss_keyboard, clearClipboard: clear_clipboard, clearStatusBar: clear_status_bar, forceQwerty: force_qwerty, // Explicit prepare_device call: do the full job, including waking WDA skipKeyboardIfWdaNotReady: false, }); const platform = dev.platform === "ios" ? "🍎" : "🤖"; const summary = steps.length > 0 ? `\n • ${steps.join("\n • ")}` : " (no actions)"; const failureSummary = failures.length > 0 ? `\n\n⚠️ Non-fatal failures:\n • ${failures.join("\n • ")}` : ""; const msg = `${platform} Device prepared : **${dev.name}**${summary}${failureSummary}`; logAction("prepare_device", msg, false, dev.platform, dev.id, dev.name); return { content: [{ type: "text", text: msg + getReportSuffix() }] }; } catch (err) { const msg = err instanceof Error ? err.message : String(err); logAction("prepare_device", `Erreur: ${msg}`, true, dev.platform, dev.id, dev.name); return { content: [{ type: "text", text: `Erreur prepare_device: ${msg}` }], isError: true }; } } ); } - src/index.ts:32-35 (registration)Tool registration in main entry point: `registerPrepareDevice(server)` wires the tool into the MCP server.
// Device management registerListDevices(server); registerSetDevice(server); registerPrepareDevice(server);