@sargonpiraev/hh-mcp-server 1.9.0 → 1.11.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.
Files changed (3) hide show
  1. package/README.md +31 -99
  2. package/build/index.js +18 -72
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,133 +1,65 @@
1
1
  # HeadHunter MCP Server
2
2
 
3
- ![npm version](https://img.shields.io/npm/v/@sargonpiraev/hh-mcp-server)
4
- ![smithery badge](https://smithery.ai/badge/@sargonpiraev/hh-mcp-server)
5
-
6
3
  MCP Server for HeadHunter API - job search and vacancy management
7
4
 
8
- ## Features
9
-
10
- - 🔍 User Profile Management - View and manage your HeadHunter profile
11
- - 📄 Resume Management - View detailed resume information
12
- - 💼 Job Application Management - Manage negotiations and communications with employers
13
- - ⭐ Vacancy Search & Favorites - Search for jobs and manage your favorites
14
-
15
- ## Get Your Credentials
16
-
17
- Before installation, you'll need to obtain your API credentials:
18
-
19
- 1. **HH_USER_AGENT**: User-Agent header for HeadHunter API requests (required by HH API)
20
-
21
- Save these credentials for the installation steps below.
5
+ ## Quick Start
22
6
 
23
- ## Installation
24
-
25
- <details>
26
- <summary><b>Installing via Smithery</b></summary>
27
-
28
- To install HeadHunter MCP Server for any client automatically via [Smithery](https://smithery.ai):
7
+ 1. Install dependencies:
29
8
 
30
9
  ```bash
31
- npx -y @smithery/cli@latest install @sargonpiraev/hh-mcp-server --client <CLIENT_NAME>
10
+ npm install
32
11
  ```
33
12
 
34
- </details>
35
-
36
- <details>
37
- <summary><b>Install in Cursor</b></summary>
38
-
39
- #### Cursor One-Click Installation
40
-
41
- [![Install MCP Server](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/install-mcp?name=@sargonpiraev/hh-mcp-server&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBzYXJnb25waXJhZXYvaGFiaXRpZnktbWNwLXNlcnZlciJdLCJlbnYiOnsiSEFCSVRJRllfQVBJX0tFWSI6InlvdXItaGFiaXRpZnktYXBpLWtleSJ9fQo=)
13
+ 2. Set up environment:
42
14
 
43
- #### Manual Configuration
44
-
45
- Add to your Cursor `~/.cursor/mcp.json` file:
46
-
47
- ```json
48
- {
49
- "mcpServers": {
50
- "hh-mcp-server": {
51
- "command": "npx",
52
- "args": ["-y", "@sargonpiraev/hh-mcp-server"],
53
- "env": {
54
- "HH_USER_AGENT": "your-HH_USER_AGENT-here"
55
- }
56
- }
57
- }
58
- }
15
+ ```bash
16
+ cp .env.example .env
17
+ # Edit .env with your API credentials
59
18
  ```
60
19
 
61
- </details>
62
-
63
- <details>
64
- <summary><b>Install in VS Code</b></summary>
65
-
66
- [![Install in VS Code](https://img.shields.io/badge/VS_Code-Install_MCP-0098FF)](vscode:mcp/install?%7B%22name%22%3A%22hh-mcp-server%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22@sargonpiraev/hh-mcp-server%22%5D%7D)
67
-
68
- Or add manually to your VS Code settings:
20
+ 3. Start the server:
69
21
 
70
- ```json
71
- "mcp": {
72
- "servers": {
73
- "hh-mcp-server": {
74
- "type": "stdio",
75
- "command": "npx",
76
- "args": ["-y", "@sargonpiraev/hh-mcp-server"],
77
- "env": {
78
- "HH_USER_AGENT": "your-HH_USER_AGENT-here"
79
- }
80
- }
81
- }
82
- }
22
+ ```bash
23
+ npm start
83
24
  ```
84
25
 
85
- </details>
26
+ ## Configuration
86
27
 
87
- <details>
88
- <summary><b>Install in Claude Desktop</b></summary>
89
-
90
- Add to your `claude_desktop_config.json`:
28
+ Add to your MCP client config:
91
29
 
92
30
  ```json
93
31
  {
94
32
  "mcpServers": {
95
33
  "hh-mcp-server": {
96
- "command": "npx",
97
- "args": ["-y", "@sargonpiraev/hh-mcp-server"],
34
+ "command": "node",
35
+ "args": ["/dist/index.js"],
98
36
  "env": {
99
- "HH_USER_AGENT": "your-HH_USER_AGENT-here"
37
+ "HH_USER_AGENT": "your_hh_user_agent"
100
38
  }
101
39
  }
102
40
  }
103
41
  }
104
42
  ```
105
43
 
106
- </details>
107
-
108
44
  ## Available Tools
109
45
 
110
- - **`get-vacancies`**: Search for vacancies
111
- - **`get-dictionaries`**: Directories of fields
112
- - **`get-areas`**: Tree view of all regions
113
- - **`get-languages`**: The list of all languages
114
- - **`get-industries`**: Industries
115
- - **`get-metro`**: The list of metro stations in all cities
116
- - **`get-professional-roles`**: Professional role directory
117
- - **`get-employers`**: Employer search
46
+ - **get-vacancies**: Search for vacancies
47
+ - **get-dictionaries**: Directories of fields
48
+ - **get-areas**: Tree view of all regions
49
+ - **get-languages**: The list of all languages
50
+ - **get-industries**: Industries
51
+ - **get-metro**: The list of metro stations in all cities
52
+ - **get-professional-roles**: Professional role directory
53
+ - **get-employers**: Employer search
118
54
 
119
- **Total: 8 tools available** 🎯
55
+ ## Development
120
56
 
121
- ## Support This Project
122
-
123
- Hi! I'm Sargon, a software engineer passionate about AI tools and automation. I create open-source MCP servers to help developers integrate AI assistants with their favorite services.
124
-
125
- Your support helps me continue developing and maintaining these tools, and motivates me to create new integrations that make AI assistants even more powerful! 🚀
126
-
127
- [![Support on Boosty](https://img.shields.io/badge/Support-Boosty-orange?logo=data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTEyIDJMMTMuMDkgOC4yNkwyMCA5TDEzLjA5IDE1Ljc0TDEyIDIyTDEwLjkxIDE1Ljc0TDQgOUwxMC45MSA4LjI2TDEyIDJaIiBmaWxsPSJ3aGl0ZSIvPgo8L3N2Zz4K)](https://boosty.to/sargonpiraev)
57
+ ```bash
58
+ npm run build # Build TypeScript
59
+ npm run test # Run tests
60
+ npm run lint # Check code style
61
+ ```
128
62
 
129
- ## Connect with Author
63
+ ## License
130
64
 
131
- - 🌐 Visit [sargonpiraev.com](https://sargonpiraev.com)
132
- - 📧 Email: [sargonpiraev@gmail.com](mailto:sargonpiraev@gmail.com)
133
- - 💬 Join [Discord](https://discord.gg/ZsWGxRGj)
65
+ MIT
package/build/index.js CHANGED
@@ -4,15 +4,10 @@ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
4
4
  import { z } from 'zod';
5
5
  import axios from 'axios';
6
6
  import dotenv from 'dotenv';
7
- // Load environment variables
8
7
  dotenv.config();
9
- // Environment configuration schema
10
8
  const envSchema = z.object({
11
9
  HH_USER_AGENT: z.string().min(1),
12
- // TOOL_GLOB_PATTERNS: z.string().optional(),
13
- // LOG_LEVEL: z.enum(['debug', 'info', 'notice', 'warning', 'error']).default('info').optional(),
14
10
  });
15
- // Parse and validate environment variables
16
11
  const env = envSchema.parse(process.env);
17
12
  const mcpServer = new McpServer({
18
13
  name: '@sargonpiraev/hh-mcp-server',
@@ -29,7 +24,6 @@ const logger = {
29
24
  error: (...message) => mcpServer.server.sendLoggingMessage({ level: 'error', data: message.join(' ') }),
30
25
  debug: (...message) => mcpServer.server.sendLoggingMessage({ level: 'debug', data: message.join(' ') }),
31
26
  };
32
- // Axios client setup
33
27
  const apiClient = axios.create({
34
28
  baseURL: 'https://api.hh.ru',
35
29
  headers: {
@@ -37,7 +31,6 @@ const apiClient = axios.create({
37
31
  },
38
32
  timeout: 30000,
39
33
  });
40
- // Add request interceptor for environment variables
41
34
  apiClient.interceptors.request.use((config) => {
42
35
  if (env.HH_USER_AGENT) {
43
36
  config.headers['User-Agent'] = env.HH_USER_AGENT;
@@ -46,6 +39,16 @@ apiClient.interceptors.request.use((config) => {
46
39
  }, (error) => {
47
40
  return Promise.reject(error);
48
41
  });
42
+ function handleResult(data) {
43
+ return {
44
+ content: [
45
+ {
46
+ type: 'text',
47
+ text: JSON.stringify(data, null, 2),
48
+ },
49
+ ],
50
+ };
51
+ }
49
52
  function handleError(error) {
50
53
  console.error(error);
51
54
  logger.error('Error occurred:', JSON.stringify(error));
@@ -61,20 +64,12 @@ function handleError(error) {
61
64
  content: [{ type: 'text', text: `Error: ${error}` }],
62
65
  };
63
66
  }
64
- // Tools
65
67
  mcpServer.tool('get-vacancies', `Search for vacancies`, {}, async (args) => {
66
68
  try {
67
69
  const response = await apiClient.get('/vacancies', {
68
70
  params: args,
69
71
  });
70
- return {
71
- content: [
72
- {
73
- type: 'text',
74
- text: JSON.stringify(response.data, null, 2),
75
- },
76
- ],
77
- };
72
+ return handleResult(response.data);
78
73
  }
79
74
  catch (error) {
80
75
  return handleError(error);
@@ -85,14 +80,7 @@ mcpServer.tool('get-dictionaries', `Directories of fields`, {}, async (args) =>
85
80
  const response = await apiClient.get('/dictionaries', {
86
81
  params: args,
87
82
  });
88
- return {
89
- content: [
90
- {
91
- type: 'text',
92
- text: JSON.stringify(response.data, null, 2),
93
- },
94
- ],
95
- };
83
+ return handleResult(response.data);
96
84
  }
97
85
  catch (error) {
98
86
  return handleError(error);
@@ -103,14 +91,7 @@ mcpServer.tool('get-areas', `Tree view of all regions`, {}, async (args) => {
103
91
  const response = await apiClient.get('/areas', {
104
92
  params: args,
105
93
  });
106
- return {
107
- content: [
108
- {
109
- type: 'text',
110
- text: JSON.stringify(response.data, null, 2),
111
- },
112
- ],
113
- };
94
+ return handleResult(response.data);
114
95
  }
115
96
  catch (error) {
116
97
  return handleError(error);
@@ -121,14 +102,7 @@ mcpServer.tool('get-languages', `The list of all languages`, {}, async (args) =>
121
102
  const response = await apiClient.get('/languages', {
122
103
  params: args,
123
104
  });
124
- return {
125
- content: [
126
- {
127
- type: 'text',
128
- text: JSON.stringify(response.data, null, 2),
129
- },
130
- ],
131
- };
105
+ return handleResult(response.data);
132
106
  }
133
107
  catch (error) {
134
108
  return handleError(error);
@@ -139,14 +113,7 @@ mcpServer.tool('get-industries', `Industries`, {}, async (args) => {
139
113
  const response = await apiClient.get('/industries', {
140
114
  params: args,
141
115
  });
142
- return {
143
- content: [
144
- {
145
- type: 'text',
146
- text: JSON.stringify(response.data, null, 2),
147
- },
148
- ],
149
- };
116
+ return handleResult(response.data);
150
117
  }
151
118
  catch (error) {
152
119
  return handleError(error);
@@ -157,14 +124,7 @@ mcpServer.tool('get-metro', `The list of metro stations in all cities`, {}, asyn
157
124
  const response = await apiClient.get('/metro', {
158
125
  params: args,
159
126
  });
160
- return {
161
- content: [
162
- {
163
- type: 'text',
164
- text: JSON.stringify(response.data, null, 2),
165
- },
166
- ],
167
- };
127
+ return handleResult(response.data);
168
128
  }
169
129
  catch (error) {
170
130
  return handleError(error);
@@ -175,14 +135,7 @@ mcpServer.tool('get-professional-roles', `Professional role directory`, {}, asyn
175
135
  const response = await apiClient.get('/professional_roles', {
176
136
  params: args,
177
137
  });
178
- return {
179
- content: [
180
- {
181
- type: 'text',
182
- text: JSON.stringify(response.data, null, 2),
183
- },
184
- ],
185
- };
138
+ return handleResult(response.data);
186
139
  }
187
140
  catch (error) {
188
141
  return handleError(error);
@@ -193,14 +146,7 @@ mcpServer.tool('get-employers', `Employer search`, {}, async (args) => {
193
146
  const response = await apiClient.get('/employers', {
194
147
  params: args,
195
148
  });
196
- return {
197
- content: [
198
- {
199
- type: 'text',
200
- text: JSON.stringify(response.data, null, 2),
201
- },
202
- ],
203
- };
149
+ return handleResult(response.data);
204
150
  }
205
151
  catch (error) {
206
152
  return handleError(error);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sargonpiraev/hh-mcp-server",
3
- "version": "1.9.0",
3
+ "version": "1.11.0",
4
4
  "description": "MCP Server for HeadHunter API - job search and vacancy management",
5
5
  "keywords": [
6
6
  "mcp",