tooluniverse 1.0.9__py3-none-any.whl → 1.0.10__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 (57) hide show
  1. tooluniverse/admetai_tool.py +1 -1
  2. tooluniverse/agentic_tool.py +65 -17
  3. tooluniverse/base_tool.py +19 -8
  4. tooluniverse/boltz_tool.py +1 -1
  5. tooluniverse/cache/result_cache_manager.py +167 -12
  6. tooluniverse/compose_scripts/drug_safety_analyzer.py +1 -1
  7. tooluniverse/compose_scripts/multi_agent_literature_search.py +1 -1
  8. tooluniverse/compose_scripts/output_summarizer.py +4 -4
  9. tooluniverse/compose_scripts/tool_graph_composer.py +1 -1
  10. tooluniverse/compose_scripts/tool_metadata_generator.py +1 -1
  11. tooluniverse/compose_tool.py +9 -9
  12. tooluniverse/core_tool.py +2 -2
  13. tooluniverse/ctg_tool.py +4 -4
  14. tooluniverse/custom_tool.py +1 -1
  15. tooluniverse/dataset_tool.py +2 -2
  16. tooluniverse/default_config.py +1 -1
  17. tooluniverse/enrichr_tool.py +14 -14
  18. tooluniverse/execute_function.py +520 -15
  19. tooluniverse/extended_hooks.py +4 -4
  20. tooluniverse/gene_ontology_tool.py +1 -1
  21. tooluniverse/generate_tools.py +3 -3
  22. tooluniverse/humanbase_tool.py +10 -10
  23. tooluniverse/logging_config.py +2 -2
  24. tooluniverse/mcp_client_tool.py +57 -129
  25. tooluniverse/mcp_integration.py +52 -49
  26. tooluniverse/mcp_tool_registry.py +147 -528
  27. tooluniverse/openalex_tool.py +8 -8
  28. tooluniverse/openfda_tool.py +2 -2
  29. tooluniverse/output_hook.py +15 -15
  30. tooluniverse/package_tool.py +1 -1
  31. tooluniverse/pmc_tool.py +2 -2
  32. tooluniverse/remote/boltz/boltz_mcp_server.py +1 -1
  33. tooluniverse/remote/depmap_24q2/depmap_24q2_mcp_tool.py +2 -2
  34. tooluniverse/remote/immune_compass/compass_tool.py +3 -3
  35. tooluniverse/remote/pinnacle/pinnacle_tool.py +2 -2
  36. tooluniverse/remote/transcriptformer/transcriptformer_tool.py +3 -3
  37. tooluniverse/remote/uspto_downloader/uspto_downloader_mcp_server.py +3 -3
  38. tooluniverse/remote_tool.py +4 -4
  39. tooluniverse/scripts/filter_tool_files.py +2 -2
  40. tooluniverse/smcp.py +93 -12
  41. tooluniverse/smcp_server.py +100 -20
  42. tooluniverse/space/__init__.py +46 -0
  43. tooluniverse/space/loader.py +133 -0
  44. tooluniverse/space/validator.py +353 -0
  45. tooluniverse/tool_finder_embedding.py +2 -2
  46. tooluniverse/tool_finder_keyword.py +9 -9
  47. tooluniverse/tool_finder_llm.py +6 -6
  48. tooluniverse/tools/_shared_client.py +3 -3
  49. tooluniverse/url_tool.py +1 -1
  50. tooluniverse/uspto_tool.py +1 -1
  51. tooluniverse/utils.py +10 -10
  52. {tooluniverse-1.0.9.dist-info → tooluniverse-1.0.10.dist-info}/METADATA +7 -3
  53. {tooluniverse-1.0.9.dist-info → tooluniverse-1.0.10.dist-info}/RECORD +57 -54
  54. {tooluniverse-1.0.9.dist-info → tooluniverse-1.0.10.dist-info}/WHEEL +0 -0
  55. {tooluniverse-1.0.9.dist-info → tooluniverse-1.0.10.dist-info}/entry_points.txt +0 -0
  56. {tooluniverse-1.0.9.dist-info → tooluniverse-1.0.10.dist-info}/licenses/LICENSE +0 -0
  57. {tooluniverse-1.0.9.dist-info → tooluniverse-1.0.10.dist-info}/top_level.txt +0 -0
