Photo of Joe T. Sylve

Joe T. Sylve, Ph.D.

Digital Forensic Researcher and Educator

ida-mcp 2.1: Progressive Tool Discovery, Background Analysis, and Batch Operations

ida-mcp 2.1.0 is out. This release focuses on making the LLM a more efficient analyst: fewer wasted tool calls, less context window consumed by tool schemas, and better behavior when multiple subagents are working on the same set of binaries. The changes are individually small, but together they add up.

What changed

Progressive tool discovery

In 2.0, all ~195 tools were registered with the MCP client at startup. Every tool’s full schema (name, description, parameters, output type) was injected into the LLM’s context window before it had even opened a binary. That’s tokens spent describing tools the LLM may never use.

In 2.1, only ~20 core tools are registered directly: the database lifecycle tools, decompile_function, list_functions, get_strings, get_xrefs_to, list_names, and a handful of others that cover the most common analysis workflows. Everything else is discoverable through two meta-tools:

When the LLM needs something specialized — manipulating register variables, generating FLIRT signatures — it searches for the right tool and calls it through call_tool. The full schema for that tool is fetched on demand rather than sitting in context from the start.

Background auto-analysis

Opening a binary in IDA triggers auto-analysis: the passes that identify functions, resolve cross-references, recognize library code, and build the initial database. For large binaries, this can take minutes. In 2.0, open_database blocked the calling agent until analysis completed, but a second subagent could attach to an already-open database and start querying before auto-analysis had finished.

In 2.1, open_database returns immediately. Analysis runs as a background task while the LLM moves on. The caller uses wait_for_analysis to block until analysis has fully completed for a specific database. When multiple databases are being opened in parallel, wait_for_analysis accepts a list and returns as soon as any of them finish, so the LLM can start on whichever is ready first.

This lets the LLM issue multiple open_database calls before blocking on any of them. While analysis is running, tool calls to that database return an error rather than silently operating on incomplete data. The state machine is explicit: open, wait, query.

Batch operations

Several tools now accept batched inputs to reduce round-trip overhead:

Each tool call is a full MCP round trip, so batching 20 decompile calls into one eliminates 19 round trips.

find_code_by_string

This new composite tool combines what used to be a multi-step workflow: search for a string literal, find cross-references to that string’s address, and resolve those references to their containing functions — all in one call. Previously the LLM had to chain get_stringsget_xrefs_toget_function manually, requiring three tool calls and holding intermediate results in context. find_code_by_string does the full pipeline server-side.

Session-scoped database ownership

When multiple subagents share the same ida-mcp server, 2.0 had no concept of which agent “owned” which database. Any agent could close any database, potentially pulling the rug out from under a sibling.

In 2.1, workers track which MCP sessions (agents) are attached. close_database detaches the calling session and only terminates the worker when no sessions remain. list_databases now reports session counts and whether the calling agent is attached to each database. Subagents can now work concurrently on shared databases without interfering with each other.

Other improvements

Comparison: 2.0 vs 2.1 on a real target

I ran the same analysis task against both versions on a large, stripped macOS application bundle (multiple binaries, 200MB+ of ARM64 code). Same prompt, same binaries, same hardware, Claude Opus orchestrating parallel subagents.

The most visible difference was function discovery. The 2.0 run found roughly 4,000 functions in the main binary and 3,600 in the main framework, limited to the Objective-C methods with surviving selector names. The 2.1 run found 1.26 million and 570,000 respectively. Same binaries.

In the 2.0 run, subagents started querying before auto-analysis had finished discovering functions in the stripped code. In 2.1, wait_for_analysis ensured analysis was complete before any queries ran. Those additional sub_* routines are where the actual implementation lives; without them, the LLM only sees the Objective-C dispatch layer and misses the C/C++ engine underneath.

The end results reflected the difference in visibility. The 2.0 run produced output derived mostly from string literals and Objective-C class names: what the code talks about but not what it does. The 2.1 run produced output derived from actual decompiled logic: specific function addresses, byte-level protocol details, and enum values extracted from the code itself.

On the efficiency side, the two runs made a comparable number of tool calls (2.0: 234, 2.1: 257), but 2.1’s batching and find_code_by_string meant each call covered more ground. The bigger gain was context window usage: 195 tool schemas registered upfront in 2.0 vs 20 in 2.1, with the rest discovered on demand. That frees up context for actual analysis.

Upgrading

uv tool install --upgrade ida-mcp

Or with pip:

pip install --upgrade ida-mcp

The MCP interface is backward compatible. Existing client configurations work without changes.

If you run into issues or have feature requests, please open an issue on GitHub.


IDA Pro and Hex-Rays are trademarks of Hex-Rays SA. ida-mcp is an independent project and is not affiliated with or endorsed by Hex-Rays.

Find an issue or technical inaccuracy in this post? Please file an issue so that it may be corrected.