Skip to main content
Glama
evilwk

DeepSeek Search MCP

by evilwk

deepseek-search-mcp

CI npm license

Unofficial. A community project. Not affiliated with, endorsed by, or supported by DeepSeek. It only calls the public Search / Fetch REST APIs with your own API key.

A TypeScript MCP server that wraps DeepSeek's Search and Fetch APIs into two read-only tools, so any MCP-capable agent can use DeepSeek's own search engine regardless of which model it runs on.

Tool

What it does

Upstream

search

Ranked web results (title / url / snippet / summary / date / authority); supports site:, lang:, after:, before:, quoted phrases

POST /v1/tools/search

fetch

One page as Markdown text, truncated to MAX_CONTENT_CHARS

POST /v1/tools/fetch

Verified end to end: 6/6 checks in scripts/smoke.ts (discovery, happy path, 429 retry, 401 surfacing, missing key, truncation), run against a mock API so no key or quota is needed.

Install

# from npm
npx -y @evilwk/deepseek-search-mcp

# straight from GitHub, no registry involved
npx -y github:evilwk/deepseek-search-mcp

# from source
git clone https://github.com/evilwk/deepseek-search-mcp
cd deepseek-search-mcp && pnpm install && pnpm build

Get a key at https://platform.deepseek.com/api_keys. Search and Fetch are billed per successful request (¥5 / 1000), so the account needs a positive balance — an HTTP 402 from the server means it ran out.

Related MCP server: websearch-deepseek

Run

export DEEPSEEK_API_KEY=sk-...
node dist/index.js          # stdio, for local agents
node dist/index.js --http   # Streamable HTTP, for sharing

A one-liner sanity check of the stdio handshake:

echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"t","version":"1"}}}' \
  | node dist/index.js

Client configuration

Each snippet below launches the server from a local build (node /abs/path/.../dist/index.js). If you installed from npm or GitHub instead, swap that for npx:

// from npm
{ "command": "npx", "args": ["-y", "@evilwk/deepseek-search-mcp"] }

// straight from GitHub
{ "command": "npx", "args": ["-y", "github:evilwk/deepseek-search-mcp"] }

Claude Code

claude mcp add deepseek-search -e DEEPSEEK_API_KEY=sk-... -- node /abs/path/deepseek-search-mcp/dist/index.js

Generic mcpServers block (Cursor, Claude Desktop, DSH, most hosts)

{
  "mcpServers": {
    "deepseek-search": {
      "command": "node",
      "args": ["/abs/path/deepseek-search-mcp/dist/index.js"],
      "env": { "DEEPSEEK_API_KEY": "sk-..." }
    }
  }
}

Codex CLI (~/.codex/config.toml)

[mcp_servers.deepseek-search]
command = "node"
args = ["/abs/path/deepseek-search-mcp/dist/index.js"]
env = { DEEPSEEK_API_KEY = "sk-..." }

Pi (~/.pi/agent/mcp.json, or .pi/mcp.json in a trusted project)

{
  "mcpServers": {
    "deepseek-search": {
      "command": "node",
      "args": ["/abs/path/deepseek-search-mcp/dist/index.js"],
      "env": { "DEEPSEEK_API_KEY": "${DEEPSEEK_API_KEY}" },
      "description": "DeepSeek 自研搜索引擎:网页搜索与单页 Markdown 抓取",
      "exposure": "direct",
      "timeout": 60
    }
  }
}

Pi's default exposure is codemode: the tools are registered but never declared to the model, so it would only reach them from codemode scripts or via tool_search. Two read-only tools belong at the top level — hence "exposure": "direct". Validate with pi mcp list, inspect with /mcp, and run /reload after editing the file outside a session.

OpenCode (~/.config/opencode/opencode.json, or project opencode.json)

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "deepseek-search": {
      "type": "local",
      "command": ["node", "/abs/path/deepseek-search-mcp/dist/index.js"],
      "enabled": true,
      "environment": { "DEEPSEEK_API_KEY": "{env:DEEPSEEK_API_KEY}" }
    }
  }
}

Note the shape differences from the Claude-style blocks above: command is an array, the env map is called environment, and interpolation is {env:NAME} rather than ${NAME}. For the HTTP mode below, use "type": "remote" with url + headers and set "oauth": false, otherwise OpenCode will try an OAuth flow the bearer token already replaces.

HTTP mode (shared / remote)

MCP_PORT=3000 MCP_AUTH_TOKEN=change-me DEEPSEEK_API_KEY=sk-... node dist/index.js --http
# -> http://127.0.0.1:3000/mcp   (Streamable HTTP, session-based)

The DeepSeek key stays server-side; callers only need MCP_AUTH_TOKEN as a bearer token. There is no OAuth flow here — if you expose this beyond localhost, put it behind a real gateway. It bills your account.

