universal-mcp 0.1.9rc1__py3-none-any.whl → 0.1.9rc2__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 (29) hide show
  1. universal_mcp/applications/application.py +19 -30
  2. universal_mcp/applications/cal_com_v2/app.py +1676 -1021
  3. universal_mcp/applications/clickup/app.py +1496 -846
  4. universal_mcp/applications/falai/README.md +42 -0
  5. universal_mcp/applications/falai/__init__.py +0 -0
  6. universal_mcp/applications/falai/app.py +332 -0
  7. universal_mcp/applications/gong/README.md +88 -0
  8. universal_mcp/applications/gong/__init__.py +0 -0
  9. universal_mcp/applications/gong/app.py +2297 -0
  10. universal_mcp/applications/hashnode/app.py +12 -8
  11. universal_mcp/applications/hashnode/prompt.md +2 -0
  12. universal_mcp/applications/heygen/README.md +69 -0
  13. universal_mcp/applications/heygen/__init__.py +0 -0
  14. universal_mcp/applications/heygen/app.py +956 -0
  15. universal_mcp/applications/mailchimp/app.py +3848 -1794
  16. universal_mcp/applications/replicate/README.md +47 -35
  17. universal_mcp/applications/replicate/__init__.py +0 -0
  18. universal_mcp/applications/replicate/app.py +215 -204
  19. universal_mcp/applications/retell_ai/app.py +84 -67
  20. universal_mcp/applications/rocketlane/app.py +49 -35
  21. universal_mcp/applications/spotify/app.py +723 -428
  22. universal_mcp/applications/supabase/app.py +909 -583
  23. universal_mcp/servers/server.py +50 -0
  24. universal_mcp/stores/store.py +2 -3
  25. universal_mcp/utils/docstring_parser.py +67 -36
  26. {universal_mcp-0.1.9rc1.dist-info → universal_mcp-0.1.9rc2.dist-info}/METADATA +5 -1
  27. {universal_mcp-0.1.9rc1.dist-info → universal_mcp-0.1.9rc2.dist-info}/RECORD +29 -19
  28. {universal_mcp-0.1.9rc1.dist-info → universal_mcp-0.1.9rc2.dist-info}/WHEEL +0 -0
  29. {universal_mcp-0.1.9rc1.dist-info → universal_mcp-0.1.9rc2.dist-info}/entry_points.txt +0 -0
@@ -234,3 +234,53 @@ class AgentRServer(BaseServer):
234
234
  except Exception:
235
235
  logger.error("Failed to load apps", exc_info=True)
236
236
  raise
237
+
238
+
239
+ class SingleMCPServer(BaseServer):
240
+ """
241
+ Minimal server implementation hosting a single BaseApplication instance.
242
+
243
+ This server type is intended for development and testing of a single
244
+ application's tools. It does not manage integrations or stores internally
245
+ beyond initializing the ToolManager and exposing the provided application's tools.
246
+ The application instance passed to the constructor should already be
247
+ configured with its appropriate integration (if required).
248
+
249
+ Args:
250
+ config: Server configuration (used for name, description, etc. but ignores 'apps')
251
+ app_instance: The single BaseApplication instance to host and expose its tools.
252
+ Can be None, in which case no tools will be registered.
253
+ **kwargs: Additional keyword arguments passed to FastMCP parent class.
254
+ """
255
+
256
+ def __init__(
257
+ self,
258
+ app_instance: BaseApplication,
259
+ config: ServerConfig | None = None,
260
+ **kwargs,
261
+ ):
262
+ server_config = ServerConfig(
263
+ type="local",
264
+ name=f"{app_instance.name.title()} MCP Server for Local Development"
265
+ if app_instance
266
+ else "Unnamed MCP Server",
267
+ description=f"Minimal MCP server for the local {app_instance.name} application."
268
+ if app_instance
269
+ else "Minimal MCP server with no application loaded.",
270
+ )
271
+ if not config:
272
+ config = server_config
273
+ super().__init__(config, **kwargs)
274
+
275
+ self.app_instance = app_instance
276
+ self._load_apps()
277
+
278
+ def _load_apps(self) -> None:
279
+ """Registers tools from the single provided application instance."""
280
+ if not self.app_instance:
281
+ logger.warning("No app_instance provided. No tools registered.")
282
+ return
283
+
284
+ tool_functions = self.app_instance.list_tools()
285
+ for tool_func in tool_functions:
286
+ self._tool_manager.add_tool(tool_func)
@@ -71,11 +71,10 @@ class BaseStore(ABC):
71
71
 
