Release v0.9.6 - fix ci go:lint 4 个 issue: - errcheck:ensure_kafka_mcp gz.Close 返回值改 _ = gz.Close() 显式忽略(只读流 Close 失败无 recovery) - gofmt:ensure_kafka_mcp const 文档块缺空行 + install_native_openclaw findOpenclawCLI candidates 数组对齐空格 gofmt 自动修 - staticcheck ST1005:error 字符串首字母大写 "Windows 不支持..." 改 "windows 不支持..."(Go 风格 error msg 不大写,跟其它 fmt.Errorf 一致) 本地 golangci-lint run 0 issues (22a37f7) - docs ensure_kafka_mcp 跟进上轮 review 后再审,只找到 2 个 docstring 跟代码不一致(无新 ship-blocker): (1) 顶部头注释 cache 路径还写 ~/.tshoot/bin/kafka-mcp-server,实际带版本号 kafka-mcp-server-<ver>;补流程 4 步明确返回绝对路径 / cache 命中条件 + 版本号文件名意图(避免 mcp-grafana 早期孤儿 binary 教训) (2) MCPBuildOptions.KafkaMCPBinaryPath 没强调隐式契约 — production 调用方必须先调 EnsureKafkaMCPInstalled 拿绝对路径;空字符串=回落 PATH 字面只两种场景用(ensure 失败 fallback / 单元测试只验 builder 逻辑);新人改代码不会漏 launchd PATH 兼容这层 其它发现的 6 个 polish(context.Context 接口 / 下载进度日志 / SHA256 校验 / 失败时返绝对 cache 路径 / 重试 / uninstall hook)都算研制阶段可接受 trade-off,不修;具体见本会话讨论 (662c16e) - fix ensure_kafka_mcp 收 reviewer 找的 3 个 ship-blocker + 4 个 hardening: (1) **PATH 命中返字面 "kafka-mcp-server" 而非 LookPath 绝对路径** — 跟 e44c74d findOpenclawCLI 同款 mac launchd GUI PATH 不兼容坑:install 从 shell 跑 PATH 有 brew prefix 写字面到 ~/.claude.json,Claude Code desktop 启动子进程 PATH 只 /usr/bin:/bin 字面找不到 ENOENT 静默挂;返回 p 绝对路径 (2) **并发 install tmp 名互相覆盖** — dest+".tmp" 固定名两个 IDE 同时跑 install 会 race;tmp+pid 后缀防覆盖 (3) **HTTP 中途截断写出 corrupt binary 后续 cache 命中误用** — io.Copy 不报错短 binary 顺利 rename 0o755 进 cache,下次启动 MCP 子进程异常退出;校验 tar header.Size 跟 io.Copy 写入字节数一致,不等则删 tmp 报 truncated hardening: (4) Windows 自动下载 EnsureKafkaMCPInstalled 头部直接 return 走手动安装路径 — 之前 log "自动下载中" 再失败误导用户 (5) cache 文件名带版本号 "kafka-mcp-server-v2.0.2" — bump 版本旧文件不被命中触发重下,避免静默用旧版;tarball 内 binary 名仍是 "kafka-mcp-server" 不带版本,匹配走常量不用 filepath.Base(dest) (6) cache 探测 0o100 owner-only 改 0o111 任意 execute bit — umask 异常时也能识别已装好的 binary (7) HTTP body 套 io.LimitReader 200 MiB — 防恶意 mirror 重定向 /dev/urandom 灌爆磁盘(tuannvm tarball 实际 ~5 MiB,10× 余量) (8) install_native_mcp_common.go:981 stale doc 引用 CheckKafkaMCPServerAvailable(已删函数)改成 EnsureKafkaMCPInstalled test:加 3 个新测试 PathHit / CacheHit / VersionPinned 覆盖核心分支,PathHit assert filepath.IsAbs(got) 能 catch ship-blocker #1 回归;删了一个依赖网络下载行为的 flaky NonExecCacheRejected 测试(下载成功失败结果不定) (3e9a82e) - feat install 时自动下载 kafka-mcp-server binary 替代之前只 warn 让用户手动 brew install:kafka-mcp-server 是单一用途 binary(不像 uv 那种系统级工具)装哪不污染系统,符合早期 mcp-grafana 自动下载判定;EnsureKafkaMCPInstalled 三档:PATH 命中返回 "kafka-mcp-server"(用户已装 brew/其它路径)/ ~/.tshoot/bin/kafka-mcp-server cache 命中直接用 / 都没有就拉 GitHub Release tarball 解到 cache(版本 pin v2.0.2 少 1 次 GitHub API 调用 + 上游崩不自动跟着崩) 90s timeout tmp+rename 避免半写残文件;失败不阻塞 install 仍 warn 给手动指引 fallback;buildKafka 接 KafkaMCPBinaryPath option 写绝对路径 / 空时回落 "kafka-mcp-server" PATH 形式(用户事后手动装到 PATH 不用重跑 install);Windows zip 暂未实现自动解压走手动安装路径(mac/linux 优先);test 加 abs path 用例验证 option 生效 (419a98e) - fix kafka MCP 换 tuannvm/kafka-mcp-server(franz-go 纯 Go binary)替代 @confluentinc/mcp-confluent:confluent 包依赖 native librdkafka 绑定(@confluentinc/kafka-javascript),Node ABI 矩阵滞后(Node 26 v147 没出 prebuilt) + install scripts 静默失败 + fallback build 需要 librdkafka/cmake 系统依赖,跨平台脆 2026-05-13 实战踩坑;tuannvm 是 MIT 纯 Go franz-go 无 native deps,GoReleaser 跨 5 个 triple(darwin/linux/windows × amd64/arm64) GitHub Release + brew tap 装一次永远稳;trade-off 是用户多一步 brew install(其它 7 家是 npx/uvx 零安装);buildKafka 改 command:"kafka-mcp-server" + env KAFKA_BROKERS+MCP_TRANSPORT,删 18 个 confluent --block-tools 黑名单(tuannvm 只 1 个 mutative tool produce_message 靠 SKILL.md 文档契约约束 LLM 不调);重加之前 9c32f8b 删的 CheckKafkaMCPServerAvailable 探测同款 CheckUvxAvailable 模板,缺 binary 打 [warn] brew 安装指引不阻塞 install;test 期望同步;kafka-runtime-query SKILL.md.tmpl 把 mcp 选用 / 安全契约段全重写 (335dbe3) - fix install_native_openclaw 找 openclaw CLI 走 PATH + 绝对路径 fallback:mac 桌面 app launchd GUI 默认 PATH 只有 /usr/bin:/bin:/usr/sbin:/sbin,brew prefix(/opt/homebrew/bin or /usr/local/bin)里装的 CLI exec.LookPath 找不到 → 用户实际装了 CLI(npm i -g openclaw)却被代码当"未装"走 [info] 文案;加 findOpenclawCLI helper 兜 4 类装机路径(Apple Silicon brew / Intel mac brew / npm-global / ~/.local)命中即用绝对路径直调 gateway restart;2 个 test 覆盖 PATH 命中分支 + 全 miss 返回空串分支(本机 brew openclaw 存在时 all-miss 自动 t.Skip 兜底) (e44c74d)