Skip to main content
Glama

dsh-mcp-worker

把本机 DSH(DeepSeek Harness) 暴露成一个 MCP worker,让 Claude Code / Codex CLI / ChatGPT(桌面)/ Claude Desktop 这些 leader 把重活交给它跑。

角色模型:leader(决策、编排)通过 MCP 调用 worker(DSH);worker 在真实项目目录里执行长任务(读代码、改文件、跑命令、跑测试),只把结果回传。

现状(本地已验证)

项

状态

单元测试

✅ 127/127 通过(pnpm test)

真实链路烟测

✅ MCP Client → worker → 真实 DSH:问答 + 写文件(hello-dsh.txt)全链路通过

长驻后端(M1)

✅ 默认 backend=sdk:真实烟测首任务 9s(含一次初始化)、第二任务 3s;大仓库真实任务 18.4s(含 initialize);headless 保留为 fallback

远程传输(M2a)

✅ DSH_MCP_TRANSPORT=http:真实 HTTP 冒烟通过(/healthz 200、无 token 401、MCP HTTP 客户端跑真实任务 8s)

审批桥(M2b)

✅ dsh_result 检测审批阻断 → elicitation 询问授权 → 以 danger-full-access 重试(4 个单测覆盖;真实 DSH 审批场景未端到端实测)

运维治理(M3)

✅ 任务 TTL 自动清理 + 数量上限(超额淘汰最老已结束任务)、每 cwd 并发配额、审计日志(dsh_audit)、任务列表(dsh_tasks)、完整产物分页读取(dsh_read_result)

批量/检索/观测(M4)

✅ dsh_batch_run/status/result 批量派发与聚合、dsh_search 历史任务内容检索、dsh_metrics 指标快照、轻量 OTel span 导出(真实冒烟捕获到 2 条 dsh.task span)

编码与写文件

✅ workspace-write 中文 UTF-8 写入/读回(字节 E4 B8 AD…);read-only 中文输出经 worker 自动双层兼容修复后回归正常(实测 read-only / workspace-write 均返回 中文探针:你好、无 �)

Windows ACL 沙箱降级(v0.6.6)

✅ 公司仓库等「仅 Modify ACL」目录请求 workspace-write 时会遇 SetNamedSecurityInfoW failed (Win32 5): grantWrite;worker 检测后自动升级为 danger-full-access + 新 session 重试,dsh_result.sandbox_fallback / effective_permission_mode 记录实际模式(真实受限仓库验证:succeeded、output=ok、30s);可用 DSH_MCP_ACL_FALLBACK=read-only 或 off 收紧

委派粒度策略(v0.6.4)

✅ 规则改为「一个 dsh_run = 一个可验收工作单元(实现+自测+证据),禁止微任务」;长轮询上限 25s→可配 120s(DSH_MCP_STATUS_WAIT_MAX_S),减少 leader 往返;规则已写入 ~/AGENTS.md、~/.codex/AGENTS.md、worker instructions 与 docs/delegation-playbook.md

执行记录分析(v0.6.5)

✅ 分析 11-02~11-09 的 64 个任务/200 条审计:修复「长任务被空闲回收误杀」(11 分钟任务、13.3M token 沉没)与「read-only 任务被 ACL 文本误判 failed」;新增 dsh_status 实时 tokens/steps/tool_calls、dsh_result.partial_output/failure_kind、token 预算护栏 DSH_MCP_MAX_TASK_TOKENS、ACL 失败 cwd 缓存(报告见 D:\work\tmp\dsh-record-analysis\DSH-MCP执行记录分析-2026-11-09.md)

续聊恢复(v0.6.3)

✅ DSH SDK 协议无 resume;worker 重建后用旧 session_id 续聊会报 session "..." already exists。worker 自动换新 session id 重试,并把上一轮任务/结果摘要作为「续聊上下文」拼入;真实两进程验证:A 建 session → B 续聊 succeeded(output=ok2),事件含 session_resume_fallback

易用性升级(v0.7.0)

✅ auto 模式 + cwd 能力缓存(跨进程,避免每次撞 ACL)+ 自动 worktree(受限仓库改到可写 worktree)+ 能力缓存 TTL 可调 + 瞬态失败自动重试 + 失败诊断 + dsh_run(wait_s) 单调用等待 + MCP 调用/字节指标 + 任务完成 webhook/命令通知

目标测量(v0.6)

✅ worker 侧 DSH token 计量(dsh_result.usage.tokens / dsh_metrics.tokens)+ A/B 对照工具 + leader 用量扫描器;真实首测:加速 2.29x、leader token 省 46.0%、cost 省 31.1%、达成率 2/2

cwd 安全校验

✅ 传用户主目录会被拒绝(Windows ACL 沙箱限制)

Claude Code 接入

✅ 已注册(user scope)并实测连通:claude mcp get dsh → √ Connected;claude -p 真实调用 dsh_describe 成功

Codex 接入

✅ 已写入 ~/.codex/config.toml,codex mcp get dsh 解析正常(工具白名单/超时/审批模式生效;未做真实调用)

ChatGPT 桌面 app

⚠️ 未实测(调研显示它与 Codex 共享 ~/.codex/config.toml,配法同 Codex)

ChatGPT web

⏸ 后置(需要 OpenAI Secure MCP Tunnel 或自建 HTTPS + OAuth)

Claude Desktop(MCPB)

⚠️ 未实测(examples/mcpb-manifest.json 已给出模板)

注册记录(2026-11-02):Claude 侧改的是 ~/.claude.json;Codex 侧在 ~/.codex/config.toml 末尾追加了 [mcp_servers.dsh],改前已备份为 config.toml.bak-dsh-registration-20261102。 撤销:claude mcp remove dsh -s user;codex mcp remove dsh(或从 config.toml 删掉对应块)。

