universal-mcp-applications 0.1.21__py3-none-any.whl → 0.1.22__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 (78) hide show
  1. universal_mcp/applications/BEST_PRACTICES.md +166 -0
  2. universal_mcp/applications/airtable/app.py +0 -1
  3. universal_mcp/applications/apollo/app.py +0 -1
  4. universal_mcp/applications/aws_s3/app.py +40 -39
  5. universal_mcp/applications/browser_use/README.md +1 -0
  6. universal_mcp/applications/browser_use/__init__.py +0 -0
  7. universal_mcp/applications/browser_use/app.py +76 -0
  8. universal_mcp/applications/calendly/app.py +125 -125
  9. universal_mcp/applications/canva/app.py +95 -99
  10. universal_mcp/applications/confluence/app.py +0 -1
  11. universal_mcp/applications/contentful/app.py +4 -5
  12. universal_mcp/applications/domain_checker/app.py +11 -15
  13. universal_mcp/applications/e2b/app.py +4 -4
  14. universal_mcp/applications/elevenlabs/app.py +18 -15
  15. universal_mcp/applications/exa/app.py +17 -17
  16. universal_mcp/applications/falai/app.py +28 -29
  17. universal_mcp/applications/file_system/app.py +9 -9
  18. universal_mcp/applications/firecrawl/app.py +36 -36
  19. universal_mcp/applications/fireflies/app.py +55 -56
  20. universal_mcp/applications/fpl/app.py +49 -50
  21. universal_mcp/applications/ghost_content/app.py +0 -1
  22. universal_mcp/applications/github/app.py +41 -43
  23. universal_mcp/applications/google_calendar/app.py +40 -39
  24. universal_mcp/applications/google_docs/app.py +56 -56
  25. universal_mcp/applications/google_drive/app.py +212 -215
  26. universal_mcp/applications/google_gemini/app.py +1 -5
  27. universal_mcp/applications/google_mail/app.py +91 -90
  28. universal_mcp/applications/google_searchconsole/app.py +29 -29
  29. universal_mcp/applications/google_sheet/app.py +115 -115
  30. universal_mcp/applications/hashnode/README.md +6 -3
  31. universal_mcp/applications/hashnode/app.py +174 -25
  32. universal_mcp/applications/http_tools/app.py +10 -11
  33. universal_mcp/applications/hubspot/__init__.py +1 -1
  34. universal_mcp/applications/hubspot/api_segments/api_segment_base.py +36 -7
  35. universal_mcp/applications/hubspot/api_segments/crm_api.py +368 -368
  36. universal_mcp/applications/hubspot/api_segments/marketing_api.py +115 -115
  37. universal_mcp/applications/hubspot/app.py +131 -72
  38. universal_mcp/applications/jira/app.py +0 -1
  39. universal_mcp/applications/linkedin/app.py +20 -20
  40. universal_mcp/applications/markitdown/app.py +10 -5
  41. universal_mcp/applications/ms_teams/app.py +123 -123
  42. universal_mcp/applications/openai/app.py +40 -39
  43. universal_mcp/applications/outlook/app.py +32 -32
  44. universal_mcp/applications/perplexity/app.py +4 -4
  45. universal_mcp/applications/reddit/app.py +69 -70
  46. universal_mcp/applications/resend/app.py +116 -117
  47. universal_mcp/applications/rocketlane/app.py +0 -1
  48. universal_mcp/applications/scraper/__init__.py +1 -1
  49. universal_mcp/applications/scraper/app.py +80 -81
  50. universal_mcp/applications/serpapi/app.py +14 -14
  51. universal_mcp/applications/sharepoint/app.py +19 -20
  52. universal_mcp/applications/shopify/app.py +0 -1
  53. universal_mcp/applications/slack/app.py +48 -48
  54. universal_mcp/applications/tavily/app.py +4 -4
  55. universal_mcp/applications/twitter/api_segments/compliance_api.py +13 -15
  56. universal_mcp/applications/twitter/api_segments/dm_conversations_api.py +20 -20
  57. universal_mcp/applications/twitter/api_segments/dm_events_api.py +12 -12
  58. universal_mcp/applications/twitter/api_segments/likes_api.py +12 -12
  59. universal_mcp/applications/twitter/api_segments/lists_api.py +37 -39
  60. universal_mcp/applications/twitter/api_segments/spaces_api.py +24 -24
  61. universal_mcp/applications/twitter/api_segments/trends_api.py +4 -4
  62. universal_mcp/applications/twitter/api_segments/tweets_api.py +105 -105
  63. universal_mcp/applications/twitter/api_segments/usage_api.py +4 -4
  64. universal_mcp/applications/twitter/api_segments/users_api.py +136 -136
  65. universal_mcp/applications/twitter/app.py +6 -2
  66. universal_mcp/applications/unipile/app.py +90 -97
  67. universal_mcp/applications/whatsapp/app.py +53 -54
  68. universal_mcp/applications/whatsapp/audio.py +39 -35
  69. universal_mcp/applications/whatsapp/whatsapp.py +176 -154
  70. universal_mcp/applications/whatsapp_business/app.py +92 -92
  71. universal_mcp/applications/yahoo_finance/app.py +105 -63
  72. universal_mcp/applications/youtube/app.py +193 -196
  73. universal_mcp/applications/zenquotes/__init__.py +2 -0
  74. universal_mcp/applications/zenquotes/app.py +3 -3
  75. {universal_mcp_applications-0.1.21.dist-info → universal_mcp_applications-0.1.22.dist-info}/METADATA +2 -1
  76. {universal_mcp_applications-0.1.21.dist-info → universal_mcp_applications-0.1.22.dist-info}/RECORD +78 -74
  77. {universal_mcp_applications-0.1.21.dist-info → universal_mcp_applications-0.1.22.dist-info}/WHEEL +0 -0
  78. {universal_mcp_applications-0.1.21.dist-info → universal_mcp_applications-0.1.22.dist-info}/licenses/LICENSE +0 -0
