DeepSeek × Exa Search Combine 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 × Exa Search Combine MCPsearch DeepSeek and Exa for recent MCP server news and merge the results"
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 × Exa Search Combine MCP
One stdio MCP server that queries DeepSeek and Exa at the same time and hands your agent a single deduplicated result list — instead of two overlapping ones it has to reconcile itself.
Configure both API keys, or just one. If only one key exists, "both" quietly narrows to that
provider instead of failing.
Zero dependencies. Node built-ins only (
fetch,readline). Nothing to audit, nothing to break.One process, two engines.
searchfans out in parallel; pages found by both are merged into one entry labelled with every source.Independent failure. A rate-limited or broken provider never removes the other provider's results.
Configurable fetch preference. Exa first by default, swap the order with one env var.
Why this exists
Both vendors ship a search MCP. Neither combines them:
Package | Limitation |
| Exa only |
| No standalone search tool — |
DeepSeek's dedicated Search & Fetch API (/v1/tools/search, /v1/tools/fetch, opened 2026-10-17) is a
separate JSON API from its chat endpoints, so nothing was using it as a first-class search backend.
This server does, and merges what it returns with Exa.
Related MCP server: Web Search Router
Install
# run without installing
npx -y deepseek-exa-search-combine-mcp
# or install globally
npm i -g deepseek-exa-search-combine-mcp
dxsc statusRequires Node.js 20+ (global fetch).
Configure
Variable | Required | Default | Notes |
| one of these | — | |
| one of these | — | |
| no |
|
|
| no |
| Fallback order for |
| no |
| Per-request deadline |
| no |
| Override for proxies/gateways |
| no |
| Override for proxies/gateways |
| no |
| Set to |
At least one of EXA_API_KEY / DEEPSEEK_API_KEY must be set — the server refuses to start with
neither, because a search server with zero backends can only fail later and less clearly.
Client configuration
{
"mcpServers": {
"search": {
"command": "npx",
"args": ["-y", "deepseek-exa-search-combine-mcp"],
"env": {
"EXA_API_KEY": "your-exa-key",
"DEEPSEEK_API_KEY": "your-deepseek-key"
}
}
}
}The block above works unchanged for Claude Desktop (claude_desktop_config.json), Cursor
(~/.cursor/mcp.json) and most other clients.
Codex CLI:
codex mcp add search \
--env EXA_API_KEY=your-exa-key \
--env DEEPSEEK_API_KEY=your-deepseek-key \
-- npx -y deepseek-exa-search-combine-mcpUsing a local checkout instead of npx avoids any launcher ambiguity on Windows — point command
straight at the binary:
{
"command": "node",
"args": ["/absolute/path/to/deepseek-exa-search-combine-mcp/bin/dxsc.mjs"],
"env": { "EXA_API_KEY": "…", "DEEPSEEK_API_KEY": "…" }
}Tools
search
Queries every configured provider in parallel, merges and deduplicates.
Parameter | Type | Default | Applies to |
| string | — | both |
|
|
| — |
| integer 1–100 | 8 | Exa ≤ 100, DeepSeek ≤ 50 (clamped per provider) |
| boolean | false | both — also return page body |
| integer 200–20000 | 4000 | both — per-page text cap |
| string[] | — | Exa |
| string[] | — | Exa |
| ISO 8601 | — | Exa |
| ISO 8601 | — | Exa |
|
| — | Exa |
|
|
| Exa |
| string ≤128 chars | — | DeepSeek — original user question |
| string | — | DeepSeek — IP used to localize results |
DeepSeek query operators pass through: site:github.com, -site:example.com, "exact phrase",
-word, lang:zh,en, after:2025, before:2026-06-01.
fetch
Pulls full page content, trying providers in order until one returns real text.
Parameter | Type | Default |
| string | — |
| string[] | — |
|
| configured |
| integer 200–20000 | 6000 |
both means "follow the fallback order", not "call both and compare": the first provider that
returns non-empty content wins per URL, so a successful Exa fetch never spends DeepSeek credits.
status
Reports which keys are configured, the default search behaviour and the effective fetch chain. No network calls, no cost.
What "combine" actually means
When both engines return the same page, you get one entry with sources: ["exa", "deepseek"],
not two near-duplicates. URLs are compared after:
lowercasing the host and dropping the fragment,
removing tracking parameters (
utm_*,ref,fbclid,gclid,mc_cid,_hsenc, …),collapsing duplicate slashes and stripping the trailing slash.
The first occurrence keeps its position, so provider ranking is preserved. Missing fields are filled
from the other provider instead of being discarded, and each provider's own snippet is kept when the
two phrase things differently. Set MERGE_DEDUPE=false to get the raw concatenation instead.
CLI
The same code path is reachable without an MCP client, which makes debugging a one-liner:
dxsc status
dxsc search "rust async runtime comparison" --count 5
dxsc search "site:arxiv.org diffusion models" --provider deepseek --count 10
dxsc search "transformer" --content --json
dxsc fetch https://example.com/article --max-chars 8000Run dxsc --help for every flag. --json prints the structured result instead of Markdown.
Cost
Nothing is cached — two identical calls cost twice.
Provider | Billing |
Exa | Per request; roughly $0.007 for a small search. |
DeepSeek | $0.75 / 1,000 successful requests (~$0.00075 each). Failed requests and empty result sets are not billed. |
fetch costs one request per provider per URL that actually gets tried, so a working Exa fetch costs
one Exa call and zero DeepSeek calls.
Troubleshooting
Symptom | Cause |
| Neither |
| You passed |
| Provider rate limit; the other provider's results are still returned |
Nothing loads in the client on Windows | The launcher could not spawn |
Exit code is 1 from the CLI when nothing could be retrieved at all; a partial success exits 0.
Development
npm test # 77 tests, node:test, no dependencies
npm run check # syntax check every moduleLayout:
bin/dxsc.mjs entry point (MCP by default, CLI for everything else)
src/config.mjs env parsing + provider resolution
src/http.mjs single POST helper, error normalisation
src/providers/ exa.mjs, deepseek.mjs, registry + fan-out
src/merge.mjs cross-provider dedupe and field merging
src/render.mjs Markdown output
src/tools.mjs tool schemas + implementations
src/server.mjs JSON-RPC dispatch (transport agnostic)
src/transports/stdio.mjs newline-delimited JSON-RPC over stdio
test/ unit + protocol tests against a fetch doubleThe dispatcher is transport-agnostic and takes an injectable fetchImpl, so tests exercise the real
protocol and the real provider mapping without network access or a child process.
License
MIT
Available Tools
3 toolsfetchCombined page fetchA
Fetch full page content for one or more URLs. Providers are tried in the configured fallback order (Exa first by default, then DeepSeek) and the first one that returns real content wins per URL. Pass provider="exa" or "deepseek" to pin a single backend.
| Name | Required | Description | Default |
|---|---|---|---|
| url | No | A single URL to fetch. | |
| urls | No | Several URLs at once. Exa handles the batch in one request. | |
| provider | No | Omit or "both" for the configured fallback order; "exa" / "deepseek" to pin one backend. | |
| max_chars | No | Per-page output cap. Default 6000. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations at all, the description carries the full burden and delivers the key non-obvious behavior: providers are tried in a configured fallback order (Exa then DeepSeek) and the first to return real content wins per URL. That is exactly the kind of execution semantics an agent cannot infer. It omits what happens when every provider fails and whether partial batch failures are surfaced.
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?
Three tight sentences with the core purpose front-loaded and no filler. The third sentence on provider pinning partially duplicates the schema's enum description, a minor redundancy.
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 4-parameter tool with no annotations and no output schema, the description covers execution order but not the return shape (raw text? markdown? metadata?) or failure behavior. The absence of an output schema means the description should say at least roughly what comes back, and it does not.
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 100%, so all four parameters are already documented, and the description's provider sentence largely restates the enum semantics. It adds the useful 'first one that returns real content wins per URL' framing but does not clarify the url-vs-urls relationship or when to prefer one over the other, so baseline 3 applies.
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 states a specific verb and resource — 'Fetch full page content' for 'one or more URLs' — which an agent can distinguish from 'search' (discovery) and 'status' (health). It stops short of naming the siblings explicitly, so it lands at clear-but-not-differentiated.
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?
The description explains provider selection well (fallback order, pinning with provider='exa'/'deepseek'), which is genuine usage guidance. However it never says when to reach for this tool over 'search' — e.g. after search returns URLs, or when full text rather than snippets is needed — so the when-to-use decision against alternatives 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.
searchCombined web searchA
Search the web through DeepSeek and Exa at once and get back a single deduplicated list. By default every configured provider is queried in parallel and pages found by both are merged into one entry (labelled with all sources). Pass provider="exa" or "deepseek" to use just one. If only one API key is configured, the default automatically narrows to that provider.
| Name | Required | Description | Default |
|---|---|---|---|
| type | No | Exa only search mode: auto (default), lite, deep-lite, deep, instant, fast. | |
| count | No | Results per provider (Exa caps at 100, DeepSeek at 50). Default 8. | |
| query | Yes | Search query. DeepSeek supports operators: site:, -site:, "exact phrase", -word, lang:zh,en, after:2025, before:2026-06-01. | |
| category | No | Exa only. Focus the index on one data category. | |
| provider | No | Which backend(s) to query. Omit or "both" to use every configured provider; "exa" / "deepseek" to force one. | |
| max_chars | No | Per-page text cap when need_content is true. Default 4000. | |
| localization | No | DeepSeek only. IP address used to localize results. | |
| need_content | No | Also fetch page body text for each hit. Much larger responses and higher cost. | |
| ori_question | No | DeepSeek only. The original user question, improves query understanding (max 128 chars). | |
| exclude_domains | No | Exa only. Exclude these domains or domain paths. | |
| include_domains | No | Exa only. Restrict results to these domains or domain paths. | |
| end_published_date | No | Exa only. ISO 8601 upper bound. | |
| start_published_date | No | Exa only. ISO 8601 lower bound, e.g. 2025-01-01T00:00:00.000Z |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden and discloses meaningful behavior beyond the schema: providers are queried in parallel by default, duplicate pages are merged into one entry labeled with all sources, and provider selection auto-narrows when only one key is configured. It does not cover response errors, pagination, or rate limits, but the core operational behavior is well explained.
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?
Three tightly written sentences with the main purpose and default behavior front-loaded. Every sentence adds information about combined search, deduplication, or provider selection without 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?
For a 13-parameter search tool with no annotations or output schema, the description does enough: it explains the combined-backend model, deduplication, source labeling, and provider defaulting. Return behavior is summarized at a high level, while detailed parameter semantics remain well covered by the schema.
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 already 100%, so the baseline is 3, but the description adds useful meaning for the provider parameter: default parallel querying across all configured providers, explicit provider forcing, and automatic narrowing with a single API key. Other parameters are left to the schema, which is appropriate given its full coverage.
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: search the web through DeepSeek and Exa, returning a single deduplicated list. It also clarifies the default multi-provider behavior and merged deduplication, so the tool is distinguishable from a simple single-backend search or fetch.
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 clear context for provider selection: default queries every configured provider, provider="exa" or "deepseek" forces one, and a single configured API key automatically narrows the default. It does not explicitly compare this tool against sibling tools such as fetch or status, but usage context is otherwise clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
statusServer statusA
Report which backends this server can reach, the default search behaviour and the fetch fallback order. Makes no network calls and costs nothing.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full burden and does meaningful work: it discloses that no network calls are made and the call costs nothing, which is exactly the safety/cost signal an agent needs. It stops short of describing the response shape or any caching/staleness caveats.
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?
Two sentences, zero filler, and the content enumeration is front-loaded ahead of the cost note. Nothing here could be cut without losing 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 parameterless informational tool with no output schema, the description is close to sufficient: it enumerates the three things returned (reachable backends, default search behaviour, fallback order) and disclaims side effects. A slightly fuller note on response format would make it complete.
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?
The tool takes zero parameters, so the baseline is 4. There is nothing for the description to clarify about inputs, and it correctly adds none.
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 (Report) and resource (reachable backends, default search behaviour, fetch fallback order), which clearly marks this as an informational tool rather than a search or fetch. It doesn't explicitly name the siblings search or fetch, so differentiation is inferred from context rather than stated.
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?
By mentioning 'default search behaviour' and 'fetch fallback order' it hints at its relationship to the search and fetch siblings, but it never says when to call it (e.g., before search, or to diagnose failures) and provides no exclusions. Usage is implied rather than instructed.
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.
3 tool updates
v1.0.0- First observed
fetch - First observed
search - First observed
status
TDQS
Scored across 3 tools
Each tool has a clearly distinct role: search performs multi-provider web search, fetch retrieves page content for URLs, and status reports backend availability without network calls. There is no meaningful overlap that would cause misselection.
The names are short, lowercase, and consistently action-oriented or state-oriented: search, fetch, status. The pattern is predictable and easy for an agent to map to intent.
Three tools are well scoped for a focused search-and-fetch server. Each tool earns its place, and there are no redundant or filler tools.
The core lifecycle is covered: search the web, fetch full content, and inspect backend status. Minor gaps exist around provider configuration or richer result management, but the essential surface is complete for the stated purpose.
Maintenance
Related MCP Connectors
Agent-driven search: build, import, tune, search, and score result quality — all over MCP.
Multi-engine search for AI agents. Trust scoring, local corpus, MCP-native. Self-hostable, BYOK.
A hosted MCP suite providing workflow primitives: web search, content fetching, compression, deduplication, cost/budget management, and agent memory pipelines.
One MCP for the Web. Easily search, crawl, navigate, and extract websites without getting blocked.…
Related MCP Servers
- AlicenseBqualityFmaintenanceAggregated search API service that provides real-time web search capabilities for AI assistants via MCP.26 npm43GPL 3.0
- FlicenseNot gradedqualityDmaintenanceA remote MCP server that routes web search queries across multiple providers (HTTP APIs, external MCP servers, LLM with grounding) with intelligent fallback and quota management.-
- AlicenseNot gradedqualityCmaintenanceMCP server for multi-engine web search and web page fetching, supporting parallel search, content extraction, and optional LLM-powered search summarization and deep search.4MIT
- AlicenseNot gradedqualityBmaintenanceEnables querying multiple search engines and paid search APIs through a local aggregation service, returning deduplicated and RRF-ranked results via a single MCP tool.1MIT