MCPcopy Index your code
hub / github.com/blacktop/ida-mcp-rs

github.com/blacktop/ida-mcp-rs @v9.3.24

Chat with this repo
repository ↗ · DeepWiki ↗ · release v9.3.24 ↗ · + Follow
937 symbols 2,113 edges 48 files 137 documented · 15%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

ida-mcp-rs

Headless IDA Pro MCP server for AI-powered reverse engineering.

<a href="https://github.com/blacktop/ida-mcp-rs/actions" alt="Actions">
      <img src="https://github.com/blacktop/ida-mcp-rs/actions/workflows/build.yml/badge.svg" /></a>
<a href="https://github.com/blacktop/ida-mcp-rs/releases/latest" alt="Downloads">
      <img src="https://img.shields.io/github/downloads/blacktop/ida-mcp-rs/total.svg" /></a>
<a href="https://github.com/blacktop/ida-mcp-rs/releases" alt="GitHub Release">
      <img src="https://img.shields.io/github/v/release/blacktop/ida-mcp-rs" /></a>
<a href="http://doge.mit-license.org" alt="LICENSE">
      <img src="https://img.shields.io/:license-mit-blue.svg" /></a>

Prerequisites

  • IDA Pro 9.2+ with valid license (9.3sp1 recommended)

Getting Started

Install

macOS / Linux (via Homebrew)

brew install blacktop/tap/ida-mcp        # Latest (IDA 9.3/9.3sp1)
brew install blacktop/tap/ida-mcp@9.2    # IDA 9.2

Windows (via Scoop)

scoop bucket add blacktop https://github.com/blacktop/scoop-bucket
scoop install blacktop/ida-mcp

Windows note: See the Windows platform setup section below for DLL discovery options.

macOS / Linux (via Nix)

nix shell github:blacktop/nur#ida-mcp \
  --extra-experimental-features 'nix-command flakes'

Linux (via Snap)

sudo snap install ida-mcp
sudo snap connect ida-mcp:dot-idapro   # grant access to ~/.idapro (license)

Strict confinement. Requires IDA Pro installed under $HOME (installer default ~/ida-pro-9.3). For IDA in /opt/ or system paths, use Homebrew or Nix.

Direct download — grab the archive for your platform from GitHub Releases.

Build from source

See docs/BUILDING.md.

ida-mcp versions mirror IDA Pro versions (v9.3.x for IDA 9.3, v9.2.x for IDA 9.2). A version mismatch is detected at startup with a clear error message. Scoop and NUR publish the latest version. For older IDA versions, use the matching GitHub Release or the versioned Homebrew cask.

Platform Setup

macOS

Standard IDA installations in /Applications work automatically:

claude mcp add ida -- ida-mcp

If you see Library not loaded: @rpath/libida.dylib, set DYLD_LIBRARY_PATH to your IDA path:

claude mcp add ida -e DYLD_LIBRARY_PATH='/path/to/IDA.app/Contents/MacOS' -- ida-mcp

Supported paths (auto-detected): - /Applications/IDA Professional 9.3.app/Contents/MacOS - /Applications/IDA Home 9.3.app/Contents/MacOS - /Applications/IDA Essential 9.3.app/Contents/MacOS - /Applications/IDA Professional 9.2.app/Contents/MacOS

Linux

The IDA installer defaults to ~/ida-pro-9.3 — the launcher script auto-detects this:

claude mcp add ida -- ida-mcp

For non-default install locations, set IDADIR:

claude mcp add ida -e IDADIR='/path/to/ida' -- ida-mcp

Resolution order: $IDADIR~/ida-pro-9.3/opt/ida-pro-9.3 and other RUNPATH fallbacks.

Windows

Option A — Install ida-mcp.exe into your IDA directory (simplest, no env setup needed):

# Copy the binary next to ida.dll / idalib.dll
copy ida-mcp.exe "C:\Program Files\IDA Professional 9.3\"
claude mcp add ida -- "C:\Program Files\IDA Professional 9.3\ida-mcp.exe"

Option B — Install via Scoop (auto-detects IDA and sets IDADIR):

scoop bucket add blacktop https://github.com/blacktop/scoop-bucket
scoop install blacktop/ida-mcp
claude mcp add ida -- ida-mcp

Option C — Set IDADIR manually:

