Command Palette

Search for a command to run...

UnylyUnyly
Browse all

Web Search (Brave)

FreeNot checked

Integrates Brave Search API for real-time web information retrieval, dynamically categorizing queries to proactively fetch current events, weather, sports score

GitHubEmbed

About

Integrates Brave Search API for real-time web information retrieval, dynamically categorizing queries to proactively fetch current events, weather, sports scores, and time-sensitive data with robust error handling.

README

An MCP server that gives an assistant live web search, full-page reading, and source citations. Stdio transport, pluggable providers, no scraper dependencies.

Claude Desktop Example

CI License: MIT Node

Quick start · Tools · Configuration · Clients · Security · Changelog


Overview

Five tools: web_search, news_search, image_search, fetch_url, list_providers. Search returns ranked summaries with stable ids; fetch_url reads the page behind any id. Brave Search is the primary provider; DuckDuckGo runs without a key as a fallback.

Requirements

Node.js >= 20.18 (uses native fetch)
npm >= 10
Brave Search API key optional. Without it, DuckDuckGo handles web_search. news_search and image_search require a key.

Quick start

git clone https://github.com/gabrimatic/mcp-web-search-tool.git
cd mcp-web-search-tool
npm install
cp .env.example .env   # edit BRAVE_API_KEY if you have one
npm run build
npm start

Run with Docker:

docker build -t mcp-web-search .
docker run --rm -i -e BRAVE_API_KEY mcp-web-search

For Claude Desktop, Claude Code, Codex, VS Code, Cursor, or Windsurf integration, see MCP_CLIENTS.md.


Tools

Each tool returns two content blocks: a Markdown rendering for the model and a fenced JSON block with the structured payload. Errors come back as isError: true content with an actionable message; only unknown-tool calls throw a protocol error.

web_search

Live web search. Use first for current, source-backed answers.

Parameter Type Description
search_term string, required Query string.
provider enum "brave search" or "duckduckgo". Defaults to Brave when a key is set, otherwise DuckDuckGo.
count int (1–20) Number of results. Default 10.
offset int Pagination offset (web only).
cursor string Opaque cursor from a previous response.
freshness string pd (24h), pw (week), pm (month), py (year), or YYYY-MM-DDtoYYYY-MM-DD.
country string ISO country code.
search_lang string UI language, e.g. en.
safesearch enum off, moderate, strict.
include_domains string[] Restrict results to these hosts.
exclude_domains string[] Drop results from these hosts (hostname-suffix match).

news_search

Recent news with source name and publish date. Brave only.

image_search

Image results with thumbnails. Brave only.

fetch_url

Reads a search result or arbitrary http(s) URL. Pass a result id from a previous search (preferred) or a full URL.

Parameter Type Description
id_or_url string A result id (e.g. r_a1b2c3d4e5f6) or a full http(s) URL.
url string Deprecated alias for id_or_url.
max_chars int (200–200 000) Soft cap on returned characters. Default 8000.
cursor string Cursor from a previous response to continue reading.

Returns the page title, readable text (scripts, styles, nav, footer, and aside stripped), the first 25 outbound links, HTTP status, content-type, byte length, and a nextCursor when truncated.

Refuses non-http(s) schemes and any host that resolves to a private, loopback, link-local, multicast, or IPv4-mapped IPv6 private address. Details: SECURITY.md.

list_providers

Returns the registered providers and the current default. Call this once if you are unsure whether news_search or image_search are available in this session.


Configuration

All configuration is environment-driven. Reference: .env.example.

Variable Default Purpose
BRAVE_API_KEY empty Brave Search API key. When unset, DuckDuckGo is used.
MAX_RESULTS 10 Default result count (clamped 1–50).
REQUEST_TIMEOUT 10000 Per-request timeout in ms (1 000–60 000).
DEFAULT_PROVIDER auto Force a specific provider (e.g. duckduckgo).
ALLOW_KEYLESS true When false, the server refuses to start without BRAVE_API_KEY.
CACHE_MAX_ENTRIES / CACHE_TTL_MS 256 / 300000 Search cache.
FETCH_CACHE_MAX / FETCH_CACHE_TTL_MS 128 / 600000 URL-fetch cache.
FETCH_TIMEOUT_MS / FETCH_MAX_BYTES 15000 / 2000000 Per-request budget for fetch_url.

Project layout

src/
├── index.ts                    MCP server: tool registry, dispatch, rendering
├── config.ts                   env loader, validation, defaults
├── providers/
│   ├── SearchProvider.ts       abstract contract and shared types
│   ├── SearchProviderFactory   registry and default selection
│   ├── BraveSearchProvider     web/news/images via Brave API
│   └── DuckDuckGoProvider      keyless HTML-lite fallback
├── services/
│   ├── SearchService.ts        provider dispatch, LRU+TTL cache
│   └── FetchService.ts         safe URL fetch, readable extraction
└── utils/
    ├── http.ts                 native fetch, retry/backoff/timeout
    ├── html.ts                 zero-dep HTML to text + links
    ├── cache.ts                LRU+TTL cache
    └── ids.ts                  stable result-id minting and resolution
tests/                          vitest suite

Add a provider

import { SearchProvider, SearchResponse, SearchOptions } from './SearchProvider.js';

export class MyProvider extends SearchProvider {
  getName() { return 'My Provider'; }
  override requiresApiKey() { return true; }
  async search(query: string, _opts: SearchOptions = {}): Promise<SearchResponse> {
    const out = this.emptyResponse(query, 'web');
    out.results = mapped; // shape: SearchResult[]
    return out;
  }
}

Register it in SearchProviderFactory.setupDefaults. Result ids are minted automatically when you call mintResultId(url) on each entry.


Development

npm run dev          # tsx watch mode
npm test             # vitest (23 tests)
npm run lint
npm run format
npm run build

CI runs on Node 20, 22, and 24, plus a Docker image build. Tests cover the LRU+TTL cache, HTML extractor, DuckDuckGo parser, search-service caching, HTTP retry/backoff, SSRF guard, domain match, and the result-id resolver.


Example prompts

  • "What are analysts saying about the MVP race after tonight's NBA games?"
  • "Summarise the top three results for RAG benchmarks 2025 and pull the abstract from the first paper."
  • "Find images of the Webb telescope's latest deep field, then open the NASA page and quote the caption."
  • "What's the weather in Berlin right now?"

License

MIT License

Developer

By Soroush Yousefpour

© All rights reserved.

YouTube Video

A short demo of MCP Web Search Tool with Claude:

Claude + MCP Web Search – Live Demo

Medium Article

Background on the project and how it works:

Deep Dive into MCP Web Search Tool

Support

Buy Me A Book

from github.com/gabrimatic/mcp-web-search-tool

Installing Web Search (Brave)

This server has no published package — it is built from source. Open the repository and follow its README.

▸ github.com/gabrimatic/mcp-web-search-tool

FAQ

Is Web Search (Brave) MCP free?

Yes, Web Search (Brave) MCP is free — one-click install via Unyly at no cost.

Does Web Search (Brave) need an API key?

No, Web Search (Brave) runs without API keys or environment variables.

Is Web Search (Brave) hosted or self-hosted?

Self-hosted: the server runs locally on your machine via the install command above.

How do I install Web Search (Brave) in Claude Desktop, Claude Code or Cursor?

Open Web Search (Brave) on unyly.org, pick your client tab (Claude Desktop, Claude Code, Cursor) and press Install — the config is generated automatically, no JSON editing.

Related MCPs

Compare Web Search (Brave) with

Not sure what to pick?

Find your stack in 60 seconds

Author?

Embed badge for your README

Browse similar

All development MCPs