@@ -1,23 +1,25 @@
1
+ from datetime import UTC, datetime
2
+ from typing import Any
3
+
1
4
  from universal_mcp.applications.application import APIApplication
2
5
  from universal_mcp.integrations import Integration
6
+
3
7
  from universal_mcp.applications.hubspot.api_segments.crm_api import CrmApi
4
8
  from universal_mcp.applications.hubspot.api_segments.marketing_api import MarketingApi
5
- from typing import List, Optional, Any
6
- from datetime import datetime, timezone
7
9
 
8
- class HubspotApp(APIApplication):
9
10
 
10
- def __init__(self, integration: Integration=None, **kwargs) -> None:
11
- super().__init__(name='hubspot', integration=integration, **kwargs)
12
- self.base_url = 'https://api.hubapi.com'
11
+ class HubspotApp(APIApplication):
12
+ def __init__(self, integration: Integration = None, **kwargs) -> None:
13
+ super().__init__(name="hubspot", integration=integration, **kwargs)
14
+ self.base_url = "https://api.hubapi.com"
13
15
  self.crm = CrmApi(self)
14
16
  self.marketing = MarketingApi(self)
15
-
17
+
16
18
  def add_a_note(
17
19
  self,
18
20
  hs_note_body: str,
19
- hs_timestamp: Optional[str] = None,
20
- associations: Optional[List[dict[str, Any]]] = None,
21
+ hs_timestamp: str | None = None,
22
+ associations: list[dict[str, Any]] | None = None,
21
23
  ) -> dict[str, Any]:
22
24
  """
23
25
  Create a note in HubSpot with the given properties and associations.
@@ -38,28 +40,30 @@ class HubspotApp(APIApplication):
38
40
  """
39
41
  if hs_note_body is None:
40
42
  raise ValueError("Missing required parameter 'hs_note_body'.")
41
-
43
+
42
44
  url = f"{self.base_url}/crm/v3/objects/notes"
43
-
45
+
44
46
  # Build the properties object
