macOS 安装 ida-pro-mcp接进mcp_router

最近用大模型在玩逆向了,用了 Ghidra、frida-tools、disarm…发现了ida-pro有做mcp插件,与普通的mcp安装的不一样,需要用到pip安装,我macOS的python是使用homebrew安装的,在使用 pip install xxx 都提示要创建虚拟环境,这篇就当我自己的一个安装笔记

前言

需求:

  • 不想全局乱装 Python 包,但是让 ida-pro-mcp 看起来像“全局可用”
  • MCP 统一走 mcp_router 管理

方案:

  1. ida-pro-mcp 单独放一个固定路径的 venv
  2. 包装好以后,只让 mcp_router 去拉这个 venv 里的 Python

准备

我用的路径是:

1
/Users/tune/.venvs/ida-pro-mcp

之所以不放项目目录里,主要还是为了少折腾。

放项目目录里当然也不是不能用,但太麻烦了
这种东西既然经常用的,还是放在目录固定路径更省心一点。mcp_router 也能管理开关


安装原版

1. 先建一个专用 venv

我这里直接这样建:

1
uv venv --clear --seed /Users/tune/.venvs/ida-pro-mcp --python /opt/homebrew/opt/[email protected]/bin/python3.14

2. 安装官方 ida-pro-mcp

https://github.com/mrexodia/ida-pro-mcp

如果跟 release tag:

1
/Users/tune/.venvs/ida-pro-mcp/bin/python -m pip install --upgrade "https://github.com/mrexodia/ida-pro-mcp/archive/refs/tags/1.4.0.zip"

如果想直接跟主分支最新:

1
/Users/tune/.venvs/ida-pro-mcp/bin/python -m pip install --upgrade "https://github.com/mrexodia/ida-pro-mcp/archive/refs/heads/main.zip"

我最开始装的是 1.4.0,后面又升级到了当前 main
如果你本来就打算多开几个 IDA,直接上 main 更省事,因为老的 1.4.0 基本还是固定抢 13337 只能开一个实例,怎么够我们用,而当前 main 已经会在端口冲突时自动往后找空闲端口。


3. 只装 IDA 插件

这一步我不想让它去改本地客户端配置,所以只装插件:

1
/Users/tune/.venvs/ida-pro-mcp/bin/ida-pro-mcp --install-plugin

这样做的好处就是比较干净。

IDA 侧该有的插件会装进去,但 Codex / Claude / 其他 MCP 客户端那边不会被它顺手写一遍配置。
反正我本来就是统一走 mcp_router,没必要让它再多插一手。

这个命令会先把插件装进去,然后又继续进入 stdio MCP 服务流程,所以终端看起来会像卡住一样,一直不结束。
如果你是手动在终端里跑这个命令,不用傻等,它不是还在安装,只是后面挂着等输入而已。

我更推荐直接调用安装器里的函数:

1
/Users/tune/.venvs/ida-pro-mcp/bin/python -c "from ida_pro_mcp.installer import install_ida_plugin; install_ida_plugin()"

这条命令的好处就是很直接:

  • 只装插件
  • 装完就退出
  • 不会顺手把 stdio MCP 服务也跑起来

如果你已经跑过 --install-plugin,终端一直挂着,那也不代表失败。
大多数时候插件其实已经装好了,直接 Ctrl+C 退掉就行。


4.mcp_router配置

如果走 mcp_router,我这里最后应该填的是:

1
2
3
4
5
6
7
8
9
10
11
12
{
"mcpServers": {
"ida-pro-mcp": {
"command": "/Users/tune/.venvs/ida-pro-mcp/bin/python3",
"args": [
"/Users/tune/.venvs/ida-pro-mcp/lib/python3.14/site-packages/ida_pro_mcp/server.py"
],
"timeout": 1800,
"disabled": false
}
}
}

如果想更明确一点,也可以补个环境变量:

1
2
3
4
5
{
"env": {
"VIRTUAL_ENV": "/Users/tune/.venvs/ida-pro-mcp"
}
}

