A FastMCP server that provides tools for analyzing sales data from a CSV file, including revenue calculations, product-level sales queries, and top-selling product identification.
The server defines 3 tools with basic structure, but has significant gaps in descriptions, parameter documentation, and error handling. Tool names are clear and follow verb_noun convention (get_*, all starting with appropriate action verbs). However, parameter descriptions are minimal or missing in the schema, output schemas are undocumented, and error handling lacks recovery guidance. The server is functional for simple read-only operations but falls short of production quality standards.
Gets sales data for a specific product.
Finds the top N selling products based on total revenue.
Calculates the total revenue from all sales.
No output schemas documented. Tools return dicts and floats with no explicit field documentation, forcing LLMs to infer structure from trial calls.
Parameter descriptions exist only in docstring prose, not in the JSON schema. The schema for get_sales_by_product has a description field in the parameter, but get_top_selling_products 'n' parameter has no description in the input schema itself.
Error handling is minimal. get_sales_by_product returns {"error": "..."} on not found, but does not guide LLM to alternatives (e.g., 'Try get_top_selling_products() to see available products'). No recovery hints provided.
No pagination, limits, or result constraints documented. The tools return all matching data without caps. If the sales dataset grows, tools could return thousands of records, exhausting context windows.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | D | 52 | 2026-07-28+ | v2 |
| 2026-03-09 | D | 55 | - | v1 |
No output format documentation. get_sales_by_product returns a list of dicts (via to_dict('records')), while get_top_selling_products returns a dict (product name → revenue). Inconsistent return types force LLMs to infer structure.
Tool descriptions are short (34-60 chars) and lack context on WHEN to use each tool or WHAT field names to expect in the response. Descriptions do not answer: 'When should I call this instead of the others?'