aurelian 0.3.2__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.
Files changed (254) hide show
  1. aurelian/__init__.py +9 -0
  2. aurelian/agents/__init__.py +0 -0
  3. aurelian/agents/amigo/__init__.py +3 -0
  4. aurelian/agents/amigo/amigo_agent.py +77 -0
  5. aurelian/agents/amigo/amigo_config.py +85 -0
  6. aurelian/agents/amigo/amigo_evals.py +73 -0
  7. aurelian/agents/amigo/amigo_gradio.py +52 -0
  8. aurelian/agents/amigo/amigo_mcp.py +152 -0
  9. aurelian/agents/amigo/amigo_tools.py +152 -0
  10. aurelian/agents/biblio/__init__.py +42 -0
  11. aurelian/agents/biblio/biblio_agent.py +94 -0
  12. aurelian/agents/biblio/biblio_config.py +40 -0
  13. aurelian/agents/biblio/biblio_gradio.py +67 -0
  14. aurelian/agents/biblio/biblio_mcp.py +115 -0
  15. aurelian/agents/biblio/biblio_tools.py +164 -0
  16. aurelian/agents/biblio_agent.py +46 -0
  17. aurelian/agents/checklist/__init__.py +44 -0
  18. aurelian/agents/checklist/checklist_agent.py +85 -0
  19. aurelian/agents/checklist/checklist_config.py +28 -0
  20. aurelian/agents/checklist/checklist_gradio.py +70 -0
  21. aurelian/agents/checklist/checklist_mcp.py +86 -0
  22. aurelian/agents/checklist/checklist_tools.py +141 -0
  23. aurelian/agents/checklist/content/checklists.yaml +7 -0
  24. aurelian/agents/checklist/content/streams.csv +136 -0
  25. aurelian/agents/checklist_agent.py +40 -0
  26. aurelian/agents/chemistry/__init__.py +3 -0
  27. aurelian/agents/chemistry/chemistry_agent.py +46 -0
  28. aurelian/agents/chemistry/chemistry_config.py +71 -0
  29. aurelian/agents/chemistry/chemistry_evals.py +79 -0
  30. aurelian/agents/chemistry/chemistry_gradio.py +50 -0
  31. aurelian/agents/chemistry/chemistry_mcp.py +120 -0
  32. aurelian/agents/chemistry/chemistry_tools.py +121 -0
  33. aurelian/agents/chemistry/image_agent.py +15 -0
  34. aurelian/agents/d4d/__init__.py +30 -0
  35. aurelian/agents/d4d/d4d_agent.py +72 -0
  36. aurelian/agents/d4d/d4d_config.py +46 -0
  37. aurelian/agents/d4d/d4d_gradio.py +58 -0
  38. aurelian/agents/d4d/d4d_mcp.py +71 -0
  39. aurelian/agents/d4d/d4d_tools.py +157 -0
  40. aurelian/agents/d4d_agent.py +64 -0
  41. aurelian/agents/diagnosis/__init__.py +33 -0
  42. aurelian/agents/diagnosis/diagnosis_agent.py +53 -0
  43. aurelian/agents/diagnosis/diagnosis_config.py +48 -0
  44. aurelian/agents/diagnosis/diagnosis_evals.py +76 -0
  45. aurelian/agents/diagnosis/diagnosis_gradio.py +52 -0
  46. aurelian/agents/diagnosis/diagnosis_mcp.py +141 -0
  47. aurelian/agents/diagnosis/diagnosis_tools.py +204 -0
  48. aurelian/agents/diagnosis_agent.py +28 -0
  49. aurelian/agents/draw/__init__.py +3 -0
  50. aurelian/agents/draw/draw_agent.py +39 -0
  51. aurelian/agents/draw/draw_config.py +26 -0
  52. aurelian/agents/draw/draw_gradio.py +50 -0
  53. aurelian/agents/draw/draw_mcp.py +94 -0
  54. aurelian/agents/draw/draw_tools.py +100 -0
  55. aurelian/agents/draw/judge_agent.py +18 -0
  56. aurelian/agents/filesystem/__init__.py +0 -0
  57. aurelian/agents/filesystem/filesystem_config.py +27 -0
  58. aurelian/agents/filesystem/filesystem_gradio.py +49 -0
  59. aurelian/agents/filesystem/filesystem_mcp.py +89 -0
  60. aurelian/agents/filesystem/filesystem_tools.py +95 -0
  61. aurelian/agents/filesystem/py.typed +0 -0
  62. aurelian/agents/github/__init__.py +0 -0
  63. aurelian/agents/github/github_agent.py +83 -0
  64. aurelian/agents/github/github_cli.py +248 -0
  65. aurelian/agents/github/github_config.py +22 -0
  66. aurelian/agents/github/github_gradio.py +152 -0
  67. aurelian/agents/github/github_mcp.py +252 -0
  68. aurelian/agents/github/github_tools.py +408 -0
  69. aurelian/agents/github/github_tools.py.tmp +413 -0
  70. aurelian/agents/goann/__init__.py +13 -0
  71. aurelian/agents/goann/documents/Transcription_Factors_Annotation_Guidelines.md +1000 -0
  72. aurelian/agents/goann/documents/Transcription_Factors_Annotation_Guidelines.pdf +0 -0
  73. aurelian/agents/goann/documents/Transcription_Factors_Annotation_Guidelines_Paper.md +693 -0
  74. aurelian/agents/goann/documents/Transcription_Factors_Annotation_Guidelines_Paper.pdf +0 -0
  75. aurelian/agents/goann/goann_agent.py +90 -0
  76. aurelian/agents/goann/goann_config.py +90 -0
  77. aurelian/agents/goann/goann_evals.py +104 -0
  78. aurelian/agents/goann/goann_gradio.py +62 -0
  79. aurelian/agents/goann/goann_mcp.py +0 -0
  80. aurelian/agents/goann/goann_tools.py +65 -0
  81. aurelian/agents/gocam/__init__.py +43 -0
  82. aurelian/agents/gocam/documents/DNA-binding transcription factor activity annotation guidelines.docx +0 -0
  83. aurelian/agents/gocam/documents/DNA-binding transcription factor activity annotation guidelines.pdf +0 -0
  84. aurelian/agents/gocam/documents/DNA-binding_transcription_factor_activity_annotation_guidelines.md +100 -0
  85. aurelian/agents/gocam/documents/E3 ubiquitin ligases.docx +0 -0
  86. aurelian/agents/gocam/documents/E3 ubiquitin ligases.pdf +0 -0
  87. aurelian/agents/gocam/documents/E3_ubiquitin_ligases.md +134 -0
  88. aurelian/agents/gocam/documents/GO-CAM annotation guidelines README.docx +0 -0
  89. aurelian/agents/gocam/documents/GO-CAM annotation guidelines README.pdf +0 -0
  90. aurelian/agents/gocam/documents/GO-CAM modelling guidelines TO DO.docx +0 -0
  91. aurelian/agents/gocam/documents/GO-CAM modelling guidelines TO DO.pdf +0 -0
  92. aurelian/agents/gocam/documents/GO-CAM_annotation_guidelines_README.md +1 -0
  93. aurelian/agents/gocam/documents/GO-CAM_modelling_guidelines_TO_DO.md +3 -0
  94. aurelian/agents/gocam/documents/How to annotate complexes in GO-CAM.docx +0 -0
  95. aurelian/agents/gocam/documents/How to annotate complexes in GO-CAM.pdf +0 -0
  96. aurelian/agents/gocam/documents/How to annotate molecular adaptors.docx +0 -0
  97. aurelian/agents/gocam/documents/How to annotate molecular adaptors.pdf +0 -0
  98. aurelian/agents/gocam/documents/How to annotate sequestering proteins.docx +0 -0
  99. aurelian/agents/gocam/documents/How to annotate sequestering proteins.pdf +0 -0
  100. aurelian/agents/gocam/documents/How_to_annotate_complexes_in_GO-CAM.md +29 -0
  101. aurelian/agents/gocam/documents/How_to_annotate_molecular_adaptors.md +31 -0
  102. aurelian/agents/gocam/documents/How_to_annotate_sequestering_proteins.md +42 -0
  103. aurelian/agents/gocam/documents/Molecular adaptor activity.docx +0 -0
  104. aurelian/agents/gocam/documents/Molecular adaptor activity.pdf +0 -0
  105. aurelian/agents/gocam/documents/Molecular carrier activity.docx +0 -0
  106. aurelian/agents/gocam/documents/Molecular carrier activity.pdf +0 -0
  107. aurelian/agents/gocam/documents/Molecular_adaptor_activity.md +51 -0
  108. aurelian/agents/gocam/documents/Molecular_carrier_activity.md +41 -0
  109. aurelian/agents/gocam/documents/Protein sequestering activity.docx +0 -0
  110. aurelian/agents/gocam/documents/Protein sequestering activity.pdf +0 -0
  111. aurelian/agents/gocam/documents/Protein_sequestering_activity.md +50 -0
  112. aurelian/agents/gocam/documents/Signaling receptor activity annotation guidelines.docx +0 -0
  113. aurelian/agents/gocam/documents/Signaling receptor activity annotation guidelines.pdf +0 -0
  114. aurelian/agents/gocam/documents/Signaling_receptor_activity_annotation_guidelines.md +187 -0
  115. aurelian/agents/gocam/documents/Transcription coregulator activity.docx +0 -0
  116. aurelian/agents/gocam/documents/Transcription coregulator activity.pdf +0 -0
  117. aurelian/agents/gocam/documents/Transcription_coregulator_activity.md +36 -0
  118. aurelian/agents/gocam/documents/Transporter activity annotation annotation guidelines.docx +0 -0
  119. aurelian/agents/gocam/documents/Transporter activity annotation annotation guidelines.pdf +0 -0
  120. aurelian/agents/gocam/documents/Transporter_activity_annotation_annotation_guidelines.md +43 -0
  121. Regulatory Processes in GO-CAM.docx +0 -0
  122. Regulatory Processes in GO-CAM.pdf +0 -0
  123. aurelian/agents/gocam/documents/WIP_-_Regulation_and_Regulatory_Processes_in_GO-CAM.md +31 -0
  124. aurelian/agents/gocam/documents/md/DNA-binding_transcription_factor_activity_annotation_guidelines.md +131 -0
  125. aurelian/agents/gocam/documents/md/E3_ubiquitin_ligases.md +166 -0
  126. aurelian/agents/gocam/documents/md/GO-CAM_annotation_guidelines_README.md +1 -0
  127. aurelian/agents/gocam/documents/md/GO-CAM_modelling_guidelines_TO_DO.md +5 -0
  128. aurelian/agents/gocam/documents/md/How_to_annotate_complexes_in_GO-CAM.md +28 -0
  129. aurelian/agents/gocam/documents/md/How_to_annotate_molecular_adaptors.md +19 -0
  130. aurelian/agents/gocam/documents/md/How_to_annotate_sequestering_proteins.md +38 -0
  131. aurelian/agents/gocam/documents/md/Molecular_adaptor_activity.md +52 -0
  132. aurelian/agents/gocam/documents/md/Molecular_carrier_activity.md +59 -0
  133. aurelian/agents/gocam/documents/md/Protein_sequestering_activity.md +52 -0
  134. aurelian/agents/gocam/documents/md/Signaling_receptor_activity_annotation_guidelines.md +271 -0
  135. aurelian/agents/gocam/documents/md/Transcription_coregulator_activity.md +54 -0
  136. aurelian/agents/gocam/documents/md/Transporter_activity_annotation_annotation_guidelines.md +38 -0
  137. aurelian/agents/gocam/documents/md/WIP_-_Regulation_and_Regulatory_Processes_in_GO-CAM.md +39 -0
  138. aurelian/agents/gocam/documents/pandoc_md/Signaling_receptor_activity_annotation_guidelines.md +334 -0
  139. aurelian/agents/gocam/gocam_agent.py +240 -0
  140. aurelian/agents/gocam/gocam_config.py +85 -0
  141. aurelian/agents/gocam/gocam_curator_agent.py +46 -0
  142. aurelian/agents/gocam/gocam_evals.py +67 -0
  143. aurelian/agents/gocam/gocam_gradio.py +89 -0
  144. aurelian/agents/gocam/gocam_mcp.py +224 -0
  145. aurelian/agents/gocam/gocam_tools.py +294 -0
  146. aurelian/agents/linkml/__init__.py +0 -0
  147. aurelian/agents/linkml/linkml_agent.py +62 -0
  148. aurelian/agents/linkml/linkml_config.py +48 -0
  149. aurelian/agents/linkml/linkml_evals.py +66 -0
  150. aurelian/agents/linkml/linkml_gradio.py +45 -0
  151. aurelian/agents/linkml/linkml_mcp.py +186 -0
  152. aurelian/agents/linkml/linkml_tools.py +102 -0
  153. aurelian/agents/literature/__init__.py +3 -0
  154. aurelian/agents/literature/literature_agent.py +55 -0
  155. aurelian/agents/literature/literature_config.py +35 -0
  156. aurelian/agents/literature/literature_gradio.py +52 -0
  157. aurelian/agents/literature/literature_mcp.py +174 -0
  158. aurelian/agents/literature/literature_tools.py +182 -0
  159. aurelian/agents/monarch/__init__.py +25 -0
  160. aurelian/agents/monarch/monarch_agent.py +44 -0
  161. aurelian/agents/monarch/monarch_config.py +45 -0
  162. aurelian/agents/monarch/monarch_gradio.py +51 -0
  163. aurelian/agents/monarch/monarch_mcp.py +65 -0
  164. aurelian/agents/monarch/monarch_tools.py +113 -0
  165. aurelian/agents/oak/__init__.py +0 -0
  166. aurelian/agents/oak/oak_config.py +27 -0
  167. aurelian/agents/oak/oak_gradio.py +57 -0
  168. aurelian/agents/ontology_mapper/__init__.py +31 -0
  169. aurelian/agents/ontology_mapper/ontology_mapper_agent.py +56 -0
  170. aurelian/agents/ontology_mapper/ontology_mapper_config.py +50 -0
  171. aurelian/agents/ontology_mapper/ontology_mapper_evals.py +108 -0
  172. aurelian/agents/ontology_mapper/ontology_mapper_gradio.py +58 -0
  173. aurelian/agents/ontology_mapper/ontology_mapper_mcp.py +81 -0
  174. aurelian/agents/ontology_mapper/ontology_mapper_tools.py +147 -0
  175. aurelian/agents/phenopackets/__init__.py +3 -0
  176. aurelian/agents/phenopackets/phenopackets_agent.py +58 -0
  177. aurelian/agents/phenopackets/phenopackets_config.py +72 -0
  178. aurelian/agents/phenopackets/phenopackets_evals.py +99 -0
  179. aurelian/agents/phenopackets/phenopackets_gradio.py +55 -0
  180. aurelian/agents/phenopackets/phenopackets_mcp.py +178 -0
  181. aurelian/agents/phenopackets/phenopackets_tools.py +127 -0
  182. aurelian/agents/rag/__init__.py +40 -0
  183. aurelian/agents/rag/rag_agent.py +83 -0
  184. aurelian/agents/rag/rag_config.py +80 -0
  185. aurelian/agents/rag/rag_gradio.py +67 -0
  186. aurelian/agents/rag/rag_mcp.py +107 -0
  187. aurelian/agents/rag/rag_tools.py +189 -0
  188. aurelian/agents/rag_agent.py +54 -0
  189. aurelian/agents/robot/__init__.py +0 -0
  190. aurelian/agents/robot/assets/__init__.py +3 -0
  191. aurelian/agents/robot/assets/template.md +384 -0
  192. aurelian/agents/robot/robot_config.py +25 -0
  193. aurelian/agents/robot/robot_gradio.py +46 -0
  194. aurelian/agents/robot/robot_mcp.py +100 -0
  195. aurelian/agents/robot/robot_ontology_agent.py +139 -0
  196. aurelian/agents/robot/robot_tools.py +50 -0
  197. aurelian/agents/talisman/__init__.py +3 -0
  198. aurelian/agents/talisman/talisman_agent.py +126 -0
  199. aurelian/agents/talisman/talisman_config.py +66 -0
  200. aurelian/agents/talisman/talisman_gradio.py +50 -0
  201. aurelian/agents/talisman/talisman_mcp.py +168 -0
  202. aurelian/agents/talisman/talisman_tools.py +720 -0
  203. aurelian/agents/ubergraph/__init__.py +40 -0
  204. aurelian/agents/ubergraph/ubergraph_agent.py +71 -0
  205. aurelian/agents/ubergraph/ubergraph_config.py +79 -0
  206. aurelian/agents/ubergraph/ubergraph_gradio.py +48 -0
  207. aurelian/agents/ubergraph/ubergraph_mcp.py +69 -0
  208. aurelian/agents/ubergraph/ubergraph_tools.py +118 -0
  209. aurelian/agents/uniprot/__init__.py +37 -0
  210. aurelian/agents/uniprot/uniprot_agent.py +43 -0
  211. aurelian/agents/uniprot/uniprot_config.py +43 -0
  212. aurelian/agents/uniprot/uniprot_evals.py +99 -0
  213. aurelian/agents/uniprot/uniprot_gradio.py +48 -0
  214. aurelian/agents/uniprot/uniprot_mcp.py +168 -0
  215. aurelian/agents/uniprot/uniprot_tools.py +136 -0
  216. aurelian/agents/web/__init__.py +0 -0
  217. aurelian/agents/web/web_config.py +27 -0
  218. aurelian/agents/web/web_gradio.py +48 -0
  219. aurelian/agents/web/web_mcp.py +50 -0
  220. aurelian/agents/web/web_tools.py +108 -0
  221. aurelian/chat.py +23 -0
  222. aurelian/cli.py +800 -0
  223. aurelian/dependencies/__init__.py +0 -0
  224. aurelian/dependencies/workdir.py +78 -0
  225. aurelian/mcp/__init__.py +0 -0
  226. aurelian/mcp/amigo_mcp_test.py +86 -0
  227. aurelian/mcp/config_generator.py +123 -0
  228. aurelian/mcp/example_config.json +43 -0
  229. aurelian/mcp/generate_sample_config.py +37 -0
  230. aurelian/mcp/gocam_mcp_test.py +126 -0
  231. aurelian/mcp/linkml_mcp_tools.py +190 -0
  232. aurelian/mcp/mcp_discovery.py +87 -0
  233. aurelian/mcp/mcp_test.py +31 -0
  234. aurelian/mcp/phenopackets_mcp_test.py +103 -0
  235. aurelian/tools/__init__.py +0 -0
  236. aurelian/tools/web/__init__.py +0 -0
  237. aurelian/tools/web/url_download.py +51 -0
  238. aurelian/utils/__init__.py +0 -0
  239. aurelian/utils/async_utils.py +15 -0
  240. aurelian/utils/data_utils.py +32 -0
  241. aurelian/utils/documentation_manager.py +59 -0
  242. aurelian/utils/doi_fetcher.py +238 -0
  243. aurelian/utils/ontology_utils.py +68 -0
  244. aurelian/utils/pdf_fetcher.py +23 -0
  245. aurelian/utils/process_logs.py +100 -0
  246. aurelian/utils/pubmed_utils.py +238 -0
  247. aurelian/utils/pytest_report_to_markdown.py +67 -0
  248. aurelian/utils/robot_ontology_utils.py +112 -0
  249. aurelian/utils/search_utils.py +95 -0
  250. aurelian-0.3.2.dist-info/LICENSE +22 -0
  251. aurelian-0.3.2.dist-info/METADATA +105 -0
  252. aurelian-0.3.2.dist-info/RECORD +254 -0
  253. aurelian-0.3.2.dist-info/WHEEL +4 -0
  254. aurelian-0.3.2.dist-info/entry_points.txt +3 -0
