До детального анализа нужно зафиксировать, какой сценарий имеется в виду. Это меняет всё.
Цель: автоматизировать работу рекрутера/компании.
Действия: публикация вакансий, поиск резюме в базе, приглашения кандидатов, ответы на отклики, аналитика воронки найма.
API статус: employer-side остался открытым после 15.12.2025.
Требования: юр.лицо (ИП/ООО), employer-подписка HH с доступом к базе резюме.
Цель: автоматизировать поиск работы за кандидата.
Действия: поиск вакансий, авто-отклики, чтение переписок с работодателями.
API статус: закрыт 15.12.2025; через API невозможно.
Альтернативы: UI-эмуляция (Playwright) — серая зона с тремя слоями риска (ToS / 152-ФЗ / ATS-репутация — см. Quick-Offer case).
Дальнейший анализ исходит из employer-интерпретации (по сигналу «корпоративный аккаунт работодателя» в плане). Где-то отметим, что меняется при job-seeker-чтении.
Через hh.ru/employer/registration. Требуется ИНН/ОГРН — нужно либо иметь ИП/ООО, либо использовать существующее юр.лицо компании. Без юр.лица employer-аккаунт получить нельзя — это первый блокер плана.
Тестовый режим: у HH нет sandbox в смысле AWS — это боевая платформа. «Тестовость» эмулируется через тестовый OAuth-app и dev-окружение, но действия с реальными вакансиями/откликами видны кандидатам.
После employer-аккаунта: dev.hh.ru/admin → «Создать приложение» → название, описание, redirect_uri → получаешь client_id, client_secret, опционально app_token.
Для PoC: создать отдельное dev-приложение, не использовать его для production. Если credentials утекут — revoke без последствий.
Что НЕ задокументировано публично:
dev.hh.ru.Что задокументировано: OAuth 2.0 (authorization code grant + client credentials), header Authorization: Bearer ..., обязательный User-Agent: AppName/Version (contact@email), домен только api.hh.ru.
Проверено. Официального MCP-сервера от HH не существует. HH предоставляет:
github.com/hhru/apiapi.hh.ru/openapi/redocdev.hh.ruMCP — внешний по отношению к HH протокол; компания им не занимается. Это не временный пробел, а архитектурное решение.
Найден один заметный кандидат:
| Проект | Тип | Покрытие | Активность | Лицензия |
|---|---|---|---|---|
| gmen1057/headhunter-mcp-server | Python MCP (stdio) | 10 tools: поиск, vacancy, employer, similar, areas, dictionaries, resumes*, apply*, negotiations* | 8 коммитов, 14 stars, 2 open issues | MIT |
Apify scrapers (easyapi/hh-ru-job-scraper, scrapestorm) |
SaaS scraper с MCP-endpoint | Read-only поиск через HTML-парсинг | Активны | SaaS / paid |
gmen1057 detailed assessment:
hh_apply_to_vacancy: параметр letter вместо message)SECURITY.md. Issue #6 (Feb 2026) — пользователи спрашивают «жив ли проект?»api.hh.ru и hh.ru; нет telemetry; нет логирования секретов; зависимости (mcp, httpx, pydantic, python-dotenv) — мейнстрим. Код безвредный.Стек выбора:
mcp SDK; быстрее на старте; готовый референс — gmen1057; можно форкнуть и убрать ненужное@modelcontextprotocol/sdk; лучше если команда TS-ориентирована; для read-only часть можно сгенерировать клиент из OpenAPI HH через openapi-generator-cliРекомендация: Python. Аргументы: gmen1057 как референс (MIT, можно форкать), официальный hhru SDK тоже на Python (hh-applicant-tool), быстрый старт для PoC.
| Tool | Endpoint | Auth | Статус |
|---|---|---|---|
search_vacancies | GET /vacancies | anonymous | работает |
search_resumes | GET /resumes | employer OAuth + подписка | работает |
get_resume | GET /resumes/{id} | employer OAuth + подписка | работает |
invite_candidate | POST /negotiations (employer-side) | employer OAuth | работает |
list_my_vacancies | GET /vacancies/{employer_id} | employer OAuth | работает |
get_negotiations | GET /negotiations (на свои вакансии) | employer OAuth | работает |
send_message | POST /messages | employer OAuth | работает |
| Tool | Endpoint | Auth | Статус |
|---|---|---|---|
search_vacancies | GET /vacancies | anonymous | работает |
get_vacancy | GET /vacancies/{id} | anonymous | работает |
apply_to_vacancy | POST /negotiations | job-seeker OAuth | закрыт 15.12.2025 |
list_my_responses | GET /negotiations | job-seeker OAuth | закрыт 15.12.2025 |
list_my_resumes | GET /resumes/mine | job-seeker OAuth | статус неясен |
Если интерпретация job-seeker — половина базового tool-set не реализуема через API. Альтернатива — UI-эмуляция через Playwright (см. предыдущий артефакт).
from mcp.server import Server
from mcp.types import Tool, TextContent
import mcp.server.stdio
import httpx, os, asyncio
server = Server("hh-employer-mcp")
BASE = "https://api.hh.ru"
TOKEN = os.getenv("HH_ACCESS_TOKEN")
UA = "MyApp/0.1 (contact@example.com)"
async def hh(path: str, params: dict | None = None):
headers = {"User-Agent": UA}
if TOKEN:
headers["Authorization"] = f"Bearer {TOKEN}"
async with httpx.AsyncClient() as client:
r = await client.get(f"{BASE}{path}", params=params, headers=headers)
r.raise_for_status()
return r.json()
@server.list_tools()
async def list_tools():
return [
Tool(name="search_vacancies", description="Поиск вакансий по тексту/региону",
inputSchema={"type": "object", "properties": {
"text": {"type": "string"},
"area": {"type": "integer", "description": "1=Москва, 2=СПб"},
"per_page": {"type": "integer", "default": 20}
}, "required": ["text"]}),
# ... + остальные tools
]
@server.call_tool()
async def call_tool(name: str, arguments: dict):
if name == "search_vacancies":
data = await hh("/vacancies", params=arguments)
return [TextContent(type="text", text=str(data))]
# ...
async def main():
async with mcp.server.stdio.stdio_server() as (read, write):
await server.run(read, write, server.create_initialization_options())
if __name__ == "__main__":
asyncio.run(main())
Простейший путь — использовать сам Claude Code как UI: подключаешь MCP-сервер через ~/.claude.json и общаешься с агентом в терминале. Для PoC хватает.
Для красивой демо — Claude Desktop (нативный chat-интерфейс, поддерживает MCP), либо собственный минимальный web-UI на FastAPI/Streamlit, который дёргает Claude API напрямую с function-calling над теми же tool-функциями.
Это базовый паттерн MCP — Claude получает tool-определения, видит естественный запрос, решает какие tools вызвать. Работает «из коробки» при правильно описанных inputSchema.
Tool: search_resumes → GET /resumes?text=senior+python&area=1
Требования: employer OAuth + активная подписка HH с пакетом контактов (без подписки — поиск ограничен или недоступен).
Caveat: в anonymous-режиме базы резюме нет вообще; нужен именно employer.
Семантика #1 (employer): «отправь приглашение N кандидатам».
invite_candidate → POST /negotiations (employer-side) с шаблоном сообщенияСемантика #2 (job-seeker): «откликнись на N вакансий».
apply_to_vacancy → POST /negotiations (job-seeker-side)Tool: get_negotiations → GET /negotiations + клиентская агрегация по statuses
Возможные срезы: total / новые / прочитанные / приглашены / отказы; разбивка по вакансиям; средний time-to-response.
Side benefit: отличный сценарий для агента — он может не только показать цифры, но и предложить инсайты («у вакансии X в 3 раза меньше откликов чем у Y — стоит проверить SEO/требования»).
Ответить на вопросы из §8. Зафиксировать: employer или job-seeker; нужна ли подписка; нужно ли действие «отклик» или только read+advisor.
Регистрация employer-аккаунта (если ещё нет юр.лица — это блокер; альтернатива на старте — job-seeker аккаунт для anonymous-only сценариев). Активация (минимальной) подписки если нужны резюме. Создание dev-приложения на dev.hh.ru/admin.
curl-проверки: /vacancies (anonymous), /me (с токеном), /resumes (если подписка). Зафиксировать актуальные лимиты эмпирически.
Вариант A (быстрый): форкнуть gmen1057/headhunter-mcp-server, удалить сломанные/неактуальные tools, добавить нужные employer-tools, починить баг #5.
Вариант B (чистый): написать с нуля по скелету из §3.3, ~200-300 строк Python для 7 tool'ов.
Конфиг в ~/.claude.json, проверка что Claude видит tools.
Прогнать три сценария руками в Claude Code. Записать скринкаст для демо. Если красивый UI нужен — обернуть в Streamlit/Gradio за 2-3 часа.
README с инструкцией установки. Документировать: какие tools работают, какие ограничения, что нужно для production.
Общая оценка: 4-7 рабочих дней от старта до working demo (если уже есть юр.лицо для employer). Без юр.лица — добавь время на регистрацию ИП (~1 неделя), либо ограничься anonymous-tools.
| Пункт плана | Employer-интерпретация | Job-seeker-интерпретация | Блокер |
|---|---|---|---|
| 1.1 Регистрация employer-аккаунта | да | — | нужно юр.лицо |
| 1.2 OAuth-приложение dev.hh.ru | да | да | — |
| 1.3 Лимиты / scopes / auth | эмпирически | эмпирически | не публикуется |
| 2.1 Официальный MCP от HH | не существует | не существует | — |
| 2.2 Open-source MCP | gmen1057 | gmen1057, частично сломан | — |
| 2.3 Оценка качества | community, MIT, safe | community, MIT, safe | — |
| 3. Собственный MCP | 1-2 дня | 1-2 дня (но половина tools — закрыта) | — |
| 4. UI/чат с агентом | Claude Code as-is | Claude Code as-is | — |
| Сценарий A: поиск резюме senior python в Москве | да | нет (нет доступа к базе) | employer-подписка |
| Сценарий B: отклик/приглашение на N резюме шаблоном | да, но риск ATS-репутации | API закрыт 15.12.2025 | — |
| Сценарий C: статистика откликов | да | API закрыт 15.12.2025 | — |