universal-mcp-applications 0.1.32__py3-none-any.whl → 0.1.36rc2__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 (105) hide show
  1. universal_mcp/applications/ahrefs/app.py +52 -198
  2. universal_mcp/applications/airtable/app.py +23 -122
  3. universal_mcp/applications/apollo/app.py +111 -464
  4. universal_mcp/applications/asana/app.py +417 -1567
  5. universal_mcp/applications/aws_s3/app.py +36 -103
  6. universal_mcp/applications/bill/app.py +546 -1957
  7. universal_mcp/applications/box/app.py +1068 -3981
  8. universal_mcp/applications/braze/app.py +364 -1430
  9. universal_mcp/applications/browser_use/app.py +2 -8
  10. universal_mcp/applications/cal_com_v2/app.py +207 -625
  11. universal_mcp/applications/calendly/app.py +61 -200
  12. universal_mcp/applications/canva/app.py +45 -110
  13. universal_mcp/applications/clickup/app.py +207 -674
  14. universal_mcp/applications/coda/app.py +146 -426
  15. universal_mcp/applications/confluence/app.py +310 -1098
  16. universal_mcp/applications/contentful/app.py +36 -151
  17. universal_mcp/applications/crustdata/app.py +28 -107
  18. universal_mcp/applications/dialpad/app.py +283 -756
  19. universal_mcp/applications/digitalocean/app.py +1766 -5777
  20. universal_mcp/applications/domain_checker/app.py +3 -54
  21. universal_mcp/applications/e2b/app.py +14 -64
  22. universal_mcp/applications/elevenlabs/app.py +9 -47
  23. universal_mcp/applications/exa/app.py +6 -17
  24. universal_mcp/applications/falai/app.py +24 -101
  25. universal_mcp/applications/figma/app.py +53 -137
  26. universal_mcp/applications/file_system/app.py +2 -13
  27. universal_mcp/applications/firecrawl/app.py +51 -152
  28. universal_mcp/applications/fireflies/app.py +59 -281
  29. universal_mcp/applications/fpl/app.py +91 -528
  30. universal_mcp/applications/fpl/utils/fixtures.py +15 -49
  31. universal_mcp/applications/fpl/utils/helper.py +25 -89
  32. universal_mcp/applications/fpl/utils/league_utils.py +20 -64
  33. universal_mcp/applications/ghost_content/app.py +52 -161
  34. universal_mcp/applications/github/app.py +19 -56
  35. universal_mcp/applications/gong/app.py +88 -248
  36. universal_mcp/applications/google_calendar/app.py +16 -68
  37. universal_mcp/applications/google_docs/app.py +85 -189
  38. universal_mcp/applications/google_drive/app.py +141 -463
  39. universal_mcp/applications/google_gemini/app.py +12 -64
  40. universal_mcp/applications/google_mail/app.py +28 -157
  41. universal_mcp/applications/google_searchconsole/app.py +15 -48
  42. universal_mcp/applications/google_sheet/app.py +100 -581
  43. universal_mcp/applications/google_sheet/helper.py +10 -37
  44. universal_mcp/applications/hashnode/app.py +57 -269
  45. universal_mcp/applications/heygen/app.py +44 -122
  46. universal_mcp/applications/http_tools/app.py +10 -32
  47. universal_mcp/applications/hubspot/api_segments/crm_api.py +460 -1573
  48. universal_mcp/applications/hubspot/api_segments/marketing_api.py +74 -262
  49. universal_mcp/applications/hubspot/app.py +23 -87
  50. universal_mcp/applications/jira/app.py +2071 -7986
  51. universal_mcp/applications/klaviyo/app.py +494 -1376
  52. universal_mcp/applications/linkedin/README.md +9 -2
  53. universal_mcp/applications/linkedin/app.py +240 -181
  54. universal_mcp/applications/mailchimp/app.py +450 -1605
  55. universal_mcp/applications/markitdown/app.py +8 -20
  56. universal_mcp/applications/miro/app.py +217 -699
  57. universal_mcp/applications/ms_teams/app.py +64 -186
  58. universal_mcp/applications/neon/app.py +86 -192
  59. universal_mcp/applications/notion/app.py +21 -36
  60. universal_mcp/applications/onedrive/app.py +16 -38
  61. universal_mcp/applications/openai/app.py +42 -165
  62. universal_mcp/applications/outlook/app.py +24 -84
  63. universal_mcp/applications/perplexity/app.py +4 -19
  64. universal_mcp/applications/pipedrive/app.py +832 -3142
  65. universal_mcp/applications/posthog/app.py +163 -432
  66. universal_mcp/applications/reddit/app.py +40 -139
  67. universal_mcp/applications/resend/app.py +41 -107
  68. universal_mcp/applications/retell/app.py +14 -41
  69. universal_mcp/applications/rocketlane/app.py +221 -934
  70. universal_mcp/applications/scraper/README.md +7 -4
  71. universal_mcp/applications/scraper/app.py +50 -109
  72. universal_mcp/applications/semanticscholar/app.py +22 -64
  73. universal_mcp/applications/semrush/app.py +43 -77
  74. universal_mcp/applications/sendgrid/app.py +512 -1262
  75. universal_mcp/applications/sentry/app.py +271 -906
  76. universal_mcp/applications/serpapi/app.py +40 -143
  77. universal_mcp/applications/sharepoint/app.py +17 -39
  78. universal_mcp/applications/shopify/app.py +1551 -4287
  79. universal_mcp/applications/shortcut/app.py +155 -417
  80. universal_mcp/applications/slack/app.py +33 -115
  81. universal_mcp/applications/spotify/app.py +126 -325
  82. universal_mcp/applications/supabase/app.py +104 -213
  83. universal_mcp/applications/tavily/app.py +1 -1
  84. universal_mcp/applications/trello/app.py +693 -2656
  85. universal_mcp/applications/twilio/app.py +14 -50
  86. universal_mcp/applications/twitter/api_segments/compliance_api.py +4 -14
  87. universal_mcp/applications/twitter/api_segments/dm_conversations_api.py +6 -18
  88. universal_mcp/applications/twitter/api_segments/likes_api.py +1 -3
  89. universal_mcp/applications/twitter/api_segments/lists_api.py +5 -15
  90. universal_mcp/applications/twitter/api_segments/trends_api.py +1 -3
  91. universal_mcp/applications/twitter/api_segments/tweets_api.py +9 -31
  92. universal_mcp/applications/twitter/api_segments/usage_api.py +1 -5
  93. universal_mcp/applications/twitter/api_segments/users_api.py +14 -42
  94. universal_mcp/applications/whatsapp/app.py +35 -186
  95. universal_mcp/applications/whatsapp/audio.py +2 -6
  96. universal_mcp/applications/whatsapp/whatsapp.py +17 -51
  97. universal_mcp/applications/whatsapp_business/app.py +70 -283
  98. universal_mcp/applications/wrike/app.py +45 -118
  99. universal_mcp/applications/yahoo_finance/app.py +19 -65
  100. universal_mcp/applications/youtube/app.py +75 -261
  101. universal_mcp/applications/zenquotes/app.py +2 -2
  102. {universal_mcp_applications-0.1.32.dist-info → universal_mcp_applications-0.1.36rc2.dist-info}/METADATA +2 -2
  103. {universal_mcp_applications-0.1.32.dist-info → universal_mcp_applications-0.1.36rc2.dist-info}/RECORD +105 -105
  104. {universal_mcp_applications-0.1.32.dist-info → universal_mcp_applications-0.1.36rc2.dist-info}/WHEEL +0 -0
  105. {universal_mcp_applications-0.1.32.dist-info → universal_mcp_applications-0.1.36rc2.dist-info}/licenses/LICENSE +0 -0
@@ -1,5 +1,4 @@
1
1
  from typing import Any
2
-
3
2
  from universal_mcp.applications.application import APIApplication
4
3
  from universal_mcp.integrations import Integration
5
4
 
@@ -15,13 +14,9 @@ class NotionApp(APIApplication):
15
14
  credentials = self.integration.get_credentials()
16
15
  if "headers" in credentials:
17
16
  return credentials["headers"]
18
- return {
19
- "Authorization": f"Bearer {credentials['access_token']}",
20
- "Accept": "application/json",
21
- "Notion-Version": "2022-06-28",
22
- }
17
+ return {"Authorization": f"Bearer {credentials['access_token']}", "Accept": "application/json", "Notion-Version": "2022-06-28"}
23
18
 
24
- def retrieve_a_user(self, id, request_body=None) -> dict[str, Any]:
19
+ async def retrieve_a_user(self, id, request_body=None) -> dict[str, Any]:
25
20
  """
26
21
  Retrieves a user's details from the server using their unique identifier.
27
22
 
@@ -47,9 +42,7 @@ class NotionApp(APIApplication):
47
42
  response.raise_for_status()
48
43
  return response.json()
49
44
 
50
- def list_all_users(
51
- self,
52
- ) -> dict[str, Any]:
45
+ async def list_all_users(self) -> dict[str, Any]:
53
46
  """
54
47
  Retrieves a complete list of users from the API endpoint.
55
48
 
@@ -72,9 +65,7 @@ class NotionApp(APIApplication):
72
65
  response.raise_for_status()
73
66
  return response.json()
74
67
 
75
- def retrieve_your_token_sbot_user(
76
- self,
77
- ) -> dict[str, Any]:
68
+ async def retrieve_your_token_sbot_user(self) -> dict[str, Any]:
78
69
  """
79
70
  Retrieves the current user's authentication token information from the SBOT service.
80
71
 
@@ -94,7 +85,7 @@ class NotionApp(APIApplication):
94
85
  response.raise_for_status()
95
86
  return response.json()
96
87
 
97
- def retrieve_a_database(self, id) -> dict[str, Any]:
88
+ async def retrieve_a_database(self, id) -> dict[str, Any]:
98
89
  """
99
90
  Retrieves detailed information about a specific database using its unique identifier.
100
91
 
@@ -119,7 +110,7 @@ class NotionApp(APIApplication):
119
110
  response.raise_for_status()
120
111
  return response.json()
121
112
 
122
- def update_a_database(self, id, request_body=None) -> dict[str, Any]:
113
+ async def update_a_database(self, id, request_body=None) -> dict[str, Any]:
123
114
  """
124
115
  Updates a database entry with the specified ID using a PATCH request.
125
116
 
@@ -145,7 +136,7 @@ class NotionApp(APIApplication):
145
136
  response.raise_for_status()
146
137
  return response.json()
147
138
 
148
- def query_a_database(self, id, request_body=None) -> dict[str, Any]:
139
+ async def query_a_database(self, id, request_body=None) -> dict[str, Any]:
149
140
  """
150
141
  Executes a database query operation using a specified database ID and optional request parameters
151
142
 
@@ -171,7 +162,7 @@ class NotionApp(APIApplication):
171
162
  response.raise_for_status()
172
163
  return response.json()
173
164
 
174
- def create_a_database(self, request_body=None) -> dict[str, Any]:
165
+ async def create_a_database(self, request_body=None) -> dict[str, Any]:
175
166
  """
176
167
  Creates a new database on the server by sending a POST request to the database endpoint.
177
168
 
@@ -195,7 +186,7 @@ class NotionApp(APIApplication):
195
186
  response.raise_for_status()
196
187
  return response.json()
197
188
 
198
- def create_a_page(self, request_body=None) -> dict[str, Any]:
189
+ async def create_a_page(self, request_body=None) -> dict[str, Any]:
199
190
  """
200
191
  Creates a new page by sending a POST request to the API endpoint.
201
192
 
@@ -218,7 +209,7 @@ class NotionApp(APIApplication):
218
209
  response.raise_for_status()
219
210
  return response.json()
220
211
 
221
- def retrieve_a_page(self, id) -> dict[str, Any]:
212
+ async def retrieve_a_page(self, id) -> dict[str, Any]:
222
213
  """
223
214
  Retrieves a specific page's data from a remote server using its unique identifier.
224
215
 
@@ -243,7 +234,7 @@ class NotionApp(APIApplication):
243
234
  response.raise_for_status()
244
235
  return response.json()
245
236
 
246
- def update_page_properties(self, id, request_body=None) -> dict[str, Any]:
237
+ async def update_page_properties(self, id, request_body=None) -> dict[str, Any]:
247
238
  """
248
239
  Updates the properties of a page with the specified ID using the provided request body.
249
240
 
@@ -270,7 +261,7 @@ class NotionApp(APIApplication):
270
261
  response.raise_for_status()
271
262
  return response.json()
272
263
 
273
- def retrieve_a_page_property_item(self, page_id, property_id) -> dict[str, Any]:
264
+ async def retrieve_a_page_property_item(self, page_id, property_id) -> dict[str, Any]:
274
265
  """
275
266
  Retrieves a specific property item from a Notion page using the page ID and property ID.
276
267
 
@@ -298,7 +289,7 @@ class NotionApp(APIApplication):
298
289
  response.raise_for_status()
299
290
  return response.json()
300
291
 
301
- def retrieve_block_children(self, id, page_size=None) -> dict[str, Any]:
292
+ async def retrieve_block_children(self, id, page_size=None) -> dict[str, Any]:
302
293
  """
303
294
  Retrieves all child blocks for a specified parent block using its ID via the API.
304
295
 
@@ -324,7 +315,7 @@ class NotionApp(APIApplication):
324
315
  response.raise_for_status()
325
316
  return response.json()
326
317
 
327
- def append_block_children(self, id, request_body=None) -> dict[str, Any]:
318
+ async def append_block_children(self, id, request_body=None) -> dict[str, Any]:
328
319
  """
329
320
  Appends child elements to a specified block and returns the updated block data.
330
321
 
@@ -350,7 +341,7 @@ class NotionApp(APIApplication):
350
341
  response.raise_for_status()
351
342
  return response.json()
352
343
 
353
- def retrieve_a_block(self, id) -> dict[str, Any]:
344
+ async def retrieve_a_block(self, id) -> dict[str, Any]:
354
345
  """
355
346
  Retrieves a specific block of data from the API using its unique identifier.
356
347
 
@@ -375,7 +366,7 @@ class NotionApp(APIApplication):
375
366
  response.raise_for_status()
376
367
  return response.json()
377
368
 
378
- def delete_a_block(self, id) -> dict[str, Any]:
369
+ async def delete_a_block(self, id) -> dict[str, Any]:
379
370
  """
380
371
  Deletes a specified block by its ID and returns the server response.
381
372
 
@@ -400,7 +391,7 @@ class NotionApp(APIApplication):
400
391
  response.raise_for_status()
401
392
  return response.json()
402
393
 
403
- def update_a_block(self, id, request_body=None) -> dict[str, Any]:
394
+ async def update_a_block(self, id, request_body=None) -> dict[str, Any]:
404
395
  """
405
396
  Updates a specific block resource via a PATCH request to the API endpoint
406
397
 
@@ -426,7 +417,7 @@ class NotionApp(APIApplication):
426
417
  response.raise_for_status()
427
418
  return response.json()
428
419
 
429
- def search(self, request_body=None) -> dict[str, Any]:
420
+ async def search(self, request_body=None) -> dict[str, Any]:
430
421
  """
431
422
  Executes a search operation by sending a POST request to the search endpoint and returns the results
432
423
 
@@ -449,9 +440,7 @@ class NotionApp(APIApplication):
449
440
  response.raise_for_status()
450
441
  return response.json()
451
442
 
452
- def retrieve_comments(
453
- self, block_id=None, page_size=None, request_body=None
454
- ) -> dict[str, Any]:
443
+ async def retrieve_comments(self, block_id=None, page_size=None, request_body=None) -> dict[str, Any]:
455
444
  """
456
445
  Retrieves comments from a remote server with optional block filtering and pagination support.
457
446
 
@@ -471,16 +460,12 @@ class NotionApp(APIApplication):
471
460
  retrieve, fetch, comments, api, pagination, http
472
461
  """
473
462
  url = f"{self.base_url}/v1/comments"
474
- query_params = {
475
- k: v
476
- for k, v in [("block_id", block_id), ("page_size", page_size)]
477
- if v is not None
478
- }
463
+ query_params = {k: v for k, v in [("block_id", block_id), ("page_size", page_size)] if v is not None}
479
464
  response = self._get(url, params=query_params)
480
465
  response.raise_for_status()
481
466
  return response.json()
482
467
 
483
- def add_comment_to_page(self, request_body=None) -> dict[str, Any]:
468
+ async def add_comment_to_page(self, request_body=None) -> dict[str, Any]:
484
469
  """
