IDA Pro MCP uses a modular API system where every exported tool is a plain Python function decorated withDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/mrexodia/ida-pro-mcp/llms.txt
Use this file to discover all available pages before exploring further.
@tool and @idasync. Adding a new tool requires no registration, routing, or boilerplate beyond the function itself — the decorators handle everything automatically.
Tool decorator pattern
Every tool function must use two decorators:@tool registers it with the MCP server, and @idasync routes the call to the IDA main thread where all SDK operations must run.
@tool must be the outermost decorator and @idasync immediately below it. Reversing the order will break tool registration.
A complete example
The following example shows a fully idiomatic tool function with type hints, docstring, batch input, and address parsing:API conventions
Following these conventions keeps new tools consistent with the rest of the codebase. Batch-first design. Accept a list or a comma-separated string for any multi-item input. Usenormalize_list_input() to handle both forms uniformly.
Annotated[...] descriptions. Every parameter should carry a human-readable description inside Annotated[...]. This string becomes part of the MCP schema that LLM clients see.
list[dict] for batch results. Every item in the list should have a consistent shape. Include an "error" key (string or None) so callers can distinguish per-item failures without raising an exception.
Common helpers
Import these fromutils.py rather than reimplementing them:
| Helper | Purpose |
|---|---|
parse_address(s) | Convert a hex string, decimal string, or symbol name to an integer address |
normalize_list_input(v) | Accept either a comma-separated string or a Python list; always returns a list |
normalize_dict_list(v) | Same as above but for TypedDict items |
paginate(items, query) | Apply offset/count pagination to a list, returning a Page result |
pattern_filter(items, pat) | Filter a list of strings by a glob pattern |
Unsafe tools
Debugger controls and destructive operations must be marked with@unsafe. This hides them from the default tool list and prevents accidental use:
The decorator order for unsafe tools is
@unsafe outermost, then @tool, then @idasync. The unsafe decorator only adds the function name to the MCP_UNSAFE set; it does not wrap the function.Choosing the right file
Place new tools in theapi_*.py file whose scope best matches the operation:
api_core.py
IDB metadata, function listing, string search, imports, integer conversion
api_analysis.py
Decompilation, disassembly, xrefs, call graphs, pattern search, basic blocks
api_memory.py
Raw byte reads, integer reads and writes, string reads, memory patching
api_types.py
Struct definitions, type inference, type application, type export
api_modify.py
Comments, renaming functions/globals/locals, assembly patching
api_stack.py
Stack frame inspection and variable declaration
api_debug.py
Debugger control — use
@unsafe for all tools in this fileapi_python.py
Arbitrary Python execution in the IDA context
api_<name>.py file in src/ida_pro_mcp/ida_mcp/. It will be loaded automatically.
Testing with MCP inspector
After adding a tool, launch the MCP inspector to verify it appears and behaves correctly:Locate your tool
Navigate to the Tools tab. Your new function should appear with the docstring as its description and the
Annotated texts as parameter descriptions.Call the tool
Fill in test arguments and click Run. Confirm the return value matches your expected shape and that errors are surfaced as per-item
"error" fields rather than exceptions.Write a test
Add a
@test() function immediately after your tool definition. See Testing IDA Pro MCP tools for the full workflow.