Back to home@bleakbelladonnals

dsh-echo

Record MCP once. Replay it safely inside DeepSeek Harness.

Stars
0
Language
TypeScript
Created
Aug 27, 2026
Updated
Aug 27, 2026

Introduction

DSH Echo — Record MCP once. Replay it safely.

CI License: Apache-2.0 Node.js 22.19+ or 24+ DSH 0.1.1-rc.2

An unofficial DeepSeek Harness plugin for deterministic MCP record/replay.
Capture a real tool session once, replay it without credentials or network, and inspect every match and contract change inside DSH.

简体中文 · Website · Install · Quick start · Architecture · Security

[!NOTE] DSH Echo is not affiliated with or endorsed by DeepSeek. Version 0.1 is installable from source but has not been published to npm.

Why DSH Echo?

MCP tools often sit in front of APIs, databases, and services that make agent tests slow, costly, nondeterministic, or unsafe. DSH Echo puts a cassette between DSH and the real MCP server: record once against reality, then replay the exact conversation offline.

Record realityReplay safely
stdio and Streamable HTTP/SSEdeterministic request matching
append-only, versioned JSONLfail-closed on an unrecorded call
secrets redacted before diskno real server on a normal replay
duration and response capturedstructured nearest-call diff
See what happenedGuard the contract
Session-scoped Web inspectorcontract snapshots
arguments, results, hit/miss stateclassified schema drift
compact Trajectory annotationsbreaking-change CI gate
second redaction pass before UIscanned fixture export

Install into DSH

Requirements:

  • Node.js 22.19+ on the Node 22 line, or Node.js 24+
  • DeepSeek Harness compatibility baseline: 0.1.1-rc.2
  • a fresh or explicitly selected DSH profile

Build a local package and install it into an isolated profile:

git clone https://github.com/bleakbelladonnals/dsh-echo.git
cd dsh-echo
npm ci
npm run build
npm pack --ignore-scripts

export DSH_HOME="$(mktemp -d)"
dsh plugin --profile web add ./dsh-echo-0.1.0.tgz
dsh --profile web --no-open

Open a Session and choose the Echo / 录制回放 tab. Installation adds the plugin with bindings: [], so it does not intercept or change an MCP server until you explicitly bind one.

To remove it:

dsh plugin --profile web remove dsh-echo

Omit the temporary DSH_HOME only when you intentionally want to install into your normal DSH profile.

Record and replay

Record a stdio MCP server. Redaction is enabled by default:

dsh-echo record -o .dsh-echo/demo.cassette.jsonl -- \
  node examples/fixture/server.mjs

Replay the same interaction offline:

dsh-echo replay .dsh-echo/demo.cassette.jsonl

An unrecorded request returns JSON-RPC error -32601 and exits non-zero. The real server is not started. Live fallback exists only when you explicitly pass --on-miss passthrough together with a real server command.

Streamable HTTP works through a loopback endpoint:

# Record
dsh-echo record -o .dsh-echo/http.cassette.jsonl \
  --http http://127.0.0.1:3000/mcp \
  --listen 127.0.0.1:6402

# Replay
dsh-echo replay .dsh-echo/http.cassette.jsonl \
  --listen 127.0.0.1:6402

Connect one DSH MCP server

DSH currently constructs MCP transports directly, so DSH Echo uses a reversible profile overlay instead of modifying DSH or editing your source profile in place:

dsh-echo profile patch \
  --source ./cordis.yml \
  --out ./cordis.echo.yml \
  --recovery ./cordis.echo.recovery.json \
  --root ./.dsh-echo \
  --server-row mcp-demo \
  --cassette-id demo \
  --cassette demo.cassette.jsonl \
  --mode replay

The generated replay row does not contain the original server command. Record/passthrough rows use argv arrays, never a shell-concatenated command. The source file is untouched. Restore the saved row into another file with:

dsh-echo profile restore \
  --recovery ./cordis.echo.recovery.json \
  --out ./cordis.restored.yml

Review generated YAML before applying it. HTTP record/replay is supported; HTTP passthrough is intentionally unavailable in v0.1.

What appears in DSH

For DSH tool names shaped like mcp__<serverName>__<tool>, the Host plugin adds a compact tool/result.meta.dshCassette reference. Full tool payloads stay in the cassette rather than being duplicated into the Session log.

The Echo / 录制回放 tab shows:

  • cassette identity, mode, transport, format, and redaction status;
  • each interaction's arguments, result, duration, and origin;
  • recorded, hit, miss, passthrough, and error state;
  • a structured argument diff for the nearest miss;
  • contract and schema drift, plus a snapshot action;
  • the annotations attached to the current Session/Trajectory.

Host APIs accept configured cassette IDs rather than caller-provided paths. All cassette and snapshot paths must resolve below the configured root, and values are redacted again before reaching the browser.

Contract gate

Capture a baseline:

dsh-echo snapshot --stdio "node examples/fixture/server.mjs" \
  -f mcp-contract.snapshot.json

Fail CI when a tool is removed or a breaking schema change appears:

dsh-echo snapshot --check --fail-on breaking \
  --stdio "node examples/fixture/server.mjs" \
  -f mcp-contract.snapshot.json

The repository's own CI fixture deliberately removes a tool and adds a required property, then asserts that the gate fails.

Export a reviewable fixture

Raw recordings live under the ignored .dsh-echo/ directory. Export is a separate, explicit step:

dsh-echo export-fixture \
  .dsh-echo/demo.cassette.jsonl \
  --root ./fixtures \
  --out demo.cassette.jsonl

Export refuses paths outside the selected fixture root and blocks detected secrets. A passing scan still requires human review: pattern-based redaction is defense in depth, not proof that a recording is safe to publish.

Architecture

flowchart LR
  DSH["DeepSeek Harness"] --> Adapter["DSH Echo profile adapter"]
  Adapter --> Core["record / replay core"]
  Core --> Live["real MCP server"]
  Core --> Tape[("versioned cassette")]
  Tape --> Core
  Core --> Session["Session annotations"]
  Session --> UI["Echo Web inspector"]

The transport engine remains usable as a standalone CLI, while the DSH layer lives under src/dsh/. See architecture for lifecycle, trust boundaries, and integration decisions.

Development

npm ci
npm run lint
npm run typecheck
npm test
npm run test:e2e
npm run audit:pack
npm pack --dry-run --ignore-scripts

The current suite covers 463 tests, including real stdio record/replay, a no-server replay tripwire, profile recovery, path containment, UI redaction, contract drift, lifecycle cleanup, and package inspection. Acceptance runs use temporary homes, loopback listeners, isolated npm caches, and isolated DSH profiles; they do not read or write the user's DSH configuration.

More detail:

Upstream and license

DSH Echo is derived from ivermin1123/mcp-cassette at commit 9e48be26cbf1f7fca5edde142673a9b102a25e86 (upstream version 0.4.0). The retained engine provides stdio and Streamable HTTP/SSE record/replay, matching, redaction, contract diff, safety lint, and Vitest integration.

See UPSTREAM.md and NOTICE for the exact import and modification record. Licensed under Apache-2.0.