MCP server for retrieving job vacancies from HeadHunter (hh.ru) API with filtering capabilities
Single tool 'get_vacancies' has acceptable naming and schema, but the description is in Russian (non-English, reducing clarity for English-speaking LLM consumers), lacks depth about usage context, and error handling is completely absent. No documentation of output schema. Parameters have type unions and descriptions, but no constraints (e.g., min/max for perPage, enum for salary format). The tool returns raw JSON from hh.ru API without any response shaping, pagination guidance, or field documentation. Input validation and error recovery paths are missing entirely.
Возвращает список всех вакансий. Можно передать фильтры
Tool description is in Russian ('Возвращает список всех вакансий. Можно передать фильтры'), not English. This severely limits usability with English-language LLM clients and violates convention for production tools.
Output schema is completely undocumented. Tool returns raw JSON from hh.ru API (likely a large object with vacancies array, metadata, and pagination). LLMs have no guidance on which fields to extract or what structure to expect. Violates baseline that 100% of A+ tools have documented return types.
No error handling or recovery guidance. If fetch() fails (network error, API down, rate limit, invalid search), the tool returns nothing helpful. LLM receives a raw exception or malformed JSON. No pattern for categorizing errors as retryable, user-fixable, or fatal.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | D | 56 | <=2025-11-25 | v2 |
| 2026-03-09 | F | 34 | - | v1 |
No pagination guidance in description. Tool accepts 'perPage' but lacks documentation of: (a) what the default is, (b) what the max allowed is, (c) how to fetch next page, (d) whether a cursor or offset is returned. Returning hundreds of vacancies without a page limit will blow context windows.
Parameter 'salary' accepts union[number, string] but lacks format documentation. Is it a minimum salary, exact salary, salary range? Is it in rubles? Should it be 50000 or '50000' or '50000-100000'? Without constraints, LLM will guess and pass invalid values.
Parameter 'perPage' accepts union[number, string] but has no min/max constraints. LLM could pass 'perPage=999999' or 'perPage=0', causing API failures or unexpected behavior. Baseline rubric requires 'Specify minimum and maximum for numeric parameters'.
Raw API response from hh.ru is dumped as-is into 'text' field. This likely includes pagination metadata, audit fields, and verbose nesting that wastes tokens and obscures relevant data. Violates 'strip-api-responses' pattern: 'APIs return verbose metadata irrelevant to chat interactions. Strip pagination internals, audit fields, and raw IDs.'
No input validation. Tool constructs a URL from user input (searchText, salary, perPage) without escaping or validation. A malicious or accidental input like 'searchText=?foo=bar&ignore=true' could alter the query. Violates 'Treat all agent-provided input as untrusted. Sanitize against SQL injection, command injection, and path traversal.'