72
72
  def __repr__(self):
73
73
  return f"{self.__class__.__name__}()"
74
-
74
+
75
75
  def __str__(self):
76
76
  return self.__repr__()
77
-
78
-
77
+
79
78
 
80
79
  class MemoryStore(BaseStore):
81
80
  """
@@ -54,12 +54,12 @@ def parse_docstring(docstring: str | None) -> dict[str, Any]:
54
54
  args[current_key] = desc
55
55
  elif current_section == "raises" and current_key:
56
56
  if desc:
57
- raises[current_key] = desc
57
+ raises[current_key] = desc
58
58
  elif current_section == "returns":
59
59
  returns = desc
60
60
  elif current_section == "tags":
61
61
  # Tags section content is treated as a comma-separated list
62
- tags.clear() # Clear existing tags in case of multiple tag sections (unlikely but safe)
62
+ tags.clear() # Clear existing tags in case of multiple tag sections (unlikely but safe)
63
63
  tags.extend([tag.strip() for tag in desc.split(",") if tag.strip()])
64
64
  # 'other' sections are ignored in the final output
65
65
 
@@ -74,40 +74,52 @@ def parse_docstring(docstring: str | None) -> dict[str, Any]:
74
74
  elif stripped_lower in ("returns:", "yields:"):
75
75
  section_type = "returns"
76
76
  elif stripped_lower in ("raises:", "errors:", "exceptions:"):
77
- section_type = "raises"
77
+ section_type = "raises"
78
78
  elif stripped_lower in ("tags:",):
79
- section_type = "tags"
79
+ section_type = "tags"
80
80
  # Allow "Raises Description:" or "Tags content:"
81
81
  elif stripped_lower.startswith(("raises ", "errors ", "exceptions ")):
82
- section_type = "raises"
83
- # Capture content after header word and potential colon/space
84
- parts = re.split(r"[:\s]+", line.strip(), maxsplit=1) # B034: Use keyword maxsplit
85
- if len(parts) > 1:
82
+ section_type = "raises"
83
+ # Capture content after header word and potential colon/space
84
+ parts = re.split(
85
+ r"[:\s]+", line.strip(), maxsplit=1
86
+ ) # B034: Use keyword maxsplit
87
+ if len(parts) > 1:
86
88
  header_content = parts[1].strip()
87
89
  elif stripped_lower.startswith(("tags",)):
88
90
  section_type = "tags"
89
91
  # Capture content after header word and potential colon/space
90
- parts = re.split(r"[:\s]+", line.strip(), maxsplit=1) # B034: Use keyword maxsplit
92
+ parts = re.split(
93
+ r"[:\s]+", line.strip(), maxsplit=1
94
+ ) # B034: Use keyword maxsplit
91
95
  if len(parts) > 1:
92
96
  header_content = parts[1].strip()
93
97
 
94
-
95
98
  # Identify other known sections, but don't store their content
96
99
  elif stripped_lower.endswith(":") and stripped_lower[:-1] in (
97
- "attributes", "see also", "example", "examples", "notes", "todo", "fixme", "warning", "warnings"
100
+ "attributes",
101
+ "see also",
102
+ "example",
103
+ "examples",
104
+ "notes",
105
+ "todo",
106
+ "fixme",
107
+ "warning",
108
+ "warnings",
98
109
  ):
99
110
  section_type = "other"
100
111
 
101
112
  return section_type is not None, section_type, header_content
102
113
 
103
-
104
114
  in_summary = True
105
115
 
106
116
  for line in lines:
107
117
  stripped_line = line.strip()
108
118
  original_indentation = len(line) - len(line.lstrip(" "))
109
119
 
110
- is_new_section_header, new_section_type_this_line, header_content_this_line = check_for_section_header(line)
120
+ is_new_section_header, new_section_type_this_line, header_content_this_line = (
121
+ check_for_section_header(line)
122
+ )
111
123
 
112
124
  should_finalize_previous = False
113
125
 
@@ -117,19 +129,18 @@ def parse_docstring(docstring: str | None) -> dict[str, Any]:
117
129
  # Empty line or section header marks the end of the summary
118
130
  in_summary = False
119
131
  summary = " ".join(summary_lines).strip()
120
- summary_lines = [] # Clear summary_lines after finalizing summary
132
+ summary_lines = [] # Clear summary_lines after finalizing summary
121
133
 
122
134
  if not stripped_line:
123
- # If the line was just empty, continue to the next line
124
- # The new_section_header check will happen on the next iteration if it exists
125
- continue
135
+ # If the line was just empty, continue to the next line
136
+ # The new_section_header check will happen on the next iteration if it exists
137
+ continue
126
138
  # If it was a header, fall through to section handling below
127
139
 
128
140
  else:
129
141
  # Still in summary, append line
130
142
  summary_lines.append(stripped_line)
131
- continue # Process next line
132
-
143
+ continue # Process next line
133
144
 
134
145
  # --- Section and Item Handling ---
135
146
 
@@ -139,16 +150,31 @@ def parse_docstring(docstring: str | None) -> dict[str, Any]:
139
150
  # 2. An empty line is encountered AFTER we've started collecting content for an item or section.
140
151
  # 3. In 'args' or 'raises', we encounter a line that looks like a new key: value pair, or a non-indented line.
141
152
  # 4. In 'returns', 'tags', or 'other', we encounter a non-indented line after collecting content.
142
- if is_new_section_header or (not stripped_line and (current_desc_lines or current_key is not None)) or \
143
- (current_section in ["args", "raises"] and current_key is not None and (key_pattern.match(line) or (original_indentation == 0 and stripped_line))) or \
144
- (current_section in ["returns", "tags", "other"] and current_desc_lines and original_indentation == 0 and stripped_line):
153
+ if (
154
+ is_new_section_header
155
+ or (not stripped_line and (current_desc_lines or current_key is not None))
156
+ or (
157
+ current_section in ["args", "raises"]
158
+ and current_key is not None
159
+ and (
160
+ key_pattern.match(line)
161
+ or (original_indentation == 0 and stripped_line)
162
+ )
163
+ )
164
+ or (
165
+ current_section in ["returns", "tags", "other"]
166
+ and current_desc_lines
167
+ and original_indentation == 0
168
+ and stripped_line
169
+ )
170
+ ):
145
171
  should_finalize_previous = True
146
172
  elif current_section in ["args", "raises"] and current_key is not None:
147
173
  # Inside args/raises, processing an item (current_key is set)
148
- pass # Logic moved to the combined if statement
174
+ pass # Logic moved to the combined if statement
149
175
  elif current_section in ["returns", "tags", "other"] and current_desc_lines:
150
176
  # Inside returns/tags/other, collecting description lines
151
- pass # Logic moved to the combined if statement
177
+ pass # Logic moved to the combined if statement
152
178
 
153
179
  # If finalizing the previous item/section
154
180
  if should_finalize_previous:
@@ -157,9 +183,14 @@ def parse_docstring(docstring: str | None) -> dict[str, Any]:
157
183
  # If it was a new section header, reset everything
158
184
  # If it was an end-of-item/block signal within a section, reset key and description lines
159
185
  # (The condition for resetting key here is complex but matches the original logic)
160
- if is_new_section_header or (current_section in ["args", "raises"] and current_key is not None and not key_pattern.match(line) and (not stripped_line or original_indentation == 0)):
161
- current_key = None
162
- current_desc_lines = [] # Always clear description lines
186
+ if is_new_section_header or (
187
+ current_section in ["args", "raises"]
188
+ and current_key is not None
189
+ and not key_pattern.match(line)
190
+ and (not stripped_line or original_indentation == 0)
191
+ ):
192
+ current_key = None
193
+ current_desc_lines = [] # Always clear description lines
163
194
 
164
195
  # --- Process the current line ---
165
196
 
@@ -167,9 +198,9 @@ def parse_docstring(docstring: str | None) -> dict[str, Any]:
167
198
  if is_new_section_header:
168
199
  current_section = new_section_type_this_line
169
200
  if header_content_this_line:
170
- # Add content immediately following the header on the same line
171
- current_desc_lines.append(header_content_this_line)
172
- continue # Move to the next line, header is processed
201
+ # Add content immediately following the header on the same line
202
+ current_desc_lines.append(header_content_this_line)
203
+ continue # Move to the next line, header is processed
173
204
 
174
205
  # If the line is empty, and not a section header (handled above), skip it
175
206
  if not stripped_line:
@@ -181,10 +212,10 @@ def parse_docstring(docstring: str | None) -> dict[str, Any]:
181
212
  if match:
182
213
  # Found a new key: value item within args/raises
183
214
  current_key = match.group(1)
184
- current_desc_lines = [match.group(2).strip()] # Start new description
215
+ current_desc_lines = [match.group(2).strip()] # Start new description
185
216
  elif current_key is not None:
186
- # Not a new key, but processing an existing item - append to description
187
- current_desc_lines.append(stripped_line)
217
+ # Not a new key, but processing an existing item - append to description
218
+ current_desc_lines.append(stripped_line)
188
219
  # Lines that don't match key_pattern and occur when current_key is None
189
220
  # within args/raises are effectively ignored by this block, which seems
190
221
  # consistent with needing a key: description format.
@@ -203,8 +234,7 @@ def parse_docstring(docstring: str | None) -> dict[str, Any]:
203
234
  # or falls through to the final finalize call if neither occurs.
204
235
  # Keeping it for clarity, though the logic flow should cover it.
205
236
  if in_summary:
206
- summary = " ".join(summary_lines).strip()
207
-
237
+ summary = " ".join(summary_lines).strip()
208
238
 
209
239
  return {
210
240
  "summary": summary,
@@ -214,6 +244,7 @@ def parse_docstring(docstring: str | None) -> dict[str, Any]:
214
244
  "tags": tags,
215
245
  }
216
246
 
247
+
217
248
  docstring_example = """
