rea-reverse

IDA Pro MCP with REA: Connect Claude Code and Codex to IDA

Written for REA 6.4.0Updated 9 min read
On this page

REA, the open-source project by morluto, can use IDA Pro as its native analysis engine. It does this through mrexodia/ida-pro-mcp: REA connects to the ida-pro-mcp server you already run, calls a fixed set of read-only tools, and returns results as Evidence, in the same format its Ghidra and Hopper providers use.

Read this first, because it decides which version you install: in REA 6.4.0, the attached (GUI) mode only understands the legacy tools of ida-pro-mcp 1.4.0. The redesigned tools in ida-pro-mcp 2.0.0 are not compatible with that mode. This is tracked in REA issue #2301, which was still open when this article was written (checked through the GitHub API on 2026-10-13). Headless mode follows a different contract; details are below.

Who this is for: people who own an IDA Pro license and want Claude Code or Codex to read IDA’s analysis through REA.

What you will learn:

  • What you need: IDA Pro 8.3+, Python 3.11+, ida-pro-mcp 1.4.0, REA 6.4.0
  • How to write the registration file REA reads, for attached and headless modes
  • Where to put REA_IDA_MCP_CONFIG and REA_ANALYSIS_PROVIDER in Claude Code and Codex
  • Which REA operations work with IDA, and which fail and why

Example target: a small C program you compile yourself (source below).

Requirements and licensing

  • IDA Pro 8.3 or newer, licensed. ida-pro-mcp’s README lists “IDA Pro (8.3 or higher, 9 recommended)” and states “IDA Free is not supported”. REA does not install, activate or license IDA. Use a copy you obtained from Hex-Rays under its license terms.
  • IDA Free does not work with REA 6.4.0 either. REA’s repository main documents an optional separate native bridge that can work with IDA Free, but its "protocol": "native" registration is not in the 6.4.0 package: the 6.4.0 registration schema rejects unknown keys. Wait for a release that includes it.
  • Python 3.11+ for ida-pro-mcp.
  • REA 6.4.0, registered with your agent through npx rea-agents setup (getting started).
  • For headless mode: IDA Pro with idalib (IDA 9.x), activated as described in the ida-pro-mcp README.

Only analyze binaries you are allowed to analyze. REA’s DISCLAIMER.md explains the boundaries.

Version compatibility in REA 6.4.0

REA 6.4.0 checks the tool list the upstream server returns before it runs anything. Each mode expects one profile:

REA mode Upstream tools REA requires Works with Status
attached (default) 1.4 legacy: get_metadata, list_functions, list_strings, get_function_by_name, get_function_by_address, decompile_function, disassemble_function, get_callers, get_callees, get_xrefs_to ida-pro-mcp 1.4.0 GUI plugin Supported
attached (2.0.0 GUI plugin exposes lookup_funcs, decompile, disasm and others instead) ida-pro-mcp 2.0.0 Not compatible (#2301)
headless Database supervisor: idb_open, idb_list, idb_close, server_health, list_funcs, lookup_funcs, find_regex, decompile, disasm, callees, xrefs_to idalib-mcp with the supervisor API Narrow: see below

About headless mode: the 1.4.0 idalib-mcp does not have the supervisor API at all. The supervisor exists only on the upstream development branch, whose pyproject.toml says 2.0.0. The #2301 thread shows that 2.0.0 builds made before upstream PR #495 lack idb_close and fail. REA’s IDA provider docs record headless verification against one upstream commit, c133c3853faa111a9b00ee615c013b720d0c4acd, on Windows x64 (IDA 9.3) and macOS arm64 (IDA Pro 9.1). Linux headless operation is listed as not yet verified. Treat headless as experimental and pinned to that commit. For the path REA 6.4.0 documents as supported, use attached mode with 1.4.0.

Why this matters in practice: upstream’s README tells you to pip install from the GitHub main archive, and today that gives you 2.0.0. Follow those instructions as written and attached mode will fail.

Step 1: Build a test target

Use something small that you compiled, so you know the right answer:

// check.c
#include <stdio.h>
#include <string.h>

static int check_key(const char *s) {
    if (strlen(s) != 8) return 0;
    int sum = 0;
    for (int i = 0; i < 8; i++) sum += s[i] ^ 0x5A;
    return sum == 0x2F0;
}

int main(int argc, char **argv) {
    if (argc < 2) { puts("usage: check KEY"); return 1; }
    puts(check_key(argv[1]) ? "ok" : "bad key");
    return 0;
}
cc -O0 -g -o check check.c
shasum -a 256 check

Why: REA binds every result to the input file’s SHA-256. In attached mode it compares that hash with the input hash IDA recorded, so you need to know exactly which file you opened. On macOS, C symbols carry a leading underscore, so the function names become _main and _check_key.

Step 2: Install ida-pro-mcp 1.4.0 (attached mode)

Install the tagged 1.4.0 release from PyPI, not the GitHub main archive:

python3 -m pip install "ida-pro-mcp==1.4.0" "mcp<2"
ida-pro-mcp --install

Why pin mcp<2: ida-pro-mcp 1.4.0 declares mcp>=1.16.0, which allows version 2 of the Python MCP SDK. The workaround in #2301 reports that the 1.4 proxy’s server.py fails to import under the 2.x SDK, so the pin keeps it on 1.x.

--install copies the IDA plugin and registers ida-pro-mcp with the MCP clients it knows. Restart IDA afterwards.

Then open the original binary (check) in IDA Pro, let auto-analysis finish, and start the plugin with Edit → Plugins → MCP (hotkey Ctrl-Alt-M in 1.4.0). The plugin listens on 127.0.0.1:13337.

If you already have 2.0.0 installed, the #2301 reporter notes that the 1.4.0 plugin file is self-contained and can sit next to a 2.0.0 install; the 1.4 plugin hard-codes its address and port, so a second instance needs those edited.

Step 3: Write the registration file REA reads

REA does not talk to IDA’s port directly. It launches ida-pro-mcp’s stdio proxy (server.py), which forwards to the plugin. Get the exact interpreter and script path from:

ida-pro-mcp --config

That prints an mcpServers → ida-pro-mcp entry with command, args, timeout and disabled. Copy only command, args (and env, if present) into a new file, for example ~/ida/ida-mcp.json:

{
  "mode": "attached",
  "command": "/absolute/path/to/python3",
  "args": [
    "/absolute/path/to/site-packages/ida_pro_mcp/server.py",
    "--ida-rpc",
    "http://127.0.0.1:13337"
  ]
}

Why not paste the output as is: REA 6.4.0 validates this file strictly. A stdio registration accepts command, args, env, type, mode, timeoutMs and workspaceRoot. A local HTTP registration replaces command/args/env with a loopback url and optional headers, and accepts the same type, mode, timeoutMs and workspaceRoot. Any other key, including timeout and disabled from --config, makes the file invalid. A wrapping {"mcpServers": {"ida-pro-mcp": {...}}} object is accepted, but the inner entry is checked just as strictly.

Optional keys:

  • "timeoutMs": per-request deadline for upstream calls, default 300000.
  • "mode": "attached" is the default; it is written out here for clarity.

The file must be at most 64 KiB (65,536 bytes), and REA_IDA_MCP_CONFIG must be an absolute path.

Step 4: Run it from the CLI

export REA_IDA_MCP_CONFIG="$HOME/ida/ida-mcp.json"
export REA_ANALYSIS_PROVIDER=ida

rea doctor --provider ida --json
rea search /absolute/path/check "bad key" --json
rea function /absolute/path/check check_key --json
rea decompile /absolute/path/check check_key --json

Use --provider ida on a single command instead of REA_ANALYSIS_PROVIDER if you also use Ghidra.

What each step proves:

  • doctor --provider ida only validates the registration file. It does not launch IDA or check upstream compatibility (#2301 points out that it reports healthy even against 2.0.0).
  • The first real command connects, compares the tool list with the attached profile, and checks that IDA’s recorded input SHA-256 matches check. REA repeats the identity and image-base check around every request.
  • function returns a complete function dossier; decompile returns pseudocode only.

xrefs with IDA needs an explicit hexadecimal address (rea xrefs /absolute/path/check 0x...), not a symbol name.

Step 5: Connect Claude Code and Codex

Add the two variables to the REA server entry, not to the ida-pro-mcp entry. If REA_IDA_MCP_CONFIG is set in your shell and points to a valid registration file when you run npx rea-agents setup --client claude_code, setup carries it into the registration; REA_ANALYSIS_PROVIDER you add by hand. Setup keeps existing env values when you rerun it.

Claude Code (~/.claude.json, inside the existing rea entry):

"env": {
  "REA_IDA_MCP_CONFIG": "/Users/you/ida/ida-mcp.json",
  "REA_ANALYSIS_PROVIDER": "ida"
}

Codex (~/.codex/config.toml):

[mcp_servers.rea.env]
REA_IDA_MCP_CONFIG = "/home/you/ida/ida-mcp.json"
REA_ANALYSIS_PROVIDER = "ida"

Restart the client completely. Opening a target waits on IDA, and in headless mode on auto-analysis, so give the client a generous tool deadline. In Codex that is tool_timeout_sec under [mcp_servers.rea]; in Claude Code the MCP_TOOL_TIMEOUT environment variable (milliseconds). Both are client settings, so check your client’s documentation for current defaults.

If ida-pro-mcp’s own --install also registered it in Claude Code, you now have two IDA-related servers. That works, but tell the agent which one to use, because both expose decompile-style tools.

Prompts that work

If you leave REA_ANALYSIS_PROVIDER unset, ask the agent to open the target with provider_id: "ida":

Use REA. Open /absolute/path/check with open_binary and provider_id "ida".
Find the function that decides whether a key is valid, decompile it, and
explain the condition in plain terms. Quote addresses for every claim and
list anything the IDA adapter reported as unknown. Close the binary when done.
With REA's IDA provider, search strings in /absolute/path/check for "key",
find which function references that string (use xrefs with the string's
address), and show that function's callees.

Why open and close explicitly: open_binary starts the provider session and close_binary releases it. In attached mode, closing only drops REA’s MCP connection; it never saves or closes your IDA database.

For a general prompt structure, see Claude Code Reverse Engineering Skill.

Headless mode in 6.4.0

Headless mode lets REA open its own IDA database without the GUI. The registration looks like this:

{
  "mode": "headless",
  "command": "idalib-mcp",
  "args": ["--stdio", "--max-workers", "1"]
}

Add "env": {"IDADIR": "/absolute/path/to/ida"} if your idalib setup needs it, and optionally "workspaceRoot": "/absolute/existing/tmp/dir". A local Streamable HTTP supervisor can use "url": "http://127.0.0.1:8745/mcp" instead of command. REA only accepts localhost, 127.0.0.1 or [::1] URLs without credentials.

What REA does in this mode:

  1. Copies the binary into a private temporary directory and re-checks its SHA-256.
  2. Calls idb_open with force_headless and its own session ID, then confirms through idb_list that it owns an active worker for that copy.
  3. Refuses to run analysis until server_health reports auto-analysis is ready.
  4. On close, calls idb_close with save: false, confirms the worker is gone, and deletes the copy.

Your original file is never modified. Requirements and limits:

  • The supervisor must provide idb_close (see the compatibility table). This is the part that 2.0.0 builds made before upstream PR #495 lack.
  • REA and the supervisor must share the same filesystem and path syntax: run both on Windows, or both on the same Unix host.
  • procedure_callers (direct callers) is unavailable in headless mode, because the modern tools do not prove direct call edges. Use xrefs on the function address instead.

What works with IDA, and what does not

REA’s IDA adapter declares these read-only operations: list and search procedures and strings, resolve a procedure address, pseudocode, assembly, raw function instructions, callers (attached only), callees, xrefs, and the analyze_function dossier.

It does not cover:

  • rea analyze / rea inspect / MCP binary_overview. These need segment and document listings that the IDA adapter doesn’t declare, so they fail with capability_unavailable (#2460, open). Start from search, function or decompile instead.
  • .idb / .i64 files. REA admits executables only. Open the original input.
  • MIPS targets. REA’s IDA adapter has no verified MIPS lane; use a Ghidra profile.
  • Renaming, patching, types, debugging or arbitrary IDAPython. The adapter is read-only by design.

Results are live: they describe the current IDA database. REA records the database state before and after a request, but cannot prove the database is unpatched.

Troubleshooting

unreadable_output / “Analysis returned an unreadable result” right after connecting. The most likely cause is a profile mismatch, such as a 2.0.0 GUI plugin behind attached mode. #2301 reports that the CLI shows only this generic error while the internal message names the missing tools. Check pip show ida-pro-mcp and install 1.4.0.

“REA_IDA_MCP_CONFIG must contain an IDA MCP command/args or local url registration”. The JSON has extra keys (often timeout or disabled from --config), or the URL isn’t loopback. Strip it down to the keys listed in Step 3.

“The attached IDA input SHA-256 does not match the selected target”. IDA has a different file open, or you passed a copy whose bytes differ. Open the exact file in IDA, or pass the path IDA loaded.

“IDA MCP integration admits executable inputs, not analysis databases”. You passed an .i64 or .idb. Pass the original binary.

“IDA auto-analysis is incomplete or readiness is unknown”. Headless worker still analyzing. Retry once analysis finishes; raise timeoutMs for large binaries.

ImportError for FastMCP when the proxy starts. The 1.4 proxy is running under the 2.x Python MCP SDK. Reinstall with "mcp<2".

Port 13337 already in use. Another IDA instance is running the plugin. Close it, or follow the #2301 note about editing the 1.4 plugin’s port for a second instance.

rea doctor is healthy but nothing works. Expected: doctor checks the file only. The first analysis call is the real compatibility test.

Next steps