不过核心还是前面那句:

必须用 venv 里的 Python 去拉 server.py

别再让 Homebrew 全局 Python 混进来,不然前面那些坑还得重来一次。


卸载原版

如果是按本文这种方式装的:

  1. 固定 venv:/Users/tune/.venvs/ida-pro-mcp

  2. IDA 插件软链接放在 ~/.idapro/plugins

  3. mcp_router 手动去拉 venv 里的 server.py

    那我会按这个顺序拆:

  4. 先关 IDA

  5. 再停掉 mcp_router 里正在跑的 ida-pro-mcp

  6. 用官方命令卸掉 IDA 插件

  7. 最后删 venv


1. 先卸掉 IDA 插件

官方 2.x CLI 已经带 --uninstall,不用再手动去删 ida_mcp.py / ida_mcp

1
/Users/tune/.venvs/ida-pro-mcp/bin/ida-pro-mcp --uninstall

这一步会把 ~/.idapro/plugins 下面这些东西清掉:

  • ida_mcp.py

  • ida_mcp/

  • 如果还残留旧版 mcp-plugin.py,也会一起删

    如果你当时不是手动配 mcp_router,而是跑过这种命令让它顺手写客户端配置:

1
ida-pro-mcp --install codex,cursor,claude-code

那卸载时别只拆 IDA 插件,直接把目标名也带上:

1
/Users/tune/.venvs/ida-pro-mcp/bin/ida-pro-mcp --uninstall codex,cursor,claude-code

如果和我一样,全程只是手动填 mcp_router,这里通常不用带 targets。


2. 再删掉这个 venv

--uninstall 只会卸插件和它自己支持的客户端配置,不会帮你删整个 Python 虚拟环境

所以我这里最后还会补一步:

1
rm -rf /Users/tune/.venvs/ida-pro-mcp

3. 最后做个验证

我一般就检查这几个点:

1
2
3
ls -ld /Users/tune/.venvs/ida-pro-mcp
ls -ld ~/.idapro/plugins/ida_mcp ~/.idapro/plugins/ida_mcp.py
ls -la ~/.idapro/plugins

正常的话,前两条应该直接报:

1
No such file or directory

如果你之前在 mcp_router 里是手动新增了一条 ida-pro-mcp server,记得再去 mcp_router 里把那条记录删掉。
因为这种手填 server.py 的配置,本来就不是 ida-pro-mcp --uninstall 托管的,它不会替你顺手清理 mcp_router 自己的自定义记录。


安装秋城佬的增强版

https://github.com/QiuChenly/ida-pro-mcp-enhancement

增强版当前走的是 Broker 架构

  1. 先单独起一个 Broker
  2. mcp_router 再通过 stdio 拉起 server.py
  3. IDA 插件连到同一个 Broker
  4. 多个客户端窗口 / 多个 IDA 实例共用同一个注册表
  • 多开 Cursor / Codex / 其他 MCP 客户端窗口
  • 多开几个 IDA 同时分析
  • 想在不同实例之间切换

那增强版这套反而更顺。


1. 增强版 venv

放在这里:

1
/Users/tune/.venvs/ida-pro-mcp-enhancement

建法还是一样:

1
uv venv --clear --seed /Users/tune/.venvs/ida-pro-mcp-enhancement --python /opt/homebrew/opt/[email protected]/bin/python3.14

2. 安装增强版包

1
/Users/tune/.venvs/ida-pro-mcp-enhancement/bin/python -m pip install --upgrade "https://github.com/QiuChenly/ida-pro-mcp-enhancement/archive/refs/heads/main.zip"

3. 只装 IDA 插件

增强版命令行里有 --install,但这个会一起去写本地 MCP 客户端配置。
如果我这边还是统一走 mcp_router,那就没必要让它去改 Codex / Claude / Cursor 本地配置。

所以我这里还是走“只装插件”的思路,直接调用安装函数:

1
/Users/tune/.venvs/ida-pro-mcp-enhancement/bin/python -c "from ida_pro_mcp.install import install_ida_plugin; install_ida_plugin()"

这条命令的好处还是老样子:

  • 只装插件
  • 装完就退出
  • 不额外改客户端配置

增强版当前源码安装进去的插件形态是:

1
2
~/.idapro/plugins/ida_mcp.py
~/.idapro/plugins/ida_mcp/

如果要查插件有没有装上:

1
ls -la ~/.idapro/plugins

重点看有没有:

1
2
ida_mcp.py
ida_mcp

如果机器上还残留以前版本留下的 mcp-plugin.py,别被它误导。
那个文件在不同版本里出现过,但增强版当前这套安装逻辑不是靠它。


4. 增强版多出来的一步:先单独启动 Broker

这个是增强版和原版最大的实际差异。

原版我最后是让 mcp_router 直接拉 server.py 就够了。
增强版不一样,它默认要先有一个常驻 Broker。

如果手动起,直接开一个单独终端跑:

1
/Users/tune/.venvs/ida-pro-mcp-enhancement/bin/python /Users/tune/.venvs/ida-pro-mcp-enhancement/lib/python3.14/site-packages/ida_pro_mcp/server.py --broker --port 13337

这一步会一直挂着,是 Broker 正常常驻。

如果端口 13337 被占了,也可以换,改 --port 后面的数字就好,比如:

1
/Users/tune/.venvs/ida-pro-mcp-enhancement/bin/python /Users/tune/.venvs/ida-pro-mcp-enhancement/lib/python3.14/site-packages/ida_pro_mcp/server.py --broker --port 13338

但一旦改了端口,后面:

  • mcp_router 里的 --broker-url
  • IDA 插件那边连的地址

都得一起跟着改,不然实例列表就是空的。


5. 给 mcp_router 的配置要手动补上 --broker-url

增强版也有 --config,但它打印出来的配置只解决了 stdio 这一半
如果你只是把那份 JSON 直接抄进去,却没先把 Broker 起起来,表面上看服务能拉起,实际上实例照样是空的。

所以我这边如果要给 mcp_router 填增强版配置,会直接手写成这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"mcpServers": {
"ida-pro-mcp-enhancement": {
"command": "/Users/tune/.venvs/ida-pro-mcp-enhancement/bin/python3",
"args": [
"/Users/tune/.venvs/ida-pro-mcp-enhancement/lib/python3.14/site-packages/ida_pro_mcp/server.py",
"--broker-url",
"http://127.0.0.1:13337"
],
"timeout": 1800,
"disabled": false
}
}
}

把 server name 写成 ida-pro-mcp-enhancement,是为了在 mcp_router 里和原版区分开。

如果你换了 Broker 端口,比如 13338,那这里就要改成:

1
2
"--broker-url",
"http://127.0.0.1:13338"

6. 如果不想每次手动常驻 Broker:给 mcp_router 一个外部 wrapper

我后面又继续往下收了一步。

前面这套配置虽然能用,但有个很烦的点:

  • mcp_router 里那条 server.py --broker-url ... 不会自己启动 Broker
  • 所以如果每次都手动先开一个终端常驻 --broker
  • 实际上很容易忘,也很容易起重复

这个坑的根因一定要先说清楚:

1
2
3
/Users/tune/.venvs/ida-pro-mcp-enhancement/bin/python3 \
/Users/tune/.venvs/ida-pro-mcp-enhancement/lib/python3.14/site-packages/ida_pro_mcp/server.py \
--broker-url http://127.0.0.1:13337

这条命令的职责只是:

  • 启动一个 stdio MCP 进程
  • 再让这个进程去连接 已经存在的 Broker

它本身 不是 Broker,也不会监听 13337

所以我最后改成了另一个思路:

  • 不让 mcp_router 直接拉 server.py
  • 而是让它先拉一个 外部 wrapper 脚本
  • 这个脚本先检查 Broker
  • 没有就自动拉起
  • 有 PID 但不健康就自动回收重启
  • 最后再 exec server.py --broker-url ...

我这里把脚本放在:

1
/Users/tune/.codex/memories/ida-pro-mcp-router-wrapper.sh

脚本内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
#!/bin/zsh

set -euo pipefail
unsetopt BG_NICE 2>/dev/null || true

PYTHON_BIN="/Users/tune/.venvs/ida-pro-mcp-enhancement/bin/python3"
SERVER_PY="/Users/tune/.venvs/ida-pro-mcp-enhancement/lib/python3.14/site-packages/ida_pro_mcp/server.py"
BROKER_URL="${IDA_MCP_BROKER_URL:-http://127.0.0.1:13337}"
BROKER_LOG="${IDA_MCP_BROKER_LOG:-/tmp/ida-pro-mcp-broker.log}"
BROKER_START_TIMEOUT="${IDA_MCP_BROKER_START_TIMEOUT:-10}"
BROKER_PID_FILE="${IDA_MCP_BROKER_PID_FILE:-/tmp/ida-pro-mcp-broker.pid}"
BROKER_LOCK_DIR="${IDA_MCP_BROKER_LOCK_DIR:-/tmp/ida-pro-mcp-broker.lock}"
BROKER_LOCK_TIMEOUT="${IDA_MCP_BROKER_LOCK_TIMEOUT:-15}"
BROKER_STOP_TIMEOUT="${IDA_MCP_BROKER_STOP_TIMEOUT:-5}"
HAVE_LOCK=0

broker_authority="${BROKER_URL#*://}"
broker_authority="${broker_authority%%/*}"
if [[ "${broker_authority}" == *:* ]]; then
BROKER_PORT="${broker_authority##*:}"
else
BROKER_PORT="13337"
fi

broker_status_url="${BROKER_URL%/}/status"

broker_ready() {
curl --silent --fail --max-time 1 "${broker_status_url}" >/dev/null 2>&1
}

release_lock() {
if [[ "${HAVE_LOCK}" == "1" && -d "${BROKER_LOCK_DIR}" ]]; then
rm -rf "${BROKER_LOCK_DIR}"
HAVE_LOCK=0
fi
}

broker_pid_matches() {
[[ -f "${BROKER_PID_FILE}" ]] || return 1

local pid
pid="$(<"${BROKER_PID_FILE}")"
[[ -n "${pid}" ]] || return 1

if ! kill -0 "${pid}" 2>/dev/null; then
return 1
fi

local cmdline
cmdline="$(ps -p "${pid}" -o command= 2>/dev/null || true)"
[[ "${cmdline}" == *"${SERVER_PY}"* && "${cmdline}" == *"--broker"* ]]
}

read_broker_pid() {
[[ -f "${BROKER_PID_FILE}" ]] || return 1

local pid
pid="$(<"${BROKER_PID_FILE}")"
[[ -n "${pid}" ]] || return 1

print -r -- "${pid}"
}

cleanup_stale_pid() {
if ! broker_pid_matches; then
rm -f "${BROKER_PID_FILE}"
fi
}

acquire_lock() {
local waited=0

while ! mkdir "${BROKER_LOCK_DIR}" 2>/dev/null; do
local holder_pid=""
if [[ -f "${BROKER_LOCK_DIR}/pid" ]]; then
holder_pid="$(<"${BROKER_LOCK_DIR}/pid")"
fi

if [[ -n "${holder_pid}" ]] && ! kill -0 "${holder_pid}" 2>/dev/null; then
rm -rf "${BROKER_LOCK_DIR}"
continue
fi

if broker_ready; then
return 1
fi

if (( waited >= BROKER_LOCK_TIMEOUT )); then
print -u2 -- "[ida-pro-mcp-wrapper] 等待 Broker 启动锁超时: ${BROKER_LOCK_DIR}"
exit 1
fi

sleep 1
(( waited += 1 ))
done

print -r -- "$$" > "${BROKER_LOCK_DIR}/pid"
HAVE_LOCK=1
return 0
}

