Back to Browse

Frida Mobile MCP Server

Developer ToolsModerate6.6MCP RegistryLocal
Free

Server data from the Official MCP Registry

Mobile Frida MCP Server - AI-powered mobile app exploration and testing via Frida instrumentation

About

Mobile Frida MCP Server - AI-powered mobile app exploration and testing via Frida instrumentation

Security Report

6.6
Moderate6.6Moderate Risk

frida-mobile-mcp is a Frida-based instrumentation server for Android and iOS whose broad capabilities (process spawn/attach, memory read/write, script execution, mobile UI automation, network-reachable HTTP transport) are inherent to its purpose and match the Developer Tools category baseline. The reviewed excerpt shows no exfiltration or hardcoded secrets, but the powerful tools (execute_script, memory write, native injection, save_script) and the HTTP transport bearer token deserve user scrutiny, and the code excerpt was truncated so tool implementations were not fully reviewed. Supply chain analysis found 1 known vulnerability in dependencies (0 critical, 1 high severity). Package verification found 1 issue.

6 files analyzed ยท 5 issues found

Security scores are indicators to help you make informed decisions, not guarantees. Always review permissions before connecting any MCP server.

What You'll Need

Set these up before or after installing:

Default Frida device ID to use (e.g. emulator-5554 or a USB serial). Can also be set with --device.Optional

Environment variable: FRIDA_DEVICE_ID

Set to "1" to enable execution of custom Frida scripts (execute_script and custom hook_function handlers). Disabled by default.Optional

Environment variable: FRIDA_MCP_ALLOW_CUSTOM_SCRIPTS

Set to "1" to enable the write_memory tool. Disabled by default for safety.Optional

Environment variable: FRIDA_MCP_MEMORY_WRITE

host[:port] of a remote frida-server to add as a remote device at startup (port defaults to 27042).Optional

Environment variable: FRIDA_MCP_REMOTE

Tool schema profile. "compact" shortens tool schemas and descriptions for clients with small context windows.Optional

Environment variable: FRIDA_MCP_SCHEMA_PROFILE

Maximum number of characters in a single tool response; longer output is truncated.Optional

Environment variable: FRIDA_MCP_MAX_RESPONSE_CHARS

Bearer token required by HTTP clients. Only used with --transport http (required when --host is not loopback); unused for the default stdio transport.Required

Environment variable: FRIDA_MCP_HTTP_TOKEN

Frida script runtime to use for injected agents.Optional

Environment variable: FRIDA_MCP_RUNTIME

Set to "1" to enable debug logging on stderr. Can also be set with --debug.Optional

Environment variable: FRIDA_MCP_DEBUG

Directory with prebuilt Java/ObjC bridge bundles (defaults to dist/bridges inside the package)Optional

Environment variable: FRIDA_MCP_BRIDGES_DIR

Cache directory for the frida.Compiler project used to compile ES module scriptsOptional

Environment variable: FRIDA_MCP_COMPILER_PROJECT_DIR

Path to a friTap fritap_agent.js bundle for capture_tls (otherwise the installed friTap Python package or a pinned download is used)Optional

Environment variable: FRITAP_AGENT_PATH

friTap release tag to download when no local agent is found (default v2.5.2)Optional

Environment variable: FRITAP_VERSION

How to Install

Add this to your MCP configuration file:

{
  "mcpServers": {
    "io-github-monkeywave-frida-mobile-mcp": {
      "env": {
        "FRITAP_VERSION": "your-fritap-version-here",
        "FRIDA_DEVICE_ID": "your-frida-device-id-here",
        "FRIDA_MCP_DEBUG": "your-frida-mcp-debug-here",
        "FRIDA_MCP_REMOTE": "your-frida-mcp-remote-here",
        "FRIDA_MCP_RUNTIME": "your-frida-mcp-runtime-here",
        "FRITAP_AGENT_PATH": "your-fritap-agent-path-here",
        "FRIDA_MCP_HTTP_TOKEN": "your-frida-mcp-http-token-here",
        "FRIDA_MCP_BRIDGES_DIR": "your-frida-mcp-bridges-dir-here",
        "FRIDA_MCP_MEMORY_WRITE": "your-frida-mcp-memory-write-here",
        "FRIDA_MCP_SCHEMA_PROFILE": "your-frida-mcp-schema-profile-here",
        "FRIDA_MCP_MAX_RESPONSE_CHARS": "your-frida-mcp-max-response-chars-here",
        "FRIDA_MCP_ALLOW_CUSTOM_SCRIPTS": "your-frida-mcp-allow-custom-scripts-here",
        "FRIDA_MCP_COMPILER_PROJECT_DIR": "your-frida-mcp-compiler-project-dir-here"
      },
      "args": [
        "-y",
        "frida-mobile-mcp"
      ],
      "command": "npx"
    }
  }
}

