universal-mcp-applications 0.1.22__py3-none-any.whl → 0.1.39rc8__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 (120) hide show
  1. universal_mcp/applications/ahrefs/app.py +92 -238
  2. universal_mcp/applications/airtable/app.py +23 -122
  3. universal_mcp/applications/apollo/app.py +122 -475
  4. universal_mcp/applications/asana/app.py +605 -1755
  5. universal_mcp/applications/aws_s3/app.py +36 -103
  6. universal_mcp/applications/bill/app.py +644 -2055
  7. universal_mcp/applications/box/app.py +1246 -4159
  8. universal_mcp/applications/braze/app.py +410 -1476
  9. universal_mcp/applications/browser_use/README.md +15 -1
  10. universal_mcp/applications/browser_use/__init__.py +1 -0
  11. universal_mcp/applications/browser_use/app.py +94 -37
  12. universal_mcp/applications/cal_com_v2/app.py +207 -625
  13. universal_mcp/applications/calendly/app.py +103 -242
  14. universal_mcp/applications/canva/app.py +75 -140
  15. universal_mcp/applications/clickup/app.py +331 -798
  16. universal_mcp/applications/coda/app.py +240 -520
  17. universal_mcp/applications/confluence/app.py +497 -1285
  18. universal_mcp/applications/contentful/app.py +36 -151
  19. universal_mcp/applications/crustdata/app.py +42 -121
  20. universal_mcp/applications/dialpad/app.py +451 -924
  21. universal_mcp/applications/digitalocean/app.py +2071 -6082
  22. universal_mcp/applications/domain_checker/app.py +3 -54
  23. universal_mcp/applications/e2b/app.py +14 -64
  24. universal_mcp/applications/elevenlabs/app.py +9 -47
  25. universal_mcp/applications/exa/README.md +8 -4
  26. universal_mcp/applications/exa/app.py +408 -186
  27. universal_mcp/applications/falai/app.py +24 -101
  28. universal_mcp/applications/figma/app.py +91 -175
  29. universal_mcp/applications/file_system/app.py +2 -13
  30. universal_mcp/applications/firecrawl/app.py +186 -163
  31. universal_mcp/applications/fireflies/app.py +59 -281
  32. universal_mcp/applications/fpl/app.py +92 -529
  33. universal_mcp/applications/fpl/utils/fixtures.py +15 -49
  34. universal_mcp/applications/fpl/utils/helper.py +25 -89
  35. universal_mcp/applications/fpl/utils/league_utils.py +20 -64
  36. universal_mcp/applications/ghost_content/app.py +66 -175
  37. universal_mcp/applications/github/app.py +28 -65
  38. universal_mcp/applications/gong/app.py +140 -300
  39. universal_mcp/applications/google_calendar/app.py +26 -78
  40. universal_mcp/applications/google_docs/app.py +324 -354
  41. universal_mcp/applications/google_drive/app.py +194 -793
  42. universal_mcp/applications/google_gemini/app.py +29 -64
  43. universal_mcp/applications/google_mail/README.md +1 -0
  44. universal_mcp/applications/google_mail/app.py +93 -214
  45. universal_mcp/applications/google_searchconsole/app.py +25 -58
  46. universal_mcp/applications/google_sheet/app.py +174 -623
  47. universal_mcp/applications/google_sheet/helper.py +26 -53
  48. universal_mcp/applications/hashnode/app.py +57 -269
  49. universal_mcp/applications/heygen/app.py +77 -155
  50. universal_mcp/applications/http_tools/app.py +10 -32
  51. universal_mcp/applications/hubspot/README.md +1 -1
  52. universal_mcp/applications/hubspot/app.py +7508 -99
  53. universal_mcp/applications/jira/app.py +2419 -8334
  54. universal_mcp/applications/klaviyo/app.py +737 -1619
  55. universal_mcp/applications/linkedin/README.md +23 -4
  56. universal_mcp/applications/linkedin/app.py +861 -155
  57. universal_mcp/applications/mailchimp/app.py +696 -1851
  58. universal_mcp/applications/markitdown/app.py +8 -20
  59. universal_mcp/applications/miro/app.py +333 -815
  60. universal_mcp/applications/ms_teams/app.py +85 -207
  61. universal_mcp/applications/neon/app.py +144 -250
  62. universal_mcp/applications/notion/app.py +36 -51
  63. universal_mcp/applications/onedrive/README.md +24 -0
  64. universal_mcp/applications/onedrive/__init__.py +1 -0
  65. universal_mcp/applications/onedrive/app.py +316 -0
  66. universal_mcp/applications/openai/app.py +42 -165
  67. universal_mcp/applications/outlook/README.md +22 -9
  68. universal_mcp/applications/outlook/app.py +606 -262
  69. universal_mcp/applications/perplexity/README.md +2 -1
  70. universal_mcp/applications/perplexity/app.py +162 -20
  71. universal_mcp/applications/pipedrive/app.py +1021 -3331
  72. universal_mcp/applications/posthog/app.py +272 -541
  73. universal_mcp/applications/reddit/app.py +88 -204
  74. universal_mcp/applications/resend/app.py +41 -107
  75. universal_mcp/applications/retell/app.py +23 -50
  76. universal_mcp/applications/rocketlane/app.py +250 -963
  77. universal_mcp/applications/scraper/README.md +7 -4
  78. universal_mcp/applications/scraper/app.py +245 -283
  79. universal_mcp/applications/semanticscholar/app.py +36 -78
  80. universal_mcp/applications/semrush/app.py +43 -77
  81. universal_mcp/applications/sendgrid/app.py +826 -1576
  82. universal_mcp/applications/sentry/app.py +444 -1079
  83. universal_mcp/applications/serpapi/app.py +40 -143
  84. universal_mcp/applications/sharepoint/README.md +16 -14
  85. universal_mcp/applications/sharepoint/app.py +245 -154
  86. universal_mcp/applications/shopify/app.py +1743 -4479
  87. universal_mcp/applications/shortcut/app.py +272 -534
  88. universal_mcp/applications/slack/app.py +58 -109
  89. universal_mcp/applications/spotify/app.py +206 -405
  90. universal_mcp/applications/supabase/app.py +174 -283
  91. universal_mcp/applications/tavily/app.py +2 -2
  92. universal_mcp/applications/trello/app.py +853 -2816
  93. universal_mcp/applications/twilio/app.py +14 -50
  94. universal_mcp/applications/twitter/api_segments/compliance_api.py +4 -14
  95. universal_mcp/applications/twitter/api_segments/dm_conversations_api.py +6 -18
  96. universal_mcp/applications/twitter/api_segments/likes_api.py +1 -3
  97. universal_mcp/applications/twitter/api_segments/lists_api.py +5 -15
  98. universal_mcp/applications/twitter/api_segments/trends_api.py +1 -3
  99. universal_mcp/applications/twitter/api_segments/tweets_api.py +9 -31
  100. universal_mcp/applications/twitter/api_segments/usage_api.py +1 -5
  101. universal_mcp/applications/twitter/api_segments/users_api.py +14 -42
  102. universal_mcp/applications/whatsapp/app.py +35 -186
  103. universal_mcp/applications/whatsapp/audio.py +2 -6
  104. universal_mcp/applications/whatsapp/whatsapp.py +17 -51
  105. universal_mcp/applications/whatsapp_business/app.py +86 -299
  106. universal_mcp/applications/wrike/app.py +80 -153
  107. universal_mcp/applications/yahoo_finance/app.py +19 -65
  108. universal_mcp/applications/youtube/app.py +120 -306
  109. universal_mcp/applications/zenquotes/app.py +4 -4
  110. {universal_mcp_applications-0.1.22.dist-info → universal_mcp_applications-0.1.39rc8.dist-info}/METADATA +4 -2
  111. {universal_mcp_applications-0.1.22.dist-info → universal_mcp_applications-0.1.39rc8.dist-info}/RECORD +113 -117
  112. {universal_mcp_applications-0.1.22.dist-info → universal_mcp_applications-0.1.39rc8.dist-info}/WHEEL +1 -1
  113. universal_mcp/applications/hubspot/api_segments/__init__.py +0 -0
  114. universal_mcp/applications/hubspot/api_segments/api_segment_base.py +0 -54
  115. universal_mcp/applications/hubspot/api_segments/crm_api.py +0 -7337
  116. universal_mcp/applications/hubspot/api_segments/marketing_api.py +0 -1467
  117. universal_mcp/applications/unipile/README.md +0 -28
  118. universal_mcp/applications/unipile/__init__.py +0 -1
  119. universal_mcp/applications/unipile/app.py +0 -1077
  120. {universal_mcp_applications-0.1.22.dist-info → universal_mcp_applications-0.1.39rc8.dist-info}/licenses/LICENSE +0 -0
