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
@@ -39,6 +39,10 @@
39
39
  "type": "string",
40
40
  "description": "Clinical summary and scope of the guideline"
41
41
  },
42
+ "content": {
43
+ "type": "string",
44
+ "description": "Cleaned clinical content extracted from the guideline page"
45
+ },
42
46
  "date": {
43
47
  "type": "string",
44
48
  "description": "Publication or last updated date"
@@ -126,6 +130,14 @@
126
130
  "type": "string"
127
131
  }
128
132
  },
133
+ "abstract": {
134
+ "type": "string",
135
+ "description": "Abstract text returned from PubMed"
136
+ },
137
+ "content": {
138
+ "type": "string",
139
+ "description": "Cleaned clinical content (mirrors abstract)"
140
+ },
129
141
  "is_guideline": {
130
142
  "type": "boolean",
131
143
  "description": "Confirms this is a clinical guideline"
@@ -223,10 +235,14 @@
223
235
  "type": "string",
224
236
  "description": "Type of publication"
225
237
  },
226
- "abstract": {
227
- "type": "string",
228
- "description": "Abstract or summary of the guideline"
229
- },
238
+ "abstract": {
239
+ "type": "string",
240
+ "description": "Abstract or summary of the guideline"
241
+ },
242
+ "content": {
243
+ "type": "string",
244
+ "description": "Extended clinical content extracted from Europe PMC when available"
245
+ },
230
246
  "is_guideline": {
231
247
  "type": "boolean",
232
248
  "description": "Indicates if this is a clinical guideline"
@@ -310,6 +326,48 @@
310
326
  "type": "string",
311
327
  "description": "Category or type of guideline"
312
328
  },
329
+ "description": {
330
+ "type": "string",
331
+ "description": "Short description provided by TRIP"
332
+ },
333
+ "content": {
334
+ "type": "string",
335
+ "description": "Detailed clinical content extracted from the guideline page when available"
336
+ },
337
+ "key_recommendations": {
338
+ "type": "array",
339
+ "description": "Extracted key recommendations (title and summary) when available",
340
+ "items": {
341
+ "type": "object",
342
+ "properties": {
343
+ "title": {
344
+ "type": "string",
345
+ "description": "Heading for the recommendation"
346
+ },
347
+ "summary": {
348
+ "type": "string",
349
+ "description": "Summary text of the recommendation"
350
+ }
351
+ }
352
+ }
353
+ },
354
+ "evidence_strength": {
355
+ "type": "array",
356
+ "description": "Strength-of-evidence or grading statements extracted from the guideline",
357
+ "items": {
358
+ "type": "object",
359
+ "properties": {
360
+ "section": {
361
+ "type": "string",
362
+ "description": "Reference section for the strength statement"
363
+ },
364
+ "strength": {
365
+ "type": "string",
366
+ "description": "Narrative grading (e.g., 'Strong recommendation')"
367
+ }
368
+ }
369
+ }
370
+ },
313
371
  "is_guideline": {
314
372
  "type": "boolean",
315
373
  "description": "Confirms this is a clinical guideline"
@@ -703,5 +761,149 @@
703
761
  }
704
762
  }
705
763
  }
