tooluniverse 0.2.0__py3-none-any.whl โ†’ 1.0.1__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 (186) 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/adverse_event_tools.json +108 -0
  23. tooluniverse/data/agentic_tools.json +1156 -0
  24. tooluniverse/data/alphafold_tools.json +87 -0
  25. tooluniverse/data/boltz_tools.json +9 -0
  26. tooluniverse/data/chembl_tools.json +16 -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 +1 -1
  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 +1 -1
  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/structural_biology_tools.json +396 -0
  66. tooluniverse/data/packages/visualization_tools.json +399 -0
  67. tooluniverse/data/pubchem_tools.json +215 -0
  68. tooluniverse/data/pubtator_tools.json +68 -0
  69. tooluniverse/data/rcsb_pdb_tools.json +1332 -0
  70. tooluniverse/data/reactome_tools.json +19 -0
  71. tooluniverse/data/semantic_scholar_tools.json +26 -0
  72. tooluniverse/data/special_tools.json +2 -25
  73. tooluniverse/data/tool_composition_tools.json +88 -0
  74. tooluniverse/data/toolfinderkeyword_defaults.json +34 -0
  75. tooluniverse/data/txagent_client_tools.json +9 -0
  76. tooluniverse/data/uniprot_tools.json +211 -0
  77. tooluniverse/data/url_fetch_tools.json +94 -0
  78. tooluniverse/data/uspto_downloader_tools.json +9 -0
  79. tooluniverse/data/uspto_tools.json +811 -0
  80. tooluniverse/data/xml_tools.json +3275 -0
  81. tooluniverse/dataset_tool.py +296 -0
  82. tooluniverse/default_config.py +165 -0
  83. tooluniverse/efo_tool.py +42 -0
  84. tooluniverse/embedding_database.py +630 -0
  85. tooluniverse/embedding_sync.py +396 -0
  86. tooluniverse/enrichr_tool.py +266 -0
  87. tooluniverse/europe_pmc_tool.py +52 -0
  88. tooluniverse/execute_function.py +1775 -95
  89. tooluniverse/extended_hooks.py +444 -0
  90. tooluniverse/gene_ontology_tool.py +194 -0
  91. tooluniverse/graphql_tool.py +158 -36
  92. tooluniverse/gwas_tool.py +358 -0
  93. tooluniverse/hpa_tool.py +1645 -0
  94. tooluniverse/humanbase_tool.py +389 -0
  95. tooluniverse/logging_config.py +254 -0
  96. tooluniverse/mcp_client_tool.py +764 -0
  97. tooluniverse/mcp_integration.py +413 -0
  98. tooluniverse/mcp_tool_registry.py +925 -0
  99. tooluniverse/medlineplus_tool.py +337 -0
  100. tooluniverse/openalex_tool.py +228 -0
  101. tooluniverse/openfda_adv_tool.py +283 -0
  102. tooluniverse/openfda_tool.py +393 -160
  103. tooluniverse/output_hook.py +1122 -0
  104. tooluniverse/package_tool.py +195 -0
  105. tooluniverse/pubchem_tool.py +158 -0
  106. tooluniverse/pubtator_tool.py +168 -0
  107. tooluniverse/rcsb_pdb_tool.py +38 -0
  108. tooluniverse/reactome_tool.py +108 -0
  109. tooluniverse/remote/boltz/boltz_mcp_server.py +50 -0
  110. tooluniverse/remote/depmap_24q2/depmap_24q2_mcp_tool.py +442 -0
  111. tooluniverse/remote/expert_feedback/human_expert_mcp_tools.py +2013 -0
  112. tooluniverse/remote/expert_feedback/simple_test.py +23 -0
  113. tooluniverse/remote/expert_feedback/start_web_interface.py +188 -0
  114. tooluniverse/remote/expert_feedback/web_only_interface.py +0 -0
  115. tooluniverse/remote/immune_compass/compass_tool.py +327 -0
  116. tooluniverse/remote/pinnacle/pinnacle_tool.py +328 -0
  117. tooluniverse/remote/transcriptformer/transcriptformer_tool.py +586 -0
  118. tooluniverse/remote/uspto_downloader/uspto_downloader_mcp_server.py +61 -0
  119. tooluniverse/remote/uspto_downloader/uspto_downloader_tool.py +120 -0
  120. tooluniverse/remote_tool.py +99 -0
  121. tooluniverse/restful_tool.py +53 -30
  122. tooluniverse/scripts/generate_tool_graph.py +408 -0
  123. tooluniverse/scripts/visualize_tool_graph.py +829 -0
  124. tooluniverse/semantic_scholar_tool.py +62 -0
  125. tooluniverse/smcp.py +2452 -0
  126. tooluniverse/smcp_server.py +975 -0
  127. tooluniverse/test/mcp_server_test.py +0 -0
  128. tooluniverse/test/test_admetai_tool.py +370 -0
  129. tooluniverse/test/test_agentic_tool.py +129 -0
  130. tooluniverse/test/test_alphafold_tool.py +71 -0
  131. tooluniverse/test/test_chem_tool.py +37 -0
  132. tooluniverse/test/test_compose_lieraturereview.py +63 -0
  133. tooluniverse/test/test_compose_tool.py +448 -0
  134. tooluniverse/test/test_dailymed.py +69 -0
  135. tooluniverse/test/test_dataset_tool.py +200 -0
  136. tooluniverse/test/test_disease_target_score.py +56 -0
  137. tooluniverse/test/test_drugbank_filter_examples.py +179 -0
  138. tooluniverse/test/test_efo.py +31 -0
  139. tooluniverse/test/test_enrichr_tool.py +21 -0
  140. tooluniverse/test/test_europe_pmc_tool.py +20 -0
  141. tooluniverse/test/test_fda_adv.py +95 -0
  142. tooluniverse/test/test_fda_drug_labeling.py +91 -0
  143. tooluniverse/test/test_gene_ontology_tools.py +66 -0
  144. tooluniverse/test/test_gwas_tool.py +139 -0
  145. tooluniverse/test/test_hpa.py +625 -0
  146. tooluniverse/test/test_humanbase_tool.py +20 -0
  147. tooluniverse/test/test_idmap_tools.py +61 -0
  148. tooluniverse/test/test_mcp_server.py +211 -0
  149. tooluniverse/test/test_mcp_tool.py +247 -0
  150. tooluniverse/test/test_medlineplus.py +220 -0
  151. tooluniverse/test/test_openalex_tool.py +32 -0
  152. tooluniverse/test/test_opentargets.py +28 -0
  153. tooluniverse/test/test_pubchem_tool.py +116 -0
  154. tooluniverse/test/test_pubtator_tool.py +37 -0
  155. tooluniverse/test/test_rcsb_pdb_tool.py +86 -0
  156. tooluniverse/test/test_reactome.py +54 -0
  157. tooluniverse/test/test_semantic_scholar_tool.py +24 -0
  158. tooluniverse/test/test_software_tools.py +147 -0
  159. tooluniverse/test/test_tool_description_optimizer.py +49 -0
  160. tooluniverse/test/test_tool_finder.py +26 -0
  161. tooluniverse/test/test_tool_finder_llm.py +252 -0
  162. tooluniverse/test/test_tools_find.py +195 -0
  163. tooluniverse/test/test_uniprot_tools.py +74 -0
  164. tooluniverse/test/test_uspto_tool.py +72 -0
  165. tooluniverse/test/test_xml_tool.py +113 -0
  166. tooluniverse/tool_finder_embedding.py +267 -0
  167. tooluniverse/tool_finder_keyword.py +693 -0
  168. tooluniverse/tool_finder_llm.py +699 -0
  169. tooluniverse/tool_graph_web_ui.py +955 -0
  170. tooluniverse/tool_registry.py +416 -0
  171. tooluniverse/uniprot_tool.py +155 -0
  172. tooluniverse/url_tool.py +253 -0
  173. tooluniverse/uspto_tool.py +240 -0
  174. tooluniverse/utils.py +369 -41
  175. tooluniverse/xml_tool.py +369 -0
  176. tooluniverse-1.0.1.dist-info/METADATA +387 -0
  177. tooluniverse-1.0.1.dist-info/RECORD +182 -0
  178. tooluniverse-1.0.1.dist-info/entry_points.txt +9 -0
  179. tooluniverse/generate_mcp_tools.py +0 -113
  180. tooluniverse/mcp_server.py +0 -3340
  181. tooluniverse-0.2.0.dist-info/METADATA +0 -139
  182. tooluniverse-0.2.0.dist-info/RECORD +0 -21
  183. tooluniverse-0.2.0.dist-info/entry_points.txt +0 -4
  184. {tooluniverse-0.2.0.dist-info โ†’ tooluniverse-1.0.1.dist-info}/WHEEL +0 -0
  185. {tooluniverse-0.2.0.dist-info โ†’ tooluniverse-1.0.1.dist-info}/licenses/LICENSE +0 -0
  186. {tooluniverse-0.2.0.dist-info โ†’ tooluniverse-1.0.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,147 @@
1
+ """
2
+ Test suite for ToolUniverse Software Package Tools
3
+
4
+ This test validates the PackageTool implementations for popular Python packages.
5
+ It follows the same pattern as other test files in the ToolUniverse test directory.
6
+
7
+ Usage:
8
+ python src/tooluniverse/test/test_software_tools.py
9
+ """
10
+
11
+ from tooluniverse.execute_function import ToolUniverse
12
+
13
+
14
+ def main():
15
+ print("๐Ÿงช Testing ToolUniverse Software Package Tools")
16
+ print("=" * 60)
17
+
18
+ # Step 1: Initialize ToolUniverse with only software tools to reduce noise
19
+ tooluni = ToolUniverse()
20
+ tooluni.load_tools(tool_type=["software"])
21
+
22
+ # Step 2: Get all software package tools
23
+ software_tools = [
24
+ name
25
+ for name in tooluni.all_tool_dict.keys()
26
+ if "get_" in name and "_info" in name
27
+ ]
28
+ print(f"๐Ÿ“ฆ Found {len(software_tools)} software package tools:")
29
+ for tool in software_tools:
30
+ package = tool.replace("get_", "").replace("_info", "").replace("_", "-")
31
+ print(f" โ€ข {package}")
32
+
33
+ # Step 3: Define test queries for the PackageTool-based software tools
34
+ test_queries = [
35
+ # Basic tests with examples
36
+ {"name": "get_numpy_info", "arguments": {"include_examples": True}},
37
+ {"name": "get_pandas_info", "arguments": {"include_examples": True}},
38
+ {"name": "get_requests_info", "arguments": {"include_examples": True}},
39
+ {"name": "get_flask_info", "arguments": {"include_examples": True}},
40
+ {"name": "get_scikit_learn_info", "arguments": {"include_examples": True}},
41
+ {"name": "get_matplotlib_info", "arguments": {"include_examples": True}},
42
+ {"name": "get_pytorch_info", "arguments": {"include_examples": True}},
43
+ # Test without examples
44
+ {"name": "get_numpy_info", "arguments": {"include_examples": False}},
45
+ # Test different source options
46
+ {"name": "get_pandas_info", "arguments": {"include_examples": False}},
47
+ {"name": "get_requests_info", "arguments": {"include_examples": True}},
48
+ {"name": "get_flask_info", "arguments": {"include_examples": False}},
49
+ ]
50
+
51
+ print("\n" + "=" * 60)
52
+
53
+ # Step 4: Run all test queries
54
+ successful_tests = 0
55
+ failed_tests = 0
56
+
57
+ for idx, query in enumerate(test_queries):
58
+ try:
59
+ package_name = (
60
+ query["name"].replace("get_", "").replace("_info", "").replace("_", "-")
61
+ )
62
+ print(f"\n[{idx+1}] Testing {package_name}...")
63
+ print(f" Tool: {query['name']}")
64
+ print(f" Args: {query['arguments']}")
65
+ print("-" * 50)
66
+
67
+ result = tooluni.run(query)
68
+
69
+ # Check if the result is successful
70
+ if (
71
+ isinstance(result, dict)
72
+ and "error" not in result
73
+ and result.get("package_name")
74
+ ):
75
+ print("โœ… SUCCESS")
76
+ successful_tests += 1
77
+
78
+ # Print key information
79
+ print(f" ๐Ÿ“ฆ Package: {result.get('package_name', 'Unknown')}")
80
+ print(
81
+ f" ๐Ÿ“‹ Description: {result.get('description', 'No description')}..."
82
+ )
83
+ print(f" ๐Ÿ”ง Import: {result.get('import_name', 'Unknown')}")
84
+ print(f" ๐Ÿ“Š Category: {result.get('category', 'Unknown')}")
85
+ print(f" ๐Ÿ’พ Source: {result.get('source', 'Unknown')}")
86
+
87
+ if result.get("installation"):
88
+ print(f" ๐Ÿ’ป Install: {result['installation'].get('pip', 'N/A')}")
89
+
90
+ if result.get("documentation"):
91
+ print(f" ๐Ÿ“š Docs: {result['documentation']}")
92
+
93
+ if query["arguments"].get("include_examples", False):
94
+ if result.get("usage_example"):
95
+ print(f" ๐Ÿ“ Example: {len(result['usage_example'])} chars")
96
+ if result.get("quick_start"):
97
+ print(f" ๐Ÿš€ Quick start: {len(result['quick_start'])} steps")
98
+
99
+ elif isinstance(result, dict) and "error" in result:
100
+ print("โŒ FAILED")
101
+ print(f" Error: {result['error']}")
102
+ failed_tests += 1
103
+
104
+ else:
105
+ print("โŒ FAILED")
106
+ print(f" Unexpected result type: {type(result)}")
107
+ failed_tests += 1
108
+
109
+ except Exception as e:
110
+ print("โŒ FAILED")
111
+ print(f" Exception: {str(e)}")
112
+ failed_tests += 1
113
+
114
+ # Step 5: Summary
115
+ print("\n" + "=" * 60)
116
+ print("๐ŸŽฏ TEST SUMMARY")
117
+ print(f"โœ… Successful: {successful_tests}")
118
+ print(f"โŒ Failed: {failed_tests}")
119
+ print(
120
+ f"๐Ÿ“Š Success Rate: {successful_tests/(successful_tests+failed_tests)*100:.1f}%"
121
+ )
122
+
123
+ print(f"\n๐Ÿ“‹ Tested {len(software_tools)} packages:")
124
+ for tool in software_tools:
125
+ pkg = tool.replace("get_", "").replace("_info", "").replace("_", "-")
126
+ print(f" โ€ข {pkg}")
127
+
128
+ print("\nโ„น๏ธ Features Tested:")
129
+ print(" - PackageTool implementation for popular Python packages")
130
+ print(" - PyPI API integration with real-time package data")
131
+ print(" - Local information fallback when API unavailable")
132
+ print(" - Different parameter combinations (include_examples, source)")
133
+ print(" - Installation instructions and documentation links")
134
+ print(" - Usage examples and quick start guides")
135
+
136
+ return successful_tests, failed_tests
137
+
138
+
139
+ if __name__ == "__main__":
140
+ successful, failed = main()
141
+
142
+ if failed == 0:
143
+ print("\n๐ŸŽ‰ ALL TESTS PASSED! Software tools are working perfectly.")
144
+ else:
145
+ print(f"\nโš ๏ธ {failed} test(s) failed. Check output above for details.")
146
+
147
+ print("\nโœจ Software package tools testing complete!")
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env python3
2
+ """Minimal test for ToolDescriptionOptimizer on FDA tool"""
3
+
4
+ import os
5
+ from tooluniverse import ToolUniverse
6
+
7
+
8
+ def main():
9
+ """Run minimal FDA tool tests."""
10
+ # Setup
11
+ tu = ToolUniverse()
12
+ tu.load_tools()
13
+ os.makedirs("temp_test", exist_ok=True)
14
+
15
+ # Get FDA tool
16
+ tool_name = "FDA_get_active_ingredient_info_by_drug_name"
17
+ tool_config = tu.get_tool_description(tool_name)
18
+
19
+ # Test 1: Multi-round optimization
20
+ result = tu.run(
21
+ {
22
+ "name": "ToolDescriptionOptimizer",
23
+ "arguments": {
24
+ "tool_config": tool_config,
25
+ "max_iterations": 3,
26
+ "satisfaction_threshold": 8.0,
27
+ },
28
+ }
29
+ )
30
+ print(
31
+ f"Multi-round optimization: {result['total_iterations']} rounds, score {result['final_quality_score']}/10"
32
+ )
33
+
34
+ # Test 2: Feedback-driven test generation
35
+ enhanced_config = tool_config.copy()
36
+ enhanced_config["_optimization_feedback"] = (
37
+ "Test with both brand and generic drug names"
38
+ )
39
+
40
+ _ = tu.run_one_function(
41
+ {"name": "TestCaseGenerator", "arguments": {"tool_config": enhanced_config}}
42
+ )
43
+
44
+ print("Feedback-driven test generation: Complete")
45
+ print("FDA tool optimization tests: PASSED")
46
+
47
+
48
+ if __name__ == "__main__":
49
+ main()
@@ -0,0 +1,26 @@
1
+ from tooluniverse import ToolUniverse
2
+
3
+ # Step 1: Initialize tool universe
4
+ tooluni = ToolUniverse()
5
+ tooluni.load_tools()
6
+
7
+ #
8
+ test_queries = [
9
+ {
10
+ "name": "Tool_Finder",
11
+ "arguments": {
12
+ "description": "a tool for finding tools related to diseases",
13
+ "limit": 10,
14
+ "return_call_result": False,
15
+ },
16
+ },
17
+ {"name": "Tool_Finder_Keyword", "arguments": {"query": "disease", "limit": 5}},
18
+ ]
19
+
20
+ for idx, query in enumerate(test_queries):
21
+ print(
22
+ f"\n[{idx+1}] Running tool: {query['name']} with arguments: {query['arguments']}"
23
+ )
24
+ result = tooluni.run(query)
25
+ print("โœ… Success. Example output snippet:")
26
+ print(result if isinstance(result, dict) else str(result))
@@ -0,0 +1,252 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Compatibility test for ToolFinderLLM - ensuring seamless replacement of original tool_finder.py
4
+
5
+ This script tests that ToolFinderLLM has the same interface and behavior as the original
6
+ ToolFinderEmbedding, making it a drop-in replacement.
7
+ """
8
+
9
+ import sys
10
+ import traceback
11
+
12
+
13
+ def test_compatibility():
14
+ """Test that ToolFinderLLM matches original tool_finder interface."""
15
+ print("๐Ÿงช Testing ToolFinderLLM compatibility...")
16
+
17
+ try:
18
+ from tooluniverse.execute_function import ToolUniverse
19
+ from tooluniverse.tool_finder_llm import ToolFinderLLM
20
+
21
+ # Initialize ToolUniverse
22
+ tooluniverse = ToolUniverse()
23
+ tooluniverse.load_tools()
24
+
25
+ # Configure LLM tool finder
26
+ config = {
27
+ "name": "ToolFinderLLM",
28
+ "type": "ToolFinderLLM",
29
+ "configs": {
30
+ "api_type": "CHATGPT",
31
+ "model_id": "gpt-4o-1120",
32
+ "temperature": 0.1,
33
+ "max_new_tokens": 2048,
34
+ "return_json": True,
35
+ },
36
+ }
37
+
38
+ llm_finder = ToolFinderLLM(config, tooluniverse)
39
+
40
+ # Test 1: Basic find_tools() method
41
+ print("โœ“ Testing find_tools() method...")
42
+ result1 = llm_finder.find_tools(
43
+ message="Find tools for drug safety analysis", rag_num=3
44
+ )
45
+ assert isinstance(result1, list), f"Expected list, got {type(result1)}"
46
+ print(f" Result type: {type(result1)} โœ“")
47
+
48
+ # Test 2: find_tools() with return_call_result=True
49
+ print("โœ“ Testing find_tools() with return_call_result=True...")
50
+ result2 = llm_finder.find_tools(
51
+ message="Find tools for gene analysis", rag_num=2, return_call_result=True
52
+ )
53
+ assert isinstance(result2, tuple), f"Expected tuple, got {type(result2)}"
54
+ assert len(result2) == 2, f"Expected tuple of length 2, got {len(result2)}"
55
+ prompts, tool_names = result2
56
+ assert isinstance(
57
+ prompts, list
58
+ ), f"Expected prompts as list, got {type(prompts)}"
59
+ assert isinstance(
60
+ tool_names, list
61
+ ), f"Expected tool_names as list, got {type(tool_names)}"
62
+ print(
63
+ f" Result: ({type(prompts)}, {type(tool_names)}) with {len(tool_names)} tools โœ“"
64
+ )
65
+
66
+ # Test 3: run() method compatibility
67
+ print("โœ“ Testing run() method...")
68
+ arguments = {
69
+ "description": "Find tools for protein analysis",
70
+ "limit": 2,
71
+ "return_call_result": False,
72
+ }
73
+ result3 = llm_finder.run(arguments)
74
+ assert isinstance(
75
+ result3, list
76
+ ), f"Expected list from run(), got {type(result3)}"
77
+ print(f" Run method result type: {type(result3)} โœ“")
78
+
79
+ # Test 4: run() with return_call_result=True
80
+ print("โœ“ Testing run() with return_call_result=True...")
81
+ arguments_with_result = {
82
+ "description": "Find tools for clinical trials",
83
+ "limit": 2,
84
+ "return_call_result": True,
85
+ }
86
+ result4 = llm_finder.run(arguments_with_result)
87
+ assert isinstance(
88
+ result4, tuple
89
+ ), f"Expected tuple from run(), got {type(result4)}"
90
+ print(f" Run method with return_call_result: {type(result4)} โœ“")
91
+
92
+ # Test 5: test with picked_tool_names (original interface)
93
+ print("โœ“ Testing find_tools() with picked_tool_names...")
94
+ test_tools = ["EuropePMC_search_articles", "PubChem_get_CID_by_compound_name"]
95
+ result5 = llm_finder.find_tools(
96
+ picked_tool_names=test_tools, return_call_result=False
97
+ )
98
+ assert isinstance(
99
+ result5, list
100
+ ), f"Expected list with picked_tool_names, got {type(result5)}"
101
+ print(f" Picked tools result type: {type(result5)} โœ“")
102
+
103
+ # Test 6: test picked_tool_names with return_call_result=True
104
+ print(
105
+ "โœ“ Testing find_tools() with picked_tool_names and return_call_result=True..."
106
+ )
107
+ result6 = llm_finder.find_tools(
108
+ picked_tool_names=test_tools, return_call_result=True
109
+ )
110
+ assert isinstance(
111
+ result6, tuple
112
+ ), f"Expected tuple with picked_tool_names, got {type(result6)}"
113
+ prompts6, names6 = result6
114
+ assert isinstance(
115
+ prompts6, list
116
+ ), f"Expected prompts as list, got {type(prompts6)}"
117
+ assert isinstance(names6, list), f"Expected names as list, got {type(names6)}"
118
+ assert len(names6) <= len(
119
+ test_tools
120
+ ), f"Expected names count <= input, got {len(names6)} > {len(test_tools)}"
121
+ print(
122
+ f" Picked tools with return_call_result: ({type(prompts6)}, {type(names6)}) โœ“"
123
+ )
124
+
125
+ print("\n๐ŸŽ‰ All compatibility tests passed!")
126
+ print("โœ… ToolFinderLLM interface matches original ToolFinderEmbedding")
127
+ return True
128
+
129
+ except ImportError as e:
130
+ print(f"โš ๏ธ ToolUniverse not available: {e}")
131
+ print("Skipping tests - this is expected in some environments")
132
+ return True
133
+
134
+ except Exception as e:
135
+ print(f"โŒ Compatibility test failed: {e}")
136
+ traceback.print_exc()
137
+ return False
138
+
139
+
140
+ def test_error_handling():
141
+ """Test error handling and edge cases."""
142
+ print("\n๐Ÿงช Testing error handling...")
143
+
144
+ try:
145
+ from tooluniverse.execute_function import ToolUniverse
146
+ from tooluniverse.tool_finder_llm import ToolFinderLLM
147
+
148
+ # Initialize ToolUniverse
149
+ tooluniverse = ToolUniverse()
150
+ tooluniverse.load_tools()
151
+
152
+ config = {
153
+ "name": "ToolFinderLLM",
154
+ "type": "ToolFinderLLM",
155
+ "configs": {
156
+ "api_type": "CHATGPT",
157
+ "model_id": "gpt-4o-1120",
158
+ "temperature": 0.1,
159
+ "max_new_tokens": 2048,
160
+ "return_json": True,
161
+ },
162
+ }
163
+
164
+ llm_finder = ToolFinderLLM(config, tooluniverse)
165
+
166
+ # Test with invalid arguments
167
+ print("โœ“ Testing error handling with None arguments...")
168
+ try:
169
+ # This should raise an assertion error
170
+ result = llm_finder.find_tools(message=None, picked_tool_names=None)
171
+ print(f" โŒ Expected AssertionError but got result: {type(result)}")
172
+ return False
173
+ except AssertionError:
174
+ print(" โœ“ AssertionError raised as expected")
175
+
176
+ # Test with empty picked_tool_names
177
+ print("โœ“ Testing with empty picked_tool_names...")
178
+ result = llm_finder.find_tools(picked_tool_names=[], return_call_result=False)
179
+ assert isinstance(
180
+ result, list
181
+ ), f"Expected list with empty picked_tool_names, got {type(result)}"
182
+ assert len(result) == 0, f"Expected empty result, got {len(result)} items"
183
+ print(" โœ“ Empty picked_tool_names handled correctly")
184
+
185
+ # Test run() with missing required arguments
186
+ print("โœ“ Testing run() with empty arguments...")
187
+ try:
188
+ result = llm_finder.run({})
189
+ print(f" โŒ Expected AssertionError but got result: {type(result)}")
190
+ return False
191
+ except AssertionError:
192
+ print(" โœ“ AssertionError raised as expected for empty arguments")
193
+
194
+ print("โœ… Error handling tests passed!")
195
+ return True
196
+
197
+ except ImportError as e:
198
+ print(f"โš ๏ธ ToolUniverse not available: {e}")
199
+ return True
200
+
201
+ except Exception as e:
202
+ print(f"โŒ Error handling test failed: {e}")
203
+ traceback.print_exc()
204
+ return False
205
+
206
+
207
+ def main():
208
+ """Run compatibility tests to ensure seamless replacement of original tool_finder."""
209
+ print("๐Ÿš€ ToolFinderLLM Compatibility Tests")
210
+ print("=" * 60)
211
+
212
+ tests = [
213
+ ("Interface Compatibility", test_compatibility),
214
+ ("Error Handling", test_error_handling),
215
+ ]
216
+
217
+ results = []
218
+ for test_name, test_func in tests:
219
+ try:
220
+ success = test_func()
221
+ results.append((test_name, success))
222
+ except Exception as e:
223
+ print(f"โŒ {test_name} crashed: {e}")
224
+ results.append((test_name, False))
225
+
226
+ print("\n" + "=" * 60)
227
+ print("๐Ÿ“Š Test Results Summary:")
228
+ print("=" * 60)
229
+
230
+ passed = 0
231
+ for test_name, success in results:
232
+ status = "โœ… PASS" if success else "โŒ FAIL"
233
+ print(f"{status} | {test_name}")
234
+ if success:
235
+ passed += 1
236
+
237
+ print(f"\n๐Ÿ Tests completed: {passed}/{len(results)} passed")
238
+
239
+ if passed == len(results):
240
+ print("๐ŸŽ‰ All compatibility tests passed!")
241
+ print(
242
+ "โœ… ToolFinderLLM can seamlessly replace the original ToolFinderEmbedding"
243
+ )
244
+ return 0
245
+ else:
246
+ print("โš ๏ธ Some compatibility tests failed.")
247
+ print("โŒ Interface modifications needed before replacement")
248
+ return 1
249
+
250
+
251
+ if __name__ == "__main__":
252
+ sys.exit(main())
@@ -0,0 +1,195 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Simplified SMCP tools/find test script
4
+
5
+ Test the new search_method parameter functionality:
6
+ - 'auto': Automatically select the best search method
7
+ - 'llm': Use LLM intelligent search
8
+ - 'embedding': Use embedding vector search
9
+ - 'keyword': Use keyword search
10
+ """
11
+
12
+ import json
13
+ import asyncio
14
+ import sys
15
+ import os
16
+
17
+ # Add the src directory to the path
18
+ sys.path.insert(0, os.path.join(os.path.dirname(__file__), "src"))
19
+
20
+
21
+ def print_test(title):
22
+ """Print test title"""
23
+ print(f"\n๐Ÿ” {title}")
24
+ print("=" * 50)
25
+
26
+
27
+ def print_result(result):
28
+ """Print results"""
29
+ if isinstance(result, dict):
30
+ # Only show key information
31
+ if "result" in result:
32
+ data = result["result"]
33
+ query = data.get("query", "unknown")
34
+ method = data.get("search_method", "unknown")
35
+ count = data.get("total_matches", 0)
36
+ print(f"โœ… Query: '{query}' | Method: {method} | Results: {count}")
37
+
38
+ # Show found tool names
39
+ if "tools" in data and data["tools"]:
40
+ print("๐Ÿ“‹ Found tools:")
41
+ for i, tool in enumerate(data["tools"][:3], 1): # Only show first 3
42
+ print(f" {i}. {tool.get('name', 'Unknown')}")
43
+ else:
44
+ print("โŒ No tools found")
45
+ elif "error" in result:
46
+ print(f"โŒ Error: {result['error']['message']}")
47
+ else:
48
+ print(f"Result: {result}")
49
+
50
+
51
+ from tooluniverse.smcp import SMCP # noqa: E402
52
+
53
+
54
+ async def test_search_methods():
55
+ """Test different search methods"""
56
+ print("๐Ÿš€ Starting SMCP search functionality tests...")
57
+
58
+ # Initialize server
59
+ print("\n๐Ÿ“ฆ Initializing SMCP server...")
60
+ server = SMCP(name="Test Server", search_enabled=True)
61
+ print(f"โœ… Server initialized, loaded {len(server._exposed_tools)} tools")
62
+
63
+ # Test query
64
+ query = "protein analysis"
65
+
66
+ # Test 1: Auto search method
67
+ print_test("Test 1: Auto search (search_method='auto')")
68
+ request = {
69
+ "jsonrpc": "2.0",
70
+ "id": "test_auto",
71
+ "method": "tools/find",
72
+ "params": {"query": query, "search_method": "auto", "limit": 3},
73
+ }
74
+ result = await server._custom_handle_request(request)
75
+ print_result(result)
76
+
77
+ # Test 2: LLM search method
78
+ print_test("Test 2: LLM intelligent search (search_method='llm')")
79
+ request = {
80
+ "jsonrpc": "2.0",
81
+ "id": "test_llm",
82
+ "method": "tools/find",
83
+ "params": {"query": query, "search_method": "llm", "limit": 3},
84
+ }
85
+ result = await server._custom_handle_request(request)
86
+ print_result(result)
87
+
88
+ # Test 3: Keyword search method
89
+ print_test("Test 3: Keyword search (search_method='keyword')")
90
+ request = {
91
+ "jsonrpc": "2.0",
92
+ "id": "test_keyword",
93
+ "method": "tools/find",
94
+ "params": {"query": "tool", "search_method": "keyword", "limit": 3},
95
+ }
96
+ result = await server._custom_handle_request(request)
97
+ print_result(result)
98
+
99
+ # Test 4: Embedding vector search method
100
+ print_test("Test 4: Embedding vector search (search_method='embedding')")
101
+ request = {
102
+ "jsonrpc": "2.0",
103
+ "id": "test_embedding",
104
+ "method": "tools/find",
105
+ "params": {"query": query, "search_method": "embedding", "limit": 3},
106
+ }
107
+ result = await server._custom_handle_request(request)
108
+ print_result(result)
109
+
110
+ # Test 5: Error handling - invalid search method
111
+ print_test("Test 5: Invalid search method (should fallback)")
112
+ request = {
113
+ "jsonrpc": "2.0",
114
+ "id": "test_invalid",
115
+ "method": "tools/find",
116
+ "params": {"query": query, "search_method": "invalid_method", "limit": 3},
117
+ }
118
+ result = await server._custom_handle_request(request)
119
+ print_result(result)
120
+
121
+ # Test 6: Error handling - missing required parameter
122
+ print_test("Test 6: Missing query parameter (should error)")
123
+ request = {
124
+ "jsonrpc": "2.0",
125
+ "id": "test_error",
126
+ "method": "tools/find",
127
+ "params": {"search_method": "auto", "limit": 3}, # Missing query
128
+ }
129
+ result = await server._custom_handle_request(request)
130
+ print_result(result)
131
+
132
+ print("\nโœ… All tests completed!")
133
+ await server.close()
134
+
135
+
136
+ def show_examples():
137
+ """Show request examples"""
138
+ print("\n๐Ÿ“„ MCP Request Examples:")
139
+
140
+ examples = [
141
+ {
142
+ "name": "Auto Search",
143
+ "request": {
144
+ "jsonrpc": "2.0",
145
+ "id": "1",
146
+ "method": "tools/find",
147
+ "params": {
148
+ "query": "protein analysis",
149
+ "search_method": "auto",
150
+ "limit": 5,
151
+ },
152
+ },
153
+ },
154
+ {
155
+ "name": "LLM Search",
156
+ "request": {
157
+ "jsonrpc": "2.0",
158
+ "id": "2",
159
+ "method": "tools/find",
160
+ "params": {
161
+ "query": "gene expression",
162
+ "search_method": "llm",
163
+ "limit": 3,
164
+ },
165
+ },
166
+ },
167
+ {
168
+ "name": "Keyword Search",
169
+ "request": {
170
+ "jsonrpc": "2.0",
171
+ "id": "3",
172
+ "method": "tools/find",
173
+ "params": {"query": "chemical", "search_method": "keyword", "limit": 3},
174
+ },
175
+ },
176
+ ]
177
+
178
+ for example in examples:
179
+ print(f"\n{example['name']}:")
180
+ print(json.dumps(example["request"], indent=2, ensure_ascii=False))
181
+
182
+
183
+ async def main():
184
+ """Main test function"""
185
+ print("๐Ÿงช Starting SMCP search method functionality tests...")
186
+
187
+ # Show examples
188
+ show_examples()
189
+
190
+ # Run tests
191
+ await test_search_methods()
192
+
193
+
194
+ if __name__ == "__main__":
195
+ asyncio.run(main())