Documentation

View on GitHub

From the project's GitHub README.

frida-mobile-mcp

npm skills.sh CI License: MIT Node >=22.12

An MCP server that gives AI agents dynamic instrumentation of Android and iOS apps through Frida 17, and runs next to REA, ReVa (Ghidra) and IDA MCP servers. It exposes 71 tools: high-level ones that manage devices, sessions and scripts for you (explore an app, hook a Java/ObjC/native method, trace calls, map reachability coverage and autonomously drive the UI toward it, find secrets in memory and turn them into reusable friTap patterns, cast a wide net over crypto, bypass SSL pinning, capture TLS keys and plaintext with friTap, run prebuilt analysis scripts, validate custom scripts) and low-level primitives (spawn/attach, module and symbol enumeration, address resolution, control-flow analysis, memory dumps). Addresses use the same module+0xoffset notation as Ghidra/IDA so results move between static and dynamic tools without conversion, and every result carries an evidence envelope (evidence_id, limitations, coverage). Optional UI automation goes through mobile-mcp.

Quick start

npx frida-mobile-mcp                      # stdio MCP server (default `serve` command)
frida-mobile-mcp doctor                   # check Node, frida-node, adb, devices, frida-server, bridge bundles
frida-mobile-mcp setup --client cursor    # write the server into a client config (claude-code, claude-desktop, cursor, vscode, windsurf, codex)
frida-mobile-mcp gadget --platform android --print   # generate a frida-gadget config.json + APK/IPA repackaging guidance

The gadget command generates a frida-gadget config.json (--interaction listen or --interaction script) and prints the APK/IPA repackaging steps. Embedding the gadget is the only way to instrument native detection that runs in .init_array / JNI_OnLoad before an attach-time script can load, and it removes the frida-server :27042 port as a fingerprint โ€” see frida_help({ topic: "evasion" }).

Claude Code:

claude mcp add frida -- npx -y frida-mobile-mcp

Claude Desktop (claude_desktop_config.json):

{
  "mcpServers": {
    "frida": {
      "command": "npx",
      "args": ["-y", "frida-mobile-mcp"],
      "env": { "FRIDA_DEVICE_ID": "emulator-5554" }
    }
  }
}

Per-client instructions, HTTP mode and remote frida-server setup are in docs/clients.md. A Claude Desktop extension manifest (manifest.json, MCPB) and an MCP registry entry (server.json) ship in the repo.

Requirements

  • Node.js >= 22.12 (CI runs 22 and 24 on Linux, macOS and Windows). npm install runs the frida package's install script, which downloads the native frida-node prebuild.

  • A device or emulator running frida-server 17.x. This package depends on frida-node ^17.24.3; frida-server on the device must have the same major version (17) and ideally the same minor version. frida-mobile-mcp doctor prints both versions and flags mismatches.

  • Android: download the matching frida-server-17.x.y-android-<arch>.xz from https://github.com/frida/frida/releases, then

    xz -d frida-server-17.24.3-android-arm64.xz
    adb push frida-server-17.24.3-android-arm64 /data/local/tmp/frida-server
    adb shell "chmod 755 /data/local/tmp/frida-server"
    adb shell "su -c '/data/local/tmp/frida-server &'"
    
  • iOS: a jailbroken device with the matching Frida package from the Frida Cydia/Sileo repository. Non-jailbroken devices need the app repackaged with the Frida Gadget; the server then attaches to the gadget-enabled process like any other.

  • Optional: pip install friTap for capture_tls (otherwise the pinned agent is downloaded on first use), and network access for npx -y @mobilenext/mobile-mcp@latest on first mobile_action.