764
+ },
765
+ {
766
+ "type": "GINGuidelinesTool",
767
+ "name": "GIN_Guidelines_Search",
768
+ "description": "Search Guidelines International Network (GIN) guidelines database. GIN maintains the world's largest database of clinical guidelines with over 6400 guidelines from various organizations worldwide.",
769
+ "parameter": {
770
+ "type": "object",
771
+ "properties": {
772
+ "query": {
773
+ "type": "string",
774
+ "description": "Medical condition, treatment, or clinical topic to search for in GIN guidelines (e.g., 'diabetes management', 'hypertension treatment', 'cancer screening')"
775
+ },
776
+ "limit": {
777
+ "type": "integer",
778
+ "description": "Maximum number of guidelines to return (default: 10)",
779
+ "default": 10
780
+ }
781
+ },
782
+ "required": [
783
+ "query",
784
+ "limit"
785
+ ]
786
+ },
787
+ "return_schema": {
788
+ "type": "array",
789
+ "description": "List of GIN clinical guidelines from various international organizations",
790
+ "items": {
791
+ "type": "object",
792
+ "properties": {
793
+ "title": {
794
+ "type": "string",
795
+ "description": "Title of the guideline"
796
+ },
797
+ "url": {
798
+ "type": "string",
799
+ "description": "URL to access the guideline"
800
+ },
801
+ "description": {
802
+ "type": "string",
803
+ "description": "Description or summary of the guideline"
804
+ },
805
+ "date": {
806
+ "type": "string",
807
+ "description": "Publication or update date"
808
+ },
809
+ "source": {
810
+ "type": "string",
811
+ "description": "Source organization (GIN)"
812
+ },
813
+ "organization": {
814
+ "type": "string",
815
+ "description": "Organization that developed the guideline"
816
+ },
817
+ "is_guideline": {
818
+ "type": "boolean",
819
+ "description": "Indicates this is a clinical guideline"
820
+ },
821
+ "official": {
822
+ "type": "boolean",
823
+ "description": "Indicates this is an official publication"
824
+ },
825
+ "content": {
826
+ "type": "string",
827
+ "description": "Full content of the guideline"
828
+ },
829
+ "note": {
830
+ "type": "string",
831
+ "description": "Additional notes about content availability"
832
+ }
833
+ }
834
+ }
835
+ }
836
+ },
837
+ {
838
+ "type": "CMAGuidelinesTool",
839
+ "name": "CMA_Guidelines_Search",
840
+ "description": "Search Canadian Medical Association (CMA) Infobase guidelines. Contains over 1200 evidence-based clinical practice guidelines developed or endorsed by Canadian healthcare organizations.",
841
+ "parameter": {
842
+ "type": "object",
843
+ "properties": {
844
+ "query": {
845
+ "type": "string",
846
+ "description": "Medical condition, treatment, or clinical topic to search for in CMA guidelines (e.g., 'diabetes management', 'hypertension treatment', 'cancer screening')"
847
+ },
848
+ "limit": {
849
+ "type": "integer",
850
+ "description": "Maximum number of guidelines to return (default: 10)",
851
+ "default": 10
852
+ }
853
+ },
854
+ "required": [
855
+ "query",
856
+ "limit"
857
+ ]
858
+ },
859
+ "return_schema": {
860
+ "type": "array",
861
+ "description": "List of CMA Infobase clinical practice guidelines",
862
+ "items": {
863
+ "type": "object",
864
+ "properties": {
865
+ "title": {
866
+ "type": "string",
867
+ "description": "Title of the guideline"
868
+ },
869
+ "url": {
870
+ "type": "string",
871
+ "description": "URL to access the guideline"
872
+ },
873
+ "description": {
874
+ "type": "string",
875
+ "description": "Description or summary of the guideline"
876
+ },
877
+ "date": {
878
+ "type": "string",
879
+ "description": "Publication or update date"
880
+ },
881
+ "source": {
882
+ "type": "string",
883
+ "description": "Source organization (CMA)"
884
+ },
885
+ "organization": {
886
+ "type": "string",
887
+ "description": "Canadian healthcare organization that developed the guideline"
888
+ },
889
+ "is_guideline": {
890
+ "type": "boolean",
891
+ "description": "Indicates this is a clinical guideline"
892
+ },
893
+ "official": {
894
+ "type": "boolean",
895
+ "description": "Indicates this is an official publication"
896
+ },
897
+ "content": {
898
+ "type": "string",
899
+ "description": "Full content of the guideline"
900
+ },
901
+ "note": {
902
+ "type": "string",
903
+ "description": "Additional notes about content availability"
904
+ }
905
+ }
906
+ }
907
+ }
706
908
  }
707
909
  ]
@@ -8,7 +8,7 @@
8
8
  "repo_id": "agenticx/MeSH2025",
9
9
  "path_in_repo": "MeSH_desc2025.xml",
10
10
  "token": null,
11
- "save_to_local_dir": "src/tooluniverse/test"
11
+ "save_to_local_dir": null
12
12
  },
13
13
  "record_xpath": "DescriptorRecord",
14
14
  "search_fields": [
@@ -175,7 +175,7 @@
175
175
  "repo_id": "agenticx/MeSH2025",
176
176
  "path_in_repo": "MeSH_desc2025.xml",
177
177
  "token": null,
178
- "save_to_local_dir": "src/tooluniverse/test"
178
+ "save_to_local_dir": null
179
179
  },
