universal-mcp 0.1.8rc2__py3-none-any.whl → 0.1.8rc4__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.
Files changed (53) hide show
  1. universal_mcp/__init__.py +0 -2
  2. universal_mcp/analytics.py +75 -0
  3. universal_mcp/applications/ahrefs/README.md +76 -0
  4. universal_mcp/applications/ahrefs/__init__.py +0 -0
  5. universal_mcp/applications/ahrefs/app.py +2291 -0
  6. universal_mcp/applications/application.py +94 -5
  7. universal_mcp/applications/calendly/app.py +412 -171
  8. universal_mcp/applications/coda/README.md +133 -0
  9. universal_mcp/applications/coda/__init__.py +0 -0
  10. universal_mcp/applications/coda/app.py +3671 -0
  11. universal_mcp/applications/e2b/app.py +8 -35
  12. universal_mcp/applications/figma/README.md +74 -0
  13. universal_mcp/applications/figma/__init__.py +0 -0
  14. universal_mcp/applications/figma/app.py +1261 -0
  15. universal_mcp/applications/firecrawl/app.py +3 -33
  16. universal_mcp/applications/github/app.py +41 -42
  17. universal_mcp/applications/google_calendar/app.py +20 -31
  18. universal_mcp/applications/google_docs/app.py +21 -46
  19. universal_mcp/applications/google_drive/app.py +53 -76
  20. universal_mcp/applications/google_mail/app.py +40 -56
  21. universal_mcp/applications/google_sheet/app.py +43 -68
  22. universal_mcp/applications/markitdown/app.py +4 -4
  23. universal_mcp/applications/notion/app.py +93 -83
  24. universal_mcp/applications/perplexity/app.py +4 -38
  25. universal_mcp/applications/reddit/app.py +32 -32
  26. universal_mcp/applications/resend/app.py +4 -22
  27. universal_mcp/applications/serpapi/app.py +6 -32
  28. universal_mcp/applications/tavily/app.py +4 -24
  29. universal_mcp/applications/wrike/app.py +565 -237
  30. universal_mcp/applications/youtube/app.py +625 -183
  31. universal_mcp/applications/zenquotes/app.py +3 -3
  32. universal_mcp/exceptions.py +1 -0
  33. universal_mcp/integrations/__init__.py +11 -2
  34. universal_mcp/integrations/agentr.py +27 -4
  35. universal_mcp/integrations/integration.py +14 -6
  36. universal_mcp/logger.py +3 -56
  37. universal_mcp/servers/__init__.py +2 -1
  38. universal_mcp/servers/server.py +73 -77
  39. universal_mcp/stores/store.py +5 -3
  40. universal_mcp/tools/__init__.py +1 -1
  41. universal_mcp/tools/adapters.py +4 -1
  42. universal_mcp/tools/func_metadata.py +5 -6
  43. universal_mcp/tools/tools.py +108 -51
  44. universal_mcp/utils/docgen.py +121 -69
  45. universal_mcp/utils/docstring_parser.py +44 -21
  46. universal_mcp/utils/dump_app_tools.py +33 -23
  47. universal_mcp/utils/installation.py +199 -8
  48. universal_mcp/utils/openapi.py +121 -47
  49. {universal_mcp-0.1.8rc2.dist-info → universal_mcp-0.1.8rc4.dist-info}/METADATA +2 -2
  50. universal_mcp-0.1.8rc4.dist-info/RECORD +81 -0
  51. universal_mcp-0.1.8rc2.dist-info/RECORD +0 -71
  52. {universal_mcp-0.1.8rc2.dist-info → universal_mcp-0.1.8rc4.dist-info}/WHEEL +0 -0
  53. {universal_mcp-0.1.8rc2.dist-info → universal_mcp-0.1.8rc4.dist-info}/entry_points.txt +0 -0
@@ -4,7 +4,6 @@ import httpx
4
4
  from loguru import logger
5
5
 
6
6
  from universal_mcp.applications.application import APIApplication
7
- from universal_mcp.exceptions import NotAuthorizedError
8
7
  from universal_mcp.integrations import Integration
9
8
 
10
9
 
@@ -18,34 +17,18 @@ class GoogleDriveApp(APIApplication):
18
17
  super().__init__(name="google-drive", integration=integration)
19
18
  self.base_url = "https://www.googleapis.com/drive/v3"
20
19
 
