tooluniverse 0.1.4__py3-none-any.whl → 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of tooluniverse might be problematic. Click here for more details.

Files changed (187) hide show
  1. tooluniverse/__init__.py +340 -4
  2. tooluniverse/admetai_tool.py +84 -0
  3. tooluniverse/agentic_tool.py +563 -0
  4. tooluniverse/alphafold_tool.py +96 -0
  5. tooluniverse/base_tool.py +129 -6
  6. tooluniverse/boltz_tool.py +207 -0
  7. tooluniverse/chem_tool.py +192 -0
  8. tooluniverse/compose_scripts/__init__.py +1 -0
  9. tooluniverse/compose_scripts/biomarker_discovery.py +293 -0
  10. tooluniverse/compose_scripts/comprehensive_drug_discovery.py +186 -0
  11. tooluniverse/compose_scripts/drug_safety_analyzer.py +89 -0
  12. tooluniverse/compose_scripts/literature_tool.py +34 -0
  13. tooluniverse/compose_scripts/output_summarizer.py +279 -0
  14. tooluniverse/compose_scripts/tool_description_optimizer.py +681 -0
  15. tooluniverse/compose_scripts/tool_discover.py +705 -0
  16. tooluniverse/compose_scripts/tool_graph_composer.py +448 -0
  17. tooluniverse/compose_tool.py +371 -0
  18. tooluniverse/ctg_tool.py +1002 -0
  19. tooluniverse/custom_tool.py +81 -0
  20. tooluniverse/dailymed_tool.py +108 -0
  21. tooluniverse/data/admetai_tools.json +155 -0
  22. tooluniverse/data/agentic_tools.json +1156 -0
  23. tooluniverse/data/alphafold_tools.json +87 -0
  24. tooluniverse/data/boltz_tools.json +9 -0
  25. tooluniverse/data/chembl_tools.json +16 -0
  26. tooluniverse/data/clait_tools.json +108 -0
  27. tooluniverse/data/clinicaltrials_gov_tools.json +326 -0
  28. tooluniverse/data/compose_tools.json +202 -0
  29. tooluniverse/data/dailymed_tools.json +70 -0
  30. tooluniverse/data/dataset_tools.json +646 -0
  31. tooluniverse/data/disease_target_score_tools.json +712 -0
  32. tooluniverse/data/efo_tools.json +17 -0
  33. tooluniverse/data/embedding_tools.json +319 -0
  34. tooluniverse/data/enrichr_tools.json +31 -0
  35. tooluniverse/data/europe_pmc_tools.json +22 -0
  36. tooluniverse/data/expert_feedback_tools.json +10 -0
  37. tooluniverse/data/fda_drug_adverse_event_tools.json +491 -0
  38. tooluniverse/data/fda_drug_labeling_tools.json +544 -168
  39. tooluniverse/data/fda_drugs_with_brand_generic_names_for_tool.py +76929 -148860
  40. tooluniverse/data/finder_tools.json +209 -0
  41. tooluniverse/data/gene_ontology_tools.json +113 -0
  42. tooluniverse/data/gwas_tools.json +1082 -0
  43. tooluniverse/data/hpa_tools.json +333 -0
  44. tooluniverse/data/humanbase_tools.json +47 -0
  45. tooluniverse/data/idmap_tools.json +74 -0
  46. tooluniverse/data/mcp_client_tools_example.json +113 -0
  47. tooluniverse/data/mcpautoloadertool_defaults.json +28 -0
  48. tooluniverse/data/medlineplus_tools.json +141 -0
  49. tooluniverse/data/monarch_tools.json +1 -1
  50. tooluniverse/data/openalex_tools.json +36 -0
  51. tooluniverse/data/opentarget_tools.json +82 -58
  52. tooluniverse/data/output_summarization_tools.json +101 -0
  53. tooluniverse/data/packages/bioinformatics_core_tools.json +1756 -0
  54. tooluniverse/data/packages/categorized_tools.txt +206 -0
  55. tooluniverse/data/packages/cheminformatics_tools.json +347 -0
  56. tooluniverse/data/packages/earth_sciences_tools.json +74 -0
  57. tooluniverse/data/packages/genomics_tools.json +776 -0
  58. tooluniverse/data/packages/image_processing_tools.json +38 -0
  59. tooluniverse/data/packages/machine_learning_tools.json +789 -0
  60. tooluniverse/data/packages/neuroscience_tools.json +62 -0
  61. tooluniverse/data/packages/original_tools.txt +0 -0
  62. tooluniverse/data/packages/physics_astronomy_tools.json +62 -0
  63. tooluniverse/data/packages/scientific_computing_tools.json +560 -0
  64. tooluniverse/data/packages/single_cell_tools.json +453 -0
  65. tooluniverse/data/packages/software_tools.json +4954 -0
  66. tooluniverse/data/packages/structural_biology_tools.json +396 -0
  67. tooluniverse/data/packages/visualization_tools.json +399 -0
  68. tooluniverse/data/pubchem_tools.json +215 -0
  69. tooluniverse/data/pubtator_tools.json +68 -0
  70. tooluniverse/data/rcsb_pdb_tools.json +1332 -0
  71. tooluniverse/data/reactome_tools.json +19 -0
  72. tooluniverse/data/semantic_scholar_tools.json +26 -0
  73. tooluniverse/data/special_tools.json +2 -25
  74. tooluniverse/data/tool_composition_tools.json +88 -0
  75. tooluniverse/data/toolfinderkeyword_defaults.json +34 -0
  76. tooluniverse/data/txagent_client_tools.json +9 -0
  77. tooluniverse/data/uniprot_tools.json +211 -0
  78. tooluniverse/data/url_fetch_tools.json +94 -0
  79. tooluniverse/data/uspto_downloader_tools.json +9 -0
  80. tooluniverse/data/uspto_tools.json +811 -0
  81. tooluniverse/data/xml_tools.json +3275 -0
  82. tooluniverse/dataset_tool.py +296 -0
  83. tooluniverse/default_config.py +165 -0
  84. tooluniverse/efo_tool.py +42 -0
  85. tooluniverse/embedding_database.py +630 -0
  86. tooluniverse/embedding_sync.py +396 -0
  87. tooluniverse/enrichr_tool.py +266 -0
  88. tooluniverse/europe_pmc_tool.py +52 -0
  89. tooluniverse/execute_function.py +1775 -95
  90. tooluniverse/extended_hooks.py +444 -0
  91. tooluniverse/gene_ontology_tool.py +194 -0
  92. tooluniverse/graphql_tool.py +158 -36
  93. tooluniverse/gwas_tool.py +358 -0
  94. tooluniverse/hpa_tool.py +1645 -0
  95. tooluniverse/humanbase_tool.py +389 -0
  96. tooluniverse/logging_config.py +254 -0
  97. tooluniverse/mcp_client_tool.py +764 -0
  98. tooluniverse/mcp_integration.py +413 -0
  99. tooluniverse/mcp_tool_registry.py +925 -0
  100. tooluniverse/medlineplus_tool.py +337 -0
  101. tooluniverse/openalex_tool.py +228 -0
  102. tooluniverse/openfda_adv_tool.py +283 -0
  103. tooluniverse/openfda_tool.py +393 -160
  104. tooluniverse/output_hook.py +1122 -0
  105. tooluniverse/package_tool.py +195 -0
  106. tooluniverse/pubchem_tool.py +158 -0
  107. tooluniverse/pubtator_tool.py +168 -0
  108. tooluniverse/rcsb_pdb_tool.py +38 -0
  109. tooluniverse/reactome_tool.py +108 -0
  110. tooluniverse/remote/boltz/boltz_mcp_server.py +50 -0
  111. tooluniverse/remote/depmap_24q2/depmap_24q2_mcp_tool.py +442 -0
  112. tooluniverse/remote/expert_feedback/human_expert_mcp_tools.py +2013 -0
  113. tooluniverse/remote/expert_feedback/simple_test.py +23 -0
  114. tooluniverse/remote/expert_feedback/start_web_interface.py +188 -0
  115. tooluniverse/remote/expert_feedback/web_only_interface.py +0 -0
  116. tooluniverse/remote/expert_feedback_mcp/human_expert_mcp_server.py +1611 -0
  117. tooluniverse/remote/expert_feedback_mcp/simple_test.py +34 -0
  118. tooluniverse/remote/expert_feedback_mcp/start_web_interface.py +91 -0
  119. tooluniverse/remote/immune_compass/compass_tool.py +327 -0
  120. tooluniverse/remote/pinnacle/pinnacle_tool.py +328 -0
  121. tooluniverse/remote/transcriptformer/transcriptformer_tool.py +586 -0
  122. tooluniverse/remote/uspto_downloader/uspto_downloader_mcp_server.py +61 -0
  123. tooluniverse/remote/uspto_downloader/uspto_downloader_tool.py +120 -0
  124. tooluniverse/remote_tool.py +99 -0
  125. tooluniverse/restful_tool.py +53 -30
  126. tooluniverse/scripts/generate_tool_graph.py +408 -0
  127. tooluniverse/scripts/visualize_tool_graph.py +829 -0
  128. tooluniverse/semantic_scholar_tool.py +62 -0
  129. tooluniverse/smcp.py +2452 -0
  130. tooluniverse/smcp_server.py +975 -0
  131. tooluniverse/test/mcp_server_test.py +0 -0
  132. tooluniverse/test/test_admetai_tool.py +370 -0
  133. tooluniverse/test/test_agentic_tool.py +129 -0
  134. tooluniverse/test/test_alphafold_tool.py +71 -0
  135. tooluniverse/test/test_chem_tool.py +37 -0
  136. tooluniverse/test/test_compose_lieraturereview.py +63 -0
  137. tooluniverse/test/test_compose_tool.py +448 -0
  138. tooluniverse/test/test_dailymed.py +69 -0
  139. tooluniverse/test/test_dataset_tool.py +200 -0
  140. tooluniverse/test/test_disease_target_score.py +56 -0
  141. tooluniverse/test/test_drugbank_filter_examples.py +179 -0
  142. tooluniverse/test/test_efo.py +31 -0
  143. tooluniverse/test/test_enrichr_tool.py +21 -0
  144. tooluniverse/test/test_europe_pmc_tool.py +20 -0
  145. tooluniverse/test/test_fda_adv.py +95 -0
  146. tooluniverse/test/test_fda_drug_labeling.py +91 -0
  147. tooluniverse/test/test_gene_ontology_tools.py +66 -0
  148. tooluniverse/test/test_gwas_tool.py +139 -0
  149. tooluniverse/test/test_hpa.py +625 -0
  150. tooluniverse/test/test_humanbase_tool.py +20 -0
  151. tooluniverse/test/test_idmap_tools.py +61 -0
  152. tooluniverse/test/test_mcp_server.py +211 -0
  153. tooluniverse/test/test_mcp_tool.py +247 -0
  154. tooluniverse/test/test_medlineplus.py +220 -0
  155. tooluniverse/test/test_openalex_tool.py +32 -0
  156. tooluniverse/test/test_opentargets.py +28 -0
  157. tooluniverse/test/test_pubchem_tool.py +116 -0
  158. tooluniverse/test/test_pubtator_tool.py +37 -0
  159. tooluniverse/test/test_rcsb_pdb_tool.py +86 -0
  160. tooluniverse/test/test_reactome.py +54 -0
  161. tooluniverse/test/test_semantic_scholar_tool.py +24 -0
  162. tooluniverse/test/test_software_tools.py +147 -0
  163. tooluniverse/test/test_tool_description_optimizer.py +49 -0
  164. tooluniverse/test/test_tool_finder.py +26 -0
  165. tooluniverse/test/test_tool_finder_llm.py +252 -0
  166. tooluniverse/test/test_tools_find.py +195 -0
  167. tooluniverse/test/test_uniprot_tools.py +74 -0
  168. tooluniverse/test/test_uspto_tool.py +72 -0
  169. tooluniverse/test/test_xml_tool.py +113 -0
  170. tooluniverse/tool_finder_embedding.py +267 -0
  171. tooluniverse/tool_finder_keyword.py +693 -0
  172. tooluniverse/tool_finder_llm.py +699 -0
  173. tooluniverse/tool_graph_web_ui.py +955 -0
  174. tooluniverse/tool_registry.py +416 -0
  175. tooluniverse/uniprot_tool.py +155 -0
  176. tooluniverse/url_tool.py +253 -0
  177. tooluniverse/uspto_tool.py +240 -0
  178. tooluniverse/utils.py +369 -41
  179. tooluniverse/xml_tool.py +369 -0
  180. tooluniverse-1.0.0.dist-info/METADATA +377 -0
  181. tooluniverse-1.0.0.dist-info/RECORD +186 -0
  182. {tooluniverse-0.1.4.dist-info → tooluniverse-1.0.0.dist-info}/WHEEL +1 -1
  183. tooluniverse-1.0.0.dist-info/entry_points.txt +9 -0
  184. tooluniverse-0.1.4.dist-info/METADATA +0 -141
  185. tooluniverse-0.1.4.dist-info/RECORD +0 -18
  186. {tooluniverse-0.1.4.dist-info → tooluniverse-1.0.0.dist-info}/licenses/LICENSE +0 -0
  187. {tooluniverse-0.1.4.dist-info → tooluniverse-1.0.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,413 @@
1
+ """
2
+ ToolUniverse MCP Integration Extensions
3
+
4
+ This module extends ToolUniverse with methods to automatically discover and load
5
+ MCP tools from remote servers, providing seamless integration between local tools
6
+ and remote MCP services.
7
+ """
8
+
9
+ from typing import List, Dict, Any
10
+
11
+
12
+ def load_mcp_tools(self, server_urls: List[str] = None, **kwargs):
13
+ """
14
+ Load MCP tools from remote servers into this ToolUniverse instance.
15
+
16
+ This method automatically discovers tools from MCP servers and registers them
17
+ as ToolUniverse tools, enabling seamless usage of remote capabilities.
18
+
19
+ Parameters:
20
+ ===========
21
+ server_urls : list of str, optional
22
+ List of MCP server URLs to load tools from. Examples:
23
+
24
+ - ["http://localhost:8001", "http://analysis-server:8002"]
25
+ - ["ws://localhost:9000"] # WebSocket MCP servers
26
+
27
+ If None, attempts to discover from local MCP tool registry.
28
+
29
+ **kwargs
30
+ Additional configuration options:
31
+
32
+ - tool_prefix (str): Prefix for loaded tool names (default: "mcp_")
33
+ - timeout (int): Connection timeout in seconds (default: 30)
34
+ - auto_register (bool): Whether to auto-register discovered tools (default: True)
35
+ - selected_tools (list): Specific tools to load from each server
36
+ - categories (list): Tool categories to filter by
37
+
38
+ Returns:
39
+ ========
40
+ dict
41
+ Summary of loaded tools with counts and any errors encountered.
42
+
43
+ Examples:
44
+ =========
45
+
46
+ Load from specific servers:
47
+ ```python
48
+ tu = ToolUniverse()
49
+
50
+ # Load tools from multiple MCP servers
51
+ result = tu.load_mcp_tools([
52
+ "http://localhost:8001", # Local analysis server
53
+ "http://ml-server:8002", # Remote ML server
54
+ "ws://realtime:9000" # WebSocket server
55
+ ])
56
+
57
+ print(f"Loaded {result['total_tools']} tools from {result['servers_connected']} servers")
58
+ ```
59
+
60
+ Load with custom configuration:
61
+ ```python
62
+ tu.load_mcp_tools(
63
+ server_urls=["http://localhost:8001"],
64
+ tool_prefix="analysis\\_",
65
+ timeout=60,
66
+ selected_tools=["protein_analysis", "drug_interaction"]
67
+ )
68
+ ```
69
+
70
+ Auto-discovery from local registry:
71
+ ```python
72
+ # If you have registered MCP tools locally, auto-discover their servers
73
+ tu.load_mcp_tools() # Uses servers from mcp_tool_registry
74
+ ```
75
+ """
76
+ # Default configuration
77
+ config = {
78
+ "tool_prefix": "mcp_",
79
+ "timeout": 30,
80
+ "auto_register": True,
81
+ "selected_tools": None,
82
+ "categories": None,
83
+ **kwargs,
84
+ }
85
+
86
+ # Get server URLs
87
+ if server_urls is None:
88
+ try:
89
+ from .mcp_tool_registry import get_mcp_tool_urls
90
+
91
+ server_urls = get_mcp_tool_urls()
92
+ except ImportError:
93
+ server_urls = []
94
+
95
+ if not server_urls:
96
+ print("📭 No MCP servers specified or discovered")
97
+ return {"total_tools": 0, "servers_connected": 0, "errors": []}
98
+
99
+ print(f"🔄 Loading MCP tools from {len(server_urls)} servers...")
100
+
101
+ results = {"total_tools": 0, "servers_connected": 0, "servers": {}, "errors": []}
102
+
103
+ for url in server_urls:
104
+ try:
105
+ result = self._load_tools_from_mcp_server(url, config)
106
+ results["servers"][url] = result
107
+ results["total_tools"] += result.get("tools_loaded", 0)
108
+ if result.get("success", False):
109
+ results["servers_connected"] += 1
110
+ except Exception as e:
111
+ error_msg = f"Failed to load from {url}: {str(e)}"
112
+ print(f"❌ {error_msg}")
113
+ results["errors"].append(error_msg)
114
+
115
+ print(
116
+ f"✅ Loaded {results['total_tools']} tools from {results['servers_connected']} servers"
117
+ )
118
+ return results
119
+
120
+
121
+ def _load_tools_from_mcp_server(
122
+ self, server_url: str, config: Dict[str, Any]
123
+ ) -> Dict[str, Any]:
124
+ """Load tools from a specific MCP server."""
125
+ try:
126
+ # Create MCPAutoLoaderTool configuration
127
+ loader_name = f"mcp_loader_{server_url.replace('://', '_').replace(':', '_').replace('/', '_')}"
128
+
129
+ loader_config = {
130
+ "name": loader_name,
131
+ "type": "MCPAutoLoaderTool",
132
+ "server_url": server_url,
133
+ "auto_register": config["auto_register"],
134
+ "tool_prefix": config["tool_prefix"],
135
+ "timeout": config["timeout"],
136
+ }
137
+
138
+ # Add selected tools filter if specified
139
+ if config["selected_tools"]:
140
+ loader_config["selected_tools"] = config["selected_tools"]
141
+
142
+ # Add the auto-loader configuration directly to the tools list
143
+ self.all_tools.append(loader_config)
144
+ self.all_tool_dict[loader_name] = loader_config
145
+
146
+ print(f"✅ Created MCP auto-loader for {server_url}")
147
+
148
+ # Try to discover tools immediately to get count (mimic _process_mcp_auto_loaders)
149
+ try:
150
+ # Import the tool registry to get the class
151
+ from .execute_function import tool_type_mappings
152
+
153
+ # Create auto loader instance (same as _process_mcp_auto_loaders)
154
+ auto_loader = tool_type_mappings["MCPAutoLoaderTool"](loader_config)
155
+
156
+ # Run auto-load process (same as _process_mcp_auto_loaders)
157
+ import asyncio
158
+ import warnings
159
+
160
+ async def _run_auto_load():
161
+ """Run auto-load with proper cleanup"""
162
+ try:
163
+ result = await auto_loader.auto_load_and_register(self)
164
+ return result
165
+ finally:
166
+ # Ensure session cleanup
167
+ await auto_loader._close_session()
168
+
169
+ # Check if we're already in an event loop
170
+ try:
171
+ asyncio.get_running_loop()
172
+ in_event_loop = True
173
+ except RuntimeError:
174
+ in_event_loop = False
175
+
176
+ if in_event_loop:
177
+ # In event loop - create task for later processing
178
+ tools_count = 0
179
+ discovery_error = (
180
+ "Cannot process in event loop - will be processed later"
181
+ )
182
+ else:
183
+ # No event loop, safe to create one (same as _process_mcp_auto_loaders)
184
+ with warnings.catch_warnings():
185
+ warnings.simplefilter("ignore", ResourceWarning)
186
+
187
+ loop = asyncio.new_event_loop()
188
+ asyncio.set_event_loop(loop)
189
+ try:
190
+ result = loop.run_until_complete(_run_auto_load())
191
+ tools_count = result.get("registered_count", 0)
192
+ discovery_error = None
193
+ finally:
194
+ loop.close()
195
+ asyncio.set_event_loop(None)
196
+
197
+ return {
198
+ "success": True,
199
+ "tools_loaded": tools_count,
200
+ "loader_name": loader_name,
201
+ "server_url": server_url,
202
+ "discovery_error": discovery_error,
203
+ }
204
+ except Exception as e:
205
+ # Auto-loader created but discovery failed
206
+ return {
207
+ "success": True,
208
+ "tools_loaded": 0,
209
+ "loader_name": loader_name,
210
+ "server_url": server_url,
211
+ "discovery_error": str(e),
212
+ }
213
+
214
+ except Exception as e:
215
+ return {"success": False, "error": str(e), "server_url": server_url}
216
+
217
+
218
+ def discover_mcp_tools(self, server_urls: List[str] = None, **kwargs) -> Dict[str, Any]:
219
+ """
220
+ Discover available tools from MCP servers without loading them.
221
+
222
+ This method connects to MCP servers to discover what tools are available
223
+ without actually registering them in ToolUniverse. Useful for exploration
224
+ and selective tool loading.
225
+
226
+ Parameters:
227
+ ===========
228
+ server_urls : list of str, optional
229
+ List of MCP server URLs to discover from
230
+ **kwargs
231
+ Additional options:
232
+ - timeout (int): Connection timeout (default: 30)
233
+ - include_schemas (bool): Include tool parameter schemas (default: True)
234
+
235
+ Returns:
236
+ ========
237
+ dict
238
+ Discovery results with tools organized by server
239
+
240
+ Examples:
241
+ =========
242
+ ```python
243
+ tu = ToolUniverse()
244
+
245
+ # Discover what's available
246
+ discovery = tu.discover_mcp_tools([
247
+ "http://localhost:8001",
248
+ "http://ml-server:8002"
249
+ ])
250
+
251
+ # Show available tools
252
+ for server, info in discovery["servers"].items():
253
+ print(f"\\n{server}:")
254
+ for tool in info.get("tools", []):
255
+ print(f" - {tool['name']}: {tool['description']}")
256
+ ```
257
+ """
258
+ if server_urls is None:
259
+ try:
260
+ from .mcp_tool_registry import get_mcp_tool_urls
261
+
262
+ server_urls = get_mcp_tool_urls()
263
+ except ImportError:
264
+ server_urls = []
265
+
266
+ if not server_urls:
267
+ return {"servers": {}, "total_tools": 0, "errors": []}
268
+
269
+ config = {"timeout": 30, "include_schemas": True, **kwargs}
270
+
271
+ print(f"🔍 Discovering tools from {len(server_urls)} MCP servers...")
272
+
273
+ results = {"servers": {}, "total_tools": 0, "errors": []}
274
+
275
+ for url in server_urls:
276
+ try:
277
+ # Create temporary discovery client
278
+ discovery_config = {
279
+ "name": f"temp_discovery_{hash(url)}",
280
+ "type": "MCPClientTool",
281
+ "server_url": url,
282
+ "timeout": config["timeout"],
283
+ }
284
+
285
+ # Register temporary tool for discovery
286
+ self.register_custom_tool(
287
+ tool_class=None, tool_type="MCPClientTool", config=discovery_config
288
+ )
289
+
290
+ # Discover tools
291
+ discovery_result = self.run_tool(
292
+ discovery_config["name"], {"operation": "list_tools"}
293
+ )
294
+
295
+ if discovery_result.get("success", False):
296
+ tools = discovery_result.get("tools", [])
297
+ results["servers"][url] = {
298
+ "tools": tools,
299
+ "count": len(tools),
300
+ "status": "success",
301
+ }
302
+ results["total_tools"] += len(tools)
303
+ print(f"✅ {url}: {len(tools)} tools discovered")
304
+ else:
305
+ error_msg = discovery_result.get("error", "Unknown error")
306
+ results["servers"][url] = {
307
+ "tools": [],
308
+ "count": 0,
309
+ "status": "error",
310
+ "error": error_msg,
311
+ }
312
+ print(f"❌ {url}: {error_msg}")
313
+
314
+ # Clean up temporary tool
315
+ if hasattr(self, "_remove_tool"):
316
+ self._remove_tool(discovery_config["name"])
317
+
318
+ except Exception as e:
319
+ error_msg = f"Discovery failed for {url}: {str(e)}"
320
+ results["errors"].append(error_msg)
321
+ results["servers"][url] = {
322
+ "tools": [],
323
+ "count": 0,
324
+ "status": "error",
325
+ "error": str(e),
326
+ }
327
+ print(f"❌ {error_msg}")
328
+
329
+ print(f"🔍 Discovery complete: {results['total_tools']} total tools found")
330
+ return results
331
+
332
+
333
+ def list_mcp_connections(self) -> Dict[str, Any]:
334
+ """
335
+ List all active MCP connections and loaded tools.
336
+
337
+ Returns:
338
+ ========
339
+ dict
340
+ Information about MCP connections, auto-loaders, and loaded tools
341
+
342
+ Examples:
343
+ =========
344
+ ```python
345
+ tu = ToolUniverse()
346
+ tu.load_mcp_tools(["http://localhost:8001"])
347
+
348
+ connections = tu.list_mcp_connections()
349
+ print(f"Active MCP connections: {len(connections['connections'])}")
350
+ ```
351
+ """
352
+ mcp_tools = {}
353
+ mcp_loaders = {}
354
+
355
+ # Find MCP-related tools in the current tool configuration
356
+ for tool_name, tool_config in getattr(self, "tool_configs", {}).items():
357
+ tool_type = tool_config.get("type", "")
358
+
359
+ if tool_type == "MCPAutoLoaderTool":
360
+ server_url = tool_config.get("server_url", "")
361
+ mcp_loaders[tool_name] = {
362
+ "server_url": server_url,
363
+ "tool_prefix": tool_config.get("tool_prefix", "mcp_"),
364
+ "auto_register": tool_config.get("auto_register", True),
365
+ "config": tool_config,
366
+ }
367
+ elif tool_type in ["MCPClientTool", "MCPProxyTool"]:
368
+ server_url = tool_config.get("server_url", "")
369
+ mcp_tools[tool_name] = {
370
+ "type": tool_type,
371
+ "server_url": server_url,
372
+ "config": tool_config,
373
+ }
374
+
375
+ return {
376
+ "connections": {"auto_loaders": mcp_loaders, "direct_tools": mcp_tools},
377
+ "total_mcp_tools": len(mcp_tools) + len(mcp_loaders),
378
+ "servers": list(
379
+ set(
380
+ [config["server_url"] for config in mcp_loaders.values()]
381
+ + [config["server_url"] for config in mcp_tools.values()]
382
+ )
383
+ ),
384
+ }
385
+
386
+
387
+ # Monkey patch methods into ToolUniverse
388
+ def _patch_tooluniverse():
389
+ """Add MCP integration methods to ToolUniverse class."""
390
+ try:
391
+ from .execute_function import ToolUniverse
392
+
393
+ # Add methods to ToolUniverse if they don't exist
394
+ if not hasattr(ToolUniverse, "load_mcp_tools"):
395
+ ToolUniverse.load_mcp_tools = load_mcp_tools
396
+
397
+ if not hasattr(ToolUniverse, "discover_mcp_tools"):
398
+ ToolUniverse.discover_mcp_tools = discover_mcp_tools
399
+
400
+ if not hasattr(ToolUniverse, "list_mcp_connections"):
401
+ ToolUniverse.list_mcp_connections = list_mcp_connections
402
+
403
+ if not hasattr(ToolUniverse, "_load_tools_from_mcp_server"):
404
+ ToolUniverse._load_tools_from_mcp_server = _load_tools_from_mcp_server
405
+
406
+ # print("✅ ToolUniverse MCP integration methods added")
407
+
408
+ except ImportError as e:
409
+ print(f"⚠️ Could not patch ToolUniverse: {e}")
410
+
411
+
412
+ # Auto-patch when module is imported
413
+ _patch_tooluniverse()