What is new for Frida 17

  • Bridges are bundled. Frida 17 no longer ships the Java/ObjC bridges in the GumJS runtime. npm run build:bridges bundles frida-java-bridge and frida-objc-bridge into dist/bridges/{java,objc}.js; the server injects the right one by platform (Java on Android, ObjC on iOS/macOS) ahead of every script.
  • Legacy scripts still work. execute_script runs classic (non-module) scripts through Script.evaluate, so a Java.perform(...) script written for Frida 16 runs unchanged and keeps its own line numbers in errors. ES modules (import Java from "frida-java-bridge", JS or TS) are compiled on the host with the Frida Compiler; frida-compile bundles (starting with the ๐Ÿ“ฆ marker) are loaded as-is.
  • Removed APIs are linted. validate_script flags the static Module.findExportByName/findBaseAddress/enumerateExports, Memory.readX/writeX and *Sync enumerators that throw on Frida 17 and suggests the Module-instance / NativePointer replacements. Generated scripts get findExport(lib, name) and hookNative(lib, name, callbacks) helpers from the agent preamble, and template options as __FRIDA_MCP__.options.
  • analyze_native_function uses Process.findFunctionRange and the Frida 17.12+ ControlFlowGraph (with a linear-disassembly fallback reported in limitations).

Tool reference

Tier 1: high-level tools