21
- def _get_headers(self):
22
- if not self.integration:
23
- raise ValueError("Integration not configured for GoogleDriveApp")
24
- credentials = self.integration.get_credentials()
25
- if not credentials:
26
- logger.warning("No Google Drive credentials found via integration.")
27
- action = self.integration.authorize()
28
- raise NotAuthorizedError(action)
29
-
30
- if "headers" in credentials:
31
- return credentials["headers"]
32
- return {
33
- "Authorization": f"Bearer {credentials['access_token']}",
34
- "Content-Type": "application/json",
35
- }
36
-
37
20
  def get_drive_info(self) -> dict[str, Any]:
38
21
  """
39
22
  Retrieves detailed information about the user's Google Drive storage and account.
40
-
23
+
41
24
  Returns:
42
25
  A dictionary containing Drive information including storage quota (usage, limit) and user details (name, email, etc.).
43
-
26
+
44
27
  Raises:
45
28
  HTTPError: If the API request fails or returns an error status code
46
29
  ConnectionError: If there are network connectivity issues
47
30
  AuthenticationError: If the authentication credentials are invalid or expired
48
-
31
+
49
32
  Tags:
50
33
  get, info, storage, drive, quota, user, api, important
51
34
  """
@@ -54,22 +37,24 @@ class GoogleDriveApp(APIApplication):
54
37
  response = self._get(url, params=params)
55
38
  return response.json()
56
39
 
57
- def list_files(self, page_size: int = 10, query: str = None, order_by: str = None) -> dict[str, Any]:
40
+ def list_files(
41
+ self, page_size: int = 10, query: str = None, order_by: str = None
42
+ ) -> dict[str, Any]:
58
43
  """
59
44
  Lists and retrieves files from Google Drive with optional filtering, pagination, and sorting.
60
-
45
+
61
46
  Args:
62
47
  page_size: Maximum number of files to return per page (default: 10)
63
48
  query: Optional search query string using Google Drive query syntax (e.g., "mimeType='image/jpeg'")
64
49
  order_by: Optional field name to sort results by, with optional direction (e.g., "modifiedTime desc")
65
-
50
+
66
51
  Returns:
67
52
  Dictionary containing a list of files and metadata, including 'files' array and optional 'nextPageToken' for pagination
68
-
53
+
69
54
  Raises:
70
55
  HTTPError: Raised when the API request fails or returns an error status code
71
56
  RequestException: Raised when network connectivity issues occur during the API request
72
-
57
+
73
58
  Tags:
74
59
  list, files, search, google-drive, pagination, important
75
60
  """
@@ -84,22 +69,21 @@ class GoogleDriveApp(APIApplication):
84
69
  response = self._get(url, params=params)
85
70
  response.raise_for_status()
86
71
  return response.json()
87
-
88
72
 
89
73
  def get_file(self, file_id: str) -> dict[str, Any]:
90
74
  """
91
75
  Retrieves detailed metadata for a specific file using its ID.
92
-
76
+
93
77
  Args:
94
78
  file_id: String identifier of the file whose metadata should be retrieved
95
-
79
+
96
80
  Returns:
97
81
  Dictionary containing the file's metadata including properties such as name, size, type, and other attributes
98
-
82
+
99
83
  Raises:
100
84
  HTTPError: When the API request fails due to invalid file_id or network issues
101
85
  JSONDecodeError: When the API response cannot be parsed as JSON
102
-
86
+
103
87
  Tags:
104
88
  retrieve, file, metadata, get, api, important
105
89
  """
@@ -110,16 +94,16 @@ class GoogleDriveApp(APIApplication):
110
94
  def delete_file(self, file_id: str) -> dict[str, Any]:
111
95
  """
112
96
  Deletes a specified file from Google Drive and returns a status message.
113
-
97
+
114
98
  Args:
115
99
  file_id: The unique identifier string of the file to be deleted from Google Drive
116
-
100
+
117
101
  Returns:
118
102
  A dictionary containing either a success message {'message': 'File deleted successfully'} or an error message {'error': 'error description'}
119
-
103
+
120
104
  Raises:
121
105
  Exception: When the DELETE request fails due to network issues, invalid file_id, insufficient permissions, or other API errors
122
-
106
+
123
107
  Tags:
124
108
  delete, file-management, google-drive, api, important
125
109
  """
@@ -129,37 +113,34 @@ class GoogleDriveApp(APIApplication):
129
113
  return {"message": "File deleted successfully"}
