An intelligent HR assistant using MCP servers (Database, Filesystem, RAG) with Groq LLM orchestration. Provides tools for employee information, announcements, and policy document search.
This is a custom MCP implementation with 18 tools spread across multiple server files. While tool naming follows verb_noun conventions reasonably well (get_employee_info, search_employees, query_documents), the implementation has significant gaps: descriptions vary wildly in quality, parameter descriptions are sparse or missing, output schemas are not documented in the code, and error handling is minimal. The codebase shows some database_server.py implementation details, but most RAG and orchestrator tools lack visible definitions. Many tools appear to be inferred from the tool list rather than explicitly defined in the source. The project uses a custom 'lightweight approach' to MCP without the official SDK, which raises questions about spec compliance. No evidence of pagination, pagination parameters, or result limits is visible. Error responses in database_server.py examples are basic dictionaries without recovery guidance.
Get a list of all employees in the database
Get employe count by department. Use when user wants to know how many employees are in each department.
Get detailed information about an employee by ID
Get employee details like name, department, position, manager, email. Use when user asks about employee information.
Get all employees in a specific department
Get employee's leave balance (casual, earned, sick leaves). Use when user asks about leave availability.
Get summary of a specific policy document.
Duplicate tool definitions: 'search_employees' appears twice (in database_server.py and orchestrator.py) with different signatures, one with (department, name_contains), one with just (name). LLMs will not know which to call.
Output schemas are not documented anywhere in the code. Tools return dictionaries (e.g., database_server returns {'employee_id': ..., 'name': ..., 'found': True}), but there is no formal JSON Schema definition showing LLMs what fields to expect. This violates pattern:tool and forces LLMs to infer structure.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | F | 49 | 2026-07-28+ | v2 |
| 2026-03-09 | F | 41 | - | v1 |
Get the most recent company announcements (default: 3). Use when user asks for latest updates.
List all company announcement files. Use when user wants to see what announcements are available.
List all available policy documents
Query ONLY announcements.
Query all documents (policies + announcements) using semantic search.
Query ONLY policy documents.
Read a specific announcement file. Use when user wants to read a particular announcement.
Search announcements by keyword. Use when user is looking for specific information.
Search for employees by name (partial match)
Search employees by department or name (partial match). Use when user wants to find specific employees.
Search policy documents. Use this for questions about leave policy, salary policy, or other HR policies.
No pagination parameters (limit, offset, page, next_cursor) visible on any list or search tool. Without it, returning thousands of results blows context and wastes tokens.
RAG tools (query_documents, query_policies, query_announcements) have 'top_k' parameter with description 'Number of results to return (default: 3)', but no hard limit is visible. If an LLM passes top_k=1000, the tool may return enormous responses.
Error handling in database_server.py returns basic dicts with error=True and message fields, but provides no recovery guidance. Per pattern:recovery-guide, errors must tell LLMs what to do next. E.g., 'Employee EMP999 not found. Try search_employees() with a partial name.' Current: just 'Employee EMP999 not found'.
Most tools from rag_server.py and orchestrator.py are not visible in the source code, only their names, descriptions, and input params are listed. No implementation, no output structure, no error handling is shown. These tools are inferred rather than explicitly defined, so per HARD SCORING RULES they must be capped at overall 50.
No parameter constraints visible for string enums or formats. E.g., 'doc_type' in query_documents says 'Filter by type (policy, announcement, or None for all)' in description but is not declared as an enum in the schema shown. Descriptions should not contain examples; use formal enum constraints.
No tool annotations (readOnlyHint, destructiveHint, idempotentHint) are visible in the source. All 18 tools are marked READ_ONLY in the metadata, but this is not reflected in actual schema tool annotations per 2026-07-28 spec.