45
47
  properties = {
46
48
  "hs_note_body": hs_note_body,
47
- "hs_timestamp": hs_timestamp if hs_timestamp else datetime.now(timezone.utc).isoformat()
49
+ "hs_timestamp": hs_timestamp
50
+ if hs_timestamp
51
+ else datetime.now(UTC).isoformat(),
48
52
  }
49
-
53
+
50
54
  # Build the request body
51
- request_body_data: dict[str, Any] = {
52
- "properties": properties
53
- }
54
-
55
+ request_body_data: dict[str, Any] = {"properties": properties}
56
+
55
57
  # Add associations if provided
56
58
  if associations:
57
59
  request_body_data["associations"] = associations
58
-
60
+
59
61
  response = self._post(url, data=request_body_data)
60
62
  return self._handle_response(response)
61
63
 
62
- def fetch_multiple_lists(self, listIds: Optional[List[str]] = None, includeFilters: Optional[bool] = None) -> dict[str, Any]:
64
+ def fetch_multiple_lists(
65
+ self, listIds: list[str] | None = None, includeFilters: bool | None = None
66
+ ) -> dict[str, Any]:
63
67
  """
64
68
  Fetch multiple lists in a single request by ILS list ID. The response will include the definitions of all lists that exist for the listIds provided.
65
69
 
@@ -77,16 +81,20 @@ class HubspotApp(APIApplication):
77
81
  Lists
78
82
  """
79
83
  url = f"{self.base_url}/crm/v3/lists/"
80
- query_params = {k: v for k, v in [('listIds', listIds), ('includeFilters', includeFilters)] if v is not None}
84
+ query_params = {
85
+ k: v
86
+ for k, v in [("listIds", listIds), ("includeFilters", includeFilters)]
87
+ if v is not None
88
+ }
81
89
  response = self._get(url, params=query_params)
82
- return self._handle_response(response)
90
+ return self._handle_response(response)
83
91
 
84
92
  def fetch_list_memberships(
85
93
  self,
86
94
  listId: str,
87
- after: Optional[str] = None,
88
- before: Optional[str] = None,
89
- limit: Optional[int] = None,
95
+ after: str | None = None,
96
+ before: str | None = None,
97
+ limit: int | None = None,
90
98
  ) -> dict[str, Any]:
91
99
  """
92
100
  Fetch the memberships of a list in order sorted by the recordId of the records in the list.
@@ -108,24 +116,34 @@ class HubspotApp(APIApplication):
108
116
  """
109
117
  if listId is None:
110
118
  raise ValueError("Missing required parameter 'listId'.")
111
-
119
+
112
120
  url = f"{self.base_url}/crm/v3/lists/{listId}/memberships"
113
121
  query_params = {}
114
-
122
+
115
123
  if after is not None:
116
124
  query_params["after"] = after
117
125
  if before is not None:
118
126
  query_params["before"] = before
119
127
  if limit is not None:
120
128
  query_params["limit"] = limit
121
-
129
+
122
130
  response = self._get(url, params=query_params)
123
131
  return self._handle_response(response)
124
132
 
125
- def create_list(self, objectTypeId: str, processingType: str, name: str, membershipSettings: Optional[dict[str, Any]] = None, customProperties: Optional[dict[str, str]] = None, listFolderId: Optional[int] = None, listPermissions: Optional[dict[str, Any]] = None, filterBranch: Optional[Any] = None) -> dict[str, Any]:
133
+ def create_list(
134
+ self,
135
+ objectTypeId: str,
136
+ processingType: str,
137
+ name: str,
138
+ membershipSettings: dict[str, Any] | None = None,
139
+ customProperties: dict[str, str] | None = None,
140
+ listFolderId: int | None = None,
141
+ listPermissions: dict[str, Any] | None = None,
142
+ filterBranch: Any | None = None,
143
+ ) -> dict[str, Any]:
126
144
  """
127
- Create a new list in HubSpot with the specified object type, processing type, and name.
128
- Optionally use this to provide membership settings, custom properties, a folder ID, list permissions,
145
+ Create a new list in HubSpot with the specified object type, processing type, and name.
146
+ Optionally use this to provide membership settings, custom properties, a folder ID, list permissions,
129
147
  and a filter branch to further configure the list.
130
148
 
131
149
  Args:
@@ -149,22 +167,31 @@ class HubspotApp(APIApplication):
149
167
  """
