ida-mcp-server/README.md
WiseDev 9cd62a53c1 Merge remote-tracking branch 'origin/main'
# Conflicts:
#	.gitignore
#	README.md
2026-07-31 13:24:49 +03:00

127 lines
6.3 KiB
Markdown

# 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
1. Copy `ida_mcp_plugin.py` into IDA's plugins directory (on macOS, something
like `IDA Professional 9.1.app/Contents/MacOS/plugins/`).
2. Install the server's dependencies and start it:
```bash
pip install httpx starlette uvicorn
python ida-mcp-server.py
```
3. Open IDA. The plugin starts automatically, picks a port, and registers
itself with the server at `http://127.0.0.1:8888` by default.
4. 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 localhost
- `IDA_MCP_ADVERTISE_HOST=<ip reachable from the server>` -- what the plugin tells the server to call it back on
- `IDA_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](LICENSE).