Related MCP server: muster

架构

leader(Claude Code / Codex / ChatGPT / Claude Desktop)
   │  MCP over stdio(本地)或 Streamable HTTP /mcp + Bearer(远程)
   ▼
dsh-mcp-worker(本进程)
   │  dsh_run 立即返回 task_id;任务后台执行
   │  任务落盘:meta.json / events.jsonl / result.txt
   ▼  后端可切换(DSH_MCP_BACKEND)
   ├─ sdk(默认):长驻 `dsh --profile sdk`,一次 initialize,之后每个任务只发 session/prompt
   └─ headless:`dsh --profile headless --json "<task>"`,每任务一个进程
   │  NDJSON 事件:session → status/tool_call/tool_result → final
   ▼
真实文件系统 / shell(cwd 必须是项目目录;默认 workspace-write)

快速开始

cd C:\path\to\dsh-mcp-worker
pnpm install
pnpm build
pnpm test          # 127 个单测
pnpm smoke         # 真实 DSH 集成烟测(约 30–60s)

worker 通过 stdio 工作,自身不监听任何端口。需要它时由 leader 拉起子进程。

本机安装(推荐 pnpm 全局)

源码仓库只用于开发(pnpm build / pnpm test);MCP 客户端加载 pnpm 全局安装的正式包,不要指向源码仓库。

pnpm add -g dsh-mcp-worker@latest      # 安装/升级
pwsh -File scripts/mcp-entry.ps1       # 输出 MCP 入口(pnpm 全局包内 dist/index.js)

把输出的入口配置给 leader(Codex/ChatGPT 的 ~/.codex/config.toml 或 Claude Code):

[mcp_servers.dsh]
command = "node"
args = ["<scripts/mcp-entry.ps1 输出的路径>"]
  • 升级:pnpm update -g dsh-mcp-worker → 重启 leader 会话;若入口路径变化,用 scripts/mcp-entry.ps1 刷新配置;

  • 不要用 cmd /c dsh-mcp-worker 作为 MCP 入口:cmd 包装下 dsh_describe 正常但真实任务会卡住(已实测),必须用 node + 全局包入口;

  • 源码开发调试可选:scripts/deploy.ps1 部署到独立目录(内容等价 npm 包),不用于本机日常使用。

通过 npm 使用

包名:dsh-mcp-worker(只发布构建产物;本机仍需安装 DSH)。

npm i -g dsh-mcp-worker      # 或直接用 npx
npx -y dsh-mcp-worker        # 由 MCP 客户端拉起(stdio)

MCP 客户端配置可用:

{
  "mcpServers": {
    "dsh": { "command": "npx", "args": ["-y", "dsh-mcp-worker"] }
  }
}

注意:npm 包不包含 DSH 本体;worker 通过 dsh(PATH)、DSH_MCP_DSH_DIR 或 DSH_MCP_DSH_CLI 找到本机 DSH。

接入 leader

1) Claude Code(最省事)

claude mcp add --scope user --transport stdio dsh -- node "C:\path\to\dsh-mcp-worker\dist\index.js"
claude mcp list
claude mcp get dsh

带环境变量时注意 --env 的位置(放在 server 名之前):

claude mcp add --scope user --transport stdio --env DSH_MCP_DEFAULT_CWD="D:\work\repo" dsh -- node "C:\path\to\dsh-mcp-worker\dist\index.js"

等价 .mcp.json 见 examples/claude-mcp.json。

避免每次弹授权:把 dsh 工具加入用户级 allowlist(~/.claude/settings.json 的 permissions.allow):

["mcp__dsh__dsh_run", "mcp__dsh__dsh_status", "mcp__dsh__dsh_result", "mcp__dsh__dsh_cancel", "mcp__dsh__dsh_describe",
 "mcp__dsh__dsh_tasks", "mcp__dsh__dsh_audit", "mcp__dsh__dsh_read_result", "mcp__dsh__dsh_batch_run",
 "mcp__dsh__dsh_batch_status", "mcp__dsh__dsh_batch_result", "mcp__dsh__dsh_search", "mcp__dsh__dsh_metrics"]

本机已写入(备份 settings.json.bak-dsh-allow-20261102)。安全边界仍由 worker 的 permission_mode / 审批桥承担。

2) Codex CLI / IDE

把下面加到 ~/.codex/config.toml(完整示例见 examples/codex-config.toml):

[mcp_servers.dsh]
command = "node"
args = ["C:\\path\\to\\dsh-mcp-worker\\dist\\index.js"]
startup_timeout_sec = 30          # 默认 10;worker 自身启动很快,留余量
tool_timeout_sec = 300            # 默认 60;allow dsh_status 长轮询(wait_s≤120s)
enabled_tools = ["dsh_run", "dsh_status", "dsh_result", "dsh_cancel", "dsh_describe", "dsh_tasks", "dsh_audit", "dsh_read_result", "dsh_batch_run", "dsh_batch_status", "dsh_batch_result", "dsh_search", "dsh_metrics"]
# approve = 不再询问(auto 仍会按风险询问);安全边界由 worker 的 permission_mode(默认 workspace-write)兜底
default_tools_approval_mode = "approve"

# 桌面端对 MCP 工具的审批可被 per-tool 覆盖(13 个工具都要写)
[mcp_servers.dsh.tools.dsh_run]
approval_mode = "approve"
# ……其余工具同理:dsh_status / dsh_result / dsh_cancel / dsh_describe / dsh_tasks / dsh_audit /
# dsh_read_result / dsh_batch_run / dsh_batch_status / dsh_batch_result / dsh_search / dsh_metrics

[mcp_servers.dsh.env]
DSH_MCP_DEFAULT_CWD = "C:\\path\\to\\your\\project"