ToolDescription
get_statusConnected devices, active sessions (platform, script count, last activity), hooks, traces and recent detaches/crashes. Run first and after a session is lost.
frida_helpTopic help: overview, hooking, tracing, memory, scripts, native, tls, mobile, examples, advanced, evasion, script_catalog, script_api, recipes, interop.
detect_app_technologiesFingerprint libraries, frameworks and security mechanisms; returns recommended script targets.
explore_appSpawn an app suspended, instrument, resume; returns pid, platform, modules and a filtered class list.
get_app_infoIdentify the installed artifact: version, SDK levels, debuggable, installer and every APK (base + splits) with on-device sha256/size; pull_to pulls and hash-verifies them for a static tool such as REA inspect_android_package. iOS: Frida app parameters only.
search_classes_and_methodsRegex search over classes (and methods with include_methods) in a running app.
describe_classFull shape of one loaded class: every method overload with parameter/return types and a hook-ready signature, constructors, fields, superclass/interfaces (ObjC: selectors with type encodings). Feed a signature to hook_method evidence: {class, signature}.
discover_cryptoFind where an app does crypto (or any API family) without assuming javax.crypto: ranked candidate hook targets across Java/ObjC classes and native symbols.
find_secrets_in_memoryContent-aware memory scan for the structure of secrets: RC4 S-box (byte[] or Java int[256]), AES key schedule (aeskeyfind โ€” encryption and decryption, mode-independent), ChaCha20/Salsa20 keys (sigma constant), high-entropy 16/24/32-byte keys, PEM/DER private keys, JWTs. Finds keys without reaching the code that uses them.
generate_memory_patternTurn a located secret into a reusable anchor pattern (stable byte signature near the key + offset): re-locate it with scan_memory, or hand it to friTap via capture_tls (patterns/offsets).
monitor_cryptoCrypto-oracle wide net: discover and hook all likely crypto sinks at once (app-owned classes + javax.crypto/Mac/MessageDigest, iOS CommonCrypto, native OpenSSL/BoringSSL) and dump every key, input and output as hex.
trace_coverageReachability map: arm cheap persistent entry-hooks over a class/package/module scope and track covered vs cold targets across trigger_and_wait drives, so you know what code you have not yet exercised.
drive_coverageAutonomously drive an instrumented session's UI toward uncovered code โ€” taps on-screen elements breadth-first and stops the instant a crypto/secret signal fires (or coverage stalls / max_steps). Pair with monitor_crypto / trace_coverage.
watch_loadsWatch for late-loaded .so libraries and Java classes, plus anti-Frida probes; emits watch_event messages as the app runs.
trigger_and_waitPerform a UI action and block until the resulting hook/message output arrives, so you learn which hook a tap fired (or that none did).
hook_methodHook Java (com.example.Class.method), ObjC (-[Class sel:]) or native targets (libssl.so!SSL_read, libfoo.so+0x1234, 0x7f..., !open) with auto session management; backtraces as module+0xoff (symbol).
trace_methodfrida-trace style tracing of glob patterns (com.example.net.*, -[NSURL*], libssl.so!SSL_*) for a duration.
execute_scriptRun a custom script: classic JS (bridges injected), ES module JS/TS (compiled with the Frida Compiler) or a frida-compile bundle. timeout_ms bounds the initial run. Requires allowCustomScripts.
validate_scriptSyntax, type and Frida 17 removed-API check without a device. Use before execute_script.
run_prebuilt_scriptRun one of the 9 prebuilt scripts below; call without script_name to list them.
bypass_ssl_pinningOne-click pinning bypass (Android: TrustManager, OkHttp CertificatePinner, Conscrypt; iOS: SecTrust, ATS, BoringSSL).
capture_tlsfriTap: TLS session keys (NSS key log) and optional decrypted plaintext / synthetic pcap for OpenSSL/BoringSSL, Conscrypt, NSS, GnuTLS, wolfSSL, mbedTLS, Secure Transport and more. Accepts friTap patterns/offsets (e.g. from generate_memory_pattern or BoringSecretHunter) for stripped libraries.
read_memoryRead up to 4 MB at any address notation; returns hex plus absolute address and module+offset.
write_memoryWrite hex bytes to memory. Disabled unless memoryWriteEnabled.
scan_memoryByte-pattern scan (48 89 5c 24 ?? 57), optionally limited to a module.
get_messagesBuffered hook invocations, trace hits, send() output and errors; since paginates.
get_evidenceRe-read a persisted tool result (params, status, structured result) by evidence_id.
export_evidence_bundleExport persisted results as a JSON or Markdown bundle, inline or to a file.
stop_instrumentationRemove all hooks, scripts and traces on a target and detach.
unload_scriptUnload a single script (hook, trace or custom) from a session while keeping it attached.
mobile_actionGateway to mobile-mcp UI automation (screenshot, elements, tap, swipe, type, launch app, list apps).
search_recipesSearch the purpose-indexed library of ready-to-run classic-JS recipes (custom crypto-key capture, native/JNI hooks, classloader/intent/WebView, iOS Keychain); returns ranked recipes with source to adapt and run via execute_script.
save_scriptSave a script under ~/.config/frida-mobile-mcp/scripts for reuse. Requires allowCustomScripts.
list_saved_scriptsList scripts saved with save_script.
run_saved_scriptRun a saved script by name against a target. Requires allowCustomScripts.
export_scriptExport a script as a standalone classic .js that runs under the plain frida -U -f <pkg> -l file.js CLI (preamble + source; bridges provided by the frida-tools CLI, not bundled).

Tier 2: advanced primitives

