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

Tool Definition Quality

Score is being calculated. Check back soon.

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