130
114
  except Exception as e:
131
115
  return {"error": str(e)}
132
-
116
+
133
117
  def create_file_from_text(
134
118
  self,
135
119
  file_name: str,
136
120
  text_content: str,
137
121
  parent_id: str = None,
138
- mime_type: str = "text/plain"
122
+ mime_type: str = "text/plain",
139
123
  ) -> dict[str, Any]:
140
124
  """
141
125
  Creates a new file in Google Drive with specified text content and returns the file's metadata.
142
-
126
+
143
127
  Args:
144
128
  file_name: Name of the file to create on Google Drive
145
129
  text_content: Plain text content to be written to the file
146
130
  parent_id: Optional ID of the parent folder where the file will be created
147
131
  mime_type: MIME type of the file (defaults to 'text/plain')
148
-
132
+
149
133
  Returns:
150
134
  Dictionary containing metadata of the created file including ID, name, and other Google Drive file properties
151
-
135
+
152
136
  Raises:
153
137
  HTTPStatusError: Raised when the API request fails during file creation or content upload
154
138
  UnicodeEncodeError: Raised when the text_content cannot be encoded in UTF-8
155
-
139
+
156
140
  Tags:
157
141
  create, file, upload, drive, text, important, storage, document
158
142
  """
159
- metadata = {
160
- "name": file_name,
161
- "mimeType": mime_type
162
- }
143
+ metadata = {"name": file_name, "mimeType": mime_type}
163
144
  if parent_id:
164
145
  metadata["parents"] = [parent_id]
165
146
  create_url = f"{self.base_url}/files"
@@ -170,27 +151,25 @@ class GoogleDriveApp(APIApplication):
170
151
  upload_headers = self._get_headers()
171
152
  upload_headers["Content-Type"] = f"{mime_type}; charset=utf-8"
172
153
  upload_response = httpx.patch(
173
- upload_url,
174
- headers=upload_headers,
175
- content=text_content.encode("utf-8")
154
+ upload_url, headers=upload_headers, content=text_content.encode("utf-8")
176
155
  )
177
156
  upload_response.raise_for_status()
178
157
  response_data = upload_response.json()
179
158
  return response_data
180
-
159
+
181
160
  def find_folder_id_by_name(self, folder_name: str) -> str | None:
182
161
  """
183
162
  Searches for and retrieves a Google Drive folder's ID using its name.
184
-
163
+
185
164
  Args:
186
165
  folder_name: The name of the folder to search for in Google Drive
187
-
166
+
188
167
  Returns:
189
168
  str | None: The folder's ID if a matching folder is found, None if no folder is found or if an error occurs
190
-
169
+
191
170
  Raises:
192
171
  Exception: Caught internally and logged when API requests fail or response parsing errors occur
193
-
172
+
194
173
  Tags:
195
174
  search, find, google-drive, folder, query, api, utility
196
175
  """
@@ -198,35 +177,36 @@ class GoogleDriveApp(APIApplication):
198
177
  try:
199
178
  response = self._get(
200
179
  f"{self.base_url}/files",
201
- params={"q": query, "fields": "files(id,name)"}
180
+ params={"q": query, "fields": "files(id,name)"},
202
181
  )
203
182
  files = response.json().get("files", [])
204
183
  return files[0]["id"] if files else None
205
184
  except Exception as e:
206
185
  logger.error(f"Error finding folder ID by name: {e}")
207
186
  return None
208
-
187
+
209
188
  def create_folder(self, folder_name: str, parent_id: str = None) -> dict[str, Any]:
210
189
  """
211
190
  Creates a new folder in Google Drive with optional parent folder specification
212
-
191
+
213
192
  Args:
214
193
  folder_name: Name of the folder to create
215
194
  parent_id: ID or name of the parent folder. Can be either a folder ID string or a folder name that will be automatically looked up
216
-
195
+
217
196
  Returns:
218
197
  Dictionary containing the created folder's metadata including its ID, name, and other Drive-specific information
219
-
198
+
220
199
  Raises:
221
200
  ValueError: Raised when a parent folder name is provided but cannot be found in Google Drive
222
-
201
+
223
202
  Tags:
224
203
  create, folder, drive, storage, important, management
225
204
  """
226
205
  import re
206
+
227
207
  metadata = {
228
208
  "name": folder_name,
229
- "mimeType": "application/vnd.google-apps.folder"
209
+ "mimeType": "application/vnd.google-apps.folder",
230
210
  }
