# bolt — 极速单文件 MCP 命令执行服务器 让 AI(Claude Code / Claude Desktop / Cursor 等 MCP 客户端)通过 **MCP 协议**连接后,在服务器上执行 shell 命令。 - **单文件**:全部代码在 `src/main.rs`(约 1900 行,其中 400 行为单元测试),仅依赖 `serde_json`(Unix 下加 `libc`) - **零框架**:手写 JSON-RPC 2.0 + MCP 协议 + Streamable HTTP 服务器,无 async runtime、无重量级依赖 - **双传输**:`stdio`(本地 AI 客户端默认)与 `Streamable HTTP`(远程连接) ## 快速开始 ```bash cargo build --release # 产物: target/release/bolt (~1MB) ``` **本地模式(stdio)**:由 MCP 客户端拉起本进程 ```bash # Claude Code claude mcp add --transport stdio bolt -- /abs/path/to/bolt # 或通用 MCP 客户端配置 # {"mcpServers": {"bolt": {"command": "/abs/path/to/bolt"}}} ``` **远程模式(Streamable HTTP)**:AI 通过网络连接 ```bash bolt --http 127.0.0.1:8080 # 仅本机 bolt --http 0.0.0.0:8080 --token mysecret # 对外 + Bearer 认证 bolt --http 0.0.0.0:8080 --token mysecret --allow "git,docker,curl" # Claude Code 连接远程 claude mcp add --transport http bolt http://127.0.0.1:8080/mcp ``` ## 工具 | 工具 | 说明 | |---|---| | `run_command` | 执行 shell 命令:完整 shell 语法(管道/重定向/`&&`)、`cwd`、`env`、`timeout_ms`(超时自动杀进程树)、`max_output_bytes`(输出截断防膨胀)、`shell=false` 直接执行二进制;客户端可传 `_meta.progressToken` 接收进度通知,支持 `notifications/cancelled` 取消 | | `shell_open` | 开启持久化交互式 shell 会话(`cd`、环境变量等状态跨次保留),可指定 `shell`(sh/bash/zsh/fish)与 `cwd` | | `shell_write` | 向会话写入输入(自动补换行) | | `shell_read` | 读取会话新输出,可阻塞等待(`timeout_ms`,0 = 等到会话退出) | | `shell_close` | 关闭并杀掉会话进程树 | `run_command` 返回:`exit_code` / `signal` / `timed_out` / `cancelled` / `duration_ms` / `stdout` / `stderr` / 截断标志等(同时提供 `content` 与 `structuredContent`)。 ## 配置 CLI 参数(环境变量 `BOLT_*` 为回退): | 参数 | 默认 | 说明 | |---|---|---| | `--http ` | 无(stdio) | 启用 Streamable HTTP 监听地址,如 `127.0.0.1:8080` | | `--token ` | 无 | HTTP 要求 `Authorization: Bearer ` | | `--allow ` | 空 | 命令白名单(命令首词前缀匹配;非空时仅允许列表内命令) | | `--deny ` | 空 | 命令黑名单(前缀匹配) | | `--timeout-ms ` | 30000 | 命令默认超时(工具参数可覆盖,0 = 无限) | | `--cwd ` | 当前 | 命令默认工作目录 | | `--max-output ` | 1M | 单流输出捕获上限(支持 K/M/G) | | `--allow-origin ` | localhost/127.0.0.1 | 额外允许的 HTTP Origin(防 DNS rebinding) | ```bash export BOLT_TOKEN=xxx BOLT_ALLOW="git,docker" BOLT_TIMEOUT_MS=60000 bolt --http 127.0.0.1:8080 ``` ## 协议实现(2025-06-18 规范) - `initialize`(协议版本协商,支持 2024-11-05 / 2025-03-26 / 2025-06-18)、`ping`、`tools/list`、`tools/call`、`shutdown` - `notifications/initialized`、`notifications/cancelled`、`notifications/exit`、`notifications/progress`(进度上报) - 工具执行错误以 `isError: true` 返回;协议错误返回标准 JSON-RPC 错误码(-32601/-32602/-32700 等) - Streamable HTTP:POST 请求(通知 → 202;请求 → JSON 或 SSE 响应)、GET 长连接 SSE 流(服务器通知广播 + 10s 心跳)、CORS、Origin 校验、Bearer 认证、无状态(不要求会话 ID) ## 性能 - 单线程事件循环 + 复用缓冲区,无锁热路径;输出计数用原子操作,进度推送不占主循环 - 子进程独占进程组(`setpgid`),超时/取消按进程组 `SIGKILL`,连带杀掉整棵进程树,无僵尸 - 实测(本机,含 Python 客户端逐字节 I/O 开销): - ping 往返吞吐 ≈ **14,700 msg/s** - 并发 `echo` 命令平均 **4.7 ms/次**(进程 spawn + 捕获输出) - 构建配置:`lto = "fat"`、`codegen-units = 1`、`strip = true`,二进制约 0.7MB ## 测试 ```bash cargo test --release # 8 个单元测试(协议分发/策略/HTTP 解析/执行引擎/会话) ``` 集成测试脚本在 `docs/`(stdio 12 项、HTTP 19 项,覆盖超时/取消/进程树/进度/并发/auth/Origin): ```bash python3 /tmp/bolt_stdio_test.py # stdio 端到端 python3 /tmp/bolt_http_test.py # HTTP 端到端 ``` ## 安全说明 - 默认只接受本机连接(`127.0.0.1`),对外公开需显式 `0.0.0.0` + `--token` - 该服务器等于远程 root shell 入口,务必配置白名单(`--allow`)与认证后再暴露公网 - Unix 下命令在独立进程组运行,取消/超时会连带杀掉子进程 ## 平台 - Linux / macOS(完整功能:进程组杀、信号处理) - Windows(基础功能:`cmd /C`、`taskkill /T` 杀进程树;无信号优雅退出) ## 在其他设备上部署(最快方式) 一键脚本支持 Linux(systemd)和 macOS(launchd),自动识别 amd64 / arm64;Apple Silicon 即使在 Rosetta 终端中也优先选择 arm64。安装需要 root 权限。 默认下载 `v0.1.0` 的 `bolt-<平台>-<架构>` 附件,例如 `bolt-linux-amd64`、`bolt-darwin-arm64`。对应附件需要事先发布到 Gitea Release;可通过 `BOLT_VERSION` 指定版本,或通过 `BOLT_DL_URL` / `--binary` 指定其他来源。 ```bash # 1. 下载并执行安装脚本(私有仓库下载附件需先 export 下载令牌) export BOLT_DL_TOKEN=你的Gitea令牌 curl -fsSL -H "Authorization: token $BOLT_DL_TOKEN" https://git.draws.qzz.io/jocay/bolt/raw/branch/main/deploy/install.sh -o install.sh sudo BOLT_DL_TOKEN="$BOLT_DL_TOKEN" sh install.sh --http 127.0.0.1:8080 # 2. 完成(脚本自动:下载二进制 → 装到 /usr/local/bin → 写 /etc/bolt.env 与 # systemd 单元 → 开机自启 → 启动服务)。看状态: systemctl status bolt ``` ### macOS arm64(Apple Silicon) 在 Mac 上运行上面的安装命令,脚本会下载 `bolt-darwin-arm64`,安装到 `/usr/local/bin/bolt`,并创建以 root 运行的 launchd 系统服务 `io.jocay.bolt`。 `v0.1.0` Release 提供 `bolt-darwin-arm64` 附件。也可以将该二进制下载或拷到 Mac 后安装: ```bash sudo sh deploy/install.sh --binary ./bolt-darwin-arm64 --http 127.0.0.1:8080 --token 你的令牌 ``` 配置保存在 `/Library/Application Support/bolt/io.jocay.bolt.plist`,包含监听地址、认证令牌、命令规则和超时。启用开机自启时,脚本还会复制配置到 `/Library/LaunchDaemons/io.jocay.bolt.plist`。两份配置均仅 root 可读写;更改参数建议重新运行安装脚本,以保持一致。 `--no-enable` 只保留手动启动配置,取消本服务的开机配置,仍可立即启动;`--no-start` 本次不加载服务,已运行的本服务也会卸载,下次开机是否启动由 `--no-enable` 决定。两个参数可一起使用。 ```bash # 查看服务 / 重启已加载的服务 / 停止并卸载 sudo launchctl print system/io.jocay.bolt sudo launchctl kickstart -k system/io.jocay.bolt sudo launchctl bootout system/io.jocay.bolt # 停止后或使用 --no-start 安装后,手动加载并启动 sudo launchctl bootstrap system '/Library/Application Support/bolt/io.jocay.bolt.plist' # 查看日志 sudo tail -f /var/log/bolt/stdout.log /var/log/bolt/stderr.log ``` macOS 服务的工作目录为 `/var/root`,PATH 包含 `/opt/homebrew/bin` 和 `/opt/homebrew/sbin`,不会加载个人 shell 配置。认证下载使用 `BOLT_DL_TOKEN`,HTTP 服务认证使用 `--token`,两者独立。 该附件交叉编译为 `aarch64-apple-darwin`,最低目标系统为 macOS 11.0,未进行 Mac 实机运行验证。SHA-256: ```text 39274c7d1f965ae924ee51d4e9e4d8a260a84d083971cd50dc6ce645245cc4b8 bolt-darwin-arm64 ``` 常用安装参数(全部可选): | 参数 | 含义 | |---|---| | `--http ` | 监听地址,默认 `127.0.0.1:8080`;对外用 `0.0.0.0:8080` | | `--token ` | Bearer 认证令牌(公网必填) | | `--allow ` / `--deny ` | 命令白/黑名单 | | `--timeout-ms ` | 默认命令超时 | | `--binary <路径或URL>` | 跳过下载,用本地已拷贝的二进制(如 `scp` 过去的) | | `--no-start` / `--no-enable` | 只安装不启动 / 不设开机自启 | 注意:仓库是私有时,Release 附件下载需要认证 —— `export BOLT_DL_TOKEN=你的令牌` 后再跑脚本;若目标设备与开发机同网,直接 `scp root@开发机:/usr/local/bin/bolt ./bolt` 后用 `--binary ./bolt` 最省事。也可以把仓库设公开,附件即可匿名下载。 ## systemd 服务部署(手动) 仓库内 `deploy/` 提供现成的部署文件: ```bash sudo install -m 0755 target/release/bolt /usr/local/bin/bolt sudo cp deploy/bolt.service /etc/systemd/system/ sudo cp deploy/bolt.env.example /etc/bolt.env # 按需修改(监听地址在 service 文件 ExecStart) sudo systemctl daemon-reload sudo systemctl enable --now bolt # 开机自启 + 立即启动 ``` 常用管理命令: ```bash systemctl status bolt # 查看状态 systemctl restart bolt # 重启(改完配置后) systemctl stop bolt # 停止 systemctl disable bolt # 取消开机自启 journalctl -u bolt -f # 实时查看日志 ``` 特性:崩溃自动重启(`Restart=on-failure`,2 秒间隔)、优雅停机(SIGTERM 时杀掉所有子进程树)、日志进 journald、`LimitNOFILE=65536`。默认监听 `127.0.0.1:8080`,对外暴露前务必在 `/etc/bolt.env` 设置 `BOLT_TOKEN`。