485
470
  Adds a comment to a page by making an HTTP POST request to the comments endpoint.
486
471
 
@@ -1,7 +1,6 @@
1
1
  import base64
2
2
  import os
3
3
  from typing import Any
4
-
5
4
  from loguru import logger
6
5
  from universal_mcp.applications.application import APIApplication
7
6
  from universal_mcp.integrations import Integration
@@ -17,7 +16,7 @@ class OnedriveApp(APIApplication):
17
16
  super().__init__(name="onedrive", integration=integration, **kwargs)
18
17
  self.base_url = "https://graph.microsoft.com/v1.0"
19
18
 
20
- def get_my_profile(self) -> dict[str, Any]:
19
+ async def get_my_profile(self) -> dict[str, Any]:
21
20
  """
22
21
  Fetches the profile for the currently authenticated user, specifically retrieving their ID and user principal name. This function confirms user identity, distinguishing it from `get_drive_info`, which returns details about the OneDrive storage space (e.g., quota) rather than the user's personal profile.
23
22
 
@@ -35,7 +34,7 @@ class OnedriveApp(APIApplication):
35
34
  response = self._get(url, params=query_params)
36
35
  return self._handle_response(response)
37
36
 
38
- def get_drive_info(self) -> dict[str, Any]:
37
+ async def get_drive_info(self) -> dict[str, Any]:
39
38
  """
40
39
  Fetches high-level information about the user's entire OneDrive. It returns drive-wide details like the owner and storage quota, differing from `get_item_metadata` which describes a specific item, and `get_my_profile` which retrieves general user account information.
41
40
 
@@ -63,7 +62,7 @@ class OnedriveApp(APIApplication):
63
62
  response = self._get(url)
64
63
  return self._handle_response(response)
65
64
 
66
- def search_files(self, query: str) -> dict[str, Any]:
65
+ async def search_files(self, query: str) -> dict[str, Any]:
67
66
  """
68
67
  Searches the user's entire OneDrive for files and folders matching a specified text query. This function performs a comprehensive search from the drive's root, distinguishing it from `list_files` or `list_folders` which only browse the contents of a single directory.
69
68
 
@@ -78,12 +77,11 @@ class OnedriveApp(APIApplication):
78
77
  """
79
78
  if not query:
80
79
  raise ValueError("Search query cannot be empty.")
81
-
82
80
  url = f"{self.base_url}/me/drive/root/search(q='{query}')"
83
81
  response = self._get(url)
84
82
  return self._handle_response(response)
85
83
 
86
- def get_item_metadata(self, item_id: str) -> dict[str, Any]:
84
+ async def get_item_metadata(self, item_id: str) -> dict[str, Any]:
87
85
  """
88
86
  Fetches detailed metadata for a specific file or folder using its unique ID. It returns properties like name, size, and type. Unlike `get_document_content`, it doesn't retrieve the file's actual content, focusing solely on the item's attributes for quick inspection without a full download.
89
87
 
@@ -98,12 +96,11 @@ class OnedriveApp(APIApplication):
98
96
  """
99
97
  if not item_id:
100
98
  raise ValueError("Missing required parameter 'item_id'.")
101
-
102
99
  url = f"{self.base_url}/me/drive/items/{item_id}"
103
100
  response = self._get(url)
104
101
  return self._handle_response(response)
105
102
 
106
- def create_folder(self, name: str, parent_id: str = "root") -> dict[str, Any]:
103
+ async def create_folder(self, name: str, parent_id: str = "root") -> dict[str, Any]:
107
104
  """
108
105
  Creates a new folder with a specified name within a parent directory, which defaults to the root. Returns metadata for the new folder. Unlike `create_folder_and_list`, this function only creates the folder and returns its specific metadata, not the parent directory's contents.
109
106
 
@@ -119,13 +116,12 @@ class OnedriveApp(APIApplication):
119
116
  """
120
117
  if not name:
121
118
  raise ValueError("Folder name cannot be empty.")