# Persistent (survives reboots)
setx IDADIR "C:\Program Files\IDA Professional 9.3"
# Then restart your terminal
claude mcp add ida -- ida-mcp

Windows requires ida.dll and idalib.dll to be discoverable at startup. Placing ida-mcp.exe in the IDA directory is the easiest approach. Otherwise, the IDA directory must be on PATH or pointed to by IDADIR.

Common IDA paths: - C:\Program Files\IDA Professional 9.3 - C:\Program Files\IDA Pro 9.3 - C:\Program Files\IDA Home 9.3

Runtime Requirements

The binary links against IDA's libraries at runtime. Standard installation paths are auto-detected via baked RPATHs. For non-standard paths:

Platform Library Fallback Configuration
macOS libida.dylib DYLD_LIBRARY_PATH
Linux libida.so IDADIR (launcher reads it) or LD_LIBRARY_PATH
Windows ida.dll Place exe in IDA dir, set IDADIR, or add IDA dir to PATH

Configure your AI agent

Claude Code

claude mcp add ida -- ida-mcp

Codex CLI

codex mcp add ida -- ida-mcp

Gemini CLI

gemini mcp add ida -- ida-mcp

Cursor

Add to .cursor/mcp.json:

{
  "mcpServers": {
    "ida": { "command": "ida-mcp" }
  }
}

Usage

Once configured, you can analyze binaries through your AI agent:

# Open a binary (returns quickly — analysis runs separately)
open_idb(path: "~/samples/malware")

# These work immediately, no analysis needed
list_functions(limit: 20)
disasm_by_name(name: "main", count: 20)
strings(limit: 10)

# For xrefs/decompile on large binaries, run analysis in background
analyze_funcs(background: true)   # returns task_id
task_status(task_id: "analyze-1") # poll progress

# Decompile (requires Hex-Rays + completed analysis)
decompile(address: "0x100000f00")

# Discover more tools
tool_catalog(query: "find callers")

HTTP/SSE worker pool

serve-http keeps the existing single in-process IDA worker by default. For stateful multi-client HTTP/SSE usage, set --max-workers above 1 to route sessions through child ida-mcp worker processes:

ida-mcp serve-http --bind 127.0.0.1:8765 --max-workers 4 --min-workers 1

Without --max-workers N, HTTP sessions still share one IDA context; a second client opening another binary waits behind the first and then gets the normal A database is already open error. Pooled startup logs include Starting pooled HTTP router and MCP pooled HTTP server listening.

Each opened HTTP session leases one child worker until close_idb, HTTP DELETE, session timeout, or server shutdown. close_idb releases the lease immediately, but the child process may stay alive idle for reuse until --worker-idle-timeout-secs elapses. If all workers are leased, new open_idb/open_dsc calls fail with Worker pool exhausted so clients can retry later. Pooled mode requires stateful HTTP sessions; --max-workers > 1 is rejected with --stateless.

If an SSE-capable client exits without sending close_idb or HTTP DELETE, pooled mode closes the session after its standalone SSE stream disconnects and the --worker-disconnect-grace-secs reconnect grace elapses. POST-only clients do not always leave a stream for the server to observe, so their orphaned sessions are reclaimed by --session-keep-alive-secs (default 1800 seconds). Lower it if you need faster pool reclaim for POST-only clients.

dyld_shared_cache analysis

open_dsc opens a single module from Apple's dyld_shared_cache. On first use it runs idat in the background to create the .i64 (this can take minutes). Subsequent opens are instant.

# Open a module from the DSC
open_dsc(path: "/path/to/dyld_shared_cache_arm64e", arch: "arm64e",
         module: "/usr/lib/libobjc.A.dylib")

# If a background task was started, poll until done
task_status(task_id: "dsc-1")

# Load additional frameworks for cross-module references
open_dsc(path: "/path/to/dyld_shared_cache_arm64e", arch: "arm64e",
         module: "/usr/lib/libobjc.A.dylib",
         frameworks: ["/System/Library/Frameworks/Foundation.framework/Foundation"])

# Incrementally load another DSC dylib into an already-open database
dsc_add_dylib(module: "/usr/lib/libSystem.B.dylib")

# Incrementally load a DSC data/GOT/stub region by address
dsc_add_region(address: "0x180116000")

# After dsc_add_dylib/dsc_add_region, confirm analysis readiness
analysis_status()

