SR

sniperrich/recafmcp

Developer tools
41 stars 8 forks Quality 55 Trend 32

Use MCP to control Recaf4.0 to achieve methods like decompile/rename

Overview

Enable AI assistants to control Recaf 4.x through the Model Context Protocol (MCP) — decompile, search, analyze, edit bytecode, compile Java, assemble/disassemble JASM, diff classes, patch workspaces, deobfuscate, and export Java bytecode directly from your AI workflow. The plugin uses a dual-process architecture to bridge AI assistants with Recaf's powerful bytecode analysis engine: - — Runs inside Recaf's process. Injects Recaf services via CDI (Jakarta) and exposes them as HTTP endpoints on localhost:9847. - — A standalone fat JAR launched by the AI client. Communicates with the AI via STDIO JSON-RPC and forwards tool calls to the Bridge Server over HTTP. This separation is necessary because Recaf runs as a JavaFX desktop application with its own module system, while MCP requires a STDIO-based process that the AI client can spawn and manage. - — Required by Recaf 4.x. Make sure java on your PATH points to JDK 22 or higher. - — This plugin is built against snapshot d07958a5c7.

README

Recaf MCP Plugin

Enable AI assistants to control Recaf 4.x through the Model Context Protocol (MCP) — decompile, search, analyze, edit bytecode, compile Java, assemble/disassemble JASM, diff classes, patch workspaces, deobfuscate, and export Java bytecode directly from your AI workflow.

中文文档

How It Works

The plugin uses a dual-process architecture to bridge AI assistants with Recaf’s powerful bytecode analysis engine:

┌─────────────────┐     STDIO / JSON-RPC     ┌─────────────────┐    HTTP :9847     ┌─────────────────┐
│  AI Assistant    │ ◄──────────────────────► │   MCP Server    │ ◄────────────────► │  Recaf Plugin   │
│ (Claude Code,   │                          │ (Standalone JAR) │                    │ (Bridge Server) │
│  Cursor, etc.)  │                          └─────────────────┘                    └────────┬────────┘
└─────────────────┘                                                                          │
                                                                                    ┌────────┴────────┐
                                                                                    │   Recaf 4.x     │
                                                                                    │ (Analysis Engine)│
                                                                                    └─────────────────┘
  • Recaf Plugin (Bridge Server) — Runs inside Recaf’s process. Injects Recaf services via CDI (Jakarta) and exposes them as HTTP endpoints on localhost:9847.
  • MCP Server — A standalone fat JAR launched by the AI client. Communicates with the AI via STDIO JSON-RPC and forwards tool calls to the Bridge Server over HTTP.

This separation is necessary because Recaf runs as a JavaFX desktop application with its own module system, while MCP requires a STDIO-based process that the AI client can spawn and manage.

Available MCP Tools (28)

Workspace Management

Tool Description Key Parameters
open_jar Open a JAR, APK, or class file for analysis path — absolute file path. Returns workspaceId.
close_workspace Close the current or a specific workspace workspaceId (optional) — close by ID
switch_workspace Switch to a previously opened workspace workspaceId — ID returned by open_jar
list_workspaces List all registered workspaces —
list_classes List classes with offset/limit pagination filter, offset, limit
get_class_info Get class details: fields, methods, interfaces className
class_outline Lightweight class structure (no code, fast) className
read_file Read a non-class file (e.g. MANIFEST.MF, configs) path, maxChars
class_delete Delete a class from the workspace className

Analysis

Tool Description Key Parameters
decompile_class Decompile a class to Java source code className
search_code Search strings, references, or declarations query, type, maxResults
get_call_graph Get method call graph (callers and callees) className, methodName, depth
get_inheritance Get inheritance hierarchy (parents/children) className, direction
diff_classes Compare two classes or class vs. source code className1, className2 or source
method_bytecode View method bytecode instructions (opcodes, operands, try-catch, locals) className, methodName, methodDesc

Compilation & Assembly

