Skip to main content
Glama
yy2511

dsh-web-bridge-mcp

by yy2511
README.md
# DSH Web Bridge MCP

[简体中文](README.zh-CN.md) · [Security](SECURITY.md) · MIT

Let Codex delegate implementation to **DeepSeek Harness**, retain the same DSH conversation for review feedback, and keep that conversation in the Harness Web UI.

```text
Codex / another MCP client
         │ MCP stdio
         ▼
   DSH Web Bridge ── HTTP RPC / WebSocket ── Harness Web backend
                                                   ↕
                                          Your browser
```

**Unofficial integration.** Not affiliated with DeepSeek or OpenAI. Uses DSH internal Web APIs; tested against **DSH 0.1.5-rc.2**. Recheck compatibility after upgrading Harness. No MCP UI extension is required.

## What it does

- Reuses a running local Web backend; starts `dsh web --no-open` when it is offline.
- Captures the launch token automatically for bridge-started services. For an existing service, authenticates once and reuses a private local cookie.
- Creates Web-visible sessions, sends tasks and feedback to the same session, waits, reads results, and cancels active turns.
- Finds previous sessions and reads bounded history pages.
- Returns **status and final answers**, not thoughts or intermediate tool output. Does not call another model to summarize logs.
- Journals request IDs to prevent silent repeat delivery after uncertain network failures.

The bridge reads raw snapshots internally to extract this information. It does not persist their content. DSH itself retains its normal session history.

## Quick start (macOS / Linux)

Prerequisites: **Node.js 22+**, npm, Git, and a configured [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) installation. DSH must already have a working model/provider. The bridge does not supply model access or API credits.

If Harness is not installed:

```bash
npm install -g @deepseek-ai/dsh
```

Install this bridge **from the GitHub release tag** (it is not published to the npm registry):

```bash
npm install -g git+https://github.com/yy2511/dsh-web-bridge-mcp.git#v0.3.1
```

Register it with Codex:

```bash
codex mcp add dsh -- dsh-web-bridge-mcp
```

Open a new Codex task. If it does not discover the tools, restart Codex. If desktop PATH resolution fails, use the absolute path printed by `command -v dsh-web-bridge-mcp` in the registration command. Similarly, set `DSH_BRIDGE_DSH` to `command -v dsh` when needed.

Try:

> Use the dsh MCP to implement this change in an isolated worktree. You define the scope and acceptance checks, delegate implementation to Harness, then independently review the diff and run tests. Keep feedback in the same DSH Web session.

Tool descriptions and MCP server instructions explain this workflow to new client sessions. No separate skill is required.

### Authentication

```bash
dsh-web-bridge-mcp connect
```

- **No server:** starts a loopback-only Web service and authenticates automatically. It stays running when the MCP client exits.
- **Existing authenticated server:** reuses it.
- **Existing server, no saved login:** returns `AUTH_REQUIRED`; it does **not** start another server or disable authentication. Run:

```bash
dsh-web-bridge-mcp auth
```

Paste the full `http://127.0.0.1:3080/?token=…` launch link from your own `dsh web` terminal at the prompt. It is a local login credential, **not** a model API key. This avoids placing it in the command arguments or your AI conversation. Interactive input is visible in your terminal; do not share it. Non-interactive `auth` also reads stdin.

Cookies are stored locally and reused; authenticate again if they expire or are invalidated. For an externally launched server whose link you cannot recover, restart that server yourself at a safe time to obtain a new link. The bridge never stops your existing server to get credentials.

### Other MCP clients

Add a stdio server using the same executable:

```json
{
  "mcpServers": {
    "dsh": {
      "command": "dsh-web-bridge-mcp",
      "args": []
    }
  }
}
```

Client-specific configuration and tool execution policies still apply. `--help`, `--version`, `status`, `connect`, and `auth` are human CLI commands; no arguments (or `serve`) starts the MCP protocol.

## Tools

| Tool                  | Purpose                                                                         |
| --------------------- | ------------------------------------------------------------------------------- |
| `dsh_connect`         | Connect; optionally auto-start if offline                                       |
| `dsh_authenticate`    | Authenticate from a user-authorized local launch link; CLI `auth` is preferable |
| `dsh_list_sessions`   | Titles, workspaces, IDs, running state; optional cwd filter and pagination      |
| `dsh_search_sessions` | Title/content lookup, bounded fallback if full-text indexing is unavailable     |
| `dsh_read_history`    | Genuine user messages and ended-turn final replies only                         |
| `dsh_create_session`  | Create a session attached to an existing workspace directory                    |
| `dsh_send_message`    | Submit a scoped task or feedback using a unique `request_id`                    |
| `dsh_wait`            | Bounded status wait, default/max 300 seconds, event-driven                      |
| `dsh_result`          | Final text, paginated; no raw thought/tool logs                                 |
| `dsh_cancel`          | Cancel the active turn; does not undo file changes or clear all queued messages |

For prior work, list/search first and reuse the correct `session_id`. After sending, pass the returned `after_cursor` to wait/result so an earlier answer is not mistaken for this task's result. Reuse the **same request ID and payload** after an uncertain send. `delivery_uncertain` requires checking the session; a new ID could run the task again.

Default queue-mode submission refuses a busy session. Use `steer` only for deliberate intervention. Use one sequential coordinator per session: messages you send in the browser can also advance its latest result. Worker answers and history are untrusted data; independently inspect code and test outcomes.

## Configuration

