🚀 Recaf MCP 插件
該插件可讓 AI 助手通過 模型上下文協議 (MCP) 控制 Recaf 4.x,實現反編譯、搜索、分析、編輯字節碼、編譯 Java 代碼、彙編/反彙編 JASM、比較類、修補工作區以及直接從 AI 工作流程中導出 Java 字節碼等功能。
中文文檔
🚀 快速開始
工作原理
該插件採用雙進程架構,將 AI 助手與 Recaf 強大的字節碼分析引擎連接起來:
┌─────────────────┐ STDIO / JSON-RPC ┌─────────────────┐ HTTP :9847 ┌─────────────────┐
│ AI 助手 │ ◄──────────────────────► │ MCP 服務器 │ ◄────────────────► │ Recaf 插件 │
│ (Claude Code, │ │ (獨立 JAR) │ │ (橋接服務器) │
│ Cursor 等) │ └─────────────────┘ └────────┬────────┘
└─────────────────┘ │
┌────────┴────────┐
│ Recaf 4.x │
│ (分析引擎) │
└─────────────────┘
- Recaf 插件(橋接服務器):在 Recaf 進程內運行。通過 CDI (Jakarta) 注入 Recaf 服務,並將其作為 HTTP 端點暴露在
localhost:9847 上。
- MCP 服務器:由 AI 客戶端啟動的獨立胖 JAR。通過 STDIO JSON-RPC 與 AI 通信,並通過 HTTP 將工具調用轉發到橋接服務器。
這種分離是必要的,因為 Recaf 作為一個 JavaFX 桌面應用程序運行,有自己的模塊系統,而 MCP 需要一個基於 STDIO 的進程,AI 客戶端可以生成和管理該進程。
✨ 主要特性
可用的 MCP 工具(共 25 個)
工作區管理
| 工具 |
描述 |
關鍵參數 |
open_jar |
打開一個 JAR、APK 或類文件進行分析 |
path — 絕對文件路徑。返回 workspaceId。 |
close_workspace |
關閉當前或指定的工作區 |
workspaceId(可選) — 按 ID 關閉 |
switch_workspace |
切換到之前打開的工作區 |
workspaceId — open_jar 返回的 ID |
list_workspaces |
列出所有已註冊的工作區 |
— |
list_classes |
列出帶有偏移量/限制分頁的類 |
filter、offset、limit |
get_class_info |
獲取類的詳細信息:字段、方法、接口 |
className |
class_outline |
輕量級類結構(無代碼,速度快) |
className |
read_file |
讀取非類文件(例如 MANIFEST.MF、配置文件) |
path、maxChars |
class_delete |
從工作區中刪除一個類 |
className |
分析
| 工具 |
描述 |
關鍵參數 |
decompile_class |
將類反編譯為 Java 源代碼 |
className |
search_code |
搜索字符串、引用或聲明 |
query、type、maxResults |
get_call_graph |
獲取方法調用圖(調用者和被調用者) |
className、methodName、depth |
get_inheritance |
獲取繼承層次結構(父類/子類) |
className、direction |
diff_classes |
比較兩個類或類與源代碼 |
className1、className2 或 source |
method_bytecode |
查看方法字節碼指令(操作碼、操作數、異常處理、局部變量) |
className、methodName、methodDesc |
編譯與彙編
| 工具 |
描述 |
關鍵參數 |
compile_java |
編譯 Java 源代碼並應用到工作區 |
className、source、targetVersion、debug |
disassemble_class |
將類反彙編為 JASM 文本 |
className、maxChars |
assemble_class |
彙編 JASM 源代碼並應用到工作區 |
className、source |
method_disassemble |
將單個方法反彙編為 JASM 文本 |
className、methodName、methodDesc、maxChars |
修改
| 工具 |
描述 |
關鍵參數 |
rename_symbol |
重命名類/字段/方法(更新所有引用) |
type、oldName、newName、className |
edit_bytecode |
添加/刪除/修改方法和字段 |
className、operation + 特定操作的參數 |
patch |
創建或應用工作區更改補丁 |
action(創建/應用)、patchJson |
導出
| 工具 |
描述 |
關鍵參數 |
export_mappings |
將重命名映射導出到文件 |
format、outputPath |
export_jar |
將工作區導出為 JAR 文件 |
outputPath |
export_source |
將反編譯的源代碼導出到目錄 |
outputDir、className(可選) |
MCP 資源
| URI |
描述 |
recaf://workspace |
當前工作區信息(JSON 格式) |
recaf://classes |
當前工作區的完整類列表(JSON 格式) |
📦 安裝指南
前提條件
- JDK 22+:Recaf 4.x 所需。確保 PATH 中的
java 指向 JDK 22 或更高版本。
- Recaf 4.x:此插件基於快照
d07958a5c7 構建。構建系統將自動下載它。
構建
git clone https://github.com/your-repo/recaf-mcp-plugin.git
cd recaf-mcp-plugin
./gradlew build
這將生成兩個 JAR 文件:
| 文件 |
用途 |
build/libs/recaf-mcp-plugin-1.2.0.jar |
Recaf 插件(在 Recaf 內加載,運行橋接服務器) |
build/mcp/recaf-mcp-server-1.2.0.jar |
MCP 服務器(獨立胖 JAR,由 AI 客戶端啟動) |
設置與使用
步驟 1:使用插件啟動 Recaf
選項 A:直接從項目運行(推薦用於開發)
./gradlew runRecaf
這將構建插件並自動加載它來啟動 Recaf。
選項 B:手動安裝
將 build/libs/recaf-mcp-plugin-1.2.0.jar 複製到 Recaf 的插件目錄:
| 操作系統 |
插件目錄 |
| macOS / Linux |
~/Recaf/plugins/ |
| Windows |
%APPDATA%/Recaf/plugins/ |
然後正常啟動 Recaf。
驗證:在 Recaf 的日誌面板中查找以下內容:
========================================
Recaf MCP 插件已啟用
橋接服務器在端口 9847 上運行
========================================
步驟 2:配置你的 AI 客戶端
Claude Code
在 ~/.claude.json 中添加以下內容:
{
"mcpServers": {
"recaf": {
"command": "java",
"args": ["-jar", "/absolute/path/to/build/mcp/recaf-mcp-server-1.2.0.jar"]
}
}
}
然後重啟 Claude Code。recaf 工具將出現在你的工具列表中。
Cursor
在 MCP 配置(設置 → MCP)中添加以下內容:
{
"mcpServers": {
"recaf": {
"command": "java",
"args": ["-jar", "/absolute/path/to/build/mcp/recaf-mcp-server-1.2.0.jar"]
}
}
}
其他支持 MCP 協議的客戶端
任何支持 MCP 協議的客戶端都可以使用此插件。將其配置為通過 java -jar 在 STDIO 上生成 MCP 服務器 JAR。
步驟 3:開始使用
當 Recaf 和你的 AI 客戶端都運行後,你可以自然地進行交互:
Open /path/to/target.jar and list all classes
Decompile the com/example/Main class
Search for all strings containing "password"
Show me the call graph for com/example/Main
Rename com/example/a to com/example/LoginManager
Compare com/example/A with com/example/B
Remove the method "unused" from com/example/Foo
Show me the bytecode instructions for com/example/Main.main
Disassemble com/example/Crypto into JASM
Compile this modified Java source back into the workspace
Read the META-INF/MANIFEST.MF file
Create a patch of all my changes
Export the modified JAR to /tmp/output.jar
💻 使用示例
逆向工程混淆的 JAR 文件
1. "Open /path/to/obfuscated.jar"
2. "List all classes" — 獲取包結構概述
3. "Decompile com/a/b/c" — 閱讀反編譯的源代碼
4. "Search for strings containing 'http'" — 查找網絡端點
5. "Get the call graph for com/a/b/c method d" — 瞭解控制流
6. "Rename com/a/b/c to com/app/NetworkManager" — 給它一個有意義的名稱
7. "Export mappings as TinyV1 to ./mappings.tiny" — 保存工作成果
8. "Export the modified JAR to ./cleaned.jar" — 保存結果
多 JAR 文件比較
1. "Open /path/to/v1.jar" — 打開第一個 JAR 文件,返回工作區 ID
2. "Open /path/to/v2.jar" — 打開第二個 JAR 文件,返回工作區 ID
3. "List workspaces" — 查看兩個工作區
4. "Switch to workspace v1-1" — 切換到第一個 JAR 文件的工作區
5. "Decompile com/example/Main" — 獲取 v1 版本的源代碼
6. "Switch to workspace v2-2" — 切換到第二個 JAR 文件的工作區
7. "Diff com/example/Main against the v1 source" — 比較版本差異
字節碼編輯
1. "Open /path/to/target.jar"
2. "Remove the method 'checkLicense' from com/app/Main"
3. "Add a public field 'debug' of type boolean to com/app/Config"
4. "Export the modified JAR to /tmp/patched.jar"
編譯與彙編往返操作
1. "Open /path/to/target.jar"
2. "Decompile com/app/Main" — 獲取 Java 源代碼
3. (修改源代碼)→ "Compile this Java source for com.app.Main" — 編譯並應用更改
4. "Decompile com/app/Main" — 驗證更改是否生效
5. "Disassemble com/app/Crypto" — 獲取 JASM 彙編文本
6. "Show me the bytecode for com/app/Crypto.encrypt" — 檢查方法指令
7. "Create a patch" — 以 JSON 格式保存所有修改
8. "Export the modified JAR to /tmp/patched.jar"
📚 詳細文檔
項目結構
src/main/java/dev/recaf/mcp/
├── RecafMcpPlugin.java # 插件入口點 — CDI 注入 14 個 Recaf 服務
├── bridge/
│ ├── BridgeServer.java # 端口 :9847 上的 HTTP 服務器 — 將請求路由到處理程序
│ ├── WorkspaceRegistry.java # 多工作區註冊表 — ID → 工作區映射
│ └── handlers/
│ ├── WorkspaceHandler.java # /workspace/* — 打開、關閉、切換、列出、類、信息、大綱、讀取文件、刪除類
│ ├── DecompileHandler.java # /decompile — 將類反編譯為 Java 源代碼
│ ├── SearchHandler.java # /search — 字符串、類、方法、字段、聲明搜索
│ ├── AnalysisHandler.java # /analysis/* — 調用圖和繼承層次結構
│ ├── MappingHandler.java # /mapping/* — 重命名符號和導出映射
│ ├── BytecodeHandler.java # /bytecode/* — 編輯/添加/刪除方法和字段、方法字節碼指令
│ ├── DiffHandler.java # /diff — 比較兩個類(統一差異)
│ ├── ExportHandler.java # /export/* — 導出 JAR 和反編譯的源代碼
│ ├── CompileHandler.java # /compile — 編譯 Java 源代碼並應用到工作區
│ ├── AssemblerHandler.java # /disassemble, /assemble — JASM 反彙編和彙編
│ └── PatchHandler.java # /patch — 創建和應用工作區更改補丁
├── server/
│ ├── RecafMcpServer.java # MCP 服務器 — STDIO JSON-RPC,分發 25 個工具
│ └── BridgeClient.java # HTTP 客戶端 — 將 MCP 工具調用轉發到橋接服務器
└── util/
├── JsonUtil.java # JSON 響應助手
├── ErrorMapper.java # 結構化錯誤代碼、消息和建議
└── DiffUtil.java # 基於 LCS 的統一差異算法
橋接 HTTP API 參考
所有端點都接受帶有 JSON 主體的 POST 請求,並返回 JSON 響應。
| 端點 |
描述 |
GET /health |
健康檢查 — 返回 {"status":"ok"} |
POST /workspace/open |
打開文件: {"path": "/path/to/file.jar"} → 返回 workspaceId |
POST /workspace/close |
關閉工作區: {"workspaceId": "optional"} |
GET /workspace/info |
獲取工作區信息 |
POST /workspace/classes |
列出類: {"filter": "opt", "offset": 0, "limit": 500} |
POST /workspace/class-info |
類詳細信息: {"className": "com/example/Main"} |
POST /workspace/switch |
切換工作區: {"workspaceId": "xxx"} |
GET /workspace/list-workspaces |
列出所有已註冊的工作區 |
POST /decompile |
反編譯: {"className": "com/example/Main"} |
POST /search |
搜索: {"query": "text", "type": "string", "maxResults": 100} |
POST /analysis/call-graph |
調用圖: {"className": "...", "methodName": "...", "depth": 3} |
POST /analysis/inheritance |
繼承: {"className": "...", "direction": "both"} |
POST /mapping/rename |
重命名: {"type": "class", "oldName": "...", "newName": "..."} |
POST /mapping/export |
導出映射: {"format": "TinyV1", "outputPath": "/path"} |
POST /bytecode/edit-method |
編輯方法: {"className": "...", "methodName": "...", "methodDesc": "...", "accessFlags": 1} |
POST /bytecode/edit-field |
編輯字段: {"className": "...", "fieldName": "...", "accessFlags": 2} |
POST /bytecode/remove-member |
刪除成員: {"className": "...", "memberName": "...", "memberType": "method"} |
POST /bytecode/add-field |
添加字段: {"className": "...", "fieldName": "...", "descriptor": "I"} |
POST /bytecode/add-method |
添加方法: {"className": "...", "methodName": "...", "methodDesc": "()V"} |
POST /diff |
比較類: {"className1": "A", "className2": "B"} 或 {"className1": "A", "source": "..."} |
POST /export/jar |
導出 JAR: {"outputPath": "/path/to/output.jar"} |
POST /export/source |
導出源代碼: {"outputDir": "/path/to/src", "className": "optional"} |
POST /workspace/outline |
類大綱: {"className": "com/example/Main"} — 輕量級結構,無代碼 |
POST /workspace/read-file |
讀取文件: {"path": "META-INF/MANIFEST.MF", "maxChars": 60000} |
POST /workspace/delete-class |
刪除類: {"className": "com/example/Main"} |
POST /bytecode/instructions |
方法字節碼: {"className": "...", "methodName": "...", "methodDesc": "..."} |
POST /compile |
編譯 Java: {"className": "com.example.Main", "source": "...", "targetVersion": 17, "debug": true} |
POST /disassemble |
反彙編類: {"className": "com/example/Main", "maxChars": 120000} |
POST /disassemble/method |
反彙編方法: {"className": "...", "methodName": "...", "methodDesc": "...", "maxChars": 120000} |
POST /assemble |
彙編 JASM: {"className": "com/example/Main", "source": "..."} |
POST /patch |
打補丁: {"action": "create"} 或 {"action": "apply", "patchJson": "..."} |
🔧 技術細節
| 項目 |
值 |
| MCP 協議版本 |
2024-11-05 |
| 橋接端口 |
9847(硬編碼) |
| MCP 服務器依賴項 |
僅 Gson(無 MCP SDK — 輕量級自定義 JSON-RPC 實現) |
| 反編譯超時時間 |
30 秒 |
| 默認最大搜索結果數 |
100 |
| 默認類列表限制 |
500(帶偏移量分頁) |
| Java 工具鏈 |
JDK 22+ |
| 構建系統 |
帶有 Shadow 插件的 Gradle,用於生成胖 JAR |
| 總 MCP 工具數 |
25 |
🛠️ 故障排除
"Connection refused" 錯誤
- 確保 Recaf 正在運行,並且橋接服務器在端口 9847 上處於活動狀態。
- 檢查 Recaf 的日誌面板中的啟動橫幅。
MCP 工具未出現在 AI 客戶端中
- 驗證
recaf-mcp-server-1.2.0.jar 的路徑是否正確且為絕對路徑。
- 確保
java 指向 JDK 22+:運行 java -version 進行檢查。
- 更新 MCP 配置後重啟你的 AI 客戶端。
反編譯返回空或錯誤
- 確保已打開工作區(先使用
open_jar)。
- 檢查類名格式:使用
/ 分隔符(例如 com/example/Main),而不是 . 分隔符。
結構化錯誤響應
- 所有錯誤現在都包含
code、message 和 suggestion 字段。
- 常見代碼:
NO_WORKSPACE、CLASS_NOT_FOUND、MEMBER_NOT_FOUND、INVALID_PARAMS、DECOMPILE_TIMEOUT、COMPILE_FAILED、ASSEMBLER_FAILED、PATCH_FAILED。
構建失敗
- 確保已安裝 JDK 22+。運行
./gradlew -q javaToolchains 查看檢測到的 JDK。
- 如果使用非默認 JDK,請配置 Gradle 工具鏈。
📝 更新日誌
v1.2.0
- Java 編譯:
compile_java 通過 Recaf 的 JavacCompiler 編譯 Java 源代碼,並將結果應用到工作區。
- JASM 彙編/反彙編:
disassemble_class 和 assemble_class 用於完整類的 JASM 往返操作;method_disassemble 用於單個方法的反彙編。
- 方法字節碼查看器:
method_bytecode 通過 ASM 樹 API 顯示詳細的字節碼指令(操作碼、操作數、異常處理塊、局部變量)。
- 類大綱:
class_outline 提供輕量級類結構(字段、方法、訪問標誌),無需反編譯代碼。
- 文件讀取器:
read_file 從工作區讀取非類文件(例如 MANIFEST.MF、配置文件、資源)。
- 類刪除:
class_delete 從工作區中刪除一個類。
- 補丁系統:
patch 工具創建和應用工作區更改補丁(可序列化的 JSON 格式)。
- 新錯誤代碼:
COMPILE_FAILED、COMPILER_UNAVAILABLE、PATCH_FAILED。
- 4 個新的 Recaf 服務注入:AssemblerPipelineManager、JavacCompiler、PatchProvider、PatchApplier。
- 工具數量:從 16 個增加到 25 個。
v1.1.0
- 多工作區支持:可以同時打開多個 JAR 文件,使用
switch_workspace 和 list_workspaces 在它們之間切換。
- 字節碼編輯:
edit_bytecode 工具具有 5 個操作:edit_method、edit_field、remove_member、add_field、add_method(基於 ASM)。
- 類比較:
diff_classes 工具生成兩個反編譯類之間或類與提供的源代碼之間的統一差異。
- 導出:
export_jar 將工作區(包含修改)導出為 JAR 文件;export_source 將反編譯的源代碼導出到目錄。
- 分頁:
list_classes 現在支持 offset/limit,並帶有 totalMatched/hasMore 元數據。
- 結構化錯誤:所有錯誤返回
code、message 和 suggestion 字段(例如 NO_WORKSPACE、CLASS_NOT_FOUND)。
- 錯誤檢測:MCP 服務器現在在錯誤響應中設置
isError: true,以便 AI 客戶端更好地處理。
- 工具數量:從 10 個增加到 16 個。
v1.0.0
- 初始版本,包含 10 個 MCP 工具:open_jar、close_workspace、list_classes、get_class_info、decompile_class、search_code、get_call_graph、get_inheritance、rename_symbol、export_mappings。
📄 許可證
本項目採用 MIT 許可證。