serper-search-mcp-server
<div align="center">
# π Serper Search MCP Server v4.0
**The First Universal Search Gateway for AI Agents β Google (Serper), Tavily, Brave, Exa, and Firecrawl with auto-failover, 14 tools, and token-smart verbosity.**
[](https://www.npmjs.com/package/serper-search-mcp)
[](https://www.npmjs.com/package/serper-search-mcp)
[](https://hub.docker.com/r/smjahid/server-serper-search)
[](https://github.com/smjahid012/serper-search-mcp-server)
[](LICENSE)
[](https://modelcontextprotocol.io)
</div>
---
## What this does
This MCP server wraps the [Serper API](https://serper.dev) (Google Search results) and exposes **14 tools** that any MCP-compatible AI client (Claude, Cursor, Windsurf, KiloCode, n8n, etc.) can call in real time β including web, image, video, news, shopping, places, scholar, patents, autocomplete, full-page scraping, and batch search.
| Tool | What you get |
|---|---|
| `search` β | Unified search `{type, provider, verbosity}` β 1 schema (~700 tokens vs ~7k for all) |
| `search_web` | Organic results + **Knowledge Graph** + **Answer Box** + "People Also Ask" + Related Searches |
| `search_images` | Image URLs, thumbnails, dimensions, source pages + `gallery` layout + `size/orientation/color/site` |
| `search_videos` | Titles, channels, durations, links |
| `search_news` | Headlines, sources, dates β freshness-filtered |
| `search_shopping` | Products, prices, ratings, delivery info (always rich) |
| `search_places` | Local businesses & POIs with address, phone, **full 7-day hours**, GPS + Directions (always rich) |
| `search_scholar` π | Academic papers with authors, journal, year, and citation counts |
| `search_patents` π | Patents with publication number, assignee, inventor, dates |
| `autocomplete` π | Query completions β cheap, no LLM needed |
| `scrape` π | Full page content as markdown β read articles found via search |
| `search_many` π | 1β10 parallel web searches with automatic cross-query dedupe |
| `deep_research` | Multi-step research: auto sub-queries β parallel searches β LLM-synthesized cited report |
| `search_rag_context` | Clean chunked text with metadata for embedding pipelines & vector DBs β no LLM needed |
| `resolve_links` π | Turn `google.com/goto` redirect links from a search into real URLs (free, 0 credits) |
### Verbosity (token-smart, auto by default)
| Mode | Who | What | Tokens |
|---|---|---|---|
| `auto` (default) | server picks | devβcompact, chatβstandard, scholar/researchβfull, places/shopping/imagesβalways rich | varies |
| `compact` | dev coding | title+URL+1-line snippet, no KG/PAA/Related | ~800 |
| `standard` | normal chat | KG + Answer Box + 10 organic | ~4k |
| `full` | researcher | everything + citations | ~5k |
> Credit rule: `compact` fetches `num=5` (never fetch-10-show-3). 1 search = 1 credit, cache hit = 0, scrape β 2. `deep_research`: basic 3cr / standard 5cr / deep 8cr.
### Providers (universal gateway β auto-failover)
| Provider | Cost per 1k | When to use |
|---|---|---|
| **Serper** (default) | $3-5, 2500 free/mo | Cheapest Google truth β keep first |
| **Tavily** fallback | $8-16 | AI-reranked, finance/news topics |
| **Brave** fallback | $5 | Independent index, private, 669ms |
| **Exa** fallback | $4-7 | Neural semantic when keywords fail |
| **Firecrawl** fallback | ~$3-4 eff | JS-rendered scraping & search upgrade |
```bash
SEARCH_PROVIDER_ORDER=serper,tavily,brave,exa # failover chain
SEARCH_FALLBACK=true # on 402/429/5xx/empty
```
### CLI (dev power-tool β 4-32x cheaper than MCP schemas)
```bash
npx serper-search-mcp search "react server components" --compact --limit 5
npx serper-search-mcp scrape https://example.com --max-chars 8000
npx serper-search-mcp research "RAG limits" --depth basic
npx serper-search-mcp rag "transformer" --format json
npx serper-search-mcp providers --status
```
> **Free to start:** Serper gives you 2,500 free queries/month. No credit card required.
---
## Quick start
### π Provider Keys & Universal Gateway Configuration
This server functions as a **Universal Search Gateway**. Only `SERPER_API_KEY` is required. You can add any combination of the other 4 search providers and LLM keys to enable automatic multi-provider failover, semantic search, and scraping upgrades:
| Variable | Provider / Purpose | Default / Priority |
|---|---|---|
| `SERPER_API_KEY` | **Serper** (Google Search baseline) | **Required** ([serper.dev](https://serper.dev)) |
| `TAVILY_API_KEY` | **Tavily** (AI-reranked fallback) | Optional ([tavily.com](https://tavily.com)) |
| `BRAVE_API_KEY` | **Brave** (Independent web index fallback) | Optional ([brave.com/search/api](https://brave.com/search/api)) |
| `EXA_API_KEY` | **Exa** (Neural semantic search fallback) | Optional ([exa.ai](https://exa.ai)) |
| `FIRECRAWL_API_KEY` | **Firecrawl** (JS-rendered scraping & search upgrade) | Optional ([firecrawl.dev](https://firecrawl.dev)) |
| `OPENROUTER_API_KEY` | LLM for `deep_research` | Optional (takes priority over Gemini) |
| `GEMINI_API_KEY` | LLM for `deep_research` | Optional (used when OpenRouter is absent) |
#### Failover Control:
```bash
SEARCH_PROVIDER_ORDER=serper,tavily,brave,exa # custom failover priority chain
SEARCH_FALLBACK=true # auto-failover on 402/429/5xx/empty (default: true)
```
---
### Option 1 β npx (MCP Client Configuration)
Add this to your MCP client config file (Claude Desktop, Cursor, Windsurf, KiloCode).
#### π Full Universal Gateway Config (All 5 Providers + Failover):
```json
{
"mcpServers": {
"serper-search": {
"command": "npx",
"args": ["-y", "serper-search-mcp"],
"env": {
"SERPER_API_KEY": "${SERPER_API_KEY}",
"TAVILY_API_KEY": "${TAVILY_API_KEY}",
"BRAVE_API_KEY": "${BRAVE_API_KEY}",
"EXA_API_KEY": "${EXA_API_KEY}",
"FIRECRAWL_API_KEY": "${FIRECRAWL_API_KEY}",
"OPENROUTER_API_KEY": "${OPENROUTER_API_KEY}",
"SEARCH_PROVIDER_ORDER": "serper,tavily,brave,exa",
"SEARCH_FALLBACK": "true"
}
}
}
}
```
*(You can omit any provider keys you don't use; the server automatically detects configured providers and skips unconfigured ones).*
#### Minimal Config (Serper Only):
```json
{
"mcpServers": {
"serper-search": {
"command": "npx",
"args": ["-y", "serper-search-mcp"],
"env": {
"SERPER_API_KEY": "your_serper_key_here"
}
}
}
}
```
---
### Option 2 β Docker
```bash
docker run -i --rm \
-e SERPER_API_KEY \
-e TAVILY_API_KEY \
-e BRAVE_API_KEY \
-e EXA_API_KEY \
-e FIRECRAWL_API_KEY \
-e OPENROUTER_API_KEY \
smjahid/server-serper-search:4
```
For HTTP mode (remote server or cloud):
```bash
docker run --rm -p 8080:8080 \
-e SERPER_API_KEY \
-e SERPER_MCP_TRANSPORT=http \
-e SERPER_MCP_HOST=0.0.0.0 \
-e SERPER_MCP_AUTH_TOKEN="your_secure_bearer_token" \
smjahid/server-serper-search:4
```
---
### Option 3 β Shell & CLI (PowerShell / Bash / CMD)
**PowerShell (Windows):**
```powershell
$env:SERPER_API_KEY = "your_key"
$env:TAVILY_API_KEY = "your_key" # optional
$env:OPENROUTER_API_KEY = "your_key" # optional
node index.js
```
**Bash / macOS / Linux:**
```bash
export SERPER_API_KEY="your_key"
export TAVILY_API_KEY="your_key" # optional
export OPENROUTER_API_KEY="your_key" # optional
node index.js
```
**Windows Command Prompt:**
```bat
set SERPER_API_KEY=your_key
node index.js
```
> **π‘ AI-powered research is free.** `deep_research` uses Gemini's free tier by default. Set `GEMINI_API_KEY` above to unlock it.
---
## Config file locations
| Client | Config path |
|---|---|
| **Claude Desktop (Mac)** | `~/Library/Application Support/Claude/claude_desktop_config.json` |
| **Claude Desktop (Win)** | `%APPDATA%\Claude\claude_desktop_config.json` |
| **Cursor** | `~/.cursor/mcp.json` |
| **Windsurf** | `~/.codeium/windsurf/mcp_config.json` |
| **KiloCode** | `~/.config/kilo/kilo.json` (global) or `<project>/kilo.json` (project) |
| **n8n** | MCP Client node β Server URL |
---
## Tool reference
### `search_web`
Google web search with the full SERP breakdown.
```jsonc
{
"query": "best mechanical keyboards 2025", // required
"num_results": 10, // 1β20, default 10
"country": "US", // ISO 3166-1 alpha-2
"search_lang": "en", // language code
"freshness": "pw", // "pd" day Β· "pw" week Β· "pm" month Β· "py" year
"safesearch": "moderate",// "off" Β· "moderate" Β· "strict"
"autocorrect": true,
"summary": false, // Serper AI summary
"page": 1, // pagination
"link_resolution": "auto" // "auto" Β· "all" Β· "none" β see Google redirect links below
}
```
**Response includes:**
- π― **Answer Box** β direct answer when available
- π§ **Knowledge Graph** β entity info (type, description, rating, website, attributes)
- π **Organic results** β title, URL, snippet, sitelinks, date
- π¬ **People Also Ask** β up to 4 follow-up questions with answers
- π **Related Searches** β up to 6 suggestions
---
### `search_images`
```jsonc
{
"query": "minimalist desk setup",
"num_results": 10,
"country": "US",
"safesearch": "moderate"
}
```
Returns: image URL, thumbnail, dimensions (width Γ height), source domain, source page URL.
---
### `search_videos`
```jsonc
{
"query": "react server components tutorial",
"num_results": 5,
"freshness": "pm"
}
```
Returns: title, channel, duration, publish date, video URL.
---
### `search_news`
```jsonc
{
"query": "OpenAI GPT-5 release",
"num_results": 10,
"freshness": "pd", // default is past day for news
"country": "US"
}
```
Returns: headline, source publication, date, snippet, URL.
---
### `search_shopping`
```jsonc
{
"query": "Sony WH-1000XM5 headphones",
"num_results": 8,
"country": "US"
}
```
Returns: product name, price, seller, star rating + review count, delivery info, product URL.
---
### `search_places` β unique to this server
```jsonc
{
"query": "ramen restaurants in Shibuya Tokyo",
"num_results": 5,
"country": "JP"
}
```
Returns: business name, category, address, phone, website, star rating + review count, opening hours, GPS coordinates + Google Maps link.
**Example use cases:**
- "Find the top-rated coffee shops near Times Square"
- "What dentists are open on Sundays in Austin TX?"
- "List coworking spaces in Dhaka"
---
### `search_scholar` π v4.0.0
Google Scholar search for academic literature.
```jsonc
{
"query": "attention is all you need",
"num_results": 10,
"country": "US"
}
```
Returns: title, link, authors/journal/year (`publicationInfo`), snippet, and citation count.
---
### `scrape` π v4.0.0
Fetch the full contents of a single URL (Serper Scrape API β `scrape.serper.dev`).
```jsonc
{
"url": "https://example.com/article", // required
"include_markdown": true, // default true β markdown rendering
"include_images": false,
"include_links": false,
"include_videos": false,
"max_chars": 50000 // 1000β200000, default 50000
}
```
Returns the page as markdown (falls back to plain text), truncated for context safety. Costs ~2 credits per page β typical flow is `search_web` β `scrape` the best result.
---
### `search_many` π v4.0.0
Run 1β10 web searches in one call, in parallel.
```jsonc
{
"queries": ["react server components", "vue server components", "sveltekit ssr"],
"num_results": 5,
"country": "US"
}
```
Duplicate URLs across queries are removed automatically; per-query failures are reported inline without failing the batch. One credit per query.
---
### Google redirect links & `resolve_links` π
Since 2026-10-30, Serper may return Google result links beyond the top 3 as `https://www.google.com/goto?url=β¦` redirects. Opening one right after the search lands on Google's "Verifying your request" page instead of the site. Serper's free `/resolve` endpoint turns them back into real URLs ([serper.dev/google-links](https://serper.dev/google-links)).
`search`, `search_web`, `search_images`, `search_videos`, `search_news`, `search_shopping` and `search_rag_context` take a `link_resolution` parameter:
| Mode | Behaviour |
|---|---|
| `auto` (default) | Serper's default: top 3 resolved. If the shown results still contain redirect links, the output says how many and gives a `search_id`. |
| `all` | Also calls `/resolve` before returning. Free, but adds ~20β30 s when redirect links are present. |
| `none` | Sends `resolveLinks: false`: fastest, links exactly as Google returns them. |
`resolve_links` resolves a search later by `search_id` (the last 50 searches with redirect links are kept in memory) or from a list of goto links:
```jsonc
{ "search_id": "Xq3vβ¦" } // re-renders that search with real URLs
{ "links": ["https://www.google.com/goto?url=β¦"], "max_wait_seconds": 60 }
```
Links that are not ready yet stay goto links and Serper suggests a wait (often 90 s); it is honoured only if it fits in `max_wait_seconds`. `/resolve` failures never fail a search: the original results are kept and the error is shown. `deep_research` resolves its sources before building the prompt and lists any citation that is still a redirect.
---
## Environment variables
### Search Providers & Universal Gateway
| Variable | Required | Default | Description |
|---|---|---|---|
| `SERPER_API_KEY` | β
| β | Primary search provider key ([serper.dev](https://serper.dev) β 2,500 free queries/mo) |
| `TAVILY_API_KEY` | β | β | Tavily fallback provider key ([tavily.com](https://tavily.com) β AI-reranked search) |
| `BRAVE_API_KEY` | β | β | Brave Search fallback provider key ([brave.com/search/api](https://brave.com/search/api) β independent index) |
| `EXA_API_KEY` | β | β | Exa neural search fallback key ([exa.ai](https://exa.ai) β semantic search & highlights) |
| `FIRECRAWL_API_KEY` | β | β | Firecrawl JS-rendered scraping & search upgrade key ([firecrawl.dev](https://firecrawl.dev)) |
| `SEARCH_PROVIDER_ORDER` | β | `serper,tavily,brave` | Comma-separated failover priority chain (`serper,tavily,brave,exa,firecrawl`) |
| `SEARCH_FALLBACK` | β | `true` | Auto-failover on 402/429/5xx/empty response (`true` or `false`) |
### Server & Transport
| Variable | Required | Default | Description |
|---|---|---|---|
| `SERPER_MCP_TRANSPORT` | β | `stdio` | MCP transport mode: `stdio` (local AI clients) or `http` (stateless Streamable HTTP) |
| `SERPER_MCP_PORT` | β | `8080` | Port for HTTP transport mode (1β65535) |
| `SERPER_MCP_HOST` | β | `0.0.0.0` | Host interface to bind for HTTP mode |
| `SERPER_MCP_AUTH_TOKEN` | β | β | If set, HTTP `/mcp` requires `Authorization: Bearer <token>` |
| `SERPER_MCP_LOG_LEVEL` | β | `info` | Logging verbosity: `error` Β· `warn` Β· `info` Β· `debug` Β· `silent` |
### Cache & Resilience Tuning
| Variable | Required | Default | Description |
|---|---|---|---|
| `SERPER_CACHE_TTL_MS` | β | `600000` | Search-result cache TTL in ms (`0` disables the cache) |
| `SERPER_CACHE_MAX` | β | `200` | Maximum cached responses (LRU eviction) |
| `SERPER_TIMEOUT_MS` | β | `30000` | Per-request timeout for Serper calls in ms |
| `SERPER_RETRIES` | β | `2` | Retries on 429 / 5xx / network errors (honors `Retry-After`) |
| `SERPER_RETRY_BASE_MS` | β | `500` | Base backoff delay in ms (exponential backoff + jitter) |
| `SERPER_LINK_RESOLUTION` | β | `auto` | Default `link_resolution` mode: `auto` Β· `all` Β· `none` |
| `SERPER_RESOLVE_MAX_WAIT` | β | `60` | Seconds `/resolve` may keep retrying when Serper says to wait |
### Deep Research LLM Synthesis
| Variable | Required | Default | Description |
|---|---|---|---|
| `OPENROUTER_API_KEY` | β | β | LLM key for `deep_research` synthesis (free tier at [openrouter.ai](https://openrouter.ai)) |
| `OPENROUTER_MODEL` | β | `google/gemini-3.1-flash-lite:free` | OpenRouter model override |
| `GEMINI_API_KEY` | β | β | LLM key for `deep_research` synthesis (free tier at [ai.google.dev](https://ai.google.dev)) |
| `GEMINI_MODEL` | β | `gemini-3.1-flash-lite` | Gemini model override |
| `SERPER_LLM_TIMEOUT_MS` | β | `120000` | Per-request timeout for LLM synthesis calls in ms |
| `SERPER_LLM_RETRIES` | β | `2` | Retries for LLM calls on rate-limit or network errors |
---
## HTTP transport (remote / Docker)
Run as a stateless Streamable HTTP server (this is also how the Docker image runs):
```bash
npx serper-search-mcp --transport http --port 8080
# or via env: SERPER_MCP_TRANSPORT=http SERPER_MCP_PORT=8080 npx serper-search-mcp
```
- MCP endpoint: `POST http://localhost:8080/mcp`
- Health probe: `GET http://localhost:8080/health`
Point any Streamable HTTP capable MCP client at `http://<host>:8080/mcp`.
### Optional bearer auth
Set `SERPER_MCP_AUTH_TOKEN` (or `--auth-token`) to require authentication on `/mcp`:
```bash
SERPER_MCP_AUTH_TOKEN=secret npx serper-search-mcp --transport http --port 8080
```
```bash
curl -X POST http://localhost:8080/mcp \
-H "Authorization: Bearer secret" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
```
Requests without the token get `401`. `/health` stays unauthenticated for load balancers and reports `auth_required`.
---
## Example prompts
Once connected to any MCP client:
```
Search for the latest news about Claude 4 and summarize the key points.
Find me 5 Italian restaurants in Warsaw with their ratings and phone numbers.
What is the current price of the MacBook Pro M4 on Google Shopping?
Search for YouTube tutorials on building agentic AI systems published this month.
Find images of brutalist architecture in Eastern Europe.
```
---
---
## `deep_research`
Runs multi-step AI research using your own LLM key. No LLM data leaves your environment.
**Requires:** `OPENROUTER_API_KEY` (free models at [openrouter.ai](https://openrouter.ai)) or `GEMINI_API_KEY` (free at [aistudio.google.com](https://aistudio.google.com))
```jsonc
{
"query": "What are the real-world limitations of RAG systems in production?",
"depth": "standard", // "basic" | "standard" | "deep"
"country": "US"
}
```
| Depth | Sub-queries | Results each | Best for |
|---|---|---|---|
| `basic` | 3 | 3 | Quick overviews |
| `standard` | 5 | 5 | Most use cases |
| `deep` | 8 | 7 | Exhaustive research |
**Output:** Structured markdown report with inline citations + Sources section.
**Supported LLMs via env (all vars documented in the [table above](#environment-variables)):**
| Provider | Variable | Default |
|---|---|---|
| OpenRouter | `OPENROUTER_API_KEY` | β |
| | `OPENROUTER_MODEL` | `google/gemini-3.1-flash-lite:free` |
| Google Gemini | `GEMINI_API_KEY` | β |
| | `GEMINI_MODEL` | `gemini-3.1-flash-lite` |
---
## `search_rag_context`
Turns Google search results into embedding-ready chunks. No LLM needed β pure text processing.
```jsonc
{
"query": "transformer architecture explained",
"num_results": 10,
"max_chunk_words": 200,
"include_paa": true,
"output_format": "json" // "json" or "text"
}
```
**JSON output** (for vector DB ingestion):
```json
{
"query": "transformer architecture explained",
"total_sources": 10,
"total_chunks": 24,
"total_words": 4231,
"chunks": [
{
"chunk_index": 0,
"source_index": 1,
"title": "Attention Is All You Need",
"url": "https://arxiv.org/abs/1706.03762",
"domain": "arxiv.org",
"date": "2024-01-15",
"text": "The transformer architecture uses self-attention mechanisms...",
"word_count": 198,
"char_count": 1124
}
]
}
```
**Text output** (for direct prompt injection):
```
--- Chunk 1 | Source 1 | arxiv.org | 2024-01-15 ---
Title: Attention Is All You Need
URL: https://arxiv.org/abs/1706.03762
The transformer architecture uses self-attention...
```
**Use cases:**
- Feed into Chroma, Pinecone, Qdrant, pgvector
- Ground prompts with fresh web data
- Build search-augmented RAG pipelines
---
## Architecture
```
serper-search-mcp-server/
βββ index.js β Zero-build JS entry (npx / Docker) β generated from src/ via `npm run bundle`; never edit by hand
βββ src/
β βββ index.ts β TypeScript CLI entry
β βββ api/
β β βββ SerperAPI.ts β HTTP client (per-type endpoints, retry, timeout, TTL cache, scrape)
β β βββ LLMClient.ts β OpenRouter + Gemini client
β βββ server/
β β βββ SerperMCPServer.ts β MCP server, stdio + HTTP transport, bearer auth
β βββ tools/
β β βββ SearchTools.ts β All 15 tool definitions + validation
β β βββ BatchSearch.ts β search_many (parallel + dedupe)
β β βββ DeepResearch.ts β Multi-step research orchestration
β β βββ RAGContext.ts β Chunk + metadata formatter
β β βββ ResolveLinks.ts β link_resolution modes + resolve_links (Serper /resolve)
β βββ types/
β β βββ index.ts β Full TypeScript types
β βββ utils/
β βββ ResultFormatter.ts β Markdown formatting
β βββ HttpRetry.ts β Timeout + retry/backoff
β βββ TtlCache.ts β TTL + LRU cache
β βββ Logger.ts β Leveled stderr logger (+ request-id)
β βββ errors.ts β Typed error hierarchy
β βββ Metrics.ts β /health counters
β βββ EnvCheck.ts β Boot-time env validation
βββ scripts/
β βββ bundle.mjs β Builds index.js from src/ (`--check` mode for CI)
βββ tests/ β node:test suite (58 tests)
βββ .github/workflows/ci.yml β Node 18/20/22: build + bundle check + tests
```
**Dual-file design:** `index.js` runs without any build step (ideal for `npx` and Docker) and is generated from `src/` β the TS tree is the only source of truth. `npm run check:bundle` fails CI if they drift.
---
## Get a Serper API key
1. Go to [serper.dev](https://serper.dev)
2. Sign up (free β no credit card)
3. Copy your API key from the dashboard
4. You get **2,500 free queries/month**
---
## Version evolution
| Feature | v1.0.0 | v2.0.1 | v3.0.0 | v4.0.0 |
|---|---|---|---|---|
| **Total tools** | 5 | 5 | 8 | 14 |
| `search` (unified) | β | β | β | β
auto-verbosity + provider failover |
| `search_web` | β
organic only | β
organic only | β
+ Answer Box, Knowledge Graph, PAA, Related | β
|
| `search_images` | β
| β
| β
+ dimensions, domain | β
+ gallery layout |
| `search_videos` | β
| β
| β
+ date field | β
|
| `search_news` | β
| β
| β
cleaner formatting | β
+ past-day default |
| `search_shopping` | β
| β
| β
+ delivery, offers | β
(always rich) |
| `search_places` | β | β | β
address, phone, hours, GPS, Maps link | β
+ full 7-day hours, directions |
| `search_scholar` | β | β | β | β
papers + citation counts |
| `search_patents` | β | β | β | β
publication, assignee, dates |
| `autocomplete` | β | β | β | β
fast query completions |
| `scrape` | β | β | β | β
full page β markdown |
| `search_many` | β | β | β | β
batch + cross-query dedupe |
| `deep_research` | β | β | β
sub-queries β parallel search β LLM report | β
|
| `search_rag_context` | β | β | β
chunked text + metadata, JSON/text output | β
|
| **API endpoints** | all hitting `/search` with `tbm` param | all hitting `/search` with `tbm` param | β
correct per-type endpoints | β
+ scholar + scrape host |
| **Answer Box / KG / PAA** | β | β | β
full SERP extraction | β
|
| **Pagination** | β | β | β
`page` param | β
|
| **Autocorrect param** | β | β | β
| β
|
| **LLM support** | β | β | β
OpenRouter + Gemini (user's own key) | β
|
| **LLM-free RAG output** | β | β | β
JSON + plain text | β
|
| **TypeScript types** | partial (heavy `any`) | partial (heavy `any`) | β
full types for every result shape | β
+ scholar/scrape |
| **MCP SDK version** | ^0.5.0 | ^0.5.0 or ^1.0.0 | ^1.0.0 | ^1.0.0 |
| **Node requirement** | >=16 | >=16 | >=18 (native `fetch`, no axios) | >=18 |
| **HTTP transport** | β | β
| β
| β
stateless Streamable HTTP |
| **HTTP bearer auth** | β | β | β | β
optional |
| **Retry + timeout** | β | β | β | β
429/5xx/network |
| **Response cache** | β | β | β | β
TTL + LRU |
| **Log levels** | β | β | β | β
error/warn/info/debug/silent |
| **Tests + CI** | β | β | β | β
node:test + GitHub Actions |
| **Docker** | β | β
| β
| β
|
| **npx** | β | β
| β
| β
|
| **Client configs** | Claude Desktop only | Claude Desktop + a few | Claude Desktop + Cursor + Windsurf + KiloCode + n8n | β
|
| **Telemetry** | β none | β none | β none (intentional β privacy win) | β none |
---
## Changelog
### v4.0.0 β Universal Search Gateway (Multi-Provider, 14 Tools, CLI, Resilience, Tests)
- β **Universal Multi-Provider Gateway** β failover chain: Serper β Tavily β Brave (+ Exa/Firecrawl) with `provider=all` reciprocal-rank fusion
- β **14 MCP Tools** β including unified `search` (token-smart auto-verbosity), `search_scholar`, `search_patents`, `autocomplete`, `scrape`, `search_many`
- β **Developer CLI** β `search`, `scrape`, `research`, `rag`, `providers`, `status` subcommands
- β **`search_scholar` tool** β Google Scholar with authors, journal, year, citation counts
- β **`scrape` tool** β full page content as markdown via `scrape.serper.dev` (truncation-safe)
- β **`search_many` tool** β 1β10 parallel web searches, cross-query URL dedupe, per-query failure isolation
- β **Retry + timeout** β 429/5xx/network retries with exponential backoff + jitter (Retry-After honored)
- β **Response cache** β in-memory TTL + LRU (`SERPER_CACHE_TTL_MS=0` disables)
- β **Optional HTTP bearer auth** β `SERPER_MCP_AUTH_TOKEN` guards `/mcp`; `/health` stays open
- β **Real log levels** β `SERPER_MCP_LOG_LEVEL` now controls error/warn/info/debug/silent
- β **Test suite + CI** β 58 `node:test` tests (no extra deps, incl. real-HTTP e2e) + GitHub Actions matrix (Node 18/20/22)
- π§ HTTP transport now works on Node 18 β WebCrypto shim for the MCP SDK (`crypto.randomUUID`); Docker base image bumped to `node:20-alpine`
- π§ `search_lang` is now correctly mapped to Serper's `hl` (was previously ignored)
- π§ News results default to past-day freshness as documented
- π§ `max_chunk_words` clamped 50β1000 (fixes a hang on zero/negative values)
- π§ Unknown `depth` falls back to `standard` in `deep_research`
- π§ Unknown tools return `MethodNotFound` instead of `InternalError`
- π§ `--api-key` without a value no longer breaks startup
- π§ `index.js` is generated from `src/` via esbuild; `npm run check:bundle` guards drift
- π§ Windows-compatible npm scripts; `npm audit` reports 0 vulnerabilities
### v3.0.0 β Places + Deep Research + RAG
- β **`search_places` tool** β local businesses with address, phone, hours, GPS
- β **Knowledge Graph** extraction in web search
- β **Answer Box** extraction in web search
- β **People Also Ask** + Related Searches in web results
- β **Pagination** support (`page` param)
- β **`autocorrect`** param on web search
- π§ Corrected per-type Serper endpoints (images/videos/news/shopping now use dedicated endpoints)
- π§ Full TypeScript types for all result shapes
- β **`deep_research` tool** β multi-step research with LLM synthesis (OpenRouter / Gemini)
- β **`search_rag_context` tool** β embedding-ready chunks with metadata (no LLM needed)
- π§ Node β₯ 18 requirement (native `fetch`)
### v2.0.1
- HTTP/SSE transport mode
- Docker Compose support
- CLI flags
### v1.0.0
- Initial release: web, images, videos, news, shopping
---
## Contributing
PRs and issues are welcome. Please open an issue before large changes.
```bash
git clone https://github.com/smjahid012/serper-search-mcp-server.git
cd serper-search-mcp-server
npm install
export SERPER_API_KEY="your_key"
node index.js # test immediately, no build required
```
---
## License
Apache 2.0 β see [LICENSE](LICENSE)
---
<div align="center">
**Built by [SMLabs AI](https://smlabsai.com) Β· [smjahid012](https://github.com/smjahid012)**
If this saved you time, a β on GitHub helps others find it.
</div>
TDQS
Scored across 15 tools
The unified `search` tool with type=web|images|videos|news|shopping|places|scholar|patents|autocomplete directly duplicates eight dedicated sibling tools (search_web, search_images, etc.), so an agent must guess which of two identical capabilities to call. `search_many` overlaps with `search`, `search_rag_context` is `search` with different formatting, and `search`'s deep mode overlaps `deep_research`. Only `scrape`, `autocomplete`, and `resolve_links` have clearly unique boundaries.
All names are snake_case and the dominant pattern is a `search_` prefix plus resource noun, which is easy to scan. The handful of deviations (`search`, `autocomplete`, `scrape`, `deep_research`) are action-distinct rather than arbitrary, so they read fine despite breaking the prefix convention. It also makes `search` vs `search_web` look confusingly similar.
15 tools sit at the upper edge of a well-scoped set, and the surface is inflated by redundancy rather than coverage β the description itself says `search` replaces 11 tools, which implies roughly half the set could be retired. A leaner ~7-tool design (search, scrape, search_many, deep_research, resolve_links, search_rag_context) would serve the same purpose.
The search domain is well covered: web, images, news, videos, shopping, places, scholar, patents, autocomplete, page scraping, batch search, deep research, RAG chunking, and redirect resolution β no obvious dead end in the core workflow. Minor gaps: credits are referenced throughout the descriptions but no tool exposes balance or cache management.