tooluniverse 1.0.7__py3-none-any.whl → 1.0.9__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 (96) hide show
  1. tooluniverse/__init__.py +37 -14
  2. tooluniverse/admetai_tool.py +16 -5
  3. tooluniverse/base_tool.py +36 -0
  4. tooluniverse/biogrid_tool.py +118 -0
  5. tooluniverse/build_optimizer.py +87 -0
  6. tooluniverse/cache/__init__.py +3 -0
  7. tooluniverse/cache/memory_cache.py +99 -0
  8. tooluniverse/cache/result_cache_manager.py +235 -0
  9. tooluniverse/cache/sqlite_backend.py +257 -0
  10. tooluniverse/clinvar_tool.py +90 -0
  11. tooluniverse/compose_scripts/output_summarizer.py +87 -33
  12. tooluniverse/compose_tool.py +2 -2
  13. tooluniverse/custom_tool.py +28 -0
  14. tooluniverse/data/adverse_event_tools.json +97 -98
  15. tooluniverse/data/agentic_tools.json +81 -162
  16. tooluniverse/data/arxiv_tools.json +1 -4
  17. tooluniverse/data/compose_tools.json +0 -54
  18. tooluniverse/data/core_tools.json +1 -4
  19. tooluniverse/data/dataset_tools.json +7 -7
  20. tooluniverse/data/doaj_tools.json +1 -3
  21. tooluniverse/data/drug_discovery_agents.json +282 -0
  22. tooluniverse/data/europe_pmc_tools.json +1 -2
  23. tooluniverse/data/genomics_tools.json +174 -0
  24. tooluniverse/data/geo_tools.json +86 -0
  25. tooluniverse/data/literature_search_tools.json +15 -35
  26. tooluniverse/data/markitdown_tools.json +51 -0
  27. tooluniverse/data/monarch_tools.json +1 -2
  28. tooluniverse/data/openalex_tools.json +1 -5
  29. tooluniverse/data/opentarget_tools.json +8 -16
  30. tooluniverse/data/output_summarization_tools.json +23 -20
  31. tooluniverse/data/packages/bioinformatics_core_tools.json +2 -2
  32. tooluniverse/data/packages/cheminformatics_tools.json +1 -1
  33. tooluniverse/data/packages/genomics_tools.json +1 -1
  34. tooluniverse/data/packages/single_cell_tools.json +1 -1
  35. tooluniverse/data/packages/structural_biology_tools.json +1 -1
  36. tooluniverse/data/pmc_tools.json +1 -4
  37. tooluniverse/data/ppi_tools.json +139 -0
  38. tooluniverse/data/pubmed_tools.json +1 -3
  39. tooluniverse/data/semantic_scholar_tools.json +1 -2
  40. tooluniverse/data/tool_composition_tools.json +2 -4
  41. tooluniverse/data/unified_guideline_tools.json +206 -4
  42. tooluniverse/data/xml_tools.json +15 -15
  43. tooluniverse/data/zenodo_tools.json +1 -2
  44. tooluniverse/dbsnp_tool.py +71 -0
  45. tooluniverse/default_config.py +6 -0
  46. tooluniverse/ensembl_tool.py +61 -0
  47. tooluniverse/execute_function.py +235 -76
  48. tooluniverse/generate_tools.py +303 -20
  49. tooluniverse/genomics_gene_search_tool.py +56 -0
  50. tooluniverse/geo_tool.py +116 -0
  51. tooluniverse/gnomad_tool.py +63 -0
  52. tooluniverse/logging_config.py +64 -2
  53. tooluniverse/markitdown_tool.py +159 -0
  54. tooluniverse/mcp_client_tool.py +10 -5
  55. tooluniverse/molecule_2d_tool.py +9 -3
  56. tooluniverse/molecule_3d_tool.py +9 -3
  57. tooluniverse/output_hook.py +217 -150
  58. tooluniverse/smcp.py +18 -10
  59. tooluniverse/smcp_server.py +89 -199
  60. tooluniverse/string_tool.py +112 -0
  61. tooluniverse/tools/{MultiAgentLiteratureSearch.py → ADMETAnalyzerAgent.py} +18 -18
  62. tooluniverse/tools/ArXiv_search_papers.py +3 -3
  63. tooluniverse/tools/CMA_Guidelines_Search.py +52 -0
  64. tooluniverse/tools/CORE_search_papers.py +3 -3
  65. tooluniverse/tools/ClinVar_search_variants.py +52 -0
  66. tooluniverse/tools/ClinicalTrialDesignAgent.py +63 -0
  67. tooluniverse/tools/CompoundDiscoveryAgent.py +59 -0
  68. tooluniverse/tools/DOAJ_search_articles.py +2 -2
  69. tooluniverse/tools/DiseaseAnalyzerAgent.py +52 -0
  70. tooluniverse/tools/DrugInteractionAnalyzerAgent.py +52 -0
  71. tooluniverse/tools/DrugOptimizationAgent.py +63 -0
  72. tooluniverse/tools/Ensembl_lookup_gene_by_symbol.py +52 -0
  73. tooluniverse/tools/EuropePMC_search_articles.py +1 -1
  74. tooluniverse/tools/GIN_Guidelines_Search.py +52 -0
  75. tooluniverse/tools/GWAS_search_associations_by_gene.py +52 -0
  76. tooluniverse/tools/LiteratureSynthesisAgent.py +59 -0
  77. tooluniverse/tools/PMC_search_papers.py +3 -3
  78. tooluniverse/tools/PubMed_search_articles.py +2 -2
  79. tooluniverse/tools/SemanticScholar_search_papers.py +1 -1
  80. tooluniverse/tools/UCSC_get_genes_by_region.py +67 -0
  81. tooluniverse/tools/Zenodo_search_records.py +1 -1
  82. tooluniverse/tools/__init__.py +33 -3
  83. tooluniverse/tools/convert_to_markdown.py +59 -0
  84. tooluniverse/tools/dbSNP_get_variant_by_rsid.py +46 -0
  85. tooluniverse/tools/gnomAD_query_variant.py +52 -0
  86. tooluniverse/tools/openalex_literature_search.py +4 -4
  87. tooluniverse/ucsc_tool.py +60 -0
  88. tooluniverse/unified_guideline_tools.py +1175 -57
  89. tooluniverse/utils.py +51 -4
  90. tooluniverse/zenodo_tool.py +2 -1
  91. {tooluniverse-1.0.7.dist-info → tooluniverse-1.0.9.dist-info}/METADATA +10 -3
  92. {tooluniverse-1.0.7.dist-info → tooluniverse-1.0.9.dist-info}/RECORD +96 -61
  93. {tooluniverse-1.0.7.dist-info → tooluniverse-1.0.9.dist-info}/entry_points.txt +0 -3
  94. {tooluniverse-1.0.7.dist-info → tooluniverse-1.0.9.dist-info}/WHEEL +0 -0
  95. {tooluniverse-1.0.7.dist-info → tooluniverse-1.0.9.dist-info}/licenses/LICENSE +0 -0
  96. {tooluniverse-1.0.7.dist-info → tooluniverse-1.0.9.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,159 @@
1
+ """
2
+ MarkItDown Tool for ToolUniverse
3
+
4
+ Simple implementation following Microsoft's official MCP pattern.
5
+ Supports http:, https:, file:, data: URIs.
6
+ """
7
+
8
+ import os
9
+ import subprocess
10
+ import sys
11
+ import urllib.parse
12
+ import urllib.request
13
+ import tempfile
14
+ from typing import Dict, Any
15
+ from .base_tool import BaseTool
16
+ from .tool_registry import register_tool
17
+
18
+
19
+ @register_tool("MarkItDownTool")
20
+ class MarkItDownTool(BaseTool):
21
+ """MarkItDown tool for converting files to Markdown."""
22
+
23
+ def __init__(self, tool_config):
24
+ super().__init__(tool_config)
25
+ self.tool_name = tool_config.get("name", "MarkItDownTool")
26
+
27
+ def run(self, arguments: Dict[str, Any]) -> Dict[str, Any]:
28
+ """Execute MarkItDown tool."""
29
+ try:
30
+ return self._convert_to_markdown(arguments)
31
+ except Exception as e:
32
+ return {"error": str(e)}
33
+
34
+ def _convert_to_markdown(self, arguments: Dict[str, Any]) -> Dict[str, Any]:
35
+ """Convert a resource described by URI to Markdown using markitdown CLI."""
36
+ uri = arguments.get("uri")
37
+ output_path = arguments.get("output_path")
38
+ enable_plugins = arguments.get("enable_plugins", False)
39
+
40
+ if not uri:
41
+ return {"error": "URI is required"}
42
+
43
+ try:
44
+ # Parse URI
45
+ parsed_uri = urllib.parse.urlparse(uri)
46
+ scheme = parsed_uri.scheme.lower()
47
+
48
+ # Handle different URI schemes
49
+ if scheme in ["http", "https"]:
50
+ # Download from URL
51
+ temp_file = self._download_from_url(uri)
52
+ if not temp_file:
53
+ return {"error": f"Failed to download from URL: {uri}"}
54
+ input_path = temp_file
55
+ cleanup_temp = True
56
+
57
+ elif scheme == "file":
58
+ # Local file
59
+ file_path = urllib.request.url2pathname(parsed_uri.path)
60
+ if not os.path.exists(file_path):
61
+ return {"error": f"File not found: {file_path}"}
62
+ input_path = file_path
63
+ cleanup_temp = False
64
+
65
+ elif scheme == "data":
66
+ # Data URI
67
+ temp_file = self._handle_data_uri(uri)
68
+ if not temp_file:
69
+ return {"error": f"Failed to process data URI: {uri}"}
70
+ input_path = temp_file
71
+ cleanup_temp = True
72
+
73
+ else:
74
+ return {
75
+ "error": f"Unsupported URI scheme: {scheme}. Supported schemes: http, https, file, data"
76
+ }
77
+
78
+ # Build markitdown command
79
+ cmd = [sys.executable, "-m", "markitdown", input_path]
80
+ if enable_plugins:
81
+ cmd.append("--use-plugins")
82
+ if output_path:
83
+ cmd.extend(["-o", output_path])
84
+
85
+ # Execute command
86
+ result = subprocess.run(cmd, capture_output=True, text=True, timeout=60)
87
+
88
+ if result.returncode != 0:
89
+ error_msg = f"MarkItDown failed: {result.stderr}"
90
+ if cleanup_temp and os.path.exists(input_path):
91
+ os.unlink(input_path)
92
+ return {"error": error_msg}
93
+
94
+ # Get markdown content
95
+ if output_path and os.path.exists(output_path):
96
+ with open(output_path, "r", encoding="utf-8") as f:
97
+ markdown_content = f.read()
98
+ else:
99
+ markdown_content = result.stdout
100
+
101
+ # Clean up temporary file if needed
102
+ if cleanup_temp and os.path.exists(input_path):
103
+ os.unlink(input_path)
104
+
105
+ # Prepare response
106
+ response = {
107
+ "markdown_content": markdown_content,
108
+ "file_info": {
109
+ "original_uri": uri,
110
+ "uri_scheme": scheme,
111
+ "output_file": output_path if output_path else None,
112
+ },
113
+ }
114
+
115
+ # If no output_path specified, also return the content as a string for convenience
116
+ if not output_path:
117
+ response["content"] = markdown_content
118
+
119
+ return response
120
+
121
+ except Exception as e:
122
+ return {"error": f"URI processing failed: {str(e)}"}
123
+
124
+ def _download_from_url(self, url: str) -> str:
125
+ """Download content from URL to temporary file."""
126
+ try:
127
+ with urllib.request.urlopen(url, timeout=30) as response:
128
+ content = response.read()
129
+
130
+ # Create temporary file
131
+ with tempfile.NamedTemporaryFile(delete=False) as temp_file:
132
+ temp_file.write(content)
133
+ return temp_file.name
134
+ except Exception:
135
+ return None
136
+
137
+ def _handle_data_uri(self, data_uri: str) -> str:
138
+ """Handle data URI and save to temporary file."""
139
+ try:
140
+ # Parse data URI: data:[<mediatype>][;base64],<data>
141
+ if "," not in data_uri:
142
+ return None
143
+
144
+ header, data = data_uri.split(",", 1)
145
+
146
+ # Check if base64 encoded
147
+ if ";base64" in header:
148
+ import base64
149
+
150
+ content = base64.b64decode(data)
151
+ else:
152
+ content = data.encode("utf-8")
153
+
154
+ # Create temporary file
155
+ with tempfile.NamedTemporaryFile(delete=False) as temp_file:
156
+ temp_file.write(content)
157
+ return temp_file.name
158
+ except Exception:
159
+ return None
@@ -26,18 +26,23 @@ class BaseMCPClient:
26
26
 
27
27
  def __init__(self, server_url: str, transport: str = "http", timeout: int = 30):
28
28
  self.server_url = os.path.expandvars(server_url)
29
- self.transport = transport
29
+ # Normalize transport for backward compatibility: treat 'stdio' as HTTP
30
+ normalized_transport = (
31
+ transport.lower() if isinstance(transport, str) else "http"
32
+ )
33
+ if normalized_transport == "stdio":
34
+ normalized_transport = "http"
35
+ self.transport = normalized_transport
30
36
  self.timeout = timeout
31
37
  self.session = None
32
38
  self.mcp_session_id = None
33
39
  self._initialized = False
34
40
 
35
- # Validate transport
41
+ # Validate transport (accept 'stdio' via normalization above)
36
42
  supported_transports = ["http", "websocket"]
37
43
  if self.transport not in supported_transports:
38
- raise ValueError(
39
- f"Invalid transport '{self.transport}'. Supported: {supported_transports}"
40
- )
44
+ # Keep message concise to satisfy line length rules
45
+ raise ValueError("Invalid transport")
41
46
 
42
47
  async def _ensure_session(self):
43
48
  """Ensure HTTP session is available for HTTP transport"""
@@ -9,6 +9,7 @@ Supports SMILES, InChI, molecule names, and various output formats.
9
9
  import base64
10
10
  import requests
11
11
  import io
12
+ import warnings
12
13
  from typing import Any, Dict, Optional
13
14
  from .visualization_tool import VisualizationTool
14
15
  from .tool_registry import register_tool
@@ -21,9 +22,14 @@ class Molecule2DTool(VisualizationTool):
21
22
  def run(self, arguments: Dict[str, Any]) -> Dict[str, Any]:
22
23
  """Generate 2D molecular structure visualization."""
23
24
  try:
24
- from rdkit import Chem
25
- from rdkit.Chem import Draw
26
- from rdkit.Chem import rdDepictor
25
+ # Suppress RDKit RuntimeWarnings about converter registration
26
+ with warnings.catch_warnings():
27
+ warnings.filterwarnings(
28
+ "ignore", category=RuntimeWarning, module="importlib._bootstrap"
29
+ )
30
+ from rdkit import Chem
31
+ from rdkit.Chem import Draw
32
+ from rdkit.Chem import rdDepictor
27
33
 
28
34
  # Extract parameters
29
35
  smiles = arguments.get("smiles")
@@ -6,6 +6,7 @@ Tool for visualizing 3D molecular structures using RDKit and py3Dmol.
6
6
  Supports SMILES, MOL files, SDF content, and various visualization styles.
7
7
  """
8
8
 
9
+ import warnings
9
10
  from typing import Any, Dict
10
11
  from .visualization_tool import VisualizationTool
11
12
  from .tool_registry import register_tool
@@ -18,9 +19,14 @@ class Molecule3DTool(VisualizationTool):
18
19
  def run(self, arguments: Dict[str, Any]) -> Dict[str, Any]:
19
20
  """Generate 3D molecular structure visualization."""
20
21
  try:
21
- import py3Dmol
22
- from rdkit import Chem
23
- from rdkit.Chem import AllChem
22
+ # Suppress RDKit RuntimeWarnings about converter registration
23
+ with warnings.catch_warnings():
24
+ warnings.filterwarnings(
25
+ "ignore", category=RuntimeWarning, module="importlib._bootstrap"
26
+ )
27
+ import py3Dmol
28
+ from rdkit import Chem
29
+ from rdkit.Chem import AllChem
24
30
 
25
31
  # Extract parameters
26
32
  smiles = arguments.get("smiles")