🚀 Recaf MCP Plugin
AIアシスタントがModel Context Protocol (MCP)を通じてRecaf 4.xを制御できるようにします。逆コンパイル、検索、分析、バイトコードの編集、Javaのコンパイル、JASMのアセンブル/ディスアセンブル、クラスの差分比較、ワークスペースのパッチ適用、AIワークフローから直接Javaバイトコードをエクスポートすることができます。
中文ドキュメント
🚀 クイックスタート
このプラグインを使ってAIアシスタントとRecafを連携させることができます。以下の手順に従ってセットアップし、使用を開始しましょう。
✨ 主な機能
- AIアシスタントとRecafの強力なバイトコード分析エンジンをブリッジするデュアルプロセスアーキテクチャを採用。
- 25種類のMCPツールを提供し、ワークスペース管理、分析、コンパイル、アセンブリ、変更、エクスポートなどの操作が可能。
📦 インストール
前提条件
- 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
これにより、2つの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のプラグインディレクトリにコピーします。
| OS |
プラグインディレクトリ |
| macOS / Linux |
~/Recaf/plugins/ |
| Windows |
%APPDATA%/Recaf/plugins/ |
その後、通常通りRecafを起動します。
確認: Recafのログパネルに以下のメッセージが表示されることを確認してください。
========================================
Recaf MCP Plugin enabled
Bridge Server running on port 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設定(Settings → MCP)に以下を追加します。
{
"mcpServers": {
"recaf": {
"command": "java",
"args": ["-jar", "/absolute/path/to/build/mcp/recaf-mcp-server-1.2.0.jar"]
}
}
}
その他のMCP互換クライアント
MCPプロトコルをサポートする任意のクライアントは、このプラグインを使用できます。java -jarを介してMCPサーバーのJARをSTDIOで起動するように設定してください。
ステップ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を開き、workspaceIdを返す
2. "Open /path/to/v2.jar" — 2番目のJARを開き、workspaceIdを返す
3. "List workspaces" — 両方のワークスペースを表示
4. "Switch to workspace v1-1" — 最初のJARに切り替える
5. "Decompile com/example/Main" — v1のソースを取得
6. "Switch to workspace v2-2" — 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"
📚 ドキュメント
利用可能な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 |
2つのクラスまたはクラスとソースコードを比較する |
className1, className2 または source |
method_bytecode |
メソッドのバイトコード命令(オペコード、オペランド、try-catch、ローカル変数)を表示する |
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 (create/apply), patchJson |
エクスポート
| ツール |
説明 |
主要パラメータ |
export_mappings |
リネームマッピングをファイルにエクスポートする |
format, outputPath |
export_jar |
ワークスペースをJARファイルとしてエクスポートする |
outputPath |
export_source |
逆コンパイルされたソースをディレクトリにエクスポートする |
outputDir, className (オプション) |
MCPリソース
| URI |
説明 |
recaf://workspace |
現在のワークスペース情報(JSON) |
recaf://classes |
現在のワークスペースの完全なクラスリスト(JSON) |
ブリッジ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+ |
| ビルドシステム |
GradleとShadowプラグインを使用したファット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を介して詳細なバイトコード命令(オペコード、オペランド、try-catchブロック、ローカル変数)を表示します。
- クラス概要 —
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ツールが2つの逆コンパイルされたクラスまたはクラスと提供されたソースの統一差分を生成します。
- エクスポート —
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