ToolDescription
list_devicesLocal, USB and remote Frida devices (frida-ls-devices).
select_deviceSelect the active device by ID, type or remote host.
get_device_infoOS version, architecture and system parameters.
list_processesRunning processes (frida-ps).
list_applicationsInstalled and running applications.
get_frontmost_applicationForeground application.
spawn_processSpawn suspended for early instrumentation; resume with resume_process.
attach_processAttach to a running process by PID or name.
resume_processResume a suspended process.
kill_processKill a process.
detach_sessionDetach a session and unload its scripts.
list_sessionsSessions managed by this server.
spawn_gatingEnable / disable / list device-wide spawn gating โ€” hold newly spawned (incl. child/isolated) processes suspended for early instrumentation; release with resume_process.
child_gatingEnable / disable child gating on a session so forked/exec'd child processes are held for instrumentation.
eternalize_scriptPin a loaded script in the target so it survives detach (fire-and-forget: no more messages/unload) โ€” leave a bypass/monitor running while you free the session.
enumerate_modulesLoaded modules with name, base, end, size, path; regex filter.
enumerate_exportsExports of a module, paginated.
enumerate_importsImports of a module with the providing module, paginated.
enumerate_symbolsSymbols including non-exported/debug symbols; regex filter and paging inside the agent (Linux, Android, iOS, macOS).
resolve_addressTranslate 0x7f... to module+0xoffset (+ nearest symbol) and module+0xoff / module!sym to an absolute address.
analyze_native_functionFunction range, basic blocks and edges, first instructions; addresses as absolute and module+0xoffset.
dump_module_memoryDump a module base-relative to a host file (under cwd, the temp dir or ~/.config/frida-mobile-mcp/dumps) for raw import into Ghidra/IDA.
list_threadsThreads with id, name, state, current pc as module+0xoffset; optional 8-frame backtraces.
hook_functionLow-level Interceptor hook on a session_id with optional custom on_enter/on_leave bodies (custom bodies need allowCustomScripts).
unhook_functionRemove a hook by ID.
frida_server_statusAndroid (adb): report frida-server PIDs, device CPU ABI, matching frida release arch, and the GitHub .xz asset URL for the installed frida-node version.
frida_server_installAndroid (adb): push a local (decompressed) frida-server binary to the device and chmod 755 it.
frida_server_startAndroid (adb): start frida-server daemonized (optionally via su) with a custom listen address/port and binary name โ€” a non-default port/name evades :27042/frida-server scans. Enforces allowedDevices.
frida_server_stopAndroid (adb): signal the matching frida-server process to stop (pkill, optionally via su).
adb_shellAndroid (adb): run an arbitrary device shell command. Disabled by default โ€” requires allowAdbShell (config) or FRIDA_MCP_ALLOW_ADB_SHELL=1.
adb_logcatAndroid (adb): dump the last N logcat lines (one-shot), optional tag:priority filters, or clear the buffer.
adb_pull / adb_pushAndroid (adb): move files between host and device.
adb_forwardAndroid (adb): add / remove / list port forwards (reach a frida-server on a non-default device port).
inject_libraryInject a native library (.so/.dylib) from the host into a process via Frida's injector, independent of the JS engine โ€” the parity path for a prebuilt gadget/agent or custom .so. Disabled by default โ€” needs allowNativeInjection (config) or FRIDA_MCP_ALLOW_NATIVE_INJECTION=1 (a capability separate from allowCustomScripts) and an architecture-matched library.

mobile_action gateway

mobile_action({ action, params }) forwards to a lazily spawned mobile-mcp process (npx -y @mobilenext/mobile-mcp@latest by default, configurable via mobileMcp, disabled with --no-mobile-mcp). Call it without action to list the available actions. All Frida tools work without it; when it cannot start the error is MOBILE_MCP_UNAVAILABLE.

The server also exposes frida:// resources (version, devices, processes, apps, sessions, messages, script catalog, persisted evidence via frida://evidence and frida://evidence/{id}) and five workflow prompts (explore_app, security_audit, trace_functionality, write_frida_script, hunt_secrets).

Prebuilt scripts

ScriptPurpose
ssl_pinning_bypassBypass certificate pinning (TrustManager, OkHttp, Conscrypt, WebView; SecTrust, ATS, BoringSSL, AFNetworking)
root_jailbreak_bypassBypass root/jailbreak detection (Java, SystemProperties, native fopen/access/stat, canOpenURL, sysctl)
class_enumerationList loaded Java/ObjC classes with a regex filter, optionally with methods
method_hookGeneric method hook (Java/ObjC methods or a native target) with argument and return value logging
crypto_monitorjavax.crypto, CommonCrypto and OpenSSL calls
network_inspectorSockets, DNS, UDP and TLS SSL_read/SSL_write (plaintext bytes with log_data)
keychain_prefsiOS Keychain and Android SharedPreferences access
filesystem_monitorFile I/O and SQLite
anti_frida_evasionObserve (mode=report, default) or neutralize (mode=spoof, needs memoryWriteEnabled) the native primitives RASP uses to detect Frida: /proc/self/{maps,status,task} reads, strstr "frida" greps, thread-name / dlopen probes, and iOS dyld image scans

Address notation and evidence envelope

Every tool that takes or returns a native address uses one vocabulary:

FormMeaningExample
module!symbolexport or ELF/Mach-O symbollibssl.so!SSL_write
module+0xOFFSEToffset from the module base (Ghidra/IDA RVA); decimal libfoo.so+4660 also acceptedlibfoo.so+0x1a2b0
0xADDRESSabsolute runtime address0x7f3a1c2b1234
symbol / !symbolglobal export searched across all modules!open