150
168
  request_body_data = None
151
169
  request_body_data = {
152
- 'membershipSettings': membershipSettings,
153
- 'objectTypeId': objectTypeId,
154
- 'processingType': processingType,
155
- 'customProperties': customProperties,
156
- 'listFolderId': listFolderId,
157
- 'name': name,
158
- 'listPermissions': listPermissions,
159
- 'filterBranch': filterBranch,
170
+ "membershipSettings": membershipSettings,
171
+ "objectTypeId": objectTypeId,
172
+ "processingType": processingType,
173
+ "customProperties": customProperties,
174
+ "listFolderId": listFolderId,
175
+ "name": name,
176
+ "listPermissions": listPermissions,
177
+ "filterBranch": filterBranch,
178
+ }
179
+ request_body_data = {
180
+ k: v for k, v in request_body_data.items() if v is not None
160
181
  }
161
- request_body_data = {k: v for k, v in request_body_data.items() if v is not None}
162
182
  url = f"{self.base_url}/crm/v3/lists/"
163
183
  query_params = {}
164
- response = self._post(url, data=request_body_data, params=query_params, content_type='application/json')
184
+ response = self._post(
185
+ url,
186
+ data=request_body_data,
187
+ params=query_params,
188
+ content_type="application/json",
189
+ )
165
190
  return self._handle_response(response)
166
191
 
167
- def get_list_by_id(self, listId: str, includeFilters: Optional[bool] = None) -> dict[str, Any]:
192
+ def get_list_by_id(
193
+ self, listId: str, includeFilters: bool | None = None
194
+ ) -> dict[str, Any]:
168
195
  """
169
196
  Fetch a single list by ILS list ID.
170
197
 
@@ -184,7 +211,9 @@ class HubspotApp(APIApplication):
184
211
  if listId is None:
185
212
  raise ValueError("Missing required parameter 'listId'.")
186
213
  url = f"{self.base_url}/crm/v3/lists/{listId}"
187
- query_params = {k: v for k, v in [('includeFilters', includeFilters)] if v is not None}
214
+ query_params = {
215
+ k: v for k, v in [("includeFilters", includeFilters)] if v is not None
216
+ }
188
217
  response = self._get(url, params=query_params)
189
218
  return self._handle_response(response)
190
219
 
@@ -210,8 +239,8 @@ class HubspotApp(APIApplication):
210
239
  query_params = {}
211
240
  response = self._delete(url, params=query_params)
212
241
  return self._handle_response(response)
213
-
214
- def add_records_to_list(self, listId: str, items: List[str]) -> dict[str, Any]:
242
+
243
+ def add_records_to_list(self, listId: str, items: list[str]) -> dict[str, Any]:
215
244
  """
216
245
  Add the records provided to the list. Records that do not exist or that are already members of the list are ignored.
217
246
  This only works for lists that have a processingType of MANUAL or SNAPSHOT.
@@ -236,10 +265,15 @@ class HubspotApp(APIApplication):
236
265
  request_body_data = items
237
266
  url = f"{self.base_url}/crm/v3/lists/{listId}/memberships/add"
238
267
  query_params = {}
239
- response = self._put(url, data=request_body_data, params=query_params, content_type='application/json')
240
- return self._handle_response(response)
268
+ response = self._put(
269
+ url,
270
+ data=request_body_data,
271
+ params=query_params,
272
+ content_type="application/json",
273
+ )
274
+ return self._handle_response(response)
241
275
 
