mardanaltynbekov1104/hh-mcp — TypeScript MCP-сервер для HH (employer-side, multi-site hh.kz/hh.ru). Пользователи подключают к Claude Code / Desktop / Cursor, используют со своими credentials.
dev.hh.ru/admin после одобрения app. Без OAuth flow. Расширенный read + application-context actions.https://github.com/mardanaltynbekov1104/hh-mcp
TypeScript MCP-сервер, employer-only с рождения. 9 group-tools покрывают 70+ HH-actions. v0.1.1, обновлён 6 дней назад.
Почему именно этот проект — см. hh-mcp-landscape-comparison-2026.html (полное сравнение 7 MCP-серверов).
Что делаем в форке:
hh_saved_searches для автопоисков резюме)api.hh.ru. Для упрощения разработки HH предоставляет self-service Application token через UI в dev.hh.ru/admin (см. tier 2 ниже).
Проверенные источники (нет упоминаний sandbox):
https://api.hh.ru; нет отдельного test-host'аAnonymous endpoints работают только с корректным User-Agent или HH-User-Agent header:
hh_dictionaries — все справочники (типы занятости, опыт, валюты, языки)hh_suggests — все 8 подсказок (skills, positions, areas, professional_roles, etc.)GET /vacancies, GET /vacancies/{id})GET /employers/{id})GET /areas, /metro, /districts)Что проверяем: вся MCP-инфраструктура — регистрация tools, stdio transport, dispatch group-tools, error handling, User-Agent header. Smoke-тест архитектуры за 1 день.
Регистрация приложения на dev.hh.ru/admin не требует юр.лица — нужен обычный hh.ru аккаунт. После одобрения заявки в личном кабинете доступна self-service генерация application token — копи-паста токена из UI без OAuth-flow вообще.
Цитата из официальной документации:
«Владелец приложения может посмотреть актуальный access_token для приложения на сайте https://dev.hh.ru/admin. Токен приложения необходимо сгенерировать 1 раз»
Что получаем:
grant_type=client_credentials — расширенный read поверх anonymous + application-context actionshh-client: Bearer header, error handling, rate-limitshh_auth tool можно реализовать «загрузить готовый app-token из env»Что НЕ доступно на этом уровне:
GET /resumes) — это employer-методhh_employer_* toolsСтоимость: 0 ₽. Срок: модерация заявки — обычно 4 дня, в редких случаях до 15 рабочих дней. Подаём заявку в день 1, параллельно работаем над Tier 1.
Все «полезные» employer-методы требуют user-token от имени employer-менеджера. Application token не подходит — нужен именно user-token с user-context, получаемый только через authorization_code grant с redirect на hh.ru. Плюс требует:
Официальные прайсы HH:
hh_employer_info — данные текущего работодателяhh_employer_vacancies — CRUD вакансий (create, read, update, archive, restore)hh_employer_resumes — поиск в базе резюме (требует подписки с пакетом контактов)hh_employer_negotiations — переписка с кандидатами, статистика воронкиhh_webhooks — подписки на employer-событияPOST /negotiations/phone_interviewБез этого не проверить: бизнес-логика employer-сценариев, реальные данные в воронке, поведение с настоящими кандидатами.
dev.hh.ru/admin.
hh_employer_resumes (поиск в базе резюме).
9 group-tools mardanaltynbekov-форка покрывают 70+ HH-actions через dispatch-параметр.
| Tool | Что внутри | Уровень доступа |
|---|---|---|
hh_auth |
Загрузка app-token из env / OAuth flow для user-token / token refresh | Tier 1 |
hh_dictionaries |
Справочники (industries, professional_roles, languages, locales, areas, metro, districts) | Tier 1 anonymous |
hh_suggests |
Подсказки (skill_set, positions, areas, professional_roles, etc.) | Tier 1 anonymous |
hh_salary |
Оценка зарплаты по параметрам вакансии | Tier 2 app token |
hh_employer_info |
Информация о текущем работодателе (managers, addresses, departments) | Tier 3 user token |
hh_employer_vacancies |
CRUD вакансий: create, read, list active/archived/hidden, prolongate, stats | Tier 3 user token |
hh_employer_negotiations |
Список откликов, статистика воронки, переписка с кандидатами, приглашения | Tier 3 user token |
hh_employer_resumes |
Поиск в базе резюме, просмотр конкретного резюме | Tier 3 user token + подписка |
hh_webhooks |
Подписки на события (новый отклик, изменение статуса) | Tier 3 user token |
Tier 1 — anonymous (только User-Agent). Tier 2 — application token (self-service из dev.hh.ru/admin, без OAuth). Tier 3 — user token employer-менеджера (OAuth + юр.лицо + подписка для базы резюме).
Что добавить в форке (опционально):
hh_saved_searches — автопоиски резюме (6 endpoints из HH API) — позволяет реактивный паттерн «бот напоминает о новых кандидатах»hh_vacancy_search — поиск чужих вакансий (для анализа рынка / конкурентов) — anonymous endpoint, не требует подпискиhh-mcp/
├── src/
│ ├── index.ts # MCP entrypoint + stdio transport
│ ├── http-server.ts # HTTP-server (port 3400)
│ ├── tools/
│ │ ├── auth.ts # hh_auth (OAuth flow)
│ │ ├── dictionaries.ts # hh_dictionaries
│ │ ├── suggests.ts # hh_suggests
│ │ ├── salary.ts # hh_salary
│ │ ├── employer-info.ts
│ │ ├── employer-vacancies.ts
│ │ ├── employer-negotiations.ts
│ │ ├── employer-resumes.ts
│ │ └── webhooks.ts
│ ├── hh-client.ts # HTTP-клиент HH с auto-refresh
│ └── config.ts # tokens.json + env
├── tests/
├── package.json
├── tsconfig.json
├── README.md
└── LICENSE # MIT (наследуем + добавляем свой copyright)
{
"name": "@your-org/hh-mcp",
"version": "0.2.0",
"type": "module",
"engines": { "node": ">=18" },
"bin": { "hh-mcp": "./dist/index.js" },
"scripts": {
"build": "tsc",
"dev": "tsx src/index.ts",
"test": "vitest",
"lint": "eslint src",
"auth": "tsx src/cli/auth.ts"
},
"dependencies": {
"@modelcontextprotocol/sdk": "^1.0.0",
"axios": "^1.7.0",
"zod": "^3.24.0"
}
}
// src/tools/employer-resumes.ts
import { z } from 'zod'
const ActionSchema = z.discriminatedUnion('action', [
z.object({
action: z.literal('search'),
text: z.string(),
area: z.number().optional(),
per_page: z.number().min(1).max(100).default(20),
}),
z.object({
action: z.literal('get'),
resume_id: z.string(),
}),
])
export const hh_employer_resumes = {
name: 'hh_employer_resumes',
description: 'Поиск и просмотр резюме в базе HH (employer + подписка).',
inputSchema: ActionSchema,
async handler(args: z.infer<typeof ActionSchema>, client: HHClient) {
if (args.action === 'search') {
return client.get('/resumes', {
text: args.text,
area: args.area,
per_page: args.per_page,
})
}
if (args.action === 'get') {
return client.get(`/resumes/${args.resume_id}`)
}
}
}
// src/cli/auth.ts
import http from 'http'
import open from 'open'
import axios from 'axios'
import { writeFileSync, mkdirSync } from 'fs'
import { homedir } from 'os'
import { join } from 'path'
const CREDS = join(homedir(), '.hh-mcp', 'tokens.json')
const REDIRECT = 'http://localhost:8080/callback'
async function authFlow(clientId: string, clientSecret: string) {
const code: { value?: string } = {}
const server = http.createServer((req, res) => {
const url = new URL(req.url!, REDIRECT)
code.value = url.searchParams.get('code') || undefined
res.end('OK, close this window.')
server.close()
})
server.listen(8080)
await open(`https://hh.ru/oauth/authorize?response_type=code&client_id=${clientId}&redirect_uri=${REDIRECT}`)
// ждём callback
await new Promise(r => server.on('close', r))
const { data } = await axios.post('https://api.hh.ru/token', {
grant_type: 'authorization_code',
code: code.value,
client_id: clientId,
client_secret: clientSecret,
redirect_uri: REDIRECT,
})
mkdirSync(join(homedir(), '.hh-mcp'), { recursive: true })
writeFileSync(CREDS, JSON.stringify({ ...data, client_id: clientId, client_secret: clientSecret }))
console.log(`✅ Saved to ${CREDS}`)
}
# hh-mcp
MCP-сервер для HH.ru (employer-side). Поиск резюме, приглашения кандидатов,
переписка, статистика воронки — через Claude Code / Desktop / Cursor.
Multi-site: работает с hh.ru, hh.kz, rabota.by, hh.uz, headhunter.ge/kg, hh1.az.
## Tools
- `hh_employer_resumes` — поиск и просмотр кандидатов
- `hh_employer_vacancies` — CRUD вакансий
- `hh_employer_negotiations` — переписка, приглашения, статистика воронки
- `hh_employer_info` — данные работодателя
- `hh_webhooks` — подписки на события
- `hh_dictionaries`, `hh_suggests`, `hh_salary` — справочники и подсказки
- `hh_auth` — OAuth flow
## Требования
- Employer-аккаунт HH.ru + employer-подписка (для базы резюме)
- Node.js ≥ 18
- Claude Code (или Desktop / Cursor / Continue)
## Установка
```bash
npm install -g @your-org/hh-mcp
```
## Onboarding
### 1. Зарегистрировать приложение на dev.hh.ru/admin
Заявка (модерация 5-15 рабочих дней):
- Название
- Redirect URI: `http://localhost:8080/callback`
- Контактное лицо
- Тип: «только сотрудники работодателя»
- Описание и функциональные возможности
После одобрения — `CLIENT_ID` и `CLIENT_SECRET`.
### 2. Получить access_token
```bash
hh-mcp auth --client-id "..." --client-secret "..."
```
Откроется браузер на hh.ru, после логина токены сохранятся
в `~/.hh-mcp/tokens.json` (с автоматическим refresh при 401).
### 3. Подключить к Claude Code
В `~/.claude.json`:
```json
{
"mcpServers": {
"hh": {
"type": "stdio",
"command": "hh-mcp",
"env": {
"HH_AUTH_BASE": "hh.ru"
}
}
}
}
```
Для hh.kz/rabota.by/etc. — поменять `HH_AUTH_BASE`.
### 4. Использовать
```bash
claude
> Найди резюме senior python в Москве, покажи топ-5
> Покажи статистику откликов по моим вакансиям за неделю
> Пригласи кандидата {resume_id} на вакансию {vacancy_id}
```
## Troubleshooting
- **401** — токен истёк; auto-refresh должен сработать; если нет — `hh-mcp auth` заново
- **403** — нет employer-подписки для базы резюме
- **429** — превышен лимит (~3000/сутки)
## License
MIT. Форк https://github.com/mardanaltynbekov1104/hh-mcp.