Requirements: - idat binary (from IDA installation) must be available via $IDADIR or standard install paths - The DSC loader and dscu plugin (bundled with IDA 9.x)

IDAPython scripting

run_script executes Python code in the open database via IDA's IDAPython engine. stdout and stderr are captured.

# Inline script
run_script(code: "import idautils\nfor f in idautils.Functions():\n    print(hex(f))")

# Run a .py file from disk
run_script(file: "/path/to/analysis_script.py")

# With timeout (default 120s, max 600s)
run_script(code: "import ida_bytes; print(ida_bytes.get_bytes(0x1000, 16).hex())",
           timeout_secs: 30)

All ida_* modules, idc, and idautils are available. See the IDAPython API reference.


Context Optimization

ida-mcp exposes 71 tools (~10k tokens of tools/list payload). Frontier models with 1M context don't notice; smaller models and agents without lazy tool loading do. Filter the surface to only what you need:

Flag Env var Effect
--toolsets=cat1,cat2 IDA_MCP_TOOLSETS Replaces "all tools" with the union of selected categories
--tools=t1,t2 IDA_MCP_TOOLS Adds individual tools (additive to --toolsets)
--exclude-tools=t1,t2 IDA_MCP_EXCLUDE_TOOLS Subtracts from the include set; always wins
--read-only IDA_MCP_READ_ONLY Strips mutating/arbitrary-code tools (run_script, patch*, rename, set_comments, type/stack edits, dsc_add_*, analyze_funcs); keeps lifecycle/discovery

No flags = all 71 tools (default). Categories: core, functions, disassembly, decompile, xrefs, control_flow, memory, search, metadata, types, editing, scripting (run tool_catalog to enumerate). Flags override env vars; unknown names rejected at startup.

Recommendations by client

  • Claude Code, Cursor: no action — both clients already lazy-load MCP tool schemas. Claude Code's MCP Tool Search auto-defers when tools exceed 10% of context (Cursor's Dynamic Context Discovery does similar).
  • Codex CLI, OpenCode: every session pays the full ~10k tokens. Pick a focused subset: bash ida-mcp --toolsets=core,functions,disassembly,decompile,xrefs
  • Gemini CLI: the Gemini API caps at 512 function declarations across all MCP servers. Shrink ida-mcp so it fits alongside others: bash ida-mcp --toolsets=core,functions,disassembly,decompile --read-only
  • Small / local models: prefer the smallest workable surface. For triage: bash ida-mcp --toolsets=core,functions --tools=decompile,callees,callers --read-only

Configuring through mcpServers.json

Most installed MCP configs run ida-mcp directly without a subcommand. The env vars apply on that path too:

{
  "mcpServers": {
    "ida-mcp": {
      "command": "ida-mcp",
      "env": {
        "IDA_MCP_TOOLSETS": "core,functions,disassembly,decompile,xrefs",
        "IDA_MCP_READ_ONLY": "true"
      }
    }
  }
}

Measuring

Run just measure-tools to see the per-tool char/token breakdown. Filtering doesn't change the numbers reported there (it acts at the protocol boundary), but the difference shows up in your client's context view (/context in Claude Code, equivalents elsewhere).

Docs

License

MIT Copyright (c) 2026 blacktop

Core symbols most depended-on inside this repo

to_tool_result
called by 135
src/error.rs
contains
called by 67
src/server/http_access.rs
try_send
called by 61
src/ida/worker.rs
crash_guarded
called by 53
src/crash_guard.rs
call_json
called by 28
src/ida/pool.rs
get
called by 28
src/server/task.rs
call_value
called by 27
src/ida/pool.rs
get
called by 21
src/server/mod.rs

Shape

Method 390
Function 386
Class 146
Enum 15

Languages

Rust99%
C1%
Python1%

Modules by API surface

src/server/mod.rs193 symbols
src/ida/pool.rs148 symbols
src/ida/worker.rs94 symbols
src/server/requests.rs63 symbols
src/server/task.rs44 symbols
src/ida/types.rs36 symbols
src/server/http_config.rs34 symbols
src/server/http_access.rs34 symbols
src/main.rs28 symbols
src/server/operation.rs26 symbols
src/ida/handlers/database.rs23 symbols
src/dsc.rs20 symbols

For agents

$ claude mcp add ida-mcp-rs \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact

Ask about this repo answers extend the page