File without changes
@@ -0,0 +1,78 @@
1
+ import tempfile
2
+ from abc import ABC
3
+ from dataclasses import dataclass, field
4
+ from pathlib import Path
5
+ from typing import List
6
+
7
+
8
+ @dataclass
9
+ class WorkDir:
10
+ """
11
+ Class to handle working directory operations.
12
+
13
+ Example:
14
+
15
+ >>> wd = WorkDir.create_temporary_workdir()
16
+ >>> wd.check_file_exists("test.txt")
17
+ False
18
+ >>> wd.write_file("test.txt", "Hello, world!")
19
+ >>> wd.check_file_exists("test.txt")
20
+ True
21
+ >>> wd.read_file("test.txt")
22
+ 'Hello, world!'
23
+ """
24
+ location: str = field(default_factory=lambda: "/tmp")
25
+
26
+ @classmethod
27
+ def create_temporary_workdir(cls) -> "WorkDir":
28
+ temp_dir = tempfile.mkdtemp()
29
+ return cls(location=temp_dir)
30
+
31
+ def _ensure_location(self):
32
+ location = Path(self.location)
33
+ location.mkdir(parents=True, exist_ok=True)
34
+
35
+ def __post_init__(self):
36
+ self._ensure_location()
37
+
38
+
39
+ def get_file_path(self, file_name: str) -> Path:
40
+ self._ensure_location()
41
+ return Path(self.location) / file_name
42
+
43
+ def read_file(self, file_path: str) -> str:
44
+ self._ensure_location()
45
+ file_path = self.get_file_path(file_path)
46
+ with open(file_path, "r") as f:
47
+ return f.read()
48
+
49
+ def check_file_exists(self, file_path: str) -> bool:
50
+ self._ensure_location()
51
+ return self.get_file_path(file_path).exists()
52
+
53
+ def write_file(self, file_path: str, content: str) -> None:
54
+ self._ensure_location()
55
+ file_path = self.get_file_path(file_path)
56
+ with open(file_path, "w") as f:
57
+ f.write(content)
58
+
59
+ def delete_file(self, file_path: str) -> None:
60
+ self._ensure_location()
61
+ file_path = self.get_file_path(file_path)
62
+ file_path.unlink()
63
+
64
+ def list_file_names(self) -> List[str]:
65
+ """
66
+ List the names of all files in the working directory.
67
+
68
+ Note: the working directory is not recursively searched, it is flat
69
+
70
+ Returns:
71
+ list of file names
72
+ """
73
+ self._ensure_location()
74
+ return [f.name for f in Path(self.location).iterdir() if f.is_file()]
75
+
76
+ @dataclass
77
+ class HasWorkdir(ABC):
78
+ workdir: WorkDir = field(default_factory=lambda: WorkDir())
File without changes
@@ -0,0 +1,86 @@
1
+ """
2
+ Test for AmiGO MCP functionality
3
+ """
4
+ import os
5
+ import tempfile
6
+ from typing import List, Optional, Dict
7
+
8
+ # try to import, don't die if import fails
9
+ try:
10
+ from mcp import Client
11
+ except ImportError:
12
+ print("mcp package not found. Please install it to run this test.")
13
+ Client = None
14
+
15
+ from pydantic import BaseModel
16
+
17
+
18
+ class Message(BaseModel):
19
+ role: str
20
+ content: str
21
+
22
+
23
+ async def test_amigo_mcp():
24
+ """Test the AmiGO MCP agent."""
25
+ client = Client("/tmp/amigo-mcp", exec_args=["python", "-m", "aurelian.agents.amigo.amigo_mcp"])
26
+
27
+ import time
28
+ time.sleep(1) # Give the server time to start
29
+
30
+ # Set up a temporary working directory for the test
31
+ tempdir = os.path.join(tempfile.gettempdir(), "test_amigo")
32
+ os.makedirs(tempdir, exist_ok=True)
33
+ os.environ["AURELIAN_WORKDIR"] = tempdir
34
+
35
+ # For testing - would normally come from configuration
36
+ os.environ["AMIGO_TAXON"] = "9606" # Human
37
+
38
+ convo: List[Message] = []
39
+
40
+ def add_to_convo(role: str, content: str) -> Message:
41
+ msg = Message(role=role, content=content)
42
+ convo.append(msg)
43
+ return msg
44
+
45
+ # Make a query
46
+ add_to_convo("user", "What tools are available for working with Gene Ontology?")
47
+
48
+ message = convo[-1].content
49
+
50
+ response = await client.chat(messages=message)
51
+ print(f"Got response: {response}")
52
+
53
+ # Get available tools
54
+ tool_choices = await client.get_tool_choice(messages=convo)
55
+ print(f"Available tools: {[t['id'] for t in tool_choices]}")
56
+
57
+ # Test gene association lookup
58
+ find_gene_associations_tool = next((t for t in tool_choices if t["id"] == "find_gene_associations"), None)
59
+ if find_gene_associations_tool:
60
+ print(f"Testing find_gene_associations tool...")
61
+ tool_input = '{"gene_id": "UniProtKB:P04637"}' # p53
62
+ try:
63
+ tool_result = await client.execute_tool(tool_id=find_gene_associations_tool["id"], tool_input=tool_input)
64
+ print(f"find_gene_associations result length: {len(tool_result)}")
65
+ print(f"First result: {tool_result[:200]}...") # Just show first 200 chars
66
+ except Exception as e:
67
+ print(f"find_gene_associations failed (expected in test): {e}")
68
+
69
+ # Test PMID lookup
70
+ lookup_pmid_tool = next((t for t in tool_choices if t["id"] == "lookup_pmid"), None)
71
+ if lookup_pmid_tool:
72
+ print(f"Testing lookup_pmid tool...")
73
+ tool_input = '{"pmid": "PMID:19661248"}'
74
+ try:
75
+ tool_result = await client.execute_tool(tool_id=lookup_pmid_tool["id"], tool_input=tool_input)
76
+ print(f"lookup_pmid result length: {len(tool_result)}")
77
+ print(f"First part of result: {tool_result[:200]}...")
78
+ except Exception as e:
79
+ print(f"lookup_pmid failed (expected in test): {e}")
80
+
81
+ await client.close()
82
+
83
+
84
+ if __name__ == "__main__":
85
+ import asyncio
86
+ asyncio.run(test_amigo_mcp())
@@ -0,0 +1,123 @@
1
+ #!/usr/bin/env python
2
+ """
3
+ MCP Configuration Generator
4
+
5
+ Utility script to generate Model Context Protocol (MCP) server configuration from a simplified input.
6
+ """
7
+
8
+ import json
9
+ import os
10
+ import argparse
11
+ from typing import Dict, Optional, Any
12
+ from pathlib import Path
13
+
14
+
15
+ class MCPConfigGenerator:
16
+ """Generator for MCP server configuration."""
17
+
18
+ def __init__(self, base_dir: Optional[str] = None):
19
+ """
20
+ Initialize the MCP config generator.
21
+
22
+ Args:
23
+ base_dir: Base directory for resolving relative paths (defaults to current working directory)
24
+ """
25
+ self.base_dir = base_dir or os.getcwd()
26
+
27
+ def generate_config(self, config: Dict[str, Any]) -> Dict[str, Any]:
28
+ """
29
+ Generate a full MCP server configuration from a simplified config.
30
+
31
+ Args:
32
+ config: Simplified configuration dictionary
33
+
34
+ Returns:
35
+ Complete MCP server configuration
36
+ """
37
+ mcp_servers = {}
38
+
39
+ for server_name, server_config in config.items():
40
+ server_type = server_config.get("type", "custom")
41
+
42
+ if server_type == "memory":
43
+ # Memory server configuration
44
+ memory_path = server_config.get("memory_path", os.path.expanduser("~/.mcp/memory.json"))
45
+ mcp_servers[server_name] = {
46
+ "command": "npx",
47
+ "args": ["-y", "@modelcontextprotocol/server-memory"],
48
+ "env": {"MEMORY_FILE_PATH": memory_path},
49
+ }
50
+ elif server_type in ["linkml", "gocam", "phenopackets", "robot", "amigo", "uniprot", "diagnosis"]:
51
+ # Aurelian agent MCP server
52
+ agent_script = f"src/aurelian/agents/{server_type}/{server_type}_mcp.py"
53
+ workdir = server_config.get("workdir", f"/tmp/{server_type}")
54
+
55
+ # Construct environment variables
56
+ env = {"AURELIAN_WORKDIR": workdir}
57
+
58
+ # Add optional environment variables
59
+ if "email" in server_config:
60
+ env["EMAIL"] = server_config["email"]
61
+ if "doi_urls" in server_config:
62
+ env["DOI_FULL_TEXT_URLS"] = server_config["doi_urls"]
63
+
64
+ # Add any additional env vars from config
65
+ if "env" in server_config:
66
+ env.update(server_config["env"])
67
+
68
+ script_path = str(Path(self.base_dir) / agent_script)
69
+ mcp_servers[server_name] = {
70
+ "command": server_config.get("python_path", "/usr/bin/python"),
71
+ "args": [script_path],
72
+ "env": env,
73
+ }
74
+ elif server_type == "custom":
75
+ # Custom server configuration (direct passthrough)
76
+ mcp_servers[server_name] = {
77
+ "command": server_config["command"],
78
+ "args": server_config["args"],
79
+ "env": server_config.get("env", {}),
80
+ }
81
+
82
+ return {"mcpServers": mcp_servers}
83
+
84
+ def write_config(self, config: Dict[str, Any], output_path: str) -> None:
85
+ """
86
+ Write the generated configuration to a file.
87
+
88
+ Args:
89
+ config: The simplified configuration dictionary
90
+ output_path: Path to write the generated configuration
91
+ """
92
+ full_config = self.generate_config(config)
93
+
94
+ with open(output_path, "w") as f:
95
+ json.dump(full_config, f, indent=2)
96
+
97
+ print(f"MCP configuration written to {output_path}")
98
+
99
+
100
+ def parse_args():
101
+ """Parse command line arguments."""
102
+ parser = argparse.ArgumentParser(description="Generate MCP server configuration")
103
+ parser.add_argument("--config", "-c", required=True, help="Path to simplified config file")
104
+ parser.add_argument("--output", "-o", required=True, help="Path to write generated config")
105
+ parser.add_argument("--base-dir", "-b", help="Base directory for resolving paths")
106
+ return parser.parse_args()
107
+
108
+
109
+ def main():
110
+ """Main entrypoint."""
111
+ args = parse_args()
112
+
113
+ # Load simplified config
114
+ with open(args.config) as f:
115
+ config = json.load(f)
116
+
117
+ # Generate and write config
118
+ generator = MCPConfigGenerator(base_dir=args.base_dir)
119
+ generator.write_config(config, args.output)
120
+
121
+
122
+ if __name__ == "__main__":
123
+ main()
@@ -0,0 +1,43 @@
1
+ {
2
+ "memory": {
3
+ "type": "memory",
4
+ "memory_path": "~/.mcp/memory.json"
5
+ },
6
+ "linkml": {
7
+ "type": "linkml",
8
+ "workdir": "/tmp/linkml",
9
+ "python_path": "/usr/bin/python"
10
+ },
11
+ "gocam": {
12
+ "type": "gocam",
13
+ "workdir": "/tmp/gocam",
14
+ "email": "user@example.com",
15
+ "doi_urls": "https://example.com/doi-resolver",
16
+ "python_path": "/usr/bin/python"
17
+ },
18
+ "phenopackets": {
19
+ "type": "phenopackets",
20
+ "workdir": "/tmp/phenopackets",
21
+ "email": "user@example.com",
22
+ "python_path": "/usr/bin/python"
23
+ },
24
+ "robot": {
25
+ "type": "robot",
26
+ "workdir": "/tmp/robot",
27
+ "python_path": "/usr/bin/python"
28
+ },
29
+ "diagnosis": {
30
+ "type": "diagnosis",
31
+ "workdir": "/tmp/diagnosis",
32
+ "python_path": "/usr/bin/python"
33
+ },
34
+ "custom_server": {
35
+ "type": "custom",
36
+ "command": "/path/to/executable",
37
+ "args": ["arg1", "arg2"],
38
+ "env": {
39
+ "ENV_VAR1": "value1",
40
+ "ENV_VAR2": "value2"
41
+ }
42
+ }
43
+ }
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env python
2
+ """
3
+ Example script to generate a sample MCP configuration file using the config generator.
4
+ """
5
+
6
+ import os
7
+ import json
8
+ from pathlib import Path
9
+ from config_generator import MCPConfigGenerator
10
+
11
+ # Define the base directory for Aurelian
12
+ aurelian_dir = Path(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__)))))
13
+ print(f"Aurelian directory: {aurelian_dir}")
14
+
15
+ # Create a simple configuration
16
+ simple_config = {
17
+ "memory": {"type": "memory", "memory_path": "~/.mcp/memory.json"},
18
+ "linkml": {"type": "linkml", "workdir": "/tmp/linkml"},
19
+ "gocam": {
20
+ "type": "gocam",
21
+ "workdir": "/tmp/gocam",
22
+ "email": "user@example.com",
23
+ "doi_urls": "https://example.com/doi-resolver",
24
+ },
25
+ }
26
+
27
+ # Generate the configuration
28
+ generator = MCPConfigGenerator(base_dir=str(aurelian_dir))
29
+ full_config = generator.generate_config(simple_config)
30
+
31
+ # Write to a file
32
+ output_path = aurelian_dir / "mcp-config.json"
33
+ with open(output_path, "w") as f:
34
+ json.dump(full_config, f, indent=2)
35
+
36
+ print(f"Generated MCP configuration at: {output_path}")
37
+ print("Use with: mcp start --config mcp-config.json")
@@ -0,0 +1,126 @@
1
+ """
2
+ Test for GOCAM MCP functionality
3
+ """
4
+ import os
5
+ import tempfile
6
+ from typing import List, Optional, Dict
7
+
8
+ # try to import, don't die if import fails
9
+ try:
10
+ from mcp import Client
11
+ except ImportError:
12
+ print("mcp package not found. Please install it to run this test.")
13
+ Client = None
14
+
15
+ from pydantic import BaseModel
16
+
17
+
18
+ class Message(BaseModel):
19
+ role: str
20
+ content: str
21
+
22
+
23
+ async def test_gocam_mcp():
24
+ """Test the GOCAM MCP agent."""
25
+ client = Client("/tmp/gocam-mcp", exec_args=["python", "-m", "aurelian.agents.gocam.gocam_mcp"])
26
+
27
+ import time
28
+ time.sleep(1) # Give the server time to start
29
+
30
+ # Set up a temporary working directory for the test
31
+ tempdir = os.path.join(tempfile.gettempdir(), "test_gocam")
32
+ os.makedirs(tempdir, exist_ok=True)
33
+ os.environ["AURELIAN_WORKDIR"] = tempdir
34
+
35
+ # For testing without a real database - would normally come from configuration
36
+ os.environ["GOCAM_DB_PATH"] = "mongodb://localhost:27017/test_gocams"
37
+ os.environ["GOCAM_DB_NAME"] = "test_gocams"
38
+ os.environ["GOCAM_COLLECTION_NAME"] = "test_main"
39
+
40
+ convo: List[Message] = []
41
+
42
+ def add_to_convo(role: str, content: str) -> Message:
43
+ msg = Message(role=role, content=content)
44
+ convo.append(msg)
45
+ return msg
46
+
47
+ # Make a query
48
+ add_to_convo("user", "What tools are available for working with GO-CAMs?")
49
+
50
+ message = convo[-1].content
51
+
52
+ response = await client.chat(messages=message)
53
+ print(f"Got response: {response}")
54
+
55
+ # Get available tools
56
+ tool_choices = await client.get_tool_choice(messages=convo)
57
+ print(f"Available tools: {[t['id'] for t in tool_choices]}")
58
+
59
+ # Test the list_files tool
60
+ list_files_tool = next((t for t in tool_choices if t["id"] == "list_files"), None)
61
+ if list_files_tool:
62
+ print(f"Testing list_files tool...")
63
+ tool_input_schema = await client.get_tool_input_schema(tool_id=list_files_tool["id"])
64
+ tool_result = await client.execute_tool(tool_id=list_files_tool["id"], tool_input='{}')
65
+ print(f"list_files result: {tool_result}")
66
+
67
+ # Create a test file
68
+ write_file_tool = next((t for t in tool_choices if t["id"] == "write_to_file"), None)
69
+ if write_file_tool:
70
+ print(f"Testing write_to_file tool...")
71
+ tool_input = '{"file_name": "gocam_test.txt", "data": "This is a test file for GOCAM MCP"}'
72
+ tool_result = await client.execute_tool(tool_id=write_file_tool["id"], tool_input=tool_input)
73
+ print(f"write_to_file result: {tool_result}")
74
+
75
+ # Check if the file was created
76
+ if list_files_tool:
77
+ tool_result = await client.execute_tool(tool_id=list_files_tool["id"], tool_input='{}')
78
+ print(f"list_files after writing: {tool_result}")
79
+
80
+ # Read the file
81
+ inspect_file_tool = next((t for t in tool_choices if t["id"] == "inspect_file"), None)
82
+ if inspect_file_tool:
83
+ print(f"Testing inspect_file tool...")
84
+ tool_input = '{"data_file": "gocam_test.txt"}'
85
+ tool_result = await client.execute_tool(tool_id=inspect_file_tool["id"], tool_input=tool_input)
86
+ print(f"inspect_file result: {tool_result}")
87
+
88
+ # Try search function
89
+ search_tool = next((t for t in tool_choices if t["id"] == "search_gocams"), None)
90
+ if search_tool:
91
+ print(f"Testing search_gocams tool...")
92
+ tool_input = '{"query": "apoptosis"}'
93
+ try:
94
+ tool_result = await client.execute_tool(tool_id=search_tool["id"], tool_input=tool_input)
95
+ print(f"search_gocams result: {tool_result[:200]}...") # Just show first 200 chars
96
+ except Exception as e:
97
+ print(f"search_gocams failed (expected in test): {e}")
98
+
99
+ # Test fetch_document
100
+ fetch_doc_tool = next((t for t in tool_choices if t["id"] == "fetch_document"), None)
101
+ if fetch_doc_tool:
102
+ print(f"Testing fetch_document tool...")
103
+ tool_input = '{"name": "Signaling receptor activity annotation guidelines"}'
104
+ try:
105
+ tool_result = await client.execute_tool(tool_id=fetch_doc_tool["id"], tool_input=tool_input)
106
+ print(f"fetch_document result: {tool_result[:200]}...") # Just show first 200 chars
107
+ except Exception as e:
108
+ print(f"fetch_document failed (expected in test without available docs): {e}")
109
+
110
+ # Test validate_gocam_model
111
+ validate_tool = next((t for t in tool_choices if t["id"] == "validate_gocam_model"), None)
112
+ if validate_tool:
113
+ print(f"Testing validate_gocam_model tool...")
114
+ valid_model = '{"model_data": "{\\"id\\": \\"gomodel:test123\\", \\"title\\": \\"Test Model\\"}", "format": "json"}'
115
+ try:
116
+ tool_result = await client.execute_tool(tool_id=validate_tool["id"], tool_input=valid_model)
117
+ print(f"validate_gocam_model result: {tool_result[:200]}...")
118
+ except Exception as e:
119
+ print(f"validate_gocam_model failed: {e}")
120
+
121
+ await client.close()
122
+
123
+
124
+ if __name__ == "__main__":
125
+ import asyncio
126
+ asyncio.run(test_gocam_mcp())
@@ -0,0 +1,190 @@
1
+ """
2
+ MCP tools for creating LinkML schemas and example datasets
3
+ """
4
+ from linkml.generators import JsonSchemaGenerator
5
+ from mcp.server.fastmcp import FastMCP
6
+
7
+ from aurelian.agents.linkml.linkml_agent import LinkMLDependencies
8
+
9
+ # Initialize FastMCP server
10
+ mcp = FastMCP("linkml")
11
+
12
+ import logfire
13
+ from linkml_runtime.loaders import yaml_loader
14
+ from linkml_runtime.linkml_model import SchemaDefinition
15
+ from linkml.validator import validate
16
+ from pydantic_ai import RunContext, ModelRetry
17
+
18
+ from aurelian.dependencies.workdir import WorkDir
19
+
20
+ def deps() -> LinkMLDependencies:
21
+ deps = LinkMLDependencies()
22
+ deps.workdir = WorkDir("/tmp/linkml")
23
+ return deps
24
+
25
+ def ctx() -> RunContext[LinkMLDependencies]:
26
+ rc: RunContext[LinkMLDependencies] = RunContext[LinkMLDependencies](deps=deps())
27
+ return rc
28
+
29
+
30
+ @mcp.tool()
31
+ async def validate_schema(schema: str, save_to_file: str="schema.yaml") -> str:
32
+ """
33
+ Validate a LinkML schema.
34
+
35
+ Args:
36
+ ctx: context
37
+ schema: schema (as yaml) to validate. Do not truncate, always pass the whole schema.
38
+ save_to_file: optional file name to save the schema to. Defaults to schema.yaml
39
+
40
+ Returns:
41
+
42
+ """
43
+ print(f"Validating schema: {schema}")
44
+ try:
45
+ schema = yaml_loader.loads(schema, target_class=SchemaDefinition)
46
+ gen = JsonSchemaGenerator(schema)
47
+ gen.serialize()
48
+ if save_to_file and schema:
49
+ deps().workdir.write_file(save_to_file, schema)
50
+ except Exception as e:
51
+ raise ModelRetry(f"Schema does not validate: {e}")
52
+ return "VALIDATES"
53
+
54
+
55
+ @mcp.tool()
56
+ async def inspect_file(data_file: str) -> str:
57
+ """
58
+ Inspect a file in the working directory.
59
+
60
+ Args:
61
+ ctx:
62
+ data_file: name of file
63
+
64
+ Returns:
65
+
66
+ """
67
+ print(f"Inspecting file: {data_file}")
68
+ return deps().workdir.read_file(data_file)
69
+
70
+
71
+ @mcp.tool()
72
+ async def list_files() -> str:
73
+ """
74
+ List files in the working directory.
75
+
76
+ Args:
77
+ ctx:
78
+
79
+ Returns:
80
+
81
+ """
82
+ return "\n".join(deps().workdir.list_file_names())
83
+
84
+ @mcp.tool()
85
+ async def write_to_file(data: str, file_name: str) -> str:
86
+ """
87
+ Write data to a file in the working directory.
88
+
89
+ Args:
90
+ ctx:
91
+ data:
92
+ file_name:
93
+
94
+ Returns:
95
+
96
+ """
97
+ print(f"Writing data to file: {file_name}")
98
+ deps().workdir.write_file(file_name, data)
99
+ return f"Data written to {file_name}"
100
+
101
+ @mcp.tool()
102
+ async def validate_data(schema: str, data_file: str) -> str:
103
+ """
104
+ Validate data file against a schema.
105
+
106
+ This assumes the data file is present in the working directory.
107
+ You can write data to the working directory using the `write_to_file` tool.
108
+
109
+ Args:
110
+ ctx:
111
+ schema: the schema (as a YAML string)
112
+ data_file: the name of the data file in the working directory
113
+
114
+ Returns:
115
+
116
+ """
117
+ logfire.log(f"Validating data file: {data_file} using schema: {schema}")
118
+ print(f"Validating data file: {data_file} using schema: {schema}")
119
+ try:
120
+ schema = yaml_loader.loads(schema, target_class=SchemaDefinition)
121
+ except Exception as e:
122
+ return f"Schema does not validate: {e}"
123
+ try:
124
+ instances = deps().parse_objects_from_file(data_file)
125
+ for instance in instances:
126
+ print(f"Validating {instance}")
127
+ rpt = validate(instance, schema)
128
+ print(f"Validation report: {rpt}")
129
+ if rpt.results:
130
+ return f"Data does not validate:\n{rpt.results}"
131
+ return f"{len(instances)} instances all validate successfully"
132
+ except Exception as e:
133
+ return f"Data does not validate: {e}"
134
+
135
+
136
+ @mcp.tool()
137
+ async def search_web(query: str) -> str:
138
+ """
139
+ Search the web using a text query.
140
+
141
+ Note, this will not retrieve the full content, for that you
142
+ should use `retrieve_web_page`.
143
+
144
+ Args:
145
+ query: Text query
146
+
147
+ Returns: matching web pages plus summaries
148
+ """
149
+ print(f"Web Search: {query}")
150
+ return web_search(query)
151
+
152
+ @mcp.tool()
153
+ async def retrieve_web_page(url: str) -> str:
154
+ """
155
+ Fetch the contents of a web page.
156
+
157
+ Args:
158
+ url: URL of the web page
159
+
160
+ Returns:
161
+ The contents of the web page.
162
+ """
163
+ print(f"Fetch URL: {url}")
164
+ import aurelian.utils.search_utils as su
165
+ return su.retrieve_web_page(url)
166
+
167
+
168
+ @mcp.tool()
169
+ async def download_web_page(url: str, local_file_name: str) -> str:
170
+ """
171
+ Download contents of a web page.
172
+
173
+ Args:
174
+ ctx:
175
+ url: URL of the web page
176
+ local_file_name: Name of the local file to save the
177
+
178
+ Returns:
179
+ str: message
180
+ """
181
+ print(f"Fetch URL: {url}")
182
+ import aurelian.utils.search_utils as su
183
+ data = su.retrieve_web_page(url)
184
+ deps().workdir.write_file(local_file_name, data)
185
+ return f"Data written to {local_file_name}"
186
+
187
+
188
+ if __name__ == "__main__":
189
+ # Initialize and run the server
190
+ mcp.run(transport='stdio')