218
249
  Starts a crawl job for a given URL using Firecrawl.
219
250
  Returns the job ID immediately.
@@ -243,4 +274,4 @@ if __name__ == "__main__":
243
274
  import json
244
275
 
245
276
  parsed = parse_docstring(docstring_example)
246
- print(json.dumps(parsed, indent=4))
277
+ print(json.dumps(parsed, indent=4))
@@ -1,11 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: universal-mcp
3
- Version: 0.1.9rc1
3
+ Version: 0.1.9rc2
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: gql[all]>=3.5.2
8
8
  Requires-Dist: keyring>=25.6.0
9
+ Requires-Dist: langchain-cerebras>=0.5.0
10
+ Requires-Dist: langchain-google-genai>=2.1.3
9
11
  Requires-Dist: litellm>=1.30.7
10
12
  Requires-Dist: loguru>=0.7.3
11
13
  Requires-Dist: mcp>=1.6.0
@@ -23,6 +25,8 @@ Requires-Dist: pytest>=8.3.5; extra == 'dev'
23
25
  Requires-Dist: ruff>=0.11.4; extra == 'dev'
24
26
  Provides-Extra: e2b
25
27
  Requires-Dist: e2b-code-interpreter>=1.2.0; extra == 'e2b'
28
+ Provides-Extra: fal-ai
29
+ Requires-Dist: fal-client>=0.5.9; extra == 'fal-ai'
26
30
  Provides-Extra: firecrawl
