tooluniverse 0.2.0__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.
- tooluniverse/__init__.py +340 -4
- tooluniverse/admetai_tool.py +84 -0
- tooluniverse/agentic_tool.py +563 -0
- tooluniverse/alphafold_tool.py +96 -0
- tooluniverse/base_tool.py +129 -6
- tooluniverse/boltz_tool.py +207 -0
- tooluniverse/chem_tool.py +192 -0
- tooluniverse/compose_scripts/__init__.py +1 -0
- tooluniverse/compose_scripts/biomarker_discovery.py +293 -0
- tooluniverse/compose_scripts/comprehensive_drug_discovery.py +186 -0
- tooluniverse/compose_scripts/drug_safety_analyzer.py +89 -0
- tooluniverse/compose_scripts/literature_tool.py +34 -0
- tooluniverse/compose_scripts/output_summarizer.py +279 -0
- tooluniverse/compose_scripts/tool_description_optimizer.py +681 -0
- tooluniverse/compose_scripts/tool_discover.py +705 -0
- tooluniverse/compose_scripts/tool_graph_composer.py +448 -0
- tooluniverse/compose_tool.py +371 -0
- tooluniverse/ctg_tool.py +1002 -0
- tooluniverse/custom_tool.py +81 -0
- tooluniverse/dailymed_tool.py +108 -0
- tooluniverse/data/admetai_tools.json +155 -0
- tooluniverse/data/agentic_tools.json +1156 -0
- tooluniverse/data/alphafold_tools.json +87 -0
- tooluniverse/data/boltz_tools.json +9 -0
- tooluniverse/data/chembl_tools.json +16 -0
- tooluniverse/data/clait_tools.json +108 -0
- tooluniverse/data/clinicaltrials_gov_tools.json +326 -0
- tooluniverse/data/compose_tools.json +202 -0
- tooluniverse/data/dailymed_tools.json +70 -0
- tooluniverse/data/dataset_tools.json +646 -0
- tooluniverse/data/disease_target_score_tools.json +712 -0
- tooluniverse/data/efo_tools.json +17 -0
- tooluniverse/data/embedding_tools.json +319 -0
- tooluniverse/data/enrichr_tools.json +31 -0
- tooluniverse/data/europe_pmc_tools.json +22 -0
- tooluniverse/data/expert_feedback_tools.json +10 -0
- tooluniverse/data/fda_drug_adverse_event_tools.json +491 -0
- tooluniverse/data/fda_drug_labeling_tools.json +1 -1
- tooluniverse/data/fda_drugs_with_brand_generic_names_for_tool.py +76929 -148860
- tooluniverse/data/finder_tools.json +209 -0
- tooluniverse/data/gene_ontology_tools.json +113 -0
- tooluniverse/data/gwas_tools.json +1082 -0
- tooluniverse/data/hpa_tools.json +333 -0
- tooluniverse/data/humanbase_tools.json +47 -0
- tooluniverse/data/idmap_tools.json +74 -0
- tooluniverse/data/mcp_client_tools_example.json +113 -0
- tooluniverse/data/mcpautoloadertool_defaults.json +28 -0
- tooluniverse/data/medlineplus_tools.json +141 -0
- tooluniverse/data/monarch_tools.json +1 -1
- tooluniverse/data/openalex_tools.json +36 -0
- tooluniverse/data/opentarget_tools.json +1 -1
- tooluniverse/data/output_summarization_tools.json +101 -0
- tooluniverse/data/packages/bioinformatics_core_tools.json +1756 -0
- tooluniverse/data/packages/categorized_tools.txt +206 -0
- tooluniverse/data/packages/cheminformatics_tools.json +347 -0
- tooluniverse/data/packages/earth_sciences_tools.json +74 -0
- tooluniverse/data/packages/genomics_tools.json +776 -0
- tooluniverse/data/packages/image_processing_tools.json +38 -0
- tooluniverse/data/packages/machine_learning_tools.json +789 -0
- tooluniverse/data/packages/neuroscience_tools.json +62 -0
- tooluniverse/data/packages/original_tools.txt +0 -0
- tooluniverse/data/packages/physics_astronomy_tools.json +62 -0
- tooluniverse/data/packages/scientific_computing_tools.json +560 -0
- tooluniverse/data/packages/single_cell_tools.json +453 -0
- tooluniverse/data/packages/software_tools.json +4954 -0
- tooluniverse/data/packages/structural_biology_tools.json +396 -0
- tooluniverse/data/packages/visualization_tools.json +399 -0
- tooluniverse/data/pubchem_tools.json +215 -0
- tooluniverse/data/pubtator_tools.json +68 -0
- tooluniverse/data/rcsb_pdb_tools.json +1332 -0
- tooluniverse/data/reactome_tools.json +19 -0
- tooluniverse/data/semantic_scholar_tools.json +26 -0
- tooluniverse/data/special_tools.json +2 -25
- tooluniverse/data/tool_composition_tools.json +88 -0
- tooluniverse/data/toolfinderkeyword_defaults.json +34 -0
- tooluniverse/data/txagent_client_tools.json +9 -0
- tooluniverse/data/uniprot_tools.json +211 -0
- tooluniverse/data/url_fetch_tools.json +94 -0
- tooluniverse/data/uspto_downloader_tools.json +9 -0
- tooluniverse/data/uspto_tools.json +811 -0
- tooluniverse/data/xml_tools.json +3275 -0
- tooluniverse/dataset_tool.py +296 -0
- tooluniverse/default_config.py +165 -0
- tooluniverse/efo_tool.py +42 -0
- tooluniverse/embedding_database.py +630 -0
- tooluniverse/embedding_sync.py +396 -0
- tooluniverse/enrichr_tool.py +266 -0
- tooluniverse/europe_pmc_tool.py +52 -0
- tooluniverse/execute_function.py +1775 -95
- tooluniverse/extended_hooks.py +444 -0
- tooluniverse/gene_ontology_tool.py +194 -0
- tooluniverse/graphql_tool.py +158 -36
- tooluniverse/gwas_tool.py +358 -0
- tooluniverse/hpa_tool.py +1645 -0
- tooluniverse/humanbase_tool.py +389 -0
- tooluniverse/logging_config.py +254 -0
- tooluniverse/mcp_client_tool.py +764 -0
- tooluniverse/mcp_integration.py +413 -0
- tooluniverse/mcp_tool_registry.py +925 -0
- tooluniverse/medlineplus_tool.py +337 -0
- tooluniverse/openalex_tool.py +228 -0
- tooluniverse/openfda_adv_tool.py +283 -0
- tooluniverse/openfda_tool.py +393 -160
- tooluniverse/output_hook.py +1122 -0
- tooluniverse/package_tool.py +195 -0
- tooluniverse/pubchem_tool.py +158 -0
- tooluniverse/pubtator_tool.py +168 -0
- tooluniverse/rcsb_pdb_tool.py +38 -0
- tooluniverse/reactome_tool.py +108 -0
- tooluniverse/remote/boltz/boltz_mcp_server.py +50 -0
- tooluniverse/remote/depmap_24q2/depmap_24q2_mcp_tool.py +442 -0
- tooluniverse/remote/expert_feedback/human_expert_mcp_tools.py +2013 -0
- tooluniverse/remote/expert_feedback/simple_test.py +23 -0
- tooluniverse/remote/expert_feedback/start_web_interface.py +188 -0
- tooluniverse/remote/expert_feedback/web_only_interface.py +0 -0
- tooluniverse/remote/expert_feedback_mcp/human_expert_mcp_server.py +1611 -0
- tooluniverse/remote/expert_feedback_mcp/simple_test.py +34 -0
- tooluniverse/remote/expert_feedback_mcp/start_web_interface.py +91 -0
- tooluniverse/remote/immune_compass/compass_tool.py +327 -0
- tooluniverse/remote/pinnacle/pinnacle_tool.py +328 -0
- tooluniverse/remote/transcriptformer/transcriptformer_tool.py +586 -0
- tooluniverse/remote/uspto_downloader/uspto_downloader_mcp_server.py +61 -0
- tooluniverse/remote/uspto_downloader/uspto_downloader_tool.py +120 -0
- tooluniverse/remote_tool.py +99 -0
- tooluniverse/restful_tool.py +53 -30
- tooluniverse/scripts/generate_tool_graph.py +408 -0
- tooluniverse/scripts/visualize_tool_graph.py +829 -0
- tooluniverse/semantic_scholar_tool.py +62 -0
- tooluniverse/smcp.py +2452 -0
- tooluniverse/smcp_server.py +975 -0
- tooluniverse/test/mcp_server_test.py +0 -0
- tooluniverse/test/test_admetai_tool.py +370 -0
- tooluniverse/test/test_agentic_tool.py +129 -0
- tooluniverse/test/test_alphafold_tool.py +71 -0
- tooluniverse/test/test_chem_tool.py +37 -0
- tooluniverse/test/test_compose_lieraturereview.py +63 -0
- tooluniverse/test/test_compose_tool.py +448 -0
- tooluniverse/test/test_dailymed.py +69 -0
- tooluniverse/test/test_dataset_tool.py +200 -0
- tooluniverse/test/test_disease_target_score.py +56 -0
- tooluniverse/test/test_drugbank_filter_examples.py +179 -0
- tooluniverse/test/test_efo.py +31 -0
- tooluniverse/test/test_enrichr_tool.py +21 -0
- tooluniverse/test/test_europe_pmc_tool.py +20 -0
- tooluniverse/test/test_fda_adv.py +95 -0
- tooluniverse/test/test_fda_drug_labeling.py +91 -0
- tooluniverse/test/test_gene_ontology_tools.py +66 -0
- tooluniverse/test/test_gwas_tool.py +139 -0
- tooluniverse/test/test_hpa.py +625 -0
- tooluniverse/test/test_humanbase_tool.py +20 -0
- tooluniverse/test/test_idmap_tools.py +61 -0
- tooluniverse/test/test_mcp_server.py +211 -0
- tooluniverse/test/test_mcp_tool.py +247 -0
- tooluniverse/test/test_medlineplus.py +220 -0
- tooluniverse/test/test_openalex_tool.py +32 -0
- tooluniverse/test/test_opentargets.py +28 -0
- tooluniverse/test/test_pubchem_tool.py +116 -0
- tooluniverse/test/test_pubtator_tool.py +37 -0
- tooluniverse/test/test_rcsb_pdb_tool.py +86 -0
- tooluniverse/test/test_reactome.py +54 -0
- tooluniverse/test/test_semantic_scholar_tool.py +24 -0
- tooluniverse/test/test_software_tools.py +147 -0
- tooluniverse/test/test_tool_description_optimizer.py +49 -0
- tooluniverse/test/test_tool_finder.py +26 -0
- tooluniverse/test/test_tool_finder_llm.py +252 -0
- tooluniverse/test/test_tools_find.py +195 -0
- tooluniverse/test/test_uniprot_tools.py +74 -0
- tooluniverse/test/test_uspto_tool.py +72 -0
- tooluniverse/test/test_xml_tool.py +113 -0
- tooluniverse/tool_finder_embedding.py +267 -0
- tooluniverse/tool_finder_keyword.py +693 -0
- tooluniverse/tool_finder_llm.py +699 -0
- tooluniverse/tool_graph_web_ui.py +955 -0
- tooluniverse/tool_registry.py +416 -0
- tooluniverse/uniprot_tool.py +155 -0
- tooluniverse/url_tool.py +253 -0
- tooluniverse/uspto_tool.py +240 -0
- tooluniverse/utils.py +369 -41
- tooluniverse/xml_tool.py +369 -0
- tooluniverse-1.0.0.dist-info/METADATA +377 -0
- tooluniverse-1.0.0.dist-info/RECORD +186 -0
- tooluniverse-1.0.0.dist-info/entry_points.txt +9 -0
- tooluniverse/generate_mcp_tools.py +0 -113
- tooluniverse/mcp_server.py +0 -3340
- tooluniverse-0.2.0.dist-info/METADATA +0 -139
- tooluniverse-0.2.0.dist-info/RECORD +0 -21
- tooluniverse-0.2.0.dist-info/entry_points.txt +0 -4
- {tooluniverse-0.2.0.dist-info ā tooluniverse-1.0.0.dist-info}/WHEEL +0 -0
- {tooluniverse-0.2.0.dist-info ā tooluniverse-1.0.0.dist-info}/licenses/LICENSE +0 -0
- {tooluniverse-0.2.0.dist-info ā tooluniverse-1.0.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,975 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
SMCP Server Entry Point
|
|
4
|
+
|
|
5
|
+
This module provides the command-line entry point for running the SMCP (Scientific Model Context Protocol) server.
|
|
6
|
+
It creates a minimal SMCP server that exposes all ToolUniverse tools as MCP tools.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import argparse
|
|
10
|
+
import sys
|
|
11
|
+
from .smcp import SMCP
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def run_http_server():
|
|
15
|
+
"""
|
|
16
|
+
Run SMCP server with streamable-http transport on localhost:8000
|
|
17
|
+
|
|
18
|
+
This function provides compatibility with the original MCP server's run_server function.
|
|
19
|
+
"""
|
|
20
|
+
parser = argparse.ArgumentParser(
|
|
21
|
+
description="Start SMCP (Scientific Model Context Protocol) Server with HTTP transport",
|
|
22
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
23
|
+
epilog="""
|
|
24
|
+
Examples:
|
|
25
|
+
# Start server with all tools using HTTP transport
|
|
26
|
+
tooluniverse-smcp-server
|
|
27
|
+
|
|
28
|
+
# Start with specific categories
|
|
29
|
+
tooluniverse-smcp-server --categories uniprot ChEMBL opentarget
|
|
30
|
+
|
|
31
|
+
# Start with hooks enabled
|
|
32
|
+
tooluniverse-smcp-server --hooks-enabled
|
|
33
|
+
|
|
34
|
+
# Start with specific hook type
|
|
35
|
+
tooluniverse-smcp-server --hook-type SummarizationHook
|
|
36
|
+
|
|
37
|
+
# Start with custom hook configuration
|
|
38
|
+
tooluniverse-smcp-server --hook-config-file /path/to/hook_config.json
|
|
39
|
+
""",
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
# Hook configuration options
|
|
43
|
+
hook_group = parser.add_argument_group("Hook Configuration")
|
|
44
|
+
hook_group.add_argument(
|
|
45
|
+
"--hooks-enabled",
|
|
46
|
+
action="store_true",
|
|
47
|
+
help="Enable output processing hooks (default: False)",
|
|
48
|
+
)
|
|
49
|
+
hook_group.add_argument(
|
|
50
|
+
"--hook-type",
|
|
51
|
+
choices=["SummarizationHook", "FileSaveHook"],
|
|
52
|
+
help="Simple hook type selection (SummarizationHook or FileSaveHook)",
|
|
53
|
+
)
|
|
54
|
+
hook_group.add_argument(
|
|
55
|
+
"--hook-config-file",
|
|
56
|
+
type=str,
|
|
57
|
+
help="Path to custom hook configuration JSON file",
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
# Server configuration options
|
|
61
|
+
server_group = parser.add_argument_group("Server Configuration")
|
|
62
|
+
server_group.add_argument(
|
|
63
|
+
"--host", default="127.0.0.1", help="Server host address (default: 127.0.0.1)"
|
|
64
|
+
)
|
|
65
|
+
server_group.add_argument(
|
|
66
|
+
"--port", type=int, default=8000, help="Server port (default: 8000)"
|
|
67
|
+
)
|
|
68
|
+
server_group.add_argument(
|
|
69
|
+
"--name",
|
|
70
|
+
default="ToolUniverse SMCP Server",
|
|
71
|
+
help="Server name (default: ToolUniverse SMCP Server)",
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
args = parser.parse_args()
|
|
75
|
+
|
|
76
|
+
try:
|
|
77
|
+
print("š Starting ToolUniverse SMCP Server...")
|
|
78
|
+
print("š” Transport: streamable-http")
|
|
79
|
+
print(f"š Address: http://{args.host}:{args.port}")
|
|
80
|
+
print(f"š·ļø Name: {args.name}")
|
|
81
|
+
|
|
82
|
+
# Load hook configuration if specified
|
|
83
|
+
hook_config = None
|
|
84
|
+
if args.hook_config_file:
|
|
85
|
+
import json
|
|
86
|
+
|
|
87
|
+
with open(args.hook_config_file, "r") as f:
|
|
88
|
+
hook_config = json.load(f)
|
|
89
|
+
print(f"š Hook config loaded from: {args.hook_config_file}")
|
|
90
|
+
|
|
91
|
+
# Determine hook settings
|
|
92
|
+
hooks_enabled = (
|
|
93
|
+
args.hooks_enabled or args.hook_type is not None or hook_config is not None
|
|
94
|
+
)
|
|
95
|
+
if hooks_enabled:
|
|
96
|
+
if args.hook_type:
|
|
97
|
+
print(f"š Hooks enabled: {args.hook_type}")
|
|
98
|
+
elif hook_config:
|
|
99
|
+
hook_count = len(hook_config.get("hooks", []))
|
|
100
|
+
print(f"š Hooks enabled: {hook_count} custom hooks")
|
|
101
|
+
else:
|
|
102
|
+
print("š Hooks enabled: default configuration")
|
|
103
|
+
else:
|
|
104
|
+
print("š Hooks disabled")
|
|
105
|
+
|
|
106
|
+
print()
|
|
107
|
+
|
|
108
|
+
# Create SMCP server with hook support
|
|
109
|
+
server = SMCP(
|
|
110
|
+
name=args.name,
|
|
111
|
+
auto_expose_tools=True,
|
|
112
|
+
search_enabled=True,
|
|
113
|
+
max_workers=5,
|
|
114
|
+
stateless_http=True, # Enable stateless mode for MCPAutoLoaderTool compatibility
|
|
115
|
+
hooks_enabled=hooks_enabled,
|
|
116
|
+
hook_config=hook_config,
|
|
117
|
+
hook_type=args.hook_type,
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
# Run server with streamable-http transport
|
|
121
|
+
server.run_simple(transport="http", host=args.host, port=args.port)
|
|
122
|
+
|
|
123
|
+
except KeyboardInterrupt:
|
|
124
|
+
print("\nš Server stopped by user")
|
|
125
|
+
sys.exit(0)
|
|
126
|
+
except Exception as e:
|
|
127
|
+
print(f"ā Error starting server: {e}")
|
|
128
|
+
sys.exit(1)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def run_stdio_server():
|
|
132
|
+
"""
|
|
133
|
+
Run SMCP server with stdio transport for Claude Desktop integration
|
|
134
|
+
|
|
135
|
+
This function provides compatibility with the original MCP server's run_claude_desktop function.
|
|
136
|
+
It accepts the same arguments as run_smcp_server but forces transport='stdio'.
|
|
137
|
+
"""
|
|
138
|
+
parser = argparse.ArgumentParser(
|
|
139
|
+
description="Start SMCP (Scientific Model Context Protocol) Server with stdio transport",
|
|
140
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
141
|
+
epilog="""
|
|
142
|
+
Examples:
|
|
143
|
+
# Start server with all tools using stdio transport (hooks enabled by default)
|
|
144
|
+
tooluniverse-stdio
|
|
145
|
+
|
|
146
|
+
# Start with specific categories
|
|
147
|
+
tooluniverse-stdio --categories uniprot ChEMBL opentarget
|
|
148
|
+
|
|
149
|
+
# Disable hooks
|
|
150
|
+
tooluniverse-stdio --no-hooks
|
|
151
|
+
|
|
152
|
+
# Use FileSaveHook instead of SummarizationHook
|
|
153
|
+
tooluniverse-stdio --hook-type FileSaveHook
|
|
154
|
+
|
|
155
|
+
# Use custom hook configuration
|
|
156
|
+
tooluniverse-stdio --hook-config-file /path/to/hook_config.json
|
|
157
|
+
|
|
158
|
+
# Start with categories but exclude specific tools
|
|
159
|
+
tooluniverse-stdio --categories uniprot ChEMBL --exclude-tools "ChEMBL_get_molecule_by_chembl_id"
|
|
160
|
+
|
|
161
|
+
# Start with all tools but exclude entire categories
|
|
162
|
+
tooluniverse-stdio --exclude-categories mcp_auto_loader_boltz mcp_auto_loader_expert_feedback
|
|
163
|
+
|
|
164
|
+
# Load only specific tools by name
|
|
165
|
+
tooluniverse-stdio --include-tools "UniProt_get_entry_by_accession" "ChEMBL_get_molecule_by_chembl_id"
|
|
166
|
+
|
|
167
|
+
# Load tools from a file
|
|
168
|
+
tooluniverse-stdio --tools-file "/path/to/tool_names.txt"
|
|
169
|
+
|
|
170
|
+
# Load additional config files
|
|
171
|
+
tooluniverse-stdio --tool-config-files "custom:/path/to/custom_tools.json"
|
|
172
|
+
|
|
173
|
+
# Include/exclude specific tool types
|
|
174
|
+
tooluniverse-stdio --include-tool-types "OpenTarget" "ToolFinderEmbedding"
|
|
175
|
+
tooluniverse-stdio --exclude-tool-types "ToolFinderLLM" "Unknown"
|
|
176
|
+
|
|
177
|
+
# List available categories
|
|
178
|
+
tooluniverse-stdio --list-categories
|
|
179
|
+
|
|
180
|
+
# List all available tools
|
|
181
|
+
tooluniverse-stdio --list-tools
|
|
182
|
+
|
|
183
|
+
# Start minimal server with just search tools
|
|
184
|
+
tooluniverse-stdio --categories special_tools tool_finder
|
|
185
|
+
""",
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
# Tool selection options
|
|
189
|
+
tool_group = parser.add_mutually_exclusive_group()
|
|
190
|
+
tool_group.add_argument(
|
|
191
|
+
"--categories",
|
|
192
|
+
nargs="*",
|
|
193
|
+
metavar="CATEGORY",
|
|
194
|
+
help="Specific tool categories to load (e.g., uniprot ChEMBL opentarget). Use --list-categories to see available options.",
|
|
195
|
+
)
|
|
196
|
+
tool_group.add_argument(
|
|
197
|
+
"--list-categories",
|
|
198
|
+
action="store_true",
|
|
199
|
+
help="List all available tool categories and exit",
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
# Tool exclusion options
|
|
203
|
+
parser.add_argument(
|
|
204
|
+
"--exclude-tools",
|
|
205
|
+
nargs="*",
|
|
206
|
+
metavar="TOOL_NAME",
|
|
207
|
+
help='Specific tool names to exclude from loading (e.g., "tool1" "tool2"). Can be used with --categories.',
|
|
208
|
+
)
|
|
209
|
+
parser.add_argument(
|
|
210
|
+
"--exclude-categories",
|
|
211
|
+
nargs="*",
|
|
212
|
+
metavar="CATEGORY",
|
|
213
|
+
help="Tool categories to exclude from loading (e.g., mcp_auto_loader_boltz). Can be used with --categories.",
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
# Tool inclusion options
|
|
217
|
+
parser.add_argument(
|
|
218
|
+
"--include-tools",
|
|
219
|
+
nargs="*",
|
|
220
|
+
metavar="TOOL_NAME",
|
|
221
|
+
help="Specific tool names to include (only these tools will be loaded). Overrides category selection.",
|
|
222
|
+
)
|
|
223
|
+
parser.add_argument(
|
|
224
|
+
"--tools-file",
|
|
225
|
+
metavar="FILE_PATH",
|
|
226
|
+
help="Path to text file containing tool names to include (one per line). Overrides category selection.",
|
|
227
|
+
)
|
|
228
|
+
parser.add_argument(
|
|
229
|
+
"--tool-config-files",
|
|
230
|
+
nargs="*",
|
|
231
|
+
metavar="CATEGORY:PATH",
|
|
232
|
+
help='Additional tool config files to load. Format: "category:/path/to/config.json"',
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
# Tool type filtering options
|
|
236
|
+
parser.add_argument(
|
|
237
|
+
"--include-tool-types",
|
|
238
|
+
nargs="*",
|
|
239
|
+
metavar="TOOL_TYPE",
|
|
240
|
+
help="Specific tool types to include (e.g., OpenTarget ToolFinderEmbedding). Only tools of these types will be loaded.",
|
|
241
|
+
)
|
|
242
|
+
parser.add_argument(
|
|
243
|
+
"--exclude-tool-types",
|
|
244
|
+
nargs="*",
|
|
245
|
+
metavar="TOOL_TYPE",
|
|
246
|
+
help="Tool types to exclude from loading (e.g., ToolFinderLLM Unknown). Useful for excluding specific tool type classes.",
|
|
247
|
+
)
|
|
248
|
+
|
|
249
|
+
# Listing options
|
|
250
|
+
parser.add_argument(
|
|
251
|
+
"--list-tools", action="store_true", help="List all available tools and exit"
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
# Server configuration (stdio-specific)
|
|
255
|
+
parser.add_argument(
|
|
256
|
+
"--name",
|
|
257
|
+
default="SMCP ToolUniverse Server",
|
|
258
|
+
help="Server name (default: SMCP ToolUniverse Server)",
|
|
259
|
+
)
|
|
260
|
+
parser.add_argument(
|
|
261
|
+
"--no-search",
|
|
262
|
+
action="store_true",
|
|
263
|
+
help="Disable intelligent search functionality",
|
|
264
|
+
)
|
|
265
|
+
parser.add_argument(
|
|
266
|
+
"--max-workers",
|
|
267
|
+
type=int,
|
|
268
|
+
default=5,
|
|
269
|
+
help="Maximum worker threads for concurrent execution (default: 5)",
|
|
270
|
+
)
|
|
271
|
+
parser.add_argument(
|
|
272
|
+
"--verbose", "-v", action="store_true", help="Enable verbose logging"
|
|
273
|
+
)
|
|
274
|
+
|
|
275
|
+
# Hook configuration options (default enabled for stdio)
|
|
276
|
+
hook_group = parser.add_argument_group("Hook Configuration")
|
|
277
|
+
hook_group.add_argument(
|
|
278
|
+
"--no-hooks",
|
|
279
|
+
action="store_true",
|
|
280
|
+
help="Disable output processing hooks (default: enabled for stdio)",
|
|
281
|
+
)
|
|
282
|
+
hook_group.add_argument(
|
|
283
|
+
"--hook-type",
|
|
284
|
+
choices=["SummarizationHook", "FileSaveHook"],
|
|
285
|
+
default="SummarizationHook",
|
|
286
|
+
help="Hook type to use (default: SummarizationHook)",
|
|
287
|
+
)
|
|
288
|
+
hook_group.add_argument(
|
|
289
|
+
"--hook-config-file",
|
|
290
|
+
type=str,
|
|
291
|
+
help="Path to custom hook configuration JSON file",
|
|
292
|
+
)
|
|
293
|
+
|
|
294
|
+
args = parser.parse_args()
|
|
295
|
+
|
|
296
|
+
# Handle --list-categories
|
|
297
|
+
if args.list_categories:
|
|
298
|
+
try:
|
|
299
|
+
from .execute_function import ToolUniverse
|
|
300
|
+
|
|
301
|
+
tu = ToolUniverse()
|
|
302
|
+
tool_types = tu.get_tool_types()
|
|
303
|
+
|
|
304
|
+
print("Available tool categories:")
|
|
305
|
+
print("=" * 50)
|
|
306
|
+
|
|
307
|
+
# Group categories for better readability
|
|
308
|
+
scientific_db = []
|
|
309
|
+
literature = []
|
|
310
|
+
software = []
|
|
311
|
+
special = []
|
|
312
|
+
clinical = []
|
|
313
|
+
other = []
|
|
314
|
+
|
|
315
|
+
for category in sorted(tool_types):
|
|
316
|
+
if category in [
|
|
317
|
+
"uniprot",
|
|
318
|
+
"ChEMBL",
|
|
319
|
+
"opentarget",
|
|
320
|
+
"pubchem",
|
|
321
|
+
"hpa",
|
|
322
|
+
"rcsb_pdb",
|
|
323
|
+
"reactome",
|
|
324
|
+
"go",
|
|
325
|
+
]:
|
|
326
|
+
scientific_db.append(category)
|
|
327
|
+
elif category in [
|
|
328
|
+
"EuropePMC",
|
|
329
|
+
"semantic_scholar",
|
|
330
|
+
"pubtator",
|
|
331
|
+
"OpenAlex",
|
|
332
|
+
]:
|
|
333
|
+
literature.append(category)
|
|
334
|
+
elif category.startswith("software_"):
|
|
335
|
+
software.append(category)
|
|
336
|
+
elif category in [
|
|
337
|
+
"special_tools",
|
|
338
|
+
"tool_finder",
|
|
339
|
+
"tool_composition",
|
|
340
|
+
"agents",
|
|
341
|
+
]:
|
|
342
|
+
special.append(category)
|
|
343
|
+
elif category in [
|
|
344
|
+
"clinical_trials",
|
|
345
|
+
"fda_drug_label",
|
|
346
|
+
"fda_drug_adverse_event",
|
|
347
|
+
"dailymed",
|
|
348
|
+
"medlineplus",
|
|
349
|
+
]:
|
|
350
|
+
clinical.append(category)
|
|
351
|
+
else:
|
|
352
|
+
other.append(category)
|
|
353
|
+
|
|
354
|
+
if scientific_db:
|
|
355
|
+
print("\nš¬ Scientific Databases:")
|
|
356
|
+
for cat in scientific_db:
|
|
357
|
+
print(f" {cat}")
|
|
358
|
+
|
|
359
|
+
if literature:
|
|
360
|
+
print("\nš Literature & Knowledge:")
|
|
361
|
+
for cat in literature:
|
|
362
|
+
print(f" {cat}")
|
|
363
|
+
|
|
364
|
+
if clinical:
|
|
365
|
+
print("\nš„ Clinical & Drug Information:")
|
|
366
|
+
for cat in clinical:
|
|
367
|
+
print(f" {cat}")
|
|
368
|
+
|
|
369
|
+
if software:
|
|
370
|
+
print("\nš» Software Tools:")
|
|
371
|
+
for cat in software[:5]: # Show first 5
|
|
372
|
+
print(f" {cat}")
|
|
373
|
+
if len(software) > 5:
|
|
374
|
+
print(f" ... and {len(software) - 5} more software categories")
|
|
375
|
+
|
|
376
|
+
if special:
|
|
377
|
+
print("\nš Special & Meta Tools:")
|
|
378
|
+
for cat in special:
|
|
379
|
+
print(f" {cat}")
|
|
380
|
+
|
|
381
|
+
if other:
|
|
382
|
+
print("\nš Other Categories:")
|
|
383
|
+
for cat in other:
|
|
384
|
+
print(f" {cat}")
|
|
385
|
+
|
|
386
|
+
print(f"\nTotal: {len(tool_types)} categories available")
|
|
387
|
+
print("\nCommon combinations:")
|
|
388
|
+
print(" Scientific research: uniprot ChEMBL opentarget pubchem hpa")
|
|
389
|
+
print(" Drug discovery: ChEMBL fda_drug_label clinical_trials pubchem")
|
|
390
|
+
print(" Literature analysis: EuropePMC semantic_scholar pubtator")
|
|
391
|
+
print(" Minimal setup: special_tools tool_finder")
|
|
392
|
+
|
|
393
|
+
except Exception as e:
|
|
394
|
+
print(f"ā Error listing categories: {e}")
|
|
395
|
+
sys.exit(1)
|
|
396
|
+
return
|
|
397
|
+
|
|
398
|
+
# Handle --list-tools
|
|
399
|
+
if args.list_tools:
|
|
400
|
+
try:
|
|
401
|
+
from .execute_function import ToolUniverse
|
|
402
|
+
|
|
403
|
+
tu = ToolUniverse()
|
|
404
|
+
tu.load_tools() # Load all tools to list them
|
|
405
|
+
|
|
406
|
+
print("Available tools:")
|
|
407
|
+
print("=" * 50)
|
|
408
|
+
|
|
409
|
+
# Group tools by category
|
|
410
|
+
tools_by_category = {}
|
|
411
|
+
for tool in tu.all_tools:
|
|
412
|
+
tool_type = getattr(tool, "tool_type", "unknown")
|
|
413
|
+
if tool_type not in tools_by_category:
|
|
414
|
+
tools_by_category[tool_type] = []
|
|
415
|
+
tools_by_category[tool_type].append(tool.name)
|
|
416
|
+
|
|
417
|
+
total_tools = 0
|
|
418
|
+
for category in sorted(tools_by_category.keys()):
|
|
419
|
+
tools = sorted(tools_by_category[category])
|
|
420
|
+
print(f"\nš {category} ({len(tools)} tools):")
|
|
421
|
+
for tool in tools[:10]: # Show first 10 tools per category
|
|
422
|
+
print(f" {tool}")
|
|
423
|
+
if len(tools) > 10:
|
|
424
|
+
print(f" ... and {len(tools) - 10} more tools")
|
|
425
|
+
total_tools += len(tools)
|
|
426
|
+
|
|
427
|
+
print(f"\nTotal: {total_tools} tools available")
|
|
428
|
+
print("\nNote: Use --exclude-tools to exclude specific tools by name")
|
|
429
|
+
print(" Use --exclude-categories to exclude entire categories")
|
|
430
|
+
|
|
431
|
+
except Exception as e:
|
|
432
|
+
print(f"ā Error listing tools: {e}")
|
|
433
|
+
sys.exit(1)
|
|
434
|
+
return
|
|
435
|
+
|
|
436
|
+
try:
|
|
437
|
+
print(f"š Starting {args.name}...")
|
|
438
|
+
print("š” Transport: stdio (for Claude Desktop)")
|
|
439
|
+
print(f"š Search enabled: {not args.no_search}")
|
|
440
|
+
|
|
441
|
+
if args.categories is not None:
|
|
442
|
+
if len(args.categories) == 0:
|
|
443
|
+
print("š No categories specified, loading all tools")
|
|
444
|
+
tool_categories = None
|
|
445
|
+
else:
|
|
446
|
+
print(f"š Tool categories: {', '.join(args.categories)}")
|
|
447
|
+
tool_categories = args.categories
|
|
448
|
+
else:
|
|
449
|
+
print("š Loading all tool categories")
|
|
450
|
+
tool_categories = None
|
|
451
|
+
|
|
452
|
+
# Handle exclusions and inclusions
|
|
453
|
+
exclude_tools = args.exclude_tools or []
|
|
454
|
+
exclude_categories = args.exclude_categories or []
|
|
455
|
+
include_tools = args.include_tools or []
|
|
456
|
+
tools_file = args.tools_file
|
|
457
|
+
include_tool_types = args.include_tool_types or []
|
|
458
|
+
exclude_tool_types = args.exclude_tool_types or []
|
|
459
|
+
|
|
460
|
+
# Parse tool config files
|
|
461
|
+
tool_config_files = {}
|
|
462
|
+
if args.tool_config_files:
|
|
463
|
+
for config_spec in args.tool_config_files:
|
|
464
|
+
if ":" in config_spec:
|
|
465
|
+
category, path = config_spec.split(":", 1)
|
|
466
|
+
tool_config_files[category] = path
|
|
467
|
+
else:
|
|
468
|
+
print(f"ā Invalid tool config file format: {config_spec}")
|
|
469
|
+
print(" Expected format: 'category:/path/to/config.json'")
|
|
470
|
+
sys.exit(1)
|
|
471
|
+
|
|
472
|
+
if exclude_tools:
|
|
473
|
+
print(f"š« Excluding tools: {', '.join(exclude_tools)}")
|
|
474
|
+
if exclude_categories:
|
|
475
|
+
print(f"š« Excluding categories: {', '.join(exclude_categories)}")
|
|
476
|
+
if include_tools:
|
|
477
|
+
print(f"ā
Including only specific tools: {len(include_tools)} tools")
|
|
478
|
+
if tools_file:
|
|
479
|
+
print(f"š Loading tools from file: {tools_file}")
|
|
480
|
+
if tool_config_files:
|
|
481
|
+
print(f"š¦ Additional config files: {', '.join(tool_config_files.keys())}")
|
|
482
|
+
if include_tool_types:
|
|
483
|
+
print(f"šÆ Including tool types: {', '.join(include_tool_types)}")
|
|
484
|
+
if exclude_tool_types:
|
|
485
|
+
print(f"š« Excluding tool types: {', '.join(exclude_tool_types)}")
|
|
486
|
+
|
|
487
|
+
# Load hook configuration if specified
|
|
488
|
+
hook_config = None
|
|
489
|
+
if args.hook_config_file:
|
|
490
|
+
import json
|
|
491
|
+
|
|
492
|
+
with open(args.hook_config_file, "r") as f:
|
|
493
|
+
hook_config = json.load(f)
|
|
494
|
+
print(f"š Hook config loaded from: {args.hook_config_file}")
|
|
495
|
+
|
|
496
|
+
# Determine hook settings (default enabled for stdio)
|
|
497
|
+
hooks_enabled = not args.no_hooks
|
|
498
|
+
if hooks_enabled:
|
|
499
|
+
if args.hook_type:
|
|
500
|
+
print(f"š Hooks enabled: {args.hook_type}")
|
|
501
|
+
elif hook_config:
|
|
502
|
+
hook_count = len(hook_config.get("hooks", []))
|
|
503
|
+
print(f"š Hooks enabled: {hook_count} custom hooks")
|
|
504
|
+
else:
|
|
505
|
+
print(f"š Hooks enabled: {args.hook_type} (default)")
|
|
506
|
+
else:
|
|
507
|
+
print("š Hooks disabled")
|
|
508
|
+
|
|
509
|
+
print(f"ā” Max workers: {args.max_workers}")
|
|
510
|
+
print()
|
|
511
|
+
|
|
512
|
+
# Create SMCP server with hook support
|
|
513
|
+
server = SMCP(
|
|
514
|
+
name=args.name,
|
|
515
|
+
tool_categories=tool_categories,
|
|
516
|
+
exclude_tools=exclude_tools,
|
|
517
|
+
exclude_categories=exclude_categories,
|
|
518
|
+
include_tools=include_tools,
|
|
519
|
+
tools_file=tools_file,
|
|
520
|
+
tool_config_files=tool_config_files,
|
|
521
|
+
include_tool_types=include_tool_types,
|
|
522
|
+
exclude_tool_types=exclude_tool_types,
|
|
523
|
+
search_enabled=not args.no_search,
|
|
524
|
+
max_workers=args.max_workers,
|
|
525
|
+
stateless_http=True, # Enable stateless mode for MCPAutoLoaderTool compatibility
|
|
526
|
+
hooks_enabled=hooks_enabled,
|
|
527
|
+
hook_config=hook_config,
|
|
528
|
+
hook_type=args.hook_type,
|
|
529
|
+
)
|
|
530
|
+
|
|
531
|
+
# Run server with stdio transport (forced)
|
|
532
|
+
server.run_simple(transport="stdio")
|
|
533
|
+
|
|
534
|
+
except KeyboardInterrupt:
|
|
535
|
+
print("\nš Server stopped by user")
|
|
536
|
+
sys.exit(0)
|
|
537
|
+
except Exception as e:
|
|
538
|
+
print(f"ā Error starting server: {e}")
|
|
539
|
+
if args.verbose:
|
|
540
|
+
import traceback
|
|
541
|
+
|
|
542
|
+
traceback.print_exc()
|
|
543
|
+
sys.exit(1)
|
|
544
|
+
|
|
545
|
+
|
|
546
|
+
def run_smcp_server():
|
|
547
|
+
"""
|
|
548
|
+
Main entry point for the SMCP server command.
|
|
549
|
+
|
|
550
|
+
This function is called when running `tooluniverse-smcp` from the command line.
|
|
551
|
+
"""
|
|
552
|
+
parser = argparse.ArgumentParser(
|
|
553
|
+
description="Start SMCP (Scientific Model Context Protocol) Server",
|
|
554
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
555
|
+
epilog="""
|
|
556
|
+
Examples:
|
|
557
|
+
# Start server with all tools on port 7890
|
|
558
|
+
tooluniverse-smcp --port 7890
|
|
559
|
+
|
|
560
|
+
# Start with specific categories
|
|
561
|
+
tooluniverse-smcp --categories uniprot ChEMBL opentarget --port 8000
|
|
562
|
+
|
|
563
|
+
# Start with categories but exclude specific tools
|
|
564
|
+
tooluniverse-smcp --categories uniprot ChEMBL --exclude-tools "ChEMBL_get_molecule_by_chembl_id" --port 8000
|
|
565
|
+
|
|
566
|
+
# Start with all tools but exclude entire categories
|
|
567
|
+
tooluniverse-smcp --exclude-categories mcp_auto_loader_boltz mcp_auto_loader_expert_feedback --port 8000
|
|
568
|
+
|
|
569
|
+
# Load only specific tools by name
|
|
570
|
+
tooluniverse-smcp --include-tools "UniProt_get_entry_by_accession" "ChEMBL_get_molecule_by_chembl_id" --port 8000
|
|
571
|
+
|
|
572
|
+
# Load tools from a file
|
|
573
|
+
tooluniverse-smcp --tools-file "/path/to/tool_names.txt" --port 8000
|
|
574
|
+
|
|
575
|
+
# Load additional config files
|
|
576
|
+
tooluniverse-smcp --tool-config-files "custom:/path/to/custom_tools.json" --port 8000
|
|
577
|
+
|
|
578
|
+
# Include/exclude specific tool types
|
|
579
|
+
tooluniverse-smcp --include-tool-types "OpenTarget" "ToolFinderEmbedding" --port 8000
|
|
580
|
+
tooluniverse-smcp --exclude-tool-types "ToolFinderLLM" "Unknown" --port 8000
|
|
581
|
+
|
|
582
|
+
# List available categories
|
|
583
|
+
tooluniverse-smcp --list-categories
|
|
584
|
+
|
|
585
|
+
# List all available tools
|
|
586
|
+
tooluniverse-smcp --list-tools
|
|
587
|
+
|
|
588
|
+
# Start minimal server with just search tools
|
|
589
|
+
tooluniverse-smcp --categories special_tools tool_finder --port 7000
|
|
590
|
+
|
|
591
|
+
# Start server for Claude Desktop (stdio transport)
|
|
592
|
+
tooluniverse-smcp --transport stdio
|
|
593
|
+
""",
|
|
594
|
+
)
|
|
595
|
+
|
|
596
|
+
# Tool selection options
|
|
597
|
+
tool_group = parser.add_mutually_exclusive_group()
|
|
598
|
+
tool_group.add_argument(
|
|
599
|
+
"--categories",
|
|
600
|
+
nargs="*",
|
|
601
|
+
metavar="CATEGORY",
|
|
602
|
+
help="Specific tool categories to load (e.g., uniprot ChEMBL opentarget). Use --list-categories to see available options.",
|
|
603
|
+
)
|
|
604
|
+
tool_group.add_argument(
|
|
605
|
+
"--list-categories",
|
|
606
|
+
action="store_true",
|
|
607
|
+
help="List all available tool categories and exit",
|
|
608
|
+
)
|
|
609
|
+
|
|
610
|
+
# Tool exclusion options
|
|
611
|
+
parser.add_argument(
|
|
612
|
+
"--exclude-tools",
|
|
613
|
+
nargs="*",
|
|
614
|
+
metavar="TOOL_NAME",
|
|
615
|
+
help='Specific tool names to exclude from loading (e.g., "tool1" "tool2"). Can be used with --categories.',
|
|
616
|
+
)
|
|
617
|
+
parser.add_argument(
|
|
618
|
+
"--exclude-categories",
|
|
619
|
+
nargs="*",
|
|
620
|
+
metavar="CATEGORY",
|
|
621
|
+
help="Tool categories to exclude from loading (e.g., mcp_auto_loader_boltz). Can be used with --categories.",
|
|
622
|
+
)
|
|
623
|
+
|
|
624
|
+
# Tool inclusion options
|
|
625
|
+
parser.add_argument(
|
|
626
|
+
"--include-tools",
|
|
627
|
+
nargs="*",
|
|
628
|
+
metavar="TOOL_NAME",
|
|
629
|
+
help="Specific tool names to include (only these tools will be loaded). Overrides category selection.",
|
|
630
|
+
)
|
|
631
|
+
parser.add_argument(
|
|
632
|
+
"--tools-file",
|
|
633
|
+
metavar="FILE_PATH",
|
|
634
|
+
help="Path to text file containing tool names to include (one per line). Overrides category selection.",
|
|
635
|
+
)
|
|
636
|
+
parser.add_argument(
|
|
637
|
+
"--tool-config-files",
|
|
638
|
+
nargs="*",
|
|
639
|
+
metavar="CATEGORY:PATH",
|
|
640
|
+
help='Additional tool config files to load. Format: "category:/path/to/config.json"',
|
|
641
|
+
)
|
|
642
|
+
|
|
643
|
+
# Tool type filtering options
|
|
644
|
+
parser.add_argument(
|
|
645
|
+
"--include-tool-types",
|
|
646
|
+
nargs="*",
|
|
647
|
+
metavar="TOOL_TYPE",
|
|
648
|
+
help="Specific tool types to include (e.g., OpenTarget ToolFinderEmbedding). Only tools of these types will be loaded.",
|
|
649
|
+
)
|
|
650
|
+
parser.add_argument(
|
|
651
|
+
"--exclude-tool-types",
|
|
652
|
+
nargs="*",
|
|
653
|
+
metavar="TOOL_TYPE",
|
|
654
|
+
help="Tool types to exclude from loading (e.g., ToolFinderLLM Unknown). Useful for excluding specific tool type classes.",
|
|
655
|
+
)
|
|
656
|
+
|
|
657
|
+
# Listing options
|
|
658
|
+
parser.add_argument(
|
|
659
|
+
"--list-tools", action="store_true", help="List all available tools and exit"
|
|
660
|
+
)
|
|
661
|
+
|
|
662
|
+
# Server configuration
|
|
663
|
+
parser.add_argument(
|
|
664
|
+
"--transport",
|
|
665
|
+
choices=["stdio", "http", "sse"],
|
|
666
|
+
default="http",
|
|
667
|
+
help="Transport protocol to use (default: http)",
|
|
668
|
+
)
|
|
669
|
+
parser.add_argument(
|
|
670
|
+
"--host",
|
|
671
|
+
default="0.0.0.0",
|
|
672
|
+
help="Host to bind to for HTTP/SSE transport (default: 0.0.0.0)",
|
|
673
|
+
)
|
|
674
|
+
parser.add_argument(
|
|
675
|
+
"--port",
|
|
676
|
+
type=int,
|
|
677
|
+
default=7000,
|
|
678
|
+
help="Port to bind to for HTTP/SSE transport (default: 7000)",
|
|
679
|
+
)
|
|
680
|
+
parser.add_argument(
|
|
681
|
+
"--name",
|
|
682
|
+
default="SMCP ToolUniverse Server",
|
|
683
|
+
help="Server name (default: SMCP ToolUniverse Server)",
|
|
684
|
+
)
|
|
685
|
+
parser.add_argument(
|
|
686
|
+
"--no-search",
|
|
687
|
+
action="store_true",
|
|
688
|
+
help="Disable intelligent search functionality",
|
|
689
|
+
)
|
|
690
|
+
parser.add_argument(
|
|
691
|
+
"--max-workers",
|
|
692
|
+
type=int,
|
|
693
|
+
default=5,
|
|
694
|
+
help="Maximum worker threads for concurrent execution (default: 5)",
|
|
695
|
+
)
|
|
696
|
+
parser.add_argument(
|
|
697
|
+
"--verbose", "-v", action="store_true", help="Enable verbose logging"
|
|
698
|
+
)
|
|
699
|
+
|
|
700
|
+
# Hook configuration options
|
|
701
|
+
hook_group = parser.add_argument_group("Hook Configuration")
|
|
702
|
+
hook_group.add_argument(
|
|
703
|
+
"--hooks-enabled",
|
|
704
|
+
action="store_true",
|
|
705
|
+
help="Enable output processing hooks (default: False)",
|
|
706
|
+
)
|
|
707
|
+
hook_group.add_argument(
|
|
708
|
+
"--hook-type",
|
|
709
|
+
choices=["SummarizationHook", "FileSaveHook"],
|
|
710
|
+
help="Simple hook type selection (SummarizationHook or FileSaveHook)",
|
|
711
|
+
)
|
|
712
|
+
hook_group.add_argument(
|
|
713
|
+
"--hook-config-file",
|
|
714
|
+
type=str,
|
|
715
|
+
help="Path to custom hook configuration JSON file",
|
|
716
|
+
)
|
|
717
|
+
|
|
718
|
+
args = parser.parse_args()
|
|
719
|
+
|
|
720
|
+
# Handle --list-categories
|
|
721
|
+
if args.list_categories:
|
|
722
|
+
try:
|
|
723
|
+
from .execute_function import ToolUniverse
|
|
724
|
+
|
|
725
|
+
tu = ToolUniverse()
|
|
726
|
+
tool_types = tu.get_tool_types()
|
|
727
|
+
|
|
728
|
+
print("Available tool categories:")
|
|
729
|
+
print("=" * 50)
|
|
730
|
+
|
|
731
|
+
# Group categories for better readability
|
|
732
|
+
scientific_db = []
|
|
733
|
+
literature = []
|
|
734
|
+
software = []
|
|
735
|
+
special = []
|
|
736
|
+
clinical = []
|
|
737
|
+
other = []
|
|
738
|
+
|
|
739
|
+
for category in sorted(tool_types):
|
|
740
|
+
if category in [
|
|
741
|
+
"uniprot",
|
|
742
|
+
"ChEMBL",
|
|
743
|
+
"opentarget",
|
|
744
|
+
"pubchem",
|
|
745
|
+
"hpa",
|
|
746
|
+
"rcsb_pdb",
|
|
747
|
+
"reactome",
|
|
748
|
+
"go",
|
|
749
|
+
]:
|
|
750
|
+
scientific_db.append(category)
|
|
751
|
+
elif category in [
|
|
752
|
+
"EuropePMC",
|
|
753
|
+
"semantic_scholar",
|
|
754
|
+
"pubtator",
|
|
755
|
+
"OpenAlex",
|
|
756
|
+
]:
|
|
757
|
+
literature.append(category)
|
|
758
|
+
elif category.startswith("software_"):
|
|
759
|
+
software.append(category)
|
|
760
|
+
elif category in [
|
|
761
|
+
"special_tools",
|
|
762
|
+
"tool_finder",
|
|
763
|
+
"tool_composition",
|
|
764
|
+
"agents",
|
|
765
|
+
]:
|
|
766
|
+
special.append(category)
|
|
767
|
+
elif category in [
|
|
768
|
+
"clinical_trials",
|
|
769
|
+
"fda_drug_label",
|
|
770
|
+
"fda_drug_adverse_event",
|
|
771
|
+
"dailymed",
|
|
772
|
+
"medlineplus",
|
|
773
|
+
]:
|
|
774
|
+
clinical.append(category)
|
|
775
|
+
else:
|
|
776
|
+
other.append(category)
|
|
777
|
+
|
|
778
|
+
if scientific_db:
|
|
779
|
+
print("\nš¬ Scientific Databases:")
|
|
780
|
+
for cat in scientific_db:
|
|
781
|
+
print(f" {cat}")
|
|
782
|
+
|
|
783
|
+
if literature:
|
|
784
|
+
print("\nš Literature & Knowledge:")
|
|
785
|
+
for cat in literature:
|
|
786
|
+
print(f" {cat}")
|
|
787
|
+
|
|
788
|
+
if clinical:
|
|
789
|
+
print("\nš„ Clinical & Drug Information:")
|
|
790
|
+
for cat in clinical:
|
|
791
|
+
print(f" {cat}")
|
|
792
|
+
|
|
793
|
+
if software:
|
|
794
|
+
print("\nš» Software Tools:")
|
|
795
|
+
for cat in software[:5]: # Show first 5
|
|
796
|
+
print(f" {cat}")
|
|
797
|
+
if len(software) > 5:
|
|
798
|
+
print(f" ... and {len(software) - 5} more software categories")
|
|
799
|
+
|
|
800
|
+
if special:
|
|
801
|
+
print("\nš Special & Meta Tools:")
|
|
802
|
+
for cat in special:
|
|
803
|
+
print(f" {cat}")
|
|
804
|
+
|
|
805
|
+
if other:
|
|
806
|
+
print("\nš Other Categories:")
|
|
807
|
+
for cat in other:
|
|
808
|
+
print(f" {cat}")
|
|
809
|
+
|
|
810
|
+
print(f"\nTotal: {len(tool_types)} categories available")
|
|
811
|
+
print("\nCommon combinations:")
|
|
812
|
+
print(" Scientific research: uniprot ChEMBL opentarget pubchem hpa")
|
|
813
|
+
print(" Drug discovery: ChEMBL fda_drug_label clinical_trials pubchem")
|
|
814
|
+
print(" Literature analysis: EuropePMC semantic_scholar pubtator")
|
|
815
|
+
print(" Minimal setup: special_tools tool_finder")
|
|
816
|
+
|
|
817
|
+
except Exception as e:
|
|
818
|
+
print(f"ā Error listing categories: {e}")
|
|
819
|
+
sys.exit(1)
|
|
820
|
+
return
|
|
821
|
+
|
|
822
|
+
# Handle --list-tools
|
|
823
|
+
if args.list_tools:
|
|
824
|
+
try:
|
|
825
|
+
from .execute_function import ToolUniverse
|
|
826
|
+
|
|
827
|
+
tu = ToolUniverse()
|
|
828
|
+
tu.load_tools() # Load all tools to list them
|
|
829
|
+
|
|
830
|
+
print("Available tools:")
|
|
831
|
+
print("=" * 50)
|
|
832
|
+
|
|
833
|
+
# Group tools by category
|
|
834
|
+
tools_by_category = {}
|
|
835
|
+
for tool in tu.all_tools:
|
|
836
|
+
tool_type = getattr(tool, "tool_type", "unknown")
|
|
837
|
+
if tool_type not in tools_by_category:
|
|
838
|
+
tools_by_category[tool_type] = []
|
|
839
|
+
tools_by_category[tool_type].append(tool.name)
|
|
840
|
+
|
|
841
|
+
total_tools = 0
|
|
842
|
+
for category in sorted(tools_by_category.keys()):
|
|
843
|
+
tools = sorted(tools_by_category[category])
|
|
844
|
+
print(f"\nš {category} ({len(tools)} tools):")
|
|
845
|
+
for tool in tools[:10]: # Show first 10 tools per category
|
|
846
|
+
print(f" {tool}")
|
|
847
|
+
if len(tools) > 10:
|
|
848
|
+
print(f" ... and {len(tools) - 10} more tools")
|
|
849
|
+
total_tools += len(tools)
|
|
850
|
+
|
|
851
|
+
print(f"\nTotal: {total_tools} tools available")
|
|
852
|
+
print("\nNote: Use --exclude-tools to exclude specific tools by name")
|
|
853
|
+
print(" Use --exclude-categories to exclude entire categories")
|
|
854
|
+
|
|
855
|
+
except Exception as e:
|
|
856
|
+
print(f"ā Error listing tools: {e}")
|
|
857
|
+
sys.exit(1)
|
|
858
|
+
return
|
|
859
|
+
|
|
860
|
+
try:
|
|
861
|
+
print(f"š Starting {args.name}...")
|
|
862
|
+
print(f"š” Transport: {args.transport}")
|
|
863
|
+
if args.transport in ["http", "sse"]:
|
|
864
|
+
print(f"š Address: http://{args.host}:{args.port}")
|
|
865
|
+
print(f"š Search enabled: {not args.no_search}")
|
|
866
|
+
|
|
867
|
+
if args.categories is not None:
|
|
868
|
+
if len(args.categories) == 0:
|
|
869
|
+
print("š No categories specified, loading all tools")
|
|
870
|
+
tool_categories = None
|
|
871
|
+
else:
|
|
872
|
+
print(f"š Tool categories: {', '.join(args.categories)}")
|
|
873
|
+
tool_categories = args.categories
|
|
874
|
+
else:
|
|
875
|
+
print("š Loading all tool categories")
|
|
876
|
+
tool_categories = None
|
|
877
|
+
|
|
878
|
+
# Handle exclusions and inclusions
|
|
879
|
+
exclude_tools = args.exclude_tools or []
|
|
880
|
+
exclude_categories = args.exclude_categories or []
|
|
881
|
+
include_tools = args.include_tools or []
|
|
882
|
+
tools_file = args.tools_file
|
|
883
|
+
include_tool_types = args.include_tool_types or []
|
|
884
|
+
exclude_tool_types = args.exclude_tool_types or []
|
|
885
|
+
|
|
886
|
+
# Parse tool config files
|
|
887
|
+
tool_config_files = {}
|
|
888
|
+
if args.tool_config_files:
|
|
889
|
+
for config_spec in args.tool_config_files:
|
|
890
|
+
if ":" in config_spec:
|
|
891
|
+
category, path = config_spec.split(":", 1)
|
|
892
|
+
tool_config_files[category] = path
|
|
893
|
+
else:
|
|
894
|
+
print(f"ā Invalid tool config file format: {config_spec}")
|
|
895
|
+
print(" Expected format: 'category:/path/to/config.json'")
|
|
896
|
+
sys.exit(1)
|
|
897
|
+
|
|
898
|
+
if exclude_tools:
|
|
899
|
+
print(f"š« Excluding tools: {', '.join(exclude_tools)}")
|
|
900
|
+
if exclude_categories:
|
|
901
|
+
print(f"š« Excluding categories: {', '.join(exclude_categories)}")
|
|
902
|
+
if include_tools:
|
|
903
|
+
print(f"ā
Including only specific tools: {len(include_tools)} tools")
|
|
904
|
+
if tools_file:
|
|
905
|
+
print(f"š Loading tools from file: {tools_file}")
|
|
906
|
+
if tool_config_files:
|
|
907
|
+
print(f"š¦ Additional config files: {', '.join(tool_config_files.keys())}")
|
|
908
|
+
if include_tool_types:
|
|
909
|
+
print(f"šÆ Including tool types: {', '.join(include_tool_types)}")
|
|
910
|
+
if exclude_tool_types:
|
|
911
|
+
print(f"š« Excluding tool types: {', '.join(exclude_tool_types)}")
|
|
912
|
+
|
|
913
|
+
# Load hook configuration if specified
|
|
914
|
+
hook_config = None
|
|
915
|
+
if args.hook_config_file:
|
|
916
|
+
import json
|
|
917
|
+
|
|
918
|
+
with open(args.hook_config_file, "r") as f:
|
|
919
|
+
hook_config = json.load(f)
|
|
920
|
+
print(f"š Hook config loaded from: {args.hook_config_file}")
|
|
921
|
+
|
|
922
|
+
# Determine hook settings
|
|
923
|
+
hooks_enabled = (
|
|
924
|
+
args.hooks_enabled or args.hook_type is not None or hook_config is not None
|
|
925
|
+
)
|
|
926
|
+
if hooks_enabled:
|
|
927
|
+
if args.hook_type:
|
|
928
|
+
print(f"š Hooks enabled: {args.hook_type}")
|
|
929
|
+
elif hook_config:
|
|
930
|
+
hook_count = len(hook_config.get("hooks", []))
|
|
931
|
+
print(f"š Hooks enabled: {hook_count} custom hooks")
|
|
932
|
+
else:
|
|
933
|
+
print("š Hooks enabled: default configuration")
|
|
934
|
+
else:
|
|
935
|
+
print("š Hooks disabled")
|
|
936
|
+
|
|
937
|
+
print(f"ā” Max workers: {args.max_workers}")
|
|
938
|
+
print()
|
|
939
|
+
|
|
940
|
+
# Create SMCP server with hook support
|
|
941
|
+
server = SMCP(
|
|
942
|
+
name=args.name,
|
|
943
|
+
tool_categories=tool_categories,
|
|
944
|
+
exclude_tools=exclude_tools,
|
|
945
|
+
exclude_categories=exclude_categories,
|
|
946
|
+
include_tools=include_tools,
|
|
947
|
+
tools_file=tools_file,
|
|
948
|
+
tool_config_files=tool_config_files,
|
|
949
|
+
include_tool_types=include_tool_types,
|
|
950
|
+
exclude_tool_types=exclude_tool_types,
|
|
951
|
+
search_enabled=not args.no_search,
|
|
952
|
+
max_workers=args.max_workers,
|
|
953
|
+
stateless_http=True, # Enable stateless mode for MCPAutoLoaderTool compatibility
|
|
954
|
+
hooks_enabled=hooks_enabled,
|
|
955
|
+
hook_config=hook_config,
|
|
956
|
+
hook_type=args.hook_type,
|
|
957
|
+
)
|
|
958
|
+
|
|
959
|
+
# Run server
|
|
960
|
+
server.run_simple(transport=args.transport, host=args.host, port=args.port)
|
|
961
|
+
|
|
962
|
+
except KeyboardInterrupt:
|
|
963
|
+
print("\nš Server stopped by user")
|
|
964
|
+
sys.exit(0)
|
|
965
|
+
except Exception as e:
|
|
966
|
+
print(f"ā Error starting server: {e}")
|
|
967
|
+
if args.verbose:
|
|
968
|
+
import traceback
|
|
969
|
+
|
|
970
|
+
traceback.print_exc()
|
|
971
|
+
sys.exit(1)
|
|
972
|
+
|
|
973
|
+
|
|
974
|
+
if __name__ == "__main__":
|
|
975
|
+
run_smcp_server()
|