universal-mcp 0.1.7rc2__py3-none-any.whl → 0.1.8__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 (61) hide show
  1. universal_mcp/__init__.py +0 -2
  2. universal_mcp/analytics.py +75 -0
  3. universal_mcp/applications/ahrefs/README.md +76 -0
  4. universal_mcp/applications/ahrefs/app.py +2291 -0
  5. universal_mcp/applications/application.py +95 -5
  6. universal_mcp/applications/calendly/README.md +78 -0
  7. universal_mcp/applications/calendly/__init__.py +0 -0
  8. universal_mcp/applications/calendly/app.py +1195 -0
  9. universal_mcp/applications/coda/README.md +133 -0
  10. universal_mcp/applications/coda/__init__.py +0 -0
  11. universal_mcp/applications/coda/app.py +3671 -0
  12. universal_mcp/applications/e2b/app.py +14 -35
  13. universal_mcp/applications/figma/README.md +74 -0
  14. universal_mcp/applications/figma/__init__.py +0 -0
  15. universal_mcp/applications/figma/app.py +1261 -0
  16. universal_mcp/applications/firecrawl/app.py +29 -32
  17. universal_mcp/applications/github/app.py +127 -85
  18. universal_mcp/applications/google_calendar/app.py +62 -138
  19. universal_mcp/applications/google_docs/app.py +47 -52
  20. universal_mcp/applications/google_drive/app.py +119 -113
  21. universal_mcp/applications/google_mail/app.py +124 -50
  22. universal_mcp/applications/google_sheet/app.py +89 -91
  23. universal_mcp/applications/markitdown/app.py +9 -8
  24. universal_mcp/applications/notion/app.py +254 -134
  25. universal_mcp/applications/perplexity/app.py +13 -45
  26. universal_mcp/applications/reddit/app.py +94 -85
  27. universal_mcp/applications/resend/app.py +12 -23
  28. universal_mcp/applications/{serp → serpapi}/app.py +14 -33
  29. universal_mcp/applications/tavily/app.py +11 -28
  30. universal_mcp/applications/wrike/README.md +71 -0
  31. universal_mcp/applications/wrike/__init__.py +0 -0
  32. universal_mcp/applications/wrike/app.py +1372 -0
  33. universal_mcp/applications/youtube/README.md +82 -0
  34. universal_mcp/applications/youtube/__init__.py +0 -0
  35. universal_mcp/applications/youtube/app.py +1428 -0
  36. universal_mcp/applications/zenquotes/app.py +12 -2
  37. universal_mcp/exceptions.py +9 -2
  38. universal_mcp/integrations/__init__.py +24 -1
  39. universal_mcp/integrations/agentr.py +27 -4
  40. universal_mcp/integrations/integration.py +143 -30
  41. universal_mcp/logger.py +3 -56
  42. universal_mcp/servers/__init__.py +6 -14
  43. universal_mcp/servers/server.py +201 -146
  44. universal_mcp/stores/__init__.py +7 -2
  45. universal_mcp/stores/store.py +103 -40
  46. universal_mcp/tools/__init__.py +3 -0
  47. universal_mcp/tools/adapters.py +43 -0
  48. universal_mcp/tools/func_metadata.py +213 -0
  49. universal_mcp/tools/tools.py +342 -0
  50. universal_mcp/utils/docgen.py +325 -119
  51. universal_mcp/utils/docstring_parser.py +179 -0
  52. universal_mcp/utils/dump_app_tools.py +33 -23
  53. universal_mcp/utils/installation.py +199 -8
  54. universal_mcp/utils/openapi.py +229 -46
  55. {universal_mcp-0.1.7rc2.dist-info → universal_mcp-0.1.8.dist-info}/METADATA +9 -5
  56. universal_mcp-0.1.8.dist-info/RECORD +81 -0
  57. universal_mcp-0.1.7rc2.dist-info/RECORD +0 -58
  58. /universal_mcp/{utils/bridge.py → applications/ahrefs/__init__.py} +0 -0
  59. /universal_mcp/applications/{serp → serpapi}/README.md +0 -0
  60. {universal_mcp-0.1.7rc2.dist-info → universal_mcp-0.1.8.dist-info}/WHEEL +0 -0
  61. {universal_mcp-0.1.7rc2.dist-info → universal_mcp-0.1.8.dist-info}/entry_points.txt +0 -0
@@ -70,6 +70,33 @@ def determine_return_type(operation: dict[str, Any]) -> str:
70
70
  return "Any"
71
71
 
72
72
 
73
+ def resolve_schema_reference(reference, schema):
74
+ """
75
+ Resolve a JSON schema reference to its target schema.
76
+
77
+ Args:
78
+ reference (str): The reference string (e.g., '#/components/schemas/User')
79
+ schema (dict): The complete OpenAPI schema that contains the reference
80
+
81
+ Returns:
82
+ dict: The resolved schema, or None if not found
83
+ """
84
+ if not reference.startswith("#/"):
85
+ return None
86
+
87
+ # Split the reference path and navigate through the schema
88
+ parts = reference[2:].split("/")
89
+ current = schema
90
+
91
+ for part in parts:
92
+ if part in current:
93
+ current = current[part]
94
+ else:
95
+ return None
96
+
97
+ return current
98
+
99
+
73
100
  def generate_api_client(schema):