Tool Description Key Parameters
compile_java Compile Java source and apply to workspace className, source, targetVersion, debug
disassemble_class Disassemble a class into JASM text className, maxChars
assemble_class Assemble JASM source and apply to workspace className, source
method_disassemble Disassemble a single method into JASM text className, methodName, methodDesc, maxChars

Modification

Tool Description Key Parameters
rename_symbol Rename class/field/method (updates all refs) type, oldName, newName, className
batch_rename Batch rename classes/fields/methods in one atomic operation mappings — array of {type, oldName, newName, className?, descriptor?}
edit_bytecode Add/remove/modify methods and fields className, operation, + operation-specific params
patch Create or apply workspace change patches action (create/apply), patchJson

Export

Tool Description Key Parameters
export_mappings Export rename mappings to a file format, outputPath
export_jar Export workspace as a JAR file outputPath
export_source Export decompiled source to a directory outputDir, className (optional)

Deobfuscation

Tool Description Key Parameters
eval_method Execute a static method in a sandboxed ClassLoader (e.g. string decryption) className, methodName, methodDesc, arguments (optional), timeout (optional)
simplify_method Multi-pass bytecode simplification: constant folding, dead branch elimination, goto chain combining, NOP cleanup, unreachable code removal className, methodName, methodDesc, passes (optional)

MCP Resources

URI Description
recaf://workspace Current workspace information (JSON)
recaf://classes Full class list of the current workspace (JSON)

Prerequisites

  • JDK 22+ — Required by Recaf 4.x. Make sure java on your PATH points to JDK 22 or higher.
  • Recaf 4.x — This plugin is built against snapshot d07958a5c7. The build system will download it automatically.

Build

git clone https://github.com/your-repo/recaf-mcp-plugin.git
cd recaf-mcp-plugin
./gradlew build

This produces two JARs:

File Purpose
build/libs/recaf-mcp-plugin-1.3.0.jar Recaf plugin (loads inside Recaf, runs the Bridge Server)
build/mcp/recaf-mcp-server-1.3.0.jar MCP Server (standalone fat JAR, launched by AI client)

Setup & Usage

Step 1: Start Recaf with the Plugin

Option A: Run directly from the project (recommended for development)

./gradlew runRecaf

This builds the plugin and launches Recaf with it auto-loaded.

Option B: Manual installation

Copy build/libs/recaf-mcp-plugin-1.3.0.jar to Recaf’s plugin directory:

OS Plugin Directory
macOS / Linux ~/Recaf/plugins/
Windows %APPDATA%/Recaf/plugins/

Then start Recaf normally.

Verify: Look for this in Recaf’s Logging panel:

========================================
  Recaf MCP Plugin enabled
  Bridge Server running on port 9847
========================================

Step 2: Configure Your AI Client

Claude Code

Add to ~/.claude.json:

{
  "mcpServers": {
    "recaf": {
      "command": "java",
      "args": ["-jar", "/absolute/path/to/build/mcp/recaf-mcp-server-1.3.0.jar"]
    }
  }
}

Then restart Claude Code. The recaf tools will appear in your tool list.

Cursor

Add to your MCP configuration (Settings → MCP):

{
  "mcpServers": {
    "recaf": {
      "command": "java",
      "args": ["-jar", "/absolute/path/to/build/mcp/recaf-mcp-server-1.3.0.jar"]
    }
  }
}

Other MCP-Compatible Clients

Any client that supports the MCP protocol can use this plugin. Configure it to spawn the MCP Server JAR via java -jar over STDIO.

Step 3: Start Using

Once both Recaf and your AI client are running, you can interact naturally:

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

Example Workflows

Reverse Engineering an Obfuscated JAR

1. "Open /path/to/obfuscated.jar"
2. "List all classes" — get an overview of the package structure
3. "Decompile com/a/b/c" — read the decompiled source
4. "Search for strings containing 'http'" — find network endpoints
5. "Get the call graph for com/a/b/c method d" — understand control flow
6. "Rename com/a/b/c to com/app/NetworkManager" — give it a meaningful name
7. "Export mappings as TinyV1 to ./mappings.tiny" — save your work
8. "Export the modified JAR to ./cleaned.jar" — save the result

