# 史诗级调试之旅:从 v0.4.5 到 v0.4.33
这是一份对 `remote-terminal-mcp` 项目在v0.4.x版本期间所经历的一系列复杂问题的深度复盘与调试日志。这个过程充分展示了从表象问题出发,通过结构化思维、假设、验证和迭代,最终找到并解决底层系统性问题的完整软件工程实践。
## 第一阶段:启动方式切换与"幽灵日志" (v0.4.5 -> v0.4.7)
* **初始目标**: 将MCP服务的启动方式从直接调用Python脚本,改为通过NPM包(`npx`)启动。
* **遇到的问题**: 服务中新增的日志功能(写入`/tmp/`目录)完全不生效。
* **思维过程**:
1. **假设1:代码未发布?** -> `npm view`证实已发布,假设错误。
2. **假设2:路径权限问题?** -> 怀疑macOS沙盒机制。将路径改为项目根目录下的相对路径`path.join(__dirname, '..')`。
3. **问题依旧**: 日志依然未出现。
4. **思维跃迁**: 意识到`npx`的执行目录并非项目目录,而是全局缓存目录。`__dirname`指向的是缓存目录。
* **解决方案 (v0.4.7)**: 将日志路径基准从`__dirname`改为`process.cwd()`,认为`cwd`会是调用`npx`的目录。
## 第二阶段:深潜"静默失败"的根源 (v0.4.7 -> v0.4.24)
* **遇到的问题**: 即便修复了路径,服务依然静默失败,没有任何日志输出。
* **思维过程**:
1. **假设3:NPX缓存?** -> 清理缓存,发布新版,问题依旧。
2. **假设4:Python子进程启动失败?** -> 怀疑是Python脚本没有正确实现MCP"握手"协议。修改Python代码,让其主动发送`server_ready`。问题依旧。
3. **假设5:Python解释器路径问题?** -> 怀疑Cursor的执行环境`PATH`不完整。尝试硬编码`which python3`的绝对路径,失败。尝试`{ shell: true }`,失败。
4. **关键转折点("染色剂测试")**: 为日志文件加入版本号,并在`mcp.json`中强制指定版本。
5. **决定性证据**: 发现运行的依然是旧版本,新代码从未被执行。重启Cursor后,从其主日志中发现了`Permission denied`错误。
* **真相大白**: 问题的**第一个根源**是`npm`在全局安装包时,未能给`bin/cli.js`脚本添加**可执行权限**。
## 第三阶段:从环境问题到代码问题的"胜利" (v0.4.24 -> v0.4.29)
* **思维过程**:
1. **环境修复**: 采用`npx --package <pkg> -c <cmd>`的命令格式,彻底绕过权限和路径问题。
2. **第一个代码Bug出现**: 看到第一个来自我们代码的错误`ERR_STREAM_CANNOT_PIPE`,证明环境问题已解决。
3. **第二个代码Bug出现**: 修复流处理逻辑后,程序立刻退出。诊断出是主进程在启动子进程后没有保持存活。
4. **第三个代码Bug出现**: 经过大量日志调试,定位到Python脚本路径错误。修复后,看到最终的协议错误`Unexpected token 'C', "Content-Length: ..." is not valid JSON`。
* **解决方案 (v0.4.29)**: 重构Python端的`send_response`函数,确保所有消息都严格遵守JSON-RPC协议。
## 第四阶段:最终的"心脏搭桥手术" (v0.4.29 -> v0.4.33)
* **遇到的问题**: 修复了所有可见问题后,在Cursor中调用工具,依然`Tool not found`。
* **思维过程**:
1. **最后的假设:服务注册失败** -> 推断服务在与Cursor Supervisor"握手"时就已崩溃。
2. **分析黑匣子**: 查看`~/mcp_service_debug.log`日志,发现Python进程在发送`server_ready`后,立刻因`Stdin closed`而退出,并抛出`BrokenPipeError`。
3. **锁定最终真凶**: 问题的**第二个、也是最根本的根源**在于Node.js的`index.js` supervisor逻辑完全错误。它被设计成一个库模块,但在`npx`执行流程中,它从未被正确调用,导致其在启动Python进程后立刻退出,切断了通信管道。
* **解决方案 (v0.4.33)**: 彻底重构`index.js`,将其从一个错误的库模块,改写成一个健壮的、可以直接运行的、能够长期维持子进程生命周期的 supervisor 脚本。
## 总结与反思
这次调试是一次典型的系统工程问题。问题点横跨了 **NPM包管理、`npx`工作机制、macOS文件权限、Node.js/Python进程间通信(IPC)、MCP协议握手、异步事件循环、代码重构和版本发布**等多个领域。
通过这次训练,我们深刻实践了:
* **大胆假设,小心求证**: 不断提出假设,并通过最小化实验去验证它。
* **日志是最终的真相**: 在黑盒环境中,日志是唯一能告诉你发生了什么的"黑匣子"。
* **第一性原理**: 当反复失败时,要敢于推翻最基础的假设。
* **分层解耦**: 一个健壮的系统,其每一层(Supervisor, Python服务, 连接逻辑)都应独立可靠。我们最后通过重构,达成了这一点。