Results prefer module+0xoffset so a static tool can decompile at image base + offset; absolute addresses appear only outside known modules and come with a limitations entry.

Every successful call returns result, evidence_id (UUID, also written to the audit log), limitations[], coverage (complete | unknown), session_context and suggested_next. Errors carry code, category, retryable, remediation and recovery_actions. Every result, errors included, is also persisted to the evidence store and retrievable by its evidence_id via get_evidence, export_evidence_bundle and the frida://evidence/{id} resource (frida://evidence lists the latest 100). Field semantics and the error-code table are in docs/interop.md; the agent workflow around them is in skills/mobile-dynamic-analysis/SKILL.md.

Working with REA, ReVa and IDA

frida-mobile-mcp is built to run next to ReVa (Ghidra), ida-pro-mcp (IDA Pro) and REA: the static side answers what the code says, this server answers what it does at runtime. A static tool finds libfoo.so+0x1234; hook_method or analyze_native_function take that string as-is; backtraces and resolve_address give offsets back in the same form for decompilation. enumerate_modules returns base/end for rebasing a Ghidra/IDA project, dump_module_memory writes a base-relative image of an unpacked library for raw import, and capture_tls shows the bytes a statically found wrapper actually puts on the wire. A three-server client configuration and a full static -> dynamic -> static walkthrough are in docs/interop.md.

REA covers static Android analysis (inspect_android_package, inspect_android_method), ADB housekeeping and a generic Frida lane for desktop binaries; this server covers the mobile runtime (Java/ObjC bridges, prebuilt scripts, TLS keys, memory, UI driving). Register both in the same client, start with get_app_info so both servers analyse the same APK hash, and keep the combined catalog small with FRIDA_MCP_TOOL_PROFILE=core and FRIDA_MCP_TOOLS_EXCLUDE=adb_*,frida_server_*. Both servers return an evidence envelope with citable evidence_ids and an export_evidence_bundle tool, so one finding ledger can cite both. Routing rules, install lines, the field and error-code mapping and an APK -> static -> hook -> report walkthrough are in docs/rea.md.

HTTP transport

frida-mobile-mcp --transport http --port 3000                 # loopback (127.0.0.1), token optional
FRIDA_MCP_HTTP_TOKEN=<token> frida-mobile-mcp --transport http --host 0.0.0.0 --port 3000

Streamable HTTP endpoint at /mcp with one MCP session per client (Mcp-Session-Id); DELETE /mcp with that header ends the session. The server binds to loopback by default; a Bearer token (--http-token or FRIDA_MCP_HTTP_TOKEN) is mandatory when --host is not a loopback address and the server refuses to start without one. Host and Origin headers are validated against the bound host (DNS-rebinding protection). There is no TLS; use a reverse proxy or SSH tunnel across networks. --port 0 picks a free port; the bound URL is printed as a JSON line on stderr. Full curl examples: docs/clients.md.

Library usage

import { McpServer } from '@modelcontextprotocol/server';
import { createServer, registerFridaTools, createSessionServer } from 'frida-mobile-mcp';

const server = createServer({ allowCustomScripts: false });      // ready-made McpServer with every tool
// or add the tools to your own server:
const mine = new McpServer({ name: 'my-agent', version: '1.0.0' });
const deviceManager = registerFridaTools(mine, { resources: true, prompts: false });
// or one server per HTTP session:
const perSession = createSessionServer();

Also exported: scriptRegistry, DeviceManager, composeAgentSource/createAgentScript, findRemovedApis, loadBridgeSource, startHttpServer, createStdioTransport, loadConfig, ensureState and the types (dist/lib.d.ts).

Configuration

Config file ~/.config/frida-mobile-mcp/config.json (merged over defaults, then CLI flags, then environment):

