REA Refuses to Guess
One MCP server wires Ghidra, IDA, Hopper, and dozens of other engines into a single agent workflow. Its most radical feature is what happens when one of them breaks.
- REA's defining feature is what it refuses to do: when a bound engine fails, it returns an explicit error instead of silently switching to another decompiler.
- A single MCP server routes dozens of engines and formats, from Ghidra, IDA, and Hopper to Electron ASARs, Android APKs, firmware images, and EVM bytecode.
- Every result is a structured Evidence record whose identity includes the analysis profile, so older records are rejected with a diagnostic rather than silently rewritten.
- Summary-first delivery turns a 334 MB dossier into a roughly 10 KB summary that points back to the full analysis, keeping the agent's context small.
The Tool That Refuses to Guess
Most tools that wrap a disassembler for an AI agent share a quiet assumption: if one engine fails, try another. REA does not. Its provider documentation states the rule as a hard contract: "runtime failure never selects another provider automatically." When a bound engine dies, REA returns an explicit failure and stops.
Why would a reverse-engineering tool deliberately break? Because the alternative is a hallucination vector. If Ghidra fails and REA silently retries in Hopper, the agent receives different decompilation, different function boundaries, and different naming, with no way to tell that the switch happened. The evidence from run one and the evidence from run two are no longer comparable, and the agent has no signal that anything changed.
The project started as a personal question. Morluto wanted to understand how a closed-source app they already used actually worked, and wiring analysis tools through MCP let an agent do the poking. The framing that stuck was evidence, not source: findings come back as records with stated limits, not as recovered code.
One MCP for reverse engineering across binaries, applications, and runtime behavior.
One MCP, Dozens of Engines
Once you accept the refusal, the breadth starts to make sense. An agent investigating a real application does not know in advance whether the interesting logic lives in a native binary, a JavaScript bundle, a managed assembly, or a network capture. REA's bet is that it should not have to care.
The server routes across a wide range of tools and target types. Native analysis runs through Hopper, Ghidra, and IDA (via the upstream ida-pro-mcp), plus rizin, objdump, GDB, and pwntools. JavaScript and Electron work covers ASAR reconstruction, source maps, the Chrome DevTools Protocol, and the V8 Inspector. Mobile and managed code spans JADX, Apktool, .NET, IL2CPP, and Flutter. Firmware routes into Binwalk and Unblob. Runtime work draws on tshark, Frida, and mitmproxy.
- Native binaries: Hopper, Ghidra, IDA, rizin, objdump, GDB, pwntools, WABT for WebAssembly
- JavaScript and Electron: ASAR reconstruction, source-map decoding, Chrome DevTools Protocol, V8 Inspector
- Mobile and managed code: Android APKs, JADX, Apktool, .NET assemblies, IL2CPP, Flutter and Dart
- Firmware and embedded: Binwalk, Unblob, ESP images, devicetree, FIT images
- Blockchain: EVM bytecode through a bounded EVMole worker
- Runtime and network: tshark and pcap analysis, SQLite, mitmproxy, Frida instrumentation
The packaging is part of the pitch. A single command, npx rea-agents setup, registers the MCP server with supported agents and installs matching workflow instructions. The installer shows the configuration changes it makes and backs up existing files. For a category where the usual advice is to assemble your own bridges, that is a real reduction in friction.
Evidence, Not Answers
REA's central data type is the Evidence record, documented in the MCP contracts. Every evidence-producing tool returns the complete record in both text and structured content. It carries a normalized result, an optional raw result from the upstream tool, an analysis profile, and an identity field called evidence_id.
The subtle rule is that the analysis profile participates in semantic identity. The same function analyzed under two different profiles produces two different IDs, because the settings are part of what the result means. Identity here is not incidental metadata. It is a claim about what was actually run.
The system also refuses to rewrite history. Saved records from an earlier identity scheme are recognized and rejected with a diagnostic rather than silently upgraded. The original ID and file are left untouched. That protects provenance at the cost of asking users to re-export, which is a deliberate trade.
Evidence is also composable. The compare_functions tool accepts complete analyze_function Evidence directly, and compare_artifacts takes a retained-evidence reference, a file path, or inline Evidence, with all three forms producing the same comparison record. The result is a data type that can be passed between tools without losing the context that makes it trustworthy.
334 MB In, 10 KB Out
Here is the part that keeps a senior engineer reading. analyze_function does not return its full dossier by default. Without a detail flag, it retains the complete analysis in the session and returns a tiny summary record whose parent_evidence_id names the dossier. The agent gets a pointer, not a payload.
The CLI documentation gives a concrete example: a 334 MB Obsidian application Evidence file produces a summary view of about 10 KB, with a page view of 32 modules available on request. The performance rules in AGENTS.md make the priority explicit, agent tokens and context come first, then analysis time, then CPU and memory.
The cost is complexity. Agents now track two identities, the summary and its parent, and the rules about which tool accepts which record are strict. Downstream tools that need the full dossier reject the summary. That strictness is the point: the type system keeps a cheap summary from being mistaken for the real thing.
The same honesty shows up at the edges. In the Ghidra bridge, string listings report a terminator state named present_or_not_required, because the API genuinely cannot tell a present terminator from a fixed or Pascal layout when none is missing. That name is an admission of what the engine can and cannot tell you, encoded in the schema.
How REA Compares
The specialist MCPs came first and do one thing tightly. REA's bet is that an agent investigating a real app needs many engines behind one contract, and one honest failure mode.
| Project | Focus | Engines / formats | Packaging | Evidence model |
|---|---|---|---|---|
| morluto/rea | Multi-engine, multi-format MCP + CLI | Native, JS/Electron, .NET, Android, firmware, WASM/EVM, runtime | One installer wires supported agents and adds workflow instructions | Structured Evidence records with semantic identity; explicit unknowns; no silent fallback |
| mrexodia/ida-pro-mcp | IDA Pro | IDA | Single bridge | Tool output |
| LaurieWired/GhidraMCP | Ghidra | Ghidra | Single bridge | Tool output |
| duty1g/x64dbg-mcp-server | x64dbg debugger | x64dbg | Single bridge | Tool output |
| fosdickio/binary_ninja_mcp | Binary Ninja | Binary Ninja | Single bridge | Tool output |
Worth stating plainly: REA does not ship its own decompiler. It is a bridge and workflow layer. The core disassembly and decompilation still come from Ghidra, IDA, Hopper, and the rest, each with its own installation and licensing requirements. The value is orchestration and agent access, not a new engine.
What REA Can't Do
The honest framing cuts both ways, and the community has been quick to say so. Decompiled pseudocode is not the original source. Static inspection cannot prove every runtime behavior, and runtime capture executes the target, which can alter files, state, or data. A controlled environment and proper authorization still matter.
The most visible pushback came from a widely shared report of a user decompiling a purchased Unity game. Commenters pointed out that Mono builds ship managed IL that established .NET tools have decompiled for years, and that IL2CPP, which compiles to native code, would be the genuinely hard case. That criticism is correct. It does not weaken REA; it clarifies what REA is for.
What comes back is decompiled guesswork in C-like form, not the original source code. Rebuilding a feature still takes real engineering. The hard analysis is still Ghidra, IDA and Hopper doing what they've done for years.
There is one more constraint REA cannot route around. What an agent is willing to do depends on the model, its policies, and the user's permissions. Community reports include cases where agents declined reverse-engineering requests regardless of the tooling on hand. REA supplies the plumbing. The judgment calls happen somewhere else.





