Skip to main content
Glama

中文

English

DSH Carrot on a Stick

A DSH plugin that exposes DSH operations through the MCP protocol。

MCP features

Tools

Tool

Purpose

dsh_get_started

dsh crash course for the agent — concepts, recipes, error recovery. Call this first

echo

connectivity check

dsh_status

plugin status: version, listening, uptime, queue counters, connected clients

dsh_list_tools

list the host's global tool registry

workspace_list

registered workspaces and their sessions

model_list

routable providers / models / reasoning efforts, and the current default

agent_run

run a task now, get a structured result back; sessionId continues a session; per-call provider / model / reasoningEffort / preset; cancellable, with progress heartbeats

agent_steer

mid-run guidance to a running agent — steer acts at the next step boundary, inject adds context only

task_inbox

queue a background task, get a taskId; idempotencyKey dedupes retries

task_result

fetch a queued task's result (detail: "status" for cheap polling)

task_list

queue overview: queued / running / finished

task_cancel

cancel a queued (immediate) or running task (cancelling → cancelled)

session_list

known sessions (live + persisted), newest first

session_history

recent turns of a session; roles filter (e.g. ["assistant"])

select_model

switch an existing session's model, history preserved

attach_session

attach a session to the workspace of its cwd

rename_session

rename a session

Resources

Resource-capable clients can read the same data without spending tokens, and subscribe to changes instead of polling:

URI

Content

dsh://status[/config|/stats|/connections]

deployment status

dsh://guide[/{section}]

dsh usage guide (markdown)

dsh://tools

host global tool registry

dsh://models[/{provider}]

model catalog

dsh://presets

legal preset ids

dsh://workspaces[/{id}]

workspace registry

dsh://sessions[/{id}]

session list / metadata

dsh://sessions/{id}/history[/{before}]

conversation digest (paged)

dsh://sessions/{id}/events[/{after}]

raw event stream (JSONL, paged)

dsh://sessions/{id}/activity

live turn window

dsh://queue[/{taskId}]

queue / task detail incl. the full result

dsh://agents

resident session pool

resources/subscribe pushes task status transitions, turn-end history refreshes, and live activity over SSE — no polling. Setting resourceFirst: true in the config retires the nine read-only tools and returns results as resource references (for clients confirmed to support MCP resources; default false keeps tools and resources coexisting).

Related MCP server: hermes-dsh-bridge

Everyday patterns

One-off task — synchronous, structured summary back; continue later with sessionId (send only the delta in context):

{ "name": "agent_run", "arguments": { "task": "fix the failing test in src/auth", "cwd": "/workspace/app" } }

Background queue — submit, poll cheaply, fetch once done:

{ "name": "task_inbox",   "arguments": { "task": "…", "cwd": "/workspace/app" } }
{ "name": "task_result",  "arguments": { "taskId": "…", "detail": "status" } }
{ "name": "task_cancel",  "arguments": { "taskId": "…" } }
{ "name": "task_result",  "arguments": { "taskId": "…" } }

Sessions — session_list to find one, session_history to read it, select_model to switch its model, agent_steer to redirect it mid-run.

Models & presets

  • Priority: per-call arguments > plugin config > host default. A half-set pair completes from the lower source; unresolvable calls fail loudly.

  • Three ways to change models: per-call provider+model · select_model mid-conversation · pin via config with allowModelOverride: false. Presets (preset argument, for new sessions) work the same way under allowPresetOverride.

  • Sessions are pooled per cwd + model + preset: same directory, different model/preset → a separate session. Taking over a session keeps its model and preset.

  • Continuing by sessionId runs in the session's own directory; an explicitly passed cwd must match it.

Result size — detail controls token cost: summary (default, a few hundred tokens) / normal (~2k) / full (debugging); task_result adds a status level for polling. Results are structured (sessionId, model, changes, verification, leftovers, …); failures come back with isError: true.

Configuration (cordis.yml)