Multi-JAR Comparison

1. "Open /path/to/v1.jar" — opens first JAR, returns workspaceId
2. "Open /path/to/v2.jar" — opens second JAR, returns workspaceId
3. "List workspaces" — see both workspaces
4. "Switch to workspace v1-1" — switch to first JAR
5. "Decompile com/example/Main" — get v1 source
6. "Switch to workspace v2-2" — switch to second JAR
7. "Diff com/example/Main against the v1 source" — compare versions

Bytecode Editing

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"

Compile & Assemble Round-Trip

1. "Open /path/to/target.jar"
2. "Decompile com/app/Main" — get the Java source
3. (modify the source) → "Compile this Java source for com.app.Main" — compile & apply
4. "Decompile com/app/Main" — verify the changes took effect
5. "Disassemble com/app/Crypto" — get JASM assembly text
6. "Show me the bytecode for com/app/Crypto.encrypt" — inspect method instructions
7. "Create a patch" — save all modifications as JSON
8. "Export the modified JAR to /tmp/patched.jar"

Deobfuscation Workflow

1. "Open /path/to/obfuscated.jar"
2. "Decompile com/a/b/c" — find encrypted strings and decryption method signatures
3. "eval_method com/a/b/Decryptor decrypt (Ljava/lang/String;)Ljava/lang/String; with args [{type:'string', value:'encrypted_data'}]"
   — call the decryption function directly, get plaintext result
4. "simplify_method com/a/b/c main (Ljava/lang/String;)V" — remove opaque predicates and dead branches
5. "Decompile com/a/b/c" — verify the simplified code is cleaner
6. "Batch rename the deobfuscated symbols"
7. "Export the cleaned JAR to /tmp/deobfuscated.jar"

Project Structure

src/main/java/dev/recaf/mcp/
├── RecafMcpPlugin.java                  # Plugin entry point — CDI injection of 14 Recaf services
├── bridge/
│   ├── BridgeServer.java                # HTTP server on :9847 — routes requests to handlers
│   ├── WorkspaceRegistry.java           # Multi-workspace registry — ID → Workspace mapping
│   └── handlers/
│       ├── WorkspaceHandler.java        # /workspace/* — open, close, switch, list, classes, info, outline, read-file, delete-class
│       ├── DecompileHandler.java        # /decompile — decompile class to Java source
│       ├── SearchHandler.java           # /search — string, class, method, field, declaration search
│       ├── AnalysisHandler.java         # /analysis/* — call graph & inheritance hierarchy
│       ├── MappingHandler.java          # /mapping/* — rename symbols & export mappings
│       ├── BytecodeHandler.java         # /bytecode/* — edit/add/remove methods & fields, method bytecode instructions
│       ├── DiffHandler.java             # /diff — compare two classes (unified diff)
│       ├── ExportHandler.java           # /export/* — export JAR & decompiled source
│       ├── CompileHandler.java          # /compile — compile Java source & apply to workspace
│       ├── AssemblerHandler.java        # /disassemble, /assemble — JASM disassembly & assembly
│       └── PatchHandler.java            # /patch — create & apply workspace patches
│       └── DeobfuscationHandler.java    # /deobf/* — eval method (string decryption) & bytecode simplification
├── server/
│   ├── RecafMcpServer.java              # MCP Server — STDIO JSON-RPC, 28 tools dispatch
│   └── BridgeClient.java               # HTTP client — forwards MCP tool calls to Bridge Server
└── util/
    ├── JsonUtil.java                    # JSON response helpers
    ├── ErrorMapper.java                 # Structured error codes, messages & suggestions
    └── DiffUtil.java                    # LCS-based unified diff algorithm

Bridge HTTP API Reference

All endpoints accept POST with JSON body and return JSON responses.