231
211
  if parent_id:
232
212
  if not re.match(r"^[a-zA-Z0-9_-]{28,33}$", parent_id):
@@ -234,7 +214,9 @@ class GoogleDriveApp(APIApplication):
234
214
  if found_id:
235
215
  metadata["parents"] = [found_id]
236
216
  else:
237
- raise ValueError(f"Could not find parent folder with name: {parent_id}")
217
+ raise ValueError(
218
+ f"Could not find parent folder with name: {parent_id}"
219
+ )
238
220
  else:
239
221
  metadata["parents"] = [parent_id]
240
222
  url = f"{self.base_url}/files"
@@ -247,49 +229,44 @@ class GoogleDriveApp(APIApplication):
247
229
  file_name: str,
248
230
  file_path: str,
249
231
  parent_id: str = None,
250
- mime_type: str = None
232
+ mime_type: str = None,
251
233
  ) -> dict[str, Any]:
252
234
  """
253
235
  Uploads a file to Google Drive by creating a file metadata entry and uploading the binary content.
254
-
236
+
255
237
  Args:
256
238
  file_name: Name to give the file on Google Drive
257
239
  file_path: Path to the local file to upload
258
240
  parent_id: Optional ID of the parent folder to create the file in
259
241
  mime_type: MIME type of the file (e.g., 'image/jpeg', 'image/png', 'application/pdf')
260
-
242
+
261
243
  Returns:
262
244
  Dictionary containing the uploaded file's metadata from Google Drive
263
-
245
+
264
246
  Raises:
265
247
  FileNotFoundError: When the specified file_path does not exist or is not accessible
266
248
  HTTPError: When the API request fails or returns an error status code
267
249
  IOError: When there are issues reading the file content
268
-
250
+
269
251
  Tags:
270
252
  upload, file-handling, google-drive, api, important, binary, storage
271
253
  """
272
- metadata = {
273
- "name": file_name,
274
- "mimeType": mime_type
275
- }
254
+ metadata = {"name": file_name, "mimeType": mime_type}
276
255
  if parent_id:
277
256
  metadata["parents"] = [parent_id]
278
257
  create_url = f"{self.base_url}/files"
279
258
  create_response = self._post(create_url, data=metadata)
280
259
  file_data = create_response.json()
281
260
  file_id = file_data.get("id")
282
- with open(file_path, 'rb') as file_content:
261
+ with open(file_path, "rb") as file_content:
283
262
  binary_content = file_content.read()
284
-
263
+
285
264
  upload_url = f"https://www.googleapis.com/upload/drive/v3/files/{file_id}?uploadType=media"
286
265
  upload_headers = self._get_headers()
287
266
  upload_headers["Content-Type"] = mime_type
288
-
267
+
289
268
  upload_response = httpx.patch(
290
- upload_url,
291
- headers=upload_headers,
292
- content=binary_content
269
+ upload_url, headers=upload_headers, content=binary_content
293
270
  )
294
271
  upload_response.raise_for_status()
295
272
  response_data = upload_response.json()
@@ -306,4 +283,4 @@ class GoogleDriveApp(APIApplication):
306
283
  self.create_folder,
307
284
  self.get_file,
308
285
  self.delete_file,
309
- ]
286
+ ]
@@ -13,39 +13,23 @@ class GoogleMailApp(APIApplication):
13
13
  super().__init__(name="google-mail", integration=integration)
14
14
  self.base_api_url = "https://gmail.googleapis.com/gmail/v1/users/me"
15
15
 
16
- def _get_headers(self):
17
- if not self.integration:
18
- raise ValueError("Integration not configured for GmailApp")
19
- credentials = self.integration.get_credentials()
20
- if not credentials:
21
- logger.warning("No Gmail credentials found via integration.")
22
- action = self.integration.authorize()
23
- raise NotAuthorizedError(action)
24
-
25
- if "headers" in credentials:
26
- return credentials["headers"]
27
- return {
28
- "Authorization": f"Bearer {credentials['access_token']}",
29
- "Content-Type": "application/json",
30
- }
31
-
32
16
  def send_email(self, to: str, subject: str, body: str) -> str:
33
17
  """
34
18
  Sends an email using the Gmail API and returns a confirmation or error message.
35
-
19
+
36
20
  Args:
37
21
  to: The email address of the recipient
38
22
  subject: The subject line of the email
39
23
  body: The main content of the email message
40
-
24
+
41
25
  Returns:
42
26
  A string containing either a success confirmation message or an error description
43
-
27
+
44
28
  Raises:
45
29
  NotAuthorizedError: When Gmail API authentication is not valid or has expired
46
30
  KeyError: When required configuration keys are missing
47
31
  Exception: For any other unexpected errors during the email sending process
48
-
32
+
49
33
  Tags:
50
34
  send, email, api, communication, important
51
35
  """
@@ -100,20 +84,20 @@ class GoogleMailApp(APIApplication):
100
84
  def create_draft(self, to: str, subject: str, body: str) -> str:
101
85
  """
102
86
  Creates a draft email message in Gmail using the Gmail API and returns a confirmation status.
103
-
87
+
104
88
  Args:
105
89
  to: The email address of the recipient
106
90
  subject: The subject line of the draft email
107
91
  body: The main content/message of the draft email
108
-
92
+
109
93
  Returns:
110
94
  A string containing either a success message with the draft ID or an error message describing the failure
111
-
95
+
112
96
  Raises:
113
97
  NotAuthorizedError: When the user's Gmail API authorization is invalid or expired
114
98
  KeyError: When required configuration keys are missing
115
99
  Exception: For general API errors, network issues, or other unexpected problems
116
-
100
+
117
101
  Tags:
118
102
  create, email, draft, gmail, api, important
119
103
  """
@@ -149,18 +133,18 @@ class GoogleMailApp(APIApplication):
149
133
  def send_draft(self, draft_id: str) -> str:
150
134
  """
151
135
  Sends an existing draft email using the Gmail API and returns a confirmation message.
152
-
136
+
153
137
  Args:
154
138
  draft_id: The unique identifier of the Gmail draft to be sent
155
-
139
+
156
140
  Returns:
157
141
  A string containing either a success message with the sent message ID or an error message detailing the failure reason
158
-
142
+
159
143
  Raises:
160
144
  NotAuthorizedError: When the user's Gmail API authorization is invalid or expired
161
145
  KeyError: When required configuration keys are missing from the API response
162
146
  Exception: For other unexpected errors during the API request or response handling
163
-
147
+
164
148
  Tags:
165
149
  send, email, api, communication, important, draft
166
150
  """
@@ -194,19 +178,19 @@ class GoogleMailApp(APIApplication):
194
178
  def get_draft(self, draft_id: str, format: str = "full") -> str:
195
179
  """
196
180
  Retrieves and formats a specific draft email from Gmail by its ID
197
-
181
+
198
182
  Args:
199
183
  draft_id: String identifier of the draft email to retrieve
200
184
  format: Output format of the draft (options: minimal, full, raw, metadata). Defaults to 'full'
201
-
185
+
202
186
  Returns:
203
187
  A formatted string containing the draft email details (ID, recipient, subject) or an error message if retrieval fails
204
-
188
+
205
189
  Raises:
206
190
  NotAuthorizedError: When the user's Gmail authorization is invalid or expired
207
191
  KeyError: When required configuration keys or response data fields are missing
208
192
  Exception: For any other unexpected errors during draft retrieval
209
-
193
+
210
194
  Tags:
211
195
  retrieve, email, gmail, draft, api, format, important
212
196
  """
@@ -261,20 +245,20 @@ class GoogleMailApp(APIApplication):
261
245
  ) -> str:
262
246
  """
263
247
  Retrieves and formats a list of email drafts from the user's Gmail mailbox with optional filtering and pagination.
264
-
248
+
265
249
  Args:
266
250
  max_results: Maximum number of drafts to return (max 500, default 20)
267
251
  q: Search query string to filter drafts using Gmail search syntax (default None)
268
252
  include_spam_trash: Boolean flag to include drafts from spam and trash folders (default False)
269
-
253
+
270
254
  Returns:
271
255
  A formatted string containing the list of draft IDs and count information, or an error message if the request fails
272
-
256
+
273
257
  Raises:
274
258
  NotAuthorizedError: When the Gmail API authentication is missing or invalid
275
259
  KeyError: When required configuration keys are missing
276
260
  Exception: For general errors during API communication or data processing
277
-
261
+
278
262
  Tags:
279
263
  list, email, drafts, gmail, api, search, query, pagination, important
280
264
  """