@@ -37,6 +37,31 @@ Examples:
37
37
 
38
38
  # Start with custom hook configuration
39
39
  tooluniverse-smcp-server --hook-config-file /path/to/hook_config.json
40
+
41
+ # Load Space configuration
42
+ tooluniverse-smcp-server --load "community/proteomics-toolkit"
43
+ tooluniverse-smcp-server --load "./my-config.yaml"
44
+ """,
45
+ )
46
+
47
+ # Space configuration options
48
+ space_group = parser.add_argument_group("Space Configuration")
49
+ space_group.add_argument(
50
+ "--load",
51
+ "-l",
52
+ type=str,
53
+ metavar="CONFIG",
54
+ help="""Load space configuration (preset/workspace).
55
+
56
+ Supports multiple formats:
57
+ • HuggingFace: username/repo, hf:username/repo@v1.0.0
58
+ • Local files: ./config.yaml, /absolute/path.yaml
59
+ • HTTP URLs: https://example.com/config.yaml
60
+
61
+ Examples:
62
+ --load "community/proteomics-toolkit"
63
+ --load "./my-config.yaml"
64
+ --load "https://example.com/config.yaml"
40
65
  """,
41
66
  )
42
67
 
@@ -106,9 +131,10 @@ Examples:
106
131
 
107
132
  print()
108
133
 
109
- # Create SMCP server with hook support
134
+ # Create SMCP server with Space support
110
135
  server = SMCP(
111
136
  name=args.name,
137
+ space=args.load, # Pass Space URI directly to SMCP
112
138
  auto_expose_tools=True,
113
139
  search_enabled=True,
114
140
  max_workers=5,
@@ -157,47 +183,73 @@ def run_stdio_server():
157
183
  epilog="""
158
184
  Examples:
159
185
  # Start server with all tools using stdio transport (hooks enabled by default)
160
- tooluniverse-stdio
186
+ tooluniverse-smcp-stdio
161
187
 
162
188
  # Start with specific categories
163
- tooluniverse-stdio --categories uniprot ChEMBL opentarget
189
+ tooluniverse-smcp-stdio --categories uniprot ChEMBL opentarget
164
190
 
165
191
  # Enable hooks
166
- tooluniverse-stdio --hooks
192
+ tooluniverse-smcp-stdio --hooks
167
193
 
168
194
  # Use FileSaveHook instead of SummarizationHook
169
- tooluniverse-stdio --hook-type FileSaveHook
195
+ tooluniverse-smcp-stdio --hook-type FileSaveHook
170
196
 
171
197
  # Use custom hook configuration
172
- tooluniverse-stdio --hook-config-file /path/to/hook_config.json
198
+ tooluniverse-smcp-stdio --hook-config-file /path/to/hook_config.json
173
199
 
174
200
  # Start with categories but exclude specific tools
175
- tooluniverse-stdio --categories uniprot ChEMBL --exclude-tools "ChEMBL_get_molecule_by_chembl_id"
201
+ tooluniverse-smcp-stdio --categories uniprot ChEMBL --exclude-tools "ChEMBL_get_molecule_by_chembl_id"
176
202
 
177
203
  # Start with all tools but exclude entire categories
178
- tooluniverse-stdio --exclude-categories mcp_auto_loader_boltz mcp_auto_loader_expert_feedback
204
+ tooluniverse-smcp-stdio --exclude-categories mcp_auto_loader_boltz mcp_auto_loader_expert_feedback
179
205
 
180
206
  # Load only specific tools by name
181
- tooluniverse-stdio --include-tools "UniProt_get_entry_by_accession" "ChEMBL_get_molecule_by_chembl_id"
207
+ tooluniverse-smcp-stdio --include-tools "UniProt_get_entry_by_accession" "ChEMBL_get_molecule_by_chembl_id"
182
208
 
183
209
  # Load tools from a file
184
- tooluniverse-stdio --tools-file "/path/to/tool_names.txt"
210
+ tooluniverse-smcp-stdio --tools-file "/path/to/tool_names.txt"
185
211
 
186
212
  # Load additional config files
187
- tooluniverse-stdio --tool-config-files "custom:/path/to/custom_tools.json"
213
+ tooluniverse-smcp-stdio --tool-config-files "custom:/path/to/custom_tools.json"
188
214
 
189
215
  # Include/exclude specific tool types
190
- tooluniverse-stdio --include-tool-types "OpenTarget" "ToolFinderEmbedding"
191
- tooluniverse-stdio --exclude-tool-types "ToolFinderLLM" "Unknown"
216
+ tooluniverse-smcp-stdio --include-tool-types "OpenTarget" "ToolFinderEmbedding"
217
+ tooluniverse-smcp-stdio --exclude-tool-types "ToolFinderLLM" "Unknown"
192
218
 
193
219
  # List available categories
194
- tooluniverse-stdio --list-categories
220
+ tooluniverse-smcp-stdio --list-categories
195
221
 
196
222
  # List all available tools
197
- tooluniverse-stdio --list-tools
223
+ tooluniverse-smcp-stdio --list-tools
198
224
 
199
225
  # Start minimal server with just search tools
200
- tooluniverse-stdio --categories special_tools tool_finder
226
+ tooluniverse-smcp-stdio --categories special_tools tool_finder
227
+
228
+ # Load Space configuration
229
+ tooluniverse-smcp-stdio --load "hf:community/proteomics-toolkit"
230
+ tooluniverse-smcp-stdio --load "./my-config.yaml"
231
+ tooluniverse-smcp-stdio --load "https://example.com/config.yaml"
232
+ """,
233
+ )
234
+
235
+ # Space configuration options
236
+ space_group = parser.add_argument_group("Space Configuration")
237
+ space_group.add_argument(
238
+ "--load",
239
+ "-l",
240
+ type=str,
241
+ metavar="CONFIG",
242
+ help="""Load space configuration (preset/workspace).
243
+
244
+ Supports multiple formats:
245
+ • HuggingFace: username/repo, hf:username/repo@v1.0.0
246
+ • Local files: ./config.yaml, /absolute/path.yaml
247
+ • HTTP URLs: https://example.com/config.yaml
248
+
249
+ Examples:
250
+ --load "community/proteomics-toolkit"
251
+ --load "./my-config.yaml"
252
+ --load "https://example.com/config.yaml"
201
253
  """,
202
254
  )
203
255
 
@@ -378,11 +430,12 @@ Examples:
378
430
  total_tools = 0
379
431
  for category in sorted(tools_by_category.keys()):
380
432
  tools = sorted(tools_by_category[category])
381
- print(f"\n📁 {category} ({len(tools, file=sys.stderr)} tools):")
433
+ print(f"\n📁 {category} ({len(tools)} tools):", file=sys.stderr)
382
434
  for tool in tools[:10]: # Show first 10 tools per category
383
435
  print(f" {tool}", file=sys.stderr)
384
436
  if len(tools) > 10:
385
- print(f" ... and {len(tools, file=sys.stderr) - 10} more tools")
437
+ # Print remaining count to stderr
438
+ print(f" ... and {len(tools) - 10} more tools", file=sys.stderr)
386
439
  total_tools += len(tools)
387
440
 
388
441
  print(f"\nTotal: {total_tools} tools available", file=sys.stderr)
@@ -508,9 +561,10 @@ Examples:
508
561
  print(f"⚡ Max workers: {args.max_workers}", file=sys.stderr)
509
562
  print(file=sys.stderr)
510
563
 
511
- # Create SMCP server with hook support
564
+ # Create SMCP server with Space and tool configuration support
512
565
  server = SMCP(
513
566
  name=args.name,
567
+ space=args.load, # Pass Space URI directly to SMCP
514
568
  tool_categories=tool_categories,
515
569
  exclude_tools=exclude_tools,
516
570
  exclude_categories=exclude_categories,
@@ -588,6 +642,31 @@ Examples:
588
642
 
589
643
  # Start server for Claude Desktop (stdio transport)
590
644
  tooluniverse-smcp --transport stdio
645
+
646
+ # Load Space configuration
647
+ tooluniverse-smcp --load "community/proteomics-toolkit" --port 8000
648
+ tooluniverse-smcp --load "./my-config.yaml" --transport stdio
649
+ """,
650
+ )
651
+
652
+ # Space configuration options
653
+ space_group = parser.add_argument_group("Space Configuration")
654
+ space_group.add_argument(
655
+ "--load",
656
+ "-l",
657
+ type=str,
658
+ metavar="CONFIG",
659
+ help="""Load space configuration (preset/workspace).
660
+
661
+ Supports multiple formats:
662
+ • HuggingFace: username/repo, hf:username/repo@v1.0.0
663
+ • Local files: ./config.yaml, /absolute/path.yaml
664
+ • HTTP URLs: https://example.com/config.yaml
665
+
666
+ Examples:
667
+ --load "community/proteomics-toolkit"
668
+ --load "./my-config.yaml"
669
+ --load "https://example.com/config.yaml"
591
670
  """,
592
671
  )
