deepseek-mcp-server
README.md
# deepseek-mcp-server
A complete, unrestricted [Model Context Protocol](https://modelcontextprotocol.io) server for the
DeepSeek API. It exposes DeepSeek's whole surface — chat, reasoning, fill-in-the-middle, prefix
completion, function calling, JSON mode, logprobs, streaming — to any MCP client: VS Code,
Claude Code, Claude Desktop, Cursor, Windsurf, or your own.
- **12 tools**, **7 prompt templates**, **5 resources**
- **No client-side caps.** No token ceiling, no output truncation, no path allowlist by default.
Every limit is an opt-in environment variable.
- **A raw passthrough tool**, so endpoints and parameters added to the DeepSeek API after this
server was written are reachable without a code change.
- **One direct dependency** (`@modelcontextprotocol/sdk` — which brings its own transitive tree,
about 95 packages in total) and no build step.
- MIT licensed.
---
## Install
```bash
git clone https://github.com/sengarcia32-ux/deepseek-mcp-server.git
cd deepseek-mcp-server
npm install
```
Register it with every MCP client on the machine:
```bash
node install/register.mjs --apply
```
On Windows you can run the whole thing in one step:
```powershell
powershell -ExecutionPolicy Bypass -File install\install.ps1
```
Then add your API key — grab one at <https://platform.deepseek.com/api_keys>:
```powershell
powershell -ExecutionPolicy Bypass -File install\set-key.ps1
```
or edit `~/.deepseek-mcp/config.json` by hand:
```json
{ "apiKey": "sk-your-key-here" }
```
Verify everything end to end:
```bash
node bin/deepseek-mcp.js --doctor
```
Restart VS Code and any Claude client so they pick up the new server.
### What `register.mjs` touches
It merges into existing config and backs up every file it writes (`*.bak-<timestamp>`).
| Client | File | Key added |
|---|---|---|
| VS Code / Insiders / VSCodium | `<user>/mcp.json` | `servers.deepseek` |
| VS Code (trust) | `<user>/settings.json` | `chat.mcp.access`, `chat.mcp.autostart`, `chat.mcp.discovery.enabled`, `chat.tools.autoApprove`, `chat.permissions.default` |
| Claude Code | `~/.claude.json` | `mcpServers.deepseek` |
| Claude Code (trust) | `~/.claude/settings.json` | `permissions.allow += mcp__deepseek`, `enableAllProjectMcpServers` |
| Claude Desktop | `claude_desktop_config.json` | `mcpServers.deepseek` |
| Cursor | `~/.cursor/mcp.json` | `mcpServers.deepseek` |
| Windsurf | `~/.codeium/windsurf/mcp_config.json` | `mcpServers.deepseek` |
Clients that aren't installed are skipped. Remove it all again with
`node install/register.mjs --apply --remove`.
No API key is written into any client config. Every client points at the same single source of
truth, `~/.deepseek-mcp/config.json`, so the key lives in exactly one file.
---
## Tools
| Tool | What it's for |
|---|---|
| `deepseek_chat` | `deepseek-chat` (V3). Fast general-purpose work. Full sampling controls, JSON mode, function calling, logprobs, streaming, sessions. |
| `deepseek_reason` | `deepseek-reasoner` (R1 thinking mode). Returns the chain of thought and the answer separately. For hard maths, logic, debugging, planning. |
| `deepseek_code` | Task-oriented coding: `generate`, `review`, `refactor`, `explain`, `test`, `debug`, `document`, `optimize`, `convert`. Takes inline code and/or file paths. Routes deep tasks to the reasoner. |
| `deepseek_fim` | Fill-in-the-middle. Give code before the cursor as `prompt` and after it as `suffix`; the model writes the middle. No commentary. |
| `deepseek_prefix` | Force the reply to begin with text you supply, then continue. Pins output format, resumes truncated answers. |
| `deepseek_analyze_files` | Read files, directories or globs and ask about them. Walks recursively, skips `node_modules`, `.git`, build output and binaries. `list_only` previews what would be sent. |
| `deepseek_session` | Manage multi-turn conversations: `list`, `get`, `clear`, `delete`, `set_system`, `import`. |
| `deepseek_models` | List model ids available to your key. |
| `deepseek_balance` | Remaining account credit per currency. |
| `deepseek_count_tokens` | Estimate token count from DeepSeek's published character ratios. |
| `deepseek_status` | Resolved config, request statistics, and an optional live connection test. Run this first when something breaks. |
| `deepseek_raw_request` | Any endpoint, any method, any body, raw JSON back. Auth, retries and timeouts still handled for you. |
### Multi-turn sessions
Pass the same `session_id` to any chat tool and prior turns are prepended automatically:
```jsonc
{ "prompt": "What is a monad?", "session_id": "fp-lesson" }
{ "prompt": "Now show me one in TypeScript.", "session_id": "fp-lesson" }
```
Sessions persist to `~/.deepseek-mcp/sessions/`. Reasoning traces are deliberately **not** fed back
on later turns, which is what the DeepSeek API requires.
### The `extra` escape hatch
Every chat tool accepts an `extra` object that is merged into the request body **last**, so it
overrides anything the server set:
```jsonc
{ "prompt": "hi", "extra": { "seed": 42, "some_new_param": true } }
```
---
## Prompts
`deepseek-code-review`, `deepseek-debug`, `deepseek-explain`, `deepseek-write-tests`,
`deepseek-optimize`, `deepseek-reason`, `deepseek-translate`.
In VS Code these appear as `/` commands in the chat input once the server is running.
## Resources
`deepseek://config`, `deepseek://models`, `deepseek://sessions`, `deepseek://stats`,
`deepseek://log`.
---
## Configuration
First match wins: **process environment** → **`<package>/.env`** → **`~/.deepseek-mcp/config.json`**
→ built-in default.
| Variable | JSON key | Default | Notes |
|---|---|---|---|
| `DEEPSEEK_API_KEY` | `apiKey` | — | Required. |
| `DEEPSEEK_BASE_URL` | `baseUrl` | `https://api.deepseek.com` | Point at any OpenAI-compatible endpoint. |
| `DEEPSEEK_BETA_BASE_URL` | `betaBaseUrl` | `<baseUrl>/beta` | Used by FIM and prefix completion. |
| `DEEPSEEK_CHAT_MODEL` | `chatModel` | `deepseek-chat` | |
| `DEEPSEEK_REASONER_MODEL` | `reasonerModel` | `deepseek-reasoner` | |
| `DEEPSEEK_TIMEOUT_MS` | `timeoutMs` | `900000` | 15 minutes, for long reasoning runs. |
| `DEEPSEEK_MAX_RETRIES` | `maxRetries` | `4` | Exponential backoff, honours `Retry-After`. |
| `DEEPSEEK_MAX_TOKENS` | `maxTokensDefault` | `0` | `0` means send no `max_tokens` and let the API use its own maximum. |
| `DEEPSEEK_MAX_OUTPUT_CHARS` | `maxOutputChars` | `0` | `0` means never truncate a tool result. |
| `DEEPSEEK_ALLOW_FS` | `allowFs` | `true` | Set `0` to block all local file reads. |
| `DEEPSEEK_FS_ROOTS` | `fsRoots` | *(empty)* | Empty means unrestricted. Set to confine reads to specific directories. |
| `DEEPSEEK_MAX_BYTES_PER_FILE` | `maxBytesPerFile` | `2000000` | `0` for unlimited. |
| `DEEPSEEK_MAX_BYTES_TOTAL` | `maxBytesTotal` | `8000000` | `0` for unlimited. |
| `DEEPSEEK_PERSIST_SESSIONS` | `persistSessions` | `true` | |
| `DEEPSEEK_SESSION_MAX_MESSAGES` | `sessionMaxMessages` | `200` | Oldest turns are dropped past this. |
| `DEEPSEEK_LOG_LEVEL` | `logLevel` | `info` | `silent`…`trace`. |
| `DEEPSEEK_LOG_FILE` | `logFile` | `~/.deepseek-mcp/deepseek-mcp.log` | Rotates at 5 MB. |
| `DEEPSEEK_LOG_TO_FILE` | `logToFile` | `true` | |
`config.json` also takes `extraHeaders` and `defaultBody` objects, applied to every request.
### Running against a different provider
`baseUrl` is not validated, so the server works against anything speaking the OpenAI chat
completions shape — DeepSeek, a local Ollama or vLLM instance, OpenRouter, a gateway of your own:
```json
{ "baseUrl": "http://localhost:11434/v1", "apiKey": "ollama", "chatModel": "deepseek-r1:14b" }
```
---
## CLI
```bash
node bin/deepseek-mcp.js # run the MCP server on stdio (what clients do)
node bin/deepseek-mcp.js --doctor # print config and test the connection
node bin/deepseek-mcp.js --list-tools
node bin/deepseek-mcp.js --version
```
## Tests
```bash
npm test
```
Launches the real server over stdio with an MCP client and runs 27 protocol-level checks. No API
key needed — the key-dependent path is asserted to fail with actionable guidance instead.
---
## A note on "unrestricted"
The defaults here are permissive on purpose: no token caps, no output truncation, and
`deepseek_analyze_files` can read anywhere the Node process can. That means **an MCP client driving
this server can send the contents of local files to DeepSeek's API**. That is the point of the tool,
but it is worth knowing.
If you want it narrower, the knobs are all there:
```json
{
"allowFs": true,
"fsRoots": ["C:\\Users\\you\\projects"],
"maxBytesTotal": 1000000
}
```
Or `"allowFs": false` to turn local file reads off entirely. Prompts, file contents and responses
are not logged at `info` level; raise to `debug` or `trace` only when you need it, and note that
`trace` puts request bodies in the log file.
## License
MIT. See [LICENSE](LICENSE).
Not affiliated with or endorsed by DeepSeek or Anthropic.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues