E-commerce MCP Server with AI-powered product search and HTTP transport
The server presents 6 tools total, but exhibits critical structural issues. Tools 4 and 6 (search_products_by_price) are duplicates, as are tools 1 and 5 (get_products), indicating poor organization. While all tools have descriptions and input schemas are visible, the descriptions vary significantly in quality and clarity. The ecommerce_server tools have verbose docstrings with Args/Returns sections that exceed recommended length (192+ chars), making them harder for LLMs to parse for intent. Parameter descriptions are present but sometimes generic ('Natural language description of products you want'). Most critically, there is no documented output schema for any tool, LLMs cannot predict what fields to extract from responses. Error handling exists (guards against non-ecommerce queries) but lacks actionable recovery guidance. The server uses FastMCP with stateless_http=True, which is modern, but tool composition is poor: multiple tools do redundant work (search by price vs. by query), violating the single-responsibility principle. The codebase shows environment-variable-based API key injection (good), but no rate limiting or input validation beyond keyword matching.
A simple add tool
A simple echo tool
Search products by category or keywords. Args: user_query: Natural language description of products you want Returns: List of products matching your query
Search products by category or keywords. Args: user_query: Natural language description of products you want Returns: List of products matching your query
Search products within a price range. Args: min_price: Minimum price in dollars max_price: Maximum price in dollars category: Optional category filter Returns: Products within the price range
Search products within a price range. Args: min_price: Minimum price in dollars max_price: Maximum price in dollars category: Optional category filter Returns: Products within the price range
Duplicate tool definitions: get_products appears twice (tools 3 & 5), search_products_by_price appears twice (tools 4 & 6). LLMs will be confused when offered identical tools. This wastes reasoning cycles and suggests incomplete testing.
No documented output schema for any tool. The get_products and search_products_by_price tools return product lists, but the response structure is inferred from the fakestore API (product_id, title, price, category, description). LLMs cannot plan downstream operations without knowing what fields are present. This violates the response schema documentation requirement.
Verbose tool descriptions (192-280 chars) that mix Args/Returns sections. Descriptions should be 10-200 chars and focus on WHAT and WHEN, not API documentation format. Example: 'Search products by category or keywords. Args: user_query: Natural language...' is over-verbose. Better: 'Search products by natural language description. Returns matching items with prices and ratings.'
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | F | 44 | 2026-07-28+ | v2 |
| 2026-03-09 | F | 47 | - | v1 |
Missing output validation and pagination. The tools fetch from fakestore API which returns all products, then filters in Python. No limit enforcement visible in code, returning 20 items is acceptable, but source code shows no cap or pagination parameters (limit, offset, next_cursor). Tools returning lists must support pagination (pattern:paginated-result).
Error messages lack recovery guidance. The is_ecommerce_related() guard returns a static rejection message for out-of-scope queries ('Out of Scope Query...') without suggesting next steps or alternative tools. Per pattern:recovery-guide, errors must tell the LLM what to do: 'This query is not about shopping. Try searching the web or asking a general knowledge tool instead.'
Parameter descriptions are generic and lack format/constraint guidance. 'user_query' is described as 'Natural language description of products you want', but what length? What language? Does it accept special characters? The baseline is that descriptions should include range, format, and allowed values. Compare: better = 'Natural language product query (English, 1-200 chars, e.g., "running shoes under $100").'
Weak tool naming for search_products_by_price. The name 'search_products_by_price' uses an underscore between 'by' and 'price', but the LLM must infer that this tool is specifically for RANGE searches (min/max), not single-price lookups. Better name: 'search_products_price_range' or explicit verb+noun: 'filter_products_by_price_range'. Also, get_products and search_products_by_price overlap in intent, agents will struggle deciding which to call.