180
180
  "record_xpath": "DescriptorRecord",
181
181
  "search_fields": [
@@ -342,7 +342,7 @@
342
342
  "repo_id": "agenticx/MeSH2025",
343
343
  "path_in_repo": "MeSH_desc2025.xml",
344
344
  "token": null,
345
- "save_to_local_dir": "src/tooluniverse/test"
345
+ "save_to_local_dir": null
346
346
  },
347
347
  "record_xpath": "DescriptorRecord",
348
348
  "search_fields": [
@@ -511,7 +511,7 @@
511
511
  "repo_id": "agenticx/MeSH2025",
512
512
  "path_in_repo": "MeSH_desc2025.xml",
513
513
  "token": null,
514
- "save_to_local_dir": "src/tooluniverse/test"
514
+ "save_to_local_dir": null
515
515
  },
516
516
  "record_xpath": "DescriptorRecord",
517
517
  "search_fields": [
@@ -678,7 +678,7 @@
678
678
  "repo_id": "agenticx/DrugBank",
679
679
  "path_in_repo": "drugbank_full_database.xml",
680
680
  "token": null,
681
- "save_to_local_dir": "src/tooluniverse/test"
681
+ "save_to_local_dir": null
682
682
  },
683
683
  "namespaces": {
684
684
  "db": "http://www.drugbank.ca"
@@ -860,7 +860,7 @@
860
860
  "repo_id": "agenticx/DrugBank",
861
861
  "path_in_repo": "drugbank_full_database.xml",
862
862
  "token": null,
863
- "save_to_local_dir": "src/tooluniverse/test"
863
+ "save_to_local_dir": null
864
864
  },
865
865
  "namespaces": {
866
866
  "db": "http://www.drugbank.ca"
@@ -1036,7 +1036,7 @@
1036
1036
  "repo_id": "agenticx/DrugBank",
1037
1037
  "path_in_repo": "drugbank_full_database.xml",
1038
1038
  "token": null,
1039
- "save_to_local_dir": "src/tooluniverse/test"
1039
+ "save_to_local_dir": null
1040
1040
  },
1041
1041
  "namespaces": {
1042
1042
  "db": "http://www.drugbank.ca"
@@ -1176,7 +1176,7 @@
1176
1176
  "repo_id": "agenticx/DrugBank",
1177
1177
  "path_in_repo": "drugbank_full_database.xml",
1178
1178
  "token": null,
1179
- "save_to_local_dir": "src/tooluniverse/test"
1179
+ "save_to_local_dir": null
1180
1180
  },
1181
1181
  "namespaces": {
1182
1182
  "db": "http://www.drugbank.ca"
@@ -1358,7 +1358,7 @@
1358
1358
  "repo_id": "agenticx/DrugBank",
1359
1359
  "path_in_repo": "drugbank_full_database.xml",
1360
1360
  "token": null,
1361
- "save_to_local_dir": "src/tooluniverse/test"
1361
+ "save_to_local_dir": null
1362
1362
  },
1363
1363
  "namespaces": {
1364
1364
  "db": "http://www.drugbank.ca"
@@ -1538,7 +1538,7 @@
1538
1538
  "repo_id": "agenticx/DrugBank",
1539
1539
  "path_in_repo": "drugbank_full_database.xml",
1540
1540
  "token": null,
1541
- "save_to_local_dir": "src/tooluniverse/test"
1541
+ "save_to_local_dir": null
1542
1542
  },
1543
1543
  "namespaces": {
1544
1544
  "db": "http://www.drugbank.ca"
@@ -1703,7 +1703,7 @@
1703
1703
  "repo_id": "agenticx/DrugBank",
1704
1704
  "path_in_repo": "drugbank_full_database.xml",
1705
1705
  "token": null,
1706
- "save_to_local_dir": "src/tooluniverse/test"
1706
+ "save_to_local_dir": null
1707
1707
  },
1708
1708
  "namespaces": {
1709
1709
  "db": "http://www.drugbank.ca"
@@ -1976,7 +1976,7 @@
1976
1976
  "repo_id": "agenticx/DrugBank",
1977
1977
  "path_in_repo": "drugbank_full_database.xml",
1978
1978
  "token": null,
1979
- "save_to_local_dir": "src/tooluniverse/test"
1979
+ "save_to_local_dir": null
1980
1980
  },