242
- def remove_records_from_list(self, listId: str, items: List[str]) -> dict[str, Any]:
276
+ def remove_records_from_list(self, listId: str, items: list[str]) -> dict[str, Any]:
243
277
  """
244
278
  Remove the records provided from the list. Records that are not members of the list are ignored.
245
279
  This only works for lists that have a processingType of MANUAL or SNAPSHOT.
@@ -264,10 +298,24 @@ class HubspotApp(APIApplication):
264
298
  request_body_data = items
265
299
  url = f"{self.base_url}/crm/v3/lists/{listId}/memberships/remove"
266
300
  query_params = {}
267
- response = self._put(url, data=request_body_data, params=query_params, content_type='application/json')
301
+ response = self._put(
302
+ url,
303
+ data=request_body_data,
304
+ params=query_params,
305
+ content_type="application/json",
306
+ )
268
307
  return self._handle_response(response)
269
308
 
270
- def search_lists(self, listIds: Optional[List[str]] = None, offset: Optional[int] = None, query: Optional[str] = None, count: Optional[int] = None, processingTypes: Optional[List[str]] = None, additionalProperties: Optional[List[str]] = None, sort: Optional[str] = None) -> dict[str, Any]:
309
+ def search_lists(
310
+ self,
311
+ listIds: list[str] | None = None,
312
+ offset: int | None = None,
313
+ query: str | None = None,
314
+ count: int | None = None,
315
+ processingTypes: list[str] | None = None,
316
+ additionalProperties: list[str] | None = None,
317
+ sort: str | None = None,
318
+ ) -> dict[str, Any]:
271
319
  """
272
320
  Search lists by list name or page through all lists by providing an empty query value.
273
321
 
@@ -299,21 +347,30 @@ class HubspotApp(APIApplication):
299
347
  """
300
348
  request_body_data = None
301
349
  request_body_data = {
302
- 'listIds': listIds,
303
- 'offset': offset,
304
- 'query': query,
305
- 'count': count,
306
- 'processingTypes': processingTypes,
307
- 'additionalProperties': additionalProperties,
308
- 'sort': sort,
350
+ "listIds": listIds,
351
+ "offset": offset,
352
+ "query": query,
353
+ "count": count,
354
+ "processingTypes": processingTypes,
355
+ "additionalProperties": additionalProperties,
356
+ "sort": sort,
357
+ }
358
+ request_body_data = {
359
+ k: v for k, v in request_body_data.items() if v is not None
309
360
  }
310
- request_body_data = {k: v for k, v in request_body_data.items() if v is not None}
311
361
  url = f"{self.base_url}/crm/v3/lists/search"
312
362
  query_params = {}
313
- response = self._post(url, data=request_body_data, params=query_params, content_type='application/json')
363
+ response = self._post(
364
+ url,
365
+ data=request_body_data,
366
+ params=query_params,
367
+ content_type="application/json",
368
+ )
314
369
  return self._handle_response(response)
315
370
 
316
- def fetch_list_by_name(self, objectTypeId: str, listName: str, includeFilters: Optional[bool] = None) -> dict[str, Any]:
371
+ def fetch_list_by_name(
372
+ self, objectTypeId: str, listName: str, includeFilters: bool | None = None
373
+ ) -> dict[str, Any]:
317
374
  """
318
375
  Fetch a list by its name and object type ID.
319
376
 
@@ -336,23 +393,25 @@ class HubspotApp(APIApplication):
336
393
  if listName is None:
337
394
  raise ValueError("Missing required parameter 'listName'.")
338
395
  url = f"{self.base_url}/crm/v3/lists/object-type-id/{objectTypeId}/name/{listName}"
339
- query_params = {k: v for k, v in [('includeFilters', includeFilters)] if v is not None}
396
+ query_params = {
397
+ k: v for k, v in [("includeFilters", includeFilters)] if v is not None
398
+ }
340
399
  response = self._get(url, params=query_params)
341
400
  return self._handle_response(response)
342
401
 
343
-
344
402
  def list_tools(self):
345
403
  all_tools = [
346
- self.add_a_note,
347
- self.fetch_multiple_lists,
348
- self.fetch_list_memberships,
349
- self.create_list,
350
- self.get_list_by_id,
351
- self.delete_list_by_id,
352
- self.add_records_to_list,
353
- self.remove_records_from_list,
354
- self.search_lists,
355
- self.fetch_list_by_name]
404
+ self.add_a_note,
405
+ self.fetch_multiple_lists,
406
+ self.fetch_list_memberships,
407
+ self.create_list,
408
+ self.get_list_by_id,
409
+ self.delete_list_by_id,
410
+ self.add_records_to_list,
411
+ self.remove_records_from_list,
412
+ self.search_lists,
413
+ self.fetch_list_by_name,
414
+ ]
356
415
  all_tools.extend(self.crm.list_tools())