Endpoint Description
GET /health Health check — returns {"status":"ok"}
POST /workspace/open Open a file: {"path": "/path/to/file.jar"} → returns workspaceId
POST /workspace/close Close workspace: {"workspaceId": "optional"}
GET /workspace/info Get workspace info
POST /workspace/classes List classes: {"filter": "opt", "offset": 0, "limit": 500}
POST /workspace/class-info Class details: {"className": "com/example/Main"}
POST /workspace/switch Switch workspace: {"workspaceId": "xxx"}
GET /workspace/list-workspaces List all registered workspaces
POST /decompile Decompile: {"className": "com/example/Main"}
POST /search Search: {"query": "text", "type": "string", "maxResults": 100}
POST /analysis/call-graph Call graph: {"className": "...", "methodName": "...", "depth": 3}
POST /analysis/inheritance Inheritance: {"className": "...", "direction": "both"}
POST /mapping/rename Rename: {"type": "class", "oldName": "...", "newName": "..."}
POST /mapping/batch-rename Batch rename: {"mappings": [{"type": "class", "oldName": "...", "newName": "..."}, ...]}
POST /mapping/export Export mappings: {"format": "TinyV1", "outputPath": "/path"}
POST /bytecode/edit-method Edit method: {"className": "...", "methodName": "...", "methodDesc": "...", "accessFlags": 1}
POST /bytecode/edit-field Edit field: {"className": "...", "fieldName": "...", "accessFlags": 2}
POST /bytecode/remove-member Remove member: {"className": "...", "memberName": "...", "memberType": "method"}
POST /bytecode/add-field Add field: {"className": "...", "fieldName": "...", "descriptor": "I"}
POST /bytecode/add-method Add method: {"className": "...", "methodName": "...", "methodDesc": "()V"}
POST /diff Diff classes: {"className1": "A", "className2": "B"} or {"className1": "A", "source": "..."}
POST /export/jar Export JAR: {"outputPath": "/path/to/output.jar"}
POST /export/source Export source: {"outputDir": "/path/to/src", "className": "optional"}
POST /workspace/outline Class outline: {"className": "com/example/Main"} — lightweight structure, no code
POST /workspace/read-file Read file: {"path": "META-INF/MANIFEST.MF", "maxChars": 60000}
POST /workspace/delete-class Delete class: {"className": "com/example/Main"}
POST /bytecode/instructions Method bytecode: {"className": "...", "methodName": "...", "methodDesc": "..."}
POST /compile Compile Java: {"className": "com.example.Main", "source": "...", "targetVersion": 17, "debug": true}
POST /disassemble Disassemble class: {"className": "com/example/Main", "maxChars": 120000}
POST /disassemble/method Disassemble method: {"className": "...", "methodName": "...", "methodDesc": "...", "maxChars": 120000}
POST /assemble Assemble JASM: {"className": "com/example/Main", "source": "..."}
POST /patch Patch: {"action": "create"} or {"action": "apply", "patchJson": "..."}
POST /deobf/eval-method Eval method: {"className": "...", "methodName": "...", "methodDesc": "...", "arguments": [...], "timeout": 5000}
POST /deobf/simplify-method Simplify method: {"className": "...", "methodName": "...", "methodDesc": "...", "passes": 3}

Technical Details

Item Value
MCP Protocol Version 2024-11-05
Bridge Port 9847 (hardcoded)
MCP Server Dependencies Gson only (no MCP SDK — lightweight custom JSON-RPC implementation)
Decompile Timeout 30 seconds
Default Max Search Results 100
Default Class List Limit 500 (with offset pagination)
Java Toolchain JDK 22+
Build System Gradle with Shadow plugin for fat JAR
Total MCP Tools 28

Troubleshooting

“Connection refused” errors from MCP Server

  • Make sure Recaf is running and the Bridge Server is active on port 9847.
  • Check Recaf’s Logging panel for the startup banner.

MCP tools not appearing in AI client

  • Verify the path to recaf-mcp-server-1.3.0.jar is correct and absolute.
  • Make sure java points to JDK 22+: run java -version to check.
  • Restart your AI client after updating the MCP configuration.

