Leave Manager MCP Server using FastMCP and Supabase
Leave-Manager-MCP exhibits mediocre definition quality typical of community MCP servers. Five tools are explicitly defined with names, descriptions, and parameter schemas visible in server.py. Tool naming follows verb_noun convention (get_*, add_*), which is positive. However, descriptions lack depth and strategic guidance for LLM decision-making. Parameter descriptions are minimal (single sentence, no constraints or format details). Output schemas are entirely undocumented, no mention of return field structure, pagination, or chaining identifiers. Error messages are generic strings rather than structured error codes with recovery guidance. The server lacks production patterns: no idempotency hints, no permission gates, no audit logging visible, no batch variants for looped operations.
Book a leave for an employee. Checks balance first and rejects if insufficient. Dates must be in YYYY-MM-DD format. On success, inserts a leave_history record and deducts days from the balance.
Check whether an employee can take leave between start_date and end_date. Dates must be in YYYY-MM-DD format. This tool only checks eligibility - it does NOT book the leave. Use add_leave to officially record the leave.
Greet an employee by name and return today's date.
Get the current year's leave balance for an employee.
Get the last 18 leave records for an employee, newest first.
No output schema documentation. All five tools return free-text strings rather than structured objects. LLMs cannot plan downstream operations or extract specific fields. Example: get_leave_balance returns a formatted string; if a subsequent tool needs 'remaining_days' as a number, the LLM must parse the text and guess the field name.
Parameter descriptions are minimal and lack format/constraint details. 'emp_id' is described as 'Employee ID' but provides no guidance on format (string? numeric? max length?). 'start_date' and 'end_date' mention YYYY-MM-DD but do not specify minimum/maximum date ranges, whether past dates are allowed, or what happens if dates span year boundaries. LLMs will guess and fail.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | F | 46 | <=2025-11-25 | v2 |
| 2026-03-09 | D | 54 | - | v1 |
Tool descriptions lack WHEN/WHY guidance. 'Get the current year's leave balance for an employee' says WHAT but not WHEN to call it instead of get_leave_history, and it does not mention that this tool is a prerequisite for apply_for_leave and add_leave. Undocumented dependencies force LLMs to explore via trial and error.
apply_for_leave and add_leave duplicate validation logic. Both check date format, date ordering, and leave balance. This violates DRY principle and creates risk: if validation changes in one tool, it may not be applied to the other. The conceptual separation (check vs. book) is reasonable, but code reuse is poor.
Error responses are unstructured free-text strings. Examples: 'Employee {emp_id} not found.', 'Invalid date format. Please use YYYY-MM-DD.', 'end_date must be on or after start_date.' These are human-readable but not machine-parseable. An LLM cannot easily categorize errors as retryable vs. user-fixable vs. fatal, nor can it extract the invalid value for auto-correction.
No pagination support on get_leave_history. Tool fetches 'last 18 leave records' but hardcodes the limit in the description. If an employee has 50 leave records, the LLM sees only 18. No limit parameter, no offset/cursor, no total count returned. For a busy employee, this tool is incomplete.
No batch operations. If an LLM needs to check leave balance for 10 employees, it must call get_leave_balance 10 times sequentially. A batch_get_leave_balance(emp_ids: list) would be far more efficient and reduce latency.
add_leave is not idempotent and has no confirmation mechanism. If an LLM retries due to a transient error, a second call will create a duplicate leave record without warning. The tool should either support dry-run mode or include an idempotentHint annotation to signal non-idempotency.