universal-mcp-applications 0.1.30__py3-none-any.whl → 0.1.36rc1__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.
- universal_mcp/applications/ahrefs/app.py +52 -198
- universal_mcp/applications/airtable/app.py +23 -122
- universal_mcp/applications/apollo/app.py +111 -464
- universal_mcp/applications/asana/app.py +417 -1567
- universal_mcp/applications/aws_s3/app.py +33 -100
- universal_mcp/applications/bill/app.py +546 -1957
- universal_mcp/applications/box/app.py +1068 -3981
- universal_mcp/applications/braze/app.py +364 -1430
- universal_mcp/applications/browser_use/app.py +2 -8
- universal_mcp/applications/cal_com_v2/app.py +207 -625
- universal_mcp/applications/calendly/app.py +61 -200
- universal_mcp/applications/canva/app.py +45 -110
- universal_mcp/applications/clickup/app.py +207 -674
- universal_mcp/applications/coda/app.py +146 -426
- universal_mcp/applications/confluence/app.py +310 -1098
- universal_mcp/applications/contentful/app.py +36 -151
- universal_mcp/applications/crustdata/app.py +28 -107
- universal_mcp/applications/dialpad/app.py +283 -756
- universal_mcp/applications/digitalocean/app.py +1766 -5777
- universal_mcp/applications/domain_checker/app.py +3 -54
- universal_mcp/applications/e2b/app.py +14 -64
- universal_mcp/applications/elevenlabs/app.py +9 -47
- universal_mcp/applications/exa/app.py +6 -17
- universal_mcp/applications/falai/app.py +23 -100
- universal_mcp/applications/figma/app.py +53 -137
- universal_mcp/applications/file_system/app.py +2 -13
- universal_mcp/applications/firecrawl/app.py +51 -152
- universal_mcp/applications/fireflies/app.py +59 -281
- universal_mcp/applications/fpl/app.py +91 -528
- universal_mcp/applications/fpl/utils/fixtures.py +15 -49
- universal_mcp/applications/fpl/utils/helper.py +25 -89
- universal_mcp/applications/fpl/utils/league_utils.py +20 -64
- universal_mcp/applications/ghost_content/app.py +52 -161
- universal_mcp/applications/github/app.py +19 -56
- universal_mcp/applications/gong/app.py +88 -248
- universal_mcp/applications/google_calendar/app.py +16 -68
- universal_mcp/applications/google_docs/app.py +88 -188
- universal_mcp/applications/google_drive/app.py +140 -462
- universal_mcp/applications/google_gemini/app.py +12 -64
- universal_mcp/applications/google_mail/app.py +28 -157
- universal_mcp/applications/google_searchconsole/app.py +15 -48
- universal_mcp/applications/google_sheet/app.py +101 -578
- universal_mcp/applications/google_sheet/helper.py +10 -37
- universal_mcp/applications/hashnode/app.py +57 -269
- universal_mcp/applications/heygen/app.py +44 -122
- universal_mcp/applications/http_tools/app.py +10 -32
- universal_mcp/applications/hubspot/api_segments/crm_api.py +460 -1573
- universal_mcp/applications/hubspot/api_segments/marketing_api.py +74 -262
- universal_mcp/applications/hubspot/app.py +23 -87
- universal_mcp/applications/jira/app.py +2071 -7986
- universal_mcp/applications/klaviyo/app.py +494 -1376
- universal_mcp/applications/linkedin/README.md +9 -2
- universal_mcp/applications/linkedin/app.py +392 -212
- universal_mcp/applications/mailchimp/app.py +450 -1605
- universal_mcp/applications/markitdown/app.py +8 -20
- universal_mcp/applications/miro/app.py +217 -699
- universal_mcp/applications/ms_teams/app.py +64 -186
- universal_mcp/applications/neon/app.py +86 -192
- universal_mcp/applications/notion/app.py +21 -36
- universal_mcp/applications/onedrive/app.py +14 -36
- universal_mcp/applications/openai/app.py +42 -165
- universal_mcp/applications/outlook/app.py +16 -76
- universal_mcp/applications/perplexity/app.py +4 -19
- universal_mcp/applications/pipedrive/app.py +832 -3142
- universal_mcp/applications/posthog/app.py +163 -432
- universal_mcp/applications/reddit/app.py +40 -139
- universal_mcp/applications/resend/app.py +41 -107
- universal_mcp/applications/retell/app.py +14 -41
- universal_mcp/applications/rocketlane/app.py +221 -934
- universal_mcp/applications/scraper/README.md +7 -4
- universal_mcp/applications/scraper/app.py +216 -102
- universal_mcp/applications/semanticscholar/app.py +22 -64
- universal_mcp/applications/semrush/app.py +43 -77
- universal_mcp/applications/sendgrid/app.py +512 -1262
- universal_mcp/applications/sentry/app.py +271 -906
- universal_mcp/applications/serpapi/app.py +40 -143
- universal_mcp/applications/sharepoint/app.py +15 -37
- universal_mcp/applications/shopify/app.py +1551 -4287
- universal_mcp/applications/shortcut/app.py +155 -417
- universal_mcp/applications/slack/app.py +50 -101
- universal_mcp/applications/spotify/app.py +126 -325
- universal_mcp/applications/supabase/app.py +104 -213
- universal_mcp/applications/tavily/app.py +1 -1
- universal_mcp/applications/trello/app.py +693 -2656
- universal_mcp/applications/twilio/app.py +14 -50
- universal_mcp/applications/twitter/api_segments/compliance_api.py +4 -14
- universal_mcp/applications/twitter/api_segments/dm_conversations_api.py +6 -18
- universal_mcp/applications/twitter/api_segments/likes_api.py +1 -3
- universal_mcp/applications/twitter/api_segments/lists_api.py +5 -15
- universal_mcp/applications/twitter/api_segments/trends_api.py +1 -3
- universal_mcp/applications/twitter/api_segments/tweets_api.py +9 -31
- universal_mcp/applications/twitter/api_segments/usage_api.py +1 -5
- universal_mcp/applications/twitter/api_segments/users_api.py +14 -42
- universal_mcp/applications/whatsapp/app.py +35 -186
- universal_mcp/applications/whatsapp/audio.py +2 -6
- universal_mcp/applications/whatsapp/whatsapp.py +17 -51
- universal_mcp/applications/whatsapp_business/app.py +70 -283
- universal_mcp/applications/wrike/app.py +45 -118
- universal_mcp/applications/yahoo_finance/app.py +19 -65
- universal_mcp/applications/youtube/app.py +75 -261
- universal_mcp/applications/zenquotes/app.py +2 -2
- {universal_mcp_applications-0.1.30.dist-info → universal_mcp_applications-0.1.36rc1.dist-info}/METADATA +2 -2
- {universal_mcp_applications-0.1.30.dist-info → universal_mcp_applications-0.1.36rc1.dist-info}/RECORD +105 -105
- {universal_mcp_applications-0.1.30.dist-info → universal_mcp_applications-0.1.36rc1.dist-info}/WHEEL +0 -0
- {universal_mcp_applications-0.1.30.dist-info → universal_mcp_applications-0.1.36rc1.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
from typing import Any
|
|
2
|
-
|
|
3
2
|
from universal_mcp.applications.application import APIApplication
|
|
4
3
|
from universal_mcp.exceptions import NotAuthorizedError, ToolError
|
|
5
4
|
from universal_mcp.integrations import Integration
|
|
6
|
-
|
|
7
5
|
import resend
|
|
8
6
|
|
|
9
7
|
|
|
@@ -21,24 +19,14 @@ class ResendApp(APIApplication):
|
|
|
21
19
|
if not self.integration:
|
|
22
20
|
raise NotAuthorizedError("Resend integration not configured.")
|
|
23
21
|
credentials = self.integration.get_credentials()
|
|
24
|
-
api_key = (
|
|
25
|
-
credentials.get("api_key")
|
|
26
|
-
or credentials.get("API_KEY")
|
|
27
|
-
or credentials.get("apiKey")
|
|
28
|
-
)
|
|
22
|
+
api_key = credentials.get("api_key") or credentials.get("API_KEY") or credentials.get("apiKey")
|
|
29
23
|
if not api_key:
|
|
30
24
|
raise NotAuthorizedError("Resend API key not found in credentials.")
|
|
31
25
|
self._api_key = api_key
|
|
32
26
|
resend.api_key = self._api_key
|
|
33
27
|
return self._api_key
|
|
34
28
|
|
|
35
|
-
def send_email(
|
|
36
|
-
self,
|
|
37
|
-
from_email: str,
|
|
38
|
-
to_emails: list[str],
|
|
39
|
-
subject: str,
|
|
40
|
-
text: str,
|
|
41
|
-
) -> dict[str, Any]:
|
|
29
|
+
async def send_email(self, from_email: str, to_emails: list[str], subject: str, text: str) -> dict[str, Any]:
|
|
42
30
|
"""
|
|
43
31
|
Sends a single email with a specified subject and text body to a list of recipients via the Resend API. Unlike `send_batch_emails`, which processes multiple distinct emails at once, this function is designed for dispatching one individual email composition per API call.
|
|
44
32
|
|
|
@@ -58,22 +46,14 @@ class ResendApp(APIApplication):
|
|
|
58
46
|
send, email, api, communication, important
|
|
59
47
|
"""
|
|
60
48
|
self.api_key
|
|
61
|
-
params: resend.Emails.SendParams = {
|
|
62
|
-
"from": from_email,
|
|
63
|
-
"to": to_emails,
|
|
64
|
-
"subject": subject,
|
|
65
|
-
"text": text,
|
|
66
|
-
}
|
|
49
|
+
params: resend.Emails.SendParams = {"from": from_email, "to": to_emails, "subject": subject, "text": text}
|
|
67
50
|
try:
|
|
68
51
|
email = resend.Emails.send(params)
|
|
69
52
|
return email
|
|
70
53
|
except Exception as e:
|
|
71
54
|
raise ToolError(f"Failed to send email: {e}")
|
|
72
55
|
|
|
73
|
-
def send_batch_emails(
|
|
74
|
-
self,
|
|
75
|
-
emails: list[dict[str, Any]],
|
|
76
|
-
) -> dict[str, Any]:
|
|
56
|
+
async def send_batch_emails(self, emails: list[dict[str, Any]]) -> dict[str, Any]:
|
|
77
57
|
"""
|
|
78
58
|
Sends multiple emails (1-100) in a single API request. Unlike the `send_email` function which handles a single message, this accepts a list of email objects for efficient, high-volume delivery. It validates that the batch size is within the allowed limits before making the API call.
|
|
79
59
|
|
|
@@ -91,9 +71,7 @@ class ResendApp(APIApplication):
|
|
|
91
71
|
"""
|
|
92
72
|
self.api_key
|
|
93
73
|
if not 1 <= len(emails) <= 100:
|
|
94
|
-
raise ToolError(
|
|
95
|
-
"The number of emails in a batch must be between 1 and 100."
|
|
96
|
-
)
|
|
74
|
+
raise ToolError("The number of emails in a batch must be between 1 and 100.")
|
|
97
75
|
params: list[resend.Emails.SendParams] = emails
|
|
98
76
|
try:
|
|
99
77
|
sent_emails_response = resend.Batch.send(params)
|
|
@@ -101,7 +79,7 @@ class ResendApp(APIApplication):
|
|
|
101
79
|
except Exception as e:
|
|
102
80
|
raise ToolError(f"Failed to send batch emails: {e}")
|
|
103
81
|
|
|
104
|
-
def retrieve_email_by_id(self, email_id: str) -> dict[str, Any]:
|
|
82
|
+
async def retrieve_email_by_id(self, email_id: str) -> dict[str, Any]:
|
|
105
83
|
"""
|
|
106
84
|
Retrieves the details and status of a single email from the Resend API using its unique identifier. This function allows for looking up a specific email that has already been sent or scheduled, distinct from functions that initiate sending.
|
|
107
85
|
|
|
@@ -124,7 +102,7 @@ class ResendApp(APIApplication):
|
|
|
124
102
|
except Exception as e:
|
|
125
103
|
raise ToolError(f"Failed to retrieve email: {e}")
|
|
126
104
|
|
|
127
|
-
def reschedule_email(self, email_id: str, scheduled_at: str) -> dict[str, Any]:
|
|
105
|
+
async def reschedule_email(self, email_id: str, scheduled_at: str) -> dict[str, Any]:
|
|
128
106
|
"""
|
|
129
107
|
Modifies the delivery time for a specific, previously scheduled email using its ID. It updates the `scheduled_at` attribute to a new ISO 8601 formatted time, effectively rescheduling its dispatch. This differs from `cancel_scheduled_email`, which permanently stops the send.
|
|
130
108
|
|
|
@@ -142,17 +120,14 @@ class ResendApp(APIApplication):
|
|
|
142
120
|
update, email, async_job, management
|
|
143
121
|
"""
|
|
144
122
|
self.api_key
|
|
145
|
-
params: resend.Emails.UpdateParams = {
|
|
146
|
-
"id": email_id,
|
|
147
|
-
"scheduled_at": scheduled_at,
|
|
148
|
-
}
|
|
123
|
+
params: resend.Emails.UpdateParams = {"id": email_id, "scheduled_at": scheduled_at}
|
|
149
124
|
try:
|
|
150
125
|
response = resend.Emails.update(params=params)
|
|
151
126
|
return response
|
|
152
127
|
except Exception as e:
|
|
153
128
|
raise ToolError(f"Failed to update scheduled email: {e}")
|
|
154
129
|
|
|
155
|
-
def cancel_scheduled_email(self, email_id: str) -> dict[str, Any]:
|
|
130
|
+
async def cancel_scheduled_email(self, email_id: str) -> dict[str, Any]:
|
|
156
131
|
"""
|
|
157
132
|
Cancels a previously scheduled email using its unique ID, preventing it from being sent. This function calls the Resend API's cancellation endpoint, returning a confirmation response. It is distinct from `update_scheduled_email`, which reschedules the email instead of stopping its transmission.
|
|
158
133
|
|
|
@@ -175,7 +150,7 @@ class ResendApp(APIApplication):
|
|
|
175
150
|
except Exception as e:
|
|
176
151
|
raise ToolError(f"Failed to cancel scheduled email: {e}")
|
|
177
152
|
|
|
178
|
-
def create_domain(self, name: str) -> dict[str, Any]:
|
|
153
|
+
async def create_domain(self, name: str) -> dict[str, Any]:
|
|
179
154
|
"""
|
|
180
155
|
Registers a new sending domain with the Resend service using the provided name. This is a prerequisite for sending emails from your own domain and returns a dictionary containing details of the new domain object, which can then be verified and managed with other domain-related functions.
|
|
181
156
|
|
|
@@ -199,7 +174,7 @@ class ResendApp(APIApplication):
|
|
|
199
174
|
except Exception as e:
|
|
200
175
|
raise ToolError(f"Failed to create domain: {e}")
|
|
201
176
|
|
|
202
|
-
def get_domain(self, domain_id: str) -> dict[str, Any]:
|
|
177
|
+
async def get_domain(self, domain_id: str) -> dict[str, Any]:
|
|
203
178
|
"""
|
|
204
179
|
Retrieves the details of a specific domain from the Resend API using its unique ID. Unlike `list_domains`, which fetches all domains, this function targets a single record and returns a dictionary containing the domain's properties, like its verification status and tracking settings.
|
|
205
180
|
|
|
@@ -222,7 +197,7 @@ class ResendApp(APIApplication):
|
|
|
222
197
|
except Exception as e:
|
|
223
198
|
raise ToolError(f"Failed to retrieve domain: {e}")
|
|
224
199
|
|
|
225
|
-
def verify_domain(self, domain_id: str) -> dict[str, Any]:
|
|
200
|
+
async def verify_domain(self, domain_id: str) -> dict[str, Any]:
|
|
226
201
|
"""
|
|
227
202
|
Triggers the verification process for a registered domain using its unique ID. This action is crucial for authorizing the domain to send emails via Resend and returns an API response containing the verification status and necessary DNS records to complete the process.
|
|
228
203
|
|
|
@@ -245,12 +220,8 @@ class ResendApp(APIApplication):
|
|
|
245
220
|
except Exception as e:
|
|
246
221
|
raise ToolError(f"Failed to verify domain: {e}")
|
|
247
222
|
|
|
248
|
-
def update_domain_settings(
|
|
249
|
-
self,
|
|
250
|
-
domain_id: str,
|
|
251
|
-
open_tracking: bool | None = None,
|
|
252
|
-
click_tracking: bool | None = None,
|
|
253
|
-
tls: str | None = None,
|
|
223
|
+
async def update_domain_settings(
|
|
224
|
+
self, domain_id: str, open_tracking: bool | None = None, click_tracking: bool | None = None, tls: str | None = None
|
|
254
225
|
) -> dict[str, Any]:
|
|
255
226
|
"""
|
|
256
227
|
Updates settings for a specific domain identified by its ID. This function can modify configurations like open and click tracking, and TLS enforcement. It returns the updated domain object from the API, raising a ToolError if the update fails. Only the provided settings are modified.
|
|
@@ -284,7 +255,7 @@ class ResendApp(APIApplication):
|
|
|
284
255
|
except Exception as e:
|
|
285
256
|
raise ToolError(f"Failed to update domain: {e}")
|
|
286
257
|
|
|
287
|
-
def list_domains(self) -> list[dict[str, Any]]:
|
|
258
|
+
async def list_domains(self) -> list[dict[str, Any]]:
|
|
288
259
|
"""
|
|
289
260
|
Fetches a complete list of all domains registered with the Resend account. Unlike `get_domain`, which retrieves a single domain by ID, this provides a comprehensive overview of all configured domains for management and verification tasks.
|
|
290
261
|
|
|
@@ -304,7 +275,7 @@ class ResendApp(APIApplication):
|
|
|
304
275
|
except Exception as e:
|
|
305
276
|
raise ToolError(f"Failed to list domains: {e}")
|
|
306
277
|
|
|
307
|
-
def remove_domain(self, domain_id: str) -> dict[str, Any]:
|
|
278
|
+
async def remove_domain(self, domain_id: str) -> dict[str, Any]:
|
|
308
279
|
"""
|
|
309
280
|
Permanently removes a specific domain from the Resend account using its unique ID. This function makes an authenticated API call to delete the domain, distinguishing it from retrieval (`get_domain`) or modification (`update_domain`) operations, and raises an error if the process fails.
|
|
310
281
|
|
|
@@ -327,7 +298,7 @@ class ResendApp(APIApplication):
|
|
|
327
298
|
except Exception as e:
|
|
328
299
|
raise ToolError(f"Failed to remove domain: {e}")
|
|
329
300
|
|
|
330
|
-
def create_api_key(self, name: str) -> dict[str, Any]:
|
|
301
|
+
async def create_api_key(self, name: str) -> dict[str, Any]:
|
|
331
302
|
"""
|
|
332
303
|
Creates a new API key for authenticating with the Resend service, identified by a specified name. It returns a dictionary containing the new key object, including the generated token required for subsequent API requests.
|
|
333
304
|
|
|
@@ -351,7 +322,7 @@ class ResendApp(APIApplication):
|
|
|
351
322
|
except Exception as e:
|
|
352
323
|
raise ToolError(f"Failed to create API key: {e}")
|
|
353
324
|
|
|
354
|
-
def list_api_keys(self) -> list[dict[str, Any]]:
|
|
325
|
+
async def list_api_keys(self) -> list[dict[str, Any]]:
|
|
355
326
|
"""
|
|
356
327
|
Retrieves a list of all API keys for the authenticated Resend account. This read-only operation allows for auditing and viewing existing credentials, contrasting with `create_api_key` and `remove_api_key` which are used to add or delete keys.
|
|
357
328
|
|
|
@@ -374,7 +345,7 @@ class ResendApp(APIApplication):
|
|
|
374
345
|
except Exception as e:
|
|
375
346
|
raise ToolError(f"Failed to list API keys: {e}")
|
|
376
347
|
|
|
377
|
-
def remove_api_key(self, api_key_id: str) -> dict[str, Any]:
|
|
348
|
+
async def remove_api_key(self, api_key_id: str) -> dict[str, Any]:
|
|
378
349
|
"""
|
|
379
350
|
Deletes a specific Resend API key identified by its unique ID. This function, part of the key management suite alongside `create_api_key` and `list_api_keys`, returns an API confirmation response or raises a `ToolError` if the operation fails.
|
|
380
351
|
|
|
@@ -397,13 +368,7 @@ class ResendApp(APIApplication):
|
|
|
397
368
|
except Exception as e:
|
|
398
369
|
raise ToolError(f"Failed to remove API key: {e}")
|
|
399
370
|
|
|
400
|
-
def register_broadcast(
|
|
401
|
-
self,
|
|
402
|
-
audience_id: str,
|
|
403
|
-
from_email: str,
|
|
404
|
-
subject: str,
|
|
405
|
-
html: str,
|
|
406
|
-
) -> dict[str, Any]:
|
|
371
|
+
async def register_broadcast(self, audience_id: str, from_email: str, subject: str, html: str) -> dict[str, Any]:
|
|
407
372
|
"""
|
|
408
373
|
Registers a new email broadcast campaign for a specific audience using the Resend API. This function creates the broadcast object but does not send it; use the `send_broadcast` function to dispatch the created campaign to the audience.
|
|
409
374
|
|
|
@@ -423,19 +388,14 @@ class ResendApp(APIApplication):
|
|
|
423
388
|
broadcast, email, important
|
|
424
389
|
"""
|
|
425
390
|
self.api_key
|
|
426
|
-
params: resend.Broadcasts.CreateParams = {
|
|
427
|
-
"audience_id": audience_id,
|
|
428
|
-
"from": from_email,
|
|
429
|
-
"subject": subject,
|
|
430
|
-
"html": html,
|
|
431
|
-
}
|
|
391
|
+
params: resend.Broadcasts.CreateParams = {"audience_id": audience_id, "from": from_email, "subject": subject, "html": html}
|
|
432
392
|
try:
|
|
433
393
|
broadcast = resend.Broadcasts.create(params)
|
|
434
394
|
return broadcast
|
|
435
395
|
except Exception as e:
|
|
436
396
|
raise ToolError(f"Failed to create broadcast: {e}")
|
|
437
397
|
|
|
438
|
-
def get_broadcast(self, broadcast_id: str) -> dict[str, Any]:
|
|
398
|
+
async def get_broadcast(self, broadcast_id: str) -> dict[str, Any]:
|
|
439
399
|
"""
|
|
440
400
|
Retrieves a specific broadcast's complete details, including its status and content, by its unique ID. Unlike `list_broadcasts` which retrieves all broadcasts, this function targets a single entry for inspection.
|
|
441
401
|
|
|
@@ -458,12 +418,7 @@ class ResendApp(APIApplication):
|
|
|
458
418
|
except Exception as e:
|
|
459
419
|
raise ToolError(f"Failed to retrieve broadcast: {e}")
|
|
460
420
|
|
|
461
|
-
def update_broadcast(
|
|
462
|
-
self,
|
|
463
|
-
broadcast_id: str,
|
|
464
|
-
html: str | None = None,
|
|
465
|
-
subject: str | None = None,
|
|
466
|
-
) -> dict[str, Any]:
|
|
421
|
+
async def update_broadcast(self, broadcast_id: str, html: str | None = None, subject: str | None = None) -> dict[str, Any]:
|
|
467
422
|
"""
|
|
468
423
|
Updates the HTML content and/or subject of an existing broadcast, identified by its ID. Requires that at least one modifiable field (html or subject) is provided. This function alters a broadcast's content, differing from `send_broadcast` which triggers its delivery.
|
|
469
424
|
|
|
@@ -488,18 +443,14 @@ class ResendApp(APIApplication):
|
|
|
488
443
|
if subject is not None:
|
|
489
444
|
params["subject"] = subject
|
|
490
445
|
if len(params) == 1:
|
|
491
|
-
raise ToolError(
|
|
492
|
-
"At least one field (e.g., html, subject) must be provided for the update."
|
|
493
|
-
)
|
|
446
|
+
raise ToolError("At least one field (e.g., html, subject) must be provided for the update.")
|
|
494
447
|
try:
|
|
495
448
|
updated_broadcast = resend.Broadcasts.update(params)
|
|
496
449
|
return updated_broadcast
|
|
497
450
|
except Exception as e:
|
|
498
451
|
raise ToolError(f"Failed to update broadcast: {e}")
|
|
499
452
|
|
|
500
|
-
def send_or_schedule_broadcast(
|
|
501
|
-
self, broadcast_id: str, scheduled_at: str | None = None
|
|
502
|
-
) -> dict[str, Any]:
|
|
453
|
+
async def send_or_schedule_broadcast(self, broadcast_id: str, scheduled_at: str | None = None) -> dict[str, Any]:
|
|
503
454
|
"""
|
|
504
455
|
Initiates the delivery of a pre-existing broadcast, identified by its ID, to its target audience. The broadcast can be sent immediately or scheduled for a future time via the optional `scheduled_at` parameter. It returns the API response upon execution.
|
|
505
456
|
|
|
@@ -526,7 +477,7 @@ class ResendApp(APIApplication):
|
|
|
526
477
|
except Exception as e:
|
|
527
478
|
raise ToolError(f"Failed to send broadcast: {e}")
|
|
528
479
|
|
|
529
|
-
def remove_draft_broadcast(self, broadcast_id: str) -> dict[str, Any]:
|
|
480
|
+
async def remove_draft_broadcast(self, broadcast_id: str) -> dict[str, Any]:
|
|
530
481
|
"""
|
|
531
482
|
Deletes a broadcast from the Resend service using its unique ID. This action is restricted to broadcasts that have a 'draft' status and have not been sent, returning the API's response upon successful removal or raising an error if the operation fails.
|
|
532
483
|
|
|
@@ -549,7 +500,7 @@ class ResendApp(APIApplication):
|
|
|
549
500
|
except Exception as e:
|
|
550
501
|
raise ToolError(f"Failed to remove broadcast: {e}")
|
|
551
502
|
|
|
552
|
-
def list_broadcasts(self) -> list[dict[str, Any]]:
|
|
503
|
+
async def list_broadcasts(self) -> list[dict[str, Any]]:
|
|
553
504
|
"""
|
|
554
505
|
Retrieves a list of all broadcasts associated with the authenticated account. Unlike `get_broadcast` which fetches a single item by ID, this function returns a list of dictionaries, each containing the attributes of a specific broadcast. Raises a `ToolError` on API failure.
|
|
555
506
|
|
|
@@ -569,7 +520,7 @@ class ResendApp(APIApplication):
|
|
|
569
520
|
except Exception as e:
|
|
570
521
|
raise ToolError(f"Failed to list broadcasts: {e}")
|
|
571
522
|
|
|
572
|
-
def create_audience(self, name: str) -> dict[str, Any]:
|
|
523
|
+
async def create_audience(self, name: str) -> dict[str, Any]:
|
|
573
524
|
"""
|
|
574
525
|
Creates a new audience, a named list for contacts, within the Resend service. This function requires a name for the audience and returns a dictionary representing the newly created object, enabling subsequent management of contacts within that specific list.
|
|
575
526
|
|
|
@@ -593,7 +544,7 @@ class ResendApp(APIApplication):
|
|
|
593
544
|
except Exception as e:
|
|
594
545
|
raise ToolError(f"Failed to create audience: {e}")
|
|
595
546
|
|
|
596
|
-
def get_audience(self, audience_id: str) -> dict[str, Any]:
|
|
547
|
+
async def get_audience(self, audience_id: str) -> dict[str, Any]:
|
|
597
548
|
"""
|
|
598
549
|
Retrieves the details of a single audience using its unique ID. This provides a targeted lookup for one audience, distinct from `list_audiences` which fetches all available audiences in the account.
|
|
599
550
|
|
|
@@ -616,7 +567,7 @@ class ResendApp(APIApplication):
|
|
|
616
567
|
except Exception as e:
|
|
617
568
|
raise ToolError(f"Failed to retrieve audience: {e}")
|
|
618
569
|
|
|
619
|
-
def remove_audience(self, audience_id: str) -> dict[str, Any]:
|
|
570
|
+
async def remove_audience(self, audience_id: str) -> dict[str, Any]:
|
|
620
571
|
"""
|
|
621
572
|
Deletes a specific audience from the Resend service using its unique identifier. This function wraps the Resend API's remove operation, returning the API's response. Unlike `remove_contact`, which targets individuals, this function removes the entire contact list defined by the audience ID.
|
|
622
573
|
|
|
@@ -639,7 +590,7 @@ class ResendApp(APIApplication):
|
|
|
639
590
|
except Exception as e:
|
|
640
591
|
raise ToolError(f"Failed to remove audience: {e}")
|
|
641
592
|
|
|
642
|
-
def list_audiences(self) -> list[dict[str, Any]]:
|
|
593
|
+
async def list_audiences(self) -> list[dict[str, Any]]:
|
|
643
594
|
"""
|
|
644
595
|
Retrieves a complete list of all audiences from the Resend account. It returns a list of dictionaries, with each containing the details of a specific audience. This function is distinct from `get_audience`, which fetches a single audience by its ID.
|
|
645
596
|
|
|
@@ -659,13 +610,8 @@ class ResendApp(APIApplication):
|
|
|
659
610
|
except Exception as e:
|
|
660
611
|
raise ToolError(f"Failed to list audiences: {e}")
|
|
661
612
|
|
|
662
|
-
def create_contact(
|
|
663
|
-
self,
|
|
664
|
-
audience_id: str,
|
|
665
|
-
email: str,
|
|
666
|
-
first_name: str | None = None,
|
|
667
|
-
last_name: str | None = None,
|
|
668
|
-
unsubscribed: bool = False,
|
|
613
|
+
async def create_contact(
|
|
614
|
+
self, audience_id: str, email: str, first_name: str | None = None, last_name: str | None = None, unsubscribed: bool = False
|
|
669
615
|
) -> dict[str, Any]:
|
|
670
616
|
"""
|
|
671
617
|
Creates a new contact with a given email, optional name, and subscription status, adding it to a specific audience. This function populates audience lists, differing from `update_contact` which modifies existing entries, and requires a valid `audience_id` to function.
|
|
@@ -687,11 +633,7 @@ class ResendApp(APIApplication):
|
|
|
687
633
|
create, contact, management, important
|
|
688
634
|
"""
|
|
689
635
|
self.api_key
|
|
690
|
-
params: resend.Contacts.CreateParams = {
|
|
691
|
-
"audience_id": audience_id,
|
|
692
|
-
"email": email,
|
|
693
|
-
"unsubscribed": unsubscribed,
|
|
694
|
-
}
|
|
636
|
+
params: resend.Contacts.CreateParams = {"audience_id": audience_id, "email": email, "unsubscribed": unsubscribed}
|
|
695
637
|
if first_name:
|
|
696
638
|
params["first_name"] = first_name
|
|
697
639
|
if last_name:
|
|
@@ -702,9 +644,7 @@ class ResendApp(APIApplication):
|
|
|
702
644
|
except Exception as e:
|
|
703
645
|
raise ToolError(f"Failed to create contact: {e}")
|
|
704
646
|
|
|
705
|
-
def get_contact(
|
|
706
|
-
self, audience_id: str, contact_id: str | None = None, email: str | None = None
|
|
707
|
-
) -> dict[str, Any]:
|
|
647
|
+
async def get_contact(self, audience_id: str, contact_id: str | None = None, email: str | None = None) -> dict[str, Any]:
|
|
708
648
|
"""
|
|
709
649
|
Fetches a single contact's details from a specified audience by its unique ID or email address. The function requires exactly one identifier for the lookup, raising an error if the identifier is missing, ambiguous, or if the API call fails.
|
|
710
650
|
|
|
@@ -736,7 +676,7 @@ class ResendApp(APIApplication):
|
|
|
736
676
|
except Exception as e:
|
|
737
677
|
raise ToolError(f"Failed to retrieve contact: {e}")
|
|
738
678
|
|
|
739
|
-
def update_contact(
|
|
679
|
+
async def update_contact(
|
|
740
680
|
self,
|
|
741
681
|
audience_id: str,
|
|
742
682
|
contact_id: str | None = None,
|
|
@@ -767,9 +707,7 @@ class ResendApp(APIApplication):
|
|
|
767
707
|
"""
|
|
768
708
|
self.api_key
|
|
769
709
|
if not (contact_id or email) or (contact_id and email):
|
|
770
|
-
raise ToolError(
|
|
771
|
-
"You must provide exactly one of 'contact_id' or 'email' to identify the contact."
|
|
772
|
-
)
|
|
710
|
+
raise ToolError("You must provide exactly one of 'contact_id' or 'email' to identify the contact.")
|
|
773
711
|
params: resend.Contacts.UpdateParams = {"audience_id": audience_id}
|
|
774
712
|
if contact_id:
|
|
775
713
|
params["id"] = contact_id
|
|
@@ -781,19 +719,15 @@ class ResendApp(APIApplication):
|
|
|
781
719
|
params["last_name"] = last_name
|
|
782
720
|
if unsubscribed is not None:
|
|
783
721
|
params["unsubscribed"] = unsubscribed
|
|
784
|
-
if len(params) <= 2:
|
|
785
|
-
raise ToolError(
|
|
786
|
-
"At least one field to update (e.g., first_name, unsubscribed) must be provided."
|
|
787
|
-
)
|
|
722
|
+
if len(params) <= 2:
|
|
723
|
+
raise ToolError("At least one field to update (e.g., first_name, unsubscribed) must be provided.")
|
|
788
724
|
try:
|
|
789
725
|
response = resend.Contacts.update(params)
|
|
790
726
|
return response
|
|
791
727
|
except Exception as e:
|
|
792
728
|
raise ToolError(f"Failed to update contact: {e}")
|
|
793
729
|
|
|
794
|
-
def remove_contact(
|
|
795
|
-
self, audience_id: str, contact_id: str | None = None, email: str | None = None
|
|
796
|
-
) -> dict[str, Any]:
|
|
730
|
+
async def remove_contact(self, audience_id: str, contact_id: str | None = None, email: str | None = None) -> dict[str, Any]:
|
|
797
731
|
"""
|
|
798
732
|
Removes a contact from a specified audience. The contact must be identified by either its unique ID or email address, but not both. Raises an error if the identifier is missing, ambiguous, or if the API call to the Resend service fails.
|
|
799
733
|
|
|
@@ -825,7 +759,7 @@ class ResendApp(APIApplication):
|
|
|
825
759
|
except Exception as e:
|
|
826
760
|
raise ToolError(f"Failed to remove contact: {e}")
|
|
827
761
|
|
|
828
|
-
def list_contacts(self, audience_id: str) -> list[dict[str, Any]]:
|
|
762
|
+
async def list_contacts(self, audience_id: str) -> list[dict[str, Any]]:
|
|
829
763
|
"""
|
|
830
764
|
Retrieves a complete list of contacts belonging to a specific audience, identified by its unique ID. This function returns all contacts within the audience, unlike `get_contact` which retrieves only a single contact by its ID or email.
|
|
831
765
|
|
|
@@ -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 RetellApp(APIApplication):
|
|
|
9
8
|
super().__init__(name="retell", integration=integration, **kwargs)
|
|
10
9
|
self.base_url = "https://api.retellai.com"
|
|
11
10
|
|
|
12
|
-
def get_v2_get_call_by_call_id(self, call_id) -> dict[str, Any]:
|
|
11
|
+
async def get_v2_get_call_by_call_id(self, call_id) -> dict[str, Any]:
|
|
13
12
|
"""
|
|
14
13
|
Retrieve detailed information about a specific call using its call ID.
|
|
15
14
|
|
|
@@ -34,13 +33,8 @@ class RetellApp(APIApplication):
|
|
|
34
33
|
response.raise_for_status()
|
|
35
34
|
return response.json()
|
|
36
35
|
|
|
37
|
-
def post_v2_create_phone_call(
|
|
38
|
-
self,
|
|
39
|
-
from_number,
|
|
40
|
-
to_number,
|
|
41
|
-
override_agent_id=None,
|
|
42
|
-
metadata=None,
|
|
43
|
-
retell_llm_dynamic_variables=None,
|
|
36
|
+
async def post_v2_create_phone_call(
|
|
37
|
+
self, from_number, to_number, override_agent_id=None, metadata=None, retell_llm_dynamic_variables=None
|
|
44
38
|
) -> dict[str, Any]:
|
|
45
39
|
"""
|
|
46
40
|
Initiates a phone call using a JSON payload with specified parameters.
|
|
@@ -79,9 +73,7 @@ class RetellApp(APIApplication):
|
|
|
79
73
|
response.raise_for_status()
|
|
80
74
|
return response.json()
|
|
81
75
|
|
|
82
|
-
def post_v2_create_web_call(
|
|
83
|
-
self, agent_id, metadata=None, retell_llm_dynamic_variables=None
|
|
84
|
-
) -> dict[str, Any]:
|
|
76
|
+
async def post_v2_create_web_call(self, agent_id, metadata=None, retell_llm_dynamic_variables=None) -> dict[str, Any]:
|
|
85
77
|
"""
|
|
86
78
|
Creates a web call via a POST request to the v2 endpoint with specified agent ID and optional metadata or dynamic variables.
|
|
87
79
|
|
|
@@ -101,11 +93,7 @@ class RetellApp(APIApplication):
|
|
|
101
93
|
"""
|
|
102
94
|
if agent_id is None:
|
|
103
95
|
raise ValueError("Missing required parameter 'agent_id'")
|
|
104
|
-
request_body = {
|
|
105
|
-
"agent_id": agent_id,
|
|
106
|
-
"metadata": metadata,
|
|
107
|
-
"retell_llm_dynamic_variables": retell_llm_dynamic_variables,
|
|
108
|
-
}
|
|
96
|
+
request_body = {"agent_id": agent_id, "metadata": metadata, "retell_llm_dynamic_variables": retell_llm_dynamic_variables}
|
|
109
97
|
request_body = {k: v for k, v in request_body.items() if v is not None}
|
|
110
98
|
url = f"{self.base_url}/v2/create-web-call"
|
|
111
99
|
query_params = {}
|
|
@@ -113,7 +101,7 @@ class RetellApp(APIApplication):
|
|
|
113
101
|
response.raise_for_status()
|
|
114
102
|
return response.json()
|
|
115
103
|
|
|
116
|
-
def get_get_voice_by_voice_id(self, voice_id) -> dict[str, Any]:
|
|
104
|
+
async def get_get_voice_by_voice_id(self, voice_id) -> dict[str, Any]:
|
|
117
105
|
"""
|
|
118
106
|
Fetches voice details based on the provided voice ID.
|
|
119
107
|
|
|
@@ -137,9 +125,7 @@ class RetellApp(APIApplication):
|
|
|
137
125
|
response.raise_for_status()
|
|
138
126
|
return response.json()
|
|
139
127
|
|
|
140
|
-
def post_v2_list_calls(
|
|
141
|
-
self, filter_criteria=None, sort_order=None, limit=None, pagination_key=None
|
|
142
|
-
) -> list[Any]:
|
|
128
|
+
async def post_v2_list_calls(self, filter_criteria=None, sort_order=None, limit=None, pagination_key=None) -> list[Any]:
|
|
143
129
|
"""
|
|
144
130
|
Sends a POST request to list call records with optional filtering, sorting, pagination, and limits.
|
|
145
131
|
|
|
@@ -158,12 +144,7 @@ class RetellApp(APIApplication):
|
|
|
158
144
|
Tags:
|
|
159
145
|
list, calls, api, batch, management, important
|
|
160
146
|
"""
|
|
161
|
-
request_body = {
|
|
162
|
-
"filter_criteria": filter_criteria,
|
|
163
|
-
"sort_order": sort_order,
|
|
164
|
-
"limit": limit,
|
|
165
|
-
"pagination_key": pagination_key,
|
|
166
|
-
}
|
|
147
|
+
request_body = {"filter_criteria": filter_criteria, "sort_order": sort_order, "limit": limit, "pagination_key": pagination_key}
|
|
167
148
|
request_body = {k: v for k, v in request_body.items() if v is not None}
|
|
168
149
|
url = f"{self.base_url}/v2/list-calls"
|
|
169
150
|
query_params = {}
|
|
@@ -171,9 +152,7 @@ class RetellApp(APIApplication):
|
|
|
171
152
|
response.raise_for_status()
|
|
172
153
|
return response.json()
|
|
173
154
|
|
|
174
|
-
def post_create_phone_number(
|
|
175
|
-
self, area_code, inbound_agent_id=None, outbound_agent_id=None, nickname=None
|
|
176
|
-
) -> dict[str, Any]:
|
|
155
|
+
async def post_create_phone_number(self, area_code, inbound_agent_id=None, outbound_agent_id=None, nickname=None) -> dict[str, Any]:
|
|
177
156
|
"""
|
|
178
157
|
Creates a phone number with the specified area code and optional parameters.
|
|
179
158
|
|
|
@@ -208,7 +187,7 @@ class RetellApp(APIApplication):
|
|
|
208
187
|
response.raise_for_status()
|
|
209
188
|
return response.json()
|
|
210
189
|
|
|
211
|
-
def get_get_phone_number_by_phone_number(self, phone_number) -> dict[str, Any]:
|
|
190
|
+
async def get_get_phone_number_by_phone_number(self, phone_number) -> dict[str, Any]:
|
|
212
191
|
"""
|
|
213
192
|
Retrieves phone number details by making a GET request to the API endpoint using the provided phone number.
|
|
214
193
|
|
|
@@ -233,9 +212,7 @@ class RetellApp(APIApplication):
|
|
|
233
212
|
response.raise_for_status()
|
|
234
213
|
return response.json()
|
|
235
214
|
|
|
236
|
-
def get_list_phone_numbers(
|
|
237
|
-
self,
|
|
238
|
-
) -> list[Any]:
|
|
215
|
+
async def get_list_phone_numbers(self) -> list[Any]:
|
|
239
216
|
"""
|
|
240
217
|
Retrieves a list of phone numbers from the remote API.
|
|
241
218
|
|
|
@@ -257,7 +234,7 @@ class RetellApp(APIApplication):
|
|
|
257
234
|
response.raise_for_status()
|
|
258
235
|
return response.json()
|
|
259
236
|
|
|
260
|
-
def patch_update_phone_number_by_phone_number(
|
|
237
|
+
async def patch_update_phone_number_by_phone_number(
|
|
261
238
|
self, phone_number, inbound_agent_id=None, outbound_agent_id=None, nickname=None
|
|
262
239
|
) -> dict[str, Any]:
|
|
263
240
|
"""
|
|
@@ -281,11 +258,7 @@ class RetellApp(APIApplication):
|
|
|
281
258
|
"""
|
|
282
259
|
if phone_number is None:
|
|
283
260
|
raise ValueError("Missing required parameter 'phone_number'")
|
|
284
|
-
request_body = {
|
|
285
|
-
"inbound_agent_id": inbound_agent_id,
|
|
286
|
-
"outbound_agent_id": outbound_agent_id,
|
|
287
|
-
"nickname": nickname,
|
|
288
|
-
}
|
|
261
|
+
request_body = {"inbound_agent_id": inbound_agent_id, "outbound_agent_id": outbound_agent_id, "nickname": nickname}
|
|
289
262
|
request_body = {k: v for k, v in request_body.items() if v is not None}
|
|
290
263
|
url = f"{self.base_url}/update-phone-number/{phone_number}"
|
|
291
264
|
query_params = {}
|
|
@@ -293,7 +266,7 @@ class RetellApp(APIApplication):
|
|
|
293
266
|
response.raise_for_status()
|
|
294
267
|
return response.json()
|
|
295
268
|
|
|
296
|
-
def delete_delete_phone_number_by_phone_number(self, phone_number) -> Any:
|
|
269
|
+
async def delete_delete_phone_number_by_phone_number(self, phone_number) -> Any:
|
|
297
270
|
"""
|
|
298
271
|
Deletes a phone number resource by its phone number identifier via an HTTP DELETE request.
|
|
299
272
|
|