Skip to main content
Glama
maxylev

MCP Server for Stealth Web Search and Fetching

SearchFetch

An MCP server that gives AI agents web search and page fetching through a stealth browser. Pages are rendered with JavaScript, stripped of noise, and returned as compact Markdown.

  • Browser rendering: CloakBrowser runs Chromium with humanized input. Each fetch uses an isolated browser context. Sites may still demand logins or challenges.

  • Fault tolerance: relaunches a disconnected browser and retries timeouts, network failures and HTTP 429 (honoring Retry-After, capped at 30 s) once. Built-in search engines fall back to DuckDuckGo HTML and then DuckDuckGo Lite.

  • Token-efficient output: scripts, styles, SVGs, inline styles and embedded data: images are removed before conversion; images, media and fonts are blocked at the network layer.

  • Template-driven extraction: JSON templates for GitHub, GitLab, npm, PyPI, crates.io, docs.rs, Docker Hub, Wikipedia, MDN, Reddit, YouTube, DEV, pkg.go.dev, Javadoc and generic documentation sites. Custom templates can be passed inline.

  • Two runtimes: Python (uvx, Python 3.11.5+) or Node.js (npx, Node 24+), with the same tools, templates and output. The first run downloads the browser binary.

Setup

No manual install is needed. Point your MCP client at uvx or npx:

{
  "mcpServers": {
    "searchfetch": {
      "command": "uvx",
      "args": ["searchfetch"]
    }
  }
}

For Node.js, use "command": "npx", "args": ["-y", "searchfetch"]. In Cursor, add a command server with uvx searchfetch or npx -y searchfetch.

Related MCP server: markdown-for-agents-mcp

Tools

Both tools are read-only. Failures are returned as MCP tool errors.

websearch

Parameter

Type

Default

Description

query

string

required

Search query (must not be blank).

engine

string

"duckduckgo"

"duckduckgo", "google", a search template name, or an inline JSON template.

region

string/null

null

Region-language code such as "us-en". DuckDuckGo: kl; Google: gl and hl.

safe_search

boolean/null

null

true or false sets the engine's safe search; null keeps the engine default.

max_results

integer

10

Maximum results (positive).

block_media

boolean

true

Block images, media and fonts at the network layer.

Results are a numbered list of titles, URLs and snippets. When an engine fails or returns no results, the next template in its fallback chain is tried (google → duckduckgo-search → duckduckgo-lite-search), and a [websearch: …] note at the top of the output explains why.

webfetch

Parameter

Type

Default

Description

url

string

required

Absolute http/https URL.

template

string

"auto"

"auto" (detect by URL), a template name, or inline JSON template.

start_index

integer

0

Start offset in Unicode code points (non-negative).

max_length

integer

10000

Maximum code points to return (positive).

block_media

boolean

true

Block images, media and fonts at the network layer.

Output ends with a footer naming the template and the character window, plus the next start_index when more content remains. Pages that match no template are converted whole after removing navigation, headers, footers, sidebars, dialogs and media (template="auto (fallback)"). The raw template converts the full <body> with no removal.

Templates

Built-in templates live in templates/ and are shared by both runtimes. Page templates: github-repo, github-issue, npm-package, pypi-package, crates-package, docs-rs, javadoc, docs-page, docker-hub, wikipedia, gitlab, reddit, mdn-web-docs, devto, go-pkg, youtube, raw. Search templates: google-search, duckduckgo-search, duckduckgo-lite-search.

Templates are validated when they are loaded or passed inline:

Field

Description

name

Required unique name (inline templates default to "custom").

sections

Required list of sections (see below).

order

Precedence for auto detection; lower wins.

url_patterns

Regular expressions (compatible with JavaScript and Python) that select the template for auto.

remove

CSS selectors removed before extraction. Defaults to scripts, styles, SVG, nav, footer, iframes.

source_url

Raw Markdown source tried first, e.g. "{url}.md"; HTML responses are ignored.

cookies

Playwright cookies added to the browser context.

block_resources

Resource types blocked when block_media is on. Default: image, media, font.

url_template

Search URL with {placeholders}; makes the template usable by websearch.

url_params

Per placeholder: required, default, and encode: "url".

engine

