6.3 KiB
ida-mcp-server
An MCP server that exposes a running IDA Pro session to Claude (or any other MCP client) over HTTP. Ships with an IDA plugin that turns a database into an HTTP API, and a small server that turns that API into MCP tools.
Why this exists
The usual way to hook IDA up to an AI assistant is a fixed pair of ports: "IDA A" on 7777, "IDA B" on 7778, hardcoded into a script. That falls apart the moment you want a third binary open, or you're running IDA on a different machine over SSH and have to juggle port forwards by hand.
This version drops the hardcoding. Each IDA instance finds a free port on its own, starts its own HTTP server, and registers itself with the MCP server over a heartbeat. Open as many IDA windows as you want, on the same machine or a remote one -- they show up automatically, and the MCP tools let you address a specific one by id or just let it pick the only one that's open.
How it's put together
ida_mcp_plugin.py runs inside IDA, one instance per open database
-> exposes decompilation, xrefs, renaming, etc. over HTTP
ida-mcp-server.py a small Starlette/uvicorn server
-> turns that HTTP API into MCP tools over JSON-RPC (/sse)
-> keeps a live registry of which IDA instances are open
The plugin and the server talk to each other in both directions: the plugin pushes heartbeats to the server so it knows what's alive, and the server pulls data from the plugin when a tool is called.
Setup
-
Copy
ida_mcp_plugin.pyinto IDA's plugins directory (on macOS, something likeIDA Professional 9.1.app/Contents/MacOS/plugins/). -
Install the server's dependencies and start it:
pip install httpx starlette uvicorn python ida-mcp-server.py -
Open IDA. The plugin starts automatically, picks a port, and registers itself with the server at
http://127.0.0.1:8888by default. -
Point your MCP client at
http://<server-host>:8888/sse.
That's it for a single machine. No ports to configure, no restart dance when you open a second binary.
Multiple IDA instances
Just open more IDA windows. Each one registers under its own id (derived from
the input file name and process id) and shows up in ida_list_instances. Most
tools take an optional instance argument -- skip it if only one IDA is open,
or pass an id from ida_list_instances to target a specific one.
Running IDA on a different machine
Set these before launching IDA on the remote box:
IDA_MCP_HOST=0.0.0.0-- so the plugin accepts connections from outside localhostIDA_MCP_ADVERTISE_HOST=<ip reachable from the server>-- what the plugin tells the server to call it back onIDA_MCP_REGISTRY_URL=http://<server-ip>:8888-- where to send heartbeats
The server still has to be able to reach that IP and port -- this handles the port bookkeeping, not your network topology. If there's a firewall in the way you'll still need a tunnel, but you won't be assigning ports by hand anymore.
Reloading the plugin without restarting IDA
If you edit ida_mcp_plugin.py, call the ida_reload_plugin tool instead of
closing and reopening IDA. It re-reads the file from disk and swaps in the new
code for anything that handles a request. The one thing that doesn't
hot-reload is the heartbeat/registration thread, which keeps running with
whatever code it started with until IDA actually restarts.
Security
By default the server and plugin trust anything that can reach them, which is
fine if everything stays on localhost. If you're exposing the server publicly
(for example through ngrok, to use it from a hosted MCP client), set
IDA_MCP_TOKEN to the same value on both the plugin's environment and the
server's environment. That gates:
- MCP tool calls against the server
- instance registration from the plugin to the server
- the OAuth handshake used by clients that require one (the token has to be typed in during authorization; it isn't handed out automatically)
Without a token, anyone who has the URL has full read/write access to whatever IDA session is open -- decompiling, renaming, patching, all of it. Don't skip the token if the server is reachable from outside your own machine.
What the tools can do
Around 40 tools, roughly grouped as:
- Discovery: list/search functions and strings, imports, segments, entry points,
ida_list_instances - Reading code: decompile (single or batched), disassembly with honest pagination (it tells you if the output was truncated), xrefs, call graphs, a triage tool that ranks functions by how referenced or how large they are
- Types: read/set a function's prototype, set a local variable's type, define structs/enums/unions in Local Types
- Writing to the database: rename functions and locals, set comments (function-level or at a specific address), a persistent per-address note store that survives across sessions
- Binary-level: raw byte reads, hex pattern search, immediate-value search, a heuristic vtable finder, byte patching, defining data items
- Objective-C: class and method listing for Mach-O binaries, read from
_OBJC_CLASS_$_symbols and+[Class sel]/-[Class sel]naming - Comparing binaries: decompile the same or different targets across two IDA instances side by side -- useful for diffing a patched build against the original, or a symboled build against a stripped one
A few of these are marked experimental in their descriptions -- mostly around byte-pattern search and struct/type APIs that have moved between IDA versions in the past (IDA 9.x renamed or relocated a handful of functions this project already ran into and worked around). If one of them fails, the error message says what actually broke rather than a generic failure.
Known limitations
- The Objective-C method scan relies on standard naming conventions
(
+[Class sel]); it won't find much in binaries where those names have been stripped or where the code is mostly Swift. - The vtable finder is a heuristic (runs of pointers into real functions in non-executable segments) and can both miss real vtables and flag things that aren't. Narrow it to a specific segment on large binaries or it can be slow.
- Byte patching and struct/data creation write directly to the IDA database. There's no undo built in beyond what IDA itself offers.
License
MIT, see LICENSE.