← Back to home@chimneyQ

dsh-mcp-context-mode

DeepSeek Harness bundle: native ctx_* sandbox tools (no MCP child), routing gate, repaired HTTPS fetching, and session context-occupancy reporting.

Stars
0
Language
JavaScript
Created
Oct 15, 2026
Updated
Oct 16, 2026

Introduction

dsh-mcp-context-mode

简体中文 | English

Give DeepSeek Harness a sandbox it can run code in, a searchable knowledge base it can file things into, and a routing gate that keeps bulk output out of the conversation.

Everything registers as plain ctx_* tools in the host process — no child process, no JSON-RPC hop, no mcp__ prefix in tool names.

What it is for

A conversation pays for every byte a tool returns, and it keeps paying for the rest of the session. This plugin moves the heavy work off that budget.

A settings page (Settings → Context mode, also a card in the Plugins panel) lists every switch this plugin has and shows a live read of the current session: total occupancy, the system / tool-schema / conversation split, the biggest contributors, and this plugin's own savings ledger. A switch that only takes effect at load time is marked as needing a restart instead of pretending it did something.

  • Analyse without reading. Run code in a sandbox and print only the answer — the raw bytes never enter the conversation.
  • File instead of paste. Put large material into a local full-text index, then pull back only the matching passages.
  • Fetch without flooding. Retrieve a page into that index rather than into the transcript.
  • See where the budget went. Ask for a breakdown of the current session's context occupancy.

Tools

Ten tools register by default, plus a context report. ctx_upgrade exists but ships switched off.

ToolWhat it does
ctx_executeRun code in a sandbox (JavaScript, TypeScript, Python, shell). Only what you print comes back.
ctx_execute_fileRun code over a file, without the file's bytes entering the conversation.
ctx_batch_executeRun several commands at once; each output is indexed automatically, and only the sections matching your queries are returned.
ctx_indexStore content in a local full-text (FTS5) knowledge base.
ctx_searchSearch that knowledge base. Batch several questions into one call.
ctx_fetch_and_indexFetch a URL and index it, returning only a small preview.
ctx_statsSession savings: bytes kept out of context and what they would have cost.
ctx_doctorSelf-check: runtimes, storage, SQLite/FTS5, version.
ctx_purgePermanently delete indexed content (per session or whole project).
ctx_insightOpen the companion analytics dashboard in a browser.
ctx_context_reportContext occupancy for this session: totals, breakdown by category, compaction suggestions, and this plugin's own ledger. Read-only — it replays the session log and makes no model calls.

Beyond the tools, a routing gate watches tool calls before they run: curl and wget are blocked outright (they paste whole pages into the conversation by design), long commands and oversized file reads get a nudge toward the tools above, and a small allowlist passes through untouched.

Install

Install straight from the repository:

dsh plugin --profile desktop add github:chimneyQ/dsh-mcp-context-mode

If pnpm stops with an ERR_PNPM_IGNORED_BUILDS message naming two dependencies, answer it with false — neither of them needs to compile:

# <DSH_HOME>/profiles/desktop/pnpm-workspace.yaml
allowBuilds:
  context-mode: false
  better-sqlite3: false

Then run the same command again.

Answer false, not true. This plugin's engine uses Node's built-in node:sqlite (present since Node 22.5) and only falls back to the native better-sqlite3 where that is unavailable. Allowing the build makes pnpm compile better-sqlite3 from source, which needs a C++ toolchain — on a machine without one it fails and the whole install aborts, leaving no plugin. Nothing needs building in the normal case.

From a local checkout, the same command takes the directory instead:

dsh plugin --profile desktop add D:\path\to\dsh-mcp-context-mode

Then restart DeepSeek Harness completely. The ctx_* tools appear in new sessions.

If the first attempt already failed

The host records the dependency before the build block is answered, and a second add on a profile that already lists it takes a different path: pnpm reports "Already up to date", the manifest keeps its entry, and the plugin is never added to dsh.profile.bundles — so it installs but never loads. Removing the entry first puts the profile back on the normal path:

# 1. answer the build block as shown above (keep allowBuilds false)
# 2. drop the half-written dependency
dsh plugin --profile desktop remove dsh-mcp-context-mode
# 3. install again — this time the bundle list is written
dsh plugin --profile desktop add github:chimneyQ/dsh-mcp-context-mode

Check it took: dsh.profile.bundles in <DSH_HOME>/profiles/desktop/package.json should list dsh-mcp-context-mode.

Use it well

SituationBetter than reading it yourself
A large log, CSV, or JSON to analysectx_execute_file — parse it in the sandbox, print the summary
Several commands whose output you need to comparectx_batch_execute with queries — gather and filter in one round trip
A long document or page you will quote fromctx_fetch_and_index, then ctx_search for the passages
Material you may need again laterctx_index once, ctx_search on demand
Wondering what is filling the contextctx_context_report

Reading a file in order to edit it is the one case where the host's own file tools are still right — they need the exact bytes.

Configuration

Every adjustable value lives in the plugin's Config, so setting it in cordis.patch.yml persists:

KeyDefaultMeaning
storageDir''Knowledge-base root; empty = <DSH_HOME>/context-mode
enginePath''Explicit engine entry; empty = resolve automatically
caPemPath'auto'TLS trust source: 'auto' writes a PEM into storageDir/ca; an absolute path is used as-is; '' disables
routingtrueMaster switch for the routing gate
denyCurlWgettrueBlock curl/wget outright
bashNudgeMinCommandBytes4096Long-command nudge threshold (bytes)
maxReadBytesBeforeAsk51200Oversized whole-file read nudge threshold (bytes)
contextReporttrueRegister ctx_context_report
compressNudgeTokens120000Occupancy warning threshold (tokens)
trustedReadBasenames4 namesFilenames exempt from the whole-read nudge
tools.*all true except upgradePer-tool switches

Verify

The repository ships SHA256SUMS.txt describing exactly the bytes it publishes. From the repository root:

node -e "const fs=require('fs'),c=require('crypto');for(const l of fs.readFileSync('SHA256SUMS.txt','utf8').split(/\r?\n/)){if(!l.trim()||l.startsWith('#'))continue;const [h,f]=l.split(/\s+/);console.log((c.createHash('sha256').update(fs.readFileSync(f)).digest('hex')===h?'OK  ':'BAD ')+f)}"

Offline self-checks. The first needs the dependency installed; the rest are self-contained:

npm ci
node smoke.mjs           # 36 assertions: tools, gate, TLS, context report
node test-client.mjs     # 17: the browser half's loader shape and field contract
node test-settings.mjs   #  8: every page control is a volatile Config field
node test-route.mjs      # 17: the settings page's data source, including every degraded path

Confirm the profile actually wired the plugin up (an install can leave the dependency recorded while never adding the plugin to dsh.profile.bundles, in which case it never loads):

node install-check.mjs --profile desktop

Known limits

  • The routing gate is advisory: where an approval channel exists it asks, and where none exists the call proceeds. It is not a security boundary.
  • tls.setDefaultCACertificates is a process-wide side effect; set caPemPath: '' to turn it off.
  • Session restore/distillation is not wired up. For durable notes, use ctx_index explicitly.

License

The plugin code in this repository is MIT (see LICENSE).

It depends on a third-party runtime engine, which is not distributed here: your package manager installs it, unmodified, under its own Elastic-2.0 license. The context-occupancy report borrows API usage from dsh-context (Apache-2.0, by bowenliang123); none of its code is copied.