Harnesses are the new moat because shipping the model alone is no longer enough. The harness has a huge effect on how useful the model feels: it controls the context, tools, file access, and the way the model works through a long task.
GPT comes with Codex, Claude comes with Claude Code, and Gemini comes with Antigravity. Each harness is built around the model it serves, so the team can tune it for the model’s quirks, strengths, and tool-use patterns.
Open-source models usually rely on common harnesses such as OpenCode and Hermes Agent. These harnesses perform well across many models, but they cannot be tuned for every model in the same way. We have also been using DeepSeek models through closed harnesses such as Claude Code and Codex. The setup works, although it can feel awkward because the model is running inside a system built with another model in mind.
The team behind V4 has now released DeepSeek Harness, which gives DeepSeek models a harness of their own.
There was no simple guide for connecting MCP to the harness, so I spent a few hours reading the code, testing different configurations, and working out how its MCP client handles remote servers. This article explains the setup that worked for me.
What is DeepSeek Harness?
DeepSeek Harness, or dsh, is an open-source agent harness built with Node.js on Cordis, a framework for composing plugins and services. Almost every part of the harness is a plugin, including model adapters, tools, permissions, sandboxes, session storage, and parts of the UI, while the active set of plugins defines what an agent can do.
Each turn runs through the same loop. The harness takes a queued prompt, opens a turn in the session log, builds the system prompt, derives the conversation history, sends the request through an LLM adapter, runs tool calls through the shared tool registry, and writes the results back to the log before the next step begins.
The session log is an append-only record of messages, model output, tool calls, and tool results. The model history is derived from this log, so anything that reached a model request can be reconstructed later. This design gives the harness its resume, fork, replay, crash recovery, and transcript features.
The Web UI ships with four presets:
Standard is the full coding agent with filesystem tools, shell access, web search, and subagents.
Minimal keeps the setup small with
bashandstr_replace_editor.Code presents the available tools as a generated TypeScript or Python SDK, which the model calls through
run_code.Creator, stored internally as the
cordispreset, helps the agent create custom presets and Cordis compositions.
The model layer also uses plugins, with a direct DeepSeek adapter and a multi-provider adapter for Anthropic, OpenAI, Bedrock, Azure, Gemini, and custom endpoints. The agent loop, tools, session system, and MCP setup stay the same when you change the model provider.
DeepSeek Harness is still in developer preview, so its presets and configuration can change between releases.
How MCP works in the DeepSeek harness
MCP is the open standard for connecting an agent to external tools and data. The harness implements it through a plugin, @deepseek-ai/dsh-mcp-client, and the rule is simple: one instance of that plugin equals one MCP server. You mount each server in the harness config, and every tool it exposes shows up in the registry namespaced as mcp__<serverName>__<toolName>. A GitHub server called github that offers a create-issue tool becomes mcp__github__create_issue.
The client speaks two transports:
Stdio launches a local MCP server as a subprocess and talks to it over standard input and output. Use this for servers you run on your own machine.
Streamable HTTP connects to a server over a URL. Use this for hosted or remote servers.
One detail to keep in mind: the built-in client passes static headers only and has no OAuth flow of its own. For servers that need OAuth, you complete that flow separately and pass a token or key through the headers.
Why route through Composio
You can add MCP servers to dsh one at a time, but each one is its own package, its own auth, and its own config block. Composio collapses that into a single hosted MCP endpoint that fronts 1000+ apps. You add one server, connect your accounts once, and your DeepSeek agent can act across all of them. Composio manages the OAuth exchange and token refresh on its side, which also keeps credentials out of your harness config since the built-in client cannot do OAuth itself.
I use Composio MCP in both Codex and Claude Code, and I have connected it to PostHog, Ahrefs, GitHub, Supabase, and several other apps. When I decided to try DeepSeek Harness with my daily workflows, I wanted access to the same tools instead of setting up each integration again.
Prerequisites
You will need Node.js (20 or 22) and pnpm, plus a Composio API key (ck_*) from the Composio dashboard. Build the harness from source:
git clone <https://github.com/deepseek-ai/deepseek-harness.git>
cd deepseek-harness
pnpm install
pnpm run build
pnpm dsh webThat launches the web UI. Set your model route under Settings → Models.
Adding a local MCP server (stdio)
MCP servers are mounted as patches in ~/.dsh/profiles/web/cordis.patch.yml. To add a local server, give the MCP client plugin a stdio config with the command that starts the server. Here is the GitHub reference server:
- insert:
- id: mcp-github
name: '@deepseek-ai/dsh-mcp-client'
config:
serverName: github
transport: stdio
command: npx
args: ['-y', '@modelcontextprotocol/server-github']
env:
GITHUB_TOKEN: !!js process.env.GITHUB_TOKENserverName sets the namespace for every tool the server exposes, so keep it short and unique ([A-Za-z0-9_-]{1,32}). command and args are how the harness starts the subprocess. The !!js tag reads a value from the environment at load time instead of writing a secret into the file.
Export the token and launch:
export GITHUB_TOKEN=ghp_your_token
pnpm dsh webAdding a remote MCP server (streamable HTTP)
For a hosted server, switch the transport to streamable-http and point it at the server's URL. As an example, this connects Composio, a hosted MCP server that fronts many apps behind one endpoint, using an API key in the header:
Note: You can use any other remote MCP server
- insert:
- id: mcp-composio
name: '@deepseek-ai/dsh-mcp-client'
config:
serverName: composio
transport: streamable-http
url: <https://connect.composio.dev/mcp>
headers:
x-consumer-api-key: !!js process.env.COMPOSIO_API_KEYThe shape is the same for any remote MCP server. Swap the url for the server you want and set whatever auth header it expects. Because the client passes headers only and does not run OAuth, complete any OAuth step ahead of time and put the resulting token in headers.
Export the key and launch:
export COMPOSIO_API_KEY=ck_your_key
pnpm dsh webIts tools then appear in the registry under the serverName you set, for example mcp__composio__GMAIL_SEND_EMAIL.
Verify it loaded
Restart dsh so it picks up the patch, then confirm the MCP block is live and the tools registered:
dsh web --dump-config | grep -A3 mcp
zstdcat ~/.dsh/sessions/*/*/session.jsonl.zstd | grep -E '"mcp__' | headYou should see the tools listed under their namespace. From there, just prompt the agent and it will call them like any other tool, with each call and result written to the session log.
Config reference
Field | Transport | Required | Purpose |
|---|---|---|---|
| both | yes |
|
| both | yes | Tool namespace, |
| stdio | yes | Executable to launch |
| stdio | no | Command arguments |
| stdio | no | Extra environment variables |
| stdio | no | Subprocess working directory |
| http | yes | MCP server address |
| http | no | Request headers (auth tokens) |
| both | no | Default 60000 |
| both | no | Default |
| both | no | Default |
Troubleshooting
If the block does not load, check that transport is exactly stdio or streamable-http and that a remote url has no trailing slash. If a stdio server never starts, run its command and args by hand to see the error, and set failOnStartupError: true while debugging so the harness surfaces it instead of continuing. If tools register but calls fail with auth errors, confirm the token in env or headers is actually set in the shell that launched dsh. If slower tools time out, raise toolCallTimeoutMs above the 60000ms default.
FAQ
Does the DeepSeek Harness support MCP natively?
Yes. It ships with an MCP client plugin (@deepseek-ai/dsh-mcp-client). Each mounted instance connects to one MCP server, over stdio for local servers or streamable HTTP for remote ones.
How do I add more than one MCP server?
Add another entry under insert: in the patch file, each with its own unique serverName. One plugin instance maps to one server.
Do I have to use a DeepSeek model?
No. dsh is model-agnostic. It runs DeepSeek V4 by default but also supports Anthropic, OpenAI, and custom OpenAI-compatible endpoints. MCP setup is identical whichever you choose.
How are MCP tools named?
As mcp__<serverName>__<toolName>. The serverName you set in the config becomes the namespace, which keeps tools from different servers from colliding.
What if a server needs OAuth?
The built-in client passes static headers only. Complete the OAuth flow separately, then pass the resulting token or key through the headers field.