1013503897/jadx-headless-mcp

▲ 6 stars today★ 79⑂ 11

Headless MCP server for Android APK static analysis, built directly on jadx-core. No JADX GUI required.

About 1013503897/jadx-headless-mcp

1013503897/jadx-headless-mcp is an open-source project on GitHub, mainly written in Kotlin. Headless MCP server for Android APK static analysis, built directly on jadx-core. No JADX GUI required. It currently holds 79 stars and 11 forks with 0 open issues, and was last pushed on an unknown date (repository created unknown).

Project Overview

AI Homed tracks it on the Today's Trending board, currently at rank #84 with 6 new stars today.

GitHub Repository Details

Repository 1013503897/jadx-headless-mcp · default branch - · size 0 KB · watchers 0 · source: GitHub REST API and repository README

README

jadx-headless-mcp

English | 简体中文

Headless MCP server for Android APK static analysis, built directly on jadx-core. No JADX GUI required, no Python adapter, no plugin to install — just one JVM process speaking MCP over stdio.

Why

jadx is two parts: the jadx-core decompiler engine, and a GUI wrapped around it for a human to click through by hand.

Give a capable LLM direct access to jadx-core and the GUI loses its reason to exist. The model walks the same class tree, resolves the same xrefs, reads the same source — headless and scriptable. As models get stronger, Java-layer reverse engineering increasingly runs end to end from the model, without a reverse engineer driving it by hand.

So this server drops the GUI and exposes jadx-core as ~26 MCP tools over stdio.

Tools

Session management

| Tool | Description | |---|---| | status | Whether an APK is loaded; path, class/resource counts, load duration | | load_apk | Load an APK / DEX / JAR (replaces any current one) | | unload_apk | Release the loaded APK and free memory |

Static analysis (require a loaded APK)

| Tool | Description | |---|---| | get_app_info | Package name, version, minSdk/targetSdk, permissions | | get_android_manifest | Full decoded AndroidManifest.xml | | get_main_activity_class | LAUNCHER activity FQN | | list_classes | Paginated class FQN list | | search_classes_by_keyword | Substring search over class FQNs | | get_class_source | Decompiled Java source. Auto-falls back to smali when jadx hits anti-decompile stubs (marker // [jadx java-decompile failed → smali]; smali_fallback=false to opt out). Resolves inner/$Companion names. | | get_class_summary | Class skeleton (method signatures, fields, inner-class names) — no method bodies | | get_smali_of_class | Smali disassembly. Pageable via offset (byte offset into full smali); header reports total_bytes/next_offset | | get_methods_of_class | Method signatures | | get_method_by_name | Java source of a single method; same smali fallback as get_class_source | | get_method_body | One method as Java-if-possible-else-smali, in a JSON envelope (mode, fell_back, markers); handles overloads | | get_method_smali | Smali of a single method (all overloads), sliced from the class disassembly | | get_inner_classes | Inner/nested classes with both dotted full_name and raw $-joined raw_name | | resolve_class | Resolve an inner/$Companion/fuzzy class name to its exact FQN, or list candidates | | get_fields_of_class | Field list with types | | search_method_by_name | Global method search (includes inner-class methods) | | get_xrefs_to_class | References to a class | | get_xrefs_to_method | References to a method | | get_xrefs_to_field | References to a field | | get_strings | String resources with optional filter | | list_resource_files | Resource file names | | get_resource_file | Resource file content (text or base64) |

Build

Requires JDK 17+.

./gradlew installDist

Output: build/install/jadx-headless-mcp/bin/jadx-headless-mcp (and .bat on Windows).

For a single portable fat jar:

./gradlew shadowJar

build/libs/jadx-headless-mcp--all.jar

No build needed? Prebuilt artifacts (fat jar + distribution zip) are attached to every GitHub Release — download one and point your MCP config at it directly.

Run

Empty start (load an APK later via load_apk tool):

./build/install/jadx-headless-mcp/bin/jadx-headless-mcp

Or eager-load on startup:

./build/install/jadx-headless-mcp/bin/jadx-headless-mcp \
  --apk /path/to/app.apk \
  --max-source-bytes 200000

The server speaks MCP over stdio. Logs go to stderr.

Install as a Claude Code plugin

This repo is also a Claude Code plugin — the easiest way to install for Claude Code, no JSON editing and no manual build. It needs JDK 17+ on PATH; on first start it downloads the released fat jar (SHA-256 verified) and caches it.

/plugin marketplace add 1013503897/jadx-headless-mcp
/plugin install jadx-headless@jadx-headless-mcp

This bundles the MCP server plus the /jadx-headless:open-apk skill. See PLUGIN.md for how it works, local development (claude --plugin-dir .), releasing, and community-marketplace submission. If you'd rather wire the server up by hand (or use another client), use the manual configuration below.

MCP client configuration

jadx-headless is a standard stdio MCP server, so any MCP-capable client can drive it — Claude Code, Claude Desktop, Cursor, Windsurf, Cline, Roo Code, VS Code / Copilot, LM Studio, Zed, Codex, Gemini CLI, and others. Claude Code has the smoothest path; the rest take one small config entry — see Other MCP clients.

Claude Code

Quickest: register with the CLI

One command, no JSON editing. -s user writes to the global ~/.claude.json; the default local scope only applies to the current project:

# installDist launcher
claude mcp add jadx-headless -s user -- C:/tools/jadx-headless-mcp/bin/jadx-headless-mcp.bat

...or the portable fat jar (single file; needs java on PATH)

claude mcp add jadx-headless -s user -- java -jar C:/tools/jadx-headless-mcp--all.jar

Then ask the AI to call load_apk with the path you want to analyze. Use unload_apk to free memory or switch to a different one — no config edit needed.

Or edit the config by hand

Register one entry, swap APKs at runtime:

{
  "mcpServers": {
    "jadx-headless": {
      "command": "C:/tools/jadx-headless-mcp/bin/jadx-headless-mcp.bat"
    }
  }
}

To point at the portable fat jar instead:

{
  "mcpServers": {
    "jadx-headless": {
      "command": "java",
      "args": ["-jar", "C:/tools/jadx-headless-mcp--all.jar"]
    }
  }
}

If you only ever analyze a single APK and want it ready immediately, append the APK path via args:

{
  "mcpServers": {
    "jadx-headless": {
      "command": "C:/tools/jadx-headless-mcp/bin/jadx-headless-mcp.bat",
      "args": ["--apk", "C:/work/current.apk"]
    }
  }
}
Note: java -jar skips the launcher's default JVM args (e.g. -XX:MaxRAMPercentage=60). stdout stays clean either way — slf4j-simple logs to stderr and Main.kt redirects System.out to stderr — but if you need a memory ceiling, pass it yourself via JAVA_OPTS / -XX. The installDist launcher keeps those defaults.

Other MCP clients

Point the client at the same launcher (or java -jar the fat jar); only the surrounding config format differs. In every case command is the launcher (or java), and for the fat jar args is ["-jar", "-all.jar"]. --apk / --max-source-bytes and the load_apk / unload_apk tools behave identically no matter which client drives it.

mcpServers JSON — the de-facto standard, accepted by Claude Desktop, Cursor, Windsurf, Cline, Roo Code, LM Studio, Gemini CLI, and most others:

{
  "mcpServers": {
    "jadx-headless": {
      "command": "C:/tools/jadx-headless-mcp/bin/jadx-headless-mcp.bat"
    }
  }
}

Only the file it goes in differs — e.g. Claude Desktop claude_desktop_config.json, Cursor .cursor/mcp.json, Windsurf ~/.codeium/windsurf/mcp_config.json. Check your client's MCP docs for the exact path.

VS Code / GitHub Copilot uses servers + type (not mcpServers), in .vscode/mcp.json:

{
  "servers": {
    "jadx-headless": {
      "type": "stdio",
      "command": "C:/tools/jadx-headless-mcp/bin/jadx-headless-mcp.bat"
    }
  }
}

TOML-based CLIs (Codex, Grok, …) use an mcp_servers table:

[mcp_servers.jadx-headless]
command = "C:/tools/jadx-headless-mcp/bin/jadx-headless-mcp.bat"
args = []

Remote mode (--transport http)

By default the server speaks stdio, so the MCP client spawns it as a local child process — client and jadx live on the same machine. To split them (client on machine B, jadx and the APK on machine A), run the server with the Streamable HTTP transport and point a remote MCP client at the URL:

# on machine A (where jadx runs and the APK lives)
./bin/jadx-headless-mcp --transport http --host 0.0.0.0 --port 8080 --allowed-host a.example.com

| Flag | Default | Meaning | |---|---|---| | --transport | stdio | serve Streamable HTTP instead of stdio | | --host | 127.0.0.1 | bind address; use 0.0.0.0 to accept connections from other machines | | --port | 8080 | listen port | | --path

| /mcp | endpoint path (serves POST/GET/DELETE) | | --allowed-host | — | extra Host header value accepted by the DNS-rebinding check (repeatable). Pass the hostname/IP clients use to reach machine A | | --no-dns-rebinding-protection | off | disable Host/Origin validation (trusted networks / behind a reverse proxy only) |

The endpoint is http://: (default http://127.0.0.1:8080/mcp). Point any Streamable-HTTP-capable MCP client at it — e.g. Claude Code:

claude mcp add --transport http jadx-headless http://a.example.com:8080/mcp

The APK always lives on the jadx host. load_apk resolves its path with File(path) on the machine running the server (A) — a remote client only sends a path string that must be valid on A. Copy the APK to A first, then call load_apk with the A-side path. It's still one APK per process; multiple HTTP sessions share the single loaded APK.

Security:

Architecture

Claude Code  ──stdio | Streamable-HTTP JSON-RPC──>  jadx-headless-mcp (JVM)
                                          │
                                          ├── MCP Kotlin SDK (stdio / Ktor CIO HTTP server)
                                          │
                                          └── SessionHolder
                                                 │  (Mutex-serialized load/unload)
                                                 └── JadxSession
                                                        └── JadxDecompiler (jadx-core)

Lazy decompilation: only get_class_source and get_smali_of_class (and get_method_by_name / code search) trigger per-class decompilation. Index building at startup is metadata-only.

Important: max_bytes truncates the response after jadx finishes materializing the class — it does not stop a slow decompile early. Fat obfuscated classes (e.g. large ViewModels) previously could block the whole MCP process for tens of minutes until the client’s multi-hour tool ceiling. As of the decompile-timeout fix:

Memory tuning

The launcher sets -XX:MaxRAMPercentage=60.0 by default. Override via JAVA_OPTS:

JAVA_OPTS="-Xmx8g" ./bin/jadx-headless-mcp

Upstream tracking

| Dependency | Mechanism | |---|---| | io.github.skylot:jadx-core and friends | Dependabot weekly (opens PRs grouped under "jadx"); CI verifies the build still passes | | io.modelcontextprotocol:kotlin-sdk | Dependabot weekly (grouped under "mcp-kotlin-sdk") | | org.jetbrains.kotlinx:* | Dependabot weekly (grouped under "kotlinx") | | GitHub Actions versions | Dependabot monthly |

Related but not auto-synced (different architecture; manual watch only):

If those projects ship a new tool worth porting, file an issue here.

Acknowledgements

License

Apache-2.0.

GitHub Stars & Activity

79Stars
11Forks
0Open issues
KotlinLanguage

GitHub Popularity

GitHub stars79
Forks11
Open issues0
Primary languageKotlin
License-
Stars gained today6
Created-
Last pushed-

Trending History

Daily boardrank #84 · ▲ 6 stars

Related AI Projects

1

obra / superpowers

Shell★ 299,745⑂ 26,770▲ 688 stars
→
2

mattpocock / skills

Shell★ 292,625⑂ 24,533▲ 1,647 stars
→
3

affaan-m / ECC

JavaScript★ 280,194⑂ 41,673▲ 1,015 stars
→
4

morluto / rea

TypeScript★ 266,499⑂ 66,930▲ 32,282 stars
→
5

anomalyco / opencode

TypeScript★ 213,868⑂ 28,699▲ 375 stars
→
6

harry0703 / MoneyPrinterTurbo

Python★ 131,531⑂ 20,689▲ 475 stars
→
7

JuliusBrussee / caveman

Go★ 112,392⑂ 6,516▲ 530 stars
→
8

paperclipai / paperclip

TypeScript★ 102,635⑂ 17,188▲ 584 stars
→

More AI Rankings