universal-mcp 0.1.22rc4__py3-none-any.whl → 0.1.23__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- universal_mcp/applications/application.py +34 -15
- universal_mcp/cli.py +2 -1
- universal_mcp/client/__main__.py +30 -0
- universal_mcp/client/agent.py +96 -0
- universal_mcp/client/client.py +198 -0
- universal_mcp/client/oauth.py +114 -0
- universal_mcp/client/token_store.py +32 -0
- universal_mcp/config.py +62 -3
- universal_mcp/integrations/integration.py +2 -2
- universal_mcp/servers/server.py +5 -5
- universal_mcp/tools/adapters.py +16 -0
- universal_mcp/tools/func_metadata.py +162 -85
- universal_mcp/tools/tools.py +10 -3
- universal_mcp/utils/agentr.py +5 -1
- universal_mcp/utils/docstring_parser.py +34 -52
- universal_mcp/utils/openapi/api_splitter.py +11 -6
- universal_mcp/utils/openapi/openapi.py +9 -12
- {universal_mcp-0.1.22rc4.dist-info → universal_mcp-0.1.23.dist-info}/METADATA +2 -2
- {universal_mcp-0.1.22rc4.dist-info → universal_mcp-0.1.23.dist-info}/RECORD +22 -17
- {universal_mcp-0.1.22rc4.dist-info → universal_mcp-0.1.23.dist-info}/WHEEL +0 -0
- {universal_mcp-0.1.22rc4.dist-info → universal_mcp-0.1.23.dist-info}/entry_points.txt +0 -0
- {universal_mcp-0.1.22rc4.dist-info → universal_mcp-0.1.23.dist-info}/licenses/LICENSE +0 -0
@@ -9,7 +9,8 @@ def parse_docstring(docstring: str | None) -> dict[str, Any]:
|
|
9
9
|
|
10
10
|
Supports multi-line descriptions for each section. Recognizes common section
|
11
11
|
headers like 'Args:', 'Returns:', 'Raises:', 'Tags:', etc. Also attempts
|
12
|
-
to parse key-value pairs within 'Args:' and 'Raises:' sections
|
12
|
+
to parse key-value pairs within 'Args:' and 'Raises:' sections, including
|
13
|
+
type information for arguments if present in the docstring.
|
13
14
|
|
14
15
|
Args:
|
15
16
|
docstring: The docstring string to parse, or None.
|
@@ -17,7 +18,9 @@ def parse_docstring(docstring: str | None) -> dict[str, Any]:
|
|
17
18
|
Returns:
|
18
19
|
A dictionary containing the parsed components:
|
19
20
|
- 'summary': The first paragraph of the docstring.
|
20
|
-
- 'args': A dictionary mapping argument names to their
|
21
|
+
- 'args': A dictionary mapping argument names to their details,
|
22
|
+
including 'description' and 'type_str' (if found).
|
23
|
+
Example: {"param_name": {"description": "desc...", "type_str": "str"}}
|
21
24
|
- 'returns': The description of the return value.
|
22
25
|
- 'raises': A dictionary mapping exception types to their descriptions.
|
23
26
|
- 'tags': A list of strings found in the 'Tags:' section.
|
@@ -31,7 +34,7 @@ def parse_docstring(docstring: str | None) -> dict[str, Any]:
|
|
31
34
|
|
32
35
|
summary: str = ""
|
33
36
|
summary_lines: list[str] = []
|
34
|
-
args: dict[str, str] = {}
|
37
|
+
args: dict[str, dict[str, str | None]] = {}
|
35
38
|
returns: str = ""
|
36
39
|
raises: dict[str, str] = {}
|
37
40
|
tags: list[str] = []
|
@@ -39,17 +42,20 @@ def parse_docstring(docstring: str | None) -> dict[str, Any]:
|
|
39
42
|
current_section: str | None = None
|
40
43
|
current_key: str | None = None
|
41
44
|
current_desc_lines: list[str] = []
|
45
|
+
current_arg_type_str: str | None = None
|
42
46
|
|
43
|
-
key_pattern = re.compile(r"^\s*([\w\.]+)\s*(?:\(
|
47
|
+
key_pattern = re.compile(r"^\s*([\w\.]+)\s*(?:\((.*?)\))?:\s*(.*)")
|
44
48
|
|
45
49
|
def finalize_current_item():
|
46
|
-
|
47
|
-
nonlocal returns, tags, args, raises
|
50
|
+
nonlocal returns, tags, args, raises, current_arg_type_str
|
48
51
|
desc = " ".join(current_desc_lines).strip()
|
49
52
|
|
50
53
|
if current_section == "args" and current_key:
|
51
|
-
if desc:
|
52
|
-
args[current_key] =
|
54
|
+
if desc or current_arg_type_str:
|
55
|
+
args[current_key] = {
|
56
|
+
"description": desc,
|
57
|
+
"type_str": current_arg_type_str,
|
58
|
+
}
|
53
59
|
elif current_section == "raises" and current_key:
|
54
60
|
if desc:
|
55
61
|
raises[current_key] = desc
|
@@ -61,7 +67,6 @@ def parse_docstring(docstring: str | None) -> dict[str, Any]:
|
|
61
67
|
tags.extend([tag.strip() for tag in desc.split(",") if tag.strip()])
|
62
68
|
|
63
69
|
def check_for_section_header(line: str) -> tuple[bool, str | None, str]:
|
64
|
-
"""Checks if a line is a recognized section header."""
|
65
70
|
stripped_lower = line.strip().lower()
|
66
71
|
section_type: str | None = None
|
67
72
|
header_content = ""
|
@@ -79,12 +84,11 @@ def parse_docstring(docstring: str | None) -> dict[str, Any]:
|
|
79
84
|
parts = re.split(r"[:\s]+", line.strip(), maxsplit=1)
|
80
85
|
if len(parts) > 1:
|
81
86
|
header_content = parts[1].strip()
|
82
|
-
elif stripped_lower.startswith(("tags",)):
|
87
|
+
elif stripped_lower.startswith(("tags",)): # Match "tags" without colon for header content
|
83
88
|
section_type = "tags"
|
84
89
|
parts = re.split(r"[:\s]+", line.strip(), maxsplit=1)
|
85
90
|
if len(parts) > 1:
|
86
91
|
header_content = parts[1].strip()
|
87
|
-
|
88
92
|
elif stripped_lower.endswith(":") and stripped_lower[:-1] in (
|
89
93
|
"attributes",
|
90
94
|
"see also",
|
@@ -97,7 +101,6 @@ def parse_docstring(docstring: str | None) -> dict[str, Any]:
|
|
97
101
|
"warnings",
|
98
102
|
):
|
99
103
|
section_type = "other"
|
100
|
-
|
101
104
|
return section_type is not None, section_type, header_content
|
102
105
|
|
103
106
|
in_summary = True
|
@@ -113,10 +116,8 @@ def parse_docstring(docstring: str | None) -> dict[str, Any]:
|
|
113
116
|
in_summary = False
|
114
117
|
summary = " ".join(summary_lines).strip()
|
115
118
|
summary_lines = []
|
116
|
-
|
117
119
|
if not stripped_line:
|
118
120
|
continue
|
119
|
-
|
120
121
|
else:
|
121
122
|
summary_lines.append(stripped_line)
|
122
123
|
continue
|
@@ -133,27 +134,15 @@ def parse_docstring(docstring: str | None) -> dict[str, Any]:
|
|
133
134
|
current_section in ["returns", "tags", "other"]
|
134
135
|
and current_desc_lines
|
135
136
|
and original_indentation == 0
|
136
|
-
and stripped_line
|
137
|
+
and stripped_line # Ensure it's not an empty unindented line (handled by rule 2)
|
137
138
|
)
|
138
139
|
):
|
139
140
|
should_finalize_previous = True
|
140
|
-
elif (
|
141
|
-
current_section in ["args", "raises"]
|
142
|
-
and current_key is not None
|
143
|
-
or current_section in ["returns", "tags", "other"]
|
144
|
-
and current_desc_lines
|
145
|
-
):
|
146
|
-
pass
|
147
141
|
|
148
142
|
if should_finalize_previous:
|
149
143
|
finalize_current_item()
|
150
|
-
|
151
|
-
|
152
|
-
and current_key is not None
|
153
|
-
and not key_pattern.match(line)
|
154
|
-
and (not stripped_line or original_indentation == 0)
|
155
|
-
):
|
156
|
-
current_key = None
|
144
|
+
current_key = None
|
145
|
+
current_arg_type_str = None
|
157
146
|
current_desc_lines = []
|
158
147
|
|
159
148
|
if is_new_section_header:
|
@@ -169,15 +158,14 @@ def parse_docstring(docstring: str | None) -> dict[str, Any]:
|
|
169
158
|
match = key_pattern.match(line)
|
170
159
|
if match:
|
171
160
|
current_key = match.group(1)
|
172
|
-
|
173
|
-
|
161
|
+
current_arg_type_str = match.group(2).strip() if match.group(2) else None
|
162
|
+
current_desc_lines = [match.group(3).strip()] # Start new description
|
163
|
+
elif current_key is not None: # Continuation line for an existing key
|
174
164
|
current_desc_lines.append(stripped_line)
|
175
|
-
|
176
165
|
elif current_section in ["returns", "tags", "other"]:
|
177
166
|
current_desc_lines.append(stripped_line)
|
178
167
|
|
179
|
-
finalize_current_item()
|
180
|
-
|
168
|
+
finalize_current_item() # Finalize any pending item at the end of the docstring
|
181
169
|
if in_summary:
|
182
170
|
summary = " ".join(summary_lines).strip()
|
183
171
|
|
@@ -191,29 +179,23 @@ def parse_docstring(docstring: str | None) -> dict[str, Any]:
|
|
191
179
|
|
192
180
|
|
193
181
|
docstring_example = """
|
194
|
-
|
195
|
-
Returns the job ID immediately.
|
182
|
+
Creates a new product in the CRM product library to manage the collection of goods and services offered by the company.
|
196
183
|
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
params: Optional dictionary of parameters to customize the crawl.
|
201
|
-
See API docs for details.
|
202
|
-
idempotency_key: Optional unique key to prevent duplicate jobs.
|
184
|
+
Args:
|
185
|
+
associations (array): associations
|
186
|
+
properties (object): No description provided. Example: "{'description': 'Onboarding service for data product', 'name': '1 year implementation consultation', 'price': '6000.00', 'hs_sku': '191902', 'hs_cost_of_goods_sold': '600.00', 'hs_recurring_billing_period': 'P24M', 'city': 'Cambridge', 'phone': '(877) 929-0687', 'state': 'Massachusetts', 'domain': 'biglytics.net', 'industry': 'Technology', 'amount': '1500.00', 'dealname': 'Custom data integrations', 'pipeline': 'default', 'closedate': '2019-12-07T16:50:06.678Z', 'dealstage': 'presentationscheduled', 'hubspot_owner_id': '910901', 'email': 'bcooper@biglytics.net', 'company': 'Biglytics', 'website': 'biglytics.net', 'lastname': 'Cooper', 'firstname': 'Bryan', 'subject': 'troubleshoot report', 'hs_pipeline': 'support_pipeline', 'hs_pipeline_stage': 'open', 'hs_ticket_priority': 'HIGH', 'quantity': '2', 'hs_product_id': '191902', 'recurringbillingfrequency': 'monthly'}".
|
203
187
|
|
204
|
-
|
205
|
-
|
206
|
-
or a string containing an error message on failure. This description
|
207
|
-
can also span multiple lines.
|
188
|
+
Returns:
|
189
|
+
dict[str, Any]: successful operation
|
208
190
|
|
209
191
|
Raises:
|
210
|
-
|
211
|
-
|
192
|
+
HTTPError: Raised when the API request fails (e.g., non-2XX status code).
|
193
|
+
JSONDecodeError: Raised if the response body cannot be parsed as JSON.
|
212
194
|
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
195
|
+
Tags:
|
196
|
+
Basic, Another Tag
|
197
|
+
Yet Another Tag
|
198
|
+
"""
|
217
199
|
|
218
200
|
if __name__ == "__main__":
|
219
201
|
import json
|
@@ -15,17 +15,21 @@ class APISegmentBase:
|
|
15
15
|
def _get(self, url: str, params: dict = None, **kwargs):
|
16
16
|
return self.main_app_client._get(url, params=params, **kwargs)
|
17
17
|
|
18
|
-
def _post(self, url: str, data: Any = None,
|
19
|
-
return self.main_app_client._post(url, data=data,
|
18
|
+
def _post(self, url: str, data: Any = None, params: dict = None, content_type: str = None, files: Any = None, **kwargs):
|
19
|
+
return self.main_app_client._post(url, data=data, params=params, content_type=content_type, files=files, **kwargs)
|
20
20
|
|
21
|
-
def _put(self, url: str, data: Any = None,
|
22
|
-
return self.main_app_client._put(url, data=data,
|
21
|
+
def _put(self, url: str, data: Any = None, params: dict = None, content_type: str = None, files: Any = None, **kwargs):
|
22
|
+
return self.main_app_client._put(url, data=data, params=params, content_type=content_type, files=files, **kwargs)
|
23
23
|
|
24
24
|
def _patch(self, url: str, data: Any = None, params: dict = None, **kwargs):
|
25
25
|
return self.main_app_client._patch(url, data=data, params=params, **kwargs)
|
26
26
|
|
27
27
|
def _delete(self, url: str, params: dict = None, **kwargs):
|
28
28
|
return self.main_app_client._delete(url, params=params, **kwargs)
|
29
|
+
|
30
|
+
def _handle_response(self, response):
|
31
|
+
return self.main_app_client._handle_response(response)
|
32
|
+
|
29
33
|
"""
|
30
34
|
|
31
35
|
|
@@ -150,7 +154,8 @@ class MethodTransformer(ast.NodeTransformer):
|
|
150
154
|
return self.generic_visit(node)
|
151
155
|
|
152
156
|
|
153
|
-
def split_generated_app_file(input_app_file: Path, output_dir: Path):
|
157
|
+
def split_generated_app_file(input_app_file: Path, output_dir: Path, package_name: str = None):
|
158
|
+
|
154
159
|
content = input_app_file.read_text()
|
155
160
|
tree = ast.parse(content)
|
156
161
|
|
@@ -500,7 +505,7 @@ def split_generated_app_file(input_app_file: Path, output_dir: Path):
|
|
500
505
|
# Adjust import path for segments subfolder
|
501
506
|
final_main_module_imports.append(
|
502
507
|
ast.ImportFrom(
|
503
|
-
module=f".{segments_foldername}.{seg_detail['module_name']}",
|
508
|
+
module=f"universal_mcp_{package_name}.{segments_foldername}.{seg_detail['module_name']}",
|
504
509
|
names=[ast.alias(name=seg_detail["class_name"])],
|
505
510
|
level=0,
|
506
511
|
)
|
@@ -150,7 +150,7 @@ def _sanitize_identifier(name: str | None) -> str:
|
|
150
150
|
|
151
151
|
# Initial replacements for common non-alphanumeric characters
|
152
152
|
sanitized = (
|
153
|
-
name.replace("-", "_").replace(".", "_").replace("[", "_").replace("]", "").replace("$", "_").replace("/", "_")
|
153
|
+
name.replace("-", "_").replace(".", "_").replace("[", "_").replace("]", "").replace("$", "_").replace("/", "_").replace("@", "at")
|
154
154
|
)
|
155
155
|
|
156
156
|
# Remove leading underscores, but preserve a single underscore if the name (after initial replace)
|
@@ -847,8 +847,7 @@ def _generate_method_code(path, method, operation):
|
|
847
847
|
|
848
848
|
raises_section_lines = [
|
849
849
|
"Raises:",
|
850
|
-
"
|
851
|
-
" JSONDecodeError: Raised if the response body cannot be parsed as JSON.",
|
850
|
+
" HTTPStatusError: Raised when the API request fails with detailed error information including status code and response body.",
|
852
851
|
]
|
853
852
|
docstring_parts.append("\n".join(raises_section_lines))
|
854
853
|
|
@@ -969,9 +968,11 @@ def _generate_method_code(path, method, operation):
|
|
969
968
|
# --- Make HTTP Request ---
|
970
969
|
# This section generates the actual HTTP call
|
971
970
|
# using the prepared URL, query parameters, request body data, files, and content type.
|
971
|
+
# Use convenience methods that automatically handle responses and errors
|
972
972
|
|
973
973
|
if method_lower == "get":
|
974
974
|
body_lines.append(" response = self._get(url, params=query_params)")
|
975
|
+
body_lines.append(" return self._handle_response(response)")
|
975
976
|
elif method_lower == "post":
|
976
977
|
if selected_content_type == "multipart/form-data":
|
977
978
|
body_lines.append(
|
@@ -981,6 +982,7 @@ def _generate_method_code(path, method, operation):
|
|
981
982
|
body_lines.append(
|
982
983
|
f" response = self._post(url, data=request_body_data, params=query_params, content_type='{final_content_type_for_api_call}')"
|
983
984
|
)
|
985
|
+
body_lines.append(" return self._handle_response(response)")
|
984
986
|
elif method_lower == "put":
|
985
987
|
if selected_content_type == "multipart/form-data":
|
986
988
|
body_lines.append(
|
@@ -990,21 +992,16 @@ def _generate_method_code(path, method, operation):
|
|
990
992
|
body_lines.append(
|
991
993
|
f" response = self._put(url, data=request_body_data, params=query_params, content_type='{final_content_type_for_api_call}')"
|
992
994
|
)
|
995
|
+
body_lines.append(" return self._handle_response(response)")
|
993
996
|
elif method_lower == "patch":
|
994
997
|
body_lines.append(" response = self._patch(url, data=request_body_data, params=query_params)")
|
998
|
+
body_lines.append(" return self._handle_response(response)")
|
995
999
|
elif method_lower == "delete":
|
996
1000
|
body_lines.append(" response = self._delete(url, params=query_params)")
|
1001
|
+
body_lines.append(" return self._handle_response(response)")
|
997
1002
|
else:
|
998
1003
|
body_lines.append(f" response = self._{method_lower}(url, data=request_body_data, params=query_params)")
|
999
|
-
|
1000
|
-
# --- Handle Response ---
|
1001
|
-
body_lines.append(" response.raise_for_status()")
|
1002
|
-
body_lines.append(" if response.status_code == 204 or not response.content or not response.text.strip():")
|
1003
|
-
body_lines.append(" return None")
|
1004
|
-
body_lines.append(" try:")
|
1005
|
-
body_lines.append(" return response.json()")
|
1006
|
-
body_lines.append(" except ValueError:")
|
1007
|
-
body_lines.append(" return None")
|
1004
|
+
body_lines.append(" return self._handle_response(response)")
|
1008
1005
|
|
1009
1006
|
# --- Combine Signature, Docstring, and Body for Final Method Code ---
|
1010
1007
|
method_code = signature + formatted_docstring + "\n" + "\n".join(body_lines)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: universal-mcp
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.23
|
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
|
License: MIT
|
@@ -15,7 +15,7 @@ Requires-Dist: keyring>=25.6.0
|
|
15
15
|
Requires-Dist: langchain-mcp-adapters>=0.0.3
|
16
16
|
Requires-Dist: litellm>=1.30.7
|
17
17
|
Requires-Dist: loguru>=0.7.3
|
18
|
-
Requires-Dist: mcp>=1.9.
|
18
|
+
Requires-Dist: mcp>=1.9.3
|
19
19
|
Requires-Dist: posthog>=3.24.0
|
20
20
|
Requires-Dist: pydantic-settings>=2.8.1
|
21
21
|
Requires-Dist: pydantic>=2.11.1
|
@@ -1,46 +1,51 @@
|
|
1
1
|
universal_mcp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
2
|
universal_mcp/analytics.py,sha256=Dkv8mkc_2T2t5NxLSZzcr3BlmOispj1RKtbB86V1i4M,2306
|
3
|
-
universal_mcp/cli.py,sha256
|
4
|
-
universal_mcp/config.py,sha256=
|
3
|
+
universal_mcp/cli.py,sha256=Ndc1I4BtmvDCM6xNtXaO6roUvNabRlclI3tLDeSHKAw,10453
|
4
|
+
universal_mcp/config.py,sha256=9yofM9MCyBiriojFVcMqRwc9njce6lgwX5r_EfvG0NE,5185
|
5
5
|
universal_mcp/exceptions.py,sha256=-pbeZhpNieJfnSd2-WM80pU8W8mK8VHXcSjky0BHwdk,665
|
6
6
|
universal_mcp/logger.py,sha256=VmH_83efpErLEDTJqz55Dp0dioTXfGvMBLZUx5smOLc,2116
|
7
7
|
universal_mcp/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
8
8
|
universal_mcp/applications/README.md,sha256=eqbizxaTxKH2O1tyIJR2yI0Db5TQxtgPd_vbpWyCa2Y,3527
|
9
9
|
universal_mcp/applications/__init__.py,sha256=l19_sMs5766VFWU_7O2niamvvvfQOteysqylbqvjjGQ,3500
|
10
|
-
universal_mcp/applications/application.py,sha256=
|
10
|
+
universal_mcp/applications/application.py,sha256=_fcnfAeT5Lm2PJpHjK5ax8pCsxlDGJIKyRqnlCdEg_w,18758
|
11
|
+
universal_mcp/client/__main__.py,sha256=72e4WyJRiLoCtHlpIuvMZcDV98LvZclVaUGJmuCvpIE,886
|
12
|
+
universal_mcp/client/agent.py,sha256=20N0aZ55ge9PBg-R9gHxit2NSY1ppSz2ez8ZXTiO5kc,3803
|
13
|
+
universal_mcp/client/client.py,sha256=rx-meuWZuurjaTbjumpf5NO9zIh4wH9nMYUAp2uAejU,8393
|
14
|
+
universal_mcp/client/oauth.py,sha256=H7goK8FcVuITiwdXR30Am-qAWcgNylsrvt9EJHZMayA,4144
|
15
|
+
universal_mcp/client/token_store.py,sha256=eoZJbVcmkR-mAGhwk1tmDXXZnDKvjoqOVZG3nXfI8f8,1234
|
11
16
|
universal_mcp/integrations/README.md,sha256=lTAPXO2nivcBe1q7JT6PRa6v9Ns_ZersQMIdw-nmwEA,996
|
12
17
|
universal_mcp/integrations/__init__.py,sha256=X8iEzs02IlXfeafp6GMm-cOkg70QdjnlTRuFo24KEfo,916
|
13
|
-
universal_mcp/integrations/integration.py,sha256=
|
18
|
+
universal_mcp/integrations/integration.py,sha256=WtW92Awr111Vb_i_vKBvyyYvsNton3N2cX7wQ3ZXy2Y,13105
|
14
19
|
universal_mcp/servers/README.md,sha256=ytFlgp8-LO0oogMrHkMOp8SvFTwgsKgv7XhBVZGNTbM,2284
|
15
20
|
universal_mcp/servers/__init__.py,sha256=eBZCsaZjiEv6ZlRRslPKgurQxmpHLQyiXv2fTBygHnM,532
|
16
|
-
universal_mcp/servers/server.py,sha256=
|
21
|
+
universal_mcp/servers/server.py,sha256=FqAdAAXh23_ZL7ghZvXR5quAidXxQ6m-vDQrim40tag,12429
|
17
22
|
universal_mcp/stores/README.md,sha256=jrPh_ow4ESH4BDGaSafilhOVaN8oQ9IFlFW-j5Z5hLA,2465
|
18
23
|
universal_mcp/stores/__init__.py,sha256=quvuwhZnpiSLuojf0NfmBx2xpaCulv3fbKtKaSCEmuM,603
|
19
24
|
universal_mcp/stores/store.py,sha256=mxnmOVlDNrr8OKhENWDtCIfK7YeCBQcGdS6I2ogRCsU,6756
|
20
25
|
universal_mcp/tools/README.md,sha256=RuxliOFqV1ZEyeBdj3m8UKfkxAsfrxXh-b6V4ZGAk8I,2468
|
21
26
|
universal_mcp/tools/__init__.py,sha256=Fatza_R0qYWmNF1WQSfUZZKQFu5qf-16JhZzdmyx3KY,333
|
22
|
-
universal_mcp/tools/adapters.py,sha256=
|
23
|
-
universal_mcp/tools/func_metadata.py,sha256=
|
27
|
+
universal_mcp/tools/adapters.py,sha256=rnicV_WBgNe0WqVG60ms0o92BoRTRqd_C9jMMndx47c,3461
|
28
|
+
universal_mcp/tools/func_metadata.py,sha256=7kUWArtUDa2Orr7VGzpwPVfyf2LM3UFA_9arMpl7Zn8,10838
|
24
29
|
universal_mcp/tools/manager.py,sha256=ao_ovTyca8HR4uwHdL_lTWNdquxcqRx6FaLA4U1lZvQ,11242
|
25
|
-
universal_mcp/tools/tools.py,sha256=
|
30
|
+
universal_mcp/tools/tools.py,sha256=8S_KzARYbG9xbyqhZcI4Wk46tXiZcWlcAMgjChXNEI4,3698
|
26
31
|
universal_mcp/utils/__init__.py,sha256=8wi4PGWu-SrFjNJ8U7fr2iFJ1ktqlDmSKj1xYd7KSDc,41
|
27
|
-
universal_mcp/utils/agentr.py,sha256
|
32
|
+
universal_mcp/utils/agentr.py,sha256=-brwvgCZgPjvF7wPXw0QfpEsl1ekXQxmcF07-1AQMR4,3663
|
28
33
|
universal_mcp/utils/common.py,sha256=HEZC2Mhilb8DrGXQG2tboAIw1r4veGilGWjfnPF1lyA,888
|
29
|
-
universal_mcp/utils/docstring_parser.py,sha256=
|
34
|
+
universal_mcp/utils/docstring_parser.py,sha256=efEOE-ME7G5Jbbzpn7pN2xNuyu2M5zfZ1Tqu1lRB0Gk,8392
|
30
35
|
universal_mcp/utils/installation.py,sha256=ItOfBFhKOh4DLz237jgAz_Fn0uOMdrKXw0n5BaUZZNs,7286
|
31
36
|
universal_mcp/utils/singleton.py,sha256=kolHnbS9yd5C7z-tzaUAD16GgI-thqJXysNi3sZM4No,733
|
32
37
|
universal_mcp/utils/testing.py,sha256=0znYkuFi8-WjOdbwrTbNC-UpMqG3EXcGOE0wxlERh_A,1464
|
33
38
|
universal_mcp/utils/openapi/__inti__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
34
39
|
universal_mcp/utils/openapi/api_generator.py,sha256=FjtvbnWuI1P8W8wXuKLCirUtsqQ4HI_TuQrhpA4SqTs,4749
|
35
|
-
universal_mcp/utils/openapi/api_splitter.py,sha256=
|
40
|
+
universal_mcp/utils/openapi/api_splitter.py,sha256=0hoq6KMcDVA5NynDBrFjjqjDugZvaWGBdfLzvyLkFAM,20968
|
36
41
|
universal_mcp/utils/openapi/docgen.py,sha256=DNmwlhg_-TRrHa74epyErMTRjV2nutfCQ7seb_Rq5hE,21366
|
37
|
-
universal_mcp/utils/openapi/openapi.py,sha256=
|
42
|
+
universal_mcp/utils/openapi/openapi.py,sha256=8TV7L1Wm9_mi_1iy0ccf_4H39XLuZjIinBnJ56H-ggw,51197
|
38
43
|
universal_mcp/utils/openapi/preprocessor.py,sha256=PPIM3Uu8DYi3dRKdqi9thr9ufeUgkr2K08ri1BwKpoQ,60835
|
39
44
|
universal_mcp/utils/openapi/readme.py,sha256=R2Jp7DUXYNsXPDV6eFTkLiy7MXbSULUj1vHh4O_nB4c,2974
|
40
45
|
universal_mcp/utils/templates/README.md.j2,sha256=Mrm181YX-o_-WEfKs01Bi2RJy43rBiq2j6fTtbWgbTA,401
|
41
46
|
universal_mcp/utils/templates/api_client.py.j2,sha256=972Im7LNUAq3yZTfwDcgivnb-b8u6_JLKWXwoIwXXXQ,908
|
42
|
-
universal_mcp-0.1.
|
43
|
-
universal_mcp-0.1.
|
44
|
-
universal_mcp-0.1.
|
45
|
-
universal_mcp-0.1.
|
46
|
-
universal_mcp-0.1.
|
47
|
+
universal_mcp-0.1.23.dist-info/METADATA,sha256=DWTYTl64ic14aYdgvi7EMsQZLvCjF79u07v6FvQY9HA,12151
|
48
|
+
universal_mcp-0.1.23.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
49
|
+
universal_mcp-0.1.23.dist-info/entry_points.txt,sha256=QlBrVKmA2jIM0q-C-3TQMNJTTWOsOFQvgedBq2rZTS8,56
|
50
|
+
universal_mcp-0.1.23.dist-info/licenses/LICENSE,sha256=NweDZVPslBAZFzlgByF158b85GR0f5_tLQgq1NS48To,1063
|
51
|
+
universal_mcp-0.1.23.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|