A payroll and HR compliance processing server that calculates tax withholding and validates labor standards compliance by jurisdiction
This MCP server has a single tool with significant quality gaps. The tool name 'process_payroll_compliance' uses a generic verb ('process') rather than a specific action verb (get_, calculate_, validate_). The description is present but generic and lacks context about when to use the tool, what it returns, or prerequisites. The input schema is partially defined but has critical issues: the 'employee_data' parameter is typed as 'dict' with nested properties, which is valid but the schema definition is incomplete, only 'salary_usd' is marked required, but the description states it contains 'at minimum' this field, implying flexibility. The 'jurisdiction' parameter has a default ('US-CA') but lacks enum constraints, inviting hallucinated jurisdiction codes (e.g., 'US-ZZ'). Most critically, there is NO documented output schema, the LLM cannot know in advance what fields the response contains. The implementation in client.py shows it returns a dict with 'tax_withholding_calc' (containing 'gross', 'estimated_tax', 'net') and 'compliance_status', but this structure is not formalized in the tool definition. Error handling is completely absent, there are no guards against invalid jurisdiction codes, negative salaries, or missing required fields, and no error messages to guide recovery. The tool performs tax calculations but hardcodes a 28% tax rate with no jurisdiction-specific logic despite claiming to validate 'labor standards compliance', this is misleading. Security: no parameter validation, no rate limiting, and no audit trail. The tool is read-only (no side effects) but the definition provides no reassurance to this effect via toolAnnotations.
Processes payroll compliance by calculating tax withholding and validating labor standards compliance for a given jurisdiction
Generic tool name 'process_payroll_compliance', uses 'process' (non-specific verb) rather than action verbs like 'calculate_', 'validate_', or 'get_'. LLMs cannot infer the specific action from the name alone.
No output schema documented. The tool returns a dict with 'tax_withholding_calc' and 'compliance_status' fields (visible in example_usage.py), but this structure is not declared in the tool definition. LLMs cannot plan downstream actions or extract fields without a documented response schema.
Input parameters lack constraints. 'jurisdiction' accepts any string with default 'US-CA', but no enum or pattern validation prevents invalid codes like 'US-ZZ', 'INVALID', or hallucinated values. Description mentions 'e.g. US-CA, US-NY', these are examples that LLMs will reuse literally.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | F | 23 | 2026-07-28+ | v2 |
No parameter descriptions for nested 'employee_data' object structure. The schema defines 'properties' (salary_usd, name) but does not describe when each field is required, what values are valid, or format expectations (e.g., salary in cents vs. dollars, name length limits).
No error handling. The implementation contains no input validation, no guard against negative salaries, and no error messages. If called with invalid jurisdiction or missing salary, it will silently use defaults or crash. No recovery guidance for the LLM.
Tool description is vague. States 'Processes payroll compliance by calculating tax withholding and validating labor standards compliance' but does not explain: What does 'validating labor standards compliance' mean? What validation is performed? When should this tool be called vs. other payroll tools? What fields does the response contain?
Implementation does not match description. Claims to validate jurisdiction-specific 'labor standards' but hardcodes a 28% tax rate for all jurisdictions and returns a canned compliance string. No actual jurisdiction-specific logic exists.
No tool annotations. The tool is read-only (does not modify state), but this is not declared via 'readOnlyHint' or similar MCP annotation. LLMs cannot distinguish this from a destructive operation without explicit metadata.