27
31
  Requires-Dist: firecrawl-py>=1.15.0; extra == 'firecrawl'
28
32
  Provides-Extra: markitdown
@@ -6,24 +6,27 @@ universal_mcp/exceptions.py,sha256=WApedvzArNujD0gZfUofYBxjQo97ZDJLqDibtLWZoRk,3
6
6
  universal_mcp/logger.py,sha256=D947u1roUf6WqlcEsPpvmWDqGc8L41qF3MO1suK5O1Q,308
7
7
  universal_mcp/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
8
  universal_mcp/applications/__init__.py,sha256=7s5c2j3Cbgdmqp7J1QKdehUQmlzSE0NLfkDE1U8Dl1A,825
9
- universal_mcp/applications/application.py,sha256=Q_DSnvYCgoZH6gS8M1FtrrOetOTXI6bIaKPjgUgQJVA,8240
9
+ universal_mcp/applications/application.py,sha256=0eC9D4HHRwIGpuFusaCxTZ0u64U68VbBpRSxjxGB5y8,8152
10
10
  universal_mcp/applications/ahrefs/README.md,sha256=bQQ5AmPFxM52gL-tllIFWC_64f7KYkBiD1tYfdTwDu4,5370
11
11
  universal_mcp/applications/ahrefs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
12
  universal_mcp/applications/ahrefs/app.py,sha256=8iYYmQ5bD6nd_JmHOk4bcEPqG162FtQ14WrnJPeTrBQ,91468