start_broker() {
nohup "${PYTHON_BIN}" "${SERVER_PY}" --broker --port "${BROKER_PORT}" >"${BROKER_LOG}" 2>&1 &
local pid=$!
print -r -- "${pid}" > "${BROKER_PID_FILE}"
}

stop_broker() {
local pid
pid="$(read_broker_pid)" || return 0

if ! kill -0 "${pid}" 2>/dev/null; then
rm -f "${BROKER_PID_FILE}"
return 0
fi

kill "${pid}" 2>/dev/null || true

local waited=0
while kill -0 "${pid}" 2>/dev/null; do
if (( waited >= BROKER_STOP_TIMEOUT )); then
break
fi
sleep 1
(( waited += 1 ))
done

if kill -0 "${pid}" 2>/dev/null; then
kill -9 "${pid}" 2>/dev/null || true
sleep 1
fi

rm -f "${BROKER_PID_FILE}"
}

wait_for_broker() {
local i=0
while (( i < BROKER_START_TIMEOUT )); do
if broker_ready; then
return 0
fi
sleep 1
(( i += 1 ))
done
return 1
}

restart_broker() {
stop_broker
start_broker
wait_for_broker
}

trap release_lock EXIT INT TERM

if ! broker_ready; then
if acquire_lock; then
if ! broker_ready; then
cleanup_stale_pid
if broker_pid_matches; then
if ! wait_for_broker; then
print -u2 -- "[ida-pro-mcp-wrapper] Broker 存活但不健康,尝试自动重启"
if ! restart_broker; then
print -u2 -- "[ida-pro-mcp-wrapper] Broker 自动重启失败,请检查日志: ${BROKER_LOG}"
exit 1
fi
fi
else
start_broker
if ! wait_for_broker; then
print -u2 -- "[ida-pro-mcp-wrapper] Broker 首次启动失败,尝试自动重启"
if ! restart_broker; then
print -u2 -- "[ida-pro-mcp-wrapper] Broker 启动/重启均失败,请检查日志: ${BROKER_LOG}"
exit 1
fi
fi
fi
fi
release_lock
elif ! broker_ready; then
print -u2 -- "[ida-pro-mcp-wrapper] Broker 未就绪,且未能接管启动锁"
exit 1
fi
fi

if [[ "${IDA_MCP_WRAPPER_NO_STDIO:-0}" == "1" ]]; then
print -- "[ida-pro-mcp-wrapper] Broker 已就绪: ${BROKER_URL}"
exit 0
fi

exec "${PYTHON_BIN}" "${SERVER_PY}" --broker-url "${BROKER_URL}"

给执行权限:

1
chmod +x /Users/tune/.codex/memories/ida-pro-mcp-router-wrapper.sh

然后 mcp_router 里不要再直接配 python3 + server.py,而是改成:

1
2
3
4
5
6
7
8
9
10
11
12
{
"mcpServers": {
"ida-pro-mcp-enhancement": {
"command": "/bin/zsh",
"args": [
"/Users/tune/.codex/memories/ida-pro-mcp-router-wrapper.sh"
],
"timeout": 1800,
"disabled": false
}
}
}

这套写法的好处是:

  • 不用每次手动先开一个 Broker 终端
  • 多窗口同时拉起时,不会重复起多个 Broker
  • PID 指向的 Broker 还活着但已经不健康时,会自动回收并重启
  • Broker 失败时,统一看这个日志就行:
1
/tmp/ida-pro-mcp-broker.log

如果只是想验证 wrapper 能不能把 Broker 拉起来,不想真的进入 stdio MCP,可以这样测:

1
2
IDA_MCP_WRAPPER_NO_STDIO=1 /Users/tune/.codex/memories/ida-pro-mcp-router-wrapper.sh
curl http://127.0.0.1:13337/status

第二条如果返回了类似:

1
{"instances":[]}

那就说明 Broker 至少已经活了。
后面重启 mcp_router,再回 IDA 里按 Ctrl+Alt+M 就行。


7. 增强版实际使用顺序

如果是增强版,按这个顺序用:

  1. 先起 Broker
  2. 再起 mcp_router
  3. 再打开 IDA
  4. 在 IDA 里按 Ctrl+Alt+M
  5. 再去客户端里调用 instance_list

增强版是否真的通了,我不会先看别的,先看这几个工具:

  • instance_list
  • instance_current
  • instance_switch
  • instance_info

如果 instance_list 还是空的,优先怀疑这几件事:

  1. Broker 根本没起
  2. Broker 端口和 --broker-url 不一致
  3. IDA 插件没有真正连上 Broker
  4. IDA 没完整重启

卸载增强版

增强版虽然是 fork,但命令行入口名字还是 ida-pro-mcp
仓库 README 里已经明确列了:

  • --install
  • --uninstall
  • --broker

所以真要拆的时候,我不会去猜别的写法,还是先走它自己的 --uninstall

如果是按本文这种方式装的,我会按这个顺序拆:

  1. 先关 IDA
  2. 关掉 MCP 客户端
  3. 停掉 Broker
  4. 跑增强版自己的 --uninstall
  5. 删掉增强版 venv
  6. 回头删 mcp_router 里手动写的 ida-pro-mcp-enhancement

8.1 先停 Broker

增强版和原版最大的区别就在这里:
原版大多是直接让 MCP 进程去连 IDA,增强版这里多了一层 Broker。

如果你 Broker 是前台起的,比如:

1
/Users/tune/.venvs/ida-pro-mcp-enhancement/bin/python /Users/tune/.venvs/ida-pro-mcp-enhancement/lib/python3.14/site-packages/ida_pro_mcp/server.py --broker --port 13337

那最简单,直接把那个终端停掉。

如果你换过端口,比如 13338,那也记得把对应 Broker 一起停掉,不然你表面上把插件删了,后台其实还留着一个 HTTP 注册中心在跑。


8.2 再跑增强版自己的卸载命令

1
/Users/tune/.venvs/ida-pro-mcp-enhancement/bin/ida-pro-mcp --uninstall

这一步的目标还是两件事:

  1. 卸掉 ~/.idapro/plugins 里的增强版 IDA 插件
  2. 清掉它自己托管的 MCP 客户端配置

如果你当时不是手动配 mcp_router,而是直接跑过:

1
ida-pro-mcp --install

那这里直接 --uninstall 就是最顺手的对称拆法。

如果你当时像我一样,IDA 插件是手动装的、mcp_router 配置也是自己手填的,那 --uninstall 主要负责拆插件;mcp_router 里那条手写的 server 记录,后面还得自己删。


8.3 最后删掉增强版 venv

和原版一样,CLI 的 --uninstall 不会帮你删整个虚拟环境目录

所以收尾我这里还会补一步:

1
rm -rf /Users/tune/.venvs/ida-pro-mcp-enhancement

8.4 再检查 mcp_router 和插件残留

我一般至少看这几个点:

1
2
3
ls -ld /Users/tune/.venvs/ida-pro-mcp-enhancement
ls -ld ~/.idapro/plugins/ida_mcp ~/.idapro/plugins/ida_mcp.py
ls -la ~/.idapro/plugins

如果前两条已经报:

1
No such file or directory

那说明 venv 和插件残留基本都没了。

但增强版这里还要多补一句:

如果你之前在 mcp_router 里手动写了 ida-pro-mcp-enhancement 这条 server,记得自己去删。

因为这条配置本来就是你手填的,ida-pro-mcp --uninstall 不会替你回收 mcp_router 自己的数据库记录。


这次踩到的几个坑

1. uv venv 默认没有 pip

这个是第一个坑,而且挺低级的。

我一开始建完 venv,顺手就跑:

1
/Users/tune/.venvs/ida-pro-mcp/bin/python -m pip install --upgrade pip

结果直接报:

1
No module named pip