357
416
  all_tools.extend(self.marketing.list_tools())
358
- return all_tools
417
+ return all_tools
@@ -1,7 +1,6 @@
1
1
  from typing import Any
2
2
 
3
3
  import httpx
4
-
5
4
  from universal_mcp.applications.application import APIApplication
6
5
  from universal_mcp.integrations import Integration
7
6
 
@@ -38,7 +38,7 @@ class LinkedinApp(APIApplication):
38
38
  ) -> dict[str, str]:
39
39
  """
40
40
  Publishes a new text post to a specified LinkedIn author's feed (person or organization). It allows configuring visibility, distribution, and lifecycle state. Upon success, it returns the unique URN and URL for the new post, distinguishing this creation operation from the update or delete functions.
41
-
41
+
42
42
  Args:
43
43
  commentary (str): The user generated commentary for the post. Supports mentions using format "@[Entity Name](urn:li:organization:123456)" and hashtags using "#keyword". Text linking to annotated entities must match the name exactly (case sensitive). For member mentions, partial name matching is supported.
44
44
  author (str): The URN of the author creating the post. Use "urn:li:person:{id}" for individual posts or "urn:li:organization:{id}" for company page posts. Example: "urn:li:person:wGgGaX_xbB" or "urn:li:organization:2414183"
@@ -46,17 +46,17 @@ class LinkedinApp(APIApplication):
46
46
  distribution (dict[str, Any], optional): Distribution settings for the post. If not provided, defaults to {"feedDistribution": "MAIN_FEED", "targetEntities": [], "thirdPartyDistributionChannels": []}. feedDistribution controls where the post appears in feeds, targetEntities specifies entities to target, and thirdPartyDistributionChannels defines external distribution channels.
47
47
  lifecycle_state (str): The state of the post. Use "PUBLISHED" for live posts accessible to all entities, "DRAFT" for posts accessible only to author, "PUBLISH_REQUESTED" for posts submitted but processing, or "PUBLISH_FAILED" for posts that failed to publish. Defaults to "PUBLISHED".
48
48
  is_reshare_disabled (bool): Whether resharing is disabled by the author. Set to True to prevent other users from resharing this post, or False to allow resharing. Defaults to False.
49
-
49
+
50
50
  Returns:
51
51
  dict[str, str]: Dictionary containing the post ID with key "post_id". Example: {"post_id": "urn:li:share:6844785523593134080"}
52
-
52
+
53
53
  Raises:
54
54
  ValueError: If required parameters (commentary, author) are missing or if x-restli-id header is not found
55
55
  HTTPStatusError: Raised when the API request fails with detailed error information including status code and response body
56
-
56
+
57
57
  Notes:
58
58
  Requires LinkedIn API permissions: w_member_social (for individual posts) or w_organization_social (for company posts). All requests require headers: X-Restli-Protocol-Version: 2.0.0 and LinkedIn-Version: 202507. Rate limits: 150 requests per day per member, 100,000 requests per day per application. The Posts API replaces the deprecated ugcPosts API.
59
-
59
+
60
60
  Tags:
61
61
  posts, important
62
62
  """
@@ -100,14 +100,14 @@ class LinkedinApp(APIApplication):
100
100
  def get_authenticated_user_profile(self) -> dict[str, Any]:
101
101
  """
102
102
  Retrieves the authenticated user's profile from the LinkedIn `/v2/userinfo` endpoint. Using credentials from the active integration, it returns a dictionary with basic user details like name and email. This function is for fetching user data, distinct from others that create, update, or delete posts.
103
-
103
+
104
104
  Returns:
105
105
  dict[str, Any]: Dictionary containing your LinkedIn profile information.
106
-
106
+
107
107
  Raises:
108
108
  ValueError: If integration is not found
109
109
  HTTPStatusError: Raised when the API request fails with detailed error information including status code and response body
110
-
110
+
111
111
  Tags:
112
112
  profile, info
113
113
  """
