iflow-mcp_gmen1057-headhunter-mcp-server 0.1.0__py3-none-any.whl

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.
examples/oauth_flow.py ADDED
@@ -0,0 +1,177 @@
1
+ #!/usr/bin/env python3
2
+ """HeadHunter OAuth Authorization Flow Example.
3
+
4
+ This script demonstrates the complete OAuth 2.0 authorization flow for HeadHunter API.
5
+ It guides the user through the process of obtaining access and refresh tokens required
6
+ for authenticated API calls to HeadHunter services.
7
+
8
+ The OAuth flow consists of the following steps:
9
+ 1. Generate authorization URL with required parameters
10
+ 2. User opens the URL, authorizes the application, and gets authorization code
11
+ 3. Exchange the authorization code for access and refresh tokens
12
+ 4. Save tokens to .env file for use by the MCP server
13
+
14
+ This script is intended to be run once to set up authentication. The obtained
15
+ tokens can then be used by the HeadHunter MCP server for authenticated operations
16
+ such as job applications and resume management.
17
+
18
+ Required environment variables:
19
+ HH_CLIENT_ID: OAuth client ID from HeadHunter developer account
20
+ HH_CLIENT_SECRET: OAuth client secret from HeadHunter developer account
21
+ HH_REDIRECT_URI: Redirect URI registered in HeadHunter application settings
22
+
23
+ Usage:
24
+ python examples/oauth_flow.py
25
+
26
+ The script will:
27
+ - Display authorization URL for user to open in browser
28
+ - Prompt for authorization code from the redirect URL
29
+ - Exchange code for tokens
30
+ - Save tokens to .env file automatically
31
+ """
32
+
33
+ import os
34
+ import asyncio
35
+ import httpx
36
+ from dotenv import load_dotenv
37
+ from urllib.parse import urlencode
38
+
39
+ load_dotenv()
40
+
41
+ CLIENT_ID = os.getenv("HH_CLIENT_ID")
42
+ CLIENT_SECRET = os.getenv("HH_CLIENT_SECRET")
43
+ REDIRECT_URI = os.getenv("HH_REDIRECT_URI")
44
+
45
+
46
+ def get_auth_url():
47
+ """Generate HeadHunter OAuth authorization URL.
48
+
49
+ Constructs the authorization URL that users need to visit to grant
50
+ permission to the application. The URL includes the client ID and
51
+ redirect URI, and uses the authorization code grant type.
52
+
53
+ The user should open this URL in a browser, log in to their HeadHunter
54
+ account, and authorize the application. After authorization, they will
55
+ be redirected to the specified redirect URI with an authorization code.
56
+
57
+ Returns:
58
+ str: Complete authorization URL with query parameters including:
59
+ - response_type: Set to "code" for authorization code flow
60
+ - client_id: OAuth client ID from environment variables
61
+ - redirect_uri: Registered redirect URI from environment variables
62
+
63
+ Note:
64
+ Requires HH_CLIENT_ID and HH_REDIRECT_URI environment variables to be set.
65
+ """
66
+ params = {
67
+ "response_type": "code",
68
+ "client_id": CLIENT_ID,
69
+ "redirect_uri": REDIRECT_URI,
70
+ }
71
+ return f"https://hh.ru/oauth/authorize?{urlencode(params)}"
72
+
73
+
74
+ async def exchange_code(code: str):
75
+ """Exchange authorization code for OAuth tokens.
76
+
77
+ Makes a POST request to HeadHunter's token endpoint to exchange
78
+ the authorization code (received from the authorization step) for
79
+ access and refresh tokens.
80
+
81
+ This is the second step of the OAuth 2.0 authorization code flow.
82
+ The authorization code has a short lifetime and can only be used once.
83
+
84
+ Args:
85
+ code (str): Authorization code received from the HeadHunter
86
+ authorization redirect. This code is typically found in the
87
+ URL query parameter after user authorization.
88
+
89
+ Returns:
90
+ Dict[str, Any]: Token response containing:
91
+ - access_token (str): OAuth access token for authenticated API calls
92
+ - refresh_token (str): Token for refreshing expired access tokens
93
+ - expires_in (int): Access token lifetime in seconds
94
+ - token_type (str): Token type (typically "Bearer")
95
+
96
+ Raises:
97
+ httpx.HTTPError: If the token exchange fails due to invalid code,
98
+ client credentials, or other OAuth errors.
99
+
100
+ Note:
101
+ Requires HH_CLIENT_ID, HH_CLIENT_SECRET, and HH_REDIRECT_URI
102
+ environment variables to be set.
103
+ """
104
+ async with httpx.AsyncClient() as client:
105
+ response = await client.post(
106
+ "https://hh.ru/oauth/token",
107
+ data={
108
+ "grant_type": "authorization_code",
109
+ "client_id": CLIENT_ID,
110
+ "client_secret": CLIENT_SECRET,
111
+ "code": code,
112
+ "redirect_uri": REDIRECT_URI,
113
+ },
114
+ )
115
+ response.raise_for_status()
116
+ return response.json()
117
+
118
+
119
+ async def main():
120
+ """Main function that orchestrates the complete OAuth flow.
121
+
122
+ This function guides the user through the entire OAuth 2.0 authorization
123
+ process for HeadHunter API access. It provides a step-by-step interactive
124
+ experience to obtain and save authentication tokens.
125
+
126
+ The function performs the following steps:
127
+ 1. Display formatted instructions and authorization URL
128
+ 2. Wait for user to complete browser authorization and enter code
129
+ 3. Exchange the authorization code for tokens
130
+ 4. Display token information (partially masked for security)
131
+ 5. Automatically append tokens to .env file for future use
132
+
133
+ The saved tokens can then be used by the HeadHunter MCP server to make
134
+ authenticated API calls for user-specific operations like job applications
135
+ and resume management.
136
+
137
+ Raises:
138
+ Exception: If required environment variables are missing or if the
139
+ OAuth flow fails at any step.
140
+
141
+ Note:
142
+ This function modifies the .env file by appending the obtained tokens.
143
+ Existing content is preserved, and tokens are added with comments
144
+ indicating their expiration time.
145
+ """
146
+ print("=" * 60)
147
+ print("HeadHunter OAuth Authorization")
148
+ print("=" * 60)
149
+ print("\n1. Откройте эту ссылку в браузере:\n")
150
+ print(get_auth_url())
151
+ print("\n2. Авторизуйтесь и разрешите доступ")
152
+ print("3. Скопируйте код из URL (после ?code=)\n")
153
+
154
+ code = input("Введите код авторизации: ").strip()
155
+
156
+ print("\nОбмен кода на токены...")
157
+ tokens = await exchange_code(code)
158
+
159
+ print("\n✅ Успешно получены токены!")
160
+ print(f"Access Token: {tokens['access_token'][:50]}...")
161
+ print(f"Refresh Token: {tokens['refresh_token'][:50]}...")
162
+ print(f"Expires in: {tokens['expires_in']} seconds")
163
+
164
+ print("\n📝 Сохраните эти токены в .env файл:")
165
+ print(f"\nHH_ACCESS_TOKEN={tokens['access_token']}")
166
+ print(f"HH_REFRESH_TOKEN={tokens['refresh_token']}")
167
+
168
+ with open(".env", "a") as f:
169
+ f.write(f"\n\n# OAuth tokens (expires at {tokens['expires_in']} seconds)\n")
170
+ f.write(f"HH_ACCESS_TOKEN={tokens['access_token']}\n")
171
+ f.write(f"HH_REFRESH_TOKEN={tokens['refresh_token']}\n")
172
+
173
+ print("\n✅ Токены сохранены в .env файл")
174
+
175
+
176
+ if __name__ == "__main__":
177
+ asyncio.run(main())