Skip to content

Commit a018369

Browse files
authored
Merge pull request #3 from mobilehackinglab/small_improvements
Pagination + new tool to search classes and small improvements
2 parents 39ead09 + d805ae0 commit a018369

File tree

5 files changed

+213
-61
lines changed

5 files changed

+213
-61
lines changed

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
## ⚙️ Jadx MCP Plugin — Decompiler Access for Claude via MCP
22

3-
This project provides a [Jadx](https://github.com/skylot/jadx) plugin written in **Java**, which exposes the **Jadx API over HTTP** — enabling live interaction through [Claude](https://www.anthropic.com/index/introducing-claude) via the [Model Context Protocol (MCP)](https://modelcontextprotocol.io/). A lightweight [FastMCP](https://github.com/pacocoursey/fastmcp) adapter in Python acts as a bridge between Claude and the plugin.
3+
This project provides a [Jadx](https://github.com/skylot/jadx) plugin written in **Java**, which exposes the **Jadx API over HTTP** — enabling live interaction through MCP clients like [Claude](https://www.anthropic.com/index/introducing-claude) via the [Model Context Protocol (MCP)](https://modelcontextprotocol.io/). A lightweight [FastMCP](https://github.com/modelcontextprotocol/python-sdk?tab=readme-ov-file#resources) adapter in Python acts as a bridge between Claude and the plugin. This enables intelligent navigation and automation of reverse engineering workflows, ideal for AI-assisted security analysis of Android apps.
44

55
---
66

@@ -70,8 +70,9 @@ After restart it should look like this:
7070
| Tool | Description |
7171
|-----------------------|---------------------------------------|
7272
| `list_all_classes` | Get all decompiled class names |
73+
| `search_class_by_name` | Find classes matching a string |
7374
| `get_class_source` | Get full source of a given class |
74-
| `search_method_by_name` | Find methods matching a string |
75+
| `search_method_by_name` | Find methods matching a string |
7576
| `get_methods_of_class` | List all method names in a class |
7677
| `get_fields_of_class` | List all field names in a class |
7778
| `get_method_code` | Extract decompiled code for a method |
@@ -126,5 +127,5 @@ This project is maintained by [Mobile Hacking Lab](https://github.com/mobilehack
126127
## 🧩 Credits
127128

128129
- [Jadx](https://github.com/skylot/jadx)
129-
- [FastMCP](https://github.com/jlowin/fastmcp)
130+
- [FastMCP](https://github.com/modelcontextprotocol/python-sdk)
130131
- [Claude by Anthropic](https://www.anthropic.com)

fastmcp_adapter.py

Lines changed: 57 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
1-
from fastmcp import FastMCP
1+
from mcp.server.fastmcp import FastMCP
22
import requests
33
from requests.exceptions import ConnectionError
44
import sys
55

6+
# Create the MCP adapter with a human-readable name
67
mcp = FastMCP("Jadx MCP Server")
78

9+
# Address of the Jadx MCP plugin's HTTP server
810
MCP_SERVER = "http://localhost:8085"
911

10-
def invoke_jadx(tool, parameters={}):
12+
def invoke_jadx(tool: str, parameters: dict = {}) -> dict:
13+
"""
14+
Internal helper to send a tool request to the Jadx MCP HTTP server.
15+
"""
1116
try:
1217
resp = requests.post(f"{MCP_SERVER}/invoke", json={"tool": tool, "parameters": parameters})
1318
resp.raise_for_status()
@@ -20,38 +25,75 @@ def invoke_jadx(tool, parameters={}):
2025
except Exception as e:
2126
raise RuntimeError(f"Unexpected error: {str(e)}")
2227

28+
29+
@mcp.tool()
30+
def list_all_classes(limit: int = 250, offset: int = 0) -> dict:
31+
"""
32+
Returns a paginated list of class names.
33+
34+
Params:
35+
- limit: Max number of classes to return (default 250)
36+
- offset: Starting index of class list
37+
"""
38+
return invoke_jadx("list_all_classes", {"limit": limit, "offset": offset})
39+
40+
2341
@mcp.tool()
24-
def list_all_classes() -> list:
25-
result = invoke_jadx("list_all_classes")
26-
return result
42+
def search_class_by_name(query: str) -> dict:
43+
"""Search for class names that contain the given query string (case-insensitive)."""
44+
return invoke_jadx("search_class_by_name", {"query": query})
45+
2746

2847
@mcp.tool()
2948
def get_class_source(class_name: str) -> str:
30-
result = invoke_jadx("get_class_source", {"class_name": class_name})
31-
return result
49+
"""
50+
Returns the full decompiled source code of a given class.
51+
"""
52+
return invoke_jadx("get_class_source", {"class_name": class_name})
53+
3254

3355
@mcp.tool()
3456
def search_method_by_name(method_name: str) -> str:
35-
result = invoke_jadx("search_method_by_name", {"method_name": method_name})
36-
return result
57+
"""
58+
Searches for all methods matching the provided name.
59+
Returns class and method pairs as string.
60+
"""
61+
return invoke_jadx("search_method_by_name", {"method_name": method_name})
62+
3763

3864
@mcp.tool()
3965
def get_methods_of_class(class_name: str) -> list:
40-
result = invoke_jadx("get_methods_of_class", {"class_name": class_name})
41-
return result
66+
"""
67+
Returns all method names declared in the specified class.
68+
"""
69+
return invoke_jadx("get_methods_of_class", {"class_name": class_name})
70+
4271

4372
@mcp.tool()
4473
def get_fields_of_class(class_name: str) -> list:
45-
result = invoke_jadx("get_fields_of_class", {"class_name": class_name})
46-
return result
74+
"""
75+
Returns all field names declared in the specified class.
76+
"""
77+
return invoke_jadx("get_fields_of_class", {"class_name": class_name})
78+
4779

4880
@mcp.tool()
4981
def get_method_code(class_name: str, method_name: str) -> str:
50-
result = invoke_jadx("get_method_code", {"class_name": class_name, "method_name": method_name})
51-
return result
82+
"""
83+
Returns only the source code block of a specific method within a class.
84+
"""
85+
return invoke_jadx("get_method_code", {
86+
"class_name": class_name,
87+
"method_name": method_name
88+
})
89+
5290

5391
@mcp.resource("jadx://tools")
5492
def get_tools_resource() -> dict:
93+
"""
94+
Fetches the list of all available tools and their descriptions from the Jadx plugin.
95+
Used for dynamic tool discovery.
96+
"""
5597
try:
5698
resp = requests.get(f"{MCP_SERVER}/tools")
5799
resp.raise_for_status()

plugin/build.gradle

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ plugins {
44
}
55

66
group = 'jadx.plugins'
7-
version = '1.0'
7+
version = '1.1'
88

99
repositories {
1010
mavenCentral()
@@ -29,7 +29,7 @@ jar {
2929
attributes(
3030
'Jadx-Plugin': 'true',
3131
'Jadx-Plugin-Class': 'com.mobilehackinglab.jadxplugin.McpPlugin',
32-
'Jadx-Plugin-Version': '1.0.0',
32+
'Jadx-Plugin-Version': '1.1.0',
3333
'Jadx-Plugin-Id': 'jadx-mcp-plugin',
3434
'Jadx-Plugin-Description': 'Exposes Jadx info over HTTP',
3535
'Jadx-Plugin-Author': 'Mobile Hacking Lab'
@@ -47,6 +47,6 @@ jar {
4747

4848
shadowJar {
4949
archiveBaseName = 'jadx-mcp-plugin'
50-
archiveVersion = '1.0.0'
50+
archiveVersion = '1.1.0'
5151
mergeServiceFiles()
5252
}

0 commit comments

Comments
 (0)