122
-
123
119
  url = f"{self.base_url}/me/drive/items/{parent_id}/children"
124
120
  data = {"name": name, "folder": {}, "@microsoft.graph.conflictBehavior": "rename"}
125
121
  response = self._post(url, data=data)
126
122
  return self._handle_response(response)
127
123
 
128
- def delete_item(self, item_id: str) -> dict[str, Any]:
124
+ async def delete_item(self, item_id: str) -> dict[str, Any]:
129
125
  """
130
126
  Permanently deletes a specified file or folder from OneDrive using its unique item ID. This versatile function can remove any type of drive item, distinguished from functions that only list or create specific types. A successful deletion returns an empty response, confirming the item's removal.
131
127
 
@@ -140,12 +136,11 @@ class OnedriveApp(APIApplication):
140
136
  """
141
137
  if not item_id:
142
138
  raise ValueError("Missing required parameter 'item_id'.")
143
-
144
139
  url = f"{self.base_url}/me/drive/items/{item_id}"
145
140
  response = self._delete(url)
146
141
  return self._handle_response(response)
147
142
 
148
- def download_file(self, item_id: str) -> dict[str, Any]:
143
+ async def download_file(self, item_id: str) -> dict[str, Any]:
149
144
  """
150
145
  Retrieves a temporary, pre-authenticated download URL for a specific file using its item ID. This function provides a link for subsequent download, differing from `get_document_content` which directly fetches the file's raw content. The URL is returned within a dictionary.
151
146
 
@@ -160,7 +155,6 @@ class OnedriveApp(APIApplication):
160
155
  """
161
156
  if not item_id:
162
157
  raise ValueError("Missing required parameter 'item_id'.")
163
-
164
158
  url = f"{self.base_url}/me/drive/items/{item_id}"
165
159
  response = self._get(url)
166
160
  metadata = self._handle_response(response)
@@ -169,7 +163,7 @@ class OnedriveApp(APIApplication):
169
163
  raise ValueError("Could not retrieve download URL for the item.")
170
164
  return {"download_url": download_url}
171
165
 
172
- def upload_file(self, file_path: str, parent_id: str = "root", file_name: str | None = None) -> dict[str, Any]:
166
+ async def upload_file(self, file_path: str, parent_id: str = "root", file_name: str | None = None) -> dict[str, Any]:
173
167
  """
174
168
  Uploads a local binary file (under 4MB) from a given path to a specified OneDrive folder. Unlike `upload_text_file`, which uploads string content, this function reads from the filesystem. The destination filename can be customized, and it returns the new file's metadata upon completion.
175
169
 
@@ -186,17 +180,15 @@ class OnedriveApp(APIApplication):
186
180
  """
187
181
  if not os.path.exists(file_path):
188
182
  raise FileNotFoundError(f"The file was not found at path: {file_path}")
189
-
190
183
  if not file_name:
191
184
  file_name = os.path.basename(file_path)
192
-
193
185
  url = f"{self.base_url}/me/drive/items/{parent_id}:/{file_name}:/content"
194
186
  with open(file_path, "rb") as f:
195
187
  data = f.read()
196
188
  response = self._put(url, data=data, content_type="application/octet-stream")
197
189
  return self._handle_response(response)
198
190
 
199
- def list_folders(self, item_id: str = "root") -> dict[str, Any]:
191
+ async def list_folders(self, item_id: str = "root") -> dict[str, Any]:
200
192
  """
201
193
  Retrieves a list of only the folders within a specified parent directory in OneDrive. Unlike `_list_drive_items` which returns all items, this function filters the results to exclude files. Defaults to the root directory if no parent `item_id` is provided.
202
194
 
@@ -213,7 +205,7 @@ class OnedriveApp(APIApplication):
213
205
  folders = [item for item in all_items.get("value", []) if "folder" in item]
214
206
  return {"value": folders}
215
207
 
216
- def list_files(self, item_id: str = "root") -> dict[str, Any]:
208
+ async def list_files(self, item_id: str = "root") -> dict[str, Any]:
217
209
  """
218
210
  Retrieves a list of files within a specified OneDrive folder, defaulting to the root. Unlike `_list_drive_items` which fetches all items, this function filters the results to exclusively return items identified as files, excluding any subdirectories.
