An MCP server for managing employee leave requests, tracking leave balances, and accessing employee information.
The HR-Leave-Manager server has clear, domain-specific tools with acceptable naming and decent descriptions. However, it suffers from critical gaps in schema documentation, parameter descriptions, and error handling. All 5 tools are directly visible in main.py with explicit @mcp.tool() decorators, so they are not inferred. Naming is solid (get_*, request_leave follows verb_noun convention). Descriptions average 120 chars, which is reasonable but lack actionable detail for LLM selection. The critical failure: input schemas are visible in the tool signatures but NOT formally documented in the response. Parameters lack descriptions at the schema level, LLMs see parameter names ('employee_id', 'leave_type', 'days', 'reason') but no formal type hints or constraints in structured schema output. Error handling is minimal: most tools return plain strings ('Error: Employee not found') with no recovery guidance. Output schemas are not documented, tools return markdown strings with no typed structure. The mock database is realistic and the logic is sound, but the interface to LLMs is weak.
Retrieve a list of all employees with their basic details.
Search for an employee's full details and leave history using their name. Use this if you do not have the Employee ID.
Get a full profile summary of an employee including department and history.
Check remaining leave days for an employee across all types.
Submit a new leave request. Validates if the employee has enough balance before approving.
No documented output schemas. Tools return plain markdown strings with no typed structure. LLMs cannot extract structured data, validate field presence, or chain downstream tools with confidence.
Parameter descriptions missing at schema level. While tool descriptions exist, individual parameters (employee_id, leave_type, days, reason) lack descriptions explaining constraints, valid values, or expected format.
No enum constraints for leave_type. The request_leave tool accepts 'leave_type' as a free-form string. It should declare valid values (Casual, Sick, Floating, Parental) as an enum to prevent hallucinated values.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | D | 50 | 2026-07-28+ | v2 |
| 2026-03-09 | F | 38 | - | v1 |
Error responses lack recovery guidance. Errors like 'Error: Employee not found' or 'Denied: Insufficient balance' do not suggest next steps. Per pattern:recovery-guide, errors should guide the LLM (e.g., 'Try search_users() with a partial name').
No input validation or limit documentation. get_all_employees returns all 6 employees without pagination; as the dataset grows, context overhead will increase. By baseline, results should be capped at 20-50 with pagination support.
Destructive operation (request_leave modifies state) lacks confirmation step. Per pattern:confirmation-request, write operations should support dry-run or require explicit confirmation to prevent accidental approvals.
No idempotent guarantees documented. If an LLM retries request_leave due to a transient error, the leave balance would be decremented twice. Tools should declare idempotency or include request deduplication.