universal-mcp-applications 0.1.30rc2__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.
- 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 +36 -103
- 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 +24 -101
- 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 +141 -463
- 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 +103 -580
- 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 +16 -38
- universal_mcp/applications/openai/app.py +42 -165
- universal_mcp/applications/outlook/app.py +24 -84
- 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 +17 -39
- 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.30rc2.dist-info → universal_mcp_applications-0.1.36rc2.dist-info}/METADATA +2 -2
- {universal_mcp_applications-0.1.30rc2.dist-info → universal_mcp_applications-0.1.36rc2.dist-info}/RECORD +105 -105
- {universal_mcp_applications-0.1.30rc2.dist-info → universal_mcp_applications-0.1.36rc2.dist-info}/WHEEL +0 -0
- {universal_mcp_applications-0.1.30rc2.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
|
|
|
@@ -19,7 +18,7 @@ class WrikeApp(APIApplication):
|
|
|
19
18
|
super().__init__(name="wrike", integration=integration, **kwargs)
|
|
20
19
|
self.base_url = "https://www.wrike.com/api/v4"
|
|
21
20
|
|
|
22
|
-
def get_contacts(self, deleted=None, fields=None, metadata=None) -> Any:
|
|
21
|
+
async def get_contacts(self, deleted=None, fields=None, metadata=None) -> Any:
|
|
23
22
|
"""
|
|
24
23
|
Retrieves contacts from the server with optional deleted status filtering, field selection, and metadata inclusion.
|
|
25
24
|
|
|
@@ -38,20 +37,12 @@ class WrikeApp(APIApplication):
|
|
|
38
37
|
retrieve, contacts, filter, api, important
|
|
39
38
|
"""
|
|
40
39
|
url = f"{self.base_url}/contacts"
|
|
41
|
-
query_params = {
|
|
42
|
-
k: v
|
|
43
|
-
for k, v in [
|
|
44
|
-
("deleted", deleted),
|
|
45
|
-
("fields", fields),
|
|
46
|
-
("metadata", metadata),
|
|
47
|
-
]
|
|
48
|
-
if v is not None
|
|
49
|
-
}
|
|
40
|
+
query_params = {k: v for k, v in [("deleted", deleted), ("fields", fields), ("metadata", metadata)] if v is not None}
|
|
50
41
|
response = self._get(url, params=query_params)
|
|
51
42
|
response.raise_for_status()
|
|
52
43
|
return response.json()
|
|
53
44
|
|
|
54
|
-
def get_contacts_by_contactid(self, contactId, fields=None) -> Any:
|
|
45
|
+
async def get_contacts_by_contactid(self, contactId, fields=None) -> Any:
|
|
55
46
|
"""
|
|
56
47
|
Retrieves contact information for a specific contact ID, optionally returning only specified fields.
|
|
57
48
|
|
|
@@ -76,15 +67,8 @@ class WrikeApp(APIApplication):
|
|
|
76
67
|
response.raise_for_status()
|
|
77
68
|
return response.json()
|
|
78
69
|
|
|
79
|
-
def put_contacts_by_contactid(
|
|
80
|
-
self,
|
|
81
|
-
contactId,
|
|
82
|
-
metadata=None,
|
|
83
|
-
currentBillRate=None,
|
|
84
|
-
currentCostRate=None,
|
|
85
|
-
jobRoleId=None,
|
|
86
|
-
customFields=None,
|
|
87
|
-
fields=None,
|
|
70
|
+
async def put_contacts_by_contactid(
|
|
71
|
+
self, contactId, metadata=None, currentBillRate=None, currentCostRate=None, jobRoleId=None, customFields=None, fields=None
|
|
88
72
|
) -> Any:
|
|
89
73
|
"""
|
|
90
74
|
Updates an existing contact using the specified contact ID with provided details including metadata, billing/cost rates, job role, and custom fields.
|
|
@@ -125,7 +109,7 @@ class WrikeApp(APIApplication):
|
|
|
125
109
|
response.raise_for_status()
|
|
126
110
|
return response.json()
|
|
127
111
|
|
|
128
|
-
def get_users_by_userid(self, userId) -> Any:
|
|
112
|
+
async def get_users_by_userid(self, userId) -> Any:
|
|
129
113
|
"""
|
|
130
114
|
Retrieves user information by ID from the API endpoint.
|
|
131
115
|
|
|
@@ -150,7 +134,7 @@ class WrikeApp(APIApplication):
|
|
|
150
134
|
response.raise_for_status()
|
|
151
135
|
return response.json()
|
|
152
136
|
|
|
153
|
-
def put_users_by_userid(self, userId, profile=None) -> Any:
|
|
137
|
+
async def put_users_by_userid(self, userId, profile=None) -> Any:
|
|
154
138
|
"""
|
|
155
139
|
Updates a user's profile information by user ID using a PUT request.
|
|
156
140
|
|
|
@@ -170,9 +154,7 @@ class WrikeApp(APIApplication):
|
|
|
170
154
|
"""
|
|
171
155
|
if userId is None:
|
|
172
156
|
raise ValueError("Missing required parameter 'userId'")
|
|
173
|
-
request_body = {
|
|
174
|
-
"profile": profile,
|
|
175
|
-
}
|
|
157
|
+
request_body = {"profile": profile}
|
|
176
158
|
request_body = {k: v for k, v in request_body.items() if v is not None}
|
|
177
159
|
url = f"{self.base_url}/users/{userId}"
|
|
178
160
|
query_params = {}
|
|
@@ -180,9 +162,7 @@ class WrikeApp(APIApplication):
|
|
|
180
162
|
response.raise_for_status()
|
|
181
163
|
return response.json()
|
|
182
164
|
|
|
183
|
-
def get_groups(
|
|
184
|
-
self, metadata=None, pageSize=None, pageToken=None, fields=None
|
|
185
|
-
) -> Any:
|
|
165
|
+
async def get_groups(self, metadata=None, pageSize=None, pageToken=None, fields=None) -> Any:
|
|
186
166
|
"""
|
|
187
167
|
Retrieves a list of groups from the API, applying optional filtering and pagination parameters.
|
|
188
168
|
|
|
@@ -203,22 +183,13 @@ class WrikeApp(APIApplication):
|
|
|
203
183
|
"""
|
|
204
184
|
url = f"{self.base_url}/groups"
|
|
205
185
|
query_params = {
|
|
206
|
-
k: v
|
|
207
|
-
for k, v in [
|
|
208
|
-
("metadata", metadata),
|
|
209
|
-
("pageSize", pageSize),
|
|
210
|
-
("pageToken", pageToken),
|
|
211
|
-
("fields", fields),
|
|
212
|
-
]
|
|
213
|
-
if v is not None
|
|
186
|
+
k: v for k, v in [("metadata", metadata), ("pageSize", pageSize), ("pageToken", pageToken), ("fields", fields)] if v is not None
|
|
214
187
|
}
|
|
215
188
|
response = self._get(url, params=query_params)
|
|
216
189
|
response.raise_for_status()
|
|
217
190
|
return response.json()
|
|
218
191
|
|
|
219
|
-
def post_groups(
|
|
220
|
-
self, title, members=None, parent=None, avatar=None, metadata=None
|
|
221
|
-
) -> Any:
|
|
192
|
+
async def post_groups(self, title, members=None, parent=None, avatar=None, metadata=None) -> Any:
|
|
222
193
|
"""
|
|
223
194
|
Creates a new group with the specified title and optional details via a POST request to the groups endpoint.
|
|
224
195
|
|
|
@@ -240,13 +211,7 @@ class WrikeApp(APIApplication):
|
|
|
240
211
|
"""
|
|
241
212
|
if title is None:
|
|
242
213
|
raise ValueError("Missing required parameter 'title'")
|
|
243
|
-
request_body = {
|
|
244
|
-
"title": title,
|
|
245
|
-
"members": members,
|
|
246
|
-
"parent": parent,
|
|
247
|
-
"avatar": avatar,
|
|
248
|
-
"metadata": metadata,
|
|
249
|
-
}
|
|
214
|
+
request_body = {"title": title, "members": members, "parent": parent, "avatar": avatar, "metadata": metadata}
|
|
250
215
|
request_body = {k: v for k, v in request_body.items() if v is not None}
|
|
251
216
|
url = f"{self.base_url}/groups"
|
|
252
217
|
query_params = {}
|
|
@@ -254,7 +219,7 @@ class WrikeApp(APIApplication):
|
|
|
254
219
|
response.raise_for_status()
|
|
255
220
|
return response.json()
|
|
256
221
|
|
|
257
|
-
def get_groups_by_groupid(self, groupId, fields=None) -> Any:
|
|
222
|
+
async def get_groups_by_groupid(self, groupId, fields=None) -> Any:
|
|
258
223
|
"""
|
|
259
224
|
Retrieves details for a specific group by its group ID, optionally returning only specified fields.
|
|
260
225
|
|
|
@@ -279,7 +244,7 @@ class WrikeApp(APIApplication):
|
|
|
279
244
|
response.raise_for_status()
|
|
280
245
|
return response.json()
|
|
281
246
|
|
|
282
|
-
def put_groups_by_groupid(
|
|
247
|
+
async def put_groups_by_groupid(
|
|
283
248
|
self,
|
|
284
249
|
groupId,
|
|
285
250
|
title=None,
|
|
@@ -333,7 +298,7 @@ class WrikeApp(APIApplication):
|
|
|
333
298
|
response.raise_for_status()
|
|
334
299
|
return response.json()
|
|
335
300
|
|
|
336
|
-
def delete_groups_by_groupid(self, groupId) -> Any:
|
|
301
|
+
async def delete_groups_by_groupid(self, groupId) -> Any:
|
|
337
302
|
"""
|
|
338
303
|
Deletes a group resource identified by the provided groupId using an HTTP DELETE request.
|
|
339
304
|
|
|
@@ -357,7 +322,7 @@ class WrikeApp(APIApplication):
|
|
|
357
322
|
response.raise_for_status()
|
|
358
323
|
return response.json()
|
|
359
324
|
|
|
360
|
-
def put_groups_bulk(self, members) -> Any:
|
|
325
|
+
async def put_groups_bulk(self, members) -> Any:
|
|
361
326
|
"""
|
|
362
327
|
Updates multiple group memberships in bulk by sending a PUT request with the given member data.
|
|
363
328
|
|
|
@@ -375,9 +340,7 @@ class WrikeApp(APIApplication):
|
|
|
375
340
|
"""
|
|
376
341
|
if members is None:
|
|
377
342
|
raise ValueError("Missing required parameter 'members'")
|
|
378
|
-
request_body = {
|
|
379
|
-
"members": members,
|
|
380
|
-
}
|
|
343
|
+
request_body = {"members": members}
|
|
381
344
|
request_body = {k: v for k, v in request_body.items() if v is not None}
|
|
382
345
|
url = f"{self.base_url}/groups_bulk"
|
|
383
346
|
query_params = {}
|
|
@@ -385,9 +348,7 @@ class WrikeApp(APIApplication):
|
|
|
385
348
|
response.raise_for_status()
|
|
386
349
|
return response.json()
|
|
387
350
|
|
|
388
|
-
def get_invitations(
|
|
389
|
-
self,
|
|
390
|
-
) -> Any:
|
|
351
|
+
async def get_invitations(self) -> Any:
|
|
391
352
|
"""
|
|
392
353
|
Retrieves all invitations from the server using a GET request.
|
|
393
354
|
|
|
@@ -409,16 +370,8 @@ class WrikeApp(APIApplication):
|
|
|
409
370
|
response.raise_for_status()
|
|
410
371
|
return response.json()
|
|
411
372
|
|
|
412
|
-
def post_invitations(
|
|
413
|
-
self,
|
|
414
|
-
email,
|
|
415
|
-
firstName=None,
|
|
416
|
-
lastName=None,
|
|
417
|
-
role=None,
|
|
418
|
-
external=None,
|
|
419
|
-
subject=None,
|
|
420
|
-
message=None,
|
|
421
|
-
userTypeId=None,
|
|
373
|
+
async def post_invitations(
|
|
374
|
+
self, email, firstName=None, lastName=None, role=None, external=None, subject=None, message=None, userTypeId=None
|
|
422
375
|
) -> Any:
|
|
423
376
|
"""
|
|
424
377
|
Sends an invitation email to a user with optional details such as name, role, and custom message.
|
|
@@ -461,9 +414,7 @@ class WrikeApp(APIApplication):
|
|
|
461
414
|
response.raise_for_status()
|
|
462
415
|
return response.json()
|
|
463
416
|
|
|
464
|
-
def put_invitations_by_invitationid(
|
|
465
|
-
self, invitationId, resend=None, role=None, external=None, userTypeId=None
|
|
466
|
-
) -> Any:
|
|
417
|
+
async def put_invitations_by_invitationid(self, invitationId, resend=None, role=None, external=None, userTypeId=None) -> Any:
|
|
467
418
|
"""
|
|
468
419
|
Updates an existing invitation by its unique ID with optional parameters, handling conditional updates and API communication.
|
|
469
420
|
|
|
@@ -486,12 +437,7 @@ class WrikeApp(APIApplication):
|
|
|
486
437
|
"""
|
|
487
438
|
if invitationId is None:
|
|
488
439
|
raise ValueError("Missing required parameter 'invitationId'")
|
|
489
|
-
request_body = {
|
|
490
|
-
"resend": resend,
|
|
491
|
-
"role": role,
|
|
492
|
-
"external": external,
|
|
493
|
-
"userTypeId": userTypeId,
|
|
494
|
-
}
|
|
440
|
+
request_body = {"resend": resend, "role": role, "external": external, "userTypeId": userTypeId}
|
|
495
441
|
request_body = {k: v for k, v in request_body.items() if v is not None}
|
|
496
442
|
url = f"{self.base_url}/invitations/{invitationId}"
|
|
497
443
|
query_params = {}
|
|
@@ -499,7 +445,7 @@ class WrikeApp(APIApplication):
|
|
|
499
445
|
response.raise_for_status()
|
|
500
446
|
return response.json()
|
|
501
447
|
|
|
502
|
-
def delete_invitations_by_invitationid(self, invitationId) -> Any:
|
|
448
|
+
async def delete_invitations_by_invitationid(self, invitationId) -> Any:
|
|
503
449
|
"""
|
|
504
450
|
Deletes a specific invitation using its unique identifier
|
|
505
451
|
|
|
@@ -524,7 +470,7 @@ class WrikeApp(APIApplication):
|
|
|
524
470
|
response.raise_for_status()
|
|
525
471
|
return response.json()
|
|
526
472
|
|
|
527
|
-
def get_a_ccount(self, fields=None) -> Any:
|
|
473
|
+
async def get_a_ccount(self, fields=None) -> Any:
|
|
528
474
|
"""
|
|
529
475
|
Retrieves account information from the API, optionally including only specified fields.
|
|
530
476
|
|
|
@@ -546,7 +492,7 @@ class WrikeApp(APIApplication):
|
|
|
546
492
|
response.raise_for_status()
|
|
547
493
|
return response.json()
|
|
548
494
|
|
|
549
|
-
def put_a_ccount(self, metadata=None) -> Any:
|
|
495
|
+
async def put_a_ccount(self, metadata=None) -> Any:
|
|
550
496
|
"""
|
|
551
497
|
Sends a PUT request to update or create an account with the provided metadata and returns the server response as a JSON object.
|
|
552
498
|
|
|
@@ -562,9 +508,7 @@ class WrikeApp(APIApplication):
|
|
|
562
508
|
Tags:
|
|
563
509
|
put, account, metadata, async_job
|
|
564
510
|
"""
|
|
565
|
-
request_body = {
|
|
566
|
-
"metadata": metadata,
|
|
567
|
-
}
|
|
511
|
+
request_body = {"metadata": metadata}
|
|
568
512
|
request_body = {k: v for k, v in request_body.items() if v is not None}
|
|
569
513
|
url = f"{self.base_url}/account"
|
|
570
514
|
query_params = {}
|
|
@@ -572,9 +516,7 @@ class WrikeApp(APIApplication):
|
|
|
572
516
|
response.raise_for_status()
|
|
573
517
|
return response.json()
|
|
574
518
|
|
|
575
|
-
def get_workflows(
|
|
576
|
-
self,
|
|
577
|
-
) -> Any:
|
|
519
|
+
async def get_workflows(self) -> Any:
|
|
578
520
|
"""
|
|
579
521
|
Retrieves all workflows from the server using a GET request.
|
|
580
522
|
|
|
@@ -596,7 +538,7 @@ class WrikeApp(APIApplication):
|
|
|
596
538
|
response.raise_for_status()
|
|
597
539
|
return response.json()
|
|
598
540
|
|
|
599
|
-
def post_workflows(self, name=None, request_body=None) -> Any:
|
|
541
|
+
async def post_workflows(self, name=None, request_body=None) -> Any:
|
|
600
542
|
"""
|
|
601
543
|
Creates a new workflow by sending a POST request to the workflows endpoint with optional name and request body.
|
|
602
544
|
|
|
@@ -619,9 +561,7 @@ class WrikeApp(APIApplication):
|
|
|
619
561
|
response.raise_for_status()
|
|
620
562
|
return response.json()
|
|
621
563
|
|
|
622
|
-
def put_workflows_by_workflowid(
|
|
623
|
-
self, workflowId, name=None, hidden=None, request_body=None
|
|
624
|
-
) -> Any:
|
|
564
|
+
async def put_workflows_by_workflowid(self, workflowId, name=None, hidden=None, request_body=None) -> Any:
|
|
625
565
|
"""
|
|
626
566
|
Updates an existing workflow by workflow ID with optional name, hidden status, and request body data.
|
|
627
567
|
|
|
@@ -643,16 +583,12 @@ class WrikeApp(APIApplication):
|
|
|
643
583
|
if workflowId is None:
|
|
644
584
|
raise ValueError("Missing required parameter 'workflowId'")
|
|
645
585
|
url = f"{self.base_url}/workflows/{workflowId}"
|
|
646
|
-
query_params = {
|
|
647
|
-
k: v for k, v in [("name", name), ("hidden", hidden)] if v is not None
|
|
648
|
-
}
|
|
586
|
+
query_params = {k: v for k, v in [("name", name), ("hidden", hidden)] if v is not None}
|
|
649
587
|
response = self._put(url, data=request_body, params=query_params)
|
|
650
588
|
response.raise_for_status()
|
|
651
589
|
return response.json()
|
|
652
590
|
|
|
653
|
-
def get_customfields(
|
|
654
|
-
self,
|
|
655
|
-
) -> Any:
|
|
591
|
+
async def get_customfields(self) -> Any:
|
|
656
592
|
"""
|
|
657
593
|
Retrieves all custom fields from the API and returns them as a parsed JSON object.
|
|
658
594
|
|
|
@@ -674,16 +610,7 @@ class WrikeApp(APIApplication):
|
|
|
674
610
|
response.raise_for_status()
|
|
675
611
|
return response.json()
|
|
676
612
|
|
|
677
|
-
def post_customfields(
|
|
678
|
-
self,
|
|
679
|
-
title,
|
|
680
|
-
type,
|
|
681
|
-
spaceId=None,
|
|
682
|
-
sharing=None,
|
|
683
|
-
shareds=None,
|
|
684
|
-
settings=None,
|
|
685
|
-
request_body=None,
|
|
686
|
-
) -> Any:
|
|
613
|
+
async def post_customfields(self, title, type, spaceId=None, sharing=None, shareds=None, settings=None, request_body=None) -> Any:
|
|
687
614
|
"""
|
|
688
615
|
Creates a custom field by sending a POST request to the customfields endpoint with the specified parameters.
|
|
689
616
|
|
|
@@ -726,7 +653,7 @@ class WrikeApp(APIApplication):
|
|
|
726
653
|
response.raise_for_status()
|
|
727
654
|
return response.json()
|
|
728
655
|
|
|
729
|
-
def get_customfields_by_customfieldid(self, customFieldId) -> Any:
|
|
656
|
+
async def get_customfields_by_customfieldid(self, customFieldId) -> Any:
|
|
730
657
|
"""
|
|
731
658
|
Retrieves details for a custom field by its unique identifier from the API
|
|
732
659
|
|
|
@@ -750,7 +677,7 @@ class WrikeApp(APIApplication):
|
|
|
750
677
|
response.raise_for_status()
|
|
751
678
|
return response.json()
|
|
752
679
|
|
|
753
|
-
def put_customfields_by_customfieldid(
|
|
680
|
+
async def put_customfields_by_customfieldid(
|
|
754
681
|
self,
|
|
755
682
|
customFieldId,
|
|
756
683
|
title=None,
|
|
@@ -812,7 +739,7 @@ class WrikeApp(APIApplication):
|
|
|
812
739
|
response.raise_for_status()
|
|
813
740
|
return response.json()
|
|
814
741
|
|
|
815
|
-
def delete_customfields_by_customfieldid(self, customFieldId) -> Any:
|
|
742
|
+
async def delete_customfields_by_customfieldid(self, customFieldId) -> Any:
|
|
816
743
|
"""
|
|
817
744
|
Deletes a custom field resource identified by its custom field ID.
|
|
818
745
|
|
|
@@ -836,7 +763,7 @@ class WrikeApp(APIApplication):
|
|
|
836
763
|
response.raise_for_status()
|
|
837
764
|
return response.json()
|
|
838
765
|
|
|
839
|
-
def get_folders(
|
|
766
|
+
async def get_folders(
|
|
840
767
|
self,
|
|
841
768
|
permalink=None,
|
|
842
769
|
descendants=None,
|
|
@@ -906,7 +833,7 @@ class WrikeApp(APIApplication):
|
|
|
906
833
|
response.raise_for_status()
|
|
907
834
|
return response.json()
|
|
908
835
|
|
|
909
|
-
def get_folders_by_folderid_folders(
|
|
836
|
+
async def get_folders_by_folderid_folders(
|
|
910
837
|
self,
|
|
911
838
|
folderId,
|
|
912
839
|
permalink=None,
|
|
@@ -977,7 +904,7 @@ class WrikeApp(APIApplication):
|
|
|
977
904
|
response.raise_for_status()
|
|
978
905
|
return response.json()
|
|
979
906
|
|
|
980
|
-
def post_folders_by_folderid_folders(
|
|
907
|
+
async def post_folders_by_folderid_folders(
|
|
981
908
|
self,
|
|
982
909
|
folderId,
|
|
983
910
|
title,
|
|
@@ -1045,7 +972,7 @@ class WrikeApp(APIApplication):
|
|
|
1045
972
|
response.raise_for_status()
|
|
1046
973
|
return response.json()
|
|
1047
974
|
|
|
1048
|
-
def delete_folders_by_folderid(self, folderId) -> Any:
|
|
975
|
+
async def delete_folders_by_folderid(self, folderId) -> Any:
|
|
1049
976
|
"""
|
|
1050
977
|
Deletes a folder resource identified by its folder ID via an HTTP DELETE request.
|
|
1051
978
|
|
|
@@ -1070,7 +997,7 @@ class WrikeApp(APIApplication):
|
|
|
1070
997
|
response.raise_for_status()
|
|
1071
998
|
return response.json()
|
|
1072
999
|
|
|
1073
|
-
def put_folders_by_folderid(
|
|
1000
|
+
async def put_folders_by_folderid(
|
|
1074
1001
|
self,
|
|
1075
1002
|
folderId,
|
|
1076
1003
|
title=None,
|
|
@@ -1155,7 +1082,7 @@ class WrikeApp(APIApplication):
|
|
|
1155
1082
|
response.raise_for_status()
|
|
1156
1083
|
return response.json()
|
|
1157
1084
|
|
|
1158
|
-
def get_tasks(
|
|
1085
|
+
async def get_tasks(
|
|
1159
1086
|
self,
|
|
1160
1087
|
descendants=None,
|
|
1161
1088
|
title=None,
|
|
@@ -1273,7 +1200,7 @@ class WrikeApp(APIApplication):
|
|
|
1273
1200
|
response.raise_for_status()
|
|
1274
1201
|
return response.json()
|
|
1275
1202
|
|
|
1276
|
-
def get_tasks_by_taskid(self, taskId, fields=None) -> Any:
|
|
1203
|
+
async def get_tasks_by_taskid(self, taskId, fields=None) -> Any:
|
|
1277
1204
|
"""
|
|
1278
1205
|
Retrieves a task by its ID from the remote service, optionally returning only specified fields.
|
|
1279
1206
|
|
|
@@ -1298,7 +1225,7 @@ class WrikeApp(APIApplication):
|
|
|
1298
1225
|
response.raise_for_status()
|
|
1299
1226
|
return response.json()
|
|
1300
1227
|
|
|
1301
|
-
def put_tasks_by_taskid(
|
|
1228
|
+
async def put_tasks_by_taskid(
|
|
1302
1229
|
self,
|
|
1303
1230
|
taskId,
|
|
1304
1231
|
title=None,
|
|
@@ -1416,7 +1343,7 @@ class WrikeApp(APIApplication):
|
|
|
1416
1343
|
response.raise_for_status()
|
|
1417
1344
|
return response.json()
|
|
1418
1345
|
|
|
1419
|
-
def delete_tasks_by_taskid(self, taskId) -> Any:
|
|
1346
|
+
async def delete_tasks_by_taskid(self, taskId) -> Any:
|
|
1420
1347
|
"""
|
|
1421
1348
|
Deletes a task identified by the given task ID via an HTTP DELETE request and returns the response as a JSON object.
|
|
1422
1349
|
|
|
@@ -1441,7 +1368,7 @@ class WrikeApp(APIApplication):
|
|
|
1441
1368
|
response.raise_for_status()
|
|
1442
1369
|
return response.json()
|
|
1443
1370
|
|
|
1444
|
-
def post_folders_by_folderid_tasks(
|
|
1371
|
+
async def post_folders_by_folderid_tasks(
|
|
1445
1372
|
self,
|
|
1446
1373
|
folderId,
|
|
1447
1374
|
title,
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
from typing import Any
|
|
2
|
-
|
|
3
2
|
import yfinance as yf
|
|
4
3
|
from universal_mcp.applications.application import APIApplication
|
|
5
4
|
from universal_mcp.integrations import Integration
|
|
@@ -14,7 +13,7 @@ class YahooFinanceApp(APIApplication):
|
|
|
14
13
|
def __init__(self, integration: Integration | None = None, **kwargs) -> None:
|
|
15
14
|
super().__init__(name="yahoo_finance", integration=integration, **kwargs)
|
|
16
15
|
|
|
17
|
-
def get_stock_info(self, symbol: str) -> dict[str, Any]:
|
|
16
|
+
async def get_stock_info(self, symbol: str) -> dict[str, Any]:
|
|
18
17
|
"""
|
|
19
18
|
Gets real-time stock information including current price, market cap, financial ratios, and company details.
|
|
20
19
|
|
|
@@ -34,23 +33,15 @@ class YahooFinanceApp(APIApplication):
|
|
|
34
33
|
"""
|
|
35
34
|
if not symbol:
|
|
36
35
|
raise ValueError("Stock symbol cannot be empty")
|
|
37
|
-
|
|
38
36
|
symbol = symbol.upper().strip()
|
|
39
37
|
ticker = yf.Ticker(symbol)
|
|
40
|
-
|
|
41
38
|
info = ticker.info
|
|
42
39
|
if not info or info.get("regularMarketPrice") is None:
|
|
43
40
|
raise KeyError(f"Stock symbol '{symbol}' not found or invalid")
|
|
44
|
-
|
|
45
41
|
return info
|
|
46
42
|
|
|
47
|
-
def get_stock_history(
|
|
48
|
-
self,
|
|
49
|
-
symbol: str,
|
|
50
|
-
period: str = "1mo",
|
|
51
|
-
interval: str = "1d",
|
|
52
|
-
start_date: str | None = None,
|
|
53
|
-
end_date: str | None = None,
|
|
43
|
+
async def get_stock_history(
|
|
44
|
+
self, symbol: str, period: str = "1mo", interval: str = "1d", start_date: str | None = None, end_date: str | None = None
|
|
54
45
|
) -> dict:
|
|
55
46
|
"""
|
|
56
47
|
Gets historical price data for a stock with OHLCV data, dividends, and stock splits.
|
|
@@ -70,21 +61,16 @@ class YahooFinanceApp(APIApplication):
|
|
|
70
61
|
"""
|
|
71
62
|
if not symbol:
|
|
72
63
|
raise ValueError("Stock symbol cannot be empty")
|
|
73
|
-
|
|
74
64
|
symbol = symbol.upper().strip()
|
|
75
65
|
ticker = yf.Ticker(symbol)
|
|
76
|
-
|
|
77
|
-
df = ticker.history(
|
|
78
|
-
period=period, interval=interval, start=start_date, end=end_date
|
|
79
|
-
)
|
|
80
|
-
|
|
66
|
+
df = ticker.history(period=period, interval=interval, start=start_date, end=end_date)
|
|
81
67
|
try:
|
|
82
|
-
data = df.to_dict("index")
|
|
68
|
+
data = df.to_dict("index")
|
|
83
69
|
if data:
|
|
84
70
|
converted_data = {}
|
|
85
71
|
for key, value in data.items():
|
|
86
|
-
if hasattr(key,
|
|
87
|
-
converted_key = key.strftime(
|
|
72
|
+
if hasattr(key, "strftime"):
|
|
73
|
+
converted_key = key.strftime("%Y-%m-%d")
|
|
88
74
|
else:
|
|
89
75
|
converted_key = str(key)
|
|
90
76
|
converted_data[converted_key] = value
|
|
@@ -93,7 +79,7 @@ class YahooFinanceApp(APIApplication):
|
|
|
93
79
|
except:
|
|
94
80
|
return {}
|
|
95
81
|
|
|
96
|
-
def get_stock_news(self, symbol: str, limit: int = 10) -> list[Any]:
|
|
82
|
+
async def get_stock_news(self, symbol: str, limit: int = 10) -> list[Any]:
|
|
97
83
|
"""
|
|
98
84
|
Gets latest news articles for a stock from Yahoo Finance.
|
|
99
85
|
|
|
@@ -109,16 +95,12 @@ class YahooFinanceApp(APIApplication):
|
|
|
109
95
|
"""
|
|
110
96
|
if not symbol:
|
|
111
97
|
raise ValueError("Stock symbol cannot be empty")
|
|
112
|
-
|
|
113
98
|
symbol = symbol.upper().strip()
|
|
114
99
|
ticker = yf.Ticker(symbol)
|
|
115
|
-
|
|
116
100
|
news = ticker.news
|
|
117
101
|
return news[:limit] if news else []
|
|
118
102
|
|
|
119
|
-
def get_financial_statements(
|
|
120
|
-
self, symbol: str, statement_type: str = "income"
|
|
121
|
-
) -> dict:
|
|
103
|
+
async def get_financial_statements(self, symbol: str, statement_type: str = "income") -> dict:
|
|
122
104
|
"""
|
|
123
105
|
Gets financial statements for a stock from Yahoo Finance.
|
|
124
106
|
|
|
@@ -134,10 +116,8 @@ class YahooFinanceApp(APIApplication):
|
|
|
134
116
|
"""
|
|
135
117
|
if not symbol:
|
|
136
118
|
raise ValueError("Stock symbol cannot be empty")
|
|
137
|
-
|
|
138
119
|
symbol = symbol.upper().strip()
|
|
139
120
|
ticker = yf.Ticker(symbol)
|
|
140
|
-
|
|
141
121
|
if statement_type == "income":
|
|
142
122
|
df = ticker.income_stmt
|
|
143
123
|
elif statement_type == "balance":
|
|
@@ -148,14 +128,13 @@ class YahooFinanceApp(APIApplication):
|
|
|
148
128
|
df = ticker.earnings
|
|
149
129
|
else:
|
|
150
130
|
df = ticker.income_stmt
|
|
151
|
-
|
|
152
131
|
try:
|
|
153
|
-
data = df.to_dict("dict")
|
|
132
|
+
data = df.to_dict("dict")
|
|
154
133
|
if data:
|
|
155
134
|
converted_data = {}
|
|
156
135
|
for key, value in data.items():
|
|
157
|
-
if hasattr(key,
|
|
158
|
-
converted_key = key.strftime(
|
|
136
|
+
if hasattr(key, "strftime"):
|
|
137
|
+
converted_key = key.strftime("%Y-%m-%d")
|
|
159
138
|
else:
|
|
160
139
|
converted_key = str(key)
|
|
161
140
|
converted_data[converted_key] = value
|
|
@@ -164,9 +143,7 @@ class YahooFinanceApp(APIApplication):
|
|
|
164
143
|
except:
|
|
165
144
|
return {}
|
|
166
145
|
|
|
167
|
-
def get_stock_recommendations(
|
|
168
|
-
self, symbol: str, rec_type: str = "recommendations"
|
|
169
|
-
) -> list[dict]:
|
|
146
|
+
async def get_stock_recommendations(self, symbol: str, rec_type: str = "recommendations") -> list[dict]:
|
|
170
147
|
"""
|
|
171
148
|
Gets analyst recommendations for a stock from Yahoo Finance.
|
|
172
149
|
|
|
@@ -182,27 +159,18 @@ class YahooFinanceApp(APIApplication):
|
|
|
182
159
|
"""
|
|
183
160
|
if not symbol:
|
|
184
161
|
raise ValueError("Stock symbol cannot be empty")
|
|
185
|
-
|
|
186
162
|
symbol = symbol.upper().strip()
|
|
187
163
|
ticker = yf.Ticker(symbol)
|
|
188
|
-
|
|
189
164
|
if rec_type == "upgrades_downgrades":
|
|
190
165
|
df = ticker.upgrades_downgrades
|
|
191
166
|
else:
|
|
192
167
|
df = ticker.recommendations
|
|
193
|
-
|
|
194
168
|
try:
|
|
195
|
-
return df.to_dict("records")
|
|
169
|
+
return df.to_dict("records")
|
|
196
170
|
except:
|
|
197
171
|
return []
|
|
198
172
|
|
|
199
|
-
def search(
|
|
200
|
-
self,
|
|
201
|
-
query: str,
|
|
202
|
-
max_results: int = 10,
|
|
203
|
-
news_count: int = 5,
|
|
204
|
-
include_research: bool = False,
|
|
205
|
-
) -> dict[str, Any]:
|
|
173
|
+
async def search(self, query: str, max_results: int = 10, news_count: int = 5, include_research: bool = False) -> dict[str, Any]:
|
|
206
174
|
"""
|
|
207
175
|
Search Yahoo Finance for quotes, news, and research using yfinance Search.
|
|
208
176
|
|
|
@@ -220,14 +188,7 @@ class YahooFinanceApp(APIApplication):
|
|
|
220
188
|
"""
|
|
221
189
|
if not query:
|
|
222
190
|
raise ValueError("Search query cannot be empty")
|
|
223
|
-
|
|
224
|
-
search = yf.Search(
|
|
225
|
-
query,
|
|
226
|
-
max_results=max_results,
|
|
227
|
-
news_count=news_count,
|
|
228
|
-
include_research=include_research,
|
|
229
|
-
)
|
|
230
|
-
|
|
191
|
+
search = yf.Search(query, max_results=max_results, news_count=news_count, include_research=include_research)
|
|
231
192
|
result = {}
|
|
232
193
|
for attr in dir(search):
|
|
233
194
|
if not attr.startswith("_"):
|
|
@@ -237,12 +198,9 @@ class YahooFinanceApp(APIApplication):
|
|
|
237
198
|
result[attr] = value
|
|
238
199
|
except:
|
|
239
200
|
continue
|
|
240
|
-
|
|
241
201
|
return result
|
|
242
202
|
|
|
243
|
-
def lookup_ticker(
|
|
244
|
-
self, query: str, lookup_type: str = "all", count: int = 25
|
|
245
|
-
) -> list[dict]:
|
|
203
|
+
async def lookup_ticker(self, query: str, lookup_type: str = "all", count: int = 25) -> list[dict]:
|
|
246
204
|
"""
|
|
247
205
|
Look up ticker symbols by type using yfinance Lookup.
|
|
248
206
|
|
|
@@ -259,10 +217,8 @@ class YahooFinanceApp(APIApplication):
|
|
|
259
217
|
"""
|
|
260
218
|
if not query:
|
|
261
219
|
raise ValueError("Lookup query cannot be empty")
|
|
262
|
-
|
|
263
220
|
try:
|
|
264
221
|
lookup = yf.Lookup(query)
|
|
265
|
-
|
|
266
222
|
if lookup_type == "stock":
|
|
267
223
|
results = lookup.get_stock(count=count)
|
|
268
224
|
elif lookup_type == "mutualfund":
|
|
@@ -277,14 +233,12 @@ class YahooFinanceApp(APIApplication):
|
|
|
277
233
|
results = lookup.get_currency(count=count)
|
|
278
234
|
elif lookup_type == "cryptocurrency":
|
|
279
235
|
results = lookup.get_cryptocurrency(count=count)
|
|
280
|
-
else:
|
|
236
|
+
else:
|
|
281
237
|
results = lookup.get_all(count=count)
|
|
282
|
-
|
|
283
238
|
try:
|
|
284
|
-
return results.to_dict("records")
|
|
239
|
+
return results.to_dict("records")
|
|
285
240
|
except:
|
|
286
241
|
return []
|
|
287
|
-
|
|
288
242
|
except Exception as e:
|
|
289
243
|
return [{"query": query, "error": f"Lookup failed: {str(e)}"}]
|
|
290
244
|
|