13
13
  universal_mcp/applications/cal_com_v2/README.md,sha256=iSgL5yZygDTV19Kh6me7mqaDyjO88Ka9TjE5rDrT8x4,20773
14
14
  universal_mcp/applications/cal_com_v2/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
- universal_mcp/applications/cal_com_v2/app.py,sha256=68o-10yoMCwb1iwzBPTm3kYyHYXktzeGaTnK3j7MKLw,234189
15
+ universal_mcp/applications/cal_com_v2/app.py,sha256=5yLDB0jJSSXud8gkwwEt73qMkgZ53hi9H5LuiNHo8x0,235353
16
16
  universal_mcp/applications/calendly/README.md,sha256=85m3XXLPhQ99oghl8SeazCZ2fjBR81-f1y_mjjhx2B0,5911
17
17
  universal_mcp/applications/calendly/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
18
  universal_mcp/applications/calendly/app.py,sha256=ANuUfiXBwDZjQC-xfB06JoVu5ebQPEy12COBO5LY3DI,49874
19
19
  universal_mcp/applications/clickup/README.md,sha256=A7q0j9IXm2jKBxGtWa4SUuTYF5_nJYEht4xeIbKhLHI,15482
20
20
  universal_mcp/applications/clickup/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
- universal_mcp/applications/clickup/app.py,sha256=_K5ZyMY3R8Ha88xvhh6xxbCsWRGr12j_of6FRrG9WVE,206947
21
+ universal_mcp/applications/clickup/app.py,sha256=byJFbwbzt0Pg7CQ2Eyqnrdqi_iFfF2aINBKQ46tbE1I,209269
22
22
  universal_mcp/applications/coda/README.md,sha256=4i6o_R-qtTuxfS1A7VoIb8_85FHAj-WVb8YG5fNvwL4,11411
23
23
  universal_mcp/applications/coda/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
24
  universal_mcp/applications/coda/app.py,sha256=47ZmtYF5A2Cn0rh3Dpc3VtkIHR1Xu2PCYe1JDH8kJbY,155862
25
25
  universal_mcp/applications/e2b/README.md,sha256=S4lTp-vEZ8VTCKPXqjUXu5nYlUMAF8lw8CQyBGPgxjs,700
26
26
  universal_mcp/applications/e2b/app.py,sha256=4cMuGHm_QY4uh0JMh3HYzhaqtnfnXajRKFhoAGmRnBE,2252
27
+ universal_mcp/applications/falai/README.md,sha256=fc31zlKe09FsOw6W5KY7VipxvKhon4KQoWjTdoMlPfc,1449
28
+ universal_mcp/applications/falai/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
+ universal_mcp/applications/falai/app.py,sha256=S6gaXLWBgTm_EBqH8aBUKih5iM2EL6gbRSAJ5Xmcfzg,12323
27
30
  universal_mcp/applications/figma/README.md,sha256=qA9UMf5PsPhfJrnteGVQOudhLuevwZ4-D_1xM6gAjgQ,4393
28
31
  universal_mcp/applications/figma/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
32
  universal_mcp/applications/figma/app.py,sha256=sr-ednZinHdIcXmDWuWAA_Ri21iBbAYPRZ0-uLeiEkM,50392
@@ -31,6 +34,9 @@ universal_mcp/applications/firecrawl/README.md,sha256=KAWe_TQbrc9eA6bSyde5dapMP1
31
34
  universal_mcp/applications/firecrawl/app.py,sha256=qO3XNH9nT2G-9yC1eN4ADZJCE_bxF0qQ3S_qtYoOa2o,8902
32
35
  universal_mcp/applications/github/README.md,sha256=6ID-__gUJ5ZxzAS_OjzmoUAag1LamSvEB75DHcj3m-g,1294
33
36
  universal_mcp/applications/github/app.py,sha256=73Y5ceM2BGRcLUO__xO0RO1NNf6Gf3ROtqTlFI5k0Fg,18162
37
+ universal_mcp/applications/gong/README.md,sha256=R-jcQOi7rRodvcwkxN8YpFRIDhR15G20AeNDQ0PzjAw,6700
38
+ universal_mcp/applications/gong/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
39
+ universal_mcp/applications/gong/app.py,sha256=C-DQffWMxZuskfsyIuyVVXZZ0u2dSAuCjAY8wIjnDnI,101011
34
40
  universal_mcp/applications/google_calendar/app.py,sha256=o2Mtto4zOIDtCUdXdEgXWhWsKRfzbHC7DAUuvyjUei4,19342