校验:codex mcp get dsh(本机已配置为 default_tools_approval_mode: approve + 13 个 per-tool approve;改前备份 config.toml.bak-dsh-approve-20261102)。改完需完全退出并重开 Codex/ChatGPT 桌面 app,配置在 app 启动时加载。

3) ChatGPT 桌面 app

调研显示 ChatGPT 桌面 app、Codex CLI、IDE 扩展共享同一份 ~/.codex/config.toml,所以按上面 Codex 的配置配好后重启桌面 app 即可使用(未实测,若无效请反馈)。

4) ChatGPT web(后置)

ChatGPT web 只接受远程 MCP(Streamable HTTP / SSE),不接受 stdio。两条路:

  • 推荐:OpenAI Secure MCP Tunnel(需要 Platform 组织 + tunnel_id + runtime API key):

    tunnel-client init --sample sample_mcp_stdio_local --profile dsh-local \
      --tunnel-id tunnel_xxxxxxxx --mcp-command "node C:\\path\\to\\dsh-mcp-worker\\dist\\index.js"
    tunnel-client run --profile dsh-local

    然后在 ChatGPT → Plugins → + → Add custom MCP server → Connection 选 Tunnel → Create。 注意 Tunnel 硬限制:单请求 120s / 10 MiB / 600 rpm,所以必须用本 worker 的异步任务模型(run 立即返回 + 轮询)。

  • 或自建 HTTPS + OAuth 2.1(工作量大,暂未实现)。

5) Claude Desktop(本地 MCPB)

模板见 examples/mcpb-manifest.json。需要把 dist/ 与 node_modules 一起打包进 MCPB 扩展,用 mcpb pack 生成 .mcpb 后拖入 Claude Desktop(未实测)。

工具面

工具

作用

关键参数

dsh_run

提交任务,立即返回 task_id

task(必填)、cwd(必填,项目目录)、session_id?、permission_mode?、timeout_s?

dsh_status

查状态 + 增量事件,支持长轮询

task_id、cursor?、wait_s?(0–25)

dsh_result

取最终结果(输出过大自动落盘)

task_id

dsh_cancel

取消任务(杀进程树)

task_id

dsh_tasks

列出最近任务摘要(回顾/继续轮询)

limit?(1–100)、status?

dsh_audit

读取审计事件(任务生命周期/审批决定)

limit?(1–200)

dsh_read_result

分页读取落盘的完整结果或事件日志

task_id、source?(result/events)、offset?、max_chars?

dsh_batch_run

批量并行派发(每项可带 cwd/session/权限)

tasks[](1–maxBatchTasks)

dsh_batch_status

批量聚合状态(整体状态 + 子任务 + 计数)

batch_id、wait_s?

dsh_batch_result

批量聚合结果(输出/错误/耗时)

batch_id、max_output_chars?

dsh_search

在历史任务的输出与工具结果里检索

query、limit?

dsh_metrics

计数/耗时分位/排队/后端/OTel 状态

—

dsh_describe

返回入口/默认值/限制,供 leader 自适应

—

典型调用序列(leader 视角):

// 1) 提交
{ "name": "dsh_run", "arguments": { "task": "修复 utils.ts 的空指针,并跑 pnpm test 验证", "cwd": "D:\\work\\repo" } }
// → { task_id, status: "queued", session_id, cwd, hint }

// 2) 轮询(每次最多等 25s;运行中会收到 notifications/progress)
{ "name": "dsh_status", "arguments": { "task_id": "...", "cursor": 0, "wait_s": 20 } }

// 3) 结束后取结果
{ "name": "dsh_result", "arguments": { "task_id": "..." } }

状态机:

queued ──▶ running ──▶ succeeded
   │           ├──▶ failed(超时/DSH 报错)
   │           ├──▶ cancelled
   └──▶ 不会出现:被取消的排队任务会直接 cancelled

多轮续聊:把首次 dsh_run 返回的 session_id 传给下一次 dsh_run;同一 session 的任务串行执行(DSH 侧单写者),不同 session 并行(受 DSH_MCP_MAX_CONCURRENT 限制)。

让 leader 主动委派(可选,推荐)

MCP 只把工具摆给 leader,是否调用由 leader 模型自己决定,协议层无法强制。想提高“自动委派”概率,三档手段(从弱到强):

  1. 工具描述/instructions(已内置):dsh_run 描述与 server instructions 写明「一个任务 = 一个可验收工作单元(实现+自测+证据);禁止微任务;长轮询 60–120s」——这是 ChatGPT web / Claude Desktop 等远程 leader 唯一可用的杠杆。

  2. 指令文件(本地 leader 有效):

    • Claude Code:~/.claude/CLAUDE.md(本机通过 @~/AGENTS.md 引用);

    • Codex:~/.codex/AGENTS.md(全局);或项目内 AGENTS.md(就近生效)。 本机已写入「粗粒度委派」规则(AGENTS.md.bak-dsh-coarse-20261102 为改前备份)。

  3. Hook(仅 Claude Code 等支持 hook 的 host):UserPromptSubmit 每次注入提醒,最稳但配置成本最高。

注意:远程 leader(ChatGPT web / Claude Desktop)读不到本地指令文件,只能靠第 1 条 + 用户明说「用 dsh 跑」。

粒度怎么定(关键)

  • 一个 dsh_run 覆盖「定位 → 实现 → 自测 → 证据」,典型:一个功能点 / 一个 bug / 一个测试修复批次 / 一次跨文件重构;

  • 少于 3 次工具调用或 2 分钟内能做完的事,leader 自己做;不要拆成多个 dsh 任务;

  • 只有独立可并行(用 dsh_batch_run)、需要决策、风险隔离时才拆分;

  • 轮询用 dsh_status(wait_s=60~120),不要在 DSH 执行期间重复劳动;

  • 详细模板、反例/正例、验收动作、如何用 scripts/leader-usage.mjs 验证:docs/delegation-playbook.md。

