jadx-mcp
Health Uyari
- No license — Repository has no license file
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Low visibility — Only 8 GitHub stars
Code Uyari
- Code scan incomplete — No supported source files were scanned during light audit
Permissions Gecti
- Permissions — No dangerous permissions requested
Bu listing icin henuz AI raporu yok.
MCP (Model Context Protocol) server as a jadx-gui plugin. Lets an AI client (Claude Code, Claude Desktop, or any MCP client) analyze the app currently loaded in jadx-gui.
jadx-mcp
MCP (Model Context Protocol) server as a jadx-gui plugin. Lets an AI client (Claude Code, Claude Desktop, or any MCP client) analyze the app currently loaded in jadx-gui: list/search classes, fetch decompiled Java or smali, per-method source, manifest components (main activity, application package), resources and strings.xml, cross-references (class/method/field level), and renames (class/method/field/package/variable) for deobfuscation loops.
Native implementation on the official MCP Java SDK - no Python shim, no external process. Server runs inside jadx-gui over streamable HTTP; host and port are configurable in the plugin's settings dialog (127.0.0.1:8090 by default).
Requirements
- jadx-gui 1.5.6 (plugin API target).
- jadx-gui running on Java 17+ (the MCP SDK and the plugin jar are Java 17 bytecode). The
jadx-gui-x.y.z-with-jre-winbundle ships a recent JRE and works out of the box. If you launchjadx-gui.batwith a system JDK, checkjava -versionfirst: on an older JVM jadx cannot load the plugin (UnsupportedClassVersionErrorin the jadx log). - To build: JDK 17+ and Gradle (or use the Gradle wrapper).
Launching the right JVM (Windows)
jadx-gui.exe(with-JRE bundle) uses its bundled JRE - always Java 17+, use this.jadx-gui.batuses the systemJAVA_HOME. If yours is older than 17, point it at a recent JDK first:
$env:JAVA_HOME = "<custom_dir_location>"
jadx-gui.bat
The plugin is Java 17 bytecode by design: the official MCP Java SDK (2.x) is records-based and requires Java 17+, and mixing bytecode levels caused classloader issues in jadx's plugin loader. Keep jadx-gui on a JVM >= 17.
Build
Prerequisites: JDK 17+ (toolchain pinned to 21, any newer JDK works) and Gradle 9.x on the PATH. jadx-core and slf4j are compileOnly - no jadx install needed to build.
PowerShell:
cd jadx-mcp
# if your default JAVA_HOME is not a JDK 17+, point Gradle at one:
$env:JAVA_HOME = "<custom_dir_location>"
gradle jar # fat jar -> build/libs/jadx-mcp-0.1.0.jar
gradle smoke # headless e2e check: loads a real jar into jadx, starts the server on an
# ephemeral port, runs raw JSON-RPC calls (initialize, tools/list for all
# 27 tools, status, get_all_classes, get_class_source, get_method_by_name,
# xrefs, renames, non-APK error paths) and stops it; prints "SMOKE OK"
What the jar contains:
- Own classes (
jadxmcp/*), compiled with--release 17. - MCP Java SDK 2.0.1 + Jackson 3 + Reactor + embedded Jetty 12 (ee11, servlet 6.1), unpacked into one fat jar (no shadow plugin; signatures and
module-info.classstripped). Jetty instead of Tomcat because the jadx with-JRE bundle ships a stripped jlink runtime withoutjava.management, which Tomcat requires. META-INF/services/jadx.api.plugins.JadxPlugin— the ServiceLoader entry jadx picks up.- Transitive
org.slf4j:slf4j-apiis excluded so jadx's own slf4j binding wins.
Build layout:
src/main/java/jadxmcp/ JadxMcpPlugin (entry), McpServerManager (Jetty + MCP lifecycle),
JadxTools (all MCP tools), Settings (host+port persistence)
src/main/resources/META-INF/services/jadx.api.plugins.JadxPlugin
src/test/java/jadxmcp/ SmokeTest (run by gradle smoke)
Gradle details worth knowing if you touch the build:
gradle clean jar smokefor a from-scratch verify.- Toolchain comes from
java.toolchaininbuild.gradle.kts— Gradle auto-downloads JDK 21 ifJAVA_HOMEdoesn't provide it; settingJAVA_HOMEjust makes it instant. - To bump versions:
val jadxVersion(plugin API target) and themcp/jetty-ee11-servletcoordinates inbuild.gradle.kts.requiredJadxVersioninJadxMcpPluginmust match the jadx line you target. gradle smokeLimitedruns the same smoke test restricted to the jadx with-JRE module set (nojava.management, nojdk.unsupported) — use it after any dependency change to make sure the server still loads in the stripped runtime.
Install
jadx plugins --install-jar jadx-mcp-0.1.0.jar
or copy the jar to ~/.jadx/plugins/ and restart jadx-gui. If an older version is installed, delete it first (same plugin id, duplicate jars in the plugins dir).
Use
- jadx-gui → open an APK/DEX/JAR.
- Menu Plugins → jadx-mcp: Settings... opens the single settings dialog:
- Host (default
127.0.0.1) and Port (default8090) — saved to~/.jadx/jadx-mcp.propertieson Start. - Start starts (or restarts with new host/port) the server; Stop stops it; the status line shows the running URL. No need to close the dialog: status updates live.
- Warning: binding a non-loopback host (e.g.
0.0.0.0or a LAN IP) exposes the server to the network — there is no authentication.
- Host (default
- Register with your MCP client (URL from the status line).
Claude Code (one-shot, no config editing):
claude mcp add --transport http jadx-mcp http://localhost:8090/mcp
With a non-default host/port, use the URL from the status dialog. Scope flag as needed: --scope project writes .mcp.json in the repo, default is user-local.
Claude Desktop - edit claude_desktop_config.json (Settings → Developer → Edit Config) and add under mcpServers:
{
"mcpServers": {
"jadx-mcp": {
"type": "http",
"url": "http://localhost:8090/mcp"
}
}
}
Restart Claude Desktop after editing. Both clients speak streamable HTTP, which is what the plugin serves.
- Stop with the Stop button in the same dialog (server also stops on jadx exit).
Smoke test (no client)
PowerShell:
$h = @{ Accept = "application/json, text/event-stream" }
$b = '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"smoke","version":"0"}}}'
$r = Invoke-WebRequest -Method Post http://localhost:8090/mcp -ContentType "application/json" -Headers $h -Body $b
$r.Headers["mcp-session-id"] # session id -> server works
Tools
27 tools, all validated against a JSON schema by the SDK. Paginated tools take optional offset/limit (default 50, max 500).
| Tool | Notes |
|---|---|
status |
app loaded, class/package/resource counts, manifest package |
| Classes | |
get_all_classes |
paginated, optional package prefix filter |
search_classes |
class name contains, case-insensitive |
get_class_source |
decompiled Java source (original or alias name) |
get_smali_of_class |
DEX disassembly |
search_classes_by_keyword |
full-text over decompiled code (class:line:source matches), paginated; expensive on large apps |
fetch_current_class |
class the analyst is viewing in jadx-gui (node under caret), with source |
| Methods / fields | |
get_method_by_name |
single method source; signature fragment disambiguates overloads |
search_method_by_name |
method name contains across all classes, paginated |
get_methods_of_class |
methods with flags, signatures, return types |
get_fields_of_class |
fields with flags and types |
| Manifest (APK) | |
get_android_manifest |
decoded AndroidManifest.xml |
get_manifest_component |
one component type (activity, activity-alias, service, receiver, provider), optional name filter |
get_main_activity_class |
MAIN/LAUNCHER activity, with source |
get_main_application_classes_names |
class names in the manifest application package, paginated |
get_main_application_classes_code |
their full sources, paginated (default 10 per page — token heavy) |
| Resources | |
get_strings |
decoded res/values/strings.xml |
get_all_resource_file_names |
paginated, optional path filter |
get_resource_file |
decoded content of one resource |
| Renames (mutate the jadx project) | |
rename_class |
short new name, GUI refresh included |
rename_method |
signature fragment disambiguates overloads |
rename_field |
|
rename_package |
full new package name, cascades to all classes in it |
rename_variable |
local var in a method; session-local (not persisted to saved jadx metadata) |
| Xrefs | |
xrefs_to_class |
all references to the class, paginated |
xrefs_to_method |
references + override-related methods, paginated |
xrefs_to_field |
methods accessing the field, paginated |
Domain errors (class not found, no app loaded, binary resource, ambiguous overload) come back as isError tool results so the LLM can self-correct.
Security
- Binds
127.0.0.1by default; Origin/Host allowlist is built from the configured host. - Origin/Host header validation (
http://localhost:*/localhost:*) to block DNS-rebinding and cross-origin requests from web pages. - No auth: keep it on localhost. Do not port-forward.
Known limits
- No
get_selected_text— the jadx plugin API (1.5.6JadxGuiContext) exposes the node under the caret, not the raw text selection.fetch_current_classis the closest equivalent. - No
debug_get_*tools (stack frames, threads, variables) — the plugin API has no debugger access. Use the jadx-gui debugger UI directly. rename_variableis session-local: the new name shows in reloaded code but is not written to saved jadx metadata (.jadxfiles), unlike the class/method/field/package renames which go through the standard deobfuscation alias system.- Comments and headless (jadx-cli) operation are not implemented.
Yorumlar (0)
Yorum birakmak icin giris yap.
Yorum birakSonuc bulunamadi