MCP server for searching and comparing furniture and home products on Casalist
The Casalist MCP server defines 7 furniture search tools with reasonable structure but significant quality gaps. All tools have descriptions (baseline: 194 chars average; these average ~80 chars, which is below median), and schemas are present with type definitions. However, parameter descriptions are generic, output schemas are not documented, error handling is minimal, and there is no guidance for downstream tool chaining. The server implements READ_ONLY operations only (appropriate for safety), but lacks depth in parameter validation, schema documentation, and recovery guidance. The core issue is that while the basic structure is sound, the implementation does not meet the 'A' bar of being LLM-optimized, descriptions are too brief, output structures are not formally documented, and error messages do not guide the LLM toward corrective actions.
Compare furniture options with detailed analysis.
Find furniture deals and discounted products.
Get price range information for a specific furniture type.
Search for budget-friendly furniture within a specific price range.
Search for furniture and home products on Casalist.
Search for furniture by category with common furniture terms.
Search for premium furniture above a certain price point.
Output schemas are not documented. Tools return dict[str, Any] with no formal schema specification. LLMs cannot anticipate return fields or plan downstream calls (pattern:tool, pattern:response-shaper). For example, search_furniture returns a 'products' key with price enrichment and summary metadata, but this is only visible in implementation code, not in tool documentation.
Error messages do not guide recovery. When API calls fail, the tool returns {'error': 'Unable to fetch ...'} with no actionable next step for the LLM (pattern:recovery-guide). For example, if CASALIST_API_BASE is not set or the API is down, the LLM receives no guidance on retry, fallback, or what to ask the user.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | D | 52 | 2026-07-28+ | v2 |
| 2026-03-09 | F | 39 | - | v1 |
Parameter descriptions are generic and lack constraints. For example, 'sort_price' accepts 'asc' or 'desc' but the description does not enforce this as an enum or state what happens if an invalid value is passed. 'offset' and 'min_price' / 'max_price' lack min/max bounds (pattern:constrained-input). LLMs may pass invalid values like offset=-1 or price=-100 without guidance.
Tool descriptions are brief (avg ~70 chars, baseline 194) and lack context on WHEN to use each tool and WHY it differs from similar tools. For example, 'search_budget_furniture' vs 'search_furniture' with max_price parameter are not differentiated. An LLM cannot determine which to call without reading implementation (pattern:tool-description).
No pagination or result limits are enforced in tool output. If a search returns hundreds of products, all are returned in the response, potentially exhausting context windows (mxe:enforce-result-limits). The tool should cap results at 20 - 50 items and support pagination via offset/limit.
No tool annotations present (readOnlyHint, destructiveHint, idempotentHint). All tools are read-only and idempotent, which should be signaled via annotations in the tool definition so the LLM and client know these tools are safe to retry and compose freely (pattern:tool-annotation).