Repository navigation
[Grok/dsh 36] 远程 MCP 认证与多类型内容 #168
Copy link
Copy link
Closed
Labels
ready-for-agentAgent-grabbable workAgent-grabbable work
Description
Activity
- added a commit that references this issue
on Sep 25, 2026 已实现并推送到
rewrite/grok-dsh-20260920:33c1699b22269b25fb4b2f584018df2b21f5c118(33c1699)实现内容(dsh 仍是执行核心,远程服务经 codsh 的 MCP 代理挂给 dsh)
- 远程传输:streamable HTTP(含
Mcp-Session-Id、404 会话丢失后重新 initialize 一次、协议版本头)与旧版 SSE(GET 事件流 + POST endpoint),headers支持${session_id}等占位符;POST 与 SSE GET 遇到 3xx 一律拒绝跟随(不把凭据带去别的源);请求头和令牌不进入 plan /mcp list/ 日志。 - OAuth:受保护资源元数据 / 授权服务器元数据发现、动态客户端注册(不支持时提示需要配置 client_id)、PKCE S256、
state常量时间比较、仅 127.0.0.1 回调;令牌存于$GROK_HOME/mcp_credentials.json(0600,Debug脱敏),到期前刷新、401 时刷新一次;mcp login|logout <name>、/mcps auth|logout <name>,登出会调用 revocation endpoint 并删除本地凭据;浏览器只打开 http(s) 地址($BROWSER,Windows 用rundll32 url.dll,FileProtocolHandler)。 - 多类型内容(按参考的投影规则):图片块和内嵌图片资源以 image 块交给 dsh(
--expose-image-base64时额外附 base64 文本),其他内嵌资源转为 JSON 文本,音频变成说明文字,资源链接等其他块原样透传,未内联的structuredContent以紧凑 JSON 追加;错误结果只保留文本。 - 用户询问(elicitation):TUI 表单卡片(按 schema 渲染 string/number/boolean/enum,校验、
d拒绝、Ctrl+C 取消)与 URL 型确认;编辑器 ACP 通过x.ai/mcp/elicit转发,多客户端先答者生效,其余收到$/cancel_request,无客户端时自动 decline,URL 完成发x.ai/mcp/elicit_complete。 - 编辑器 ACP 扩展:
x.ai/mcp/auth_status、x.ai/mcp/auth_trigger(登录成功后重启该会话的 MCP 服务)、x.ai/mcp/read_resource(仅限已挂载服务,30 s 超时)。 - 资源/提示对照:固定参考源码 e8563f8 中可达的资源能力是 ACP
x.ai/mcp/read_resource(已实现);参考里McpStateResourceProvider虽有定义但未注入,也没有ListMcpResources/FetchMcpResource工具实现,MCP prompts 也未被任何界面使用,所以这里不另造模型侧资源工具或 prompts 界面。 - 文档:README / README.zh / CONTEXT / packages/cli/README / CONTRIBUTING /
--help,以及 changeset(codsh-cli、codsh-bundle minor)。
验证(真实数字)
- 受控远端协议测试
scripts/rust-mcp-remote.spec.mjs(4/4 通过):本地回环 fixture 覆盖 OAuth 登录、刷新(refresh grant 恰好 1 次)、404 重新初始化(initialize 恰好 2 次,副作用调用只执行 1 次)、图片块、登出撤销;SSE +${session_id}+ 重定向拒绝 + 请求头不进 plan;编辑器 elicitation(表单、URL、错误、非法内容、取消)、auth_status/trigger、read_resource。 - 真实集成:MCP TypeScript SDK 1.30.0 官方示例
simpleStreamableHttp.js --oauth --oauth-strict(从 dsh 依赖链解析,未联网、未用付费服务)——OAuth 登录、调用 greet、编辑器回答 collect-user-info 表单 elicitation、read_resource、登出,全部通过。 - PTY:
scripts/rust-mcp-remote-pty-test.py通过(/mcps显示需要认证 →/mcps auth→ 列表 → 表单卡片编辑提交 →d拒绝 → URL 接受 →/mcps logout);scripts/rust-plugin-mcp-pty-test.py通过。 - 检查(基于 cbcbfcf 之上的 33c1699,Linux x86_64):
pnpm run typecheck通过;TMPDIR=/tmp pnpm test:107 个文件中 105 通过、2 跳过;2613 个用例中 2598 通过、0 失败、15 跳过。cargo fmt --check通过;cargo clippy -D warnings只剩两个已知问题(filesystem_sandbox.rs 的tail_marker未使用、多余的return),加-A dead_code -A clippy::needless_return后通过。cargo test --locked --workspace --offline --no-fail-fast:1772 通过、4 失败、2 忽略。4 个失败都是本单之前就有的、与本改动无关:filesystem_sandbox 的 2 个;privacy::drafts_stay_local… 与 voice::substitute_route…,这两个测试用的本地 HTTP 桩只read()一次,请求体分包发送时就收不到。本单没有改 privacy.rs / voice.rs。
- 安全复查:令牌只在 0600 文件与内存中,Debug/日志/plan/导出不含令牌或自定义请求头;回调仅绑定 127.0.0.1 并校验 state;拒绝 3xx 跟随;浏览器 opener 不经 shell;elicitation 超时/取消/拒绝不会重放工具调用,认证过期只刷新重试一次,不扩大权限。
未验证
- macOS / Windows 未实测(Windows 的浏览器打开路径只有代码,未实测)。
- 未连接任何托管的远程 MCP 服务或真实第三方授权服务器;未运行参考二进制,参考行为依据固定源码 e8563f8。
- 未处理 URL 型 elicitation 的
-32042错误重试(README 已注明限制);headless-p不提供 elicitation。
范围:main、npm 发布、默认启动路径均未改动;未发布版本,PR #213 未动。
后续:本单只阻塞 #211;#211 仍被 #186、#188、#201、#203、#206、#209 阻塞,所以本单关闭后没有新解锁的任务。
- 远程传输:streamable HTTP(含
Metadata
Metadata
Assignees
Labels
ready-for-agentAgent-grabbable workAgent-grabbable work
Parent
#132
Ticket: 36
Status: ready-for-agent
User Stories: 39, 40(见父规格)
What to build
用户连接支持的远程 MCP 服务并完成认证,使用结构化/图片内容和需要用户回答的请求。
Acceptance criteria
Blocked by
Delivery contract
用户于2026-09-20批准当前测试与任务拆分。按父规格的已安装产物/真实终端和公开协议测试验收;实际实现须带适用的文档、Changeset及必要检查。ready-for-agent表示任务已定义,不表示前置任务已完成,也不授权自动开始本轮实施、购买付费资源或发布软件版本。