Skip to content

[code-review] SetElicitationBroker has zero call sites in the entire repo while the elicitation handler itself is registered, so every MCP elicitation/create request dies at 'no interaction broker available' and the user never sees the server's question - a half-wired feature shipped dead; MCP sampling ignores the server's maxTokens entirely (provider.Chat has no per-request channel, so a 64-token request generates at provider default), fabricates stopReason max_tokens whenever output happens to reach the unenforced cap while stop_sequence is unreachable, and runs as the only LLM-consuming path with no permission gate, rate limit, quota, or even a config off-switch despite its own handler doc saying permission checks belong there #1484

Description

@topcheer

文件行号

internal/agentruntime/mcp_elicitation.go L21-24(包级 elicitationBroker 零值 nil)+ L29-34(SetElicitationBroker 唯一赋值入口——全库 grep 零调用点)+ L47-49(handler 入口 broker==nil 即报 "no interaction broker available for elicitation");对照 interactive_core.go L62(SetElicitationHandler 已注册——handler 接了电源、broker 没接)与 L125(SetSamplingProvider 有真实调用——平行机制对照)+ interactions.go:49(AwaitAskUser 真实可用路径);mcp_sampling.go L62-63(maxTokens 只进 debug.Log)+ L65(p.Chat(ctx, messages, nil)——provider.go:188 Chat 签名第三参是 tools 无 maxTokens 通道;anthropic.go:91-98/804 effectiveMaxTokens 为 provider 构造级全局值非 per-request)+ L78-81(stopReason 启发式——provider.go:238-241 ChatResponse 只含 Message+Usage 根本不携带 stop reason)+ mcp/sampling.go:44/50(StopSequences 同未传;"stop_sequence" 分支不可达)+ L33-96(handler 全文零 permission/零 rate limit/零配额——grep internal/permission 与 config 零命中连禁用开关都没有;L55-59 SamplingHandler 文档自述 "If sampling is not permitted... return an error"——设计预期有门禁实现为空)+ client.go:2007-2028(仅 60s 单次超时不限次数)

问题

案 A(High,功能 100% 死亡·半接线):SetElicitationBroker 全库零调用——elicitation 整个功能上线即死

  • 任何 MCP server 发 elicitation/create → handler 已注册非 nil → 进入即 broker==nil → 返回 -32603 错误——用户在 TUI/Desktop/IM 任何表面永远看不到 server 提问
  • commit 926b6c7 对 interactive_core.go 的唯一改动是注册 handler 一行,设计文档 docs/design/mcp-elicitation.md 描述了完整用户路由流——意图明确要接通,组装点缺失属遗漏;对照 sampling 平行机制接了(L125)elicitation 没接
    :interactive_core 组装处补 SetElicitationBroker(broker) 一行。

案 B(Med,协议核心参数静默丢弃):server 请求的 maxTokens 从未传给 provider——LLM 按 provider 全局上限生成、计费失控

  • server 请求 maxTokens:64 → EffectiveMaxTokens 钳制结果只进日志 → Chat 按 Anthropic 默认 ≥4096 生成——超长文本+超额计费;MCP spec 中 maxTokens 是 createMessage 必填核心参数(客户端可少采样、不可无视)
  • provider.Chat 签名无 per-request 通道(effectiveMaxTokens 为构造级全局)——需扩展接口或经 Message 侧通道
    :Chat 加 options 或 provider 加 per-request override。

案 C(Med,协议级误报双向):stopReason 启发式谎报 max_tokens、stop_sequence 永不可达

  • 根因:ChatResponse 只含 Message+Usage 不携带真实 stop reason(上游 anthropic.go:905-916 有映射但只用于流式错误路径)
  • (a) 假阳性:maxTokens:64 被无视、LLM 自然生成 100 tokens → 100>=64 → 报 max_tokens——描述了从未发生的截断;迭代采样 server 据 stopReason 决定续写会做错误决策 (b) StopSequences 同未传 → "stop_sequence" 分支不可达
    :ChatResponse 携带 stop reason;StopSequences 透传。

案 D(Med,设计缺口+无止损开关):sampling 是唯一无门禁的 LLM 消耗路径

  • 恶意/buggy server 可循环+并发发起 sampling 烧配额到余额耗尽——全程无提示无熔断;连 "关闭 sampling" 的配置开关都不存在(grep permission/config 零命中)
  • SamplingHandler 文档自述预期有门禁("If sampling is not permitted... return an error")实现为空——接口设计自我矛盾;MCP spec 明确建议客户端 "SHOULD obtain user approval";对照:普通工具走 permission、elicitation 走用户路由,sampling 独豁免无一致性依据
    :加 permission/频率门禁+配置开关。

干净项与附注

mobile_interactions 无问题(fail-closed 决策映射/#1038 顺序/无状态纯函数)。mcp_hotreload:坏配置 last-good/增删分类/锁外 Close/tombstone 对齐全对;mtime 回退(cp -p/rsync -a 替换为更早 mtime 的不同内容)漏检 Low 附注。interactive_core:生命周期顺序/mcpStartOnce/Close 幂等全对;gRPC 插件子进程 Close 不杀(L171-189 无 GRPCPluginMgr.Close——桌面多会话泄漏,使用面窄 Low-Med 附注);包级 samplingProvider 多会话 last-wins(A 会话配 Claude B 配 GLM,B 创建后 A 的 sampling 走 B 计费)Low 附注。elicitation 伴生坑(修 A 后暴露):nextElicitCounter 非原子递增 race(E2)+ 必填字段空答仍回 Accept(E3)。

严重程度

High + Med×3


独立复核确认:SetElicitationBroker 全库 grep 零调用+git show 926b6c7 唯一改动行+设计文档意图、Chat 签名与 effectiveMaxTokens 构造级实证、ChatResponse 字段全集+anthropic stop_reason 映射位置、handler 全文与 permission/config 零命中+SamplingHandler 文档自相矛盾。死接线意外族再添一例(第 6 例)。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions