ida-mcp-rs 的 --workspace 模式:AI 如何同时逆向多个二进制数据库
ida-mcp-rs 的 --workspace 模式:AI 如何同时逆向多个二进制数据库
ida-mcp-rs 是一个用 Rust 编写的无头(Headless)IDA Pro MCP Server,让 AI 代理直接驱动 IDA 做逆向工程。它的 --workspace 模式专攻多二进制并行分析的痛点:一次开启后,AI 可以同时打开多个数据库(IDB),为每个二进制分配独立的 database_id 和专属的 IDA 工作进程,实现真正的多库并发逆向——而不是排队等一个库关完再开下一个。
下面这篇指南会带你从"为什么需要它"讲到"怎么稳定跑起来",全程尽量不堆代码。
1️⃣ 为什么需要 --workspace:从"单库"到"多库"
默认情况下,ida-mcp-rs 只服务一个隐式数据库。这意味着:
- AI 想分析第二个二进制时,必须先
close_idb关第一个,否则会报A database is already open; - 多个 AI 客户端共用一个 HTTP 服务时,大家挤在同一个 IDA 上下文里,互相阻塞。
--workspace 模式把"一个隐式库"换成了"一组显式句柄"。每个 open_idb / open_dsc 都会返回一个 database_id,之后所有针对数据库的操作都要带上这个 ID。对比如下:
| 维度 | 默认模式 | --workspace 模式 |
|---|---|---|
| 数据库数量 | 1 个(隐式) | 多个(显式句柄) |
| 工具调用 | 不带库标识 | 必须携带 database_id |
| IDA 工作进程 | 全体共享一个 | 每个库独占一个租约 |
| 并发 | 串行排队 | 多库并发(受上限约束) |
| 找回句柄 | 不支持 | 支持 list_databases |
一句话概括:默认模式是"一个工位",workspace 模式是"一个工位 + 门牌号"。
2️⃣ 一键开启:--workspace 模式配置步骤
开启非常简单,只需加上 --workspace 参数。按需搭配传输方式即可:
# stdio 模式(配合 Claude Code 等 CLI 代理)
ida-mcp --workspace --workspace-max-workers 4
# Streamable HTTP 模式(多客户端、无状态)
ida-mcp --workspace serve-http --bind 127.0.0.1:8765 --stateless
核心参数一目了然:
| 参数 | 默认值 | 作用 |
|---|---|---|
--workspace |
关 | 开启显式多库路由 |
--workspace-max-workers |
4 |
最多可并发服务的库数量 |
--workspace-idle-timeout-secs |
1800 |
空闲库多久后被回收(0 关闭回收) |
--workspace-worker-idle-timeout-secs |
300 |
空闲子进程多久后被清理 |
--workspace-worker-op-timeout-secs |
1800 |
单库操作看门狗,防止卡死 |
💡 提示:workspace 模式用
--workspace-max-workers控制并发,与旧式的--max-workers是两套独立开关,不要混用。
3️⃣ database_id:多库并发的"路牌"
database_id 是整个模式的灵魂——它是每个打开的数据库的"门牌号",格式为 UUID。
# 打开两个二进制,各自拿到一个独立的 database_id
open_idb(path: "~/samples/firmware/boot") # 返回 database_id: "a3f2..."
open_idb(path: "~/samples/malware/sample") # 返回 database_id: "9c11..."
# 之后每次调用都带上对应的 database_id,互不干扰
list_functions(database_id: "a3f2...", limit: 20)
decompile(database_id: "9c11...", address: "0x100000f00")
几个值得新手记住的细节:
- 分配类工具不带 ID:
open_idb本身就是"发门牌号"的工具,它的入参里没有database_id; - 数据库作用域工具必带 ID:
list_functions、decompile、rename等都必须传,漏传会报requires database_id; - 运行时工具拒绝 ID:像
tool_catalog这种全局工具不接受database_id,传了会报runtime-scoped错误。
这种"该带的必须带、不该带的坚决拒"的设计,保证了 AI 不会把对库 A 的修改误伤到库 B。
4️⃣ 隔离与并发:每个库独占一个 IDA 工作进程
为什么多库不会"串味"?关键在于进程级的隔离。
在 --workspace 模式下,每个打开的数据库都独占一个受监督的子工作进程租约(lease),并用自己的 database_id 寻址。不同句柄的调用可以真正并发运行,上限就是 --workspace-max-workers。这套机制的实现集中在 src/ida/pool.rs 的 WorkspaceRegistry 与 WorkerPool 中。
┌──────────────────────────────┐
│ ida-mcp 父进程 │
│ (路由:按 database_id 分发) │
└───────┬───────────┬──────────┘
│ │
┌──────────▼──┐ ┌───▼──────────┐
│ 子工作进程 #1 │ │ 子工作进程 #2 │
│ 库 A (boot) │ │ 库 B (sample)│
└──────────────┘ └──────────────┘
这意味着:
- 修改互不污染:在库 A 里
rename一个函数,库 B 完全不受影响; - 崩溃可隔离:某个库的 IDA 调用崩了,只会替换它对应的那个子进程,其他库照常运行;
- 关闭也精准:
close_idb(database_id: ...)只移除你指定的那一个句柄,其余句柄继续存活。
集成测试 test/stdio_workspace.sh 就专门验证了这一点:它打开两个库、分别在各自库中改名、再关掉第一个,最后确认"改名只停留在它选定的数据库里"、"关闭只失效了被选中的句柄"。
5️⃣ list_databases:AI 丢失句柄后如何找回
database_id 是找回句柄的唯一钥匙,但万一 AI 丢了某次 open_idb 的响应、或走的是无状态 HTTP 重连了怎么办?
这正是 list_databases 工具的用武之地。它只读、且只在 --workspace 下出现,返回所有已路由的 database_id 及其路径和状态(open / busy / no_worker):
list_databases()
# 返回每个句柄的 database_id、数据库路径和当前状态
有了它,AI 就能"凭印象重新定位"一个打开过的库,而不用干等到空闲超时。配合无状态 HTTP 场景尤其有用——因为每个请求都是全新上下文,客户端必须靠 database_id 在请求之间保持对库的连续引用。这个流程在 test/http_workspace.sh 里被验证为"无状态请求间复用同一个显式句柄"。
6️⃣ 空闲回收与守护超时:让服务长期稳定运行
多库服务跑久了,资源回收是新手最容易忽略的坑。--workspace 内置了两级"回收"和一道"看门狗",帮你省心:
- 库级回收:未被占用、也未被打上 pin 的空闲句柄,超过
--workspace-idle-timeout-secs(默认 30 分钟)后自动关闭并从list_databases中消失; - 进程级回收:空闲的子工作进程在
--workspace-worker-idle-timeout-secs(默认 5 分钟)后被清理,释放内存; - 看门狗:如果某次 IDA 调用卡死超过
--workspace-worker-op-timeout-secs(默认 1800 秒),父进程会杀掉那个子进程并返回超时,避免一个卡死的库拖垮整条服务线。
三者各司其职:库 TTL 管"哪些库还该留着",进程 TTL 管"哪些进程该退了",看门狗管"谁卡死了要强制重启"。想长期挂着不回收,把对应超时设为 0 即可。
7️⃣ 典型场景:让 AI 同时分析多个二进制
把上面串起来,一个真实工作流长这样:
- 启动:
ida-mcp --workspace --workspace-max-workers 4起一个可并发 4 个库的服务; - 批量打开:对固件里的
boot、kernel、app各调一次open_idb,拿到三个database_id; - 并行分析:AI 在三个句柄上同时跑
analyze_funcs、list_functions,谁也不等谁; - 跨库对比:分别
decompile两个版本里的同名函数,直接比差异; - 兜底找回:若某次响应丢了,
list_databases一把列出所有存活句柄; - 收尾:逐个
close_idb,或交给空闲超时自动回收。
除了多库分析,--workspace 还是无头调试器的前置条件——debug_open_module 要求 --workspace,因为它要在一个新数据库里加载运行时镜像,同时保持持有调试会话的那个库原封不动。调试会话还会自动给对应库打上 pin,让它跳过空闲回收,直到 debug_stop 或 close_idb 释放。更多场景可参考 docs/TRANSPORTS.md 与 docs/TOOLS.md。
小结
ida-mcp-rs 的 --workspace 模式,用"显式 database_id + 每库独立工作进程"这一组合拳,把 AI 从"一次只能啃一个二进制"解放出来,实现真正的多库并发逆向。对新手来说,只需记住三步:加 --workspace 启动、给每个库记住 database_id、用 list_databases 兜底找回句柄。剩下的回收、隔离、看门狗,模式都替你想好了。
📌 相关实现与文档:多库路由与租约隔离见 src/ida/pool.rs,CLI 参数定义见 src/main.rs,多库路由测试见 test/stdio_workspace.sh 与 test/http_workspace.sh,传输细节见 docs/TRANSPORTS.md。