search-rotation
Use one MCP server to search the web and extract page content across multiple providers with automatic quota-aware rotation and failover.
Run
search_webwith a query, optional result count, preferred engine, and relative or explicit date filters.Run
fetch_urlto retrieve a known http(s) URL as Markdown, with extraction-provider failover and content truncation beyond 50,000 characters.Inspect enabled engines, access modes, rotation order, local usage counters, and quota sources with
get_engine_status.Enable/disable engines, reorder search/fetch rotation, and set daily or monthly per-engine limits with
update_engine_config.Open the local dashboard with
open_dashboardto manage API keys, credentials, strict-free mode, port/access token, quotas, and request history.Use the server locally over stdio or authenticated Streamable HTTP.
Provides web search through DuckDuckGo HTML as one of the supported search providers, with keyless access and integration into the multi-provider rotation and automatic failover system.
Provides web search through Google Programmable Search Engine (PSE) as one of the supported search providers, integrated into the multi-provider rotation with quota-aware ordering and automatic failover.
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., "@search-rotationSearch the web for the latest MCP server updates and summarize the top 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.
One MCP server for web search and page extraction across multiple providers.
Built by Robin Bially.
Rotate across available quotas, automatically fail over when a provider is unavailable, and return consistent results to your AI assistant. A local dashboard lets you manage API keys, reorder engines, check quotas, and inspect request history.
Actual dashboard UI, shown in English with illustrative demo data. Calls and provider budgets are displayed separately; activity bars offer time-window and per-engine details.
Quick start
npm
npx -y search-rotation --http --openRequires Node.js 20.3+. For MCP over stdio, configure your client to run
npx -y search-rotation with no arguments. The server is also listed in the
official MCP Registry
as io.github.robin-bially/search-rotation.
Homebrew
brew install robin-bially/tap/search-rotation
search-rotation --http --openHomebrew installs the required Node.js runtime. For MCP over stdio, configure your
client to run search-rotation with no arguments. See the
Homebrew tap for upgrades and details.
Pinned release from GitHub
npx -y --allow-git=all github:robin-bially/search-rotation-mcp#v0.6.0Use this when you want a fixed version instead of the current npm release.
Add your provider keys in the dashboard, then connect your assistant using the MCP client setup guide for Codex, Claude, Cursor, or OpenCode.
Related MCP server: freeWeb MCP Server
What you get
Search and fetch: independent rotation for web search and Markdown page extraction.
Automatic failover: quota-aware ordering, rate-limit cooldowns, and request timeouts.
Local dashboard: API keys, drag-and-drop engine order, per-engine calls and errors, separate quota balances, and interactive request history.
Local or remote: MCP over stdio or authenticated Streamable HTTP.
Providers: Tavily · Firecrawl · Parallel · Exa · You.com · Google PSE · Jina Reader · DuckDuckGo HTML. Keyless access and quota accounting vary by provider.
MCP tools
search_web · fetch_url · get_engine_status · update_engine_config · open_dashboard
Every name pairs an action with its target. update_engine_config covers what the dashboard's engine list does: enable and disable engines, set the search and fetch rotation order, and set monthly or daily limits per engine. API keys stay in the dashboard. If your client keeps an allowlist of tool names, replace the earlier web_search and engine_status entries there.
searchOrder and fetchOrder must list every search- or fetch-capable engine exactly once. After an upgrade that adds an engine, include its id; the tool names missing ids and writes nothing otherwise.
The dashboard's MCP Tools tab explains each tool, its parameters, and copyable example calls.
Actual dashboard UI, shown in English.
Search time filters
search_web accepts the following arguments:
Parameter | Meaning |
| Required search text. |
| Optional result count, 1–20; otherwise the dashboard setting applies. |
| Preferred provider, subject to time-filter support and availability; failover stays enabled. |
|
|
| Optional lower date bound in |
| Optional upper date bound in |
Use either timeRange or explicit dates. One-sided bounds and equal start/end dates are allowed; invalid calendar dates, reversed bounds, and mixing relative and explicit filters are rejected before any provider request.
{"name":"search_web","arguments":{"query":"AI inference research","timeRange":"week","numResults":5}}{"name":"search_web","arguments":{"query":"AI inference research","startDate":"2026-08-01","endDate":"2026-08-31"}}Relative windows are resolved once per request into UTC dates, including across failover. These are date filters, not exact rolling 24-hour windows; month and year mean 30 and 365 days, not calendar arithmetic. Exa receives the start of the first UTC day and the end of the last UTC day.
Provider support and rotation
Provider / access | Relative window | Two date bounds | One date bound |
Tavily, with or without key | Yes | Yes | Yes |
Firecrawl, with or without key | Yes | Yes | Skipped |
Exa, direct API with key | Yes | Yes | Yes |
Exa, hosted MCP without key | Skipped | Skipped | Skipped |
You.com, with or without key | Yes | Yes | Skipped |
Parallel, either access mode | Skipped | Skipped | Skipped |
Google PSE / DuckDuckGo HTML | Skipped | Skipped | Skipped |
This table describes implemented support in search-rotation, not every upstream feature. Tavily receives start_date / end_date, Firecrawl receives a custom tbs range, Exa receives startPublishedDate / endPublishedDate, and You.com receives a freshness range in YYYY-MM-DDtoYYYY-MM-DD form. Firecrawl and You.com are conservatively excluded for one-sided dates; the other skipped paths have no implemented date mapping.
The router excludes incompatible providers before quota checks and rotation, including when an incompatible engine is preferred. Each eligible provider pool has its own rotation cursor, so mixing filtered and unfiltered searches does not starve providers. Existing quota priorities, cooldowns, strict-free rules, and failover apply within that pool. If no compatible provider is available, the search fails explicitly; it never retries without the filter. Searches without time arguments retain access to all otherwise eligible providers.
Results show a publication date when supplied by the adapter, and request history includes the requested period. Provider date metadata can be estimated or missing: Tavily filters publication or update dates, Exa filters estimated publication dates, and Firecrawl uses its search index's date interpretation. Exact boundary inclusion follows the provider; this is not an independent verification of each page's publication date. See the Tavily, Firecrawl, and Exa references.
After updating, reconnect your MCP client to load the new tool schema.
Releasing
VERSION=0.4.10 ./scripts/release.sh --publishThe script checks the package (npm ci, build, tests, npm run smoke:package), bumps the version, points the document pins at it, commits and tags, packs the tarball with its checksum, creates the GitHub release, updates the formula in robin-bially/homebrew-tap and finally waits until the npm registry serves the new version. Without --publish it only prepares the artifacts in .build/releases; --dry-run checks the prerequisites, --draft creates a draft release and --force tolerates a dirty tree. The tap is cloned temporarily when TAP_DIR is not set, so a fresh checkout is enough.
Publishing to npm happens in .github/workflows/publish.yml through trusted publishing once the GitHub release is published, so the script itself needs no npm credentials. The workflow requires a trusted publisher for search-rotation on npmjs.com that points at this repository and publish.yml.
The same workflow registers the version in the official MCP Registry from server.json. Distribution & listings tracks every channel, who keeps it current, and what each one still needs.
Learn more
Client setup · Operations & configuration (DE) · Distribution & listings · Releases · CI · MIT license
Available Tools
5 toolsfetch_urlFetch URLARead-onlyIdempotent
Fetch one web page and return its main content as Markdown, rotating across extraction providers (Jina Reader, Firecrawl, Parallel, Tavily, Exa) with failover. Use it to read a URL the user or a previous search_web result already names; it does not discover links or crawl a site. Only http and https URLs are accepted. The result names the provider that succeeded, lists failed attempts and truncates content beyond 50,000 characters with a marker; if every provider fails, the tool returns an error listing each provider's reason.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | Absolute http(s) URL of the page to fetch, including scheme and host |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover the safety profile (readOnly, idempotent, openWorld), and the description adds substantial behavior beyond them: provider rotation with failover across five named providers, a 50,000-character truncation with marker, the result naming the successful provider and listing failed attempts, and an all-providers-fail error enumerating each reason. That is exactly the extra context a caller needs.
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 packed sentences, front-loaded with the core action and followed by usage routing and return/error behavior. No filler; every clause conveys operational 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?
With no output schema and a trivial input schema, the description carries the burden and does so: it explains return shape (Markdown content, provider name, failed attempts, truncation marker) and error semantics. Nothing an agent needs to invoke or interpret the call is missing.
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?
Only one parameter at 100% schema coverage, so the schema already documents it fully. The description still adds the accepted-scheme constraint (only http and https), which goes slightly beyond the schema, though URL formatting details remain with the schema.
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+resource (fetch one web page, return main content as Markdown) and explicitly contrasts itself with search_web by declaring it does not discover links or crawl a site. An agent can distinguish it from siblings immediately.
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 the selection condition explicitly: use it to read a URL the user or a previous search_web result already names, with an explicit exclusion (does not discover links or crawl a site). The http/https-only constraint further bounds usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_engine_statusEngine StatusARead-onlyIdempotent
Read this server's local engine configuration: enabled state, configured rotation order, per-capability access (keyless, configured key, or key/extra credentials still required), local usage counters and the quota source per engine. Use it before update_engine_config for valid engine ids, and as the machine-readable answer when you need to know which providers are active, how much quota is left or why a provider is skipped — the dashboard is the human-facing view of the same installation. The tool performs no search and no fetch: it is not a live health check, stored errors are historical observations, and a disabled engine is a configuration state, not proof that a key is missing. Provider balances can come from a cached lookup that the dashboard refreshes; unknown provider limits are reported as null rather than zero or unlimited.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish read-only/idempotent, but the description adds substantial non-obvious behavior: it is not a live health check, stored errors are historical, a disabled engine is not proof of a missing key, provider balances may come from a cached lookup, and unknown limits are reported as null rather than zero or unlimited. These caveats directly prevent misreading the output.
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?
The purpose is front-loaded in the first clause, followed by usage and then caveats, so the ordering is sound. The middle sentence is dense and long, and the description runs as a single paragraph, but nearly every clause carries information an agent needs.
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?
With no output schema and no parameters, the description must convey what comes back, and it does: engine state, rotation order, per-capability credential requirements, counters, and quota source, plus the interpretation caveats. Nothing essential to calling or reading this tool is missing.
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; the input schema is empty and there is nothing for the description to clarify. No credit above baseline is warranted, but there is no gap either.
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+resource ('Read this server's local engine configuration') and immediately enumerates what is returned: enabled state, rotation order, per-capability access, usage counters, quota source. This cleanly distinguishes it from search_web, fetch_url, and open_dashboard.
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?
Explicit when-to-use: 'before update_engine_config for valid engine ids' and 'when you need to know which providers are active, how much quota is left or why a provider is skipped'. It also routes the agent between alternatives, noting the dashboard is the human-facing view of the same data. Nothing 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.
open_dashboardOpen DashboardA
Open the local dashboard of this server in a browser on the machine running the server, for a human: it is the only place to enter API keys and provider credentials, strict-free mode, port and access token, and it shows the interactive usage, quota and request-history views. Use it for those credential and network settings and when a person should look at the data; read configuration with get_engine_status and change engines with update_engine_config instead, because their results are machine-readable and this call only launches a browser. The browser opens on the server host, not on the client's machine, and a server started with --no-dashboard returns an error.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations mark it non-read-only, non-destructive, non-idempotent, but the description adds the traits that actually matter: the browser launches on the server host rather than the caller's machine, this is the only path for entering API keys/provider credentials and strict-free mode, and it errors under --no-dashboard. That is substantive disclosure beyond the structured hints.
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?
Dense and front-loaded — the purpose and the 'for a human' qualifier come first, alternatives second, caveats last. It is a single long run-on sentence with some redundancy, but nearly every clause carries a distinct constraint.
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?
With no parameters and no output schema, the description carries the full burden and does so: it covers what happens on invocation, where the browser opens, the error case, and when to prefer sibling tools.
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. The description adds meaning by explaining what the dashboard UI is for (credentials, port, access token, usage/quota/history views), which is more than an empty schema conveys.
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 ('Open') and resource ('the local dashboard of this server') plus the crucial scope nuance that the browser opens on the server host, not the client. An agent can distinguish it from get_engine_status and update_engine_config without reading any schema.
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?
Explicitly routes: use this for credential/network settings and when a human should view the data, and use get_engine_status or update_engine_config instead for machine-readable reads/writes. It also names the failure condition (server started with --no-dashboard returns an error).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_webWeb SearchARead-onlyIdempotent
Search the web through a rotating pool of search providers (Tavily, Firecrawl, Parallel, Exa, You.com, Google PSE, DuckDuckGo) with automatic failover when one errors, is rate-limited or has no local quota left. Use it when the answer depends on current web pages and no URL is known yet; use fetch_url to read a page whose URL is already known. Returns numbered results (title, URL, snippet, publication date when the provider supplies one) and names the provider that answered plus every failed attempt, so failover stays visible. Time filters keep rotation inside the providers that implement them and fail explicitly instead of searching without the filter; if every eligible provider fails, the tool returns an error listing each provider's reason. The engine parameter only prefers a provider and leaves failover active.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Search query | |
| engine | No | Preferred engine id from get_engine_status; only moves that engine to the front, failover to the others stays active. Engines without implemented support for the time filter are skipped even when preferred. | |
| endDate | No | End date YYYY-MM-DD (through this date, subject to provider boundary semantics). Cannot combine with timeRange. | |
| startDate | No | Start date YYYY-MM-DD. May be used alone or with endDate; cannot combine with timeRange. | |
| timeRange | No | Relative UTC date window: day=1, week=7, month=30, year=365 days through today. Cannot combine with startDate/endDate; day precision, not rolling hours. | |
| numResults | No | Optional result count (1–20). Omit to use the dashboard setting: a custom count or the provider default. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare read-only, open-world, idempotent, non-destructive; the description adds substantial behavior beyond that: automatic failover on error, rate limit or exhausted quota, visibility of every failed attempt and the answering provider, and how time filters constrain rotation. It also documents the failure mode when all eligible providers fail, which is exactly the operational context an agent needs for retry decisions.
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?
The important routing information is front-loaded in the first two sentences, and each subsequent sentence adds a distinct behavioral fact rather than restating the schema. It is dense and slightly long — the provider roster reads as a list dump — but nothing is genuinely wasted.
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 six-parameter tool with no output schema, the description covers what is returned (numbered results with title, URL, snippet, publication date, plus the answering provider and failed attempts) and the error contract. Combined with the fully documented input schema and read-only annotations, an agent has everything needed to invoke it correctly.
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 coverage is 100%, so the baseline is 3, but the description adds genuine meaning the schema does not: the engine parameter only reorders preference while failover stays active, and time filters deliberately fail rather than silently searching unfiltered. The remaining parameters (startDate, endDate, timeRange mutual exclusivity) are already fully documented in the schema, so no further credit is warranted.
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 description opens with a specific verb and resource ("Search the web") and immediately narrows scope: it searches via a rotating pool of named providers with failover. It explicitly contrasts itself with the sibling fetch_url, so an agent can distinguish retrieval-by-query from retrieval-by-URL without opening either schema.
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?
It states the selecting condition plainly: use this when the answer depends on current web pages and no URL is known yet, and use fetch_url when the URL is already known. It also names get_engine_status implicitly via the engine parameter, giving the agent a prerequisite step for preferring a provider.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_engine_configUpdate Engine ConfigAIdempotent
Change the local engine configuration: enable or disable engines, set the search and fetch rotation order, and set monthly or daily call limits per engine. Use it when the user wants a provider switched on or off, reordered or capped; call get_engine_status first for valid ids, current order and access modes. The tool writes the shared configuration file of this installation, so the change applies to later searches of every client without a restart. API keys are not accepted here: an engine that still needs a key or extra credentials cannot be enabled until they are set in the dashboard (open_dashboard). Returns the effective per-engine configuration, or an error naming the offending ids — on error nothing is written.
| Name | Required | Description | Default |
|---|---|---|---|
| enabled | No | Per engine id (see get_engine_status): true enables, false disables. Enabling an engine whose access mode is api_key_required or extra_configuration_required fails until the credential exists in the dashboard. | |
| fetchOrder | No | Complete fetch rotation: every fetch-capable engine id exactly once, the first entry is tried first. | |
| dailyLimits | No | Per engine id: cap for locally counted calls per day, or null to remove the override. Applies to providers whose quota period is counted per day. | |
| searchOrder | No | Complete search rotation: every search-capable engine id exactly once, the first entry is queried first. Fetch-only engines are not part of this order and keep their place behind it. | |
| monthlyLimits | No | Per engine id: cap for locally counted calls per month, or null to remove the override and fall back to the provider default. The cap drives rotation and strict-free ordering; it does not change the provider account. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations, it discloses that the write targets the shared configuration file of the installation, applies to later searches of every client without a restart, rejects API keys, and that on error nothing is written. The atomicity guarantee is genuinely useful context for a mutation tool.
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 front-loaded sentences, the primary action first, followed by prerequisites and failure behavior; nearly every clause earns its place, though the credential paragraph is somewhat dense.
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?
With no output schema, the description still explains the return value (effective per-engine configuration or an error naming offending ids) and the no-write-on-error behavior, covering what an agent needs for a 5-parameter nested-object mutation.
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% and the schema itself richly documents each of the five parameters (rotation semantics, null-to-remove, access-mode failures). The description reinforces but does not meaningfully extend these meanings, so the baseline of 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?
States a specific verb (Change) and resource (local engine configuration), then enumerates the three capabilities: enable/disable, rotation order, and call limits. An agent can distinguish it from search_web, fetch_url, get_engine_status, and open_dashboard without opening the schema.
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?
Explicitly says when to use it (user wants a provider switched on/off, reordered or capped) and gives a prerequisite: call get_engine_status first for valid ids, current order and access modes. It also states when it will not work (engines needing keys must be set via open_dashboard).
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.
6 tool updates
v0.5.0- Removed
engine_status - Changed
fetch_url1 field changed- changed
Input schema / properties / url / descriptionPrevious value: -"URL to fetch"New value: +"Absolute http(s) URL of the page to fetch, including scheme and host"
- Added
get_engine_status - Added
search_web - Added
update_engine_config - Removed
web_search
2 tool updates
v0.4.5- Changed
fetch_url1 field changed- removed
Input schema / additionalPropertiesRemoved value: -false
- Changed
web_search4 fields changed- removed
Input schema / additionalPropertiesRemoved value: -false - removed
Input schema / properties / endDate / $refRemoved value: -"#/properties/startDate" - added
Input schema / properties / endDate / patternAdded value: +"^\\d{4}-\\d{2}-\\d{2}$" - added
Input schema / properties / endDate / typeAdded value: +"string"
1 tool update
v0.4.2- Changed
web_search3 fields changed- added
Input schema / properties / endDateAdded value: +{ + "$ref": "#/properties/startDate", + "description": "End date YYYY-MM-DD (through this date, subject to provider boundary semantics). Cannot combine with timeRange." +} - added
Input schema / properties / startDateAdded value: +{ + "description": "Start date YYYY-MM-DD. May be used alone or with endDate; cannot combine with timeRange.", + "pattern": "^\\d{4}-\\d{2}-\\d{2}$", + "type": "string" +} - added
Input schema / properties / timeRangeAdded value: +{ + "description": "Relative UTC date window: day=1, week=7, month=30, year=365 days through today. Cannot combine with startDate/endDate; day precision, not rolling hours.", + "enum": [ + "day", + "week", + "month", + "year" + ], + "type": "string" +}
4 tool updates
v0.3.3- First observed
engine_status - First observed
fetch_url - First observed
open_dashboard - First observed
web_search
TDQS
Scored across 5 tools
The two retrieval tools are explicitly separated by the known-URL vs discover-links distinction, and each description cross-references the other. The three configuration tools (get_engine_status, update_engine_config, open_dashboard) are read/write/human-view respectively, and the descriptions state those boundaries outright. No pair of tools appears to do the same thing.
All five names follow a strict snake_case verb_noun pattern (fetch_url, search_web, get_engine_status, open_dashboard, update_engine_config). The verb choices are also semantically consistent: get for reading state, update for mutating it, open for launching.
Five tools is tightly scoped to the stated purpose: two data-plane operations and three configuration/administration operations. Nothing appears redundant or missing at the count level.
Search, fetch, config read, config write and credential/dashboard access cover the full lifecycle of a rotating-provider retrieval server. Minor gaps remain, such as no batch multi-URL fetch and no way to probe live provider health, but these are either explicitly out of scope or workable around.
Maintenance
Related MCP Connectors
One MCP server for all web data. Scrape, search, crawl, and AI research in one install.
MCP server for Google search results via SERP API
Web search API and MCP server for developers building AI agents.
Unified 15-tool SEO, SERP, clean Markdown & GEO (LLM citation Share-of-Voice) MCP server.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceAn MCP server that aggregates web search results from multiple engines and optionally renders pages to Markdown, providing a unified search interface.10 npm3ISC
- AlicenseNot gradedqualityDmaintenanceA lightweight MCP server providing web search via DuckDuckGo and page content extraction in multiple formats.1MIT
- 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.5MIT
- AlicenseAqualityCmaintenanceA self-hosted MCP server for web search with multi-engine support, combining search, URL fetching, and deep research along with proxy routing and deduplication.3MIT