universal-mcp 0.1.1__py3-none-any.whl → 0.1.2__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.
Files changed (37) hide show
  1. universal_mcp/applications/__init__.py +23 -28
  2. universal_mcp/applications/application.py +13 -8
  3. universal_mcp/applications/e2b/app.py +74 -0
  4. universal_mcp/applications/firecrawl/app.py +381 -0
  5. universal_mcp/applications/github/README.md +35 -0
  6. universal_mcp/applications/github/app.py +133 -100
  7. universal_mcp/applications/google_calendar/app.py +170 -139
  8. universal_mcp/applications/google_mail/app.py +185 -160
  9. universal_mcp/applications/markitdown/app.py +32 -0
  10. universal_mcp/applications/notion/README.md +32 -0
  11. universal_mcp/applications/notion/__init__.py +0 -0
  12. universal_mcp/applications/notion/app.py +415 -0
  13. universal_mcp/applications/reddit/app.py +112 -71
  14. universal_mcp/applications/resend/app.py +3 -8
  15. universal_mcp/applications/serp/app.py +84 -0
  16. universal_mcp/applications/tavily/app.py +11 -10
  17. universal_mcp/applications/zenquotes/app.py +3 -3
  18. universal_mcp/cli.py +98 -16
  19. universal_mcp/config.py +20 -3
  20. universal_mcp/exceptions.py +1 -3
  21. universal_mcp/integrations/__init__.py +6 -2
  22. universal_mcp/integrations/agentr.py +26 -24
  23. universal_mcp/integrations/integration.py +72 -35
  24. universal_mcp/servers/__init__.py +21 -1
  25. universal_mcp/servers/server.py +77 -44
  26. universal_mcp/stores/__init__.py +15 -2
  27. universal_mcp/stores/store.py +123 -13
  28. universal_mcp/utils/__init__.py +1 -0
  29. universal_mcp/utils/api_generator.py +269 -0
  30. universal_mcp/utils/docgen.py +360 -0
  31. universal_mcp/utils/installation.py +17 -2
  32. universal_mcp/utils/openapi.py +216 -111
  33. {universal_mcp-0.1.1.dist-info → universal_mcp-0.1.2.dist-info}/METADATA +23 -5
  34. universal_mcp-0.1.2.dist-info/RECORD +40 -0
  35. universal_mcp-0.1.1.dist-info/RECORD +0 -29
  36. {universal_mcp-0.1.1.dist-info → universal_mcp-0.1.2.dist-info}/WHEEL +0 -0
  37. {universal_mcp-0.1.1.dist-info → universal_mcp-0.1.2.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,32 @@
1
+ from markitdown import MarkItDown
2
+
3
+ from universal_mcp.applications.application import Application
4
+
5
+
6
+ class MarkitdownApp(Application):
7
+ def __init__(self, **kwargs):
8
+ super().__init__(name="markitdown", **kwargs)
9
+ self.markitdown = MarkItDown()
10
+
11
+ async def convert_to_markdown(self, uri: str) -> str:
12
+ """Convert a web page, file, or data URI to markdown format.
13
+
14
+ Args:
15
+ uri (str): The URI to convert. Supported URI schemes:
16
+ - http:// or https:// for web pages
17
+ - file:// for local files
18
+ - data: for data URIs
19
+
20
+ Returns:
21
+ str: The markdown representation of the resource content.
22
+
23
+ Example:
24
+ >>> await convert_to_markdown("https://example.com")
25
+ "# Example Domain\n\nThis domain is for use in illustrative examples..."
26
+ """
27
+ return self.markitdown.convert_uri(uri).markdown
28
+
29
+ def list_tools(self):
30
+ return [
31
+ self.convert_to_markdown,
32
+ ]
@@ -0,0 +1,32 @@
1
+ # Notion Tool
2
+
3
+ This is automatically generated from OpenAPI schema for the Notion API.
4
+
5
+ ## Supported Integrations
6
+
7
+ This tool can be integrated with any service that supports HTTP requests.
8
+
9
+ ## Tool List
10
+
11
+ | Tool | Description |
12
+ |------|-------------|
13
+ | notion_retrieve_auser | Retrieves user information from the Notion API by user ID. |
14
+ | notion_list_all_users | Fetches and returns a list of all users from the Notion API. |
15
+ | notion_retrieve_your_token_sbot_user | Retrieves the current user's token data from the Notion API. |
16
+ | notion_retrieve_adatabase | Retrieves a Notion database by its unique identifier. |
17
+ | notion_update_adatabase | Updates a Notion database with the given ID and request body data. |
18
+ | notion_query_adatabase | Executes a query on a Notion database using the Notion API. |
19
+ | notion_create_adatabase | Creates a new database in Notion using the provided request body. |
20
+ | notion_create_apage | Creates a new page in Notion by sending a POST request with the specified request body. |
21
+ | notion_retrieve_apage | Retrieves a page from the Notion API using a given page ID. |
22
+ | notion_update_page_properties | Updates the properties of a Notion page identified by a given ID. |
23
+ | notion_retrieve_apage_property_item | Retrieves a specific property item from a page in Notion using the page and property IDs. |
24
+ | notion_retrieve_block_children | Retrieves the child blocks of a specified Notion block. |
25
+ | notion_append_block_children | Appends child blocks to a block in Notion using its API. |
26
+ | notion_retrieve_ablock | Retrieves a block from the Notion API using the specified block ID. |
27
+ | notion_delete_ablock | Deletes a block from the Notion database using the specified block ID. |
28
+ | notion_update_ablock | Updates a block in Notion with the given ID and request body. |
29
+ | notion_search | Executes a search request to the Notion API and returns the response in JSON format. |
30
+ | notion_retrieve_comments | Retrieves comments from a Notion block using the Notion API. |
31
+ | notion_add_comment_to_page | Adds a comment to a specified Notion page using the provided request body. |
32
+
File without changes
@@ -0,0 +1,415 @@
1
+ from typing import Any
2
+
3
+ from universal_mcp.applications import APIApplication
4
+ from universal_mcp.integrations import Integration
5
+
6
+
7
+ class NotionApp(APIApplication):
8
+ def __init__(self, integration: Integration = None, **kwargs) -> None:
9
+ """
10
+ Initializes a new instance of the class with given integration and additional options.
11
+
12
+ Args:
13
+ integration: An optional Integration instance to configure the connection. Defaults to None.
14
+ **kwargs: Additional keyword arguments for configuration.
15
+
16
+ Returns:
17
+ None
18
+ """
19
+ super().__init__(name='notion', integration=integration, **kwargs)
20
+ self.base_url = "https://api.notion.com"
21
+
22
+ def _get_headers(self):
23
+ if not self.integration:
24
+ raise ValueError("Integration not configured for NotionApp")
25
+ credentials = self.integration.get_credentials()
26
+ if "headers" in credentials:
27
+ return credentials["headers"]
28
+ return {
29
+ "Authorization": f"Bearer {credentials['access_token']}",
30
+ "Accept": "application/json",
31
+ "Notion-Version": "2022-06-28",
32
+ }
33
+
34
+ def notion_retrieve_auser(self, id, request_body=None) -> dict[str, Any]:
35
+ """
36
+ Retrieves user information from the Notion API by user ID.
37
+
38
+ Args:
39
+ id: The unique identifier of the user whose information is to be retrieved.
40
+ request_body: A dictionary representing the request body, optional, default is None.
41
+
42
+ Returns:
43
+ A dictionary containing the user's information from the Notion API.
44
+ """
45
+ if id is None:
46
+ raise ValueError("Missing required parameter 'id'")
47
+ url = f"{self.base_url}/v1/users/{id}"
48
+ query_params = {}
49
+ response = self._get(url, params=query_params)
50
+ response.raise_for_status()
51
+ return response.json()
52
+
53
+ def notion_list_all_users(self, ) -> dict[str, Any]:
54
+ """
55
+ Fetches and returns a list of all users from the Notion API.
56
+
57
+ Args:
58
+ None: This method does not take any parameters.
59
+
60
+ Returns:
61
+ A dictionary containing the JSON response from the Notion API, representing all users data.
62
+ """
63
+ url = f"{self.base_url}/v1/users"
64
+ query_params = {}
65
+ response = self._get(url, params=query_params)
66
+ response.raise_for_status()
67
+ return response.json()
68
+
69
+ def notion_retrieve_your_token_sbot_user(self, ) -> dict[str, Any]:
70
+ """
71
+ Retrieves the current user's token data from the Notion API.
72
+
73
+ Args:
74
+ self: Instance of the class containing the necessary configuration and authentication details for accessing the Notion API.
75
+
76
+ Returns:
77
+ A dictionary containing the current user's token information as retrieved from the Notion API.
78
+ """
79
+ url = f"{self.base_url}/v1/users/me"
80
+ query_params = {}
81
+ response = self._get(url, params=query_params)
82
+ response.raise_for_status()
83
+ return response.json()
84
+
85
+ def notion_retrieve_adatabase(self, id) -> dict[str, Any]:
86
+ """
87
+ Retrieves a Notion database by its unique identifier.
88
+
89
+ Args:
90
+ id: A string representing the unique identifier of the Notion database to be retrieved.
91
+
92
+ Returns:
93
+ A dictionary containing the details of the retrieved Notion database.
94
+ """
95
+ if id is None:
96
+ raise ValueError("Missing required parameter 'id'")
97
+ url = f"{self.base_url}/v1/databases/{id}"
98
+ query_params = {}
99
+ response = self._get(url, params=query_params)
100
+ response.raise_for_status()
101
+ return response.json()
102
+
103
+ def notion_update_adatabase(self, id, request_body=None) -> dict[str, Any]:
104
+ """
105
+ Updates a Notion database with the given ID and request body data.
106
+
107
+ Args:
108
+ self: An instance of the class containing configuration and methods for HTTP requests.
109
+ id: A string representing the unique identifier of the Notion database to be updated.
110
+ request_body: An optional dictionary containing the fields and values to update in the database.
111
+
112
+ Returns:
113
+ A dictionary representing the JSON response from the Notion API after updating the database.
114
+ """
115
+ if id is None:
116
+ raise ValueError("Missing required parameter 'id'")
117
+ url = f"{self.base_url}/v1/databases/{id}"
118
+ query_params = {}
119
+ response = self._patch(url, data={}, params=query_params)
120
+ response.raise_for_status()
121
+ return response.json()
122
+
123
+ def notion_query_adatabase(self, id, request_body=None) -> dict[str, Any]:
124
+ """
125
+ Executes a query on a Notion database using the Notion API.
126
+
127
+ Args:
128
+ self: Instance of the class which should contain 'base_url' and '_post' method.
129
+ id: A string representing the unique identifier of the Notion database to query.
130
+ request_body: Optional. A dictionary representing the request body for the query. Defaults to None.
131
+
132
+ Returns:
133
+ A dictionary containing the JSON response from the Notion API after querying the specified database.
134
+ """
135
+ if id is None:
136
+ raise ValueError("Missing required parameter 'id'")
137
+ url = f"{self.base_url}/v1/databases/{id}/query"
138
+ query_params = {}
139
+ json_body = request_body if request_body is not None else None
140
+ response = self._post(url, data=json_body, params=query_params)
141
+ response.raise_for_status()
142
+ return response.json()
143
+
144
+ def notion_create_adatabase(self, request_body=None) -> dict[str, Any]:
145
+ """
146
+ Creates a new database in Notion using the provided request body.
147
+
148
+ Args:
149
+ self: Reference to the current instance of the class.
150
+ request_body: Optional dictionary containing the specifications for creating the Notion database. If None, a default empty request body is used.
151
+
152
+ Returns:
153
+ A dictionary representing the JSON response from the Notion API, containing data about the newly created database.
154
+ """
155
+ url = f"{self.base_url}/v1/databases/"
156
+ query_params = {}
157
+ json_body = request_body if request_body is not None else None
158
+ response = self._post(url, data=json_body, params=query_params)
159
+ response.raise_for_status()
160
+ return response.json()
161
+
162
+ def notion_create_apage(self, request_body=None) -> dict[str, Any]:
163
+ """
164
+ Creates a new page in Notion by sending a POST request with the specified request body.
165
+
166
+ Args:
167
+ request_body: Optional; A dictionary containing the data to create a new page in Notion. Defaults to None.
168
+
169
+ Returns:
170
+ A dictionary containing the JSON response from the Notion API with the details of the newly created page.
171
+ """
172
+ url = f"{self.base_url}/v1/pages/"
173
+ query_params = {}
174
+ json_body = request_body if request_body is not None else None
175
+ response = self._post(url, data=json_body, params=query_params)
176
+ response.raise_for_status()
177
+ return response.json()
178
+
179
+ def notion_retrieve_apage(self, id) -> dict[str, Any]:
180
+ """
181
+ Retrieves a page from the Notion API using a given page ID.
182
+
183
+ Args:
184
+ id: The unique identifier of the Notion page to be retrieved.
185
+
186
+ Returns:
187
+ A dictionary containing the JSON response from the Notion API, representing the page data.
188
+ """
189
+ if id is None:
190
+ raise ValueError("Missing required parameter 'id'")
191
+ url = f"{self.base_url}/v1/pages/{id}"
192
+ query_params = {}
193
+ response = self._get(url, params=query_params)
194
+ response.raise_for_status()
195
+ return response.json()
196
+
197
+ def notion_update_page_properties(self, id, request_body=None) -> dict[str, Any]:
198
+ """
199
+ Updates the properties of a Notion page identified by a given ID.
200
+
201
+ Args:
202
+ self: Instance of the class containing the Notion API credentials and methods.
203
+ id: The unique identifier of the Notion page to update. Must not be None.
204
+ request_body: An optional dictionary representing the request body to be sent with the update request. Defaults to None, indicating no additional properties to update.
205
+
206
+ Returns:
207
+ A dictionary containing the JSON response from the Notion API after the page update request.
208
+ """
209
+ if id is None:
210
+ raise ValueError("Missing required parameter 'id'")
211
+ url = f"{self.base_url}/v1/pages/{id}"
212
+ query_params = {}
213
+ response = self._patch(url, data={}, params=query_params)
214
+ response.raise_for_status()
215
+ return response.json()
216
+
217
+ def notion_retrieve_apage_property_item(self, page_id, property_id) -> dict[str, Any]:
218
+ """
219
+ Retrieves a specific property item from a page in Notion using the page and property IDs.
220
+
221
+ Args:
222
+ page_id: The unique identifier for the Notion page from which the property item should be retrieved.
223
+ property_id: The unique identifier for the property item within the specified page that should be retrieved.
224
+
225
+ Returns:
226
+ A dictionary containing the JSON response from the Notion API representing the requested property item.
227
+ """
228
+ if page_id is None:
229
+ raise ValueError("Missing required parameter 'page_id'")
230
+ if property_id is None:
231
+ raise ValueError("Missing required parameter 'property_id'")
232
+ url = f"{self.base_url}/v1/pages/{page_id}/properties/{property_id}"
233
+ query_params = {}
234
+ response = self._get(url, params=query_params)
235
+ response.raise_for_status()
236
+ return response.json()
237
+
238
+ def notion_retrieve_block_children(self, id, page_size=None) -> dict[str, Any]:
239
+ """
240
+ Retrieves the child blocks of a specified Notion block.
241
+
242
+ Args:
243
+ self: The instance of the class this method belongs to.
244
+ id: The unique identifier of the parent block whose children are to be retrieved.
245
+ page_size: Optional; the number of child blocks to retrieve per request.
246
+
247
+ Returns:
248
+ A dictionary containing the JSON response with details about the child blocks.
249
+ """
250
+ if id is None:
251
+ raise ValueError("Missing required parameter 'id'")
252
+ url = f"{self.base_url}/v1/blocks/{id}/children"
253
+ query_params = {k: v for k, v in [('page_size', page_size)] if v is not None}
254
+ response = self._get(url, params=query_params)
255
+ response.raise_for_status()
256
+ return response.json()
257
+
258
+ def notion_append_block_children(self, id, request_body=None) -> dict[str, Any]:
259
+ """
260
+ Appends child blocks to a block in Notion using its API.
261
+
262
+ Args:
263
+ self: Instance of the class containing Notion API credentials and configuration.
264
+ id: The unique identifier of the parent block to which child blocks are to be appended.
265
+ request_body: An optional dictionary containing the block data to append. Defaults to None.
266
+
267
+ Returns:
268
+ A dictionary representing the response from the Notion API, containing the result of the append operation.
269
+ """
270
+ if id is None:
271
+ raise ValueError("Missing required parameter 'id'")
272
+ url = f"{self.base_url}/v1/blocks/{id}/children"
273
+ query_params = {}
274
+ response = self._patch(url, data={}, params=query_params)
275
+ response.raise_for_status()
276
+ return response.json()
277
+
278
+ def notion_retrieve_ablock(self, id) -> dict[str, Any]:
279
+ """
280
+ Retrieves a block from the Notion API using the specified block ID.
281
+
282
+ Args:
283
+ id: The unique identifier of the block to retrieve from the Notion API. Must be a non-null string.
284
+
285
+ Returns:
286
+ A dictionary containing the block data in JSON format as retrieved from the Notion API.
287
+ """
288
+ if id is None:
289
+ raise ValueError("Missing required parameter 'id'")
290
+ url = f"{self.base_url}/v1/blocks/{id}"
291
+ query_params = {}
292
+ response = self._get(url, params=query_params)
293
+ response.raise_for_status()
294
+ return response.json()
295
+
296
+ def notion_delete_ablock(self, id) -> dict[str, Any]:
297
+ """
298
+ Deletes a block from the Notion database using the specified block ID.
299
+
300
+ Args:
301
+ id: The unique identifier of the block to be deleted. Must not be None.
302
+
303
+ Returns:
304
+ A dictionary containing the JSON response from the Notion API after attempting to delete the block.
305
+ """
306
+ if id is None:
307
+ raise ValueError("Missing required parameter 'id'")
308
+ url = f"{self.base_url}/v1/blocks/{id}"
309
+ query_params = {}
310
+ response = self._delete(url, params=query_params)
311
+ response.raise_for_status()
312
+ return response.json()
313
+
314
+ def notion_update_ablock(self, id, request_body=None) -> dict[str, Any]:
315
+ """
316
+ Updates a block in Notion with the given ID and request body.
317
+
318
+ Args:
319
+ id: The unique identifier of the Notion block to update.
320
+ request_body: The request body containing the updates to be made to the block. Defaults to None if not provided.
321
+
322
+ Returns:
323
+ A dictionary containing the JSON response from the Notion API after the block has been updated.
324
+ """
325
+ if id is None:
326
+ raise ValueError("Missing required parameter 'id'")
327
+ url = f"{self.base_url}/v1/blocks/{id}"
328
+ query_params = {}
329
+ response = self._patch(url, data={}, params=query_params)
330
+ response.raise_for_status()
331
+ return response.json()
332
+
333
+ def notion_search(self, request_body=None) -> dict[str, Any]:
334
+ """
335
+ Executes a search request to the Notion API and returns the response in JSON format.
336
+
337
+ Args:
338
+ request_body: An optional dictionary containing the search parameters for the API request. Defaults to None if not provided.
339
+
340
+ Returns:
341
+ A dictionary containing the response from the Notion API in JSON format.
342
+ """
343
+ url = f"{self.base_url}/v1/search"
344
+ query_params = {}
345
+ json_body = request_body if request_body is not None else None
346
+ response = self._post(url, data=json_body, params=query_params)
347
+ response.raise_for_status()
348
+ return response.json()
349
+
350
+ def notion_retrieve_comments(self, block_id=None, page_size=None, request_body=None) -> dict[str, Any]:
351
+ """
352
+ Retrieves comments from a Notion block using the Notion API.
353
+
354
+ Args:
355
+ block_id: Optional; The ID of the block for which to retrieve comments. If None, it retrieves comments for all blocks available to the user.
356
+ page_size: Optional; The maximum number of comments to retrieve in one request. If None, the default page size will be used.
357
+ request_body: Optional; A dictionary to include additional parameters in the request body. If None, no extra parameters are added.
358
+
359
+ Returns:
360
+ A dictionary containing the JSON response from the Notion API with the comments retrieved.
361
+ """
362
+ url = f"{self.base_url}/v1/comments"
363
+ query_params = {k: v for k, v in [('block_id', block_id), ('page_size', page_size)] if v is not None}
364
+ response = self._get(url, params=query_params)
365
+ response.raise_for_status()
366
+ return response.json()
367
+
368
+ def notion_add_comment_to_page(self, request_body=None) -> dict[str, Any]:
369
+ """
370
+ Adds a comment to a specified Notion page using the provided request body.
371
+
372
+ Args:
373
+ request_body: An optional dictionary containing the details of the comment to be added to the Notion page. If None, no data is sent in the request's body.
374
+
375
+ Returns:
376
+ A dictionary containing the response data from the Notion API, parsed from JSON format.
377
+ """
378
+ url = f"{self.base_url}/v1/comments"
379
+ query_params = {}
380
+ json_body = request_body if request_body is not None else None
381
+ response = self._post(url, data=json_body, params=query_params)
382
+ response.raise_for_status()
383
+ return response.json()
384
+
385
+ def list_tools(self):
386
+ """
387
+ Returns a list of functions that interact with Notion's API for various operations.
388
+
389
+ Args:
390
+ None: This method does not take any parameters.
391
+
392
+ Returns:
393
+ A list of functions that perform specific operations with Notion's API, such as retrieving or updating users, databases, pages, blocks, and comments.
394
+ """
395
+ return [
396
+ self.notion_retrieve_auser,
397
+ self.notion_list_all_users,
398
+ self.notion_retrieve_your_token_sbot_user,
399
+ self.notion_retrieve_adatabase,
400
+ self.notion_update_adatabase,
401
+ self.notion_query_adatabase,
402
+ self.notion_create_adatabase,
403
+ self.notion_create_apage,
404
+ self.notion_retrieve_apage,
405
+ self.notion_update_page_properties,
406
+ self.notion_retrieve_apage_property_item,
407
+ self.notion_retrieve_block_children,
408
+ self.notion_append_block_children,
409
+ self.notion_retrieve_ablock,
410
+ self.notion_delete_ablock,
411
+ self.notion_update_ablock,
412
+ self.notion_search,
413
+ self.notion_retrieve_comments,
414
+ self.notion_add_comment_to_page
415
+ ]