universal-mcp-applications 0.1.33__py3-none-any.whl → 0.1.39rc16__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.

Potentially problematic release.


This version of universal-mcp-applications might be problematic. Click here for more details.

Files changed (119) hide show
  1. universal_mcp/applications/BEST_PRACTICES.md +1 -1
  2. universal_mcp/applications/ahrefs/app.py +92 -238
  3. universal_mcp/applications/airtable/app.py +36 -135
  4. universal_mcp/applications/apollo/app.py +124 -477
  5. universal_mcp/applications/asana/app.py +605 -1755
  6. universal_mcp/applications/aws_s3/app.py +63 -119
  7. universal_mcp/applications/bill/app.py +644 -2055
  8. universal_mcp/applications/box/app.py +1246 -4159
  9. universal_mcp/applications/braze/app.py +410 -1476
  10. universal_mcp/applications/browser_use/README.md +15 -1
  11. universal_mcp/applications/browser_use/__init__.py +1 -0
  12. universal_mcp/applications/browser_use/app.py +91 -26
  13. universal_mcp/applications/cal_com_v2/app.py +207 -625
  14. universal_mcp/applications/calendly/app.py +103 -242
  15. universal_mcp/applications/canva/app.py +75 -140
  16. universal_mcp/applications/clickup/app.py +331 -798
  17. universal_mcp/applications/coda/app.py +240 -520
  18. universal_mcp/applications/confluence/app.py +497 -1285
  19. universal_mcp/applications/contentful/app.py +40 -155
  20. universal_mcp/applications/crustdata/app.py +44 -123
  21. universal_mcp/applications/dialpad/app.py +451 -924
  22. universal_mcp/applications/digitalocean/app.py +2071 -6082
  23. universal_mcp/applications/domain_checker/app.py +3 -54
  24. universal_mcp/applications/e2b/app.py +17 -68
  25. universal_mcp/applications/elevenlabs/README.md +27 -3
  26. universal_mcp/applications/elevenlabs/app.py +741 -74
  27. universal_mcp/applications/exa/README.md +8 -4
  28. universal_mcp/applications/exa/app.py +415 -186
  29. universal_mcp/applications/falai/README.md +5 -7
  30. universal_mcp/applications/falai/app.py +156 -232
  31. universal_mcp/applications/figma/app.py +91 -175
  32. universal_mcp/applications/file_system/app.py +2 -13
  33. universal_mcp/applications/firecrawl/app.py +198 -176
  34. universal_mcp/applications/fireflies/app.py +59 -281
  35. universal_mcp/applications/fpl/app.py +92 -529
  36. universal_mcp/applications/fpl/utils/fixtures.py +15 -49
  37. universal_mcp/applications/fpl/utils/helper.py +25 -89
  38. universal_mcp/applications/fpl/utils/league_utils.py +20 -64
  39. universal_mcp/applications/ghost_content/app.py +70 -179
  40. universal_mcp/applications/github/app.py +30 -67
  41. universal_mcp/applications/gong/app.py +142 -302
  42. universal_mcp/applications/google_calendar/app.py +26 -78
  43. universal_mcp/applications/google_docs/README.md +15 -14
  44. universal_mcp/applications/google_docs/app.py +103 -206
  45. universal_mcp/applications/google_drive/app.py +194 -793
  46. universal_mcp/applications/google_gemini/app.py +68 -59
  47. universal_mcp/applications/google_mail/README.md +1 -0
  48. universal_mcp/applications/google_mail/app.py +93 -214
  49. universal_mcp/applications/google_searchconsole/app.py +25 -58
  50. universal_mcp/applications/google_sheet/README.md +2 -1
  51. universal_mcp/applications/google_sheet/app.py +226 -624
  52. universal_mcp/applications/google_sheet/helper.py +26 -53
  53. universal_mcp/applications/hashnode/app.py +57 -269
  54. universal_mcp/applications/heygen/README.md +10 -32
  55. universal_mcp/applications/heygen/app.py +339 -811
  56. universal_mcp/applications/http_tools/app.py +10 -32
  57. universal_mcp/applications/hubspot/README.md +1 -1
  58. universal_mcp/applications/hubspot/app.py +7508 -99
  59. universal_mcp/applications/jira/app.py +2419 -8334
  60. universal_mcp/applications/klaviyo/app.py +739 -1621
  61. universal_mcp/applications/linkedin/README.md +18 -1
  62. universal_mcp/applications/linkedin/app.py +729 -251
  63. universal_mcp/applications/mailchimp/app.py +696 -1851
  64. universal_mcp/applications/markitdown/app.py +8 -20
  65. universal_mcp/applications/miro/app.py +333 -815
  66. universal_mcp/applications/ms_teams/app.py +420 -1407
  67. universal_mcp/applications/neon/app.py +144 -250
  68. universal_mcp/applications/notion/app.py +38 -53
  69. universal_mcp/applications/onedrive/app.py +26 -48
  70. universal_mcp/applications/openai/app.py +43 -166
  71. universal_mcp/applications/outlook/README.md +22 -9
  72. universal_mcp/applications/outlook/app.py +403 -141
  73. universal_mcp/applications/perplexity/README.md +2 -1
  74. universal_mcp/applications/perplexity/app.py +161 -20
  75. universal_mcp/applications/pipedrive/app.py +1021 -3331
  76. universal_mcp/applications/posthog/app.py +272 -541
  77. universal_mcp/applications/reddit/app.py +65 -164
  78. universal_mcp/applications/resend/app.py +72 -139
  79. universal_mcp/applications/retell/app.py +23 -50
  80. universal_mcp/applications/rocketlane/app.py +252 -965
  81. universal_mcp/applications/scraper/app.py +114 -142
  82. universal_mcp/applications/semanticscholar/app.py +36 -78
  83. universal_mcp/applications/semrush/app.py +44 -78
  84. universal_mcp/applications/sendgrid/app.py +826 -1576
  85. universal_mcp/applications/sentry/app.py +444 -1079
  86. universal_mcp/applications/serpapi/app.py +44 -146
  87. universal_mcp/applications/sharepoint/app.py +27 -49
  88. universal_mcp/applications/shopify/app.py +1748 -4486
  89. universal_mcp/applications/shortcut/app.py +275 -536
  90. universal_mcp/applications/slack/app.py +43 -125
  91. universal_mcp/applications/spotify/app.py +206 -405
  92. universal_mcp/applications/supabase/app.py +174 -283
  93. universal_mcp/applications/tavily/app.py +2 -2
  94. universal_mcp/applications/trello/app.py +853 -2816
  95. universal_mcp/applications/twilio/app.py +27 -62
  96. universal_mcp/applications/twitter/api_segments/compliance_api.py +4 -14
  97. universal_mcp/applications/twitter/api_segments/dm_conversations_api.py +6 -18
  98. universal_mcp/applications/twitter/api_segments/likes_api.py +1 -3
  99. universal_mcp/applications/twitter/api_segments/lists_api.py +5 -15
  100. universal_mcp/applications/twitter/api_segments/trends_api.py +1 -3
  101. universal_mcp/applications/twitter/api_segments/tweets_api.py +9 -31
  102. universal_mcp/applications/twitter/api_segments/usage_api.py +1 -5
  103. universal_mcp/applications/twitter/api_segments/users_api.py +14 -42
  104. universal_mcp/applications/whatsapp/app.py +35 -186
  105. universal_mcp/applications/whatsapp/audio.py +2 -6
  106. universal_mcp/applications/whatsapp/whatsapp.py +17 -51
  107. universal_mcp/applications/whatsapp_business/app.py +86 -299
  108. universal_mcp/applications/wrike/app.py +80 -153
  109. universal_mcp/applications/yahoo_finance/app.py +19 -65
  110. universal_mcp/applications/youtube/app.py +120 -306
  111. universal_mcp/applications/zenquotes/app.py +3 -3
  112. {universal_mcp_applications-0.1.33.dist-info → universal_mcp_applications-0.1.39rc16.dist-info}/METADATA +4 -2
  113. {universal_mcp_applications-0.1.33.dist-info → universal_mcp_applications-0.1.39rc16.dist-info}/RECORD +115 -119
  114. {universal_mcp_applications-0.1.33.dist-info → universal_mcp_applications-0.1.39rc16.dist-info}/WHEEL +1 -1
  115. universal_mcp/applications/hubspot/api_segments/__init__.py +0 -0
  116. universal_mcp/applications/hubspot/api_segments/api_segment_base.py +0 -54
  117. universal_mcp/applications/hubspot/api_segments/crm_api.py +0 -7337
  118. universal_mcp/applications/hubspot/api_segments/marketing_api.py +0 -1467
  119. {universal_mcp_applications-0.1.33.dist-info → universal_mcp_applications-0.1.39rc16.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
 
@@ -9,7 +8,7 @@ class SlackApp(APIApplication):
9
8
  super().__init__(name="slack", integration=integration, **kwargs)
10
9
  self.base_url = "https://slack.com/api"
11
10
 
12
- def _get_headers(self) -> dict[str, str]:
11
+ async def _aget_headers(self) -> dict[str, str]:
13
12
  """
14
13
  Get headers for Slack API requests.
15
14
  Prioritizes user-scoped access token from raw.authed_user.access_token
@@ -17,35 +16,22 @@ class SlackApp(APIApplication):
17
16
  """
18
17
  if not self.integration:
19
18
  raise ValueError("Integration not configured for SlackApp")
20
-
21
- credentials = self.integration.get_credentials()
19
+ credentials = await self.integration.get_credentials_async()
22
20
  if not credentials:
23
21
  raise ValueError("No credentials found for Slack integration")
24
-
25
22
  access_token = None
26
- raw = credentials.get('raw', {})
27
- if isinstance(raw, dict) and 'authed_user' in raw:
28
- authed_user = raw.get('authed_user', {})
23
+ raw = credentials.get("raw", {})
24
+ if isinstance(raw, dict) and "authed_user" in raw:
25
+ authed_user = raw.get("authed_user", {})
29
26
  if isinstance(authed_user, dict):
30
- access_token = authed_user.get('access_token')
31
-
27
+ access_token = authed_user.get("access_token")
32
28
  if not access_token:
33
- access_token = credentials.get('access_token')
34
-
29
+ access_token = credentials.get("access_token")
35
30
  if not access_token:
36
31
  raise ValueError("Access token not found in Slack credentials")
37
-
38
- return {
39
- "Authorization": f"Bearer {access_token}",
40
- "Content-Type": "application/json",
41
- }
32
+ return {"Authorization": f"Bearer {access_token}", "Content-Type": "application/json"}
42
33
 
43
- def chat_delete(
44
- self,
45
- as_user: bool | None = None,
46
- channel: str | None = None,
47
- ts: float | None = None,
48
- ) -> dict[str, Any]:
34
+ async def chat_delete(self, as_user: bool | None = None, channel: str | None = None, ts: float | None = None) -> dict[str, Any]:
49
35
  """
50
36
  Deletes a specific message from a Slack channel. It identifies the message using its channel ID and timestamp (`ts`). This function is distinct from `chat_update` which modifies a message, and `chat_post_message` which sends a new one.
51
37
 
@@ -64,25 +50,14 @@ class SlackApp(APIApplication):
64
50
  chat
65
51
  """
66
52
  request_body_data = None
67
- request_body_data = {
68
- "as_user": as_user,
69
- "channel": channel,
70
- "ts": ts,
71
- }
72
- request_body_data = {
73
- k: v for k, v in request_body_data.items() if v is not None
74
- }
53
+ request_body_data = {"as_user": as_user, "channel": channel, "ts": ts}
54
+ request_body_data = {k: v for k, v in request_body_data.items() if v is not None}
75
55
  url = f"{self.base_url}/chat.delete"
76
56
  query_params = {}
77
- response = self._post(
78
- url,
79
- data=request_body_data,
80
- params=query_params,
81
- content_type="application/x-www-form-urlencoded",
82
- )
57
+ response = await self._apost(url, data=request_body_data, params=query_params, content_type="application/x-www-form-urlencoded")
83
58
  return self._handle_response(response)
84
59
 
85
- def chat_post_message(
60
+ async def chat_post_message(
86
61
  self,
87
62
  as_user: bool | None = None,
88
63
  attachments: str | None = None,
@@ -147,20 +122,13 @@ class SlackApp(APIApplication):
147
122
  "unfurl_media": unfurl_media,
148
123
  "username": username,
149
124
  }
150
- request_body_data = {
151
- k: v for k, v in request_body_data.items() if v is not None
152
- }
125
+ request_body_data = {k: v for k, v in request_body_data.items() if v is not None}
153
126
  url = f"{self.base_url}/chat.postMessage"
154
127
  query_params = {}
155
- response = self._post(
156
- url,
157
- data=request_body_data,
158
- params=query_params,
159
- content_type="application/x-www-form-urlencoded",
160
- )
128
+ response = await self._apost(url, data=request_body_data, params=query_params, content_type="application/x-www-form-urlencoded")
161
129
  return self._handle_response(response)
162
130
 
163
- def chat_update(
131
+ async def chat_update(
164
132
  self,
165
133
  as_user: str | None = None,
166
134
  attachments: str | None = None,
@@ -204,20 +172,13 @@ class SlackApp(APIApplication):
204
172
  "text": text,
205
173
  "ts": ts,
206
174
  }
207
- request_body_data = {
208
- k: v for k, v in request_body_data.items() if v is not None
209
- }
175
+ request_body_data = {k: v for k, v in request_body_data.items() if v is not None}
210
176
  url = f"{self.base_url}/chat.update"
211
177
  query_params = {}
212
- response = self._post(
213
- url,
214
- data=request_body_data,
215
- params=query_params,
216
- content_type="application/x-www-form-urlencoded",
217
- )
178
+ response = await self._apost(url, data=request_body_data, params=query_params, content_type="application/x-www-form-urlencoded")
218
179
  return self._handle_response(response)
219
180
 
220
- def conversations_history(
181
+ async def conversations_history(
221
182
  self,
222
183
  token: str | None = None,
223
184
  channel: str | None = None,
@@ -262,10 +223,10 @@ class SlackApp(APIApplication):
262
223
  ]
263
224
  if v is not None
264
225
  }
265
- response = self._get(url, params=query_params)
226
+ response = await self._aget(url, params=query_params)
266
227
  return self._handle_response(response)
267
228
 
268
- def conversations_list(
229
+ async def conversations_list(
269
230
  self,
270
231
  token: str | None = None,
271
232
  exclude_archived: bool | None = None,
@@ -295,19 +256,13 @@ class SlackApp(APIApplication):
295
256
  url = f"{self.base_url}/conversations.list"
296
257
  query_params = {
297
258
  k: v
298
- for k, v in [
299
- ("token", token),
300
- ("exclude_archived", exclude_archived),
301
- ("types", types),
302
- ("limit", limit),
303
- ("cursor", cursor),
304
- ]
259
+ for k, v in [("token", token), ("exclude_archived", exclude_archived), ("types", types), ("limit", limit), ("cursor", cursor)]
305
260
  if v is not None
306
261
  }
307
- response = self._get(url, params=query_params)
262
+ response = await self._aget(url, params=query_params)
308
263
  return self._handle_response(response)
309
264
 
310
- def reactions_add(self, channel: str, name: str, timestamp: str) -> dict[str, Any]:
265
+ async def reactions_add(self, channel: str, name: str, timestamp: str) -> dict[str, Any]:
311
266
  """
312
267
  Adds a specific emoji reaction to a message in a Slack channel, identifying the message by its channel ID and timestamp. This method creates a new reaction, unlike `reactions_get` or `reactions_list` which retrieve existing reaction data for items or users.
313
268
 
@@ -326,25 +281,14 @@ class SlackApp(APIApplication):
326
281
  reactions
327
282
  """
328
283
  request_body_data = None
329
- request_body_data = {
330
- "channel": channel,
331
- "name": name,
332
- "timestamp": timestamp,
333
- }
334
- request_body_data = {
335
- k: v for k, v in request_body_data.items() if v is not None
336
- }
284
+ request_body_data = {"channel": channel, "name": name, "timestamp": timestamp}
285
+ request_body_data = {k: v for k, v in request_body_data.items() if v is not None}
337
286
  url = f"{self.base_url}/reactions.add"
338
287
  query_params = {}
339
- response = self._post(
340
- url,
341
- data=request_body_data,
342
- params=query_params,
343
- content_type="application/x-www-form-urlencoded",
344
- )
288
+ response = await self._apost(url, data=request_body_data, params=query_params, content_type="application/x-www-form-urlencoded")
345
289
  return self._handle_response(response)
346
290
 
347
- def get_reactions_for_item(
291
+ async def get_reactions_for_item(
348
292
  self,
349
293
  token: str,
350
294
  channel: str | None = None,
@@ -386,10 +330,10 @@ class SlackApp(APIApplication):
386
330
  ]
387
331
  if v is not None
388
332
  }
389
- response = self._get(url, params=query_params)
333
+ response = await self._aget(url, params=query_params)
390
334
  return self._handle_response(response)
391
335
 
392
- def get_user_reactions(
336
+ async def get_user_reactions(
393
337
  self,
394
338
  token: str,
395
339
  user: str | None = None,
@@ -434,10 +378,10 @@ class SlackApp(APIApplication):
434
378
  ]
435
379
  if v is not None
436
380
  }
437
- response = self._get(url, params=query_params)
381
+ response = await self._aget(url, params=query_params)
438
382
  return self._handle_response(response)
439
383
 
440
- def search_messages(
384
+ async def search_messages(
441
385
  self,
442
386
  token: str,
443
387
  query: str,
@@ -482,10 +426,10 @@ class SlackApp(APIApplication):
482
426
  ]
483
427
  if v is not None
484
428
  }
485
- response = self._get(url, params=query_params)
429
+ response = await self._aget(url, params=query_params)
486
430
  return self._handle_response(response)
487
431
 
488
- def team_info(self, token: str, team: str | None = None) -> dict[str, Any]:
432
+ async def team_info(self, token: str, team: str | None = None) -> dict[str, Any]:
489
433
  """
490
434
  Fetches details for a Slack team, such as name and domain, by calling the `team.info` API endpoint. This function requires an authentication token and can optionally target a specific team by its ID, distinguishing it from user or channel-specific functions.
491
435
 
@@ -503,18 +447,11 @@ class SlackApp(APIApplication):
503
447
  team
504
448
  """
505
449
  url = f"{self.base_url}/team.info"
506
- query_params = {
507
- k: v for k, v in [("token", token), ("team", team)] if v is not None
508
- }
509
- response = self._get(url, params=query_params)
450
+ query_params = {k: v for k, v in [("token", token), ("team", team)] if v is not None}
451
+ response = await self._aget(url, params=query_params)
510
452
  return self._handle_response(response)
511
453
 
512
- def get_user_info(
513
- self,
514
- token: str,
515
- include_locale: bool | None = None,
516
- user: str | None = None,
517
- ) -> dict[str, Any]:
454
+ async def get_user_info(self, token: str, include_locale: bool | None = None, user: str | None = None) -> dict[str, Any]:
518
455
  """
519
456
  Fetches detailed profile information for a single Slack user, identified by their user ID. Unlike `users_list`, which retrieves all workspace members, this function targets an individual and can optionally include their locale information. It directly calls the `users.info` Slack API endpoint.
520
457
 
@@ -533,24 +470,12 @@ class SlackApp(APIApplication):
533
470
  users, important
534
471
  """
535
472
  url = f"{self.base_url}/users.info"
536
- query_params = {
537
- k: v
538
- for k, v in [
539
- ("token", token),
540
- ("include_locale", include_locale),
541
- ("user", user),
542
- ]
543
- if v is not None
544
- }
545
- response = self._get(url, params=query_params)
473
+ query_params = {k: v for k, v in [("token", token), ("include_locale", include_locale), ("user", user)] if v is not None}
474
+ response = await self._aget(url, params=query_params)
546
475
  return self._handle_response(response)
547
476
 
548
- def users_list(
549
- self,
550
- token: str | None = None,
551
- limit: int | None = None,
552
- cursor: str | None = None,
553
- include_locale: bool | None = None,
477
+ async def users_list(
478
+ self, token: str | None = None, limit: int | None = None, cursor: str | None = None, include_locale: bool | None = None
554
479
  ) -> dict[str, Any]:
555
480
  """
556
481
  Fetches a paginated list of all users in a Slack workspace, including deactivated members. Unlike `users_info` which retrieves a single user's details, this function returns a collection and supports limiting results or including locale data through optional parameters.
@@ -572,16 +497,9 @@ class SlackApp(APIApplication):
572
497
  """
573
498
  url = f"{self.base_url}/users.list"
574
499
  query_params = {
575
- k: v
576
- for k, v in [
577
- ("token", token),
578
- ("limit", limit),
579
- ("cursor", cursor),
580
- ("include_locale", include_locale),
581
- ]
582
- if v is not None
500
+ k: v for k, v in [("token", token), ("limit", limit), ("cursor", cursor), ("include_locale", include_locale)] if v is not None
583
501
  }
584
- response = self._get(url, params=query_params)
502
+ response = await self._aget(url, params=query_params)
585
503
  return self._handle_response(response)
586
504
 
587
505
  def list_tools(self):