"duckduckgo" or "google": how region and safe_search map to URL parameters.

fallback

Name of the search template to try when this one fails.

Each section has a name, a selector (empty selects <body>), and optionally format (text, markdown, attribute with attribute, or html), transform (one or a list of strip, decode_google_url, decode_ddg_url, json_parse, resolve_href), required, multiple, max_items, and children (fields extracted from inside each matched element).

Selectors separated by top-level commas are ordered fallbacks: the first selector that matches wins, and an empty fallback selects the current element. Children search inside their parent element and its ancestors, never neighbouring results, so a missing field stays missing. Missing required sections or fields are reported as errors.

A records section whose first item has Author/User and Comment/Body fields is rendered as a comment thread; other records render as indented Key: value blocks.

Development

npm ci && uv sync --locked --extra dev
git config core.hooksPath .githooks   # optional: format, lint and unit tests before commits

npm test               # Node (node:test) and Python (pytest) unit tests
npm run lint           # ESLint and Ruff
npm run format         # Prettier and Ruff format (format:check to verify)
npm run e2e            # real browser against local fixtures, plus the packed npm and wheel builds
npm run check          # everything CI runs
npm run inspect:node   # MCP Inspector (inspect:py for Python)

Layout

Path

Contents

src/

Node.js runtime (index.js is the searchfetch executable).

searchfetch/

Python package (python -m searchfetch or the searchfetch script).

templates/

Shared templates; bundled into the npm package and the Python wheel.

tests/fixtures/

Shared fixtures that keep both runtimes' extraction and output identical.

tests/node, tests/python

Unit tests.

tests/e2e/

MCP end-to-end tests over stdio against a local HTTP server.

The runtimes mirror each other module for module (templates, extract, markdown, compose, browser, server). Any change to one should be made to the other, with a shared fixture if the behavior is observable.

Releasing

Bump version in both package.json and pyproject.toml (then npm install and uv lock), commit, and push a matching tag:

git tag -a v4.0.1 -m "v4.0.1" && git push origin main v4.0.1

The Publish workflow checks that the tag matches both versions, runs lint and unit tests, publishes to npm and PyPI, and then creates the GitHub Release with generated notes. To retry a tag, run the workflow manually from the Actions tab with that tag.

Limits

  • HTML-to-Markdown conversion uses turndown (Node) and markdownify (Python). They agree on common content, but edge cases such as tables differ.

  • After the DOM is ready, each fetch waits up to five seconds for network activity to settle. Pages that keep rendering after that may return partial content.

  • E2E tests use local fixtures. Live search-engine availability and third-party page layouts change over time and need separate live checks.

Available Tools

2 tools
webfetchWeb FetchA
Read-only

Fetch a web page in a JavaScript-capable stealth browser and return its main content as Markdown, with images, scripts and styles stripped. Long output is paginated.

NameRequiredDescriptionDefault
urlYesAbsolute http(s) URL of the page to fetch.
templateNo'auto' (detect from the URL), a template name (github-repo, github-issue, npm-package, pypi-package, crates-package, docs-rs, javadoc, docs-page, docker-hub, wikipedia, gitlab, reddit, mdn-web-docs, devto, go-pkg, youtube, raw), or an inline JSON template. 'raw' converts the whole page with minimal filtering.auto
max_lengthNoMaximum characters to return. Default: 10000.
block_mediaNoBlock images, media and fonts at the network layer. Default: true.
start_indexNoOffset in characters (Unicode code points) for pagination. Default: 0.

TDQS

A3.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and openWorldHint, so the safety profile is covered. The description adds genuinely useful behavior beyond that: rendering happens in a JavaScript-capable stealth browser, output is reduced to main content as Markdown with images/scripts/styles stripped, and long results are paginated. It stops short of rate limits, auth, or how pagination should be driven.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tightly packed sentences with no filler, front-loading the core action before the extraction and pagination details. Every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description carries the return-value burden and does so: Markdown main content, stripped media, paginated output. All five parameters are schema-documented and annotations cover the open-world read-only nature. Minor gaps are error behavior and how to continue pagination.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all five parameters are documented in the schema itself, which sets the baseline at 3. The description's only parameter-relevant additions are the Markdown/media-stripping behavior (mapping loosely to block_media) and 'Long output is paginated' (mapping to start_index/max_length), neither of which adds syntax or semantics beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description gives a specific verb ('Fetch') and resource ('a web page') plus the processing pipeline (JS-capable stealth browser, main content as Markdown, media stripped). This clearly separates it from the sibling websearch, though it never names websearch explicitly as the search-oriented alternative.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied: you call this when you have a URL whose page content you want. There is no statement of when to prefer this over websearch, no prerequisites, and no mention of failure modes for unreachable or JS-blocked pages.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