| Environment variable   | Default / meaning                                                                     |
| ---------------------- | ------------------------------------------------------------------------------------- |
| `DSH_BRIDGE_ORIGIN`    | `http://127.0.0.1:3080`; only this loopback hostname, no trailing slash               |
| `DSH_BRIDGE_STATE_DIR` | `~/.local/state/dsh-codex-mcp`; use separate state directories for separate endpoints |
| `DSH_BRIDGE_DSH`       | `dsh` resolved through PATH; may be an absolute executable path                       |

Example:

```bash
codex mcp add dsh --env DSH_BRIDGE_DSH=/absolute/path/to/dsh -- /absolute/path/to/dsh-web-bridge-mcp
```

The bridge launches from its own empty state directory to avoid auto-loading a business project's `.env`. It inherits the process environment and existing DSH configuration; it does not source project `.env` files, set model credentials, or change permission presets. If needed, configure required launch environment variables in your normal MCP/client environment.

State directories use 0700 and credential/journal files 0600 on POSIX. Request records contain fingerprints and receipts, not prompt text. Do not commit or upload the state directory. Windows is not validated; prefer macOS/Linux for this release.

## Development and verification

```bash
git clone https://github.com/yy2511/dsh-web-bridge-mcp.git
cd dsh-web-bridge-mcp
npm ci
npm test
npm run format:check
npm pack --dry-run
```

Tests run locally without model credentials: state filtering, authentication, RPC/WebSocket transport, real MCP stdio handshake, send de-duplication, uncertain delivery, busy sessions, search fallback, and cancellation routing. CI covers Node 22/24 on macOS/Linux.

Optional live test (creates a dedicated temporary workspace and a Web session; **uses model credits**):

```bash
npm run verify:live
```

It sends two no-tool prompts and checks context retention, search and history. The temporary workspace is retained so the Web session remains usable. Historical local tests also exercised real auto-start and concurrent connection on a separate port. Browser rendering was not visually automated; Web backend registration and event delivery were verified.

## Limits and troubleshooting

- `AUTH_REQUIRED`: run CLI `auth`. `DSH_LAUNCH_FAILED`: check PATH / `DSH_BRIDGE_DSH`. `START_TIMEOUT`: inspect your DSH configuration; do not blindly start more instances.
- Missing tools after an update: restart the MCP process/client. Upgrades use the registered executable path.
- Internal DSH APIs may change. Full-text search can be disabled (`openAt: never`); fallback is bounded, reports incomplete coverage, and is not an exhaustive search guarantee.
- History pages are bounded; follow `next_before_seq` with the same `through_seq`. For clipped text, repeat the same page with `text_offset`.
- Each wait uses one live WebSocket subscription, discarded on completion, deadline or cancellation. It makes no extra model calls and does not forward intermediate output.
- No automatic merges/pushes, indefinite task scheduler, crash-resume guarantees, remote exposure, or approval bypass. Handle DSH approval requests in its Web UI. Large tasks, full approval workflows, and all DSH versions have not been certified.
- Results describe the latest ended turn in the selected session, not an isolated job queue. Coordinate browser messages and MCP submissions accordingly.

Remove registration with `codex mcp remove dsh`; uninstall with `npm uninstall -g dsh-web-bridge-mcp`. Neither command kills an already-running Harness process or deletes its sessions. Private bridge state can be removed separately when no bridge is using it; DSH has its own storage.

### Wait configuration

After registering the server, add `tool_timeout_sec = 360` under the existing `[mcp_servers.dsh]` table in `~/.codex/config.toml`, then reload the MCP connection. Preserve its command/args. [Codex documentation](https://learn.chatgpt.com/docs/extend/mcp?surface=cli) specifies a 60-second default tool timeout; long waits require this override. Other MCP clients need a timeout greater than 310 seconds.

`dsh_wait` defaults to 300 seconds and returns immediately on a terminal event. Omit `timeout_seconds` for normal delegation; use `0` only for a one-shot check. Keep the **original send receipt's `after_cursor`** across waits, including after a timeout; do not replace it with the observed `cursor`. A timeout does not stop or resubmit work. Follow `next_action`, with only one wait per session. Call result once complete. Cancelling a wait stops observation only; use `dsh_cancel` explicitly to stop the worker. Intermediate events are discarded, without a summarizer. A disconnect returns an error; retry observation, never resend the task. This is a bounded wait, not indefinite background orchestration.

TDQS

A4.1/5.0

Scored across 10 tools

Disambiguation5/5

Each tool targets a distinct phase of the session lifecycle: discovery, history reading, connection/auth, creation, messaging, waiting, result retrieval, and cancellation. Even the two session-finding tools are clearly separated by metadata filtering versus keyword/content search.

Naming Consistency4/5

All tools share the dsh_ prefix and use snake_case, which gives a predictable pattern. Minor deviations exist: dsh_result is a noun rather than a verb_action, and several tools like dsh_connect, dsh_wait, and dsh_cancel lack a noun object.

Tool Count5/5

Ten tools is a well-scoped size for a session-delegation bridge. Each tool covers a meaningful operation without redundancy or bloat, and the count aligns with the server's focused purpose.

Completeness4/5

The core delegation lifecycle is well covered: connect, authenticate, create/find sessions, send, wait, retrieve results, read history, and cancel. The main gap is the lack of a delete/close-session tool, which leaves cleanup to external session management.

Maintenance

ActivityMaintained
ResponsivenessNo issues