1981
1981
  "namespaces": {
1982
1982
  "db": "http://www.drugbank.ca"
@@ -2134,7 +2134,7 @@
2134
2134
  "repo_id": "agenticx/DrugBank",
2135
2135
  "path_in_repo": "drugbank_full_database.xml",
2136
2136
  "token": null,
2137
- "save_to_local_dir": "src/tooluniverse/test"
2137
+ "save_to_local_dir": null
2138
2138
  },
2139
2139
  "namespaces": {
2140
2140
  "db": "http://www.drugbank.ca"
@@ -2369,7 +2369,7 @@
2369
2369
  "repo_id": "agenticx/DrugBank",
2370
2370
  "path_in_repo": "drugbank_full_database.xml",
2371
2371
  "token": null,
2372
- "save_to_local_dir": "src/tooluniverse/test"
2372
+ "save_to_local_dir": null
2373
2373
  },
2374
2374
  "namespaces": {
2375
2375
  "db": "http://www.drugbank.ca"
@@ -2521,7 +2521,7 @@
2521
2521
  "repo_id": "agenticx/DrugBank",
2522
2522
  "path_in_repo": "drugbank_full_database.xml",
2523
2523
  "token": null,
2524
- "save_to_local_dir": "src/tooluniverse/test"
2524
+ "save_to_local_dir": null
2525
2525
  },
2526
2526
  "namespaces": {
2527
2527
  "db": "http://www.drugbank.ca"
@@ -24,8 +24,7 @@
24
24
  },
25
25
  "required": [
26
26
  "query",
27
- "max_results",
28
- "community"
27
+ "max_results"
29
28
  ]
30
29
  },
