@theyahia/hh-mcp 1.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +114 -70
- package/dist/index.d.ts +3 -1
- package/dist/index.js +50 -13
- package/dist/index.js.map +1 -1
- package/dist/tools/resumes.d.ts +29 -0
- package/dist/tools/resumes.js +45 -0
- package/dist/tools/resumes.js.map +1 -0
- package/package.json +35 -56
package/README.md
CHANGED
|
@@ -1,70 +1,114 @@
|
|
|
1
|
-
# @theyahia/hh-mcp
|
|
2
|
-
|
|
3
|
-
MCP-сервер для hh.ru
|
|
4
|
-
|
|
5
|
-
[](https://www.npmjs.com/package/@theyahia/hh-mcp)
|
|
6
|
-
[](https://www.npmjs.com/package/@theyahia/hh-mcp)
|
|
6
|
+
[](https://github.com/theYahia/hh-mcp/actions)
|
|
7
|
+
[](https://opensource.org/licenses/MIT)
|
|
8
|
+
|
|
9
|
+
Часть серии [Russian API MCP](https://github.com/theYahia/russian-mcp) (50 серверов) by [@theYahia](https://github.com/theYahia).
|
|
10
|
+
|
|
11
|
+
## Два режима работы
|
|
12
|
+
|
|
13
|
+
| Режим | Что доступно | Нужен токен? |
|
|
14
|
+
|-------|-------------|--------------|
|
|
15
|
+
| **Без токена** | Поиск вакансий, вакансия по ID, работодатели, зарплаты, регионы, профроли | Нет |
|
|
16
|
+
| **С токеном** | Всё выше + поиск резюме, резюме по ID | Да (`HH_ACCESS_TOKEN`) |
|
|
17
|
+
|
|
18
|
+
Получить токен: [dev.hh.ru/admin](https://dev.hh.ru/admin)
|
|
19
|
+
|
|
20
|
+
## Установка
|
|
21
|
+
|
|
22
|
+
### Claude Desktop
|
|
23
|
+
|
|
24
|
+
```json
|
|
25
|
+
{
|
|
26
|
+
"mcpServers": {
|
|
27
|
+
"hh": {
|
|
28
|
+
"command": "npx",
|
|
29
|
+
"args": ["-y", "@theyahia/hh-mcp"],
|
|
30
|
+
"env": {
|
|
31
|
+
"HH_ACCESS_TOKEN": "your-token-here (опционально)"
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Claude Code
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
claude mcp add hh -- npx -y @theyahia/hh-mcp
|
|
42
|
+
# С токеном:
|
|
43
|
+
claude mcp add hh -e HH_ACCESS_TOKEN=your-token -- npx -y @theyahia/hh-mcp
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### VS Code / Cursor
|
|
47
|
+
|
|
48
|
+
```json
|
|
49
|
+
{ "servers": { "hh": { "command": "npx", "args": ["-y", "@theyahia/hh-mcp"] } } }
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Windsurf
|
|
53
|
+
|
|
54
|
+
```json
|
|
55
|
+
{ "mcpServers": { "hh": { "command": "npx", "args": ["-y", "@theyahia/hh-mcp"] } } }
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### HTTP режим (Streamable HTTP)
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
npx @theyahia/hh-mcp --http
|
|
62
|
+
# или
|
|
63
|
+
HTTP_PORT=8080 npx @theyahia/hh-mcp --http
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Эндпоинт: `http://localhost:3000/mcp`
|
|
67
|
+
Health check: `http://localhost:3000/health`
|
|
68
|
+
|
|
69
|
+
## Инструменты (8)
|
|
70
|
+
|
|
71
|
+
| Инструмент | Описание | Нужен токен? |
|
|
72
|
+
|------------|----------|:------------:|
|
|
73
|
+
| `search_vacancies` | Поиск вакансий по словам, региону, зарплате, опыту | Нет |
|
|
74
|
+
| `get_vacancy` | Полная информация о вакансии с описанием и контактами | Нет |
|
|
75
|
+
| `search_resumes` | Поиск резюме по ключевым словам и параметрам | **Да** |
|
|
76
|
+
| `get_resume` | Полная информация о резюме | **Да** |
|
|
77
|
+
| `get_employers` | Поиск работодателей по названию | Нет |
|
|
78
|
+
| `get_salary_stats` | Статистика зарплат по специальности и региону | Нет |
|
|
79
|
+
| `get_areas` | Справочник регионов РФ и СНГ с кодами | Нет |
|
|
80
|
+
| `get_professional_roles` | Справочник профессиональных ролей | Нет |
|
|
81
|
+
|
|
82
|
+
## Примеры
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
Найди вакансии Python в Москве от 200К
|
|
86
|
+
Покажи вакансии в Яндексе
|
|
87
|
+
Средняя зарплата Senior Backend?
|
|
88
|
+
Какие регионы есть в hh.ru?
|
|
89
|
+
Найди резюме Java-разработчиков в Петербурге
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## API
|
|
93
|
+
|
|
94
|
+
Все публичные эндпоинты используют `https://api.hh.ru` без авторизации. Эндпоинты резюме требуют OAuth 2.0 токен через переменную окружения `HH_ACCESS_TOKEN`.
|
|
95
|
+
|
|
96
|
+
User-Agent: `theYahia-hh-mcp/1.0`
|
|
97
|
+
|
|
98
|
+
## Разработка
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
git clone https://github.com/theYahia/hh-mcp.git
|
|
102
|
+
cd hh-mcp
|
|
103
|
+
npm install
|
|
104
|
+
npm run build
|
|
105
|
+
npm test
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Часть серии Russian API MCP
|
|
109
|
+
|
|
110
|
+
**50 серверов:** [github.com/theYahia/russian-mcp](https://github.com/theYahia/russian-mcp)
|
|
111
|
+
|
|
112
|
+
## Лицензия
|
|
113
|
+
|
|
114
|
+
MIT
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,24 +1,61 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
3
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
4
5
|
import { searchVacanciesSchema, handleSearchVacancies, getVacancySchema, handleGetVacancy } from "./tools/vacancies.js";
|
|
5
6
|
import { getEmployersSchema, handleGetEmployers } from "./tools/employers.js";
|
|
6
7
|
import { handleGetAreas, handleGetProfessionalRoles, getSalaryStatsSchema, handleGetSalaryStats } from "./tools/references.js";
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
server.tool("
|
|
15
|
-
server.tool("
|
|
16
|
-
server.tool("
|
|
8
|
+
import { searchResumesSchema, handleSearchResumes, getResumeSchema, handleGetResume } from "./tools/resumes.js";
|
|
9
|
+
import http from "node:http";
|
|
10
|
+
function createServer() {
|
|
11
|
+
const server = new McpServer({
|
|
12
|
+
name: "hh-mcp",
|
|
13
|
+
version: "1.1.0",
|
|
14
|
+
});
|
|
15
|
+
server.tool("search_vacancies", "Поиск вакансий на hh.ru по ключевым словам, региону, зарплате, опыту.", searchVacanciesSchema.shape, async (params) => ({ content: [{ type: "text", text: await handleSearchVacancies(params) }] }));
|
|
16
|
+
server.tool("get_vacancy", "Полная информация о вакансии: описание, требования, навыки, контакты.", getVacancySchema.shape, async (params) => ({ content: [{ type: "text", text: await handleGetVacancy(params) }] }));
|
|
17
|
+
server.tool("search_resumes", "Поиск резюме на hh.ru (требуется HH_ACCESS_TOKEN).", searchResumesSchema.shape, async (params) => ({ content: [{ type: "text", text: await handleSearchResumes(params) }] }));
|
|
18
|
+
server.tool("get_resume", "Полная информация о резюме (требуется HH_ACCESS_TOKEN).", getResumeSchema.shape, async (params) => ({ content: [{ type: "text", text: await handleGetResume(params) }] }));
|
|
19
|
+
server.tool("get_employers", "Поиск работодателей по названию.", getEmployersSchema.shape, async (params) => ({ content: [{ type: "text", text: await handleGetEmployers(params) }] }));
|
|
20
|
+
server.tool("get_salary_stats", "Статистика зарплат по специальности и региону.", getSalaryStatsSchema.shape, async (params) => ({ content: [{ type: "text", text: await handleGetSalaryStats(params) }] }));
|
|
21
|
+
server.tool("get_areas", "Справочник регионов РФ и СНГ с кодами для поиска.", {}, async () => ({ content: [{ type: "text", text: await handleGetAreas() }] }));
|
|
22
|
+
server.tool("get_professional_roles", "Справочник профессиональных ролей для поиска вакансий.", {}, async () => ({ content: [{ type: "text", text: await handleGetProfessionalRoles() }] }));
|
|
23
|
+
return server;
|
|
24
|
+
}
|
|
17
25
|
async function main() {
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
26
|
+
const args = process.argv.slice(2);
|
|
27
|
+
const httpMode = args.includes("--http") || !!process.env.HTTP_PORT;
|
|
28
|
+
const port = Number(process.env.HTTP_PORT || process.env.PORT || 3000);
|
|
29
|
+
if (httpMode) {
|
|
30
|
+
const server = createServer();
|
|
31
|
+
const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: () => crypto.randomUUID() });
|
|
32
|
+
await server.connect(transport);
|
|
33
|
+
const httpServer = http.createServer(async (req, res) => {
|
|
34
|
+
const url = new URL(req.url || "/", `http://localhost:${port}`);
|
|
35
|
+
if (url.pathname === "/health") {
|
|
36
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
37
|
+
res.end(JSON.stringify({ status: "ok", tools: 8 }));
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (url.pathname === "/mcp") {
|
|
41
|
+
await transport.handleRequest(req, res);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
res.writeHead(404);
|
|
45
|
+
res.end("Not found. Use /mcp for MCP protocol or /health for health check.");
|
|
46
|
+
});
|
|
47
|
+
httpServer.listen(port, () => {
|
|
48
|
+
console.error(`[hh-mcp] HTTP mode on port ${port}. Endpoint: /mcp`);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
const server = createServer();
|
|
53
|
+
const transport = new StdioServerTransport();
|
|
54
|
+
await server.connect(transport);
|
|
55
|
+
console.error("[hh-mcp] Сервер запущен (stdio). 8 инструментов.");
|
|
56
|
+
}
|
|
21
57
|
}
|
|
58
|
+
export { createServer };
|
|
22
59
|
main().catch((error) => {
|
|
23
60
|
console.error("[hh-mcp] Ошибка:", error);
|
|
24
61
|
process.exit(1);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxH,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC9E,OAAO,EAAE,cAAc,EAAE,0BAA0B,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const searchResumesSchema: z.ZodObject<{
|
|
3
|
+
text: z.ZodOptional<z.ZodString>;
|
|
4
|
+
area: z.ZodOptional<z.ZodNumber>;
|
|
5
|
+
professional_role: z.ZodOptional<z.ZodNumber>;
|
|
6
|
+
experience: z.ZodOptional<z.ZodEnum<["noExperience", "between1And3", "between3And6", "moreThan6"]>>;
|
|
7
|
+
per_page: z.ZodDefault<z.ZodNumber>;
|
|
8
|
+
}, "strip", z.ZodTypeAny, {
|
|
9
|
+
per_page: number;
|
|
10
|
+
text?: string | undefined;
|
|
11
|
+
area?: number | undefined;
|
|
12
|
+
experience?: "noExperience" | "between1And3" | "between3And6" | "moreThan6" | undefined;
|
|
13
|
+
professional_role?: number | undefined;
|
|
14
|
+
}, {
|
|
15
|
+
text?: string | undefined;
|
|
16
|
+
area?: number | undefined;
|
|
17
|
+
experience?: "noExperience" | "between1And3" | "between3And6" | "moreThan6" | undefined;
|
|
18
|
+
per_page?: number | undefined;
|
|
19
|
+
professional_role?: number | undefined;
|
|
20
|
+
}>;
|
|
21
|
+
export declare function handleSearchResumes(params: z.infer<typeof searchResumesSchema>): Promise<string>;
|
|
22
|
+
export declare const getResumeSchema: z.ZodObject<{
|
|
23
|
+
id: z.ZodString;
|
|
24
|
+
}, "strip", z.ZodTypeAny, {
|
|
25
|
+
id: string;
|
|
26
|
+
}, {
|
|
27
|
+
id: string;
|
|
28
|
+
}>;
|
|
29
|
+
export declare function handleGetResume(params: z.infer<typeof getResumeSchema>): Promise<string>;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { hhGet } from "../client.js";
|
|
3
|
+
export const searchResumesSchema = z.object({
|
|
4
|
+
text: z.string().optional().describe("Ключевые слова для поиска резюме"),
|
|
5
|
+
area: z.number().optional().describe("Код региона (1=Москва, 2=СПб)"),
|
|
6
|
+
professional_role: z.number().optional().describe("Код профессиональной роли"),
|
|
7
|
+
experience: z.enum(["noExperience", "between1And3", "between3And6", "moreThan6"]).optional().describe("Опыт работы"),
|
|
8
|
+
per_page: z.number().int().min(1).max(100).default(20).describe("Количество на странице"),
|
|
9
|
+
});
|
|
10
|
+
export async function handleSearchResumes(params) {
|
|
11
|
+
const token = process.env.HH_ACCESS_TOKEN;
|
|
12
|
+
if (!token) {
|
|
13
|
+
return JSON.stringify({
|
|
14
|
+
error: "Требуется авторизация. Задайте HH_ACCESS_TOKEN для доступа к резюме.",
|
|
15
|
+
hint: "Получите токен на https://dev.hh.ru/admin",
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
const query = new URLSearchParams();
|
|
19
|
+
if (params.text)
|
|
20
|
+
query.set("text", params.text);
|
|
21
|
+
if (params.area)
|
|
22
|
+
query.set("area", String(params.area));
|
|
23
|
+
if (params.professional_role)
|
|
24
|
+
query.set("professional_role", String(params.professional_role));
|
|
25
|
+
if (params.experience)
|
|
26
|
+
query.set("experience", params.experience);
|
|
27
|
+
query.set("per_page", String(params.per_page));
|
|
28
|
+
const result = await hhGet(`/resumes?${query.toString()}`);
|
|
29
|
+
return JSON.stringify(result, null, 2);
|
|
30
|
+
}
|
|
31
|
+
export const getResumeSchema = z.object({
|
|
32
|
+
id: z.string().describe("ID резюме"),
|
|
33
|
+
});
|
|
34
|
+
export async function handleGetResume(params) {
|
|
35
|
+
const token = process.env.HH_ACCESS_TOKEN;
|
|
36
|
+
if (!token) {
|
|
37
|
+
return JSON.stringify({
|
|
38
|
+
error: "Требуется авторизация. Задайте HH_ACCESS_TOKEN для доступа к резюме.",
|
|
39
|
+
hint: "Получите токен на https://dev.hh.ru/admin",
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
const result = await hhGet(`/resumes/${params.id}`);
|
|
43
|
+
return JSON.stringify(result, null, 2);
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=resumes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resumes.js","sourceRoot":"","sources":["../../src/tools/resumes.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,56 +1,35 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@theyahia/hh-mcp",
|
|
3
|
-
"version": "1.0
|
|
4
|
-
"description": "MCP
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "dist/index.js",
|
|
7
|
-
"bin": {
|
|
8
|
-
|
|
9
|
-
},
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
"
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
},
|
|
22
|
-
"
|
|
23
|
-
"@
|
|
24
|
-
"
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
"
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
"
|
|
35
|
-
|
|
36
|
-
"mcp",
|
|
37
|
-
"mcp-server",
|
|
38
|
-
"model-context-protocol",
|
|
39
|
-
"claude",
|
|
40
|
-
"ai",
|
|
41
|
-
"russian-api",
|
|
42
|
-
"hh",
|
|
43
|
-
"headhunter",
|
|
44
|
-
"jobs",
|
|
45
|
-
"vacancies",
|
|
46
|
-
"salary",
|
|
47
|
-
"resume"
|
|
48
|
-
],
|
|
49
|
-
"license": "MIT",
|
|
50
|
-
"repository": {
|
|
51
|
-
"type": "git",
|
|
52
|
-
"url": "https://github.com/theYahia/hh-mcp.git"
|
|
53
|
-
},
|
|
54
|
-
"homepage": "https://github.com/theYahia/hh-mcp#readme",
|
|
55
|
-
"author": "theYahia (https://github.com/theYahia)"
|
|
56
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@theyahia/hh-mcp",
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "MCP-сервер для hh.ru: поиск вакансий, резюме, зарплаты, работодатели, справочники. 8 инструментов.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": { "hh-mcp": "dist/index.js" },
|
|
8
|
+
"files": ["dist"],
|
|
9
|
+
"engines": { "node": ">=18.0.0" },
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"dev": "tsx src/index.ts",
|
|
13
|
+
"start": "node dist/index.js",
|
|
14
|
+
"test": "vitest run",
|
|
15
|
+
"test:watch": "vitest",
|
|
16
|
+
"prepublishOnly": "npm run build && npm test"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
20
|
+
"zod": "^3.24.0"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@types/node": "^22.0.0",
|
|
24
|
+
"tsx": "^4.19.0",
|
|
25
|
+
"typescript": "^5.7.0",
|
|
26
|
+
"vitest": "^3.0.0"
|
|
27
|
+
},
|
|
28
|
+
"publishConfig": { "access": "public" },
|
|
29
|
+
"mcpName": "io.github.theYahia/hh-mcp",
|
|
30
|
+
"keywords": ["mcp", "mcp-server", "model-context-protocol", "claude", "ai", "russian-api", "hh", "headhunter", "jobs", "vacancies", "salary", "resume"],
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"repository": { "type": "git", "url": "https://github.com/theYahia/hh-mcp.git" },
|
|
33
|
+
"homepage": "https://github.com/theYahia/hh-mcp#readme",
|
|
34
|
+
"author": "theYahia (https://github.com/theYahia)"
|
|
35
|
+
}
|