frida-mobile-mcp
Enables dynamic instrumentation of Android apps via Frida: spawning apps suspended, exploring and searching classes/methods, hooking Java methods, tracing calls, enumerating modules/exports/symbols, reading/writing/scanning memory, dumping module memory for Ghidra/IDA, bypassing SSL pinning (TrustManager, OkHttp, Conscrypt) and capturing TLS keys/plaintext.
Enables dynamic instrumentation of iOS apps via Frida (jailbroken or Frida Gadget): hooking Objective-C methods such as -[Class sel:], tracing, module and symbol enumeration on the ObjC runtime, memory analysis, SSL pinning bypass (SecTrust, ATS, BoringSSL) and TLS key/plaintext capture, plus optional UI automation.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@frida-mobile-mcpattach to com.example.app on the emulator and bypass its SSL pinning"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
frida-mobile-mcp
An MCP server that gives AI agents dynamic instrumentation of Android and iOS apps through Frida 17. It exposes 40 tools: high-level ones that manage devices, sessions and scripts for you (explore an app, hook a Java/ObjC/native method, trace calls, 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)Claude Code:
claude mcp add frida -- npx -y frida-mobile-mcpClaude 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.
Related MCP server: Frida MCP Server
Requirements
Node.js >= 22.12 (CI runs 22 and 24 on Linux, macOS and Windows).
npm installruns thefridapackage'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 doctorprints both versions and flags mismatches.Android: download the matching
frida-server-17.x.y-android-<arch>.xzfrom https://github.com/frida/frida/releases, thenxz -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 friTapforcapture_tls(otherwise the pinned agent is downloaded on first use), and network access fornpx -y @mobilenext/mobile-mcp@lateston firstmobile_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:bridgesbundlesfrida-java-bridgeandfrida-objc-bridgeintodist/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_scriptruns classic (non-module) scripts throughScript.evaluate, so aJava.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_scriptflags the staticModule.findExportByName/findBaseAddress/enumerateExports,Memory.readX/writeXand*Syncenumerators that throw on Frida 17 and suggests the Module-instance /NativePointerreplacements. Generated scripts getfindExport(lib, name)andhookNative(lib, name, callbacks)helpers from the agent preamble, and template options as__FRIDA_MCP__.options.analyze_native_functionusesProcess.findFunctionRangeand the Frida 17.12+ControlFlowGraph(with a linear-disassembly fallback reported inlimitations).
Tool reference
Tier 1: high-level tools
Tool | Description |
| Connected devices, active sessions (platform, script count, last activity), hooks, traces and recent detaches/crashes. Run first and after a session is lost. |
| Topic help: overview, hooking, tracing, memory, scripts, native, tls, mobile, examples, advanced, script_catalog. |
| Fingerprint libraries, frameworks and security mechanisms; returns recommended script targets. |
| Spawn an app suspended, instrument, resume; returns pid, platform, modules and a filtered class list. |
| Regex search over classes (and methods with |
| Hook Java ( |
| frida-trace style tracing of glob patterns ( |
| Run a custom script: classic JS (bridges injected), ES module JS/TS (compiled with the Frida Compiler) or a frida-compile bundle. |
| Syntax, type and Frida 17 removed-API check without a device. Use before |
| Run one of the 8 prebuilt scripts below; call without |
| One-click pinning bypass (Android: TrustManager, OkHttp CertificatePinner, Conscrypt; iOS: SecTrust, ATS, BoringSSL). |
| friTap: TLS session keys (NSS key log) and optional decrypted plaintext / synthetic pcap for OpenSSL/BoringSSL, Conscrypt, NSS, GnuTLS, wolfSSL, mbedTLS, Secure Transport and more. |
| Read up to 4 MB at any address notation; returns hex plus absolute address and |
| Write hex bytes to memory. Disabled unless |
| Byte-pattern scan ( |
| Buffered hook invocations, trace hits, |
| Remove all hooks, scripts and traces on a target and detach. |
| Unload a single script (hook, trace or custom) from a session while keeping it attached. |
| Gateway to mobile-mcp UI automation (screenshot, elements, tap, swipe, type, launch app, list apps). |
Tier 2: advanced primitives
Tool | Description |
| Local, USB and remote Frida devices (frida-ls-devices). |
| Select the active device by ID, type or remote host. |
| OS version, architecture and system parameters. |
| Running processes (frida-ps). |
| Installed and running applications. |
| Foreground application. |
| Spawn suspended for early instrumentation; resume with |
| Attach to a running process by PID or name. |
| Resume a suspended process. |
| Kill a process. |
| Detach a session and unload its scripts. |
| Sessions managed by this server. |
| Loaded modules with name, base, end, size, path; regex |
| Exports of a module, paginated. |
| Imports of a module with the providing module, paginated. |
| Symbols including non-exported/debug symbols; regex filter and paging inside the agent (Linux, Android, iOS, macOS). |
| Translate |
| Function range, basic blocks and edges, first instructions; addresses as absolute and |
| Dump a module base-relative to a host file (under cwd, the temp dir or |
| Threads with id, name, state, current pc as |
| Low-level |
| Remove a hook by ID. |
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) and three workflow prompts (explore_app, security_audit, trace_functionality).
Prebuilt scripts
Script | Purpose |
| Bypass certificate pinning (TrustManager, OkHttp, Conscrypt, WebView; SecTrust, ATS, BoringSSL, AFNetworking) |
| Bypass root/jailbreak detection (Java, SystemProperties, native fopen/access/stat, canOpenURL, sysctl) |
| List loaded Java/ObjC classes with a regex filter, optionally with methods |
| Generic method hook (Java/ObjC methods or a native |
| javax.crypto, CommonCrypto and OpenSSL calls |
| Sockets, DNS, UDP and TLS SSL_read/SSL_write (plaintext bytes with |
| iOS Keychain and Android SharedPreferences access |
| File I/O and SQLite |
Address notation and evidence envelope
Every tool that takes or returns a native address uses one vocabulary:
Form | Meaning | Example |
| export or ELF/Mach-O symbol |
|
| offset from the module base (Ghidra/IDA RVA); decimal |
|
| absolute runtime address |
|
| global export searched across all modules |
|
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. 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 static tools
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.
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 3000Streamable 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,
"allowedDevices": [],
"maxSessions": 4,
"sessionTimeoutMinutes": 30,
"maxMessageBuffer": 1000,
"auditLogPath": "~/.config/frida-mobile-mcp/audit.jsonl",
"mobileMcp": { "enabled": true, "command": "npx", "args": ["-y", "@mobilenext/mobile-mcp@latest"] },
"rateLimits": { "scriptsPerMinute": 10, "memoryReadsPerMinute": 60, "sessionsPerMinute": 5 }
}Variable | Default | Description |
| first USB device | Device to use; same as |
| unset |
|
| unset |
|
| unset |
|
| unset |
|
| unset | Bearer token for the HTTP transport; same as |
|
|
|
|
| Truncation limit for a single tool response |
| Frida default |
|
|
| Directory with the bundled |
|
| Project dir the Frida Compiler uses for ES module scripts |
| unset | Path to a |
|
| friTap tag to download when no local agent is found |
Security guardrails
execute_scriptand customhook_functionhandler bodies are refused withCUSTOM_SCRIPTS_DISABLEDunlessallowCustomScriptsis on; prebuilt scripts and typed hook tools never need it.write_memoryis refused withMEMORY_WRITE_DISABLEDunlessmemoryWriteEnabledis on.allowedDevicesrestricts 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);maxSessionsandsessionTimeoutMinutescap concurrent and idle sessions.Every tool call is appended to the JSONL audit log at
auditLogPathwith itsevidence_id.dump_module_memoryonly 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 whileadb devicesworks): frida-server on the device must be 17.x matching frida-node. Runfrida-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_appresumes before class enumeration for this reason; withspawn_process, callresume_processpromptly. 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. Pollget_messagesagain after a few seconds. "Java is not available" means a native-only process; usehook_function,enumerate_exportsoranalyze_native_function.Frida java bridge bundle not found: runnpm run build:bridges(part ofnpm run buildandpretest) or pointFRIDA_MCP_BRIDGES_DIRat a directory withjava.js/objc.js.npm installfails downloading the frida prebuild: thefridapackage fetches its native binding in an install script; make sure install scripts are allowed (npm ci --foreground-scriptsshows the download) and GitHub releases are reachable.Two devices attached: set
FRIDA_DEVICE_ID/--device, passdeviceto the tool, orselect_device; withallowedDevicesset an unlisted device yieldsDEVICE_NOT_FOUND.SESSION_LOST/ "script destroyed": the app crashed or was detached;get_statusshowsrecent_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, setFRITAP_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 --watchDevice 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_E2E=1 FRIDA_DEVICE_ID=emulator-5556 npx vitest run test/fritap/capture-tls.e2e.test.tsCommits 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
This server cannot be deployed
Maintenance
Related MCP Connectors
Remote MCP for Android CLI agent build gate, structured receipts, audit logs, and reviewer-ready evi
Capture, inspect & debug HTTPS traffic across iOS, Android, browsers & backends — 304 MCP tools.
Search and inspect source-pinned agent skills, plugins and tools through a free public MCP.
61Security scanner for MCP servers. Detect vulnerabilities, prompt injection, and tool poisoning.
Related MCP Servers
- AlicenseBqualityNot gradedmaintenanceEnables AI systems to interact with mobile and desktop applications through Frida's dynamic instrumentation capabilities. Provides process management, device control, JavaScript REPL execution, and script injection for runtime analysis and reverse engineering.142MIT
- AlicenseBqualityCmaintenanceA comprehensive MCP server that exposes Frida's dynamic instrumentation toolkit to AI agents for process management, script injection, and memory operations. It provides over 50 tools to interact with local and mobile devices, enabling advanced capabilities like function hooking and memory analysis.55MIT
- FlicenseAqualityFmaintenanceAn AI-driven Android dynamic analysis tool that enables AI models to perform automated reverse engineering by controlling Frida. It provides capabilities to inject scripts, manage application processes, and analyze real-time execution data through the Model Context Protocol.1070-
- AlicenseNot gradedqualityDmaintenanceExposes Frida dynamic instrumentation capabilities to AI assistants, enabling process management, memory access, and function hooking through structured tool calls.MIT