{
  "allowCustomScripts": false,
  "memoryWriteEnabled": false,
  "allowNativeInjection": false,
  "allowedDevices": [],
  "maxSessions": 4,
  "sessionTimeoutMinutes": 30,
  "maxMessageBuffer": 1000,
  "auditLogPath": "~/.config/frida-mobile-mcp/audit.jsonl",
  "evidence": { "enabled": true, "path": "~/.config/frida-mobile-mcp/evidence", "maxMb": 200, "maxEntries": 5000, "maxEntryKb": 2048 },
  "mobileMcp": { "enabled": true, "command": "npx", "args": ["-y", "@mobilenext/mobile-mcp@latest"] },
  "rateLimits": { "scriptsPerMinute": 10, "memoryReadsPerMinute": 60, "sessionsPerMinute": 5 }
}
VariableDefaultDescription
FRIDA_DEVICE_IDfirst USB deviceDevice to use; same as --device
FRIDA_MCP_ALLOW_CUSTOM_SCRIPTSunset1/true enables execute_script and custom hook_function bodies; same as --allow-custom-scripts
FRIDA_MCP_MEMORY_WRITEunset1/true enables write_memory; same as --allow-memory-write
FRIDA_MCP_ALLOW_NATIVE_INJECTIONunset1/true enables inject_library (native .so/.dylib injection); a capability separate from custom scripts
FRIDA_MCP_ALLOW_ADB_SHELLunset1/true enables adb_shell (arbitrary device shell commands)
FRIDA_MCP_DEBUGunset1 enables debug logging on stderr; same as --debug
FRIDA_MCP_REMOTEunsethost[:port] of a frida-server added as a remote device at startup (port 27042); same as --remote
FRIDA_MCP_REMOTE_TOKENunsetAuth token of that frida-server (frida-server --token); same as --remote-token
FRIDA_MCP_REMOTE_CERTunsetPath to the PEM certificate of a TLS frida-server (frida-server --certificate); same as --remote-cert
FRIDA_MCP_HTTP_TOKENunsetBearer token for the HTTP transport; same as --http-token
FRIDA_MCP_SCHEMA_PROFILEfullcompact shortens tool schemas for small context windows
FRIDA_MCP_TOOL_PROFILEfullcore registers only the core tool set (smaller tools/list, e.g. next to REA); also --tool-profile. With FRIDA_MCP_SCHEMA_PROFILE=compact the catalog drops to 17% of full; see docs/rea.md
FRIDA_MCP_TOOLS_EXCLUDE(none)Comma-separated tool-name globs never registered, e.g. adb_*,frida_server_* when REA's ADB tools handle the device; also --exclude-tools. get_status reports the count as hidden_tools
FRIDA_MCP_MAX_RESPONSE_CHARS25000Truncation limit for a single tool response
FRIDA_MCP_RUNTIMEFrida defaultqjs or v8 script runtime for injected agents
FRIDA_MCP_SNAPSHOTSunset1 pre-warms a per-session V8 snapshot of the bridge bundle (only with FRIDA_MCP_RUNTIME=v8); see docs/clients.md
FRIDA_MCP_EVIDENCE10 stops persisting tool results to the evidence store; same as config evidence.enabled
FRIDA_MCP_EVIDENCE_PATH~/.config/frida-mobile-mcp/evidenceEvidence store directory (YYYY-MM-DD/<evidence_id>.json plus index.jsonl, mode 0600)
FRIDA_MCP_EVIDENCE_MAX_MB200Size cap of the evidence store; the oldest records are pruned beyond it
FRIDA_MCP_BRIDGES_DIRdist/bridgesDirectory with the bundled java.js/objc.js bridges
FRIDA_MCP_COMPILER_PROJECT_DIR$TMPDIR/frida-mobile-mcp/compiler-projectProject dir the Frida Compiler uses for ES module scripts
FRITAP_AGENT_PATHunsetPath to a fritap_agent.js bundle for capture_tls
FRITAP_VERSIONv2.5.2friTap tag to download when no local agent is found
FRITAP_AGENT_SHA256pinned for v2.5.2Bare sha256 of the downloaded friTap agent for the selected FRITAP_VERSION tag; a mismatch refuses the bundle