219
211
 
@@ -230,7 +222,7 @@ class OnedriveApp(APIApplication):
230
222
  files = [item for item in all_items.get("value", []) if "file" in item]
231
223
  return {"value": files}
232
224
 
233
- def create_folder_and_list(self, name: str, parent_id: str = "root") -> dict[str, Any]:
225
+ async def create_folder_and_list(self, name: str, parent_id: str = "root") -> dict[str, Any]:
234
226
  """
235
227
  Performs a composite action: creates a new folder, then lists all items (files and folders) within that parent directory. This confirms creation by returning the parent's updated contents, distinct from `create_folder` which only returns the new folder's metadata.
236
228
 
@@ -244,10 +236,10 @@ class OnedriveApp(APIApplication):
244
236
  Tags:
245
237
  create, folder, list, important
246
238
  """
247
- self.create_folder(name=name, parent_id=parent_id)
239
+ await self.create_folder(name=name, parent_id=parent_id)
248
240
  return self._list_drive_items(item_id=parent_id)
249
241
 
250
- def upload_text_file(self, content: str, parent_id: str = "root", file_name: str = "new_file.txt") -> dict[str, Any]:
242
+ async def upload_text_file(self, content: str, parent_id: str = "root", file_name: str = "new_file.txt") -> dict[str, Any]:
251
243
  """
252
244
  Creates and uploads a new file to OneDrive directly from a string of text content. Unlike `upload_file`, which requires a local file path, this function is specifically for creating a text file from in-memory string data, with a customizable name and destination folder.
253
245
 
@@ -264,13 +256,12 @@ class OnedriveApp(APIApplication):
264
256
  """
265
257
  if not file_name:
266
258
  raise ValueError("File name cannot be empty.")
267
-
268
259
  url = f"{self.base_url}/me/drive/items/{parent_id}:/{file_name}:/content"
269
260
  data = content.encode("utf-8")
270
261
  response = self._put(url, data=data, content_type="text/plain")
271
262
  return self._handle_response(response)
272
263
 
273
- def get_document_content(self, item_id: str) -> dict[str, Any]:
264
+ async def get_document_content(self, item_id: str) -> dict[str, Any]:
274
265
  """
275
266
  Retrieves the content of a specific file by its item ID and returns it directly as base64-encoded data. This function is distinct from `download_file`, which only provides a temporary URL for the content, and from `get_item_metadata`, which returns file attributes without the content itself. The function fetches the content by following the file's pre-authenticated download URL.
276
267
 
@@ -289,36 +280,23 @@ class OnedriveApp(APIApplication):
289
280
  """
290
281
  if not item_id:
291
282
  raise ValueError("Missing required parameter 'item_id'.")
292
-
293
- metadata = self.get_item_metadata(item_id=item_id)
283
+ metadata = await self.get_item_metadata(item_id=item_id)
294
284
  file_metadata = metadata.get("file")
295
285
  if not file_metadata:
296
286
  raise ValueError(f"Item with ID '{item_id}' is not a file.")
297
-
298
287
  file_mime_type = file_metadata.get("mimeType", "application/octet-stream")
299
288
  file_name = metadata.get("name")
300
-
301
289
  download_url = metadata.get("@microsoft.graph.downloadUrl")
302
290
  if not download_url:
303
291
  logger.error(f"Could not find @microsoft.graph.downloadUrl in metadata for item {item_id}")
304
292
  raise ValueError("Could not retrieve download URL for the item.")
305
-
306
293
  response = self._get(download_url)
307
-
308
294
  response.raise_for_status()
309
-
310
295
  content = response.content
311
-
312
296
  attachment_type = file_mime_type.split("/")[0] if "/" in file_mime_type else "file"
313
297
  if attachment_type not in ["image", "audio", "video", "text"]:
314
298
  attachment_type = "file"
315
-
316
- return {
317
- "type": attachment_type,
318
- "data": content,
319
- "mime_type": file_mime_type,
320
- "file_name": file_name,
321
- }
299
+ return {"type": attachment_type, "data": content, "mime_type": file_mime_type, "file_name": file_name}
322
300
 
323
301
  def list_tools(self):
324
302
  return [