Skip to main content
Glama
DmitriyOT

MCP Web Search Server

by DmitriyOT
README.md
# MCP Web Search Server

MCP server for web search with results optimized for LLMs and advanced bot-detection evasion.

## Features

- **Search**: DuckDuckGo (no API key), Serper.dev, Bing Web Search
- **Search aggregation**: `fallback` mode or `merge` mode that queries multiple providers in parallel, deduplicates and ranks results by query relevance
- **Content extraction**: Headless browser with stealth injection, browser page pool, and plain HTTP text fallback when pages are blocked
- **Anti-detection**: Dynamic fingerprint generation (viewport, UA, locale, timezone), human-like behavior, proxy support
- **LLM formatting**: Clean markdown via Turndown, metadata, structured data, links, images, PDF text extraction
- **OCR**: Extract text from image URLs using `tesseract.js`
- **Broken link checker**: Scan a page and report the status of its outgoing links
- **Robustness**: Retry with exponential backoff, circuit breaker per provider, token-bucket rate limiting, concurrency limiting, in-flight request deduplication, persistent cache, graceful shutdown
- **Observability**: Structured JSON logging via Pino, latency/error metrics per provider and fetch operation
- **Config hot reload**: `.env` changes are picked up automatically while the server is running
- **Multiple transports**: stdio (default) or HTTP Streamable MCP transport

## Installation

```bash
npm install
npm run build
```

## Configuration

Copy `.env.example` to `.env` and configure:

```env
# Search providers (optional — DuckDuckGo works without API keys)
SERPER_API_KEY=your_key
BING_API_KEY=your_key

# Search aggregation: "fallback" or "merge"
SEARCH_MERGE_MODE=fallback

# Rate limits (requests per second per provider)
SERPER_RATE_LIMIT=10
BING_RATE_LIMIT=10
DUCKDUCKGO_RATE_LIMIT=1

# Anti-detect
STEALTH_ENABLED=true
HEADLESS=true
PROXY_LIST=http://proxy1:8080,http://proxy2:8080
USER_DATA_DIR=

# Browser page pool size
BROWSER_POOL_SIZE=2

# Limits
MAX_RESULTS=10
MAX_CONTENT_LENGTH=8000
MAX_RESPONSE_SIZE_BYTES=10000000
REQUEST_TIMEOUT=30000
CACHE_TTL=300

# Behavior
MIN_DELAY=500
MAX_DELAY=3000
MAX_CONCURRENT=2
SCROLL_TO_BOTTOM=true

# Fetch fallback when the browser is blocked
TEXT_FETCH_FALLBACK=true

# Optional persistent cache directory
CACHE_DIR=./cache

# Logging
LOG_LEVEL=info

# Transport: stdio or http
MCP_TRANSPORT=stdio
HTTP_HOST=127.0.0.1
HTTP_PORT=8080

# Ethics / safety
ROBOTS_TXT_ENABLED=true
ALLOWED_DOMAINS=
BLOCKED_DOMAINS=

# Debug only — weakens browser security
ALLOW_INSECURE_BROWSER_FLAGS=false
```

## MCP Tools

### `web_search`

Search by query.

```json
{
  "query": "latest AI developments 2025",
  "num_results": 10,
  "provider": "auto",
  "recency_days": 7
}
```

### `fetch_url`

Fetch and clean a page.

```json
{
  "url": "https://example.com/article",
  "max_length": 8000,
  "include_images": false,
  "include_links": false
}
```

### `search_and_fetch`

Search and automatically fetch top-N results.

```json
{
  "query": "quantum computing breakthrough",
  "num_results": 5,
  "fetch_content": true,
  "max_content_length": 5000,
  "include_images": false,
  "include_links": false
}
```

### `health_check`

Check provider availability, circuit breaker state, and rate limits.

```json
{}
```

### `ocr_image`

Extract text from an image URL.

```json
{
  "url": "https://example.com/screenshot.png",
  "language": "eng"
}
```

### `check_links`

Fetch a page and check its outgoing links.

```json
{
  "url": "https://example.com/article",
  "max_links": 20
}
```

## Claude Desktop Integration

```json
{
  "mcpServers": {
    "web-search": {
      "command": "node",
      "args": ["C:\\Files\\git\\mcp-web-search\\dist\\index.js"],
      "env": {
        "SERPER_API_KEY": "..."
      }
    }
  }
}
```

## HTTP Transport

Set `MCP_TRANSPORT=http` and `HTTP_PORT=8080`, then point an MCP client that supports Streamable HTTP at `http://127.0.0.1:8080`.

## Anti-Detection & Reliability

The server uses a layered approach:

1. **puppeteer-extra-plugin-stealth** — hides automation fingerprints
2. **Dynamic fingerprint generation** — random Chrome on Windows/macOS/Linux with matching timezone
3. **Browser page pool** — reusable Puppeteer pages to reduce launch overhead
4. **Human-like behavior** — random delays, scroll, mouse events
5. **Proxy support** — random proxy selection from `PROXY_LIST`
6. **Text fetch fallback** — plain HTTP fetch when the headless browser is blocked
7. **Search result merging & ranking** — combine multiple providers and rank by relevance
8. **Circuit breaker** — temporarily disables failing providers
9. **Token-bucket rate limiting** — per-provider rate limiting
10. **Retry & concurrency limiting** — exponential backoff, bounded parallelism, in-flight deduplication
11. **Graceful shutdown** — waits for active requests on SIGINT/SIGTERM
12. **Robots.txt respect** — honors site crawl rules (can be disabled)

## Development

```bash
npm run dev          # watch mode
npm test             # run unit tests
npm run build        # compile TypeScript
npm run lint         # run ESLint
npm run format       # format with Prettier
```

## Docker

```bash
docker build -t mcp-web-search .
docker run --rm -e SERPER_API_KEY=... mcp-web-search
```

## License

MIT

TDQS

A3.5/5.0

Scored across 3 tools

Disambiguation5/5

Each tool serves a clearly distinct purpose: web_search returns a list of results, fetch_url extracts content from a specific URL, and search_and_fetch combines search with automatic fetching. No overlap or ambiguity.

Naming Consistency4/5

Tool names consistently use snake_case and mostly follow a verb_noun pattern (fetch_url, web_search). The exception is search_and_fetch which uses two verbs, but it still clearly conveys its combined functionality.

Tool Count4/5

With 3 tools, the set is on the smaller side but still covers the core needs of web searching and URL fetching. It feels slightly minimal but not insufficient for the stated purpose.

Completeness4/5

The tool surface covers searching, fetching individual pages, and a combined operation. Minor gaps like lacking custom search parameters or batch fetching exist, but the core workflow is functional.

Maintenance

ActivityStale
ResponsivenessNo issues