MCP server exposing web_search and web_extractor tools with configurable provider fallback chains (Tavily, Firecrawl, Exa, SearXNG for search; Tavily, Firecrawl, Exa, Crawl4AI for extraction). Supports both MCP (stdio/HTTP) and REST API transports.
Two tools with complete input schemas and clear descriptions. web_search and web_extractor both have well-structured parameters with types, descriptions, and sensible defaults. Descriptions are concise (90-120 chars) and action-oriented. However, output schemas are not documented in the visible code, only inferred from implementation. Parameter descriptions could be more prescriptive about constraints (e.g., exact enum values for 'mode', 'categories'). Error handling is mentioned in descriptions ('never raises') but recovery guidance is absent. No tool annotations (readOnlyHint, destructiveHint) despite both being read-only operations.
Fetch http(s) URLs via the configured fallback chain; returns Markdown per URL or error dict (never raises).
Search the web via the configured fallback chain; returns ranked results or an error dict (never raises).
Output schemas not documented. Tool descriptions mention return format ('ranked results', 'Markdown') but no structured schema is visible in code or docs. LLMs cannot plan downstream tool calls without knowing response field names and types.
Parameter 'categories' and 'mode' accept free-form strings with examples in descriptions ('general, news, science, it, images' and 'fit', 'raw', 'bm25', 'llm') but no enum constraint. LLMs may hallucinate invalid values like 'sports' or 'summary'.
No tool annotations. Both tools are read-only (safe to retry) but lack readOnlyHint in schema. Agents cannot distinguish safe tools from destructive ones without explicit hints.
Error recovery guidance missing. Descriptions state tools 'never raise' and return error dicts, but do not explain what the LLM should do when an error occurs (retry, try different provider, ask user).
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 67 | 2026-07-28+ | v2 |
Parameter 'time_range' accepts null default but description does not clarify what null means (no filter? backend default?). Ambiguous defaults invite misuse.