
Headless IDA Pro MCP server for AI-assisted binary analysis, powered by idalib
Headless IDA CLI and skill-first toolkit for binary analysis on macOS and
Linux. ida-cli auto-selects a runtime backend, auto-starts a local server
when needed, and exposes the same surface as a flat CLI, a stdio MCP
transport, and a Streamable HTTP MCP transport.
ida-cli binary (client + service in one executable)ida-cli skill (skill/SKILL.md) for agent environmentsThe underlying worker / router service layer is started and shut down by the
CLI automatically. You only need to run serve / serve-http explicitly
when you actually want a long-lived, externally addressable service.
Runtime requirements: IDA 9.4/9.5 and Python >=3.11. All database operations use the dedicated pinned Nexus 0.13.4 / Domain 0.5.1 environment. Missing dependencies or mismatched patches fail explicitly. Rust builds need no IDA SDK.
On supported IDA 9.x runtimes, ida-cli can:
.i64 databasesread_* and convert_number helpersrun_scriptAll tools use Nexus with explicit capability errors. See docs/TOOLS.md for the generated tool list.
The default entrypoint is the ida-cli skill, not a manual CLI install.
# list the skill exposed by this repository
npx -y skills add https://github.com/cpkt9762/ida-cli --list
# install the ida-cli skill for Codex
npx -y skills add https://github.com/cpkt9762/ida-cli --skill ida-cli --agent codex --yes --global
After install, the skill ships its own bootstrap wrapper:
~/.agents/skills/ida-cli/scripts/ida-cli.sh --help
~/.agents/skills/ida-cli/scripts/ida-cli.sh probe-runtime
~/.agents/skills/ida-cli/scripts/ida-cli.sh --path /path/to/binary list-functions --limit 20
If ida-cli is missing, the wrapper installs it through the repository
installer before forwarding the command.
Use this only if you want the standalone CLI without going through the skill.
curl -fsSL https://raw.githubusercontent.com/cpkt9762/ida-cli/master/scripts/install.sh | bash -s -- --add-path
Useful variants:
# install a specific release
curl -fsSL https://raw.githubusercontent.com/cpkt9762/ida-cli/master/scripts/install.sh | bash -s -- --tag v0.9.3 --add-path
# build directly from a branch or ref
curl -fsSL https://raw.githubusercontent.com/cpkt9762/ida-cli/master/scripts/install.sh | bash -s -- --ref master --build-from-source --add-path
Notes:
~/.local/bin/ida-cli by default.--add-path appends that bin directory to your shell rc file..app version under /Applications or ~/Applications and prints the selected and other candidates. 9.10 is newer than 9.9; trailing zero components are equal, with canonical path order breaking ties. Explicit IDADIR takes priority. An incompatible selected wheel/runtime fails explicitly. If no candidate is found, installation fails with instructions to set IDADIR.IDADIR overrides it; .app, Contents and runtime paths are accepted. See version comparison and runtime checks.git clone https://github.com/cpkt9762/ida-cli.git
cd ida-cli
export IDADIR="/Applications/IDA Professional 9.5.app/Contents/MacOS" # or a Linux install
cargo build --bin ida-cli
./target/debug/ida-cli --help
ida-cli is client-first. Any client subcommand auto-starts a local
Streamable-HTTP server bound to a random port and writes
/tmp/ida-cli.socket for discovery:
./target/debug/ida-cli --path /path/to/sample.bin list-functions --limit 20
./target/debug/ida-cli --path /path/to/sample.bin decompile --addr 0x140001000
./target/debug/ida-cli --path /path/to/sample.bin raw '{"method":"get_xrefs_to","params":{"address":"0x140001000"}}'
To see which databases the daemon currently holds open, and which clients
hold them, run list-idbs (MCP tool: list_idbs). Run it before rebuilding
or replacing an .i64, for example with idat: a database that is still
listed is held open by the daemon, and idat fails on a database that is
open elsewhere. The answer is {"count": N, "idbs": [...]}; each entry has
the db_handle, the input path and the .i64 path, an opaque id of the
client that opened it, when it was opened, the worker process, whether it is
the active database, and the clients that still hold references. Close
tokens are never returned.
./target/debug/ida-cli list-idbs --json
To get the address behind each line of pseudocode, add --line-addresses to
decompile (MCP and RPC: line_addresses: true on decompile_function). The
answer becomes {"code": ..., "lines": [...]}: code is the usual text and
each lines entry is {"line", "text", "addresses"}. line counts from 1,
text is that line of code, and addresses are the IDA addresses (hex
strings, ascending, no duplicates) of the ctree items Hex-Rays anchored on the
line. A line can map to several non-contiguous addresses, and the list is not
every instruction of the statement. The signature and local declarations have
none; {, }, else and blank lines can carry the address of the block or
if that owns them (the function entry for the outermost braces). The sub_
rename hint is not added in this mode. Hex-Rays can print a very large function
differently from one call to the next, so use code and lines from the same
answer only. Nexus supports this mode. Over the CLI socket a large
answer is stored in the response cache like any other (IDA_MCP_MAX_INLINE_BYTES).
{"line": 6, "text": " while ( a1 != 1 )", "addresses": ["0x10000033c", "0x100000340"]}
Commands whose first argument is a service subcommand (serve,
serve-http, serve-worker, probe-runtime) enter service mode instead:
./target/debug/ida-cli serve # stdio MCP transport
./target/debug/ida-cli serve-http --bind 127.0.0.1:8765
./target/debug/ida-cli probe-runtime
probe-runtime checks Nexus dependencies, patches and protocol readiness; mismatches exit nonzero.
For the complete CLI surface see skill/references/cli-tool-reference.md.
IDADIR (runtime support starts at IDA 9.4)