Environment variables

Var

Default

Notes

DEEPSEEK_API_KEY

—

Required for tool calls

DEEPSEEK_BASE_URL

https://api.deepseek.com

For testing against a mock

MAX_CONTENT_CHARS

40000

fetch truncation limit

MCP_PORT / MCP_HOST

3000 / 127.0.0.1

HTTP mode only

MCP_AUTH_TOKEN

unset

HTTP mode; unset = no auth, localhost only

Design notes

  • stdout is forbidden territory in stdio mode. All logging goes to stderr; a stray console.log corrupts the JSON-RPC stream and produces the classic "server disconnected" symptom.

  • Retries match the documented policy. 408 / 429 / 5xx get two retries with 500 ms → 1 s backoff (enough for the account-wide 5 QPS cap). 402 is a hard stop — retrying only burns quota.

  • Errors are model-readable. Failures come back as isError: true with an explicit "retry" / "do not retry" hint, so the agent does not hammer a permanent 4xx.

  • need_content defaults to false. summary (600–800 chars) answers most questions; full page bodies would inflate the context window by orders of magnitude.

  • readOnlyHint: true on both tools, so hosts can auto-approve them without a prompt.

  • The API client is transport-agnostic. src/deepseek.ts imports nothing from the MCP SDK — it can back a CLI or an HTTP tool just as easily as this server.

Layout

src/deepseek.ts   REST client: retry, timeouts, truncation, typed errors
src/server.ts     McpServer + tool registration (zod schemas, annotations)
src/index.ts      entry: stdio by default, --http for Streamable HTTP
src/http.ts       express 5 + session map + bearer auth
scripts/smoke.ts  mock-API end-to-end test, no real key needed

Skill or MCP?

Both are thin shells over src/deepseek.ts. Use MCP when the host cannot execute shell commands or needs typed tool schemas; use a Skill when the host has bash and you want to avoid a resident process and per-tool schema overhead. This repo is the MCP half.

Available Tools

2 tools
fetchDeepSeek Web FetchA
Read-only

Fetch one web page and return its title plus Markdown body. Use after search when a single result needs full-text reading. Long pages are truncated.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlYesAbsolute http(s) URL with a host, no embedded credentials.

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and openWorldHint, so safety and scope are covered structurally. The description adds genuinely useful behavior the agent cannot infer: the return shape (title + Markdown body) and the truncation of long pages, which affects how results should be trusted.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, zero redundancy, with the core capability front-loaded and the usage rule and truncation caveat following in order of importance. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter, read-only tool with no output schema, the description covers what the agent most needs: the return format and the truncation limit. Nothing required to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The single `url` parameter is 100% documented in the schema (absolute http(s), host required, no credentials), so the description is not obligated to compensate. 'One web page' reinforces the single-URL constraint but adds no syntax or format detail beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (fetch), a bounded resource (one web page), and the exact return payload (title plus Markdown body). An agent can distinguish this from `search` purely from the description without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly names the sibling and the condition that selects this tool: 'Use after `search` when a single result needs full-text reading.' It does not state the inverse case (e.g., don't use it to read many documents at once), but the sequencing guidance is clear enough to route correctly.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 2 tool updatesv0.1.1
    • First observedfetch
    • First observedsearch

TDQS

A4.5/5.0

Scored across 2 tools

Disambiguation5/5

Search and fetch target clearly different operations: search returns ranked results, while fetch retrieves a single page's full content. The descriptions reinforce the intended use sequence (search then fetch), leaving no meaningful ambiguity.

Naming Consistency5/5

Both tool names are simple lowercase verbs (search, fetch), following a consistent single-verb convention. There is no mixing of styles or noun phrasing.

Tool Count4/5

Two tools is slightly below the typical 3–15 range, but each is well-scoped and earns its place for a focused web search and retrieval server. The surface is minimal yet sufficient for the core workflow.

Completeness5/5

The server is read-only, and its domain lifecycle is search then fetch; both operations are present with useful filtering parameters. No obvious gaps exist for basic web search and page retrieval.

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    MCP server that exposes web_search and web_fetch tools, allowing LLM applications to search the web via DuckDuckGo and fetch page content as cleaned markdown.
    -
  • A
    license
    A
    quality
    C
    maintenance
    An MCP server that provides web search powered by DeepSeek's native search API, returning AI-generated answers with source links. Integrates with MCP-compatible clients like Claude Code and Cursor.
    1
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    Enables AI agents to run local deep-research workflows via a single MCP stdio server, combining web search, page extraction, query-aware distillation, and caching without cloud quotas. It exposes tools for deep research, search, and single or batch URL reading.
    6
    MIT