DeepSeek Search Everywhere MCP
This MCP server lets AI agents search the web, fetch pages, gather multi-source research, run deep cited research, and extract structured data via DeepSeek.
Search the web with inline page text or snippets, ranking, date/domain/language filters, deduplication, optional query rewrite, and cache bypass.
Fetch a URL as Markdown with character budgets, optional relevant snippets, sectional reading, cleaning, and boilerplate stripping.
Fetch up to 10 URLs concurrently, preserving input order, deduplicating URLs, sharing a deadline, and reporting per-item failures.
Gather research sources in a single pass: one search plus automatic fetches for pages with missing content; no iteration or summarization.
Run deep research by decomposing a topic into subqueries, gathering sources, and synthesizing a cited briefing report.
Extract structured JSON from a page using requested fields, a JSON schema, or an instruction.
Check account balance and session telemetry, including queries, cache hit rate, and estimated cost.
Operate over stdio or optional bearer-protected streamable HTTP, with in-memory caching, local rate limiting, SSRF checks, and secret redaction.
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. Seven 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_researchgathers sources in a single pass: one search, then direct fetches for pages whose search content is missing. It does not iterate or summarise.Deep research and structured extraction:
deepseek_deep_researchdecomposes topics into subqueries and synthesizes cited briefing reports;deepseek_extractextracts validated structured JSON matching schemas or fields.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 server is published on PyPI and listed in the
official MCP Registry
as io.github.radoxtech/deepseek-search-everywhere-mcp.
# Run without installing (uv)
uvx deepseek-search-everywhere-mcp
# Or install with pip
pip install deepseek-search-everywhere-mcpThe HTTP transport needs the http extra (it pulls in uvicorn):
pip install "deepseek-search-everywhere-mcp[http]"To run the latest unreleased code from main, or from a source checkout:
uvx --from git+https://github.com/radoxtech/deepseek-search-everywhere-mcp deepseek-search-everywhere-mcp
git clone https://github.com/radoxtech/deepseek-search-everywhere-mcp.git
cd deepseek-search-everywhere-mcp
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 deepseek-search-everywhere-mcpClaude Desktop
Edit claude_desktop_config.json (Settings, Developer, Edit Config):
{
"mcpServers": {
"deepseek-search-everywhere": {
"command": "uvx",
"args": ["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", "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 "deepseek-search-everywhere-mcp[http]"
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).
Docker
An official container image is available on GitHub Container Registry (ghcr.io):
docker pull ghcr.io/radoxtech/deepseek-search-everywhere-mcp:latestStdio mode (Claude Desktop, Cursor, local IDEs):
{
"mcpServers": {
"deepseek-search-everywhere": {
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "DEEPSEEK_API_KEY=sk-...",
"ghcr.io/radoxtech/deepseek-search-everywhere-mcp:latest"
]
}
}
}Remote HTTP hosting (Docker Compose, VPS, n8n, Dify, cloud agents):
docker run -d --name deepseek-mcp -p 8000:8000 \
-e DEEPSEEK_API_KEY="sk-..." \
-e MCP_BEARER_TOKEN="your-secret-token" \
ghcr.io/radoxtech/deepseek-search-everywhere-mcp:latest \
--transport streamable-http --host 0.0.0.0 --port 8000The container runs as an unprivileged non-root user (UID 10001) with dependencies isolated from the host.
Tools
Tool | Purpose | Parameters (defaults) |
| Search the web; returns inline page text (default) or snippets and metadata |
|
| Fetch one known URL as Markdown (supports lexical snippet extraction and sectional reading) |
|
| Fetch 1-10 URLs concurrently (up to 5 at a time) |
|
| Single-pass source gathering: search with content and auto-fetch stub pages (< 200 chars). No iteration, no summary |
|
| Multi-angle research on a topic; decomposes subqueries, gathers sources, and synthesizes a cited report |
|
| Extract structured JSON from a web page conforming to target fields or a schema |
|
| Account balance and session metrics (upstream queries, cache hits, estimated cost) | 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.after,before,include_domainsandexclude_domainsare explicit filter parameters for search tools.include_domainscompiles to space-separatedsite:operators,exclude_domainsto-site:, and dates toafter:YYYY-MM-DD/before:YYYY-MM-DD. Filters and query are budget-guarded together to stay within DeepSeek's 128-character limit.queryindeepseek_fetchanddeepseek_fetch_manyextracts ranked relevant excerpts using a BM25-lite scoring engine without invoking an LLM.section(1-based index) enables sectional reading of long documents withhas_moreandtotal_sectionspagination metadata. Both operate in-memory on cached pages.deepseek_deep_researchdecomposes topics into 2-4 subqueries viadeepseek-flash, searches concurrently, merges and dedupes candidate sources, and synthesizes a cited report with numbered bracket citations[1],[2]capped at 6 sources / 24,000 characters. If the synthesis deadline is approached, it gracefully falls back to returning the gathered sources.deepseek_extractusesdeepseek-flashto extract structured JSON matching eitherfields: list[str]or aschema: dictwithout ingesting the full page text into client context. Missing requested fields are populated withnull, and pages with no readable text fast-fail with zero LLM token consumption.deepseek_check_balance(and legacy aliasdeepseek_balance) includes asessionblock with uptime, total queries handled, cache hit rate, and estimated cost and savings (at $0.00075 per request).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.Without
need_content, each search result carries a shortsummaryinstead of page text. It is capped atsummary_chars(default 400) and never longer thanmax_chars_per_result;summary_chars=0leaves it out. With content, asummaryonly stands in for a result that came back without content, andsummary_charsthen defaults tomax_chars_per_result. Summaries count towardsmax_total_chars.rewrite=True(also indeepseek_research) translates the query to English withdeepseek-flashbefore searching. It is skipped whenlangis set and falls back silently to the original query if the rewrite fails.clean=True(fetch tools and search content) removes backslash escapes from every ASCII punctuation character (\(,\-,\[,\/,\#...). Fenced code blocks and inline code spans are left untouched.Search results (content,
snippet,summary, and sodeepseek_researchsources) also get JSON string escapes decoded when the search index returns a page's text still JSON-escaped (Kr\u00f3tkiebecomesKrótkie,<\/p>becomes</p>), outside code. Simple attribute-less HTML tags left in snippets and summaries (<p>,<br>,</h2>...) are replaced with a space.strip_boilerplate=True(keyword-only, on every tool that returns page content) removes known site-interface lines. DeepSeek returns Reddit threads with the site UI localised to Chinese whatever the thread's language: the comment-sort menu (排序方式:,最佳,新...), the# 评论区域heading, the archived-post banner,[已删除]author lines and the sign-up footer. Rules are per site (Reddit only for now, matched onreddit.comand its subdomains) and only drop lines that consist entirely of a known label, so user text, Chinese included, and code blocks are kept. One rule applies to every site: a cookie-consent (CMP) dialog at the very start of the content ("Informacje o prywatności", "We value your privacy", "Wir verwenden Cookies"...) is removed when its first line opens with a known consent phrase and the run of lines shows a dialog control ("Accept all", "Zarządzaj preferencjami zgody"...). Removal stops at the first line that is not part of the dialog, and text further down is never touched, so an article about privacy is kept. When a fetched page is nothing but the banner,contentis empty and a note says so. It runs aftercleanand before the character caps, so budgets count the cleaned text; it does not change caching.strip_boilerplate=Falsereturns the content as fetched.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_researchis single-pass source gathering, not an agent: it makes exactly one search plus the gap fetches, never refines the query or searches again, and does no summarising. It takes the samelang,rewriteanddedupeoptions as search; the envelope'squery_usedshows the query that was sent. It does no summarising and makes no model call unlessrewrite=True: it returns sources for the caller to synthesise. Each source carriestitle,url,dateandsite(both null when the upstream gave none),date_source,authorityandrerank_score, so stale or off-topic sources are visible without opening them.deepseek_researchis for reconnaissance: finding candidate sources. There is no quality filter, so results can include low-quality or secondary pages (student papers, aggregators, clickbait). Verify facts in the primary source before citing them. To reach primary sources, ask in English for the primary study (for example "original study on X, journal article") and usesite:for Polish or other local sources (site:cbos.pl ...).authorityis passed through from the upstream index as is. Its meaning is not documented and it does not track credibility (a student PDF and a reference database can score alike), so do not use it to judge or filter sources.
Example calls:
deepseek_search(query="rust async runtime comparison", count=5)
deepseek_search(query="gobierno de España presupuestos 2026", lang="es", need_content=False)
deepseek_fetch(url="https://docs.rs/tokio/latest/tokio/", max_chars=15000)
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)
deepseek_deep_research(topic="comparing Raft vs Paxos consensus mechanisms in distributed systems")
deepseek_extract(url="https://news.ycombinator.com", fields=["top_story", "points", "author"])
deepseek_check_balance()Response envelope
Every tool returns a JSON object with ok.
Field | Where | Meaning |
| all |
|
| all tools except balance; also per item in |
|
|
| how many responses in this call were served from the cache |
|
| upstream requests actually made (cache hits are free) |
| all, including errors | wall time of the tool call in milliseconds (monotonic clock); a cache hit reports its own, near-zero time |
| 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; a title repeated around -, such as Reddit's X - X, is collapsed to X), url, date, authority (0-4, -1 unknown; an upstream field, not a credibility score), rerank_score, site, snippet,
and content with chars or summary where available. When the upstream gives no date, a YYYY-MM-DD date
(a valid calendar date, year 1990 to next year) found in the title or the first 600 characters of the text is
used instead. Without one, a full English or Polish month name next to a year (September 2025,
wrzesień 2025, PubMed-style 2025 September) gives the first of that month, and a day written with it (15 września 2025,
September 15, 2025) gives that day; Polish names are matched in the nominative and genitive, abbreviations
and a bare year are ignored; date_source is "upstream", "content" or null (no date), on search results and research
sources alike. deepseek_fetch returns url, title, content, chars,
truncated. deepseek_deep_research returns topic, subqueries, report (with bracketed citations [1], [2]),
synthesized, and sources. deepseek_extract returns url, title, and data (the extracted JSON matching the
requested fields or schema). chars is always the length of the content returned, in every tool.
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 |
Response size and cost
Serialized JSON size of one response per mode, measured on 2026-10-28 against the live API with the default parameters of each tool (compact JSON, UTF-8 bytes):
Call | Size |
| 3.7 KB |
| 2.3 KB |
| 15.1 KB |
| 20.9 KB |
| 13.3 KB |
| 20.1 KB |
These are single samples, not guarantees: sizes vary with the query and the pages returned, and are bounded by
max_chars_per_result, max_total_chars and the other character budgets, not by a fixed number.
Cost: DeepSeek bills Search and Fetch per successful request, not per returned result, so count does not change
the price of a call. See the DeepSeek Search & Fetch guide for
current prices, billing rules and limits; they may change and this project does not track them. A tool call that
needs several upstream requests (for example deepseek_research fetching pages whose search content is missing,
or deepseek_fetch_many) is billed for each of them, and rewrite=true additionally uses deepseek-flash tokens.
Cache hits are not billed.
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_searchwith the page title or asite:-scoped query instead.Fetch returns only title and content: no final URL, status code or publication date.
Fetch latency is DeepSeek's page render, not this server: an already rendered page returns in about 0.5 s, others take 3-10 s, and a missing page (HTTP 404) still takes 3-5 s before DeepSeek reports it. A 404 is not retried.
deepseek_fetch_manyruns up to 5 fetches at once, so a batch takes about as long as its slowest page; plan for that with larger batches.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.
See CONTRIBUTING.md for the contribution workflow and commit conventions.
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 a few cents at most (it also makes deepseek-flash judge calls).
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
Versions follow Semantic Versioning and are automated with
release-please from
Conventional Commits. Everything runs in
.github/workflows/release.yml:
Every push to
mainruns release-please. It opens (or updates) a release PR that bumps the version inpyproject.toml,server.jsonand.release-please-manifest.jsonand prepends a section toCHANGELOG.md. Standard Semantic Versioning applies:fixbumps the patch version,featbumps the minor, and breaking changes (feat!:) bump the major version;feat,fix,perf,refactor,docsanddepsappear in the changelog.Merging the release PR makes release-please tag
vX.Y.Zand create the GitHub Release.The same workflow run then builds the tagged commit, checks that the tag equals the versions in
pyproject.tomlandserver.json, runstwine checkand a clean-wheel smoke test, publishes to PyPI through Trusted Publishing (OIDC, no tokens), attaches the artifacts to the GitHub Release and updates the MCP Registry.
Publishing happens in the same workflow because tags and PRs created with GITHUB_TOKEN do not trigger other
workflows.
Manual fallback: bump the version in pyproject.toml, server.json and .release-please-manifest.json
(tests/test_version_sync.py checks the first two agree), update CHANGELOG.md, commit, and push a tag. The
workflow then publishes and creates the GitHub Release itself.
git tag -a v2.0.0 -m "v2.0.0" && git push origin v2.0.0
bash scripts/smoke_package.sh # optional local check: build, install into a clean venv, run the CLIRunning the workflow manually (workflow_dispatch) builds and verifies the package and publishes to TestPyPI
only.
One-time repository setup:
Settings, Actions, General: enable "Allow GitHub Actions to create and approve pull requests" so release-please can open its PR.
Settings, Environments: create a
pypienvironment (andtestpypifor manual runs); adding required reviewers there gates every PyPI publish.On PyPI (and TestPyPI), add a trusted publisher for this repository with workflow
release.ymland environmentpypi(testpypion TestPyPI).
Publishing 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 publishPublish to PyPI first: the registry checks that the package version exists. release-please keeps pyproject.toml
and server.json in step; tests/test_version_sync.py fails when they drift apart.
Changelog
See CHANGELOG.md for release notes.
License
MIT. Not affiliated with DeepSeek.
Available Tools
7 toolsdeepseek_check_balanceARead-onlyIdempotent
Check DeepSeek account balance (CNY/USD) and in-memory session telemetry.
Verify account funds and monitor session usage (requests, cache hits, estimated cost). Do not use for search or retrieval (use deepseek_search or deepseek_fetch). Requires DEEPSEEK_API_KEY. Takes no arguments.
| 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?
Annotations already declare readOnly, idempotent, non-destructive and closed-world, so the safety profile is covered. The description adds genuinely new operational context: it requires DEEPSEEK_API_KEY and takes no arguments, and that telemetry is in-memory (session-scoped, likely not persisted). It stops short of noting that the balance portion makes an authenticated network call that can fail on missing/invalid keys.
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 the primary verb+resource and kept to three short sentences. The second sentence partially restates the first ("Verify account funds and monitor session usage" vs the opening line), which is mild redundancy but also serves as the usage statement.
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 no-argument read tool with an output schema, everything essential is present: purpose, auth prerequisite, arity, and routing away from siblings. The only soft spot is "in-memory session telemetry", which leaves ambiguous whose session is measured and when the counters reset.
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?
Zero parameters, so the baseline is 4. The description reinforces this with "Takes no arguments", which prevents an agent from hunting for a currency or session-id parameter that does not exist.
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 pair ("Check DeepSeek account balance (CNY/USD)") plus a second explicit capability ("in-memory session telemetry"), and names the sibling tools it is not for. An agent can distinguish it from the deepseek_search/fetch family 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 explicit positive context ("Verify account funds and monitor session usage") and an explicit exclusion with named alternatives: "Do not use for search or retrieval (use deepseek_search or deepseek_fetch)". Both when-to-use and when-not-to-use are covered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
deepseek_deep_researchARead-onlyIdempotent
Execute multi-angle research on a topic and generate a cited briefing report.
Decomposes topic into subqueries, retrieves sources concurrently, and synthesizes a cited report [1], [2]. Use for deep topic synthesis. Do not use for simple lookups (use deepseek_search/deepseek_research) or reading known URLs (use deepseek_fetch).
Args: topic: Research subject, max 500 chars. max_queries: Subqueries to run (2-4, default 3). max_pages_per_query: Sources per subquery (1-5, default 3). lang: Language filter (e.g. 'en', 'pl'). dedupe: Collapse duplicates across subqueries (default True). refresh: Bypass response cache (default False). strip_boilerplate: Strip site UI text (default True).
| Name | Required | Description | Default |
|---|---|---|---|
| lang | No | ||
| topic | Yes | ||
| dedupe | No | ||
| refresh | No | ||
| max_queries | No | ||
| strip_boilerplate | No | ||
| max_pages_per_query | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/openWorld/non-destructive, so the safety profile is covered. The description adds real behavioral value beyond that: it discloses the internal pipeline (subquery decomposition, concurrent retrieval, citation markers [1],[2]) and the caching behavior implied by the refresh parameter. It stops short of stating cost, latency, or failure modes for a tool that fans out multiple network calls, which is the one remaining gap.
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 a one-line purpose, then usage rules, then a compact Args block. Every line carries information — no restatement of the tool name, no filler prose.
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 needn't be explained, and the parameter section compensates fully for the 0% schema coverage. Purpose, routing, and per-argument semantics are all present for a 7-param tool, leaving nothing an agent would need to guess before calling it.
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 carry the full burden and it does: all seven params are documented with meaning, ranges (topic max 500 chars, max_queries 2-4, max_pages_per_query 1-5), defaults (3, 3, True, False, True), and an example value for lang ('en', 'pl'). This is information the schema alone does not convey.
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: 'Execute multi-angle research on a topic and generate a cited briefing report.' The second sentence explains the mechanism (decompose into subqueries, concurrent retrieval, synthesized cited report), which distinguishes it from the plain search/fetch siblings.
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 routes the agent: 'Use for deep topic synthesis. Do not use for simple lookups (use deepseek_search/deepseek_research) or reading known URLs (use deepseek_fetch).' Both exclusions and named alternatives are given, so nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
deepseek_extractARead-onlyIdempotent
Extract structured JSON from a web page conforming to target fields or a schema.
Extracts specific entities or key-value data without returning full page text. Returns extracted JSON under 'data'. Do not use for general reading (use deepseek_fetch), nor for search or discovery (use deepseek_search).
Args: url: Absolute web page URL to extract from. fields: Target attribute names (e.g. ['price', 'specs']), exclusive with schema. schema: JSON Schema defining target structure, exclusive with fields. instruction: Optional extraction guidance. clean: Remove Markdown backslash escapes (default True). max_chars: Content cap before extraction (default 40000). refresh: Bypass cache and fetch page again (default False). strip_boilerplate: Remove site UI lines from text (default True).
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | ||
| clean | No | ||
| fields | No | ||
| schema | No | ||
| refresh | No | ||
| max_chars | No | ||
| instruction | No | ||
| strip_boilerplate | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, openWorld, and non-destructive, so the safety profile is covered. The description adds value beyond that: it states the result is returned under 'data', that full page text is not returned, that caching exists and can be bypassed via refresh, and that escapes/boilerplate are cleaned by default. Missing only rate limits, auth/cost behavior, and extraction failure semantics.
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?
Purpose and sibling routing are front-loaded in the first paragraph, followed by a compact Args list where each line carries distinct information. The only waste is echoing defaults already visible in the schema and one near-tautological parameter gloss.
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-value detail is not required, yet the description still tells the agent where the payload lives ('data'). Combined with the field/schema exclusivity rule and the cache/fetch controls, an agent has everything needed to 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?
Schema coverage is 0%, so the description carries the full burden and does document all eight parameters with intent, not just names — notably the mutual exclusivity of fields and schema, which the schema does not express at all. Defaults are restated (clean, max_chars, refresh, strip_boilerplate), which is mildly redundant, and a couple of glosses are thin ('schema: JSON Schema defining target structure', 'instruction: Optional extraction guidance').
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 names a specific verb (extract), a specific resource (web page), and a specific output shape (structured JSON conforming to fields or a schema). It further scopes the tool negatively ('without returning full page text'), so an agent can distinguish it from deepseek_fetch and deepseek_search 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?
Explicit exclusions are given with named alternatives: 'Do not use for general reading (use deepseek_fetch), nor for search or discovery (use deepseek_search).' This is exactly the when-not/alternative routing an agent needs, and it names two of the six siblings directly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
deepseek_fetchARead-onlyIdempotent
Fetch one known URL and return its title and Markdown content.
Retrieves full Markdown content for a known URL. Use when target URL is known. For multiple URLs use deepseek_fetch_many; for structured data use deepseek_extract; for search use deepseek_search. Returns 404 for PDFs/Reddit (use deepseek_search instead).
Args: url: Absolute http(s) URL, max 8192 characters. clean: Remove Markdown backslash escapes (default True). max_chars: Content cap after cleaning (default 20000). query: Query to extract ranked relevant snippets. section: 1-based index to read a specific document section. max_snippets: Max ranked snippets when query is set (default 3, 1-5). refresh: Bypass cache and fetch page again (default False). strip_boilerplate: Remove site UI lines from text (default True).
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | ||
| clean | No | ||
| query | No | ||
| refresh | No | ||
| section | No | ||
| max_chars | No | ||
| max_snippets | No | ||
| strip_boilerplate | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, openWorldHint and destructiveHint=false, so the safety profile is covered. The description adds genuinely new behavioral context beyond them: caching with a refresh bypass, content caps, escape-cleaning, boilerplate stripping, and a concrete failure mode (404 on PDFs/Reddit). It stops short of describing pagination or what 'sections' look like structurally.
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 the one-line purpose and the routing sentence, then the arg list. The Args block is long but each entry earns its place given 0% schema coverage. Minor duplication between the opening line and the second sentence ('Fetch one known URL' / 'Retrieves full Markdown content for a known URL').
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 needn't be explained, and the description states them anyway (title + Markdown). With 8 params, an open-world network dependency, and a known failure mode, the definition gives an agent nearly everything needed to call correctly. It could go slightly further on cache staleness semantics for refresh/section interplay.
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 carries the full burden, and it does: every one of the 8 params is documented with defaults and constraints (url absolute http(s) max 8192 chars, max_snippets 1-5, section 1-based, clean removes backslash escapes, max_chars applies after cleaning). That is materially more than the bare titles and defaults in 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?
States a specific verb and resource ('Fetch one known URL') and explicitly names the output ('its title and Markdown content'). The pairing with sibling names in the next sentence lets an agent distinguish deepseek_fetch from deepseek_fetch_many 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit selection condition ('Use when target URL is known') plus a per-alternative routing map: fetch_many for multiple URLs, extract for structured data, search for search. It even names a carve-out case (PDFs/Reddit return 404, use deepseek_search instead), which is exactly the kind of when-not guidance that prevents wrong selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
deepseek_fetch_manyARead-onlyIdempotent
Fetch up to 10 known URLs concurrently and return each page's title and Markdown content.
Fetch multiple known URLs in parallel. Use when target URLs are known. Do not use for a single URL (use deepseek_fetch), nor for search/discovery (use deepseek_search). Skips blanks, deduplicates, and preserves order.
Args: urls: 1-10 absolute http(s) URLs, max 8192 characters each. max_chars_per_url: Content cap per page (default 4000). max_total_chars: Total content budget across all pages (default 20000). clean: Remove Markdown backslash escapes (default True). query: Query to extract ranked snippets across fetched pages. refresh: Bypass cache and fetch pages again (default False). strip_boilerplate: Remove site UI lines from text (default True). deadline: Max seconds before cancelling pending fetches (default 120s).
| Name | Required | Description | Default |
|---|---|---|---|
| urls | Yes | ||
| clean | No | ||
| query | No | ||
| refresh | No | ||
| deadline | No | ||
| max_total_chars | No | ||
| max_chars_per_url | No | ||
| strip_boilerplate | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/openWorld/non-destructive, and the description still adds real behavior: blank-skipping, deduplication, order preservation, cache bypass via refresh, cancellation of pending fetches at the deadline, and per-page plus global content budgets. It stops short of saying what happens when individual URLs fail (partial results vs. whole-call error), which is the main behavioral gap for a concurrent fetch tool.
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 the core statement and the use/do-not-use routing before the Args block, so an agent gets the decision-relevant information first. The opening two sentences are somewhat redundant ("Fetch up to 10 known URLs concurrently" / "Fetch multiple known URLs in parallel"), costing a little space without adding 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?
With an output schema present, the description needn't explain return values, and it covers routing, all 8 parameters, budgets, caching, and timeout behavior for a moderately complex tool. The remaining unknown (per-URL failure semantics) is secondary to correct invocation.
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 carry all parameter meaning, and it does document all 8 including defaults and constraints (1–10 absolute http(s) URLs, 8192 chars each, default budgets). The weakest entry is `query`, described only as "extract ranked snippets across fetched pages," which doesn't make clear whether it changes the return shape or filters content.
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 (fetch), resource (up to 10 known URLs concurrently), and even the return shape (each page's title and Markdown content). It explicitly contrasts itself with deepseek_fetch and deepseek_search, so an agent can distinguish it from siblings without opening a 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 positive condition ("Use when target URLs are known") and two explicit exclusions with the named alternatives to use instead (single URL → deepseek_fetch, search/discovery → deepseek_search). Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
deepseek_researchARead-onlyIdempotent
Single-pass source gathering: search with page content and auto-fetch stub pages.
Gathers candidate sources for research. It does not iterate, refine the query or summarise: there is exactly one search and sources return raw content for the caller to synthesise.
Unlike deepseek_search (index-only), deepseek_research auto-fetches stub results in parallel for deep source gathering. Use when research requires complete documents rather than snippets.
Args: question: Search query, max 128 characters. max_pages: Results to use, 1-50 (default 5). per_page_chars: Cap per source (default 6000). total_chars: Budget across sources (default 30000). after: Date on or after (YYYY-MM-DD/YYYY). before: Date on or before (YYYY-MM-DD/YYYY). include_domains: Restrict domains (e.g. ['arxiv.org']). exclude_domains: Exclude domains (e.g. ['wikipedia.org']). lang: Language filter (e.g. 'pl', 'es', 'ja'). rewrite: Translate query via deepseek-flash (default False). dedupe: Collapse duplicate results (default True). refresh: Bypass response cache (default False). strip_boilerplate: Strip site UI text (default True).
| Name | Required | Description | Default |
|---|---|---|---|
| lang | No | ||
| after | No | ||
| before | No | ||
| dedupe | No | ||
| refresh | No | ||
| rewrite | No | ||
| question | Yes | ||
| max_pages | No | ||
| total_chars | No | ||
| per_page_chars | No | ||
| exclude_domains | No | ||
| include_domains | No | ||
| strip_boilerplate | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, openWorldHint and destructiveHint=false, so the safety profile is covered. The description still adds real value beyond that: exactly one search, no query refinement or summarization, raw content returned to the caller, parallel auto-fetch of stub pages, and cache-bypass via refresh. It stops short of anything on rate limits, failure/partial-result behavior, or what happens when stub fetches fail, so it is good but not fully transparent.
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 is front-loaded and tight — purpose, non-behavior, sibling contrast, then the parameter block. The only waste is mild redundancy in restating defaults (5, 6000, 30000, True/False) already present in the schema, though the added ranges and examples justify most of the repetition.
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?
With an output schema present, return values need no explanation, and annotations cover the safety profile. What remains — single-pass semantics, raw-content contract, cache and dedupe behavior, and full parameter meaning — is all covered, so an agent has everything needed to call this 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?
Schema description coverage is 0% and there are 13 parameters, so the description carries the full burden — and it does, documenting every parameter with units and constraints ('max 128 characters', '1-50 (default 5)', date formats 'YYYY-MM-DD/YYYY', domain list examples, language codes). This is exactly the compensation the low coverage requires.
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 line gives a specific verb and resource ('Single-pass source gathering: search with page content and auto-fetch stub pages') and the second sentence scopes the behavior ('Gathers candidate sources for research'). It explicitly contrasts itself with the named sibling deepseek_search ('index-only'), so an agent can distinguish the two 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It states the selection condition directly: 'Use when research requires complete documents rather than snippets,' and names the alternative (deepseek_search) that covers the snippet case. The 'does not iterate, refine the query or summarise' clause implicitly routes multi-pass work away from this tool, giving both a when and a when-not.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
deepseek_searchARead-onlyIdempotent
Search the web with DeepSeek index and return page text, snippets, and metadata.
Primary search and retrieval tool for AI agents. Queries DeepSeek's search index directly to return ranked results with snippets (need_content=False) or indexed full page text (default need_content=True). Use for standard search, targeted queries, and discovery. Unlike deepseek_research (auto-fetches stub pages), this tool only returns indexed content.
Args: query: Search query, max 128 chars (supports site:, -site:, "phrase", after:, before:). count: Results to return, 1-50 (default 5). ori_question: Natural question, max 128 chars; improves ranking. need_content: Full text inline (default True; False for snippets). lang: Language filter (e.g. 'es', 'de', 'ja'). max_chars_per_result: Cap per result (default 4000). max_total_chars: Budget across results (default 30000). dedupe: Collapse duplicate results (default True). rewrite: Rewrite query via deepseek-flash (default False). after: Date on or after (YYYY-MM-DD/YYYY). before: Date on or before (YYYY-MM-DD/YYYY). include_domains: Restrict domains (e.g. ['arxiv.org']). exclude_domains: Exclude domains (e.g. ['wikipedia.org']). refresh: Bypass response cache (default False). summary_chars: Summary cap per result without content. strip_boilerplate: Strip site UI text (default True).
| Name | Required | Description | Default |
|---|---|---|---|
| lang | No | ||
| after | No | ||
| count | No | ||
| query | Yes | ||
| before | No | ||
| dedupe | No | ||
| refresh | No | ||
| rewrite | No | ||
| need_content | No | ||
| ori_question | No | ||
| summary_chars | No | ||
| exclude_domains | No | ||
| include_domains | No | ||
| max_total_chars | No | ||
| strip_boilerplate | 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?
Annotations already declare readOnlyHint, idempotentHint, openWorldHint, and non-destructive behavior, so the safety profile is covered structurally. The description adds meaningful non-annotation context: a response cache that refresh bypasses, optional query rewriting via deepseek-flash, dedupe collapse behavior, and boilerplate stripping. It does not mention rate limits, cost, or failure/fallback behavior, keeping it below a 5.
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 purpose, primary-use statement, and sibling differentiation are front-loaded in three tight sentences, then a compact Args block. Every line earns its place, though the Args list at 16 entries makes the whole thing long; the leading prose could be trimmed slightly without loss.
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 16-parameter tool this is thorough: ranking modifiers, content-vs-snippet mode, char budgets, domain filters, date filters, and cache control are all explained. An output schema exists, so return-value explanation is correctly omitted, and nothing an agent needs 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.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description bears the full burden, and it documents all 16 parameters with defaults, ranges, and formats (count 1-50 default 5, date formats YYYY-MM-DD/YYYY, query operators site:/after:/before:, example domain lists). This meaningfully exceeds what the bare schema conveys.
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 first sentence names a specific verb (search) and resource (web via DeepSeek index) plus the return shape (page text, snippets, metadata). It explicitly states 'Primary search and retrieval tool for AI agents' and contrasts itself with the deepseek_research sibling, so an agent can distinguish the two without inspecting schemas.
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?
It names a positive context ('Use for standard search, targeted queries, and discovery') and gives an explicit differentiation rule versus deepseek_research ('auto-fetches stub pages' vs 'only returns indexed content'). It stops short of naming when to prefer deepseek_fetch, deepseek_fetch_many, or deepseek_extract for known-URL retrieval, leaving some routing to inference.
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.
10 tool updates
v2.0.1- Removed
deepseek_balance - Added
deepseek_check_balance - Added
deepseek_deep_research - Added
deepseek_extract - Changed
deepseek_fetch3 fields changed- added
Input schema / properties / max_snippetsAdded value: +{ + "default": 3, + "title": "Max Snippets", + "type": "integer" +} - added
Input schema / properties / queryAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Query" +} - added
Input schema / properties / sectionAdded value: +{ + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Section" +}
- Changed
deepseek_fetch_many2 fields changed- added
Input schema / properties / deadlineAdded value: +{ + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Deadline" +} - added
Input schema / properties / queryAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Query" +}
- Changed
deepseek_research4 fields changed- added
Input schema / properties / afterAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "After" +} - added
Input schema / properties / beforeAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Before" +} - added
Input schema / properties / exclude_domainsAdded value: +{ + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Exclude Domains" +} - added
Input schema / properties / include_domainsAdded value: +{ + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Include Domains" +}
- Added
deepseek_search - Removed
deepseek_search_and_read - Removed
deepseek_web_search
5 tool updates
v1.0.0- Changed
deepseek_fetch1 field changed- added
Input schema / properties / strip_boilerplateAdded value: +{ + "default": true, + "title": "Strip Boilerplate", + "type": "boolean" +}
- Changed
deepseek_fetch_many1 field changed- added
Input schema / properties / strip_boilerplateAdded value: +{ + "default": true, + "title": "Strip Boilerplate", + "type": "boolean" +}
- Changed
deepseek_research4 fields changed- added
Input schema / properties / dedupeAdded value: +{ + "default": true, + "title": "Dedupe", + "type": "boolean" +} - added
Input schema / properties / langAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Lang" +} - added
Input schema / properties / rewriteAdded value: +{ + "default": false, + "title": "Rewrite", + "type": "boolean" +} - added
Input schema / properties / strip_boilerplateAdded value: +{ + "default": true, + "title": "Strip Boilerplate", + "type": "boolean" +}
- Changed
deepseek_search_and_read2 fields changed- added
Input schema / properties / strip_boilerplateAdded value: +{ + "default": true, + "title": "Strip Boilerplate", + "type": "boolean" +} - added
Input schema / properties / summary_charsAdded value: +{ + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Summary Chars" +}
- Changed
deepseek_web_search2 fields changed- added
Input schema / properties / strip_boilerplateAdded value: +{ + "default": true, + "title": "Strip Boilerplate", + "type": "boolean" +} - added
Input schema / properties / summary_charsAdded value: +{ + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Summary Chars" +}
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 7 tools
Each tool targets a distinct retrieval mode (search, single fetch, batch fetch, structured extraction, research passes, balance check) and descriptions explicitly disambiguate against siblings (e.g. 'Unlike deepseek_research...', 'Do not use for a single URL'). The only residual overlap is deepseek_research vs deepseek_deep_research, which differ mainly in autonomy rather than in surface inputs, so an agent could still hesitate between them.
All tools use a uniform deepseek_ prefix followed by clear snake_case verb/noun tokens (search, check_balance, fetch, fetch_many, research, deep_research, extract). The pattern is predictable and scales cleanly.
Seven tools is well within the sweet spot and each maps to a distinct capability tier (recovery/search, read, batch read, extract, research, deep research, account check). No tool feels redundant or bolted on.
The surface covers the full lifecycle from discovery through reading, structured extraction, and cited synthesis plus an operational balance check. Minor gap: deepseek_fetch explicitly 404s on PDFs/Reddit with no dedicated document handler, leaving a documented dead end that callers must reroute around.
Maintenance
Related MCP Connectors
Web search and page fetch for AI agents. Results come from a shared cache; cached calls cost less.
Web scraping, search, crawling, structured extraction and research for AI agents.
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
- AlicenseAqualityDmaintenanceA general MCP server providing web search capabilities using DeepSeek's native online search API.154 npm33MIT
- 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.-
- AlicenseAqualityDmaintenanceEnables real-time web search via DeepSeek's server-side tool without requiring additional search API keys.121 npmMIT