35
41
  universal_mcp/applications/google_docs/README.md,sha256=SyOgJG-XU0FXhrVukvg9mxwin73mpqaCOT6rDJ64Klk,909
36
42
  universal_mcp/applications/google_docs/app.py,sha256=f31nJ3tr9XF-1AbRI3DNVXgMXT4Y33gWMRlBoA-t630,3436
@@ -40,11 +46,14 @@ universal_mcp/applications/google_mail/README.md,sha256=LL6TjjmwEqyuRVvIfCh-I_Pl
40
46
  universal_mcp/applications/google_mail/app.py,sha256=1XI1hve2FXOqkzgJNYu2ki5J1yGKfeMx3cO_Qyflp_o,27286
41
47
  universal_mcp/applications/google_sheet/README.md,sha256=yW1b_qlb_pbIJzCxZc58581kKzC5vyP8Mj4iwXgidtQ,1108
42
48
  universal_mcp/applications/google_sheet/app.py,sha256=O6g8P697ve93CsljLK9ejWbIyzGbZ-_ThK_A_3cTpIk,6310
43
- universal_mcp/applications/hashnode/app.py,sha256=TGfJmumJGOkS_M0QONWHR0dcBmrHcsWslJYsUvxjj7A,2286
44
- universal_mcp/applications/hashnode/prompt.md,sha256=RTXicHP_JrI9pMoMf6oay0OxkJUI1yBWyMGCYP6X7xE,1651
49
+ universal_mcp/applications/hashnode/app.py,sha256=v0OR00kkMqyL-NcclCuriCdGErE7PRvHoWScfvAeEXQ,2538
50
+ universal_mcp/applications/hashnode/prompt.md,sha256=K-LPmn2wchYEX2ytANDS4-fsKrhPphKPV62oYZ_n-M4,1742
51
+ universal_mcp/applications/heygen/README.md,sha256=8YW_JYxPMXIFqNlhp-IYtRN8CrPAR0Uh1q3FFzlPni0,4304
52
+ universal_mcp/applications/heygen/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
53
+ universal_mcp/applications/heygen/app.py,sha256=2H0RI_zs-L2uT8TiCzCFtuLmuH6O2mDtmVIvNUu4qNA,35256
45
54
  universal_mcp/applications/mailchimp/README.md,sha256=9p7rVwf0aX2lClVeMliUz8rFWtXNhi55AAKj3hbHSng,33688
46
55
  universal_mcp/applications/mailchimp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
47
- universal_mcp/applications/mailchimp/app.py,sha256=Qg8GupbjKMueThLVtUi-_6Xh0qzIKvv531XDLPj6zKI,453966
56
+ universal_mcp/applications/mailchimp/app.py,sha256=_ceKe-ZM6KTgi17WABs9I45dum1cTj0ZlnccJ9BQwuE,466711
48
57
  universal_mcp/applications/markitdown/app.py,sha256=FeJONdT-Jwe5mJBelOfgpM1A3T-hIDfFGf1PCR5x1gA,1832
49
58
  universal_mcp/applications/notion/README.md,sha256=45NmPOmSQv99qBvWdwmnV5vbaYc9_8vq8I-FA7veVAA,2600
50
59
  universal_mcp/applications/notion/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -53,24 +62,25 @@ universal_mcp/applications/perplexity/README.md,sha256=QGV1iReH5p-Np7vvkZsVHxxDK
53
62
  universal_mcp/applications/perplexity/app.py,sha256=WAFDLH6jkH5eo9LLQfD_MRhpJdgZgHXchqs_ARJe3oI,2633
54
63
  universal_mcp/applications/reddit/README.md,sha256=YVbJ1RN6NWlB-P6w2LxCk_DuUWl7mwaKZScY-mIMnNc,1271
55
64
  universal_mcp/applications/reddit/app.py,sha256=Jd-Pr-IMhROun82kuLf0mNJ3P-LDfGfvj1bn_8qNIAI,15748