74
101
  """
75
102
  Generate a Python API client class from an OpenAPI schema.
@@ -130,7 +157,7 @@ def generate_api_client(schema):
130
157
  if method in ["get", "post", "put", "delete", "patch", "options", "head"]:
131
158
  operation = path_info[method]
132
159
  method_code, func_name = generate_method_code(
133
- path, method, operation, tool_name
160
+ path, method, operation, schema, tool_name
134
161
  )
135
162
  methods.append(method_code)
136
163
  method_names.append(func_name)
@@ -164,7 +191,7 @@ def generate_api_client(schema):
164
191
  return class_code
165
192
 
166
193
 
167
- def generate_method_code(path, method, operation, tool_name=None):
194
+ def generate_method_code(path, method, operation, full_schema, tool_name=None):
168
195
  """
169
196
  Generate the code for a single API method.
170
197
 
@@ -172,14 +199,15 @@ def generate_method_code(path, method, operation, tool_name=None):
172
199
  path (str): The API path (e.g., '/users/{user_id}').
173
200
  method (str): The HTTP method (e.g., 'get').
174
201
  operation (dict): The operation details from the schema.
202
+ full_schema (dict): The complete OpenAPI schema, used for reference resolution.
175
203
  tool_name (str, optional): The name of the tool/app to prefix the function name with.
176
204
 
177
205
  Returns:
178
206
  tuple: (method_code, func_name) - The Python code for the method and its name.