websearchWeb SearchB
Read-only

Search the web with DuckDuckGo or Google and return numbered results with titles, URLs and snippets.

NameRequiredDescriptionDefault
queryYesThe search query.
engineNo'duckduckgo' (default), 'google', a search template name, or an inline JSON search template. Built-in engines fall back to DuckDuckGo when unavailable.duckduckgo
regionNoRegion-language code such as 'us-en' or 'de-de'. DuckDuckGo uses it as-is; Google maps it to country (gl) and language (hl). Default: engine default.
block_mediaNoBlock images, media and fonts at the network layer. Default: true.
max_resultsNoMaximum results to return. Default: 10.
safe_searchNoEnable (true) or disable (false) safe search. Default: engine default.

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and openWorldHint, so the safety profile is covered. The description usefully adds the output format (numbered results with titles, URLs, snippets), but says nothing about pagination, result limits, or rate behavior beyond what the schema's max_results covers.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single well-formed sentence that front-loads the action and resource, with no wasted words. Nothing is padded or redundant.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a straightforward read-only search tool with no output schema, the description conveys the essential action and return format, and annotations plus a 100%-documented schema carry the rest. Only the search-vs-fetch routing is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 100% schema description coverage, the schema already documents all six parameters in detail (engine fallback, region mapping, block_media, safe_search). The description adds no parameter-specific meaning beyond that baseline, so a 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (search) and resource (the web), names the supported engines, and describes the return shape (numbered results with titles, URLs, snippets). It clearly differs from webfetch, though the differentiation is left implicit 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.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no guidance on when to use this versus the sibling webfetch, nor any prerequisites or exclusions. The agent must infer the search-vs-fetch distinction on its own.

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.

  1. 2 tool updatesv4.0.0
    • Changedwebfetch5 fields changed
      • changedInput schema / properties / block_media / description
        Previous value: -"Block images, videos, and fonts entirely at the network layer. Default is true."New value: +"Block images, media and fonts at the network layer. Default: true."
      • changedInput schema / properties / max_length / description
        Previous value: -"Maximum characters to return per request. Default is 10000."New value: +"Maximum characters to return. Default: 10000."
      • changedInput schema / properties / start_index / description
        Previous value: -"Character offset for pagination. Default: 0."New value: +"Offset in characters (Unicode code points) for pagination. Default: 0."
      • changedInput schema / properties / template / description
        Previous value: -"Template to use: 'auto' (auto-detect from URL), a built-in page template name (wikipedia, reddit, mdn-web-docs, gitlab, youtube, devto, go-pkg, javadoc, github-repo, github-issue, npm-package, pypi-package, crates-package, docker-hub, docs-rs, docs-page), 'raw' for minimal-filtering full-page output, or inline JSON."New value: +"'auto' (detect from the URL), a template name (github-repo, github-issue, npm-package, pypi-package, crates-package, docs-rs, javadoc, docs-page, docker-hub, wikipedia, gitlab, reddit, mdn-web-docs, devto, go-pkg, youtube, raw), or an inline JSON template. 'raw' converts the whole page with minimal filtering."
      • changedInput schema / properties / url / description
        Previous value: -"The full URL of the webpage to fetch (must start with http/https)."New value: +"Absolute http(s) URL of the page to fetch."
    • Changedwebsearch6 fields changed
      • changedInput schema / properties / block_media / description
        Previous value: -"Block images, videos, and fonts entirely at the network layer. Default is true."New value: +"Block images, media and fonts at the network layer. Default: true."
      • changedInput schema / properties / engine / description
        Previous value: -"Search engine to use. Can be 'duckduckgo' or 'google'. Default is 'duckduckgo'."New value: +"'duckduckgo' (default), 'google', a search template name, or an inline JSON search template. Built-in engines fall back to DuckDuckGo when unavailable."
      • changedInput schema / properties / max_results / description
        Previous value: -"Maximum number of search results to return. Default is 10."New value: +"Maximum results to return. Default: 10."
      • changedInput schema / properties / query / description
        Previous value: -"The search query string."New value: +"The search query."
      • changedInput schema / properties / region / description
        Previous value: -"Region and language code to localize search results (e.g., 'us-en', 'uk-en', 'de-de'). For DuckDuckGo it maps directly. For Google, 'us' is country code and 'en' is language. Default is null (uses template default)."New value: +"Region-language code such as 'us-en' or 'de-de'. DuckDuckGo uses it as-is; Google maps it to country (gl) and language (hl). Default: engine default."
      • changedInput schema / properties / safe_search / description
        Previous value: -"Enable safe search filtering. null = use template default. Applies to both DuckDuckGo and Google."New value: +"Enable (true) or disable (false) safe search. Default: engine default."
  2. 2 tool updatesv3.3.4
    • Changedwebfetch7 fields changed
      • addedInput schema / properties / max_length / exclusiveMinimum
        Added value: +0
      • addedInput schema / properties / max_length / maximum
        Added value: +9007199254740991
      • changedInput schema / properties / max_length / type
        Previous value: -"number"New value: +"integer"
      • addedInput schema / properties / start_index / maximum
        Added value: +9007199254740991
      • addedInput schema / properties / start_index / minimum
        Added value: +0
      • changedInput schema / properties / start_index / type
        Previous value: -"number"New value: +"integer"
      • addedInput schema / properties / url / format
        Added value: +"uri"
    • Changedwebsearch8 fields changed
      • addedInput schema / properties / max_results / exclusiveMinimum
        Added value: +0
      • addedInput schema / properties / max_results / maximum
        Added value: +9007199254740991
      • changedInput schema / properties / max_results / type
        Previous value: -"number"New value: +"integer"
      • addedInput schema / properties / query / minLength
        Added value: +1
      • removedInput schema / properties / region / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedInput schema / properties / region / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedInput schema / properties / safe_search / anyOf
        Removed value: -[
        -  {
        -    "type": "boolean"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedInput schema / properties / safe_search / type
        Added value: +[
        +  "boolean",
        +  "null"
        +]
  3. 2 tool updatesv3.3.2
    • First observedwebfetch
    • First observedwebsearch

TDQS

A3.8/5.0

Scored across 2 tools

Disambiguation5/5

The two tools have clearly distinct purposes: websearch performs discovery (querying DuckDuckGo/Google), while webfetch retrieves and renders a specific URL. There is no plausible overlap or confusion between searching and fetching.

Naming Consistency5/5

Both names follow the identical 'web' + verb convention (websearch, webfetch) in consistent lowercase with no separator. The pattern is fully predictable across the set.

Tool Count4/5

Two tools is minimal but well-matched to a narrow search-and-fetch domain, where each tool maps to a core operation. It is slightly thin (no batch or pagination-control tool), but nothing feels redundant.

Completeness4/5

Search plus JavaScript-capable fetch with pagination covers the essential lifecycle of web retrieval, and the fetch tool handles content normalization. Minor gaps exist around result-count/format control, but core workflows are fully served.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    A production-ready Model Context Protocol server that brings AI-powered web search directly into development environments, providing intelligent search results with proper citations in Claude Desktop, Cursor, or any MCP-compatible client.
    231 npm
    22
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    MCP server for AI agents -- fetch any URL with full JavaScript rendering (Playwright/Chromium) and convert to clean, token-efficient markdown. Works on React, Vue, Angular, and any JS-heavy page. Includes web search, batch fetching, binary file download, LRU cache, SSRF protection, and structured output.
    3 npm
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    MCP server for browser automation with anti-detection. Scout pages, find elements, interact with websites, and monitor network traffic from any AI client that supports the Model Context Protocol.
    21
    1
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    MCP server for web scraping and browser automation, enabling AI agents to extract clean, token-efficient content from web pages.
    1
    MIT