Skip to main content
Glama

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
NameRequiredDescriptionDefault
serialYesADB device serial (from interceptor_android_devices)
inject_certNoPush CA cert to system store (requires root)
setup_tunnelNoSet up ADB reverse tunnel
set_wifi_proxyNoSet global Wi-Fi HTTP proxy via adb settings

Implementation Reference

  • 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 };
    }
  • 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) }) }] };
        }
      },
    );
Install Server

Other Tools

Latest Blog Posts

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/yfe404/proxy-mcp'

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