- insert:
      - id: dsh-carrot-on-a-stick
        name: 'dsh-carrot-on-a-stick'
        config:
            http: true
            port: 8090
            host: 127.0.0.1 # localhost only by default; add auth before exposing
            # authToken: 'your-secret-token'
            # workspaceRoots: ['/workspace']   # cwd whitelist (also gates session surfaces)
            # allowedHosts: ['my-box.lan']     # extra allowed Host header values
            # preset: 'standard'               # agent preset to mount
            # model: ''                        # pair with provider; empty = follow host default
            # provider: ''
            # reasoningEffort: ''              # empty = adapter default
            # allowModelOverride: true         # false = pin the model
            # allowPresetOverride: true        # false = pin the preset
            # queuePersistPath: '.dsh/queue.json'
            # queuePersistKey: 'passphrase'    # encrypt the persistence file
            # sessionTtlMs: 86400000

Field

Default

Meaning

host / port

127.0.0.1 / 8090

MCP server bind address; a listen failure fails plugin startup

authToken

—

Bearer token; enforced on every request when set

workspaceRoots

—

cwd whitelist — agents may only work inside listed directories; also limits which sessions can be taken over or read

allowedHosts

—

extra allowed Host-header values (bind host and loopback always allowed)

provider / model

follow host settings

default model for spawned agents; configure as a pair

reasoningEffort

adapter default

default reasoning effort (ids in model_list)

allowModelOverride

true

whether callers may override the model per call

allowPresetOverride

true

whether callers may pick a preset for new sessions

preset

standard

agent preset to mount (per-call preset applies to new sessions only)

defaultDetail

summary

default detail level for agent_run / task_result

resourceFirst

false

resource-first mode: read-only tools retire, results come back as resource references

reattachOrphans

false

bulk-attach ungrouped sessions to workspaces at startup

maxQueue / taskTtlMs / maxAgents

100 / 24 h / 8

queue capacity, result retention, session-pool size

taskTimeoutMs

0 (off)

auto-cancel an agent turn after this long

progressIntervalMs

5000 (min 250)

progress heartbeat interval

queuePersistPath

— (off)

persist the task queue; finished results survive restarts, queued tasks re-execute, running tasks are marked interrupted

queuePersistKey

— (plaintext + warning)

encrypts the persistence file; wrong passphrase / corrupt file → queue starts empty

sessionTtlMs

86400000

idle MCP transport sessions are reaped after this (0 = never)

Security

⚠️ This plugin exposes local code execution (equivalent to RCE). It binds 127.0.0.1 only. When enabling:

  1. Set authToken — protects against other local processes and DNS rebinding;

  2. Set workspaceRoots — without it there is no directory boundary at all; with it, execution and session reads (list / history / steer / takeover) are both constrained;

  3. Never bind 0.0.0.0 or expose to LAN/WAN without a reverse proxy + TLS + auth.

Built-in guards: Host- and Origin-header allowlists (DNS-rebinding guard), HTTP surface limited to /mcp, 401 answers with a Bearer challenge, idle transport sessions reaped after sessionTtlMs. Note that spawned sessions follow the host/preset approval policy — this plugin runs unattended, so ask-style policies may pop dialogs or fail closed; verify sensitive operations under your preset before deploying. If you enable queuePersistPath, task payloads are written to that file (plaintext unless queuePersistKey is set) — choose a location with appropriate permissions.

Web settings panel

The bundle adds a Settings → dsh-carrot-on-a-stick section to the dsh web UI: live status badge, the MCP endpoint (click to copy), start/stop buttons, connected client list, and queue counters.

Known limitations

  • Spawned sessions follow the host/preset approval policy — ask-style policies may pop a dialog or fail closed in unattended use.

  • select_model requires the web profile's sessionController; headless deployments fall back to the model catalog plus per-call overrides.

  • dsh_list_tools only lists the host-global registry; per-agent tool visibility needs a host-side API.

  • Without queuePersistPath the queue lives in memory and is lost on restart.

Acknowledgements

Started as a copy of chushixixin/dsh-harness-mcp-server (MIT, thanks @chushixixin), now an independent project.

Maintenance

ActivityMaintained
ResponsivenessUnresponsive

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables external MCP clients to drive DeepSeek Harness agents for real coding tasks, providing tools for task execution and queueing, session management, sandboxed file access, preset switching, and usage statistics.
    454 npm
    6
    GPL 3.0
  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables local workspace management and status checks through MCP tools over an HTTP endpoint, allowing DeepSeek Harness to interact with the platform.
    MIT