E-commerce analytics MCP server with PostgreSQL
This server demonstrates solid foundational quality with 17 well-organized tools covering analytics, operations, and schema discovery. All tools have explicit descriptions and most have properly typed input schemas with reasonable defaults. Tool names follow verb_noun conventions and are appropriately specific. However, the server has consistent gaps in output schema documentation, parameter descriptions lack depth regarding constraints and expected formats, and error handling guidance is minimal. The analytics tools are particularly strong (descriptions explain exclusions like cancelled orders, defaults are sensible), while schema/ops tools are more generic. No critical security issues detected, all tools are READ_ONLY except seed_demo_data which has proper guards. The architecture leverages fastmcp's @mcp.tool() decorator with annotations like readOnlyHint, showing protocol awareness. Despite these strengths, the server would benefit from more comprehensive parameter documentation and explicit output schema declarations to reach 80+.
Connectivity check: current database/user/schema/server time.
Describe a table: columns, types, nullability, and default values (best effort).
Gross margin for last N days (uses order_items unit_cost if available, else products.cost).
List all tables in public schema.
List low-stock items (requires v_inventory_on_hand view or inventory table).
Operational health snapshot: status mix + pending backlog + optional low-stock summary.
Clear cached schema metadata (use after running migrations).
Output schemas not documented. Tools like revenue_by_day, top_products_last_days, and ops_health_report return complex objects (dicts with 'days', 'rows', 'limit' keys; markdown strings) but no formal output schema is declared in code or docstring. LLMs cannot plan downstream operations or extract fields with confidence.
Parameter descriptions lack depth on constraints and expected values. E.g., 'days' parameters have descriptions like 'Number of days to analyze' but do not specify range (e.g., 1-365), default behavior if not specified, or what 'days' means exactly (rolling window? calendar days?). The sql_readonly 'max_rows' has min/max constraints (1-2000) in schema but other tools lack equivalent rigor.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | D | 54 | <=2025-11-25 | v2 |
| 2026-03-09 | F | 44 | - | v1 |
Repeat purchase rate over last N days (share of customers with 2+ orders).
Orders + revenue by day for the last N days (excludes cancelled if status exists).
Professional one-page composite dashboard image (2x2): revenue trend, orders trend, top products, KPI tiles.
One-page Markdown sales report (KPIs + trend + top products).
List tables + columns in the public schema (Claude-friendly).
Insert realistic demo e-commerce data. Optionally truncates first. Requires ALLOW_WRITES=1.
Run one read-only SQL statement (SELECT/WITH/SHOW/EXPLAIN). Returns rows as JSON.
Row counts for common e-commerce tables (only those that exist).
Top customers by revenue for the last N days (excludes cancelled if status exists).
Top products by revenue for the last N days (excludes cancelled if status exists).
Error handling and recovery guidance absent. No tool provides actionable error messages or hints on what to do if an operation fails. E.g., low_stock and sql_readonly do not document what happens if the required view/table does not exist, or how the LLM should recover. This violates the recovery-guide pattern.
Tools returning composite outputs (lists + metadata) lack pagination support. top_products_last_days, top_customers_last_days, low_stock, and sql_readonly return rows but do not expose limit, offset, or next_cursor parameters consistently. sql_readonly has max_rows, but analytics tools rely only on 'limit', making it unclear if results are truncated or incomplete.
describe_table and schema tools have generic descriptions. E.g., 'Describe a table: columns, types, nullability, and default values (best effort).' The '(best effort)' signals incomplete behavior but does not explain when/why it fails or what the LLM should do. Similarly, refresh_schema_cache says 'Clear cached schema metadata (use after running migrations)' but does not explain why cache needs clearing or what happens if you don't.
seed_demo_data requires environment variable ALLOW_WRITES=1 for execution, but this constraint is not exposed as a parameter or validated with a clear error message. If ALLOW_WRITES is not set, the tool will silently fail or raise a generic exception. The description should explicitly state the prerequisite and the error message should guide the user to set it.
Parameter type mismatches. sql_readonly's query parameter is described as 'Single SQL statement (SELECT/WITH/SHOW/EXPLAIN). Semicolon allowed at end.' but no enum or regex pattern is defined to enforce this. LLMs could pass INSERT, UPDATE, or other non-SELECT statements and fail. A formal constraint (either in schema or validation inside the tool) is needed.