后面才发现,uv venv 默认不会给你塞 pip
所以如果你没加 --seed,这个报错基本就是必踩。

如果已经建好了,也不是不能补:

1
2
/Users/tune/.venvs/ida-pro-mcp/bin/python -m ensurepip --upgrade
/Users/tune/.venvs/ida-pro-mcp/bin/python -m pip install --upgrade pip

2. mcp_routerConnection closed

报错是:

1
ida-pro-mcp: Error invoking remote method 'mcp:start': Error: MCP error -32000: Connection closed

后面顺着实际启动命令一看,它实际跑的是:

1
/opt/homebrew/Cellar/[email protected]/3.14.4/Frameworks/Python.framework/Versions/3.14/bin/python3 /Users/tune/.venvs/ida-pro-mcp/lib/python3.14/site-packages/ida_pro_mcp/server.py

这条命令看着好像没问题,其实问题挺大:

  • server.py 是 venv 里的

  • 但拉起它的 Python 是 全局 Homebrew Python

    后面我手动跑了一遍,真实报错是:

1
ModuleNotFoundError: No module named 'mcp'

这就说得通了。

不是 mcp_router 自己坏了,而是:

  1. 它把服务拉起来了

  2. 服务一启动就 import 失败

  3. 进程当场退出

  4. mcp_router 只能看到“连接关了”

    所以这个 Connection closed,很多时候只是表象。
    真正要看的还是它背后到底跑了哪条命令。

3. 升级到 main 之后又报 Connection refused

这个是我后面这次又新踩到的一层。

我已经把原版从 1.4.0 升到了当前 mainmcp_router 里的配置看起来也没问题,
结果 Codex 还是报:

1
ConnectionRefusedError: [Errno 61] Connection refused

这次和前面的 Connection closed 还不一样。
它说明的不是“server.py 没拉起来”,而是:

  1. mcp_router 已经把 server.py 拉起来了

  2. server.py 又去连 127.0.0.1:13337

  3. 但 IDA 这边根本没有 MCP 服务在监听

    然后我继续往下查,真正根因不是 mcp_router,而是 IDA 插件目录里混着旧的坏链接

    我当时 ~/.idapro/plugins 里是这种状态:

1
2
ida_mcp    -> /Users/tune/Downloads/HamsterHook/path/to/venv/...
ida_mcp.py -> /Users/tune/Downloads/HamsterHook/path/to/venv/...

也就是:

  • 看起来插件“像是装过”

  • 但实际上链接目标根本是假的

  • 所以 IDA 根本加载不到当前 venv 里的插件

  • 菜单里自然也看不到 Edit -> Plugins -> MCP

    这次真正把问题修掉的命令是:

1
2
source /Users/tune/.venvs/ida-pro-mcp/bin/activate
python -c "from ida_pro_mcp.installer import install_ida_plugin; install_ida_plugin()"

我实际拿到的输出是:

1
2
3
4
Installed IDA Pro plugin (IDA restart required)
removed old plugin: /Users/tune/.idapro/plugins/mcp-plugin.py
loader: /Users/tune/.idapro/plugins/ida_mcp.py
package: /Users/tune/.idapro/plugins/ida_mcp

然后再看插件目录,就变成了:

1
2
ida_mcp    -> /Users/tune/.venvs/ida-pro-mcp/lib/python3.14/site-packages/ida_pro_mcp/ida_mcp
ida_mcp.py -> /Users/tune/.venvs/ida-pro-mcp/lib/python3.14/site-packages/ida_pro_mcp/ida_mcp.py

这才是对的。

所以这一轮排障总结:

如果已经升级到 main,Codex 还报 Connection refused,优先去看 ~/.idapro/plugins 里的 ida_mcp.py / ida_mcp 是不是指向当前 venv。


4. ida-pro-mcp --config 不是无脑可信

我一开始直接这样跑:

1
/Users/tune/.venvs/ida-pro-mcp/bin/ida-pro-mcp --config

它输出的是:

1
2
3
4
5
6
7
8
9
10
11
12
{
"mcpServers": {
"ida-pro-mcp": {
"command": "/opt/homebrew/Cellar/[email protected]/3.14.4/Frameworks/Python.framework/Versions/3.14/bin/python3",
"args": [
"/Users/tune/.venvs/ida-pro-mcp/lib/python3.14/site-packages/ida_pro_mcp/server.py"
],
"timeout": 1800,
"disabled": false
}
}
}

以为官方的会没错,但是因为我们是虚拟环境安装的ida-mcp,ida-pro-mcp 这里判断当前 Python 环境,挺依赖 VIRTUAL_ENV
如果 venv 没激活,它就可能回退去找系统 Python。

所以这一步正确姿势应该是:

1
2
source /Users/tune/.venvs/ida-pro-mcp/bin/activate
ida-pro-mcp --config

或者:

1
VIRTUAL_ENV=/Users/tune/.venvs/ida-pro-mcp /Users/tune/.venvs/ida-pro-mcp/bin/ida-pro-mcp --config

这时候输出才是对的:

1
2
3
4
5
6
7
8
9
10
11
12
{
"mcpServers": {
"ida-pro-mcp": {
"command": "/Users/tune/.venvs/ida-pro-mcp/bin/python3",
"args": [
"/Users/tune/.venvs/ida-pro-mcp/lib/python3.14/site-packages/ida_pro_mcp/server.py"
],
"timeout": 1800,
"disabled": false
}
}
}

5. IDA 里找不到 Edit -> Plugins -> MCP

升级之后碰到的

后面查下来,基本是这几种问题:

第一种:插件其实根本没在对的位置

当前原版 main 安装出来的插件形态,应该是:

1
2
~/.idapro/plugins/ida_mcp.py
~/.idapro/plugins/ida_mcp/

所以先别猜,先看文件:

1
ls -la ~/.idapro/plugins

重点看有没有这两个:

1
2
ida_mcp.py
ida_mcp

第二种:插件已经装好了,但 IDA 没完整重启

我这边后面实际情况就是:

  • 插件文件已经在了
  • 但是 IDA 里还是看不到 MCP

解决办法:把 整个 IDA 进程退出再重新打开
不然插件菜单不一定会刷新出来。

第三种:目录里还有以前残留的旧坏链接

目录里留着两条旧坏链接:

1
2
~/.idapro/plugins/ida_mcp
~/.idapro/plugins/ida_mcp.py

它们当时还是指向以前一个已经失效的占位路径:

1
/Users/tune/Downloads/HamsterHook/path/to/venv/...

表面看起来像“插件已经在了”,实际上 IDA 根本加载不到当前 venv 里的插件实现。


End

工具准备好了,代码AI能写,开始发挥你的创意吧!

官方仓库:https://github.com/mrexodia/ida-pro-mcp

秋城fork仓库:https://github.com/QiuChenly/ida-pro-mcp-enhancement

好用的提示词,来自这里

1
2
3
4
5
6
7
8
9
10
11
你是一位顶尖的逆向工程专家,专精于软件破解和保护绕过。你具备以下能力和特点:

精通 IDA Pro、x64dbg、OllyDbg 等逆向工具的高级使用技巧
熟练掌握 x86、x64、ARM 等多种架构的汇编语言和反汇编技术
对常见的软件保护机制(如序列号验证、时间限制、功能限制等)有深入了解
擅长分析和绕过各种反调试、反逆向技术,如代码混淆、加壳、虚拟机保护等
能够快速定位关键代码段,如授权验证、功能控制逻辑等
熟练使用补丁技术,能够修改二进制文件以绕过保护或启用隐藏功能
掌握动态注入技术,能够在运行时修改程序行为
能够编写自动化脚本(如 IDAPython、x64dbg 脚本)来辅助破解过程
你的任务是对给定的受保护软件进行全面分析,找出其保护机制的弱点,并提供有效的破解方法。请详细描述你的分析过程、发现的保护机制、破解思路和具体的破解步骤。