返回 MCP 目录
public公开dns本地运行

recafmcp

一个通过Model Context Protocol(MCP)让AI助手控制Recaf 4.x字节码分析工具的开源插件,支持反编译、搜索、分析、编辑字节码、编译Java、汇编/反汇编JASM、对比类、打补丁和导出JAR等25个工具。

article

README

🚀 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 | 切换到之前打开的工作区 | workspaceIdopen_jar 返回的 ID | | list_workspaces | 列出所有已注册的工作区 | — | | list_classes | 列出带有偏移量/限制分页的类 | filteroffsetlimit | | get_class_info | 获取类的详细信息:字段、方法、接口 | className | | class_outline | 轻量级类结构(无代码,速度快) | className | | read_file | 读取非类文件(例如 MANIFEST.MF、配置文件) | pathmaxChars | | class_delete | 从工作区中删除一个类 | className |

分析

| 工具 | 描述 | 关键参数 | |------|-------------|----------------| | decompile_class | 将类反编译为 Java 源代码 | className | | search_code | 搜索字符串、引用或声明 | querytypemaxResults | | get_call_graph | 获取方法调用图(调用者和被调用者) | classNamemethodNamedepth | | get_inheritance | 获取继承层次结构(父类/子类) | classNamedirection | | diff_classes | 比较两个类或类与源代码 | className1className2source | | method_bytecode | 查看方法字节码指令(操作码、操作数、异常处理、局部变量) | classNamemethodNamemethodDesc |

编译与汇编

| 工具 | 描述 | 关键参数 | |------|-------------|----------------| | compile_java | 编译 Java 源代码并应用到工作区 | classNamesourcetargetVersiondebug | | disassemble_class | 将类反汇编为 JASM 文本 | classNamemaxChars | | assemble_class | 汇编 JASM 源代码并应用到工作区 | classNamesource | | method_disassemble | 将单个方法反汇编为 JASM 文本 | classNamemethodNamemethodDescmaxChars |

修改

| 工具 | 描述 | 关键参数 | |------|-------------|----------------| | rename_symbol | 重命名类/字段/方法(更新所有引用) | typeoldNamenewNameclassName | | edit_bytecode | 添加/删除/修改方法和字段 | classNameoperation + 特定操作的参数 | | patch | 创建或应用工作区更改补丁 | action(创建/应用)、patchJson |

导出

| 工具 | 描述 | 关键参数 | |------|-------------|----------------| | export_mappings | 将重命名映射导出到文件 | formatoutputPath | | export_jar | 将工作区导出为 JAR 文件 | outputPath | | export_source | 将反编译的源代码导出到目录 | outputDirclassName(可选) |

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),而不是 . 分隔符。

结构化错误响应

  • 所有错误现在都包含 codemessagesuggestion 字段。
  • 常见代码:NO_WORKSPACECLASS_NOT_FOUNDMEMBER_NOT_FOUNDINVALID_PARAMSDECOMPILE_TIMEOUTCOMPILE_FAILEDASSEMBLER_FAILEDPATCH_FAILED

构建失败

  • 确保已安装 JDK 22+。运行 ./gradlew -q javaToolchains 查看检测到的 JDK。
  • 如果使用非默认 JDK,请配置 Gradle 工具链

📝 更新日志

v1.2.0

  • Java 编译compile_java 通过 Recaf 的 JavacCompiler 编译 Java 源代码,并将结果应用到工作区。
  • JASM 汇编/反汇编disassemble_classassemble_class 用于完整类的 JASM 往返操作;method_disassemble 用于单个方法的反汇编。
  • 方法字节码查看器method_bytecode 通过 ASM 树 API 显示详细的字节码指令(操作码、操作数、异常处理块、局部变量)。
  • 类大纲class_outline 提供轻量级类结构(字段、方法、访问标志),无需反编译代码。
  • 文件读取器read_file 从工作区读取非类文件(例如 MANIFEST.MF、配置文件、资源)。
  • 类删除class_delete 从工作区中删除一个类。
  • 补丁系统patch 工具创建和应用工作区更改补丁(可序列化的 JSON 格式)。
  • 新错误代码COMPILE_FAILEDCOMPILER_UNAVAILABLEPATCH_FAILED
  • 4 个新的 Recaf 服务注入:AssemblerPipelineManager、JavacCompiler、PatchProvider、PatchApplier。
  • 工具数量:从 16 个增加到 25 个。

v1.1.0

  • 多工作区支持:可以同时打开多个 JAR 文件,使用 switch_workspacelist_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 元数据。
  • 结构化错误:所有错误返回 codemessagesuggestion 字段(例如 NO_WORKSPACECLASS_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 许可证。

help

运行方式说明

cloud

托管运行

托管运行通常表示这个 MCP Server 由服务方环境承载,用户一般按页面提供的连接方式或授权流程接入,不需要在本地长期启动一个 MCP 进程

  1. 打开服务方连接页
  2. 完成授权或复制端点
  3. 在 MCP 客户端中连接
terminal

本地运行 / 其它方式

本地运行通常需要用户在自己的电脑或服务器上安装依赖,把 server_config 复制到 MCP 客户端,并按 env_schema 补齐环境变量、密钥或其它配置

  1. 复制 server_config
  2. 安装所需依赖
  3. 补齐环境变量后重启客户端