每次 Claude Code 或 Codex 调用一次 cat、rg 或 git status,都在交一笔隐形的"税":fork + exec + 页面表建立 + 库加载 + syscall 流 + 清理。
对于一个任务发几百个小读操作的 agent 来说,这不是业务逻辑,这是 kernel 开销。
madeye 开源的 mcp-cli 用一个 sidecar-daemon + MCP bridge 架构,把这笔税彻底取消。
核心数字
在 Codex(rust-v0.121.0)分析自身代码库上实测:
| 指标 | 基线 | 使用 mcp-cli | 变化 |
|---|---|---|---|
execve 总调用 | 83 | 22 | −73% |
rg 调用次数 | 13 | 0 | −100% |
sed 调用次数 | 50 | 2 | −96% |
| 墙壁时间 | 201s | 324s | +61%(见正文说明) |
架构
Claude Code / Codex
↓ stdio (MCP)
mcp-cli-bridge ←→ Unix Domain Socket ←→ mcp-cli-daemon(长驻进程)
├── mmap VFS(文件读)
├── libgit2(git 状态)
├── ripgrep searcher(搜索)
└── 未来:tree-sitter、LSP
三层:
mcp-cli-bridge:小型 stdio 二进制,agent 启动时 spawn。负责把 MCP 工具请求翻译成 UDS 调用。生命周期短暂,重量级状态全在 daemon。mcp-cli-daemon:长驻进程,拥有整个项目。用 mmap 做文件读(无需每次read(2)syscall)、用 libgit2 做 git 状态(无需 forkgit)、用 ripgrep 的grep-searcher库做搜索。fs.snapshot/fs.changes:增量同步机制。daemon 在 inotify(Linux)/FSEvents(macOS) 上监听 gitignore 过滤的文件变化,维护单调版本游标,返回自客户端指定版本以来的合并变化事件。如果客户端落后太远,返回overflowed: true让客户端重新扫描而不是静默丢事件。
为什么这样设计
传统 shell-wrapped 工具调用的成本构成:
fork + exec + page-table setup + 库加载 + syscall 流 + 清理
对于发几百个小读操作的 agent,这笔开销不是例外,是常态。
解法:保持一个热 daemon。
- 文件读来自已在 page cache 的 mmap——内核只在 miss 时 page-in,没有每次调用的
readsyscall 流 - Git、搜索、(计划中的)解析操作都在进程内——内核看到的是一个长驻进程,不是 thousands of 短命进程
- Bridge 保持极小,每次调用成本就是一个预热 socket 上的 UDS 往返
这是未来更多层的地基:增量 inotify diffs、tree-sitter 索引、clangd/rust-analyzer 等语言后端复用。
安装与使用
cargo build --release
target/release/mcp-cli install
Daemon 在首次工具调用时自动按项目根目录 spawn,空闲 30 分钟后自动退出,无需手动运行任何东西。
对于 Codex,要额外传 --prefer-mcp 让它真正走 daemon 而不是 fallback 到自己的 Bash:
target/release/mcp-cli install --target codex --prefer-mcp
--prefer-mcp 写入 ~/.codex/config.toml:
[features] shell_tool = false(停用 Codex 内置 Bash 工具)- 每个 mcp-cli 工具设
approval_mode = "approve"(非交互执行时不弹确认)
墙壁时间回归的问题
注意到 mcp-cli 的墙壁时间反而从 201s 增加到 324s(+61%)。这是因为每次 MCP 调用是原子的,而 bash 是管道——两个调用可以合并成一个进程完成。
作者已在迭代解决这个问题:第一个 run 124 MCP turns / 375s,经过 search_grep ?context 合并优化后降到 73 turns / 324s。开放方向包括 compound/batch MCP 工具(合并多个操作)、io_uring I/O、per-request arenas。
现状与路线图
已完成:skeleton、增量同步、tree-sitter 解析缓存、drop-in 安装、per-cwd auto-spawn、reconnect-on-dead、mimalloc + buffer pool、M5/M7 基准测试。
开放项:rust-analyzer / clangd 语言后端、compound/batch MCP 工具(解决 wall-clock 回归)、io_uring I/O、per-request arenas、LSP / WASI 挂载层。