Security guardrails

  • execute_script and custom hook_function handler bodies are refused with CUSTOM_SCRIPTS_DISABLED unless allowCustomScripts is on; prebuilt scripts and typed hook tools never need it.
  • write_memory is refused with MEMORY_WRITE_DISABLED unless memoryWriteEnabled is on. Prebuilt scripts that write target memory (e.g. anti_frida_evasion with mode=spoof) and watch_loads with spoof=true are gated the same way.
  • inject_library is refused with NATIVE_INJECTION_DISABLED unless allowNativeInjection is on โ€” a capability kept separate from allowCustomScripts so native code injection can be withheld even when JS agents are permitted.
  • allowedDevices restricts which device IDs may be used (empty = any).
  • Rate limits per minute for script loads, memory reads/scans and attach/spawn (RATE_LIMIT_EXCEEDED, retryable); maxSessions and sessionTimeoutMinutes cap concurrent and idle sessions.
  • Every tool call is appended to the JSONL audit log at auditLogPath with its evidence_id.
  • Every tool result (including memory dumps' metadata, read memory and found secrets) is persisted under the evidence path (evidence.path, default ~/.config/frida-mobile-mcp/evidence) with mode 0600; opt out with FRIDA_MCP_EVIDENCE=0.
  • dump_module_memory only writes under the current directory, the OS temp directory or ~/.config/frida-mobile-mcp/dumps.
  • HTTP transport: loopback bind by default, token required off-loopback, Host/Origin validation.

See SECURITY.md for reporting vulnerabilities.

Troubleshooting

  • Version mismatch (unable to connect to remote frida-server, protocol/"unexpected message" errors, timeouts while adb devices works): frida-server on the device must be 17.x matching frida-node. Run frida-mobile-mcp doctor, then push the matching release (see Requirements).
  • "Timeout was reached" / app killed after spawn: Android kills a spawned app that stays suspended for more than ~10 s (Frida >= 17.6 cannot disable the launch timeout). explore_app resumes before class enumeration for this reason; with spawn_process, call resume_process promptly. If spawning is slow, launch the app first and attach (spawn: false / attach_process).
  • No Java messages right after hooking: Java hooks install inside Java.perform, which runs once the ART VM is up. Poll get_messages again after a few seconds. "Java is not available" means a native-only process; use hook_function, enumerate_exports or analyze_native_function.
  • Frida java bridge bundle not found: run npm run build:bridges (part of npm run build and pretest) or point FRIDA_MCP_BRIDGES_DIR at a directory with java.js/objc.js.
  • npm install fails downloading the frida prebuild: the frida package fetches its native binding in an install script; make sure install scripts are allowed (npm ci --foreground-scripts shows the download) and GitHub releases are reachable.
  • Two devices attached: set FRIDA_DEVICE_ID/--device, pass device to the tool, or select_device; with allowedDevices set an unlisted device yields DEVICE_NOT_FOUND.
  • SESSION_LOST / "script destroyed": the app crashed or was detached; get_status shows recent_detaches. Re-running the hook tool creates a fresh session; frequent crashes right after hooking point to anti-Frida checks (root_jailbreak_bypass, capture_tls({ anti_root: true })).
  • FRITAP_AGENT_UNAVAILABLE: pip install friTap, set FRITAP_AGENT_PATH, or allow the download (allow_download: true).

Development

npm ci --foreground-scripts   # installs deps and the frida prebuild
npm run build                 # build:bridges (rollup bundles of the Java/ObjC bridges) + tsc
npm run lint                  # tsc --noEmit
npm test                      # vitest (pretest rebuilds the bridges); device suites are skipped
npm run dev                   # tsc --watch

Device end-to-end tests opt in through environment variables:

FRIDA_MCP_E2E_DEVICE=emulator-5556 FRIDA_MCP_E2E_TARGET=com.example.rc4demo npx vitest run test/e2e
FRIDA_MCP_E2E_DEVICE=emulator-5556 npx vitest run test/fritap/capture-tls.e2e.test.ts

The older FRIDA_E2E=1, FRIDA_DEVICE_ID and FRIDA_E2E_TARGET names still work for the capture_tls test.

Commits follow Conventional Commits (feat:, fix:, docs:, ...); release-please opens the release PR, maintains CHANGELOG.md and the publish job in release.yml publishes to npm via OIDC trusted publishing. See CONTRIBUTING.md and AGENTS.md.

License

MIT

Reviews

No reviews yet

Be the first to review this server!