DeepSeek Search Everywhere MCP
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@DeepSeek Search Everywhere MCPsearch the web for the latest MCP server best practices and summarize them"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
DeepSeek Search Everywhere MCP
An MCP server that gives AI agents web search, page fetching and multi-source research through the official DeepSeek Search & Fetch API.
It is a thin, careful layer over that API: results are deduplicated, content is capped to a budget you set, repeated calls are served from an in-memory cache, and outgoing calls are paced by a local rate limiter. Six tools, stdio by default, optional bearer-protected streamable HTTP.
It is a standard MCP server, so it works with any MCP-compatible AI client or agent: Claude Code, Claude Desktop, Google Antigravity, Cursor, Windsurf, VS Code (GitHub Copilot), Gemini CLI, Codex CLI, Zed, opencode and others. Local clients launch it over stdio; remote or shared setups can connect over HTTP.
Not affiliated with DeepSeek. This is an independent, community-maintained project.
Features
Search with content in one request:
need_contentreturns page text inline, so there is usually no need for a second fetch per result.Batch fetch and research:
deepseek_fetch_manyfetches up to 10 URLs concurrently;deepseek_researchruns a search and fills the gaps by fetching pages whose search content is missing.Result hygiene: canonical-URL and title/site deduplication, per-result and total character budgets, Markdown unescaping.
Optional query rewrite to English through
deepseek-flash(thinking disabled), plus an explicitlangoperator for non-English queries.Cache and limiter: TTL + LRU cache with single-flight, per-endpoint token buckets,
refreshto bypass.Safe by default: static SSRF checks, secret redaction, no telemetry. See Security.
Related MCP server: Web Search MCP Server
Requirements
Python 3.11 or newer
A DeepSeek API key (
DEEPSEEK_API_KEY) from the DeepSeek platform
Install
The package is installed from GitHub; no registry release is required.
# Run without installing (uv)
uvx --from git+https://github.com/radoxtech/deepseek-search-everywhere-mcp deepseek-search-everywhere-mcp
# Or install with pip
pip install git+https://github.com/radoxtech/deepseek-search-everywhere-mcp.git
# Or from a source checkout
git clone https://github.com/radoxtech/deepseek-search-everywhere-mcp.git
cd deepseek-search-everywhere-mcp
pip install -e .The HTTP transport needs the http extra (it pulls in uvicorn):
pip install "deepseek-search-everywhere-mcp[http] @ git+https://github.com/radoxtech/deepseek-search-everywhere-mcp.git"
# from a checkout: pip install -e ".[http]"Check that the key and connectivity work (prints your balance, then exits):
export DEEPSEEK_API_KEY=sk-...
deepseek-search-everywhere-mcp --checkQuick start
All examples use stdio. Replace sk-... with your key.
The server is client-agnostic: the examples below cover common clients, and any other MCP client (Antigravity, Cursor, Windsurf, VS Code, Gemini CLI, Codex CLI, Zed, ...) works with the same command, arguments and environment variable in its own MCP configuration format.
Claude Code
claude mcp add deepseek-search-everywhere -e DEEPSEEK_API_KEY=sk-... -- \
uvx --from git+https://github.com/radoxtech/deepseek-search-everywhere-mcp deepseek-search-everywhere-mcpClaude Desktop
Edit claude_desktop_config.json (Settings, Developer, Edit Config):
{
"mcpServers": {
"deepseek-search-everywhere": {
"command": "uvx",
"args": [
"--from",
"git+https://github.com/radoxtech/deepseek-search-everywhere-mcp",
"deepseek-search-everywhere-mcp"
],
"env": { "DEEPSEEK_API_KEY": "sk-..." }
}
}
}opencode
In opencode.json:
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"deepseek-search-everywhere": {
"type": "local",
"command": [
"uvx",
"--from",
"git+https://github.com/radoxtech/deepseek-search-everywhere-mcp",
"deepseek-search-everywhere-mcp"
],
"environment": { "DEEPSEEK_API_KEY": "{env:DEEPSEEK_API_KEY}" },
"enabled": true
}
}
}Any stdio client
Most clients (including Antigravity, Cursor and Windsurf) use an mcpServers JSON block. Use the uvx
form from the Claude Desktop example, or, if the package is already installed, point the client at the
console script:
{
"mcpServers": {
"deepseek-search-everywhere": {
"command": "deepseek-search-everywhere-mcp",
"env": { "DEEPSEEK_API_KEY": "sk-..." }
}
}
}python -m deepseek_search_everywhere_mcp is equivalent.
Streamable HTTP
For clients that connect over HTTP. A bearer token is always required; the server refuses to start without one.
pip install -e ".[http]" # or the pip/GitHub form shown above
export DEEPSEEK_API_KEY=sk-...
export MCP_BEARER_TOKEN="$(python -c 'import secrets; print(secrets.token_urlsafe(32))')"
deepseek-search-everywhere-mcp --transport streamable-http # http://127.0.0.1:8000/mcpOptions: --host (default 127.0.0.1), --port (default 8000), --path (default /mcp). The token is read
from the environment only, never from the command line. The server runs stateless and answers with JSON
(no SSE streams). Client entry:
{
"mcpServers": {
"deepseek-search-everywhere": {
"url": "http://127.0.0.1:8000/mcp",
"headers": { "Authorization": "Bearer <MCP_BEARER_TOKEN>" }
}
}
}Claude Code: claude mcp add --transport http deepseek-search-everywhere http://127.0.0.1:8000/mcp --header "Authorization: Bearer $MCP_BEARER_TOKEN".
The server speaks plain HTTP; when binding beyond loopback, put TLS in front of it (see SECURITY.md).
Tools
Tool | Purpose | Parameters (defaults) |
| Search; titles, URLs, dates, authority, rerank scores, optional page content |
|
| Search with page content in one request; the recommended retrieval path |
|
| Fetch one known URL as Markdown |
|
| Fetch 1-10 URLs concurrently (up to 5 at a time) |
|
| One search with content, then fetch the sources whose content is missing or shorter than 200 characters (at most 5 fetches) |
|
| Account balance | none |
Notes on the parameters:
queryandquestionare limited to 128 characters and supportsite:,-site:,"phrase",lang:,after:andbefore:.ori_question(max 128 characters) is the natural-language question and improves ranking.langis an explicit language operator such ases,de,jaorpt-BR. Without it, results for non-English queries may be mixed-language; for named entities, compare with and without it.With
dedupe=True, searches ask the upstream for a few extra results (max(2, ceil(count * 0.5)), capped at 50) and trim tocountafter removing duplicates, so you still getcountresults when the index returns repeats. Withdedupe=Falseexactlycountare requested.rewrite=Truetranslates the query to English withdeepseek-flashbefore searching. It is skipped whenlangis set and falls back silently to the original query if the rewrite fails.deepseek_fetch_manyskips empty entries, fetches duplicate URLs (same canonical URL) once, keeps the input order, and reports a failing URL as an item withok: falseinstead of failing the batch. All fetches share a 120 s deadline; URLs still pending then are reported asdeadline_exceeded. Each page gets at mostmin(max_chars_per_url, max_total_chars // number of URLs)characters.deepseek_researchdoes no summarising and makes no model call: it returns sources for the caller to synthesise.
Example calls:
deepseek_search_and_read(query="rust async runtime comparison", count=5)
deepseek_web_search(query="gobierno de España presupuestos 2026", lang="es", need_content=False)
deepseek_fetch_many(urls=["https://example.com/a", "https://example.com/b"], max_total_chars=12000)
deepseek_research(question="how does HTTP/3 connection migration work", max_pages=4)Response envelope
Every tool returns a JSON object with ok.
Field | Where | Meaning |
| all |
|
| search, search-and-read, fetch; and per item in |
|
|
| how many responses in this call were served from the cache |
|
| upstream requests actually made (cache hits are free) |
| all success envelopes | human-readable remarks: dedupe counts, rewrite applied or failed, |
| failures |
|
|
|
|
|
| number of failed items or sources |
Search results carry title (the URL host without www. when the upstream title is blank), url, date, authority (0-4, -1 unknown), rerank_score, site, snippet,
and content/content_chars or summary where available. deepseek_fetch returns title, content,
content_chars, truncated.
Error codes
Code | Meaning |
| no key in |
| URL rejected locally: internal host, literal private/loopback address, or embedded credentials |
| malformed or oversized URL |
| invalid arguments |
| no local rate-limit token became available within the maximum wait |
| upstream body exceeded the cap (8 MiB search, 32 MiB fetch) |
| batch item not finished within the shared batch deadline |
| transport-level failures |
| unexpected exception while fetching one batch item |
other / | upstream API errors keep the code from DeepSeek (or |
Cache and rate limiting
The cache and the limiter live in the server process and are not shared between processes.
Search | Fetch | Query rewrite | |
Cache TTL | 5 min | 30 min | 24 h |
Entry limit | 128 | 128 | 1024 |
Size limit | 16 MiB | 32 MiB | 1 MiB |
Rate limit (sustained / burst) | 10 / s, 20 | 5 / s, 10 | not limited |
Only successful, non-empty responses are cached. Errors are never cached.
Identical concurrent calls share one upstream request (single-flight); only the one that made the request pays a limiter token, and none of them reports
cached: true.refresh=trueskips the cache read for that call and replaces the stored entry.dedupechanges the upstream request (the search over-fetches), sodedupe=trueanddedupe=falsecalls do not share a cache entry.Cache hits and rewrite calls cost no limiter token. One logical call takes one token, retries included.
If a token would take longer than 5 s to become available, the call fails immediately with
rate_limited_localrather than queueing indefinitely.Transient failures (HTTP 429 and gateway 5xx) are retried once.
DEEPSEEK_MCP_CACHE=0disables all caches.
Configuration
Variable | Required | Purpose |
| yes | DeepSeek platform key |
| no | API base URL (default |
| HTTP only | token clients must send as |
| no |
|
| no | stderr log level for the server, the MCP SDK and uvicorn: |
| no | path to a JSON file used as the key fallback (see Security) |
.env.example lists the same variables. The server does not read .env files itself; export the variables or
set them in your MCP client's env.
Security
Full policy and reporting instructions: SECURITY.md.
Static SSRF checks only. URLs are validated before the cache, the limiter or the network are touched: non-http(s) schemes, internal hostnames, literal private/loopback/link-local addresses and URLs with embedded credentials return
ssrf_blocked. The server does not resolve DNS, and DeepSeek performs the actual fetch, so this is not network isolation.Key handling. The key is sent only in the
Authorizationheader to the configured API base URL. Keys, bearer tokens and similar secrets are redacted from error messages and notes.HTTP transport requires the bearer token on every request (constant-time comparison, never logged).
No telemetry. The only outbound destination is the DeepSeek API.
Legacy opencode fallback. If
DEEPSEEK_API_KEYis unset, the server reads the key from~/.local/share/opencode/auth.json({"deepseek": {"key": "..."}}), or from the file named byDEEPSEEK_AUTH_JSON. This exists only for opencode users; prefer the environment variable.Tool inputs (queries, URLs) are sent to DeepSeek to do the work. Do not pass secrets in them.
Limitations
deepseek_fetchreturns HTTP 404 for PDFs and Reddit and times out on some sites. Usedeepseek_search_and_readwith the page title or asite:-scoped query instead.Fetch returns only title and content: no final URL, status code or publication date.
Search and fetch only. No site mapping or crawling, no asynchronous jobs, a single provider (DeepSeek).
The cache and rate limiter are per process; running several server processes multiplies the effective rate.
Local rate limits are conservative defaults and do not replace DeepSeek's own quotas.
The HTTP transport is plain HTTP, stateless and JSON-only; there are no OAuth and no SSE streams.
Development
git clone https://github.com/radoxtech/deepseek-search-everywhere-mcp.git
cd deepseek-search-everywhere-mcp
python -m venv .venv && . .venv/bin/activate
pip install -e ".[test,lint,http]" build twine
pytest -q # offline suite; no network, no key needed
ruff check . # lint
python -m build # sdist + wheel in dist/
python -m twine check dist/* # validate package metadataThe offline tests clear DEEPSEEK_* variables and point the key fallback at a nonexistent file, so they cannot
reach the network. CI runs lint, tests and build on Python 3.11, 3.12 and 3.13.
Live tests
The live suite calls the real DeepSeek API end to end and uses deepseek-flash as an LLM judge to grade whether
results are relevant and answer the question. It is excluded from the default run, skips itself without a key,
and a full run costs well under $0.01.
cp .env.example .env # then put your key in DEEPSEEK_API_KEY=
set -a && . ./.env && set +a # export the variables; tests do not read .env themselves
pytest -m liveJudge scores and reasons are printed after the run. .env is git-ignored; never commit it.
Releasing
Releases are published by .github/workflows/release.yml when a v* tag is pushed. The workflow builds once,
checks that the tag equals the version in pyproject.toml and server.json, runs twine check and a clean-wheel
smoke test, publishes to PyPI through Trusted Publishing (OIDC, no
tokens), creates a GitHub Release with the artifacts and then updates the MCP Registry. Running the workflow
manually publishes to TestPyPI only.
# bump the version in pyproject.toml and server.json (tests/test_version_sync.py checks they agree), commit, then:
git tag v0.2.1 && git push origin v0.2.1
bash scripts/smoke_package.sh # optional local check: build, install into a clean venv, run the CLIPublishing to the MCP Registry manually
server.json describes the PyPI package for the MCP Registry. The
README carries an mcp-name comment that the registry uses to verify package ownership. The release workflow
does this automatically; to publish by hand:
python scripts/validate_server_json.py # structural checks; also runs `mcp-publisher validate` if installed
mcp-publisher login github # the io.github.radoxtech namespace requires GitHub authentication
mcp-publisher publishBump the version in pyproject.toml and server.json together and publish to PyPI first; tests/test_version_sync.py
fails when the versions drift apart.
Changelog
See CHANGELOG.md for release notes.
License
MIT. Not affiliated with DeepSeek.
Available Tools
6 toolsdeepseek_balanceA
Check the DeepSeek account balance (granted and topped-up, in CNY and USD).
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the burden. It does disclose the currency units and the split between granted and topped-up balance, which is useful. However, it does not state whether authentication/API key is required or whether the call is read-only (implied but not declared).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single sentence, front-loaded with the verb and resource, with the currency/breakdown detail trailing. No waste.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained. For a zero-parameter read-only balance check, the description gives all an agent needs to select and invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There are zero parameters, so the baseline is 4 by rule. The description adds nothing parameter-related, and nothing is needed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (check) and resource (DeepSeek account balance) and even names the returned breakdown (granted vs topped-up, CNY and USD). Clearly distinguishable from all siblings, which are search/fetch/research tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is strongly implied: this is the only account/balance tool among search and fetch siblings, so an agent can infer when to call it. But there is no explicit when-to-use/when-not-to-use statement or named alternative.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
deepseek_fetchA
Fetch one known URL and return its title and Markdown content.
Caveat measured on 2026-10-20: this endpoint returns HTTP 404 for PDFs and for Reddit, and times out on some sites. When the URL is a document or a blocked site, call deepseek_search_and_read with the page title or a site:-scoped query instead.
The response contains only title and content — no final URL, status code or publication date, so keep the provenance on your side.
Pages are cached in memory for about half an hour and identical concurrent calls share one upstream request; the envelope's cached flag tells which happened. Calls are rate-limited locally per endpoint: if no slot frees up within a short wait the error code is rate_limited_local. A response larger than 32 MiB fails with response_too_large.
URLs that point at internal hosts or literal private addresses, or that embed credentials (user:pass@host), are rejected locally with ssrf_blocked before any request is made.
Args: url: Absolute http(s) URL, max 8192 characters. clean: Remove DeepSeek's spurious Markdown escaping (# at line start, , , etc.). max_chars: Content cap, applied after cleaning. refresh: Bypass the response cache and fetch the page again (the envelope's cached flag says whether the page came from the cache).
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | ||
| clean | No | ||
| refresh | No | ||
| max_chars | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does so: known 404 and timeout cases, ~30 minute in-memory cache with concurrent-call dedupe, a local per-endpoint rate limit with the rate_limited_local error code, a 32 MiB response_too_large cap, and ssrf_blocked rejection of internal hosts, private addresses and credentialed URLs before any request. It also warns that the return payload omits final URL, status and date, telling the agent to preserve provenance itself.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose and return shape, then caveat, then cache/limit behavior, then Args. Dense but zero filler: every sentence either routes the agent or prevents a specific failure mode.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers the whole call lifecycle for a four-parameter fetch tool: eligibility (SSRF, URL length), known failure modes with error codes, caching semantics, and the limits of the returned payload. Even though an output schema exists, the note about missing provenance fields is advisory context the schema would not supply.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must compensate and it does: url is bounded ('absolute http(s) URL, max 8192 characters'), clean explains the specific DeepSeek escaping artifacts it strips, max_chars is pinned to 'applied after cleaning', and refresh is tied to the cache flag in the envelope. Only minor gap is that defaults for clean/refresh/max_chars are left to the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb and scope ('Fetch one known URL') plus what comes back ('title and Markdown content'), which cleanly separates it from deepseek_web_search, deepseek_search_and_read and deepseek_fetch_many. The single-URL scope is stated explicitly, so an agent can pick this tool without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit when-not rule with the failure conditions spelled out (PDFs and Reddit return 404, some sites time out) and names the exact alternative plus the query shape to use there ('deepseek_search_and_read with the page title or a site:-scoped query'). Routing is fully determined, not inferred.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
deepseek_fetch_manyA
Fetch up to 10 known URLs concurrently and return each page's title and Markdown content.
Each URL goes through the same validation, cache, rate limiter and SSRF checks as deepseek_fetch. Empty entries are skipped and duplicates (same canonical URL) are fetched once. Results keep the input order; a failing URL yields an item with ok=false and an error instead of failing the batch. All fetches share one deadline (120 s by default); URLs still pending then are cancelled and reported with error code deadline_exceeded.
Each page gets min(max_chars_per_url, max_total_chars // count) characters and the total content never exceeds max_total_chars; a note says when any content was truncated. The envelope reports count (unique URLs), requests_used (upstream fetches attempted), cached_count (items served from the cache), failed_count (items with ok=false), partial (true when any item failed), results and notes. The top-level ok only says the batch ran; check partial or each item's ok for per-URL failures. Each result carries its own cached flag.
Args: urls: 1-10 absolute http(s) URLs, max 8192 characters each. max_chars_per_url: Content cap per page, applied after cleaning. max_total_chars: Total content budget across all pages. clean: Remove DeepSeek's spurious Markdown escaping (# at line start, , etc.). refresh: Bypass the response cache and fetch every page again.
| Name | Required | Description | Default |
|---|---|---|---|
| urls | Yes | ||
| clean | No | ||
| refresh | No | ||
| max_total_chars | No | ||
| max_chars_per_url | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does so thoroughly: shared 120s deadline, cancellation with deadline_exceeded, per-URL failure isolation, duplicate/empty handling, cache interaction, and the top-level ok vs partial distinction. That last point in particular prevents a real misread of batch success.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with capability, then behavior, then Args – a sound structure with little waste. The paragraph enumerating every envelope field is somewhat redundant given an output schema exists, which is the only thing keeping this below a 5.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 5-parameter concurrent batch tool with no annotations, this covers the edge cases an agent must reason about: partial failure, deadline truncation, truncation notes, and per-item cache flags. Nothing needed to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, yet the Args block gives meaning to all five parameters: the 1-10 / 8192-char URL bounds, the purpose of max_chars_per_url and max_total_chars, and what clean and refresh actually change. The allocation formula min(max_chars_per_url, max_total_chars // count) is semantics the schema cannot express at all.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb, resource, and cardinality bound ('Fetch up to 10 known URLs concurrently') plus the return shape (page title and Markdown content). The 'known URLs' phrasing and the explicit reference to deepseek_fetch's validation pipeline make the boundary with the single-URL sibling clear.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Known URLs' implicitly steers the agent away from this tool for discovery (deepseek_web_search/deepseek_research), and the deepseek_fetch reference establishes the shared pipeline. However, it never states explicitly when to pick this over calling deepseek_fetch repeatedly, leaving that inference to the reader.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
deepseek_researchA
Gather source material for a question: one search with page content, then fetch the gaps.
Runs a single search with need_content=True (no query rewrite, no model call, no summary). Results whose content is missing or shorter than 200 characters and whose URL passes validation are fetched directly with deepseek_fetch_many (at most 5 per call); a fetched page replaces the search content of that source. A URL that fails validation (for example an internal address) is not fetched. Failed or rejected sources keep the search content and set the source's error; the call still succeeds with partial=true.
Each source has id, title, url, authority, rerank_score, content, chars, origin ('search' or 'fetch'), error (null or {code, message}) and cached (whether its content came from the cache). Content is capped at per_page_chars per source and total_chars overall, in source order; a note says when any content was truncated. requests_used counts upstream requests made (the search plus each fetch; cache hits are free) and cached_count counts responses served from the cache. failed_count counts sources whose error is set and partial is true when it is non-zero. Synthesis is left to the caller.
Args: question: Search query, max 128 characters. Supports site:, -site:, "phrase", lang:. max_pages: Number of search results to use, 1-50 (default 5). per_page_chars: Content cap per source. total_chars: Total content budget across all sources. refresh: Bypass the response caches for the search and the fetches.
| Name | Required | Description | Default |
|---|---|---|---|
| refresh | No | ||
| question | Yes | ||
| max_pages | No | ||
| total_chars | No | ||
| per_page_chars | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden and does so: it explains the fallback fetch path, the 200-character/URL-validation triggers, the 5-fetch cap, that failures keep search content and set error while the call still returns partial=true, cache-hit accounting in requests_used/cached_count, and truncation notes. Nothing important about failure modes or side effects is left implicit.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
It is front-loaded with the core action and organized into behavioral paragraphs followed by args, which is good. However, the sentence enumerating every source field (id, title, url, authority, rerank_score, content, chars, origin, error, cached) largely restates the output schema and adds bulk without new decision-relevant information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 5-parameter tool with a multi-stage search-and-fetch pipeline and partial-failure semantics, the description covers trigger conditions, budget capping, caching, error propagation, and counting fields. Combined with an existing output schema, an agent has everything needed to call it correctly and interpret the result.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate, and it largely does: question gets a 128-character limit plus supported operators (site:, -site:, "phrase", lang:), max_pages gets the 1-50 range and default 5, and refresh is defined as bypassing caches for both search and fetches. per_page_chars and total_chars are only described as caps without ranges, which is the remaining gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence states a specific verb and resource plus the internal workflow: 'Gather source material for a question: one search with page content, then fetch the gaps.' It also disambiguates from siblings by declaring 'no query rewrite, no model call, no summary', which separates it from the search-and-read style tools listed alongside it.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Synthesis is left to the caller' establishes the boundary of responsibility, and the search-then-fetch-gaps framing tells an agent when this pipeline is the right shape. It stops short of explicitly naming deepseek_web_search or deepseek_search_and_read as alternatives with selection criteria, so no exclusion rules are given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
deepseek_search_and_readA
Search and return full page content in one request — the recommended retrieval path.
This is search with need_content=True. Measured on 14 benchmark questions it returned content for PDFs and Reddit threads where deepseek_fetch returned HTTP 404, in about 0.7s per call.
Responses are cached in memory for a few minutes and identical concurrent calls share one upstream request; the envelope's cached flag tells which happened. Calls are rate-limited locally per endpoint: if no slot frees up within a short wait the error code is rate_limited_local. A response larger than 8 MiB fails with response_too_large.
Args: query: Search query, max 128 characters. count: Number of results to return, 1-50 (default 5). With dedupe on, extras are requested upstream so duplicates do not leave you short. ori_question: Original natural-language question, max 128 characters. lang: Language operator, e.g. 'es', 'de' or 'ja'. For non-English queries set it to the appropriate code; without it results may be mixed-language. For named entities test with and without the operator. max_chars_per_result: Content cap per result. max_total_chars: Total content budget across all results. dedupe: Collapse near-duplicate results (same canonical URL or same title+site), default on. rewrite: Rewrite the query via deepseek-flash before searching, default off. Skipped when lang is set; falls back silently to the original query on failure. refresh: Bypass the response cache and query upstream again (the envelope's cached flag says whether the results came from the cache).
| Name | Required | Description | Default |
|---|---|---|---|
| lang | No | ||
| count | No | ||
| query | Yes | ||
| dedupe | No | ||
| refresh | No | ||
| rewrite | No | ||
| ori_question | No | ||
| max_total_chars | No | ||
| max_chars_per_result | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does so well: in-memory caching window, concurrent-call coalescing, the `cached` envelope flag, per-endpoint local rate limiting with the specific `rate_limited_local` error, and an 8 MiB `response_too_large` ceiling. These are exactly the runtime traits an agent needs to retry or budget correctly.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The recommendation and the one-request framing are front-loaded, followed by operational behavior, then an Args block — a sensible order. The benchmark anecdote (14 questions, ~0.7s/call) is slightly padded but does real work justifying the recommendation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained, and the description still flags the `cached` envelope field. For a 9-parameter retrieval tool with no annotations, the mix of routing guidance, failure modes, and per-argument behavior leaves nothing an agent needs missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must compensate — and it documents all nine parameters with behavior the schema cannot express: count interacts with dedupe (extras requested upstream), rewrite is skipped when lang is set and falls back silently, refresh bypasses cache, lang is a language operator with a test-with-and-without heuristic for named entities, plus the two char budgets.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opening line states a specific verb and resource plus the key differentiator: search *and* full page content in a single request. It also equates itself to a known primitive ('search with need_content=True') and names the sibling it outperforms (deepseek_fetch), so an agent can place it immediately.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Calls itself 'the recommended retrieval path' and gives concrete evidence for preferring it over deepseek_fetch (PDFs/Reddit where fetch returned 404). It does not, however, state when to prefer deepseek_web_search (metadata-only) or deepseek_fetch_many, which are the closest alternatives in the sibling list.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
deepseek_web_searchA
Search the web with DeepSeek's index. Returns titles, URLs, dates, authority and rerank scores.
Use this for discovery and ranking. Set need_content=True to get full page text inline in the same call (billed as one request, no per-page charge) — this is usually cheaper and more reliable than calling deepseek_fetch afterwards.
For non-English queries set lang to the appropriate code (e.g. 'es', 'de', 'ja'). Without it results may be mixed-language; for named entities test with and without the operator. Each result carries date (RFC 3339) and authority (0-4, -1 unknown).
Responses are cached in memory for a few minutes and identical concurrent calls share one upstream request; the envelope's cached flag tells which happened. Calls are rate-limited locally per endpoint: if no slot frees up within a short wait the error code is rate_limited_local. A response larger than 8 MiB fails with response_too_large.
Args: query: Search query, max 128 characters. Supports site:, -site:, "phrase", lang:, after:, before:. count: Number of results to return, 1-50 (default 10). With dedupe on, extras are requested upstream so duplicates do not leave you short. ori_question: Original natural-language question, max 128 characters; improves ranking. need_content: Return full page text per result (recommended for reading). lang: Language operator, e.g. 'es', 'de' or 'ja'. For non-English queries set it to the appropriate code; without it results may be mixed-language. For named entities test with and without the operator. max_chars_per_result: Content cap per result when need_content is set. max_total_chars: Total content budget across all results. dedupe: Collapse near-duplicate results (same canonical URL or same title+site), default on. rewrite: Rewrite the query via deepseek-flash before searching, default off. Skipped when lang is set; falls back silently to the original query on failure. refresh: Bypass the response cache and query upstream again (the envelope's cached flag says whether the results came from the cache).
| Name | Required | Description | Default |
|---|---|---|---|
| lang | No | ||
| count | No | ||
| query | Yes | ||
| dedupe | No | ||
| refresh | No | ||
| rewrite | No | ||
| need_content | No | ||
| ori_question | No | ||
| max_total_chars | No | ||
| max_chars_per_result | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, and the description carries the full load well: memory caching with a cached flag, deduped concurrent request sharing, local per-endpoint rate limiting with the rate_limited_local error code, an 8 MiB response_too_large failure mode, and rewrite being skipped when lang is set with silent fallback. These are exactly the operational traits an agent needs before invoking.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The prose preamble is front-loaded and dense with useful content, but the trailing Args block restates the lang guidance almost verbatim ("For non-English queries set it to the appropriate code; without it results may be mixed-language. For named entities test with and without the operator"), which appears twice. Redundant rather than bloated, so minor deduction only.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 10-parameter search tool with no annotations, the definition covers invocation semantics, cost/alternative tradeoffs, failure codes, and even result field meanings (date RFC 3339, authority 0-4 with -1 unknown). An output schema exists so return-value structure needn't be spelled out, and nothing needed to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate, and it does: every one of the 10 parameters is documented with bounds (query max 128 chars, count 1-50 default 10), supported query operators (site:, -site:, "phrase", lang:, after:, before:), and defaults (dedupe on, rewrite off, refresh false). It also explains secondary effects, e.g. that dedupe causes extras to be requested upstream so duplicates don't leave you short.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb+resource ("Search the web with DeepSeek's index") and immediately states what comes back (titles, URLs, dates, authority and rerank scores). It also distinguishes itself from the sibling deepseek_fetch by positioning this tool as the discovery/ranking entry point, so an agent can pick it without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says what to use it for ("discovery and ranking") and names the alternative plus the decision rule: set need_content=True to avoid "calling deepseek_fetch afterwards" because it is "cheaper and more reliable." It also gives conditional guidance for lang (non-English queries) and for named entities (test with and without the operator).
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.
6 tool updates
v0.2.0- First observed
deepseek_balance - First observed
deepseek_fetch - First observed
deepseek_fetch_many - First observed
deepseek_research - First observed
deepseek_search_and_read - First observed
deepseek_web_search
TDQS
Scored across 6 tools
Three tools (deepseek_web_search with need_content=True, deepseek_search_and_read, and deepseek_research) all perform search-plus-content retrieval and differ mainly by preset flags and internal fallback behavior rather than by distinct purpose. The descriptions do attempt to steer selection ('recommended retrieval path', 'search with need_content=True'), which mitigates but does not eliminate the overlap. Fetch vs fetch_many is clearly distinct.
All names use a uniform deepseek_ prefix with snake_case and are mostly verb- or verb_noun-shaped (web_search, search_and_read, fetch, fetch_many, research). deepseek_balance is noun-only, a minor deviation from the otherwise predictable pattern.
Six tools is well-scoped for a search-and-retrieval service, covering discovery, single fetch, batch fetch, a composite research call, and account balance. No bloat; the only questionable inclusion is search_and_read, which duplicates an existing flag.
The retrieval lifecycle is well covered: search, rank, read content inline, fan out over known URLs, and a gap-filling composite. Missing pieces are minor conveniences (e.g. a way to inspect rate-limit status or paginate beyond the 50-result cap), and documented caveats on deepseek_fetch give agents a workaround.
Maintenance
Related MCP Connectors
Search, scrape, and crawl the web for AI agents. Batch scraping and answers with citations.
Web search and page fetch for AI agents. Results come from a shared cache; cached calls cost less.
Agent-native search engine with live web research optimized for AI agents.
LLM-ready web search + instant answers + URL-to-clean-text fetch for agents and RAG.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables AI agents to perform web searches, extract webpage content, and conduct end-to-end search-and-extract operations using multiple search providers and content extraction methods.-
- FlicenseNot gradedqualityDmaintenanceEnables AI agents to search the web and extract content using multiple search providers, with caching, retry logic, and options for JavaScript-heavy page rendering.-
- AlicenseAqualityAmaintenanceEnables AI agents to search and fetch high-quality information from multiple sources, including general web APIs, Wikipedia, arXiv, Hacker News, Stack Exchange, and Crossref, with optional pro-mode deep research and clean markdown page extraction.10MIT
- AlicenseAqualityAmaintenanceEnables AI agents to perform web searches, fetch and extract page content, and crawl sites with caching, rate limiting, and robots.txt compliance, all without needing API keys.11195 PyPI1MIT