Install
$ agentstack add mcp-jiezeng2004-design-dsh-chatgpt-bridge ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
dsh-chatgpt-bridge
An MCP bridge that lets ChatGPT Web create, view, continue and supervise DeepSeek Harness (DSH) agent sessions through the official Model Context Protocol. v0.3.0 — Goal Control Plane. The bridge only connects — DSH keeps its own session log, agent loop, tools, skills, subagents, workflows, approvals, sandbox and workspace security model. It is a standalone DSH plugin: zero DSH core modifications.
> Self-hosted / dogfooding development: implemented against the installed DeepSeek > Harness source (0.1.0-rc.6) and verified end-to-end against a live local DSH > runtime with the official MCP SDK client.
Quick Start
This gets a new user from zero to a verified ChatGPT ↔ DSH connection. Deep architecture and configuration details follow below — you do not need them to install and verify.
Requirements
- Node.js >= 22 installed and on your
PATH. - A working DeepSeek Harness (DSH) installation —
dshon yourPATH
(or use pnpm dlx @deepseek-ai/dsh@0.1.0-rc.6 in place of dsh in every command below).
- A web profile is recommended. The Web UI and the Bridge should run in
the same web profile/runtime so that ChatGPT-created sessions appear live in DSH Web.
- **ChatGPT-side MCP and write-action availability depends on your current
plan/workspace. Check OpenAI's current official documentation before setup.**
- This plugin includes write/action tools (
dsh_send_message,
dsh_start_goal, dsh_approve, ...), not just read-only MCP. It drives a real DSH agent that can modify files inside registered workspaces under DSH's approval/sandbox policy. Treat it accordingly.
1. Install
Recommended — install the plugin into the web profile (from the published npm package):
dsh plugin --profile web add dsh-chatgpt-bridge
npm install dsh-chatgpt-bridge alone is not enough: the plugin must be added to a DSH profile bundle, which dsh plugin ... add does for you. See [Detailed install](#detailed-install) for source, headless, and manual variants.
2. Start one shared DSH runtime
dsh web
Run the DSH Web UI and the Bridge in the same web profile/runtime. ChatGPT-created sessions are native DSH sessions; they only stream live in DSH Web when both share one runtime.
| Endpoint | URL | | --- | --- | | DSH Web | http://127.0.0.1:3080 | | Bridge MCP | http://127.0.0.1:3456/mcp |
3. Read the authentication token
On first boot the bridge generates a token and persists it to $DSH_HOME/chatgpt-bridge.token. Read it with:
Windows (PowerShell):
Get-Content "$HOME\.dsh\chatgpt-bridge.token"
macOS / Linux:
cat ~/.dsh/chatgpt-bridge.token
> Never commit this token to GitHub or paste it into a public chat. It > authorizes MCP access to your DSH runtime. Alternatively, set > DSH_CHATGPT_BRIDGE_TOKEN yourself and the bridge uses it instead of the > generated file.
4. Connect ChatGPT
ChatGPT Web cannot open a plain localhost MCP endpoint. A URL like http://127.0.0.1:3456/mcp exists only on your machine; ChatGPT Web is a remote MCP client and cannot reach it directly.
- If the Bridge runs on your machine, connect ChatGPT through the **Secure
MCP Tunnel / secure tunneling mechanism that OpenAI currently supports** for MCP/custom apps. The tunnel forwards ChatGPT's requests to the loopback endpoint.
- Use the token from step 3 as the MCP Authorization Bearer token for the
connector/tunnel.
- The Bridge keeps its localhost-first design: it binds
127.0.0.1, never
exposes a public interface, and never self-hosts a tunnel.
- The stdio transport is not the ChatGPT Web quick path — ChatGPT Web does
not launch local processes. See [Advanced / other MCP clients](#advanced--other-mcp-clients) for stdio and non-ChatGPT MCP clients.
5. Scan / refresh tools
After the MCP connection is established, scan / refresh the MCP tools in ChatGPT. v0.3.0 exposes 15 tools, and dsh_update_goal must be present (it is the 15th). If the tool list looks stale, refresh/rescan the connector (see [Tool count is stale](#tool-count-is-stale--dshupdategoal-missing-after-upgrade)).
6. First verification
Give ChatGPT this read-only acceptance prompt:
请使用已连接的 DSH App,只做只读检查:
1. 调用 dsh_health
2. 调用 dsh_list_workspaces
3. 不修改任何文件
4. 返回 bridge version、health 和 workspace 名称
Expected:
health = ok
bridge version = 0.3.0
Then a minimal Goal Supervision example (still read-only):
使用 dsh_start_goal 创建一个只读检查目标(workspace 用 dsh_list_workspaces
查到的名称),goal 描述为“只读检查项目”,plan 为列出项目结构并总结
README,constraints 使用 {"read_only": true}。然后反复调用 dsh_wait_goal
直到 terminal,最后只汇报 health、goal revision 和总结,不修改任何文件。
Troubleshooting
ChatGPT cannot connect
http://127.0.0.1:3456/mcp is a loopback address on your machine — ChatGPT Web cannot reach it as a remote MCP server. Check the Secure MCP Tunnel / currently supported secure connection method for MCP/custom apps: the tunnel must forward to the loopback endpoint with the bearer token.
401 Unauthorized
- Read the token:
Get-Content "$HOME\.dsh\chatgpt-bridge.token"
(PowerShell) or cat ~/.dsh/chatgpt-bridge.token (macOS/Linux).
- The connector must send it as the
Authorization: Bearerheader. - The token belongs to the runtime that generated it. A different
$DSH_HOME, a regenerated token, or a mismatched DSH_CHATGPT_BRIDGE_TOKEN all cause 401 — make sure the token matches the currently running runtime.
dsh_health works but no workspace appears
dsh_list_workspaces only lists workspaces already registered in DSH. The bridge never auto-registers arbitrary paths; dsh_create_session with an unregistered path fails with WORKSPACE_NOT_FOUND on purpose. Register the workspace in DSH (Web profile workspace settings / DSH configuration) first.
Session exists but does not appear live in DSH Web
The Bridge and DSH Web must run in the same web profile/runtime. Do not run a separate chatgpt-bridge runtime and a separate web runtime and expect live parity — sessions persist and can be resumed, but they will not stream in real time.
Tool count is stale / dshupdategoal missing after upgrade
Re-scan / refresh the MCP tools on the ChatGPT side after upgrading the plugin and restarting the profile. v0.3.0 exposes 15 tools; dsh_update_goal is the 15th.
Port 3456 already in use
Identify the process first — never auto-kill an unknown process. On Windows (PowerShell):
Get-NetTCPConnection -LocalPort 3456 | Select-Object LocalAddress, LocalPort, OwningProcess
Get-Process -Id | Select-Object Id, ProcessName, Path
On macOS/Linux:
lsof -iTCP:3456 -sTCP:LISTEN # or: ss -ltnp 'sport = :3456'
If it is an old dsh/bridge process, stop it cleanly. Otherwise change the bridge port in the profile config (see [DSH configuration](#dsh-configuration)) or free the port.
Bridge error codes
| Symptom | Cause / fix | | --- | --- | | WORKSPACE_NOT_FOUND | The workspace is not registered in DSH; dsh_list_workspaces shows what is allowed. | | SESSION_NOT_FOUND | Unknown session id (never created, or persistence not mounted). | | SESSION_NOT_LIVE on cancel | The session is not loaded in this process; only live sessions can be cancelled. | | APPROVAL_NOT_FOUND / QUESTION_NOT_FOUND | The decision was already taken or the bridge restarted (parked decisions are in-memory). | | question provider slot taken (log) | A web UI is attached and owns user questions; answer them in the UI. | | Cold sessions show no title in dsh_list_sessions | Cold titles come from the projection cache; concurrent DSH profiles sharing the cache can clobber rows. Single-profile deployments get titles. |
60-second smoke test
After completing Quick Start steps 1–3:
dsh web— one shared runtime.- Establish the MCP tunnel to
http://127.0.0.1:3456/mcp. - In ChatGPT: Scan Tools.
- Ask ChatGPT to call
dsh_health. - Confirm:
health = okbridge version = 0.3.0- tool count = 15
dsh_update_goalexists in the tool list
- Optionally call
dsh_list_workspacesto confirm your workspace is
visible.
Architecture
ChatGPT Web
|
| MCP (Streamable HTTP / stdio)
v
dsh-chatgpt-bridge ask user --> dsh_approve --> wait again
+-- waiting_for_user --> ask user --> dsh_answer_question --> wait again
+-- completed / failed / cancelled --> done (result is in the wait payload)
continuation_requiredis an MCP client contract: ChatGPT should call
dsh_wait_goal again in the same assistant turn until the loop stops. Do not reply "the task is running in the background" and end the turn.
- One MCP call waits internally (≈500ms polls, up to 25s). Do not spam
dsh_get_task_status every few hundred milliseconds.
waiting_for_approval/waiting_for_usersetneeds_user_actionand
do not continue. Never auto-approve; never guess the answer.
dsh_stop_goalis the user-facing "stop DSH" tool. It is idempotent
(already_stopped=true if the session is already terminal).
- Optional
request_idondsh_start_goalmakes connector retries in the
same process idempotent. It is an in-memory map (cap 256), not a Goal DB. After a process restart, continue with session_id.
dsh_health.capabilities.goalSupervisionis always true in v0.2+.- The stabilization work originally tracked as "0.2.1" (never released) is
folded into v0.3.0: reconciled todos (from tool/result facts, not assistant text), progress_delta on dsh_wait_goal, structured blocked + remaining_runnable_steps, and fail-safe cleanup of goal-owned temps.
- v0.3.0 adds
dsh_update_goal(15 tools) and a Goal Control Plane: revisions,
execution modes, structured constraints, deferred/resume, bounded history.
Low-level tools remain for inspection and one-shot messages.
Goal lifecycle
create dsh_start_goal(workspace, goal, plan?, execution_mode?, constraints?)
-> revision 1, session_id
run DSH agent works; ChatGPT calls dsh_wait_goal
wait continuation_required → wait again
waiting_for_user / waiting_for_approval → ask human, then continue
revise dsh_update_goal(action=revise) or dsh_start_goal(..., session_id)
-> revision +1, previous snapshot kept
defer dsh_update_goal(action=defer, defer_steps=["npm_publish"])
-> step is deferred (not failed); independent branches stay runnable
resume dsh_update_goal(action=resume, resume_steps=["npm_publish"])
-> same session_id + goal_id; completed steps are not replayed
complete wait returns terminal + result; deferred_steps may still be listed
stop dsh_stop_goal (no revision bump; goal_cancelled event)
Approval and question answers do not increment revision.
Execution modes
| Mode | When | Behaviour | | --- | --- | --- | | standard | default, omitted | Current v0.2 agent instructions. Reasonable analysis/tests allowed. | | minimal | "only wait 35s", smoke, no extra work | Only actions strictly required. Default constraints: no workspace scan, max_changed_files=0. | | strict | user-supplied plan/constraints | Follow the plan/constraints; do not expand scope. |
Constraints (examples)
{
"read_only": true,
"allow_workspace_scan": false,
"max_changed_files": 0,
"forbidden_actions": ["filesystem.scan", "filesystem.write"]
}
Constraints can only tighten DSH sandbox/approval. read_only=false does not grant write. Runtime enforcement uses the approval waterfall (toolName + optional callId lookup of the logged tool/call) plus post-hoc fact checks. A bash command that never asks approval can only be caught after the fact.
Action classes: filesystem.read, filesystem.write, filesystem.scan, process.exec, git.mutate, npm.publish, github.release, network.
Dependency-aware Goal (npm + GitHub Release)
commit → verify → push → tag
├─ npm publish (may defer on 2FA)
└─ GitHub Release (still runnable)
When npm hits 2FA: dsh_update_goal({ action: "defer", defer_steps: ["npm_publish"] }). GitHub Release continues on the same session. Later action: "resume" reactivates npm without retagging or repushing.
Deliberately NOT exposed (first version)
execute_shell, run_command, read_any_file, write_any_file, delete_file, git_push, install_package, run_arbitrary_tool. ChatGPT never gets a direct shell: it talks to the DSH agent, and the DSH agent uses DSH tools under DSH's approval/sandbox/workspace policy.
Session lifecycle
Preferred (v0.2 Goal Supervision):
ChatGPT: dsh_start_goal(workspace, goal, plan)
-> { session_id, continuation_required, next_tool_call: dsh_wait_goal }
ChatGPT: dsh_wait_goal(session_id) (repeat while continuation_required)
-> { terminal: true, result: { summary, changed_files, todos } }
Low-level Session API (still supported):
ChatGPT: dsh_create_session(workspace)
-> session_id (e.g. session-034daf61-...)
ChatGPT: dsh_send_message(session_id, "帮我分析这个项目,不修改文件。")
-> {accepted: true} # returns immediately
DSH: agent.followup() -> turn runs in the background
ChatGPT: dsh_get_task_status(session_id) -> running -> completed
ChatGPT: dsh_get_result(session_id) -> analysis text
ChatGPT: dsh_send_message(session_id, "刚才第 2 项不错,现在实现它。")
-> same session, same agent loop, same durable log
DSH is the authority for session identity. Sessions persist as $DSH_HOME/sessions///session.jsonl.zstd (event log) and survive bridge restarts, ChatGPT conversations, and DSH restarts: dsh_send_message on a cold session resumes it through ctx.agents.resume(), which replays the log into the model context (verified: a marker learned before a process restart was still remembered afterwards).
Security model
- No arbitrary shell tool — see the tool catalog.
- Workspace boundary — sessions can only be created in workspaces DSH
already registered (ctx.workspaceRegistry). Arbitrary paths are never opened or auto-registered; dsh_create_session with C:\Users\..., /, ~, etc. is rejected with WORKSPACE_NOT_FOUND.
- Approval is never bypassed — if DSH asks for approval, the bridge parks
the request (waiting_for_approval) and only dsh_approve with the exact approval id can grant it, once, for that exact tool call (allowed-once). No auto-approve, no approve-all. If the bridge unloads while requests are parked, they resolve cancelled (fail closed).
- Sandbox is inherited, not weakened — created sessions get
meta.cwd = workspace.path, so DSH's per-session sandbox confines the agent's file effects to that workspace.
- Localhost-first — the HTTP server binds
127.0.0.1by default. - Secret redaction — all bridge logs and tool outputs pass through a
redactor (sk-... keys, bearer tokens, key=value secrets, OTP, secret-shaped keys). Goal history never stores OTP, tokens, cookies, or Authorization headers. The generated token is never logged.
- Goal constraints tighten only — they never raise sandbox or approval
rights. OTP supplied for one exact operation is not persisted.
- No ChatGPT credentials — the bridge never reads cookies, never drives a
browser, never stores OpenAI session tokens.
Approval behavior (concrete)
- The DSH agent requests a permission. DSH emits
approval/request. - The bridge (an answerer for its own sessions) parks the request; the
session shows waiting_for_approval with {approval_id, tool_name, call_id?, reason?}.
- ChatGPT calls
dsh_approve(session_id, approval_id, "approve")→
`a
…
Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: jiezeng2004-design
- Source: jiezeng2004-design/dsh-chatgpt-bridge
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.