目标达成率测量(leader 提速 / 省 token)

目标前提:Codex/ChatGPT、Claude Code 作为 leader,通过本 worker 把重活交给 DSH。核对方式:同任务 A/B 对照(leader 自己做 vs 委派 DSH)。

# A/B 对照(会真实消耗 leader 额度;只读分析类任务最安全)
pnpm measure:ab -- --cwd D:\work\repo --task "统计 src 下 ts 文件数量并列出最大的 3 个(只读分析)" --runs 3 --expect "src"

# 持续观察 leader 自己的会话用量(不跑基准)
pnpm measure:leader -- --since-hours 24

报告包含:加速比、leader token 节省率、cost 节省率、正确性守门、DSH token、DSH token / 省下 leader token,以及目标达成率 x/2 或 x/3。

  • 口径/公式/协议/局限:docs/measurement.md

  • 真实首测(单样本,任务:统计 src 下 ts 文件并列出最大 3 个):加速 2.29x、leader token 省 46.0%、cost 省 31.1%、达成率 2/2;报告样例在 measure-runs/report-*.md。

  • leader token 来自 Claude Code -p --output-format json 的 usage/cost;Codex 用 scripts/leader-usage.mjs 从 rollout 聚合;ChatGPT web 无本地计量(见文档局限)。

配置(环境变量)

变量

默认

说明

DSH_MCP_TRANSPORT

stdio

MCP 传输:stdio(本地 leader)/ http(Streamable HTTP,远程 leader)

DSH_MCP_HTTP_HOST

127.0.0.1

HTTP 监听地址;0.0.0.0 时必须设 token

DSH_MCP_HTTP_PORT

7391

HTTP 端口(0 = 随机)

DSH_MCP_HTTP_TOKEN

无

HTTP Bearer token;非回环地址必填

DSH_MCP_DSH_CLI

自动探测

@deepseek-ai/dsh/lib/bin.js 的绝对路径(用 node 启动,最稳)

DSH_MCP_DSH_COMMAND

—

完整命令(如 dsh),通过 shell 启动;优先级低于 DSH_MCP_DSH_CLI

DSH_MCP_DSH_DIR

—

DSH 安装目录(自动拼 node_modules/@deepseek-ai/dsh/lib/bin.js)

DSH_MCP_PROFILE

headless

headless 后端使用的 profile

DSH_MCP_BACKEND

sdk

执行后端:sdk(长驻,默认)/ headless(每任务一进程)

DSH_MCP_SDK_PROFILE

sdk

长驻后端使用的 DSH profile

DSH_MCP_SDK_PROVIDER

deepseek-official

SDK 后端 provider

DSH_MCP_SDK_MODEL

deepseek-flash

SDK 后端 model(进程级固定)

DSH_MCP_SDK_REASONING_EFFORT

无

推理强度(可选,如 max)

DSH_MCP_SDK_MAX_TOKENS

无

单次输出 token 上限(可选)

DSH_MCP_SDK_IDLE_MIN

10

后端空闲多少分钟回收(1–240)

DSH_MCP_SDK_INIT_TIMEOUT_S

300

后端 initialize 超时(秒);失败自动重试 1 次,仍失败则自动降级 headless

DSH_MCP_DEFAULT_CWD

无

省略 cwd 时使用;没设则用 worker 进程 cwd(stdio 启动时通常是 leader 的项目目录)

DSH_MCP_ALLOWED_CWDS

无

分号分隔的允许目录白名单(设置后只能在这些目录下跑)

DSH_MCP_PERMISSION_MODE

auto

默认 auto(worker 按 cwd 能力自动适配);也可显式 read-only / workspace-write / danger-full-access

DSH_MCP_TIMEOUT_S

900

单任务默认超时(秒)

DSH_MCP_MAX_CONCURRENT

2

全局并发任务上限(1–8,另受同 session 串行约束)

DSH_MCP_MAX_CONCURRENT_PER_CWD

1

同一 cwd 的并发上限(防止单项目占满)

DSH_MCP_TASK_TTL_MIN

1440

已结束任务保留分钟数,超时自动清理

DSH_MCP_TASK_MAX

500

任务数上限;超额先淘汰最老的已结束任务

DSH_MCP_CLEANUP_INTERVAL_MIN

10

自动清理间隔(分钟)

DSH_MCP_AUDIT_DIR

$DSH_HOME/mcp-audit

审计日志目录(audit.jsonl)

DSH_MCP_BATCH_DIR

$DSH_HOME/mcp-batches

批量任务元数据目录

DSH_MCP_BATCH_MAX

8

单次批量提交的最大任务数(1–32)

DSH_MCP_OTEL_ENDPOINT

无