@@ -333,18 +317,18 @@ class GoogleMailApp(APIApplication):
333
317
  def get_message(self, message_id: str) -> str:
334
318
  """
335
319
  Retrieves and formats a specific email message from Gmail API by its ID, including sender, recipient, date, subject, and message preview.
336
-
320
+
337
321
  Args:
338
322
  message_id: The unique identifier of the Gmail message to retrieve
339
-
323
+
340
324
  Returns:
341
325
  A formatted string containing the message details (ID, From, To, Date, Subject, Preview) or an error message if the retrieval fails
342
-
326
+
343
327
  Raises:
344
328
  NotAuthorizedError: When the request lacks proper Gmail API authorization
345
329
  KeyError: When required configuration keys or message fields are missing
346
330
  Exception: For general API communication errors or unexpected issues
347
-
331
+
348
332
  Tags:
349
333
  retrieve, email, format, api, gmail, message, important
350
334
  """
@@ -406,20 +390,20 @@ class GoogleMailApp(APIApplication):
406
390
  ) -> str:
407
391
  """
408
392
  Retrieves and formats a list of messages from the user's Gmail mailbox with optional filtering and pagination support.
409
-
393
+
410
394
  Args:
411
395
  max_results: Maximum number of messages to return (max 500, default 20)
412
396
  q: Search query string to filter messages using Gmail search syntax
413
397
  include_spam_trash: Boolean flag to include messages from spam and trash folders (default False)
414
-
398
+
415
399
  Returns:
416
400
  A formatted string containing the list of message IDs and thread IDs, or an error message if the operation fails
417
-
401
+
418
402
  Raises:
419
403
  NotAuthorizedError: When the Gmail API authentication is invalid or missing
420
404
  KeyError: When required configuration keys are missing
421
405
  Exception: For general API errors, network issues, or other unexpected problems
422
-
406
+
423
407
  Tags:
424
408
  list, messages, gmail, search, query, pagination, important
425
409
  """
@@ -482,17 +466,17 @@ class GoogleMailApp(APIApplication):
482
466
  def list_labels(self) -> str:
483
467
  """
484
468
  Retrieves and formats a list of all labels (both system and user-created) from the user's Gmail account, organizing them by type and sorting them alphabetically.
485
-
469
+
486
470
  Args:
487
471
  None: This method takes no arguments
488
-
472
+
489
473
  Returns:
490
474
  A formatted string containing a list of Gmail labels categorized by type (system and user), with their IDs, or an error message if the operation fails.
491
-
475
+
492
476
  Raises:
493
477
  NotAuthorizedError: Raised when the user's Gmail authorization is invalid or missing
494
478
  Exception: Raised when any other unexpected error occurs during the API request or data processing
495
-
479
+
496
480
  Tags:
497
481
  list, gmail, labels, fetch, organize, important, management
498
482
  """
@@ -562,17 +546,17 @@ class GoogleMailApp(APIApplication):
562
546
  def create_label(self, name: str) -> str:
563
547
  """
564
548
  Creates a new Gmail label with specified visibility settings and returns creation status details.
565
-
549
+
566
550
  Args:
567
551
  name: The display name of the label to create
568
-
552
+
569
553
  Returns:
570
554
  A formatted string containing the creation status, including the new label's name and ID if successful, or an error message if the creation fails
571
-
555
+
572
556
  Raises:
573
557
  NotAuthorizedError: Raised when the request lacks proper Gmail API authorization
574
558
  Exception: Raised for any other unexpected errors during label creation
575
-
559
+
576
560
  Tags:
577
561
  create, label, gmail, management, important
578
562
  """
@@ -615,17 +599,17 @@ class GoogleMailApp(APIApplication):
615
599
  def get_profile(self) -> str:
616
600
  """
617
601
  Retrieves and formats the user's Gmail profile information including email address, message count, thread count, and history ID.
618
-
602
+
619
603
  Args:
620
604
  None: This method takes no arguments besides self
621
-
605
+
622
606
  Returns:
623
607
  A formatted string containing the user's Gmail profile information or an error message if the request fails
624
-
608
+
625
609
  Raises:
626
610
  NotAuthorizedError: Raised when the user's credentials are invalid or authorization is required
627
611
  Exception: Raised for any other unexpected errors during the API request or data processing
628
-
612
+
629
613
  Tags:
630
614
  fetch, profile, gmail, user-info, api-request, important
631
615
  """