@@ -1,5 +1,4 @@
1
1
  from typing import Any
2
-
3
2
  from loguru import logger
4
3
  from universal_mcp.applications.application import APIApplication
5
4
  from universal_mcp.integrations import Integration
@@ -17,12 +16,9 @@ class GithubApp(APIApplication):
17
16
  credentials = self.integration.get_credentials()
18
17
  if "headers" in credentials:
19
18
  return credentials["headers"]
20
- return {
21
- "Authorization": f"Bearer {credentials['access_token']}",
22
- "Accept": "application/vnd.github.v3+json",
23
- }
19
+ return {"Authorization": f"Bearer {credentials['access_token']}", "Accept": "application/vnd.github.v3+json"}
24
20
 
25
- def star_repository(self, repo_full_name: str) -> str:
21
+ async def star_repository(self, repo_full_name: str) -> str:
26
22
  """
27
23
  Stars a GitHub repository for the authenticated user. This user-centric action takes the full repository name ('owner/repo') and returns a simple string message confirming the outcome, unlike other functions that list or create repository content like issues or pull requests.
28
24
 
@@ -40,7 +36,7 @@ class GithubApp(APIApplication):
40
36
  star, github, api, action, social, repository, important
41
37
  """
42
38
  url = f"https://api.github.com/user/starred/{repo_full_name}"