31
30
  "return_schema": {
@@ -0,0 +1,71 @@
1
+ import requests
2
+ from .base_tool import BaseTool
3
+ from .tool_registry import register_tool
4
+
5
+
6
+ @register_tool("DbSnpTool")
7
+ class DbSnpTool(BaseTool):
8
+ """
9
+ Local tool wrapper for dbSNP via NCBI Variation Services.
10
+ Fetches variant by rsID using the refsnp endpoint.
11
+ """
12
+
13
+ def __init__(self, tool_config):
14
+ super().__init__(tool_config)
15
+ self.base = "https://api.ncbi.nlm.nih.gov/variation/v0"
16
+ self.session = requests.Session()
17
+
18
+ def run(self, arguments):
19
+ rsid = arguments.get("rsid")
20
+ if not rsid:
21
+ return {"error": "Missing required parameter: rsid"}
22
+
23
+ # Clean rsid (remove 'rs' prefix if present)
24
+ if rsid.startswith("rs"):
25
+ rsid = rsid[2:]
26
+
27
+ url = f"{self.base}/refsnp/{rsid}"
28
+ resp = self.session.get(url, timeout=20)
29
+ resp.raise_for_status()
30
+ data = resp.json()
31
+
32
+ # Extract key fields from primary snapshot
33
+ primary = data.get("primary_snapshot_data", {})
34
+ placements = primary.get("placements_with_allele", [])
35
+
36
+ chrom = ""
37
+ pos = None
38
+ alleles = []
39
+ hgvs = []
40
+
41
+ if placements:
42
+ placement = placements[0]
43
+ chrom = (
44
+ placement.get("seq_id", "").replace("NC_0000", "").replace(".11", "")
45
+ )
46
+ if chrom.startswith("0"):
47
+ chrom = chrom[1:]
48
+ chrom = f"chr{chrom}"
49
+
50
+ allele_data = placement.get("alleles", [])
51
+ for allele in allele_data:
52
+ spdi = allele.get("allele", {}).get("spdi", {})
53
+ if spdi:
54
+ ref = spdi.get("deleted_sequence", "")
55
+ alt = spdi.get("inserted_sequence", "")
56
+ if ref and alt:
57
+ alleles.append(f"{ref}>{alt}")
58
+ elif ref:
59
+ alleles.append(ref)
60
+
61
+ hgvs_val = allele.get("hgvs", "")
62
+ if hgvs_val:
63
+ hgvs.append(hgvs_val)
64
+
65
+ return {
66
+ "refsnp_id": f"rs{rsid}",
67
+ "chrom": chrom,
68
+ "pos": pos,
69
+ "alleles": alleles,
70
+ "hgvs": hgvs,
71
+ }
@@ -51,6 +51,9 @@ default_tool_files = {
51
51
  "fatcat": os.path.join(current_dir, "data", "fatcat_tools.json"),
52
52
  "wikidata_sparql": os.path.join(current_dir, "data", "wikidata_sparql_tools.json"),
53
53
  "agents": os.path.join(current_dir, "data", "agentic_tools.json"),
54
+ "drug_discovery_agents": os.path.join(
55
+ current_dir, "data", "drug_discovery_agents.json"
56
+ ),
54
57
  "dataset": os.path.join(current_dir, "data", "dataset_tools.json"),
55
58
  # 'mcp_clients': os.path.join(current_dir, 'data', 'mcp_client_tools_example.json'),
56
59
  "mcp_auto_loader_txagent": os.path.join(
@@ -142,6 +145,9 @@ default_tool_files = {
142
145
  current_dir, "data", "output_summarization_tools.json"
143
146
  ),
144
147
  "odphp": os.path.join(current_dir, "data", "odphp_tools.json"),
148
+ "markitdown": os.path.join(current_dir, "data", "markitdown_tools.json"),
149
+ # Genomics tools
150
+ "genomics": os.path.join(current_dir, "data", "genomics_tools.json"),
145
151
  # Guideline and health policy tools
146
152
  "guidelines": os.path.join(current_dir, "data", "unified_guideline_tools.json"),
147
153
  }
@@ -0,0 +1,61 @@
1
+ import requests
2
+ from .base_tool import BaseTool
3
+ from .tool_registry import register_tool
4
+
5
+
6
+ @register_tool("EnsemblTool")
7
+ class EnsemblTool(BaseTool):
8
+ """
9
+ Local tool wrapper for Ensembl REST API lookups.
10
+ Supports symbol→gene lookup (xrefs/symbol) then lookup/id to
11
+ fetch metadata.
12
+ """
13
+
14
+ def __init__(self, tool_config):
15
+ super().__init__(tool_config)
16
+ self.base = "https://rest.ensembl.org"
17
+ self.session = requests.Session()
18
+ self.session.headers.update(
19
+ {"Accept": "application/json", "Content-Type": "application/json"}
20
+ )
21
+
22
+ def run(self, arguments):
23
+ species = arguments.get("species", "homo_sapiens")
24
+ symbol = arguments.get("symbol")
25
+ if not symbol:
26
+ return {"error": "Missing required parameter: symbol"}
27
+
28
+ # 1) symbol -> xref(s) to get Ensembl gene ID
29
+ xref_url = f"{self.base}/xrefs/symbol/{species}/{symbol}"
30
+ xref_resp = self.session.get(xref_url, timeout=20)
31
+ xref_resp.raise_for_status()
32
+ xrefs = xref_resp.json() or []
33
+ gene_id = None
34
+ for item in xrefs:
35
+ if item.get("type") == "gene" and item.get("id"):
36
+ gene_id = item["id"]
37
+ break
38
+ if not gene_id and xrefs:
39
+ gene_id = xrefs[0].get("id")
40
+ if not gene_id:
41
+ return {"error": f"No Ensembl gene found for {symbol}"}
42
+
43
+ # 2) lookup by Ensembl ID (expand=1 to include transcripts)
44
+ lookup_url = f"{self.base}/lookup/id/{gene_id}?expand=1"
45
+ look_resp = self.session.get(lookup_url, timeout=30)
46
+ look_resp.raise_for_status()
47
+ data = look_resp.json() or {}
48
+
49
+ transcripts = data.get("Transcript") or []
50
+ return {
51
+ "id": data.get("id"),
52
+ "symbol": symbol,
53
+ "display_name": data.get("display_name"),
54
+ "species": data.get("species"),
55
+ "seq_region_name": data.get("seq_region_name"),
56
+ "start": data.get("start"),
57
+ "end": data.get("end"),
58
+ "strand": data.get("strand"),
59
+ "biotype": data.get("biotype"),
60
+ "transcript_count": len(transcripts),
61
+ }