interceptor_android_activate
Activate Android device interception by injecting CA certificates, establishing ADB tunnels, and configuring Wi-Fi proxies for network traffic analysis.
Instructions
Full Android interception: inject CA cert into system store (root required), set up ADB reverse tunnel, and optionally set Wi-Fi proxy. Proxy must be running.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| serial | Yes | ADB device serial (from interceptor_android_devices) | |
| inject_cert | No | Push CA cert to system store (requires root) | |
| setup_tunnel | No | Set up ADB reverse tunnel | |
| set_wifi_proxy | No | Set global Wi-Fi HTTP proxy via adb settings |
Implementation Reference
- src/interceptors/android-adb.ts:113-208 (handler)Implementation of the Android ADB interception activation, including root cert injection, reverse tunnel setup, and global Wi-Fi proxy configuration.
async activate(options: ActivateOptions): Promise<ActivateResult> { const { proxyPort, certPem } = options; const serial = options.serial as string | undefined; const injectCert = options.injectCert !== false; // Default true const setupTunnel = options.setupTunnel !== false; // Default true const setWifiProxy = options.setWifiProxy as boolean | undefined; if (!serial) { throw new Error("'serial' option required. Use interceptor_android_devices to list devices."); } const targetId = `adb_${serial}`; let reversePort: number | null = null; let certInjected = false; let wifiProxy = false; // 1. Inject CA cert into system store (requires root) if (injectCert) { const hasRoot = await checkRoot(serial); if (!hasRoot) { throw new Error(`Device ${serial} does not have root access. Certificate injection requires root. Use injectCert:false to skip.`); } const derBuf = pemToDer(certPem); const hash = await getSubjectHash(certPem); const certFileName = `${hash}.0`; // Push DER cert to device temp const tmpPath = `/data/local/tmp/${certFileName}`; // Write DER to a local temp file first const { writeFileSync, unlinkSync } = await import("node:fs"); const { join } = await import("node:path"); const { tmpdir } = await import("node:os"); const localTmp = join(tmpdir(), `adb-cert-${Date.now()}.der`); writeFileSync(localTmp, derBuf); try { await adb(serial, "push", localTmp, tmpPath); } finally { try { unlinkSync(localTmp); } catch { /* ignore */ } } // Mount tmpfs overlay on cacerts dir and copy cert const sdkStr = await adbShell(serial, "getprop ro.build.version.sdk").catch(() => "30"); const sdk = parseInt(sdkStr, 10); // Standard system cert path await adbShell(serial, `su -c "mount -t tmpfs tmpfs /system/etc/security/cacerts 2>/dev/null; cp /system/etc/security/cacerts_orig/* /system/etc/security/cacerts/ 2>/dev/null; cp ${tmpPath} /system/etc/security/cacerts/${certFileName}; chmod 644 /system/etc/security/cacerts/${certFileName}; chown root:root /system/etc/security/cacerts/${certFileName}"`).catch(() => { // Fallback: try without tmpfs mount (already rw) return adbShell(serial, `su -c "cp ${tmpPath} /system/etc/security/cacerts/${certFileName} && chmod 644 /system/etc/security/cacerts/${certFileName}"`); }); // Android 14+ APEX conscrypt module if (sdk >= 34) { await adbShell(serial, `su -c "cp ${tmpPath} /apex/com.android.conscrypt/cacerts/${certFileName} 2>/dev/null; chmod 644 /apex/com.android.conscrypt/cacerts/${certFileName} 2>/dev/null"`).catch(() => { // Not all devices have this path }); } // Clean up temp await adbShell(serial, `rm ${tmpPath}`).catch(() => {}); certInjected = true; } // 2. Set up ADB reverse tunnel if (setupTunnel) { await adb(serial, "reverse", `tcp:${proxyPort}`, `tcp:${proxyPort}`); reversePort = proxyPort; } // 3. Set Wi-Fi proxy if (setWifiProxy) { await adbShell(serial, `settings put global http_proxy 127.0.0.1:${proxyPort}`); wifiProxy = true; } const info = await getDeviceInfo(serial); const target: ActiveTarget = { id: targetId, description: `${info.manufacturer ?? ""} ${info.model ?? serial} (Android ${info.version ?? "?"})`.trim(), activatedAt: Date.now(), details: { serial, ...info, certInjected, reversePort, wifiProxy, proxyPort, }, }; this.devices.set(targetId, { target, serial, reversePort, wifiProxy, certInjected }); return { targetId, details: target.details }; } - src/tools/interceptors.ts:550-578 (registration)Registration and MCP tool handler for 'interceptor_android_activate' in src/tools/interceptors.ts.
"interceptor_android_activate", "Full Android interception: inject CA cert into system store (root required), set up ADB reverse tunnel, and optionally set Wi-Fi proxy. Proxy must be running.", { serial: z.string().describe("ADB device serial (from interceptor_android_devices)"), inject_cert: z.boolean().optional().default(true).describe("Push CA cert to system store (requires root)"), setup_tunnel: z.boolean().optional().default(true).describe("Set up ADB reverse tunnel"), set_wifi_proxy: z.boolean().optional().default(false).describe("Set global Wi-Fi HTTP proxy via adb settings"), }, async ({ serial, inject_cert, setup_tunnel, set_wifi_proxy }) => { try { const proxyInfo = requireProxy(); const result = await interceptorManager.activate("android-adb", { ...proxyInfo, serial, injectCert: inject_cert, setupTunnel: setup_tunnel, setWifiProxy: set_wifi_proxy, }); return { content: [{ type: "text", text: JSON.stringify({ status: "success", ...result }), }], }; } catch (e) { return { content: [{ type: "text", text: JSON.stringify({ status: "error", error: errorToString(e) }) }] }; } }, );