43
- response = self._put(url, data={})
39
+ response = await self._aput(url, data={})
44
40
  if response.status_code == 204:
45
41
  return f"Successfully starred repository {repo_full_name}"
46
42
  elif response.status_code == 404:
@@ -49,7 +45,7 @@ class GithubApp(APIApplication):
49
45
  logger.error(response.text)
50
46
  return f"Error starring repository: {response.text}"
51
47
 
52
- def list_recent_commits(self, repo_full_name: str) -> str:
48
+ async def list_recent_commits(self, repo_full_name: str) -> str:
53
49
  """
54
50
  Fetches and formats the 12 most recent commits from a repository. It returns a human-readable string summarizing each commit's hash, author, and message, providing a focused overview of recent code changes, unlike functions that list branches, issues, or pull requests.
55
51
 
@@ -68,21 +64,20 @@ class GithubApp(APIApplication):
68
64
  """
69
65
  repo_full_name = repo_full_name.strip()
70
66
  url = f"{self.base_api_url}/{repo_full_name}/commits"
71
- response = self._get(url)
67
+ response = await self._aget(url)
72
68
  response.raise_for_status()
73
69
  commits = response.json()
74
70
  if not commits:
75
71
  return f"No commits found for repository {repo_full_name}"
76
72
  result = f"Recent commits for {repo_full_name}:\n\n"
77
- for commit in commits[:12]: # Limit to 12 commits
73
+ for commit in commits[:12]:
78
74
  sha = commit.get("sha", "")[:7]
79
75
  message = commit.get("commit", {}).get("message", "").split("\n")[0]
80
76
  author = commit.get("commit", {}).get("author", {}).get("name", "Unknown")
81
-
82
77
  result += f"- {sha}: {message} (by {author})\n"
83
78
  return result
84
79
 
85
- def list_branches(self, repo_full_name: str) -> str:
80
+ async def list_branches(self, repo_full_name: str) -> str:
86
81
  """
87
82
  Fetches all branches for a specified GitHub repository and formats them into a human-readable string. This method is distinct from others like `search_issues`, as it returns a formatted list for display rather than raw JSON data for programmatic use.
88
83
 
@@ -101,7 +96,7 @@ class GithubApp(APIApplication):
101
96
  """
102
97
  repo_full_name = repo_full_name.strip()
103
98
  url = f"{self.base_api_url}/{repo_full_name}/branches"
104
- response = self._get(url)
99
+ response = await self._aget(url)
105
100
  response.raise_for_status()
106
101
  branches = response.json()
107
102
  if not branches:
@@ -112,7 +107,7 @@ class GithubApp(APIApplication):
112
107
  result += f"- {branch_name}\n"