56
- universal_mcp/applications/replicate/README.md,sha256=9ZT3LPpsSG_SSyAJhw0Y60NhynmWoxSttmDkJyCsT9I,4415
57
- universal_mcp/applications/replicate/app.py,sha256=CkvUjWAWxp06WE_H8CEQkUfj6bwUDUMuWYdu0XXNR5c,39674
65
+ universal_mcp/applications/replicate/README.md,sha256=8_PT_Mft6ZvkamU50lVbF7XBQ_jBb-X78ALMCAokna8,3718
66
+ universal_mcp/applications/replicate/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
67
+ universal_mcp/applications/replicate/app.py,sha256=--agxFi0OunJkdzjsah10V660Xz9sDHet8t-PT6OMeI,38818
58
68
  universal_mcp/applications/resend/README.md,sha256=k-sb2UwbFvDPEz6qQPLWd2cJj8hDx5f3NW7dz2jAfjI,719
59
69
  universal_mcp/applications/resend/app.py,sha256=dWhijrx73hw2OLMAC01keVj7hVgu4CUZsURyRjxD7ew,1370
60
70
  universal_mcp/applications/retell_ai/README.md,sha256=XKBvMeA-wQAZYGMXogWMyvcqclhLGVnK72G4q2ZdfVM,1882
61
71
  universal_mcp/applications/retell_ai/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
62
- universal_mcp/applications/retell_ai/app.py,sha256=Ux0XuH65Y51CPgInfLZxGMLRdfATd31yMptcusUk-BA,13601
72
+ universal_mcp/applications/retell_ai/app.py,sha256=qhXAdXQhOYMNirJ08xU_R5TnJa_d97lc1Hue9xWrX3U,13406
63
73
  universal_mcp/applications/rocketlane/README.md,sha256=WtWkCt5nRN-SESaQXpYxgZwGEcxOXIcn9aQB7dDY8vM,1245
64
74
  universal_mcp/applications/rocketlane/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
65
- universal_mcp/applications/rocketlane/app.py,sha256=ZjqpgyT059Z8wlXCcz5WOiU37VjXImSOplyx-bhDhgk,6875
75
+ universal_mcp/applications/rocketlane/app.py,sha256=EvHFiIi_hAuU_UqLCxkdXE3Cb9uNHZmunsUaNjiyfwU,6795
66
76
  universal_mcp/applications/serpapi/README.md,sha256=hX4VeT2iL_67ZsMhKd60DAujQCh9K3IdHroHIq808RY,691
67
77
  universal_mcp/applications/serpapi/app.py,sha256=krx9STkJI0vLarXo34emySv3fs9o9lmQ2qfjWbzxtg4,2918
68
78
  universal_mcp/applications/spotify/README.md,sha256=iT8nx2_1jcpNqf6Xn3E0-oxmimg1Z1CYFAJg9qNR_4g,9626
69
79
  universal_mcp/applications/spotify/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
70
- universal_mcp/applications/spotify/app.py,sha256=Lk-zLUAleiTNhEIBSdePGbNoBwxPnEz7pyBafwk6Zyo,104644
80
+ universal_mcp/applications/spotify/app.py,sha256=x8QxvW9gjKtxjM58ECta1MN-_0lwPUGpnmW443a2OM0,105444
71
81
  universal_mcp/applications/supabase/README.md,sha256=CqCTwOGJWwOgwPQSblgUxYMWHBn5jZn6gOxB568sVrs,9743
72
82
  universal_mcp/applications/supabase/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
73
- universal_mcp/applications/supabase/app.py,sha256=Dp1pMdKgJyFIx8iIxhUFUMmCET1knNiWrawsnRe-01g,135495
83
+ universal_mcp/applications/supabase/app.py,sha256=WRacy6_gqPsoTjtjHu-N2vhned2X-rW77IBj0IyGHh4,135842
74
84
  universal_mcp/applications/tavily/README.md,sha256=cNg4EwX5wBbkDpPtNBNC3A_GxglfSVhdAJuweSrXN20,721
75
85
  universal_mcp/applications/tavily/app.py,sha256=rU9IRyhzYkchjs8rqQMU89hkBQy13W8yeQqpQhPCCFA,1924
76
86
  universal_mcp/applications/wrike/README.md,sha256=4EHVPlA8B_dzTA1-HQQqp89z6QL37RTyD2l6DD7vG9E,5156
@@ -86,9 +96,9 @@ universal_mcp/integrations/__init__.py,sha256=YY8Uw0XGNUpAQ1j-qgCOrwHTcuSew4W92c
86
96
  universal_mcp/integrations/agentr.py,sha256=Bap4PA2-K4BkBhscgAVsBdvXNN19dkuCLO82sQFRvUM,3952