Decompilation returns empty or errors

  • Ensure a workspace is open (use open_jar first).
  • Check the class name format: use / separators (e.g. com/example/Main), not . separators.

Structured error responses

  • All errors now include code, message, and suggestion fields.
  • Common codes: NO_WORKSPACE, CLASS_NOT_FOUND, MEMBER_NOT_FOUND, INVALID_PARAMS, DECOMPILE_TIMEOUT, COMPILE_FAILED, ASSEMBLER_FAILED, PATCH_FAILED, EVAL_FAILED, EVAL_TIMEOUT, SIMPLIFY_FAILED.

Build fails

  • Ensure JDK 22+ is installed. Run ./gradlew -q javaToolchains to see detected JDKs.
  • If using a non-default JDK, configure a Gradle toolchain.

Changelog

v1.3.0

  • String decryption — eval_method executes static methods in a sandboxed ClassLoader, enabling direct invocation of obfuscator string decryption functions to recover plaintext
  • Bytecode simplification — simplify_method performs multi-pass bytecode transforms: constant folding, dead branch elimination, goto chain combining, NOP cleanup, and unreachable code removal
  • New error codes — EVAL_FAILED, EVAL_TIMEOUT, SIMPLIFY_FAILED
  • Deobfuscation handler — new DeobfuscationHandler with sandboxed WorkspaceClassLoader (parent = PlatformClassLoader for isolation)
  • COMPUTE_FRAMES fallback — simplify_method falls back to COMPUTE_MAXS if COMPUTE_FRAMES fails on malformed bytecode
  • Tool count: 26 → 28

v1.2.0

  • Batch rename — batch_rename applies multiple class/field/method renames in a single atomic operation, ideal for deobfuscation workflows
  • Java compilation — compile_java compiles Java source code via Recaf’s JavacCompiler and applies the result to the workspace
  • JASM assembly/disassembly — disassemble_class and assemble_class for full class JASM round-trip; method_disassemble for single method disassembly
  • Method bytecode viewer — method_bytecode shows detailed bytecode instructions (opcodes, operands, try-catch blocks, local variables) via ASM tree API
  • Class outline — class_outline provides lightweight class structure (fields, methods, access flags) without decompiling code
  • File reader — read_file reads non-class files from the workspace (e.g. MANIFEST.MF, config files, resources)
  • Class deletion — class_delete removes a class from the workspace
  • Patch system — patch tool creates and applies workspace change patches (serializable JSON format)
  • New error codes — COMPILE_FAILED, COMPILER_UNAVAILABLE, PATCH_FAILED
  • 4 new Recaf service injections — AssemblerPipelineManager, JavacCompiler, PatchProvider, PatchApplier
  • Tool count: 16 → 26

v1.1.0

  • Multi-workspace support — open multiple JARs simultaneously, switch between them with switch_workspace and list_workspaces
  • Bytecode editing — edit_bytecode tool with 5 operations: edit_method, edit_field, remove_member, add_field, add_method (ASM-based)
  • Class diff — diff_classes tool produces unified diff between two decompiled classes or class vs. provided source
  • Export — export_jar exports the workspace (with modifications) as a JAR; export_source exports decompiled source to a directory
  • Pagination — list_classes now supports offset/limit with totalMatched/hasMore metadata
  • Structured errors — all errors return code, message, and suggestion fields (e.g. NO_WORKSPACE, CLASS_NOT_FOUND)
  • Error detection — MCP Server now sets isError: true on error responses for better AI client handling
  • Tool count: 10 → 16

v1.0.0

  • Initial release with 10 MCP tools: open_jar, close_workspace, list_classes, get_class_info, decompile_class, search_code, get_call_graph, get_inheritance, rename_symbol, export_mappings

License

MIT

View this README on GitHub

Install

This server does not publish a one-line install command.

Open the repository installation guide

Configuration

{ "mcpServers": { "recaf": { "command": "java", "args": ["-jar", "/absolute/path/to/build/mcp/recaf-mcp-server-1.3.0.jar"] } } }