113
108
  return result
114
109
 
115
- def list_pull_requests(self, repo_full_name: str, state: str = "open") -> str:
110
+ async def list_pull_requests(self, repo_full_name: str, state: str = "open") -> str:
116
111
  """
117
112
  Fetches pull requests for a repository, filtered by state (e.g., 'open'). It returns a formatted string summarizing each PR's details, distinguishing it from `get_pull_request` (single PR) and `search_issues` (raw issue data).
118
113
 
@@ -132,7 +127,7 @@ class GithubApp(APIApplication):
132
127
  repo_full_name = repo_full_name.strip()
133
128
  url = f"{self.base_api_url}/{repo_full_name}/pulls"
134
129
  params = {"state": state}
135
- response = self._get(url, params=params)
130
+ response = await self._aget(url, params=params)
136
131
  response.raise_for_status()
137
132
  pull_requests = response.json()
138
133
  if not pull_requests:
@@ -143,20 +138,11 @@ class GithubApp(APIApplication):
143
138
  pr_number = pr.get("number", "Unknown")
144
139
  pr_state = pr.get("state", "Unknown")
145
140
  pr_user = pr.get("user", {}).get("login", "Unknown")
146
-
147
- result += (
148
- f"- PR #{pr_number}: {pr_title} (by {pr_user}, Status: {pr_state})\n"
149
- )
141
+ result += f"- PR #{pr_number}: {pr_title} (by {pr_user}, Status: {pr_state})\n"
150
142
  return result
151
143
 
152
- def search_issues(
153
- self,
154
- repo_full_name: str,
155
- state: str = "open",
156
- assignee: str = None,
157
- labels: str = None,
158
- per_page: int = 30,
159
- page: int = 1,
144
+ async def search_issues(
145
+ self, repo_full_name: str, state: str = "open", assignee: str = None, labels: str = None, per_page: int = 30, page: int = 1
160
146
  ) -> list[dict[str, Any]]:
161
147
  """
162
148
  Fetches issues from a GitHub repository using specified filters (state, assignee, labels) and pagination. It returns the raw API response as a list of dictionaries, providing detailed issue data for programmatic processing, distinct from other methods that return formatted strings.
@@ -186,11 +172,11 @@ class GithubApp(APIApplication):
186
172
  params["assignee"] = assignee
187
173
  if labels:
188
174
  params["labels"] = labels
189
- response = self._get(url, params=params)
175
+ response = await self._aget(url, params=params)
190
176
  response.raise_for_status()
191
177
  return response.json()
192
178
 
193
- def get_pull_request(self, repo_full_name: str, pull_number: int) -> str:
179
+ async def get_pull_request(self, repo_full_name: str, pull_number: int) -> str:
194
180
  """
195
181
  Fetches a specific pull request from a repository using its unique number. It returns a human-readable string summarizing the PR's title, creator, status, and description, unlike `list_pull_requests` which retrieves a list of multiple PRs.
196
182
 
@@ -210,7 +196,7 @@ class GithubApp(APIApplication):
210
196
  """
211
197
  repo_full_name = repo_full_name.strip()
212
198
  url = f"{self.base_api_url}/{repo_full_name}/pulls/{pull_number}"
213
- response = self._get(url)
199
+ response = await self._aget(url)
214
200
  response.raise_for_status()
215
201
  pr = response.json()
216
202
  pr_title = pr.get("title", "No Title")
@@ -218,15 +204,10 @@ class GithubApp(APIApplication):
218
204
  pr_state = pr.get("state", "Unknown")
219
205
  pr_user = pr.get("user", {}).get("login", "Unknown")
220
206
  pr_body = pr.get("body", "No description provided.")
221
- result = (
222
- f"Pull Request #{pr_number}: {pr_title}\n"
223
- f"Created by: {pr_user}\n"
224
- f"Status: {pr_state}\n"
225
- f"Description: {pr_body}\n"
226
- )
207
+ result = f"Pull Request #{pr_number}: {pr_title}\nCreated by: {pr_user}\nStatus: {pr_state}\nDescription: {pr_body}\n"
227
208
  return result
228
209
 
