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.
- aurelian/__init__.py +9 -0
- aurelian/agents/__init__.py +0 -0
- aurelian/agents/amigo/__init__.py +3 -0
- aurelian/agents/amigo/amigo_agent.py +77 -0
- aurelian/agents/amigo/amigo_config.py +85 -0
- aurelian/agents/amigo/amigo_evals.py +73 -0
- aurelian/agents/amigo/amigo_gradio.py +52 -0
- aurelian/agents/amigo/amigo_mcp.py +152 -0
- aurelian/agents/amigo/amigo_tools.py +152 -0
- aurelian/agents/biblio/__init__.py +42 -0
- aurelian/agents/biblio/biblio_agent.py +94 -0
- aurelian/agents/biblio/biblio_config.py +40 -0
- aurelian/agents/biblio/biblio_gradio.py +67 -0
- aurelian/agents/biblio/biblio_mcp.py +115 -0
- aurelian/agents/biblio/biblio_tools.py +164 -0
- aurelian/agents/biblio_agent.py +46 -0
- aurelian/agents/checklist/__init__.py +44 -0
- aurelian/agents/checklist/checklist_agent.py +85 -0
- aurelian/agents/checklist/checklist_config.py +28 -0
- aurelian/agents/checklist/checklist_gradio.py +70 -0
- aurelian/agents/checklist/checklist_mcp.py +86 -0
- aurelian/agents/checklist/checklist_tools.py +141 -0
- aurelian/agents/checklist/content/checklists.yaml +7 -0
- aurelian/agents/checklist/content/streams.csv +136 -0
- aurelian/agents/checklist_agent.py +40 -0
- aurelian/agents/chemistry/__init__.py +3 -0
- aurelian/agents/chemistry/chemistry_agent.py +46 -0
- aurelian/agents/chemistry/chemistry_config.py +71 -0
- aurelian/agents/chemistry/chemistry_evals.py +79 -0
- aurelian/agents/chemistry/chemistry_gradio.py +50 -0
- aurelian/agents/chemistry/chemistry_mcp.py +120 -0
- aurelian/agents/chemistry/chemistry_tools.py +121 -0
- aurelian/agents/chemistry/image_agent.py +15 -0
- aurelian/agents/d4d/__init__.py +30 -0
- aurelian/agents/d4d/d4d_agent.py +72 -0
- aurelian/agents/d4d/d4d_config.py +46 -0
- aurelian/agents/d4d/d4d_gradio.py +58 -0
- aurelian/agents/d4d/d4d_mcp.py +71 -0
- aurelian/agents/d4d/d4d_tools.py +157 -0
- aurelian/agents/d4d_agent.py +64 -0
- aurelian/agents/diagnosis/__init__.py +33 -0
- aurelian/agents/diagnosis/diagnosis_agent.py +53 -0
- aurelian/agents/diagnosis/diagnosis_config.py +48 -0
- aurelian/agents/diagnosis/diagnosis_evals.py +76 -0
- aurelian/agents/diagnosis/diagnosis_gradio.py +52 -0
- aurelian/agents/diagnosis/diagnosis_mcp.py +141 -0
- aurelian/agents/diagnosis/diagnosis_tools.py +204 -0
- aurelian/agents/diagnosis_agent.py +28 -0
- aurelian/agents/draw/__init__.py +3 -0
- aurelian/agents/draw/draw_agent.py +39 -0
- aurelian/agents/draw/draw_config.py +26 -0
- aurelian/agents/draw/draw_gradio.py +50 -0
- aurelian/agents/draw/draw_mcp.py +94 -0
- aurelian/agents/draw/draw_tools.py +100 -0
- aurelian/agents/draw/judge_agent.py +18 -0
- aurelian/agents/filesystem/__init__.py +0 -0
- aurelian/agents/filesystem/filesystem_config.py +27 -0
- aurelian/agents/filesystem/filesystem_gradio.py +49 -0
- aurelian/agents/filesystem/filesystem_mcp.py +89 -0
- aurelian/agents/filesystem/filesystem_tools.py +95 -0
- aurelian/agents/filesystem/py.typed +0 -0
- aurelian/agents/github/__init__.py +0 -0
- aurelian/agents/github/github_agent.py +83 -0
- aurelian/agents/github/github_cli.py +248 -0
- aurelian/agents/github/github_config.py +22 -0
- aurelian/agents/github/github_gradio.py +152 -0
- aurelian/agents/github/github_mcp.py +252 -0
- aurelian/agents/github/github_tools.py +408 -0
- aurelian/agents/github/github_tools.py.tmp +413 -0
- aurelian/agents/goann/__init__.py +13 -0
- aurelian/agents/goann/documents/Transcription_Factors_Annotation_Guidelines.md +1000 -0
- aurelian/agents/goann/documents/Transcription_Factors_Annotation_Guidelines.pdf +0 -0
- aurelian/agents/goann/documents/Transcription_Factors_Annotation_Guidelines_Paper.md +693 -0
- aurelian/agents/goann/documents/Transcription_Factors_Annotation_Guidelines_Paper.pdf +0 -0
- aurelian/agents/goann/goann_agent.py +90 -0
- aurelian/agents/goann/goann_config.py +90 -0
- aurelian/agents/goann/goann_evals.py +104 -0
- aurelian/agents/goann/goann_gradio.py +62 -0
- aurelian/agents/goann/goann_mcp.py +0 -0
- aurelian/agents/goann/goann_tools.py +65 -0
- aurelian/agents/gocam/__init__.py +43 -0
- aurelian/agents/gocam/documents/DNA-binding transcription factor activity annotation guidelines.docx +0 -0
- aurelian/agents/gocam/documents/DNA-binding transcription factor activity annotation guidelines.pdf +0 -0
- aurelian/agents/gocam/documents/DNA-binding_transcription_factor_activity_annotation_guidelines.md +100 -0
- aurelian/agents/gocam/documents/E3 ubiquitin ligases.docx +0 -0
- aurelian/agents/gocam/documents/E3 ubiquitin ligases.pdf +0 -0
- aurelian/agents/gocam/documents/E3_ubiquitin_ligases.md +134 -0
- aurelian/agents/gocam/documents/GO-CAM annotation guidelines README.docx +0 -0
- aurelian/agents/gocam/documents/GO-CAM annotation guidelines README.pdf +0 -0
- aurelian/agents/gocam/documents/GO-CAM modelling guidelines TO DO.docx +0 -0
- aurelian/agents/gocam/documents/GO-CAM modelling guidelines TO DO.pdf +0 -0
- aurelian/agents/gocam/documents/GO-CAM_annotation_guidelines_README.md +1 -0
- aurelian/agents/gocam/documents/GO-CAM_modelling_guidelines_TO_DO.md +3 -0
- aurelian/agents/gocam/documents/How to annotate complexes in GO-CAM.docx +0 -0
- aurelian/agents/gocam/documents/How to annotate complexes in GO-CAM.pdf +0 -0
- aurelian/agents/gocam/documents/How to annotate molecular adaptors.docx +0 -0
- aurelian/agents/gocam/documents/How to annotate molecular adaptors.pdf +0 -0
- aurelian/agents/gocam/documents/How to annotate sequestering proteins.docx +0 -0
- aurelian/agents/gocam/documents/How to annotate sequestering proteins.pdf +0 -0
- aurelian/agents/gocam/documents/How_to_annotate_complexes_in_GO-CAM.md +29 -0
- aurelian/agents/gocam/documents/How_to_annotate_molecular_adaptors.md +31 -0
- aurelian/agents/gocam/documents/How_to_annotate_sequestering_proteins.md +42 -0
- aurelian/agents/gocam/documents/Molecular adaptor activity.docx +0 -0
- aurelian/agents/gocam/documents/Molecular adaptor activity.pdf +0 -0
- aurelian/agents/gocam/documents/Molecular carrier activity.docx +0 -0
- aurelian/agents/gocam/documents/Molecular carrier activity.pdf +0 -0
- aurelian/agents/gocam/documents/Molecular_adaptor_activity.md +51 -0
- aurelian/agents/gocam/documents/Molecular_carrier_activity.md +41 -0
- aurelian/agents/gocam/documents/Protein sequestering activity.docx +0 -0
- aurelian/agents/gocam/documents/Protein sequestering activity.pdf +0 -0
- aurelian/agents/gocam/documents/Protein_sequestering_activity.md +50 -0
- aurelian/agents/gocam/documents/Signaling receptor activity annotation guidelines.docx +0 -0
- aurelian/agents/gocam/documents/Signaling receptor activity annotation guidelines.pdf +0 -0
- aurelian/agents/gocam/documents/Signaling_receptor_activity_annotation_guidelines.md +187 -0
- aurelian/agents/gocam/documents/Transcription coregulator activity.docx +0 -0
- aurelian/agents/gocam/documents/Transcription coregulator activity.pdf +0 -0
- aurelian/agents/gocam/documents/Transcription_coregulator_activity.md +36 -0
- aurelian/agents/gocam/documents/Transporter activity annotation annotation guidelines.docx +0 -0
- aurelian/agents/gocam/documents/Transporter activity annotation annotation guidelines.pdf +0 -0
- aurelian/agents/gocam/documents/Transporter_activity_annotation_annotation_guidelines.md +43 -0
- Regulatory Processes in GO-CAM.docx +0 -0
- Regulatory Processes in GO-CAM.pdf +0 -0
- aurelian/agents/gocam/documents/WIP_-_Regulation_and_Regulatory_Processes_in_GO-CAM.md +31 -0
- aurelian/agents/gocam/documents/md/DNA-binding_transcription_factor_activity_annotation_guidelines.md +131 -0
- aurelian/agents/gocam/documents/md/E3_ubiquitin_ligases.md +166 -0
- aurelian/agents/gocam/documents/md/GO-CAM_annotation_guidelines_README.md +1 -0
- aurelian/agents/gocam/documents/md/GO-CAM_modelling_guidelines_TO_DO.md +5 -0
- aurelian/agents/gocam/documents/md/How_to_annotate_complexes_in_GO-CAM.md +28 -0
- aurelian/agents/gocam/documents/md/How_to_annotate_molecular_adaptors.md +19 -0
- aurelian/agents/gocam/documents/md/How_to_annotate_sequestering_proteins.md +38 -0
- aurelian/agents/gocam/documents/md/Molecular_adaptor_activity.md +52 -0
- aurelian/agents/gocam/documents/md/Molecular_carrier_activity.md +59 -0
- aurelian/agents/gocam/documents/md/Protein_sequestering_activity.md +52 -0
- aurelian/agents/gocam/documents/md/Signaling_receptor_activity_annotation_guidelines.md +271 -0
- aurelian/agents/gocam/documents/md/Transcription_coregulator_activity.md +54 -0
- aurelian/agents/gocam/documents/md/Transporter_activity_annotation_annotation_guidelines.md +38 -0
- aurelian/agents/gocam/documents/md/WIP_-_Regulation_and_Regulatory_Processes_in_GO-CAM.md +39 -0
- aurelian/agents/gocam/documents/pandoc_md/Signaling_receptor_activity_annotation_guidelines.md +334 -0
- aurelian/agents/gocam/gocam_agent.py +240 -0
- aurelian/agents/gocam/gocam_config.py +85 -0
- aurelian/agents/gocam/gocam_curator_agent.py +46 -0
- aurelian/agents/gocam/gocam_evals.py +67 -0
- aurelian/agents/gocam/gocam_gradio.py +89 -0
- aurelian/agents/gocam/gocam_mcp.py +224 -0
- aurelian/agents/gocam/gocam_tools.py +294 -0
- aurelian/agents/linkml/__init__.py +0 -0
- aurelian/agents/linkml/linkml_agent.py +62 -0
- aurelian/agents/linkml/linkml_config.py +48 -0
- aurelian/agents/linkml/linkml_evals.py +66 -0
- aurelian/agents/linkml/linkml_gradio.py +45 -0
- aurelian/agents/linkml/linkml_mcp.py +186 -0
- aurelian/agents/linkml/linkml_tools.py +102 -0
- aurelian/agents/literature/__init__.py +3 -0
- aurelian/agents/literature/literature_agent.py +55 -0
- aurelian/agents/literature/literature_config.py +35 -0
- aurelian/agents/literature/literature_gradio.py +52 -0
- aurelian/agents/literature/literature_mcp.py +174 -0
- aurelian/agents/literature/literature_tools.py +182 -0
- aurelian/agents/monarch/__init__.py +25 -0
- aurelian/agents/monarch/monarch_agent.py +44 -0
- aurelian/agents/monarch/monarch_config.py +45 -0
- aurelian/agents/monarch/monarch_gradio.py +51 -0
- aurelian/agents/monarch/monarch_mcp.py +65 -0
- aurelian/agents/monarch/monarch_tools.py +113 -0
- aurelian/agents/oak/__init__.py +0 -0
- aurelian/agents/oak/oak_config.py +27 -0
- aurelian/agents/oak/oak_gradio.py +57 -0
- aurelian/agents/ontology_mapper/__init__.py +31 -0
- aurelian/agents/ontology_mapper/ontology_mapper_agent.py +56 -0
- aurelian/agents/ontology_mapper/ontology_mapper_config.py +50 -0
- aurelian/agents/ontology_mapper/ontology_mapper_evals.py +108 -0
- aurelian/agents/ontology_mapper/ontology_mapper_gradio.py +58 -0
- aurelian/agents/ontology_mapper/ontology_mapper_mcp.py +81 -0
- aurelian/agents/ontology_mapper/ontology_mapper_tools.py +147 -0
- aurelian/agents/phenopackets/__init__.py +3 -0
- aurelian/agents/phenopackets/phenopackets_agent.py +58 -0
- aurelian/agents/phenopackets/phenopackets_config.py +72 -0
- aurelian/agents/phenopackets/phenopackets_evals.py +99 -0
- aurelian/agents/phenopackets/phenopackets_gradio.py +55 -0
- aurelian/agents/phenopackets/phenopackets_mcp.py +178 -0
- aurelian/agents/phenopackets/phenopackets_tools.py +127 -0
- aurelian/agents/rag/__init__.py +40 -0
- aurelian/agents/rag/rag_agent.py +83 -0
- aurelian/agents/rag/rag_config.py +80 -0
- aurelian/agents/rag/rag_gradio.py +67 -0
- aurelian/agents/rag/rag_mcp.py +107 -0
- aurelian/agents/rag/rag_tools.py +189 -0
- aurelian/agents/rag_agent.py +54 -0
- aurelian/agents/robot/__init__.py +0 -0
- aurelian/agents/robot/assets/__init__.py +3 -0
- aurelian/agents/robot/assets/template.md +384 -0
- aurelian/agents/robot/robot_config.py +25 -0
- aurelian/agents/robot/robot_gradio.py +46 -0
- aurelian/agents/robot/robot_mcp.py +100 -0
- aurelian/agents/robot/robot_ontology_agent.py +139 -0
- aurelian/agents/robot/robot_tools.py +50 -0
- aurelian/agents/talisman/__init__.py +3 -0
- aurelian/agents/talisman/talisman_agent.py +126 -0
- aurelian/agents/talisman/talisman_config.py +66 -0
- aurelian/agents/talisman/talisman_gradio.py +50 -0
- aurelian/agents/talisman/talisman_mcp.py +168 -0
- aurelian/agents/talisman/talisman_tools.py +720 -0
- aurelian/agents/ubergraph/__init__.py +40 -0
- aurelian/agents/ubergraph/ubergraph_agent.py +71 -0
- aurelian/agents/ubergraph/ubergraph_config.py +79 -0
- aurelian/agents/ubergraph/ubergraph_gradio.py +48 -0
- aurelian/agents/ubergraph/ubergraph_mcp.py +69 -0
- aurelian/agents/ubergraph/ubergraph_tools.py +118 -0
- aurelian/agents/uniprot/__init__.py +37 -0
- aurelian/agents/uniprot/uniprot_agent.py +43 -0
- aurelian/agents/uniprot/uniprot_config.py +43 -0
- aurelian/agents/uniprot/uniprot_evals.py +99 -0
- aurelian/agents/uniprot/uniprot_gradio.py +48 -0
- aurelian/agents/uniprot/uniprot_mcp.py +168 -0
- aurelian/agents/uniprot/uniprot_tools.py +136 -0
- aurelian/agents/web/__init__.py +0 -0
- aurelian/agents/web/web_config.py +27 -0
- aurelian/agents/web/web_gradio.py +48 -0
- aurelian/agents/web/web_mcp.py +50 -0
- aurelian/agents/web/web_tools.py +108 -0
- aurelian/chat.py +23 -0
- aurelian/cli.py +800 -0
- aurelian/dependencies/__init__.py +0 -0
- aurelian/dependencies/workdir.py +78 -0
- aurelian/mcp/__init__.py +0 -0
- aurelian/mcp/amigo_mcp_test.py +86 -0
- aurelian/mcp/config_generator.py +123 -0
- aurelian/mcp/example_config.json +43 -0
- aurelian/mcp/generate_sample_config.py +37 -0
- aurelian/mcp/gocam_mcp_test.py +126 -0
- aurelian/mcp/linkml_mcp_tools.py +190 -0
- aurelian/mcp/mcp_discovery.py +87 -0
- aurelian/mcp/mcp_test.py +31 -0
- aurelian/mcp/phenopackets_mcp_test.py +103 -0
- aurelian/tools/__init__.py +0 -0
- aurelian/tools/web/__init__.py +0 -0
- aurelian/tools/web/url_download.py +51 -0
- aurelian/utils/__init__.py +0 -0
- aurelian/utils/async_utils.py +15 -0
- aurelian/utils/data_utils.py +32 -0
- aurelian/utils/documentation_manager.py +59 -0
- aurelian/utils/doi_fetcher.py +238 -0
- aurelian/utils/ontology_utils.py +68 -0
- aurelian/utils/pdf_fetcher.py +23 -0
- aurelian/utils/process_logs.py +100 -0
- aurelian/utils/pubmed_utils.py +238 -0
- aurelian/utils/pytest_report_to_markdown.py +67 -0
- aurelian/utils/robot_ontology_utils.py +112 -0
- aurelian/utils/search_utils.py +95 -0
- aurelian-0.3.2.dist-info/LICENSE +22 -0
- aurelian-0.3.2.dist-info/METADATA +105 -0
- aurelian-0.3.2.dist-info/RECORD +254 -0
- aurelian-0.3.2.dist-info/WHEEL +4 -0
- 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())
|
aurelian/mcp/__init__.py
ADDED
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')
|