179
207
  """
180
208
  # Extract path parameters from the URL path
181
- path_params_in_url = re.findall(r'{([^}]+)}', path)
182
-
209
+ path_params_in_url = re.findall(r"{([^}]+)}", path)
210
+
183
211
  # Determine function name
184
212
  if "operationId" in operation:
185
213
  raw_name = operation["operationId"]
@@ -195,42 +223,179 @@ def generate_method_code(path, method, operation, tool_name=None):
195
223
  else:
196
224
  name_parts.append(part)
197
225
  func_name = "_".join(name_parts).replace("-", "_").lower()
198
-
199
-
200
-
201
- func_name = re.sub(r'_a([^_])', r'_a_\1', func_name) # Fix for patterns like retrieve_ablock
202
- func_name = re.sub(r'_an([^_])', r'_an_\1', func_name) # Fix for patterns like create_anitem
226
+
227
+ # Only fix isolated 'a' and 'an' as articles, not when they're part of words
228
+ func_name = re.sub(
229
+ r"_a([^_a-z])", r"_a_\1", func_name
230
+ ) # Fix for patterns like retrieve_ablock -> retrieve_a_block
231
+ func_name = re.sub(
232
+ r"_a$", r"_a", func_name
233
+ ) # Don't change if 'a' is at the end of the name
234
+ func_name = re.sub(
235
+ r"_an([^_a-z])", r"_an_\1", func_name
236
+ ) # Fix for patterns like create_anitem -> create_an_item
237
+ func_name = re.sub(
238
+ r"_an$", r"_an", func_name
239
+ ) # Don't change if 'an' is at the end of the name
203
240
 
204
241
  # Get parameters and request body
205
- # Filter out header parameters
206
- parameters = [param for param in operation.get("parameters", []) if param.get("in") != "header"]
242
+ # Resolve parameter references before processing
243
+ resolved_parameters = []
244
+ for param in operation.get("parameters", []):
245
+ if "$ref" in param:
246
+ # Resolve reference to actual parameter object
247
+ ref_param = resolve_schema_reference(param["$ref"], full_schema)
248
+ if ref_param:
249
+ resolved_parameters.append(ref_param)
250
+ else:
251
+ print(
252
+ f"Warning: Could not resolve parameter reference: {param['$ref']}"
253
+ )
254
+ else:
255
+ resolved_parameters.append(param)
256
+
257
+ # Filter out header parameters from the resolved parameters
258
+ parameters = [param for param in resolved_parameters if param.get("in") != "header"]
259
+
207
260
  has_body = "requestBody" in operation
208
261
  body_required = has_body and operation["requestBody"].get("required", False)
209
262
 
263
+ # Check if the requestBody has actual content or is empty
264
+ has_empty_body = False
265
+ if has_body:
266
+ request_body_content = operation["requestBody"].get("content", {})
267
+ if not request_body_content or all(
268
+ not content for content_type, content in request_body_content.items()
269
+ ):
270
+ has_empty_body = True
271
+ else:
272
+ # Handle empty properties with additionalProperties:true
273
+ for content_type, content in request_body_content.items():
274
+ if content_type.startswith("application/json") and "schema" in content:
275
+ schema = content["schema"]
276
+
277
+ # Resolve schema reference if present
278
+ if "$ref" in schema:
279
+ ref_schema = resolve_schema_reference(
280
+ schema["$ref"], full_schema
281
+ )
282
+ if ref_schema:
283
+ schema = ref_schema
284
+
285
+ # Check if properties is empty and additionalProperties is true
286
+ if (
287
+ schema.get("type") == "object"
288
+ and schema.get("additionalProperties", False) is True
289
+ ):
290
+ properties = schema.get("properties", {})
291
+ if not properties or len(properties) == 0:
292
+ has_empty_body = True
293
+
294
+ # Extract request body schema properties and required fields
295
+ required_fields = []
296
+ request_body_properties = {}
297
+ is_array_body = False
298
+ array_items_schema = None
299
+
300
+ if has_body:
301
+ for content_type, content in (
302
+ operation["requestBody"].get("content", {}).items()
303
+ ):
304
+ if content_type.startswith("application/json") and "schema" in content:
305
+ schema = content["schema"]
306
+
307
+ # Resolve schema reference if present
308
+ if "$ref" in schema:
309
+ ref_schema = resolve_schema_reference(schema["$ref"], full_schema)
310
+ if ref_schema:
311
+ schema = ref_schema
312
+
313
+ # Check if the schema is an array type
314
+ if schema.get("type") == "array":
315
+ is_array_body = True
316
+ array_items_schema = schema.get("items", {})
317
+ # Try to resolve any reference in items
318
+ if "$ref" in array_items_schema:
319
+ array_items_schema = resolve_schema_reference(
320
+ array_items_schema["$ref"], full_schema
321
+ )
322
+ else:
323
+ # Extract required fields from schema
324
+ if "required" in schema:
325
+ required_fields = schema["required"]
326
+ # Extract properties from schema
327
+ if "properties" in schema:
328
+ request_body_properties = schema["properties"]
329
+
330
+ # Check for nested references in properties
331
+ for prop_name, prop_schema in request_body_properties.items():
332
+ if "$ref" in prop_schema:
333
+ ref_prop_schema = resolve_schema_reference(
334
+ prop_schema["$ref"], full_schema
335
+ )
336
+ if ref_prop_schema:
337
+ request_body_properties[prop_name] = ref_prop_schema
338
+
339
+ # Handle schemas with empty properties but additionalProperties: true
340
+ # by treating them similar to empty bodies
341
+ if (
342
+ not request_body_properties or len(request_body_properties) == 0
343
+ ) and schema.get("additionalProperties") is True:
344
+ has_empty_body = True
345
+
210
346
  # Build function arguments
211
347
  required_args = []
212
348
  optional_args = []
213
-
214
-
349
+
350
+ # Add path parameters
215
351
  for param_name in path_params_in_url:
216
352
  if param_name not in required_args:
217
353
  required_args.append(param_name)
218
354
 
219
-
355
+ # Add query parameters
220
356
  for param in parameters:
221
357
  param_name = param["name"]
222
- if param_name not in required_args:
358
+ if param_name not in required_args:
223
359
  if param.get("required", False):
224
360
  required_args.append(param_name)
225
361
  else:
226
362
  optional_args.append(f"{param_name}=None")
227
363
 
228
- # Add request body parameter
364
+ # Handle array type request body differently
365
+ request_body_params = []
229
366
  if has_body:
230
- if body_required:
231
- required_args.append("request_body")
232
- else:
233
- optional_args.append("request_body=None")
367
+ if is_array_body:
368
+ # For array request bodies, add a single parameter for the entire array
369
+ array_param_name = "items"
370
+ # Try to get a better name from the operation or path
371
+ if func_name.endswith("_list_input"):
372
+ array_param_name = func_name.replace("_list_input", "")
373
+ elif "List" in func_name:
374
+ array_param_name = func_name.split("List")[0].lower() + "_list"
375
+
376
+ # Make the array parameter required if the request body is required
377
+ if body_required:
378
+ required_args.append(array_param_name)
379
+ else:
380
+ optional_args.append(f"{array_param_name}=None")
381
+
382
+ # Remember this is an array param
383
+ request_body_params = [array_param_name]
384
+ elif request_body_properties:
385
+ # For object request bodies, add individual properties as parameters
386
+ for prop_name in request_body_properties:
387
+ if prop_name in required_fields:
388
+ request_body_params.append(prop_name)
389
+ if prop_name not in required_args:
390
+ required_args.append(prop_name)
391
+ else:
392
+ request_body_params.append(prop_name)
393
+ if f"{prop_name}=None" not in optional_args:
394
+ optional_args.append(f"{prop_name}=None")
395
+
396
+ # If request body is present but empty (content: {}), add a generic request_body parameter
397
+ if has_empty_body and "request_body=None" not in optional_args:
398
+ optional_args.append("request_body=None")
234
399
 
235
400
  # Combine required and optional arguments
236
401
  args = required_args + optional_args
@@ -245,19 +410,32 @@ def generate_method_code(path, method, operation, tool_name=None):
245
410
 
246
411
  # Validate required parameters including path parameters
247
412
  for param_name in required_args:
248
- if param_name != "request_body": # Skip validation for request body as it's handled separately
249
- body_lines.append(f" if {param_name} is None:")
250
- body_lines.append(
251
- f" raise ValueError(\"Missing required parameter '{param_name}'\")"
252
- )
253
-
254
- # Validate required body
255
- if has_body and body_required:
256
- body_lines.append(" if request_body is None:")
413
+ body_lines.append(f" if {param_name} is None:")
257
414
  body_lines.append(
258
- ' raise ValueError("Missing required request body")'
415
+ f" raise ValueError(\"Missing required parameter '{param_name}'\")"
259
416
  )
260
417
 
418
+ # Build request body (handle array and object types differently)
419
+ if has_body:
420
+ if is_array_body:
421
+ # For array request bodies, use the array parameter directly
422
+ body_lines.append(" # Use items array directly as request body")
423
+ body_lines.append(f" request_body = {request_body_params[0]}")
424
+ elif request_body_properties:
425
+ # For object request bodies, build the request body from individual parameters
426
+
427
+ body_lines.append(" request_body = {")
428
+
429
+ for prop_name in request_body_params:
430
+ # Only include non-None values in the request body
431
+ body_lines.append(f" '{prop_name}': {prop_name},")
432
+
433
+ body_lines.append(" }")
434
+
435
+ body_lines.append(
436
+ " request_body = {k: v for k, v in request_body.items() if v is not None}"
437
+ )
438
+
261
439
  # Format URL directly with path parameters
262
440
  url_line = f' url = f"{{self.base_url}}{path}"'
263
441
  body_lines.append(url_line)
@@ -276,30 +454,35 @@ def generate_method_code(path, method, operation, tool_name=None):
276
454
 
277
455
  # Make HTTP request using the proper method
278
456
  method_lower = method.lower()
457
+
458
+ # Determine what to use as the request body argument
459
+ if has_empty_body:
460
+ request_body_arg = "request_body"
461
+ elif not has_body:
462
+ request_body_arg = "{}"
463
+ else:
464
+ request_body_arg = "request_body"
465
+
279
466
  if method_lower == "get":
280
467
  body_lines.append(" response = self._get(url, params=query_params)")
281
468
  elif method_lower == "post":
282
- if has_body:
283
- body_lines.append(" response = self._post(url, data=request_body, params=query_params)")
284
- else:
285
- body_lines.append(" response = self._post(url, data={}, params=query_params)")
469
+ body_lines.append(
470
+ f" response = self._post(url, data={request_body_arg}, params=query_params)"
471
+ )
286
472
  elif method_lower == "put":
287
- if has_body:
288
- body_lines.append(" response = self._put(url, data=request_body, params=query_params)")
289
- else:
290
- body_lines.append(" response = self._put(url, data={}, params=query_params)")
473
+ body_lines.append(
474
+ f" response = self._put(url, data={request_body_arg}, params=query_params)"
475
+ )
291
476
  elif method_lower == "patch":
292
- if has_body:
293
- body_lines.append(" response = self._patch(url, data=request_body, params=query_params)")
294
- else:
295
- body_lines.append(" response = self._patch(url, data={}, params=query_params)")
477
+ body_lines.append(
478
+ f" response = self._patch(url, data={request_body_arg}, params=query_params)"
479
+ )
296
480
  elif method_lower == "delete":
297
481
  body_lines.append(" response = self._delete(url, params=query_params)")
298
482
  else:
299
- if has_body:
300
- body_lines.append(f" response = self._{method_lower}(url, data=request_body, params=query_params)")
301
- else:
302
- body_lines.append(f" response = self._{method_lower}(url, data={{}}, params=query_params)")
483
+ body_lines.append(
484
+ f" response = self._{method_lower}(url, data={request_body_arg}, params=query_params)"
485
+ )
303
486
 
304
487
  # Handle response
305
488
  body_lines.append(" response.raise_for_status()")
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: universal-mcp
3
- Version: 0.1.7rc2
3
+ Version: 0.1.8
4
4
  Summary: Universal MCP acts as a middle ware for your API applications. It can store your credentials, authorize, enable disable apps on the fly and much more.
5
5
  Author-email: Manoj Bajaj <manojbajaj95@gmail.com>
6
6
  Requires-Python: >=3.11
7
7
  Requires-Dist: keyring>=25.6.0
8
8
  Requires-Dist: litellm>=1.30.7
9
9
  Requires-Dist: loguru>=0.7.3
10
- Requires-Dist: mcp>=1.5.0
10
+ Requires-Dist: mcp>=1.6.0
11
11
  Requires-Dist: posthog>=3.24.0
12
12
  Requires-Dist: pydantic-settings>=2.8.1
13
13
  Requires-Dist: pydantic>=2.11.1
@@ -25,16 +25,16 @@ Requires-Dist: e2b-code-interpreter>=1.2.0; extra == 'e2b'
25
25
  Provides-Extra: firecrawl
26
26
  Requires-Dist: firecrawl-py>=1.15.0; extra == 'firecrawl'
27
27
  Provides-Extra: markitdown
28
- Requires-Dist: markitdown[all,e2b]>=0.1.1; extra == 'markitdown'
28
+ Requires-Dist: markitdown[all]>=0.1.1; extra == 'markitdown'
29
29
  Provides-Extra: playground
30
30
  Requires-Dist: fastapi[standard]>=0.115.12; extra == 'playground'
31
- Requires-Dist: langchain-anthropic>=0.3.10; extra == 'playground'
32
31
  Requires-Dist: langchain-mcp-adapters>=0.0.3; extra == 'playground'
33
32
  Requires-Dist: langchain-openai>=0.3.12; extra == 'playground'
34
33
  Requires-Dist: langgraph-checkpoint-sqlite>=2.0.6; extra == 'playground'
35
34
  Requires-Dist: langgraph>=0.3.24; extra == 'playground'
36
35
  Requires-Dist: python-dotenv>=1.0.1; extra == 'playground'
37
36
  Requires-Dist: streamlit>=1.44.1; extra == 'playground'
37
+ Requires-Dist: watchdog>=6.0.0; extra == 'playground'
38
38
  Provides-Extra: serpapi
39
39
  Requires-Dist: google-search-results>=2.4.2; extra == 'serpapi'
40
40
  Description-Content-Type: text/markdown
@@ -155,12 +155,16 @@ Universal MCP comes with several pre-built applications:
155
155
  | `firecrawl` | Scrape/crawl web pages, search | API Key (via Integration) |
156
156
  | `github` | Interact with GitHub repos, issues, PRs | OAuth (AgentR) |
157
157
  | `google-calendar`| Manage Google Calendar events | OAuth (AgentR) |
158
+ | `google-docs` | Create and manage Google Docs documents | OAuth (AgentR) |
159
+ | `google-drive` | Manage Google Drive files and folders | OAuth (AgentR) |
158
160
  | `google-mail` | Read and send Gmail emails | OAuth (AgentR) |
161
+ | `google-sheet` | Manage Google Sheets spreadsheets | OAuth (AgentR) |
159
162
  | `markitdown` | Convert web pages/files to Markdown | None |
160
163
  | `notion` | Interact with Notion pages/databases | OAuth (AgentR) |
164
+ | `perplexity` | Interact with Perplexity AI models | API Key (via Integration) |
161
165
  | `reddit` | Interact with Reddit posts/comments | OAuth (AgentR) |
162
166
  | `resend` | Send emails via Resend API | API Key (via Integration) |
163
- | `serp` | Perform web searches via SerpApi | API Key (via Integration) |
167
+ | `serpapi` | Perform web searches via SerpApi | API Key (via Integration) |
164
168
  | `tavily` | Advanced web search & research API | API Key (via Integration) |
165
169
  | `zenquotes` | Get inspirational quotes | None |
166
170
 
@@ -0,0 +1,81 @@
1
+ universal_mcp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ universal_mcp/analytics.py,sha256=aGCg0Okpcy06W70qCA9I8_ySOiCgAtzJAIWAdhBsOeA,2212
3
+ universal_mcp/cli.py,sha256=DG-Qxc5vQIdbhAIQuU7bKKJuRGzwyOigjfCKSWBRhBI,5258
4
+ universal_mcp/config.py,sha256=sJaPI4q51CDPPG0z32rMJiE7a64eaa9nxbjJgYnaFA4,838
5
+ universal_mcp/exceptions.py,sha256=WApedvzArNujD0gZfUofYBxjQo97ZDJLqDibtLWZoRk,373
6
+ universal_mcp/logger.py,sha256=D947u1roUf6WqlcEsPpvmWDqGc8L41qF3MO1suK5O1Q,308
7
+ universal_mcp/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ universal_mcp/applications/__init__.py,sha256=qeWnbdIudyMR7ST4XTc0gpEM9o6TsM1ZnZ92dMAPSBA,754
9
+ universal_mcp/applications/application.py,sha256=CUNUUfPl4JVmnFPBuYYhhlwRo63_SRvVw1HuKZ3u0js,6772
10
+ universal_mcp/applications/ahrefs/README.md,sha256=bQQ5AmPFxM52gL-tllIFWC_64f7KYkBiD1tYfdTwDu4,5370
11
+ universal_mcp/applications/ahrefs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
+ universal_mcp/applications/ahrefs/app.py,sha256=8iYYmQ5bD6nd_JmHOk4bcEPqG162FtQ14WrnJPeTrBQ,91468
13
+ universal_mcp/applications/calendly/README.md,sha256=85m3XXLPhQ99oghl8SeazCZ2fjBR81-f1y_mjjhx2B0,5911
14
+ universal_mcp/applications/calendly/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
+ universal_mcp/applications/calendly/app.py,sha256=ANuUfiXBwDZjQC-xfB06JoVu5ebQPEy12COBO5LY3DI,49874
16
+ universal_mcp/applications/coda/README.md,sha256=4i6o_R-qtTuxfS1A7VoIb8_85FHAj-WVb8YG5fNvwL4,11411
17
+ universal_mcp/applications/coda/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
+ universal_mcp/applications/coda/app.py,sha256=47ZmtYF5A2Cn0rh3Dpc3VtkIHR1Xu2PCYe1JDH8kJbY,155862
19
+ universal_mcp/applications/e2b/README.md,sha256=S4lTp-vEZ8VTCKPXqjUXu5nYlUMAF8lw8CQyBGPgxjs,700
20
+ universal_mcp/applications/e2b/app.py,sha256=4cMuGHm_QY4uh0JMh3HYzhaqtnfnXajRKFhoAGmRnBE,2252
21
+ universal_mcp/applications/figma/README.md,sha256=qA9UMf5PsPhfJrnteGVQOudhLuevwZ4-D_1xM6gAjgQ,4393
22
+ universal_mcp/applications/figma/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
+ universal_mcp/applications/figma/app.py,sha256=sr-ednZinHdIcXmDWuWAA_Ri21iBbAYPRZ0-uLeiEkM,50392
24
+ universal_mcp/applications/firecrawl/README.md,sha256=KAWe_TQbrc9eA6bSyde5dapMP1CNvarVItV_YJH3d_0,1430
25
+ universal_mcp/applications/firecrawl/app.py,sha256=qO3XNH9nT2G-9yC1eN4ADZJCE_bxF0qQ3S_qtYoOa2o,8902
26
+ universal_mcp/applications/github/README.md,sha256=6ID-__gUJ5ZxzAS_OjzmoUAag1LamSvEB75DHcj3m-g,1294
27
+ universal_mcp/applications/github/app.py,sha256=73Y5ceM2BGRcLUO__xO0RO1NNf6Gf3ROtqTlFI5k0Fg,18162
28
+ universal_mcp/applications/google_calendar/app.py,sha256=o2Mtto4zOIDtCUdXdEgXWhWsKRfzbHC7DAUuvyjUei4,19342
29
+ universal_mcp/applications/google_docs/README.md,sha256=SyOgJG-XU0FXhrVukvg9mxwin73mpqaCOT6rDJ64Klk,909
30
+ universal_mcp/applications/google_docs/app.py,sha256=f31nJ3tr9XF-1AbRI3DNVXgMXT4Y33gWMRlBoA-t630,3436
31
+ universal_mcp/applications/google_drive/README.md,sha256=YlN8IT12oO8zVMib1MlTYRBGNP7rzW_KyVAZyyxKvME,1192
32
+ universal_mcp/applications/google_drive/app.py,sha256=4cJYvT_RSlqL2Vfm4cbrxJYl58gHWdNytVAQVu1amY8,11253
33
+ universal_mcp/applications/google_mail/README.md,sha256=LL6TjjmwEqyuRVvIfCh-I_PlWp9ciCZOdJC0LafGZYc,1185
34
+ universal_mcp/applications/google_mail/app.py,sha256=1XI1hve2FXOqkzgJNYu2ki5J1yGKfeMx3cO_Qyflp_o,27286
35
+ universal_mcp/applications/google_sheet/README.md,sha256=yW1b_qlb_pbIJzCxZc58581kKzC5vyP8Mj4iwXgidtQ,1108
36
+ universal_mcp/applications/google_sheet/app.py,sha256=O6g8P697ve93CsljLK9ejWbIyzGbZ-_ThK_A_3cTpIk,6310
37
+ universal_mcp/applications/markitdown/app.py,sha256=j1AidXGmDwEV4sBw0A-mEe8O4V4Yln4Atrqnk29AHiI,1836
38
+ universal_mcp/applications/notion/README.md,sha256=45NmPOmSQv99qBvWdwmnV5vbaYc9_8vq8I-FA7veVAA,2600
39
+ universal_mcp/applications/notion/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
40
+ universal_mcp/applications/notion/app.py,sha256=nc-p531L-L6gMFqOOkYu5Irn9SReWAYRmJ8ZOIv5LrQ,20834
41
+ universal_mcp/applications/perplexity/README.md,sha256=QGV1iReH5p-Np7vvkZsVHxxDKQ0YaitHEwomNmGEyQs,732
42
+ universal_mcp/applications/perplexity/app.py,sha256=W2wXe2ltQKqKM6hKcVW0DczsULdmPhcsJdjx93wSXaM,2673
43
+ universal_mcp/applications/reddit/README.md,sha256=YVbJ1RN6NWlB-P6w2LxCk_DuUWl7mwaKZScY-mIMnNc,1271
44
+ universal_mcp/applications/reddit/app.py,sha256=Jd-Pr-IMhROun82kuLf0mNJ3P-LDfGfvj1bn_8qNIAI,15748
45
+ universal_mcp/applications/resend/README.md,sha256=k-sb2UwbFvDPEz6qQPLWd2cJj8hDx5f3NW7dz2jAfjI,719
46
+ universal_mcp/applications/resend/app.py,sha256=dWhijrx73hw2OLMAC01keVj7hVgu4CUZsURyRjxD7ew,1370
47
+ universal_mcp/applications/serpapi/README.md,sha256=hX4VeT2iL_67ZsMhKd60DAujQCh9K3IdHroHIq808RY,691
48
+ universal_mcp/applications/serpapi/app.py,sha256=krx9STkJI0vLarXo34emySv3fs9o9lmQ2qfjWbzxtg4,2918
49
+ universal_mcp/applications/tavily/README.md,sha256=cNg4EwX5wBbkDpPtNBNC3A_GxglfSVhdAJuweSrXN20,721
50
+ universal_mcp/applications/tavily/app.py,sha256=rU9IRyhzYkchjs8rqQMU89hkBQy13W8yeQqpQhPCCFA,1924
51
+ universal_mcp/applications/wrike/README.md,sha256=4EHVPlA8B_dzTA1-HQQqp89z6QL37RTyD2l6DD7vG9E,5156
52
+ universal_mcp/applications/wrike/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
53
+ universal_mcp/applications/wrike/app.py,sha256=j0sfbVaRSBoWN0dnpscifg_mwwSsKulX6dy-2ac3R68,60259
54
+ universal_mcp/applications/youtube/README.md,sha256=NHqIm6QvXQK7I2oZ8hUwfjLDS4_eSK9NPeFbuGIbmhg,5405
55
+ universal_mcp/applications/youtube/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
56
+ universal_mcp/applications/youtube/app.py,sha256=EQgeLNJS8Spm8xB82hSIBANJ4HR2-ktcurgW9Cn_ebU,56885
57
+ universal_mcp/applications/zenquotes/README.md,sha256=wA3hjqjrkrczQaffpwyolSKq6gXmkLgeHx6_EQrYEOY,709
58
+ universal_mcp/applications/zenquotes/app.py,sha256=xp_nlW4LFi0Mw1GRWIde4k8eexXUJx1wNqNExJ0oeKA,1085
59
+ universal_mcp/integrations/README.md,sha256=lTAPXO2nivcBe1q7JT6PRa6v9Ns_ZersQMIdw-nmwEA,996
60
+ universal_mcp/integrations/__init__.py,sha256=YY8Uw0XGNUpAQ1j-qgCOrwHTcuSew4W92cEtYXMxry4,963
61
+ universal_mcp/integrations/agentr.py,sha256=Bap4PA2-K4BkBhscgAVsBdvXNN19dkuCLO82sQFRvUM,3952
62
+ universal_mcp/integrations/integration.py,sha256=33i1-E4EMTZOhCcbLXSrJfnGUCmRROk7m7DxXUVCt5c,9985
63
+ universal_mcp/servers/__init__.py,sha256=dDtvvMzbWskABlobTZHztrWMb3hbzgidza3BmEmIAD8,474
64
+ universal_mcp/servers/server.py,sha256=azsUnzMwJXttNDBs4C6_yuds0A3gEsXkf0Dyc-vHeI8,7941
65
+ universal_mcp/stores/__init__.py,sha256=quvuwhZnpiSLuojf0NfmBx2xpaCulv3fbKtKaSCEmuM,603
66
+ universal_mcp/stores/store.py,sha256=8Hobd55WCXGXTJeADn7d_Qe-U8VkC6X3QDTgaKr3Saw,6774
67
+ universal_mcp/tools/__init__.py,sha256=hVL-elJLwD_K87Gpw_s2_o43sQRPyRNOnxlzt0_Pfn8,72
68
+ universal_mcp/tools/adapters.py,sha256=2HvpyFiI0zg9dp0XshnG7t6KrVqFHM7hgtmgY1bsHN0,927
69
+ universal_mcp/tools/func_metadata.py,sha256=f_5LdDNsOu1DpXvDUeZYiJswVmwGZz6IMPtpJJ5B2-Y,7975
70
+ universal_mcp/tools/tools.py,sha256=27PkcxoxdADoUqQHUyvKX1GJCOYb1lrOtqcR24tR7fs,12982
71
+ universal_mcp/utils/__init__.py,sha256=8wi4PGWu-SrFjNJ8U7fr2iFJ1ktqlDmSKj1xYd7KSDc,41
72
+ universal_mcp/utils/api_generator.py,sha256=-wRBpLVfJQXy1R-8FpDNs6b8_eeekVDuPc_uwjSGgiY,8883
73
+ universal_mcp/utils/docgen.py,sha256=yGBcBIr7dz3mNMGrCb_-JFsDf-ShmCKWWiPpuEj2SIU,21878
74
+ universal_mcp/utils/docstring_parser.py,sha256=-QVW9u9i1_FlAMwSkFil6ZNaKIkXKI6gqOYtURdp5ak,6745
75
+ universal_mcp/utils/dump_app_tools.py,sha256=9bQePJ4ZKzGtcIYrBgLxbKDOZmL7ajIAHhXljT_AlyA,2041
76
+ universal_mcp/utils/installation.py,sha256=KPBojDlt2YfFY2DfJ9pUr5evFJ9QQGp99KQUsRkz9GQ,10235
77
+ universal_mcp/utils/openapi.py,sha256=AgmcyntPyovic2mRqr-a7P4kEc7hU-yk9gRVIsO4078,20673
78
+ universal_mcp-0.1.8.dist-info/METADATA,sha256=Y68fFEe1WbvNoMG-5m2XM7JfyeMMc7y9BZBT1x1GAF0,11268
79
+ universal_mcp-0.1.8.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
80
+ universal_mcp-0.1.8.dist-info/entry_points.txt,sha256=QlBrVKmA2jIM0q-C-3TQMNJTTWOsOFQvgedBq2rZTS8,56
81
+ universal_mcp-0.1.8.dist-info/RECORD,,
@@ -1,58 +0,0 @@
1
- universal_mcp/__init__.py,sha256=2gdHpHaDDcsRjZjJ01FLN-1iidN_wbDAolNpxhGoFB4,59
2
- universal_mcp/cli.py,sha256=DG-Qxc5vQIdbhAIQuU7bKKJuRGzwyOigjfCKSWBRhBI,5258
3
- universal_mcp/config.py,sha256=sJaPI4q51CDPPG0z32rMJiE7a64eaa9nxbjJgYnaFA4,838
4
- universal_mcp/exceptions.py,sha256=Zp2_v_m3L7GDAmD1ZyuwFtY6ngapdhxuIygrvpZAQtM,271
5
- universal_mcp/logger.py,sha256=W6A868vyvpdkEQ4Dd0rWdC_7ErSxSQ1z2uxCb77IM8Y,2015
6
- universal_mcp/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
- universal_mcp/applications/__init__.py,sha256=qeWnbdIudyMR7ST4XTc0gpEM9o6TsM1ZnZ92dMAPSBA,754
8
- universal_mcp/applications/application.py,sha256=dqp8lgIi2xhY62imwo7C6769URQtNmqd6Ok6PiTr6wc,3399
9
- universal_mcp/applications/e2b/README.md,sha256=S4lTp-vEZ8VTCKPXqjUXu5nYlUMAF8lw8CQyBGPgxjs,700
10
- universal_mcp/applications/e2b/app.py,sha256=l7oRmxIuVglA1v9EtYqx_rlvYjUZz7GShmI_VLEQLjI,2979
11
- universal_mcp/applications/firecrawl/README.md,sha256=KAWe_TQbrc9eA6bSyde5dapMP1CNvarVItV_YJH3d_0,1430
12
- universal_mcp/applications/firecrawl/app.py,sha256=aPYx3uCsrR6CHz0RERE0ikHMbzwbhKE-SDkF5DVZLiQ,9572
13
- universal_mcp/applications/github/README.md,sha256=6ID-__gUJ5ZxzAS_OjzmoUAag1LamSvEB75DHcj3m-g,1294
14
- universal_mcp/applications/github/app.py,sha256=L201f5MSx1YVx0nqgduZ5gyHPZdX0UfcEhPmDWiWK6s,13686
15
- universal_mcp/applications/google_calendar/app.py,sha256=g_3vrsM2ltwpTySgC5I4SYg47n4UJiYigECO0ax1EHM,19134
16
- universal_mcp/applications/google_docs/README.md,sha256=SyOgJG-XU0FXhrVukvg9mxwin73mpqaCOT6rDJ64Klk,909
17
- universal_mcp/applications/google_docs/app.py,sha256=RGpk4xW6u2rA62zkjsokDbhff3bk_bGt261ToQlAQNY,3157
18
- universal_mcp/applications/google_drive/README.md,sha256=YlN8IT12oO8zVMib1MlTYRBGNP7rzW_KyVAZyyxKvME,1192
19
- universal_mcp/applications/google_drive/app.py,sha256=PUK19kZlYNWn3_4Us1179_gc6o_565B4hsfxUleeR68,9546
20
- universal_mcp/applications/google_mail/README.md,sha256=LL6TjjmwEqyuRVvIfCh-I_PlWp9ciCZOdJC0LafGZYc,1185
21
- universal_mcp/applications/google_mail/app.py,sha256=VXeD3_TRgYIUDFUzDPCKgR47XvovxLFulD-HG22hls8,22716
22
- universal_mcp/applications/google_sheet/README.md,sha256=yW1b_qlb_pbIJzCxZc58581kKzC5vyP8Mj4iwXgidtQ,1108
23
- universal_mcp/applications/google_sheet/app.py,sha256=zYsi_vTpJ-BtBPH6rQFRfwAJJkN_d8DJm6tFUzJBOSw,5399
24
- universal_mcp/applications/markitdown/app.py,sha256=Gh12f1dW6DA_AW5DuStbCkOR7KtyJp8VEjdTaIicrRI,1996
25
- universal_mcp/applications/notion/README.md,sha256=45NmPOmSQv99qBvWdwmnV5vbaYc9_8vq8I-FA7veVAA,2600
26
- universal_mcp/applications/notion/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
- universal_mcp/applications/notion/app.py,sha256=XpLnmeXj0Gnf_RYHlbAFnwtSCTYsrNzk6MSMSyDmHGQ,17283
28
- universal_mcp/applications/perplexity/README.md,sha256=QGV1iReH5p-Np7vvkZsVHxxDKQ0YaitHEwomNmGEyQs,732
29
- universal_mcp/applications/perplexity/app.py,sha256=q3FUnSHwq-_HnIUTYuxVdKmNJ5p0b-Aj3vZ0ZrP7Mg4,3494
30
- universal_mcp/applications/reddit/README.md,sha256=YVbJ1RN6NWlB-P6w2LxCk_DuUWl7mwaKZScY-mIMnNc,1271
31
- universal_mcp/applications/reddit/app.py,sha256=leU__w5VxX1vMK-kfuy-dvY97Pn8Mn80X2payVshirU,13562
32
- universal_mcp/applications/resend/README.md,sha256=k-sb2UwbFvDPEz6qQPLWd2cJj8hDx5f3NW7dz2jAfjI,719
33
- universal_mcp/applications/resend/app.py,sha256=fl_0U61Rm0fqz1lCxPiuGRkl2x0meafp6kMZbshD7wo,1733
34
- universal_mcp/applications/serp/README.md,sha256=hX4VeT2iL_67ZsMhKd60DAujQCh9K3IdHroHIq808RY,691
35
- universal_mcp/applications/serp/app.py,sha256=ug-XkyRrWRRgO_DV_lw4kIzQaGREd5VW1vV4Xv3ptAc,3461
36
- universal_mcp/applications/tavily/README.md,sha256=cNg4EwX5wBbkDpPtNBNC3A_GxglfSVhdAJuweSrXN20,721
37
- universal_mcp/applications/tavily/app.py,sha256=K5TLh6OSQ7w792poupZidzgbWotrIyEsu7YnGzPRX0w,2123
38
- universal_mcp/applications/zenquotes/README.md,sha256=wA3hjqjrkrczQaffpwyolSKq6gXmkLgeHx6_EQrYEOY,709
39
- universal_mcp/applications/zenquotes/app.py,sha256=nidRGwVORIU25QGCCbjDIv1UNFUj5nWA3qqK4JP0Tdg,621
40
- universal_mcp/integrations/README.md,sha256=lTAPXO2nivcBe1q7JT6PRa6v9Ns_ZersQMIdw-nmwEA,996
41
- universal_mcp/integrations/__init__.py,sha256=8e11JZyctaR9CmlNkfEZ6HhGDvhlvf9iug2wdjb5pwY,270
42
- universal_mcp/integrations/agentr.py,sha256=l0mo79oeDML19udFfoCo9lyhbDAf0X94_lnpOgbTrb0,3331
43
- universal_mcp/integrations/integration.py,sha256=X8COgD8vg1bKUq4-0ytkMytk1eEaDF1O2JLvu3ewgFk,5828
44
- universal_mcp/servers/__init__.py,sha256=dgRW_khG537GeLKC5_U5jhxCuu1L_1YeTujeDg0601E,654
45
- universal_mcp/servers/server.py,sha256=9GazpAzNiMgCMg4Vb4VeyoviddEt6pQzi7vLli8vC5A,6677
46
- universal_mcp/stores/__init__.py,sha256=Sc4AWtee_qtK5hpEVUAH2XM_6EBhcfikQXWiGXdNfes,560
47
- universal_mcp/stores/store.py,sha256=CNOnmKeOCkSU2ZA9t12AIWJcmqZZX_LSyZaV8FQf8Xk,4545
48
- universal_mcp/utils/__init__.py,sha256=8wi4PGWu-SrFjNJ8U7fr2iFJ1ktqlDmSKj1xYd7KSDc,41
49
- universal_mcp/utils/api_generator.py,sha256=-wRBpLVfJQXy1R-8FpDNs6b8_eeekVDuPc_uwjSGgiY,8883
50
- universal_mcp/utils/bridge.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
51
- universal_mcp/utils/docgen.py,sha256=yK6Ijo8G-wHPU3E1AnFpnXS9vXt2j9FM77w0etTaNOA,12639
52
- universal_mcp/utils/dump_app_tools.py,sha256=cLB9SumKsbs-rXJ_02lpMyyNkOmKZ57gekhCjhAlcHg,2009
53
- universal_mcp/utils/installation.py,sha256=3vy9ZLjQj1xpSAOyWpOanBr7o5DtffzWB5JAjN0Jjtk,3757
54
- universal_mcp/utils/openapi.py,sha256=ud_ZB7_60BcS1Vao7ESKDqo0gry9JN5wzy-CFssrjm8,13140
55
- universal_mcp-0.1.7rc2.dist-info/METADATA,sha256=p5lVC89uhzjoZVt6ltqWNKdwpLljzROvssQRJAXrVu0,10855
56
- universal_mcp-0.1.7rc2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
57
- universal_mcp-0.1.7rc2.dist-info/entry_points.txt,sha256=QlBrVKmA2jIM0q-C-3TQMNJTTWOsOFQvgedBq2rZTS8,56
58
- universal_mcp-0.1.7rc2.dist-info/RECORD,,
File without changes