87
97
  universal_mcp/integrations/integration.py,sha256=imzxq1jZJAjq9odF6ttCUS2-yQW7qqG8NNUj1LudT9U,9986
88
98
  universal_mcp/servers/__init__.py,sha256=dDtvvMzbWskABlobTZHztrWMb3hbzgidza3BmEmIAD8,474
89
- universal_mcp/servers/server.py,sha256=g2BJklnkPiO1yX9G1CQdRjb-bs_mg9NGYgPKgiKHEyg,7953
99
+ universal_mcp/servers/server.py,sha256=bm1gprc_6TPB8iShI6H7Kzp8CWsW5A51vb8DHW8AiUA,9916
90
100
  universal_mcp/stores/__init__.py,sha256=quvuwhZnpiSLuojf0NfmBx2xpaCulv3fbKtKaSCEmuM,603
91
- universal_mcp/stores/store.py,sha256=-yCedzDQafYvQh17RjTPzUwXdjyOOO_0UP_QmAqeClE,6913
101
+ universal_mcp/stores/store.py,sha256=lYaFd-9YKC404BPeqzNw_Xm3ziQjksZyvQtaW1yd9FM,6900
92
102
  universal_mcp/tools/__init__.py,sha256=hVL-elJLwD_K87Gpw_s2_o43sQRPyRNOnxlzt0_Pfn8,72
93
103
  universal_mcp/tools/adapters.py,sha256=2HvpyFiI0zg9dp0XshnG7t6KrVqFHM7hgtmgY1bsHN0,927
94
104
  universal_mcp/tools/func_metadata.py,sha256=f_5LdDNsOu1DpXvDUeZYiJswVmwGZz6IMPtpJJ5B2-Y,7975
@@ -96,11 +106,11 @@ universal_mcp/tools/tools.py,sha256=PbvTi8A1hT7F8UXiiP291aP_oZmIPBfhfcgqR8XeSqo,
96
106
  universal_mcp/utils/__init__.py,sha256=8wi4PGWu-SrFjNJ8U7fr2iFJ1ktqlDmSKj1xYd7KSDc,41
97
107
  universal_mcp/utils/api_generator.py,sha256=-wRBpLVfJQXy1R-8FpDNs6b8_eeekVDuPc_uwjSGgiY,8883
98
108
  universal_mcp/utils/docgen.py,sha256=yGBcBIr7dz3mNMGrCb_-JFsDf-ShmCKWWiPpuEj2SIU,21878
99
- universal_mcp/utils/docstring_parser.py,sha256=UU_PzE4nYTPNWNJhVS4t-uvFiA3IL-zK-_H6rSerCOI,10976
109
+ universal_mcp/utils/docstring_parser.py,sha256=j7aE-LLnBOPTJI0qXayf0NlYappzxICv5E_hUPNmAlc,11459
100
110
  universal_mcp/utils/dump_app_tools.py,sha256=9bQePJ4ZKzGtcIYrBgLxbKDOZmL7ajIAHhXljT_AlyA,2041
101
111
  universal_mcp/utils/installation.py,sha256=KPBojDlt2YfFY2DfJ9pUr5evFJ9QQGp99KQUsRkz9GQ,10235
102
112
  universal_mcp/utils/openapi.py,sha256=AgmcyntPyovic2mRqr-a7P4kEc7hU-yk9gRVIsO4078,20673
103
- universal_mcp-0.1.9rc1.dist-info/METADATA,sha256=478HydebTfGc-zWDh_7tfhUqPQKDqP_Gfd6BcWnra-s,11302
104
- universal_mcp-0.1.9rc1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
105
- universal_mcp-0.1.9rc1.dist-info/entry_points.txt,sha256=QlBrVKmA2jIM0q-C-3TQMNJTTWOsOFQvgedBq2rZTS8,56
106
- universal_mcp-0.1.9rc1.dist-info/RECORD,,
113
+ universal_mcp-0.1.9rc2.dist-info/METADATA,sha256=_jBOv89dqpJ40o3e40nZytj_2vDbCqpJkSWBy6FoaSk,11463
114
+ universal_mcp-0.1.9rc2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
115
+ universal_mcp-0.1.9rc2.dist-info/entry_points.txt,sha256=QlBrVKmA2jIM0q-C-3TQMNJTTWOsOFQvgedBq2rZTS8,56
116
+ universal_mcp-0.1.9rc2.dist-info/RECORD,,