593
672
 
@@ -873,9 +952,10 @@ Examples:
873
952
  print(f"⚡ Max workers: {args.max_workers}")
874
953
  print()
875
954
 
876
- # Create SMCP server with hook support
955
+ # Create SMCP server with Space and hook support
877
956
  server = SMCP(
878
957
  name=args.name,
958
+ space=args.load, # Pass Space URI directly to SMCP
879
959
  tool_categories=tool_categories,
880
960
  exclude_tools=exclude_tools,
881
961
  exclude_categories=exclude_categories,
@@ -0,0 +1,46 @@
1
+ """
2
+ ToolUniverse Space Configuration Management
3
+
4
+ This module provides tools for loading, validating, and managing ToolUniverse Space configurations.
5
+ Space allows users to define collections of tools with specific configurations,
6
+ LLM settings, and hooks for advanced scientific workflows.
7
+
8
+ Main Components:
9
+ - SpaceLoader: Loads Space configurations from various sources (HuggingFace, local files, URLs)
10
+ - SpaceValidator: Validates Space configurations using JSON Schema
11
+ - ValidationError: Exception raised when configuration validation fails
12
+
13
+ Usage:
14
+ from tooluniverse.space import SpaceLoader, validate_space_config
15
+
16
+ # Load a Space configuration
17
+ loader = SpaceLoader()
18
+ config = loader.load("hf:user/repo")
19
+
20
+ # Validate a configuration
21
+ is_valid, errors = validate_space_config(config)
22
+ """
23
+
24
+ from .loader import SpaceLoader
25
+ from .validator import (
26
+ validate_space_config,
27
+ validate_with_schema,
28
+ validate_yaml_file_with_schema,
29
+ validate_yaml_format_by_template,
30
+ validate_yaml_file,
31
+ fill_defaults,
32
+ ValidationError,
33
+ SPACE_SCHEMA,
34
+ )
35
+
36
+ __all__ = [
37
+ "SpaceLoader",
38
+ "validate_space_config",
39
+ "validate_with_schema",
40
+ "validate_yaml_file_with_schema",
41
+ "validate_yaml_format_by_template",
42
+ "validate_yaml_file",
43
+ "fill_defaults",
44
+ "ValidationError",
45
+ "SPACE_SCHEMA",
46
+ ]
@@ -0,0 +1,133 @@
1
+ """
2
+ ToolUniverse Space Configuration Loader
3
+
4
+ Simplified loader supporting HuggingFace, local files, and HTTP/HTTPS.
5
+ """
6
+
7
+ import json
8
+ from pathlib import Path
9
+ from typing import Any, Dict, Optional, Union
10
+ import yaml
11
+ import requests
12
+ from huggingface_hub import hf_hub_download
13
+
14
+ from ..utils import get_user_cache_dir
15
+ from .validator import validate_space_config
16
+
17
+
18
+ class SpaceLoader:
19
+ """Simplified loader for ToolUniverse Space configurations."""
20
+
21
+ def __init__(self, cache_dir: Optional[Union[str, Path]] = None):
22
+ """
23
+ Initialize the Space loader.
24
+
25
+ Args:
26
+ cache_dir: Directory for caching downloaded configurations
27
+ """
28
+ if cache_dir:
29
+ self.cache_dir = Path(cache_dir)
30
+ else:
31
+ self.cache_dir = Path(get_user_cache_dir()) / "spaces"
32
+
33
+ self.cache_dir.mkdir(parents=True, exist_ok=True)
34
+
35
+ def load(self, uri: str) -> Dict[str, Any]:
36
+ """
37
+ Load Space configuration from URI.
38
+
39
+ Args:
40
+ uri: Space URI (e.g., "hf:user/repo", "./config.yaml", "https://example.com/config.yaml")
41
+
42
+ Returns
43
+ Loaded configuration dictionary
44
+
45
+ Raises:
46
+ ValueError: If URI is unsupported or configuration is invalid
47
+ """
48
+ # Use URI directly (no alias resolution)
49
+ resolved_uri = uri
50
+
51
+ # Detect URI type
52
+ if resolved_uri.startswith("hf:"):
53
+ config = self._load_from_hf(resolved_uri)
54
+ elif resolved_uri.startswith(("http://", "https://")):
55
+ config = self._load_from_url(resolved_uri)
56
+ else:
57
+ config = self._load_from_file(resolved_uri)
58
+
59
+ # Validate configuration
60
+ is_valid, errors = validate_space_config(config)
61
+ if not is_valid:
62
+ error_msg = "Configuration validation failed:\n" + "\n".join(
63
+ f" - {e}" for e in errors
64
+ )
65
+ raise ValueError(error_msg)
66
+
67
+ return config
68
+
69
+ def _load_from_hf(self, uri: str) -> Dict[str, Any]:
70
+ """Load configuration from HuggingFace Hub."""
71
+ repo_id = uri[3:] # Remove 'hf:' prefix
72
+
73
+ try:
74
+ # Try to download the config file
75
+ config_path = hf_hub_download(
76
+ repo_id=repo_id,
77
+ filename="space.yaml",
78
+ cache_dir=self.cache_dir,
79
+ local_files_only=False,
80
+ )
81
+ return self._load_from_file(config_path)
82
+ except Exception as e:
83
+ # Fallback: try space.json
84
+ try:
85
+ config_path = hf_hub_download(
86
+ repo_id=repo_id,
87
+ filename="space.json",
88
+ cache_dir=self.cache_dir,
89
+ local_files_only=False,
90
+ )
91
+ return self._load_from_file(config_path)
92
+ except Exception:
93
+ raise ValueError(
94
+ f"Failed to load Space from HuggingFace {repo_id}: {e}"
95
+ )
96
+
97
+ def _load_from_url(self, uri: str) -> Dict[str, Any]:
98
+ """Load configuration from HTTP/HTTPS URL."""
99
+ try:
100
+ response = requests.get(uri, timeout=30)
101
+ response.raise_for_status()
102
+
103
+ # Try YAML first, then JSON
104
+ try:
105
+ return yaml.safe_load(response.text)
106
+ except yaml.YAMLError:
107
+ return response.json()
108
+ except Exception as e:
109
+ raise ValueError(f"Failed to load Space from URL {uri}: {e}")
110
+
111
+ def _load_from_file(self, file_path: str) -> Dict[str, Any]:
112
+ """Load configuration from local file."""
113
+ path = Path(file_path)
114
+
115
+ if not path.exists():
116
+ raise ValueError(f"Space file not found: {file_path}")
117
+
118
+ try:
119
+ with open(path, "r", encoding="utf-8") as f:
120
+ if path.suffix.lower() in [".yaml", ".yml"]:
121
+ return yaml.safe_load(f)
122
+ elif path.suffix.lower() == ".json":
123
+ return json.load(f)
124
+ else:
125
+ # Try YAML first, then JSON
126
+ try:
127
+ f.seek(0)
128
+ return yaml.safe_load(f)
129
+ except yaml.YAMLError:
130
+ f.seek(0)
131
+ return json.load(f)
132
+ except Exception as e:
133
+ raise ValueError(f"Failed to load Space from file {file_path}: {e}")