Web search capability using Exa API, Firecrawl API that provides real-time internet search results and use RAG to search for relevant data. Supports both basic and advanced search with filtering options including domain restrictions, text inclusion requirements, and date filtering. Returns formatted results with titles, URLs, publication dates, and content summaries.
This MCP server has two tools with basic schemas but significant quality gaps. Both tools are defined with proper verb-noun naming (search_web_tool, get_web_content_tool) and async implementations via FastMCP. However, descriptions lack specificity about WHEN to use each tool vs. the other, and critical parameter constraints are missing. Input schemas declare parameter types but provide minimal context. Output is returned as unstructured strings rather than structured JSON, forcing the LLM to parse free-form text. Error handling is present in get_web_content_tool (timeout, exception handling) but search_web_tool lacks explicit error guidance. The tools compose reasonably (search then RAG enhancement), but the composition logic is baked into search_web_tool rather than left to agent orchestration, reducing flexibility. No pagination, no output schema documentation, no tool annotations (readOnlyHint, idempotentHint), no documented return structure for downstream chaining.
Get web content from a URL using FireCrawl API and return the page content
Search the web using the Exa API and return formatted and raw results, then use RAG to search for relevant data from the retrieved URLs
Output is unstructured string rather than structured JSON. Both tools return plain text strings (e.g., 'No search results found', concatenated RAG documents). LLMs cannot parse, extract fields, or chain to downstream tools without guessing at structure. Should return {results: [...], count: int, error?: string}.
Descriptions lack differentiation and WHEN-to-use context. search_web_tool says 'Search the web using the Exa API and return formatted and raw results, then use RAG to search for relevant data from the retrieved URLs' (133 chars). This does not explain: Why call this vs. get_web_content_tool directly? What does 'formatted results' mean? When would an agent prefer raw results? Should state 'Use this for exploratory queries; returns summaries of multiple pages. Use get_web_content_tool when you need full content from a specific URL.'
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | F | 48 | <=2025-11-25 | v2 |
| 2026-03-09 | D | 51 | - | v1 |
No input validation or constraints on parameters. 'query' and 'url' are bare strings with no length limits, format validation, or pattern constraints. Should include: query: 'Search query string (1-500 chars, no leading/trailing whitespace)', url: 'HTTP(S) URL (must start with http:// or https://)'.
No output schema documentation. Tools return strings; no documentation of fields, structure, or how to extract data for chaining. search_web_tool's output mixes 'formatted_results' and 'RAG Results' with no documented structure. get_web_content_tool returns concatenated page_content with newlines as delimiters, brittle and ambiguous.
search_web_tool bakes RAG composition into its implementation (search → fetch URLs → RAG → return). This violates single-responsibility and reduces agent flexibility. If an agent wants search results alone, or wants to RAG different sources, it cannot. Should split: search_web_tool returns URLs + summaries; rag_search_tool accepts URLs + query and returns RAG results. Agent orchestrates composition.
No error recovery guidance. search_web_tool returns 'No search results found' or 'No valid URLs found in search results', but does not guide agent recovery (e.g., 'Try a simpler query', 'Check Exa API quota'). get_web_content_tool returns timeout and generic exceptions but lacks 'retry after N seconds' or 'check URL validity' guidance.
No pagination or result limits. search_web_tool could return dozens of RAG documents joined by '---\n'; no cap on output size. This risks exhausting context windows. Should limit to top-K results (e.g., 10) and document limit in description.
Missing tool annotations. Neither tool declares readOnlyHint=true (both are read-only, safe for retries), idempotentHint=true (both are idempotent), or destructiveHint=false. Agents cannot infer retry safety or side effects without these hints.