serp-mcp has two tools with basic schemas and descriptions, but multiple quality gaps. Schemas are present but incomplete, parameters lack full type definitions and descriptions are minimal. The web_search tool description is 88 chars (below the 194 baseline), and fetch_content is only 54 chars. No parameter descriptions exist for either tool (critical gap per pattern:tool-description). Error handling is absent, no recovery guidance or error classification. Naming is acceptable (verb-noun pattern), but the lack of parameter docs and minimal tool descriptions make LLM selection and invocation unreliable. The server is functional but would not pass production code review.
Tools (2)
fetch_contentread onlysource verified48/100
Fetch a page and return only important readable content.
web_searchread onlysource verified52/100
Google Search the web and return SerpAPI-like output:
{
"q": "...",
"organic_results": [{"title": "...", "link": "...", "snippet": "..."}]
}
Tool descriptions are too short to guide LLM selection. web_search is 88 chars (baseline 194), fetch_content is 54 chars. Both lack context on WHEN to use them and WHY they exist.
No parameter descriptions exist for any tool. LLMs cannot infer that 'q' is a search query or that 'max_results' controls result count, the descriptions field is missing entirely.
No error handling or recovery guidance. If a search fails, times out, or returns no results, the LLM gets no actionable error message or suggestion (e.g. 'try a different query'). No error classification (retryable vs user-fixable).
Expand web_search description to 100-150 chars, explaining: 'Search Google or your configured backend for web results. Returns structured results with title, link, and snippet for each match, plus optional AI overview. Use this to answer questions, find links, or explore topics.' This answers WHAT, WHEN, and WHAT'S RETURNED.
Expand fetch_content description to 80-120 chars: 'Fetch the readable content of a web page, stripping navigation, ads, and scripts. Returns the page title and up to max_chars of clean text. Use this after web_search to read full articles or extract specific information.'
Add parameter descriptions in the schema: 'q' → 'The search query string (e.g. "python asyncio tutorial"). Supports Google-style operators like "site:example.com" and quoted phrases.'; 'max_results' → 'Maximum number of results to return (1 - 50, default 10). Higher values increase latency.'; 'url' → 'The full URL of the page to fetch (must start with http:// or https://).'; 'max_chars' → 'Maximum characters of body text to return (500 - 50000, default 8000). Larger values are slower and use more tokens.'
Add output schema documentation as a comment or in tool description: web_search returns {q: string, organic_results: [{title, link, snippet}], ai_overview?: string}; fetch_content returns {url, title, content}.
Implement error handling with recovery hints. Example: if fetch_content receives a 404, return 'Page not found (404). Try a different URL or search for alternatives using web_search.' If web_search returns 0 results, suggest 'No results for that query. Try broader keywords or remove filters.' Handle timeout gracefully with 'Request timed out. Try a simpler query or try again in a few seconds.'
Score history
Overall score trend
↓ 8 points across a rubric change (v1 → v2)
37/100
Scored
Grade
Overall
Spec posture
Rubric
2026-09-22
F
37
2026-07-28+
v2
2026-03-09
F
45
-
v1
Output schemas not documented. Agents calling web_search expect to know the structure of 'organic_results' and 'ai_overview' fields, this is not explicit in the tool definition. fetch_content returns a dict with 'url', 'title', 'content' but this is undocumented.
Parameter constraints not documented. max_results defaults to 10 but accepts 1-50 per code. max_chars defaults to 8000 but accepts 500-50000 per code. LLMs cannot infer these bounds and may pass invalid values. No enum/min/max constraints in schema.
web_search does not document what fields are returned in organic_results objects. Are they always title/link/snippet, or does ai_overview sometimes replace them? This ambiguity forces LLMs to guess about the response structure.
web_search
Document constraints in schema: Add minimum/maximum to max_results (1, 50) and max_chars (500, 50000). Add format or pattern to url parameter (must match http(s)://).)
Consider adding optional parameters for filtering: web_search could accept 'region', 'safesearch', or 'time_range' (e.g., 'past_week'). These would leverage the existing config but expose them to the LLM for fine-grained control.
Add a note about rate limiting or cost in the description if using paid APIs. Example: 'Note: searches cost API credits if using a paid provider. Use sparingly in loops.'
Consider splitting web_search into two tools if AI overview is rarely needed: web_search (simple, fast) and web_search_with_overview (includes AI summary). This lets simple queries avoid latency overhead.
Add an optional 'include_links' parameter to fetch_content to allow stripping URLs (useful for fitting more content in context window).