FastMCP server that provides web search and grounded AI answers using Perplexity's API
The server provides three well-named, verb-based tools (search, ask, ask_more) with comprehensive input schemas and detailed parameter descriptions. All tools declare ToolAnnotations with readOnlyHint=True and idempotentHint=True, showing good security awareness. However, output schemas are not formally documented, only a docstring mentions 'Returns: Searchable results' without specifying structured fields. Error handling exists but is generic (HTTPStatusError caught and returned as plain text). The domain_filter parameter uses a sophisticated design accepting both include/exclude domains via '-' prefix, but the mechanism is underdocumented in descriptions. Parameter descriptions are well above the 20-char minimum and often exceed the 72-char baseline. The recency parameter resolution logic is complex and well-handled server-side, reducing LLM cognitive load. Missing: formal output schema documentation, per-parameter error guidance, and explicit rate-limit or timeout constraints.
Get AI-synthesized answers with web-grounded search.
Dig deeper with more comprehensive analysis — uses more sources and deeper processing than ask().
**PREFER THIS FIRST** - Find and evaluate sources yourself. Returns URLs, titles, and snippets.
Output schema not formally documented. Tools return formatted strings (via format_search_results() and format_chat_response()) but the structure of that string (markdown, citation format, image/related-question sections) is not declared in tool descriptions. LLMs cannot reliably parse or plan downstream actions on opaque text responses.
Error handling is generic. Exceptions (HTTPStatusError, general Exception) are caught and returned as plain strings ('Chat API error: 401 - ...') without categorizing errors as retryable/user-fixable/fatal or providing recovery guidance. An LLM receives 'Request failed: timeout' with no hint to retry, check the API key, or reduce max_tokens.
domain_filter parameter uses a sophisticated prefix syntax ('-' for exclusion) that is documented in the description but not validated in code. The server passes the array directly to the API without sanitizing or confirming the format. If the API rejects malformed filters, the LLM receives a raw API error with no guidance on the correct syntax.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | D | 56 | 2026-07-28+ | v2 |
| 2026-03-09 | D | 58 | - | v1 |
No timeout or rate-limit handling visible. httpx.Client(timeout=60.0) sets a single global timeout, but if the Perplexity API is slow or the agent calls search() repeatedly in a tight loop, there is no backoff or rate-limit guidance to the LLM. An agent in a retry loop could hammer the API.
The 'sources' parameter in search, ask, ask_more uses the enum ['web', 'academic', 'sec'], but the description says 'Source type - web (general), sec (financial filings), academic (scholarly)'. The order in the enum differs from the description order (web, academic, sec vs web, sec, academic), which can confuse LLMs about whether the enum is exhaustive or ordered.