OTLP/HTTP traces 端点(如 http://127.0.0.1:4318/v1/traces);空 = 关闭

DSH_MCP_OTEL_SERVICE

dsh-mcp-worker

OTel service.name

DSH_MCP_DSH_PATCH

apply

DSH 兼容补丁:apply(启动时自动检测+修复①pwsh 编码前缀 ②输出 GBK 兜底解码)/ notify / off

DSH_MCP_ACL_FALLBACK

danger-full-access

workspace-write 沙箱 ACL 授权失败时的自动升级策略:danger-full-access(默认,B 方案:升级为全权重试)/ read-only(只读重试)/ off(直接失败并给修法)。注意 full access 无沙箱

DSH_MCP_STATUS_WAIT_MAX_S

120

dsh_status 单次长轮询等待上限(秒,5–600);调大可减少 leader 轮询次数

DSH_MCP_MAX_TASK_TOKENS

0

暂缓启用:单任务 DSH token 预算,默认 0=不限制、不产生任何行为。实现已完成但按当前决定不开启;待积累 ≥20 条成功任务后,再按任务类型 p90×1.5 校准并启用(totalTokens 94–98% 是 cacheRead,若控成本需另按 input+output 折算)

DSH_MCP_CAPABILITY_CACHE

1

cwd 能力缓存(落盘,auto 模式据此选权限模式),跨 worker 进程

DSH_MCP_CAPABILITY_TTL_H

24

cwd 能力缓存 TTL(小时)

DSH_MCP_RETRY_TRANSIENT

1

后端崩溃/初始化失败时自动重试一次

DSH_MCP_AUTO_WORKTREE

1

ACL 受限仓库自动创建可写 worktree(仅干净 git 仓库)

DSH_MCP_WORKTREE_ROOT

~/dsh-worktrees

自动 worktree 根目录

DSH_MCP_NOTIFY_WEBHOOK

无

任务结束 POST 通知(JSON)

DSH_MCP_NOTIFY_CMD

无

任务结束执行命令(DSH_MCP_NOTIFY_JSON 环境变量传事件)

DSH_MCP_MAX_RESULT_CHARS

40000

结果超长时落盘阈值

DSH_MCP_MAX_STATUS_EVENTS

100

单次 dsh_status 最多返回多少条事件

DSH_MCP_TASKS_DIR

$DSH_HOME/mcp-tasks

任务落盘根目录

DSH_HOME

~/.dsh

DSH 状态目录(会透传给子进程)

权限模式说明(DSH 侧行为):

  • read-only:只读任务;

  • workspace-write(默认):项目目录内可读写、可跑命令;越界/提权操作会被 DSH 审批 fail-closed 拒绝(headless 没有审批通道);

  • danger-full-access:全权,谨慎使用(只在明确信任的任务上开)。

任务落盘与恢复

$DSH_HOME/mcp-tasks/<task_id>/
  meta.json      状态、cwd、session、退出码、错误
  events.jsonl   DSH --json 事件流(追加写)
  result.txt     输出超长时的完整结果

审计日志(append-only,独立于任务目录):$DSH_HOME/mcp-audit/audit.jsonl,记录 task_created / task_started / task_succeeded|failed|cancelled / approval_*;可用 dsh_audit 查询。

worker 重启时,未完成的 queued/running 任务会被标记为 failed(interrupted: worker restarted before the task finished),不会假装成功。

安全模型

  • 只走 stdio 或显式 HTTP:默认 stdio 不监听端口;HTTP 模式必须 Bearer token(0.0.0.0 无 token 直接拒绝启动)。

  • cwd 校验:拒绝用户主目录及其祖先目录(Windows ACL 沙箱会让 shell 工具不可用),可加 DSH_MCP_ALLOWED_CWDS 白名单。

  • 默认 fail-closed:无人值守没有审批通道(两种后端一致),需要审批的操作一律拒绝,不会静默放权。

  • 取消即杀进程树(Windows taskkill /T /F),避免僵尸 DSH。

  • 输出有界:超长结果落盘,避免撑爆 leader 上下文。

已知限制

  1. 冷启动:sdk 后端首次任务支付一次 initialize(本机实测 7–30s,随机器负载波动),之后每任务只付模型时间(实测 3s 级);headless 后端每任务 4–11s(fallback)。initialize 超时默认 300s,失败自动重试 1 次;仍失败则自动降级 headless 重跑同一任务(避免 leader 直接看到一次失败)。

  2. sdk 后端没有 cancel 协议:dsh_cancel 等价于杀掉该 cwd 的后端进程,下次任务自动重建(已实测);同一 cwd + 权限模式共享一个后端。

  3. sdk 后端模型/权限是进程级:模型由 DSH_MCP_SDK_MODEL 固定;不同 permission_mode 会走不同后端进程。

  4. session_id 复用仅在同一个后端进程生命周期内可靠;进程被回收/杀掉后同 id 行为未验证。

  5. --json 事件流对非 final 字段有 8 KiB / 32 KiB 截断,final 无损;完整轨迹看 events.jsonl。

  6. 同一 session_id 只能串行;并发续聊需拆成不同 session。

  7. Progress 通知依赖 leader 传 progressToken;不传时只是没有进度事件,不影响任务。

  8. HTTP 模式是无状态的:每个请求独立创建 server/transport,不做 MCP 会话;进度通知只在单次请求的 SSE 流内有效。

  9. 任务会被自动清理:超过 DSH_MCP_TASK_TTL_MIN 的已结束任务(含落盘目录)会被删除,之后查询返回 task_not_found。

  10. 授权弹窗由 leader 侧配置决定:Codex/ChatGPT 的「不询问」值是 approve(auto 仍会按风险询问;writes 只对写工具询问;prompt 全问),建议 default_tools_approval_mode = "approve" + 每个工具的 [mcp_servers.dsh.tools.<tool>] approval_mode = "approve",并完全退出重开 app;Claude Code 用 permissions.allow。桌面端另有已知 bug(openai/codex#40793、#20289:部分版本线程内仍每次询问、忽略 approval_mode),遇到底座 bug 只能点「始终允许」、升级 app 或改用 Claude Code/CLI。关闭逐次确认后安全边界由 worker 的 permission_mode(默认 workspace-write)与审批桥 fail-closed 兜底。

  11. initialize 偶发卡顿:initialize 正常 7–30s;曾出现 >120s 超时(旧默认值)导致任务失败,现已改为 300s + 重试 + headless 降级,并在错误里带 stderr 证据。

  12. Windows ACL 沙箱要求目录为「完全控制」:DSH 的 workspace-write 会给工作目录写能力 SID + Low 标签,要求调用方对目录拥有完全控制(含 WRITE_OWNER);公司仓库常见继承 ACL 只有 Modify → SetNamedSecurityInfoW failed (Win32 5)。worker 默认按 B 方案:检测到该失败后自动升级 danger-full-access 重试(结果里 sandbox_fallback + effective_permission_mode 显式记录,不掩盖);可用 DSH_MCP_ACL_FALLBACK=read-only|off 收紧。

  13. 自动升级的 full access 无沙箱:任务在 danger-full-access 下可读写当前用户能访问的任意路径;这是为「调用简单」有意选择的 B 方案,请配合 DSH_MCP_ALLOWED_CWDS 限定目录、审计日志与 git 回滚使用;高敏感仓库建议用 read-only 或 off。

  14. 审计日志无轮转:audit.jsonl 持续追加,长期使用需自行归档/切割。

  15. ChatGPT 直连未打通:需要 Secure MCP Tunnel(无配额未实测)或自建 HTTPS + OAuth 2.1(OAuth 未实现);本地 HTTP + Bearer 给不了 ChatGPT。

  16. 审批桥 v0 是粗粒度:只做「检测审批阻断 → elicitation 询问 → 整任务以 danger-full-access 重试」,且真实 DSH 审批场景尚未端到端实测。

  17. 批量/检索的边界:批量元数据(batch_id → task_ids)落盘可跨重启,但子任务本身仍受 TTL 清理;dsh_search 只扫内存中保留的任务(被清理的历史任务搜不到)。

  18. OTel 是轻量实现:不引 OTel SDK,只把每个任务的 span 以 OTLP/HTTP JSON 推送(best-effort,3s 超时);指标是 dsh_metrics 拉取式快照,未做 OTLP metrics 推送。

  19. read-only 下的 pwsh 编码问题(已自动双层修复):DSH 的 dsh-pwsh-local 会给每条命令前缀 [Console]::OutputEncoding = [System.Text.UTF8Encoding]::new($false);read-only 的 Windows ACL 沙箱以 ConstrainedLanguage 启动 pwsh,构造 .NET 类型被拒 → 每次调用两条 InvalidOperation: 无法创建类型…。跳过该前缀后,无控制台 spawn 的 pwsh 又会按系统代码页(GBK)写 stdout/stderr,而 DSH 固定按 UTF-8 解码 → 中文输出/错误乱码。worker 启动时自动修两层:① 前缀改为仅非 ConstrainedLanguage 执行;② dsh-subprocess-local 的输出解码改为「UTF-8 严格解码失败 → GBK 兜底」(合法 UTF-8 输出不受影响)。均带备份、幂等;DSH 升级后下次启动自动重打。可用 DSH_MCP_DSH_PATCH=notify|off 关闭自动修复,手动脚本见 scripts/patch-dsh-pwsh-encoding.ps1 与 scripts/patch-dsh-output-decoding.ps1。

  20. ChatGPT web / Claude Desktop 两条远程/打包路径尚未实测。

  21. 续聊 session 不能跨后端恢复(已自动恢复):DSH SDK 协议只有 initialize/session/prompt/shutdown,没有 resume/restore;worker 重启或后端重建后用旧 session id 续聊会报 session "..." already exists。worker 自动换新 session id 重试一次,并把上一轮任务/结果摘要作为「续聊上下文」拼进新指令(事件 session_resume_fallback 可见;结果里的 session_id 是新 id)。同一后端存活时则正常续聊、不触发恢复。

  22. 长任务空闲回收(v0.6.5 已修):此前 sweep() 只看 lastUsedAt,运行超过 10 分钟的任务会被回收杀掉(真实 11 分钟任务、13.3M token 沉没);现在有 in-flight prompt 的后端不会被回收,任务结束刷新时间。

  23. read-only 的 ACL 误判(v0.6.5 已修):此前只要事件/最终文本里出现 SetNamedSecurityInfoW 就会被当作写沙箱失败,导致已产出完整报告的只读任务被标 failed;现在仅「非 read-only 模式 + tool_result.isError」才判定。

  24. token 预算默认关闭:DSH_MCP_MAX_TASK_TOKENS=0;建议真实使用设 3M–8M,防止单个失控任务烧掉大量额度。超限任务会被取消并标 failed(不是用户取消),事件流有 token_budget_exceeded。

  25. 自动 worktree 只对干净 git 仓库生效:有未提交改动/非 git 仓库会退回原目录的降级模式;worktree 创建后保留供 leader 审查,需自行清理。

  26. 完成通知是外部通道:MCP 协议无法主动唤醒空闲 leader;DSH_MCP_NOTIFY_WEBHOOK/NOTIFY_CMD 用于 webhook/桌面通知,未配置时不发通知。

排错

现象

处理

leader 里工具列表没有 dsh_*

检查命令路径、node 版本(需 ≥20);Claude Code 用 claude mcp get dsh 看状态与日志

DSH worker 错误 [invalid_cwd]

传具体项目目录;不要用 C:\Users\<user> 这类主目录

DSH worker 错误 [task_not_finished]

任务还没结束:先 dsh_status 轮询到终态,再 dsh_result

任务 failed 且 error 提到 approval

当前任务需要审批(如写工作区外):换 permission_mode=danger-full-access 或把操作限定在 cwd 内

Codex/ChatGPT 桌面端每次调用仍弹授权

确认 config.toml 中是 default_tools_approval_mode = "approve"(不是 auto)+ 13 个 per-tool approve,并完全退出重开 app;仍复现则是桌面端已知 bug(openai/codex#40793),可点「始终允许」、升级 app,或改用 Claude Code / codex exec(CLI 尊重配置)

read-only 任务中文输出乱码 / stderr 出现 InvalidOperation: 无法创建类型…

worker 启动时自动修复两层(前缀 + GBK 兜底解码);若调成 notify/off,手动跑 scripts/patch-dsh-pwsh-encoding.ps1 和 scripts/patch-dsh-output-decoding.ps1

任务报 SetNamedSecurityInfoW failed (Win32 5): grantWrite(...)

该目录 ACL 只有 Modify(常见于公司仓库):worker 默认自动升级 danger-full-access 重试,结果里 sandbox_fallback/effective_permission_mode 可见;不想用全权则设 DSH_MCP_ACL_FALLBACK=read-only 或 off

续聊报 session "..." already exists

正常降级路径:worker 自动换新 session id + 带上本地「续聊上下文」重试(事件 session_resume_fallback),无需手动处理;若任务需要严格原会话历史,请在同一 worker 进程/后端存活期内续聊

找不到 DSH 入口

设 DSH_MCP_DSH_CLI=D:\dsh-harness\node_modules\@deepseek-ai\dsh\lib\bin.js

想看真实参数/限制

调 dsh_describe

开发

src/
  index.ts         stdio 入口(生产环境装配)
  server.ts        MCP 工具注册(13 个工具 + instructions)
  task-manager.ts  异步任务:排队/并发/session 串行/每 cwd 配额/TTL 清理/状态机/长轮询/恢复/审计
  dsh-runner.ts    headless 后端:spawn dsh、NDJSON 解析、超时、杀进程树、stderr 尾部
  sdk-backend.ts   sdk 后端:长驻进程、initialize、prompt、session.event 映射、取消=杀进程
  sdk-pool.ts      按 cwd + 权限模式缓存后端,空闲回收
  sdk-runner.ts    用长驻后端实现 TaskRunner
  fallback-runner.ts  sdk 启动失败时自动降级 headless(仅基础设施失败触发)
  sandbox-errors.ts  Windows ACL 沙箱失败识别(grantWrite Win32 5)与降级判定/提示
  jsonrpc-line.ts  换行 JSON-RPC 客户端(请求/通知/超时/关闭)
  http-server.ts   Streamable HTTP 传输(无状态、Bearer、/healthz)
  approval.ts      审批阻断检测(供 dsh_result 的审批桥使用)
  audit.ts         append-only 审计日志(JSONL)
  artifacts.ts     任务产物的安全分页读取(dsh_read_result)
  batch-manager.ts 批量任务(fan-out):创建、聚合状态/结果、取消
  search.ts        历史任务内容检索(输出 + 工具结果)
  otel.ts          轻量 OTLP/HTTP span 导出(无 SDK 依赖)
  usage.ts         DSH token 用量提取/累加(headless step_end 与 sdk assistant/message)
  dsh-patch.ts     DSH 兼容补丁:启动时检测/修复 pwsh 编码前缀(apply/notify/off)
  ndjson.ts        NDJSON 解析(跨 chunk/CRLF/脏行)
  output.ts        输出落盘与摘要
  keyed-lock.ts    session 级串行锁
  config.ts        环境变量、DSH 入口探测、cwd 校验
  store.ts         meta.json / events.jsonl 落盘
test/              127 个单测 + 真实 DSH 烟测(`test/mcp-smoke.ts`、`test/http-smoke.ts`)
examples/          多端接入示例(Claude / Codex / MCPB / 远程接入)
scripts/           部署与运维:deploy.ps1(源码→运行目录)/ patch-dsh-pwsh-encoding / patch-dsh-output-decoding / measure-goals / leader-usage
docs/              measurement.md(目标口径/公式/A/B 协议/局限)、delegation-playbook.md(委派粒度与任务模板)
pnpm test          # 单元测试(假 DSH fixture,不耗模型 token)
pnpm smoke         # 真实 DSH 全链路(stdio,消耗少量 token)
pnpm smoke:http    # 真实 HTTP 传输冒烟(healthz / 401 / 真实任务)
pnpm measure:ab    # 目标达成率 A/B(leader 自己做 vs 委派 DSH;消耗 leader 额度)
pnpm measure:leader# 扫描 leader 会话用量(Claude transcripts + Codex rollouts)
pnpm build         # tsc 产物到 dist/

测试覆盖:NDJSON 解析/截断、输出落盘、session 锁、dsh 进程超时与取消、任务管理器(并发/每 cwd 配额/session 串行/长轮询/恢复/取消/TTL 清理/数量上限/审计)、JSON-RPC 客户端、SDK 长驻后端与池、HTTP 传输(鉴权/healthz)、审批桥、新增只读工具、DSH token 用量提取与累加、DSH 兼容补丁(编码前缀 + GBK 兜底解码;apply/notify/off/幂等/版本漂移)。

发布到 npm(维护者)

采用 npm Trusted Publishing(OIDC 绑定 GitHub Actions),CI 发布不需要 NPM_TOKEN。

  1. 首次发布必须手动(npm 上还不存在该包时无法配置 Trusted Publisher):

    npm login          # 浏览器/2FA
    pnpm build
    npm publish --access public
  2. 在 npm 包页面 → Settings → Trusted Publishing → GitHub Actions:

    • Organization/user:tongsh6

    • Repository:dsh-mcp-worker

    • Workflow filename:publish.yml

    • 保存时按需输入 2FA。

  3. 之后发布只需打 tag:

    npm version patch --no-git-tag-version
    git add -A && git commit -m "chore(release): vX.Y.Z"
    git tag vX.Y.Z && git push --follow-tags

    Actions 会执行 pnpm test → pnpm build → npm publish --access public --provenance(OIDC,无 token)。

  4. 也可在 Actions → publish → Run workflow 手动触发。

注意:npm Trusted Publisher 要求使用较新的 npm CLI(workflow 里用 Node 24),且 workflow 文件名必须与配置一致。

License:MIT(见 LICENSE)。

路线图

  • M1 ✅ 已完成(2026-11-02):长驻 dsh --profile sdk 后端(默认),一次 initialize 后每任务只发 prompt;保留 headless fallback。

  • M2 🟡 部分完成(2026-11-02):HTTP 传输(无状态 Streamable HTTP + Bearer + /healthz)与审批桥 v0 已实现并测试;ChatGPT 直连需 Secure MCP Tunnel(无配额)或 OAuth 2.1(未实现),见 examples/remote-access.md。

  • M3 ✅ 已完成(2026-11-02):任务 TTL 清理 + 数量上限、每 cwd 并发配额、审计日志(dsh_audit)、dsh_tasks、dsh_read_result。

  • M4 ✅ 已完成(2026-11-02):批量派发(fan-out)/ 历史任务检索 / 指标快照 / 轻量 OTel span 导出。

  • M5 ✅ 已完成(2026-11-02):目标达成率测量——worker 侧 DSH token 计量、A/B 对照工具、leader 用量扫描器、口径文档。

设计依据与市场调研见 本机分析报告(未随仓库提供)。

Available Tools

13 tools
dsh_audit查询审计日志A
Read-only

读取最近的审计事件(任务创建/开始/结束/取消、审批决定等),用于追溯与排障。

Inputs: limit.

dsh_batch_result获取批量任务结果A
Read-only

返回批量中每个任务的最终输出/错误/耗时;单条输出超过 max_output_chars 会截断(完整内容用 dsh_read_result)。

Inputs: batch_id (required), max_output_chars.

dsh_batch_run批量提交 DSH 任务A
Destructive

一次并行派发多个彼此独立、各自可验收的工作单元(每个任务仍应覆盖「实现+自测+证据」),立即返回 batch_id;用 dsh_batch_status / dsh_batch_result 聚合查询。不要用它串行拆解同一工作流。

Inputs: tasks (required).

dsh_batch_status查询批量任务状态A
Read-only

返回批量任务的整体状态、各子任务状态与计数;wait_s>0 时轮询到批量结束或超时。

Inputs: batch_id (required), wait_s.

dsh_cancel取消 DSH 任务A
Destructive

取消排队中或运行中的任务:运行中的任务会杀掉整个进程树。

Inputs: task_id (required).

dsh_describe描述 DSH worker 能力A
Read-only

返回 worker 版本、DSH 入口、默认参数与限制,便于 leader 自适应调用方式。

Inputs: no named parameters.

dsh_metrics查看运行指标A
Read-only

返回任务计数、耗时分位(avg/p50/p95/max)、DSH 侧 token 汇总、并发限制、排队情况、后端与 OTel 状态;用于 leader 自适应与「省 token/提速」核对。

Inputs: no named parameters.

dsh_read_result读取任务完整产物A
Read-only

当 dsh_result 因输出过长落盘(返回 artifacts)时,用本工具分页读取完整结果或事件日志;仅限任务目录内。

Inputs: task_id (required), offset, source, max_chars.

dsh_result获取 DSH 任务结果A
Read-only

任务结束后获取最终结果(含完整输出、退出码、耗时)。输出过大时会自动落盘并返回文件路径。任务未结束时返回错误。

Inputs: task_id (required).

dsh_run提交 DSH 任务A
Destructive

把一个可验收的完整工作单元(功能点/bug/测试修复批次/跨文件重构)交给本机 DSH 异步执行,立即返回 task_id。DSH 自己规划并执行多步工具调用(读代码、改文件、跑测试),一次任务应覆盖「实现 + 自测 + 证据」;不要提交单步/逐文件微任务。之后用 dsh_status 长轮询(wait_s 60–120)到终态,dsh_result 取结果;中断用 dsh_cancel。cwd 传当前项目绝对路径。

Inputs: task (required), cwd, wait_s, timeout_s, +2 more.

dsh_status查询 DSH 任务状态A
Read-only

查询任务状态与增量事件。status 为 succeeded/failed/cancelled 表示结束。用 wait_s 长轮询(建议 60–120s)一次等更久,减少 leader 往返;不要用 5–25s 高频轮询。

Inputs: task_id (required), cursor, wait_s.

dsh_tasks列出 DSH 任务B
Read-only

列出最近的任务摘要(task_id / 状态 / 任务预览 / cwd / 时间 / 错误),用于回顾历史与继续轮询。

Inputs: limit, status.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A4/5.0

    Scored across 13 tools

    Disambiguation4/5

    The lifecycle tools (run/status/result/cancel) and their batch counterparts (batch_run/batch_status/batch_result) are clearly separated by purpose. Minor overlap exists between dsh_result and dsh_read_result, and between dsh_tasks and dsh_search, but descriptions make the boundaries clear.

    Naming Consistency5/5

    All tools use a consistent dsh_ prefix with snake_case verb_noun patterns (dsh_run, dsh_status, dsh_batch_run, dsh_read_result). The batch family mirrors the single-task family predictably.

    Tool Count5/5

    13 tools is well within the ideal 3-15 range and each earns its place: core lifecycle, batch orchestration, result reading, search, audit, metrics, and introspection.

    Completeness5/5

    The surface covers the full async task lifecycle: submit, poll, fetch result, cancel, batch dispatch/status/result, large-output pagination, search, audit trail, metrics, and worker introspection. No obvious dead ends.

    Maintenance

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      B
      quality
      B
      maintenance
      Enables launching and supervising local Codex and Claude Code agent sessions and one-shot tasks, exposing run, list, stop, and output operations over MCP with session-scoped permissions and sandbox controls.
      2
      336 npm
      1
      MIT
    • A
      license
      Not graded
      quality
      B
      maintenance
      Connects ChatGPT and MCP clients to authorized local development environments, enabling secure file access, shell execution, persistent tasks, browser/desktop control, and remote management of projects.
      19
      MIT
    • A
      license
      D
      quality
      C
      maintenance
      Enables controlled local developer operations including file and process management, shell execution, SSH, WSL, Docker, Git, browser and desktop automation, media processing, and asynchronous jobs through MCP.
      146
      MIT