@@ -124,18 +124,18 @@ class LinkedinApp(APIApplication):
124
124
  def delete_post(self, post_urn: str) -> dict[str, str]:
125
125
  """
126
126
  Deletes a LinkedIn post identified by its unique Uniform Resource Name (URN). This function sends a DELETE request to the API, permanently removing the content. Upon a successful HTTP 204 response, it returns a dictionary confirming the post's deletion status.
127
-
127
+
128
128
  Args:
129
129
  post_urn (str): The URN of the post to delete. Can be either a ugcPostUrn (urn:li:ugcPost:{id}) or shareUrn (urn:li:share:{id}).
130
-
130
+
131
131
  Returns:
132
132
  dict[str, str]: Dictionary containing the deletion status. Example: {"status": "deleted", "post_urn": "urn:li:share:6844785523593134080"}
133
-
133
+
134
134
  Raises:
135
135
  ValueError: If required parameter (post_urn) is missing or if integration is not found
136
136
  HTTPStatusError: Raised when the API request fails with detailed error information including status code and response body
137
-
138
-
137
+
138
+
139
139
  Tags:
140
140
  posts, important
141
141
  """
@@ -164,7 +164,7 @@ class LinkedinApp(APIApplication):
164
164
  ) -> dict[str, str]:
165
165
  """
166
166
  Modifies an existing LinkedIn post, identified by its URN, by performing a partial update. It selectively changes attributes like commentary or ad context, distinguishing it from `create_post` which creates new content. Returns a confirmation dictionary upon successful completion.
167
-
167
+
168
168
  Args:
169
169
  post_urn (str): The URN of the post to update. Can be either a ugcPostUrn (urn:li:ugcPost:{id}) or shareUrn (urn:li:share:{id}).
170
170
  commentary (str | None, optional): The user generated commentary of this post in little format.
@@ -173,17 +173,17 @@ class LinkedinApp(APIApplication):
173
173
  lifecycle_state (str | None, optional): The state of the content. Can be DRAFT, PUBLISHED, PUBLISH_REQUESTED, or PUBLISH_FAILED.
174
174
  ad_context_name (str | None, optional): Update the name of the sponsored content.
175
175
  ad_context_status (str | None, optional): Update the status of the sponsored content.
176
-
176
+
177
177
  Returns:
178
178
  dict[str, str]: Dictionary containing the update status. Example: {"status": "updated", "post_urn": "urn:li:share:6844785523593134080"}
179
-
179
+
180
180
  Raises:
181
181
  ValueError: If required parameter (post_urn) is missing or if integration is not found
182
182
  HTTPStatusError: Raised when the API request fails with detailed error information including status code and response body
183
-
184
-
185
-
186
-
183
+
184
+
185
+
186
+
187
187
  Tags:
188
188
  posts, update, important
189
189
  """
@@ -1,8 +1,9 @@
1
1
  import re
2
2
 
3
- from markitdown import MarkItDown
4
3
  from universal_mcp.applications.application import BaseApplication
5
4
 
5
+ from markitdown import MarkItDown
6
+
6
7
 
7
8
  class MarkitdownApp(BaseApplication):
8
9
  def __init__(self, **kwargs):
@@ -61,11 +62,15 @@ class MarkitdownApp(BaseApplication):
61
62
  self.convert_to_markdown,
62
63
  ]
63
64
 
65
+
64
66
  async def main():
65
67
  app = MarkitdownApp()
66
- result = await app.convert_to_markdown("https://www.youtube.com/watch?v=Cr9B6yyLZSk")
67
- print(result)
68
-
68
+ await app.convert_to_markdown(
69
+ "https://www.youtube.com/watch?v=Cr9B6yyLZSk"
70
+ )
71
+
72
+
69
73
  if __name__ == "__main__":
70
74
  import asyncio
71
- asyncio.run(main())
75
+
76
+ asyncio.run(main())