229
- def create_pull_request(
210
+ async def create_pull_request(
230
211
  self,
231
212
  repo_full_name: str,
232
213
  head: str,
@@ -262,12 +243,7 @@ class GithubApp(APIApplication):
262
243
  """
263
244
  repo_full_name = repo_full_name.strip()
264
245
  url = f"{self.base_api_url}/{repo_full_name}/pulls"
265
- pull_request_data = {
266
- "head": head,
267
- "base": base,
268
- "maintainer_can_modify": maintainer_can_modify,
269
- "draft": draft,
270
- }
246
+ pull_request_data = {"head": head, "base": base, "maintainer_can_modify": maintainer_can_modify, "draft": draft}
271
247
  if issue is not None:
272
248
  pull_request_data["issue"] = issue
273
249
  else:
@@ -276,13 +252,11 @@ class GithubApp(APIApplication):
276
252
  pull_request_data["title"] = title
277
253
  if body is not None:
278
254
  pull_request_data["body"] = body
279
- response = self._post(url, pull_request_data)
255
+ response = await self._apost(url, pull_request_data)
280
256
  response.raise_for_status()
281
257
  return response.json()
282
258
 
283
- def create_issue(
284
- self, repo_full_name: str, title: str, body: str = "", labels=None
285
- ) -> str:
259
+ async def create_issue(self, repo_full_name: str, title: str, body: str = "", labels=None) -> str:
286
260
  """
287
261
  Creates a new issue in a GitHub repository using a title, body, and optional labels. It returns a formatted confirmation string with the new issue's number and URL, differing from `update_issue` which modifies existing issues and `search_issues` which returns raw API data.
288
262
 
@@ -306,26 +280,18 @@ class GithubApp(APIApplication):
306
280
  issue_data = {"title": title, "body": body}
307
281
  if labels:
308
282
  if isinstance(labels, str):
309
- labels_list = [
310
- label.strip() for label in labels.split(",") if label.strip()
311
- ]
283
+ labels_list = [label.strip() for label in labels.split(",") if label.strip()]
312
284
  issue_data["labels"] = labels_list
313
285
  else:
314
286
  issue_data["labels"] = labels
315
- response = self._post(url, issue_data)
287
+ response = await self._apost(url, issue_data)
316
288
  response.raise_for_status()
317
289
  issue = response.json()
318
290
  issue_number = issue.get("number", "Unknown")
319
291
  issue_url = issue.get("html_url", "")
320
- return (
321
- f"Successfully created issue #{issue_number}:\n"
322
- f"Title: {title}\n"
323
- f"URL: {issue_url}"
324
- )
325
-
326
- def list_repo_activities(
327
- self, repo_full_name: str, direction: str = "desc", per_page: int = 30
328
- ) -> str:
292
+ return f"Successfully created issue #{issue_number}:\nTitle: {title}\nURL: {issue_url}"
293
+
294
+ async def list_repo_activities(self, repo_full_name: str, direction: str = "desc", per_page: int = 30) -> str:
329
295
  """
330
296
  Fetches recent events for a GitHub repository and formats them into a human-readable string. It summarizes activities with actors and timestamps, providing a general event feed, unlike other `list_*` functions which retrieve specific resources like commits or issues.
331
297
 
@@ -347,24 +313,21 @@ class GithubApp(APIApplication):
347
313
  repo_full_name = repo_full_name.strip()
348
314
  url = f"{self.base_api_url}/{repo_full_name}/activity"
349
315
  params = {"direction": direction, "per_page": per_page}
350
- response = self._get(url, params=params)
316
+ response = await self._aget(url, params=params)
351
317
  response.raise_for_status()
352
318
  activities = response.json()
353
319
  if not activities:
354
320
  return f"No activities found for repository {repo_full_name}"
355
321
  result = f"Repository activities for {repo_full_name}:\n\n"
356
322
  for activity in activities:
357
- # Extract common fields
358
323
  timestamp = activity.get("timestamp", "Unknown time")
359
324
  actor_name = "Unknown user"
360
325
  if "actor" in activity and activity["actor"]:
361
326
  actor_name = activity["actor"].get("login", "Unknown user")
362
-
363
- # Create a simple description of the activity
364
327
  result += f"- {actor_name} performed an activity at {timestamp}\n"
365
328
  return result
366
329
 
367
- def update_issue(
330
+ async def update_issue(
368
331
  self,
369
332
  repo_full_name: str,
370
333
  issue_number: int,