diff --git a/BioScientist/LICENSE b/BioScientist/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..1f33373449ed4e4e7c4ee337b68578aad5ecfa96 --- /dev/null +++ b/BioScientist/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 florensiawidjaja + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/BioScientist/agent_system/engines/__pycache__/__init__.cpython-310.pyc b/BioScientist/agent_system/engines/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..aedba7018ad6a230ea5a00ad849237297ca534ac Binary files /dev/null and b/BioScientist/agent_system/engines/__pycache__/__init__.cpython-310.pyc differ diff --git a/BioScientist/agent_system/engines/__pycache__/__init__.cpython-311.pyc b/BioScientist/agent_system/engines/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d5aa6cd7cc6c8de2a266cd03fb7565c36a12ca93 Binary files /dev/null and b/BioScientist/agent_system/engines/__pycache__/__init__.cpython-311.pyc differ diff --git a/BioScientist/agent_system/engines/__pycache__/e1_validator.cpython-310.pyc b/BioScientist/agent_system/engines/__pycache__/e1_validator.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9c16aba3734f7a0723020f52bf7bf050c70639b7 Binary files /dev/null and b/BioScientist/agent_system/engines/__pycache__/e1_validator.cpython-310.pyc differ diff --git a/BioScientist/agent_system/engines/__pycache__/e1_validator.cpython-311.pyc b/BioScientist/agent_system/engines/__pycache__/e1_validator.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..34a5f116d047af7cb2a98349a51d7f0d2ca1006a Binary files /dev/null and b/BioScientist/agent_system/engines/__pycache__/e1_validator.cpython-311.pyc differ diff --git a/BioScientist/agent_system/engines/__pycache__/t1_consultant.cpython-310.pyc b/BioScientist/agent_system/engines/__pycache__/t1_consultant.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6afa17a9844b3af89e16f7d70557621f8196438c Binary files /dev/null and b/BioScientist/agent_system/engines/__pycache__/t1_consultant.cpython-310.pyc differ diff --git a/BioScientist/agent_system/engines/__pycache__/t1_consultant.cpython-311.pyc b/BioScientist/agent_system/engines/__pycache__/t1_consultant.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9fafe3a97cf198601f2a87ad6170a26a6d7d41eb Binary files /dev/null and b/BioScientist/agent_system/engines/__pycache__/t1_consultant.cpython-311.pyc differ diff --git a/BioScientist/agent_system/engines/__pycache__/t1_consultant.cpython-313.pyc b/BioScientist/agent_system/engines/__pycache__/t1_consultant.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d064ab2667a43b8ba48dfa70ecd4e20d721371df Binary files /dev/null and b/BioScientist/agent_system/engines/__pycache__/t1_consultant.cpython-313.pyc differ diff --git a/BioScientist/agent_system/engines/__pycache__/v1_executor.cpython-310.pyc b/BioScientist/agent_system/engines/__pycache__/v1_executor.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0e8186dedf15bbdf1745edfb5b88de20d44852d1 Binary files /dev/null and b/BioScientist/agent_system/engines/__pycache__/v1_executor.cpython-310.pyc differ diff --git a/BioScientist/agent_system/engines/__pycache__/v1_executor.cpython-311.pyc b/BioScientist/agent_system/engines/__pycache__/v1_executor.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..156fa9f7d56b2d271ea67df5b79dd21892ff084e Binary files /dev/null and b/BioScientist/agent_system/engines/__pycache__/v1_executor.cpython-311.pyc differ diff --git a/BioScientist/agent_system/engines/v1_executor_backup/__pycache__/__init__.cpython-310.pyc b/BioScientist/agent_system/engines/v1_executor_backup/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b0921608be41e920a5c39fe61591c92c22ba7043 Binary files /dev/null and b/BioScientist/agent_system/engines/v1_executor_backup/__pycache__/__init__.cpython-310.pyc differ diff --git a/BioScientist/agent_system/engines/v1_executor_backup/__pycache__/__init__.cpython-311.pyc b/BioScientist/agent_system/engines/v1_executor_backup/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..444a06fe8484ec3ea3b7130f19b963220de9d0e3 Binary files /dev/null and b/BioScientist/agent_system/engines/v1_executor_backup/__pycache__/__init__.cpython-311.pyc differ diff --git a/BioScientist/agent_system/engines/v1_executor_backup/__pycache__/__init__.cpython-313.pyc b/BioScientist/agent_system/engines/v1_executor_backup/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..623cc6f035a43033cb8cc05eeeace8aa1083c584 Binary files /dev/null and b/BioScientist/agent_system/engines/v1_executor_backup/__pycache__/__init__.cpython-313.pyc differ diff --git a/BioScientist/agent_system/engines/v1_executor_backup/__pycache__/config.cpython-311.pyc b/BioScientist/agent_system/engines/v1_executor_backup/__pycache__/config.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f4f86cb3dc119bc07b7c6e3b10e5fd7c53c181d8 Binary files /dev/null and b/BioScientist/agent_system/engines/v1_executor_backup/__pycache__/config.cpython-311.pyc differ diff --git a/BioScientist/agent_system/engines/v1_executor_backup/__pycache__/env_desc.cpython-311.pyc b/BioScientist/agent_system/engines/v1_executor_backup/__pycache__/env_desc.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..66e608468c37daf471dd0c4cf828ec8d2b52e0f5 Binary files /dev/null and b/BioScientist/agent_system/engines/v1_executor_backup/__pycache__/env_desc.cpython-311.pyc differ diff --git a/BioScientist/agent_system/engines/v1_executor_backup/__pycache__/llm.cpython-311.pyc b/BioScientist/agent_system/engines/v1_executor_backup/__pycache__/llm.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..58964efa33b2d05698ac098f74f8c70b4556e98b Binary files /dev/null and b/BioScientist/agent_system/engines/v1_executor_backup/__pycache__/llm.cpython-311.pyc differ diff --git a/BioScientist/agent_system/engines/v1_executor_backup/__pycache__/utils.cpython-311.pyc b/BioScientist/agent_system/engines/v1_executor_backup/__pycache__/utils.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a439a364d45b22346a56767130ba148571af626e Binary files /dev/null and b/BioScientist/agent_system/engines/v1_executor_backup/__pycache__/utils.cpython-311.pyc differ diff --git a/BioScientist/agent_system/engines/v1_executor_backup/__pycache__/version.cpython-310.pyc b/BioScientist/agent_system/engines/v1_executor_backup/__pycache__/version.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bef7a6d6d0226d72f175ba202d96427157237c11 Binary files /dev/null and b/BioScientist/agent_system/engines/v1_executor_backup/__pycache__/version.cpython-310.pyc differ diff --git a/BioScientist/agent_system/engines/v1_executor_backup/__pycache__/version.cpython-311.pyc b/BioScientist/agent_system/engines/v1_executor_backup/__pycache__/version.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..af1e5d5252aeaa510b2181f1d578100075eaa266 Binary files /dev/null and b/BioScientist/agent_system/engines/v1_executor_backup/__pycache__/version.cpython-311.pyc differ diff --git a/BioScientist/agent_system/engines/v1_executor_backup/__pycache__/version.cpython-313.pyc b/BioScientist/agent_system/engines/v1_executor_backup/__pycache__/version.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..26ae0394aa01331593c0ec3cd3b5c74abad1d5f7 Binary files /dev/null and b/BioScientist/agent_system/engines/v1_executor_backup/__pycache__/version.cpython-313.pyc differ diff --git a/BioScientist/agent_system/engines/v1_executor_backup/biorxiv_scripts/extract_biorxiv_tasks.py b/BioScientist/agent_system/engines/v1_executor_backup/biorxiv_scripts/extract_biorxiv_tasks.py new file mode 100644 index 0000000000000000000000000000000000000000..961c32a4034065184a312eee4b28ef148b66d897 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/biorxiv_scripts/extract_biorxiv_tasks.py @@ -0,0 +1,404 @@ +#!/usr/bin/env python3 +"""Script to extract common tasks, databases, and software from bioRxiv papers +using the PaperTaskExtractor and existing metadata CSV. +""" + +import argparse +import io +import json +import os +import random +import sys +import time +from typing import Any + +import pandas as pd +import PyPDF2 +import requests +from tqdm import tqdm + +# Add the parent directory to the path so we can import the bioagentos package +sys.path.append("../../") +from biomni.agent.env_collection import PaperTaskExtractor + + +def parse_arguments(): + """Parse command line arguments.""" + parser = argparse.ArgumentParser(description="Extract tasks from bioRxiv papers in a specific subject area.") + parser.add_argument( + "--subject", + type=str, + required=True, + help='Subject area to search for papers (e.g., "neuroscience", "bioinformatics")', + ) + parser.add_argument( + "--limit", + type=int, + default=10, + help="Maximum number of papers to process (default: 10)", + ) + parser.add_argument( + "--metadata-path", + type=str, + default="/dfs/user/kexinh/BioAgentOS/data/biorxiv_metadata.csv", + help="Path to bioRxiv metadata CSV file (default: data/biorxiv_metadata.csv)", + ) + parser.add_argument( + "--output-dir", + type=str, + default=None, + help="Directory to save results (default: ./biorxiv_results_{subject}_{limit})", + ) + parser.add_argument( + "--model", + type=str, + default="claude-3-haiku-20240307", + help="LLM model to use for extraction (default: claude-3-haiku-20240307)", + ) + parser.add_argument( + "--chunk-size", + type=int, + default=4000, + help="Chunk size for text processing (default: 4000)", + ) + parser.add_argument( + "--chunk-overlap", + type=int, + default=400, + help="Chunk overlap for text processing (default: 400)", + ) + parser.add_argument( + "--max-paper-length", + type=int, + default=200000, + help="Maximum paper length in characters (default: 200000)", + ) + parser.add_argument("--save-pdfs", action="store_true", help="Save downloaded PDFs (default: False)") + parser.add_argument( + "--random-sample", + action="store_true", + help="Randomly sample papers instead of taking the first N (default: False)", + ) + return parser.parse_args() + + +def load_papers_from_csv(metadata_path: str, subject: str, limit: int, random_sample: bool) -> pd.DataFrame: + """Load papers from bioRxiv metadata CSV file. + + Args: + metadata_path: Path to the metadata CSV file + subject: Subject area to filter by + limit: Maximum number of papers to return + random_sample: Whether to randomly sample papers + + Returns: + DataFrame of filtered papers + + """ + try: + # Load the metadata CSV + df_biorxiv = pd.read_csv(metadata_path) + + # Filter published papers in the specified subject + if subject.lower() == "all": + filtered_df = df_biorxiv[df_biorxiv.published != "NA"] + else: + filtered_df = df_biorxiv[ + (df_biorxiv.published != "NA") & (df_biorxiv.category.str.lower() == subject.lower()) + ] + + # Sample papers + if len(filtered_df) > limit: + filtered_df = filtered_df.sample(limit, random_state=42) if random_sample else filtered_df.head(limit) + + print(f"Loaded {len(filtered_df)} papers in subject: {subject}") + return filtered_df + + except Exception as e: + print(f"Error loading papers from CSV: {e}") + return pd.DataFrame() + + +def download_pdf(paper_doi: str, save_path: str | None = None) -> str | None: + """Download PDF for a given paper DOI. + + Args: + paper_doi: DOI of the paper + save_path: Path to save the PDF (if None, won't save to disk) + + Returns: + PDF text content or None if download failed + + """ + # Construct PDF URL from DOI + pdf_url = f"https://www.biorxiv.org/content/{paper_doi}v1.full.pdf" + + try: + # Add random delay to avoid rate limiting + time.sleep(random.uniform(1, 3)) + + response = requests.get(pdf_url, stream=True) + response.raise_for_status() + + # Save PDF if requested + if save_path: + os.makedirs(os.path.dirname(save_path), exist_ok=True) + with open(save_path, "wb") as f: + for chunk in response.iter_content(chunk_size=8192): + f.write(chunk) + + # Extract text from PDF + pdf_text = extract_text_from_pdf(io.BytesIO(response.content)) + return pdf_text + + except requests.exceptions.RequestException as e: + print(f"Error downloading PDF for {paper_doi}: {e}") + return None + + +def extract_text_from_pdf(pdf_file) -> str: + """Extract text content from a PDF file. + + Args: + pdf_file: File-like object containing PDF data + + Returns: + Extracted text content + + """ + try: + pdf_reader = PyPDF2.PdfReader(pdf_file) + text = "" + for page_num in range(len(pdf_reader.pages)): + page = pdf_reader.pages[page_num] + text += page.extract_text() + "\n\n" + return text + except Exception as e: + print(f"Error extracting text from PDF: {e}") + return "" + + +def truncate_text(text: str, max_length: int) -> str: + """Truncate text to a maximum length while preserving complete sentences. + + Args: + text: The text to truncate + max_length: Maximum length in characters + + Returns: + Truncated text + + """ + if len(text) <= max_length: + return text + + # Find the last sentence boundary before max_length + truncated = text[:max_length] + last_period = truncated.rfind(".") + last_question = truncated.rfind("?") + last_exclamation = truncated.rfind("!") + + # Find the last sentence boundary + last_boundary = max(last_period, last_question, last_exclamation) + + if last_boundary > 0: + return text[: last_boundary + 1] + else: + # If no sentence boundary found, just truncate at max_length + return truncated + + +def process_papers(papers_df: pd.DataFrame, args) -> list[dict[str, Any]]: + """Process papers using PaperTaskExtractor. + + Args: + papers_df: DataFrame of paper metadata + args: Command line arguments + + Returns: + List of papers with extracted tasks, databases, and software + + """ + # Initialize the task extractor + extractor = PaperTaskExtractor(llm=args.model, chunk_size=args.chunk_size, chunk_overlap=args.chunk_overlap) + + results = [] + + for _, paper in tqdm(papers_df.iterrows(), total=len(papers_df), desc="Processing papers"): + paper_doi = paper.get("doi") + if not paper_doi: + continue + + print(f"\nProcessing paper: {paper.get('title')} (DOI: {paper_doi})") + + # Create paths + pdf_path = None + if args.save_pdfs: + pdf_path = os.path.join(args.output_dir, "pdfs", f"{paper_doi.replace('/', '_')}.pdf") + + result_path = os.path.join(args.output_dir, "results", f"{paper_doi.replace('/', '_')}.json") + + # Skip if already processed + if os.path.exists(result_path): + print(f"Paper already processed, loading from {result_path}") + with open(result_path) as f: + paper_result = json.load(f) + results.append(paper_result) + continue + + # Download and process PDF + pdf_text = download_pdf(paper_doi, pdf_path) + if not pdf_text: + print(f"Failed to download or extract text from {paper_doi}") + continue + + # Truncate text if it exceeds max length + if len(pdf_text) > args.max_paper_length: + original_length = len(pdf_text) + pdf_text = truncate_text(pdf_text, args.max_paper_length) + print(f"Truncated paper from {original_length} to {len(pdf_text)} characters") + + # Extract tasks, databases, and software + try: + _, extraction_results = extractor.go(pdf_text) + + # Add paper metadata to results + paper_result = { + "metadata": { + "doi": paper.get("doi"), + "title": paper.get("title"), + "authors": paper.get("authors", ""), + "abstract": paper.get("abstract", ""), + "date": paper.get("date", ""), + "category": paper.get("category", ""), + "text_length": len(pdf_text), + }, + "extraction": extraction_results, + } + + # Save results + os.makedirs(os.path.dirname(result_path), exist_ok=True) + with open(result_path, "w") as f: + json.dump(paper_result, f, indent=2) + + results.append(paper_result) + + except Exception as e: + print(f"Error processing paper {paper_doi}: {e}") + + return results + + +def generate_summary(results: list[dict[str, Any]], output_dir: str): + """Generate summary of extracted tasks, databases, and software. + + Args: + results: List of papers with extraction results + output_dir: Directory to save summary + + """ + # Collect all tasks, databases, and software + all_tasks = [] + all_databases = [] + all_software = [] + + for paper in results: + extraction = paper.get("extraction", {}) + + # Add paper metadata to each item + paper_meta = paper.get("metadata", {}) + paper_id = f"{paper_meta.get('title')} ({paper_meta.get('doi')})" + + # Process tasks + for task in extraction.get("tasks", []): + task["paper"] = paper_id + all_tasks.append(task) + + # Process databases + for db in extraction.get("databases", []): + db["paper"] = paper_id + all_databases.append(db) + + # Process software + for sw in extraction.get("software", []): + sw["paper"] = paper_id + all_software.append(sw) + + # Create summary dataframes + if all_tasks: + tasks_df = pd.DataFrame(all_tasks) + tasks_df.to_csv(os.path.join(output_dir, "tasks_summary.csv"), index=False) + + if all_databases: + db_df = pd.DataFrame(all_databases) + db_df.to_csv(os.path.join(output_dir, "databases_summary.csv"), index=False) + + if all_software: + sw_df = pd.DataFrame(all_software) + sw_df.to_csv(os.path.join(output_dir, "software_summary.csv"), index=False) + + # Generate frequency counts + task_counts = {} + for task in all_tasks: + task_name = task.get("task_name") + if task_name: + task_counts[task_name] = task_counts.get(task_name, 0) + 1 + + db_counts = {} + for db in all_databases: + db_name = db.get("name") + if db_name: + db_counts[db_name] = db_counts.get(db_name, 0) + 1 + + sw_counts = {} + for sw in all_software: + sw_name = sw.get("name") + if sw_name: + sw_counts[sw_name] = sw_counts.get(sw_name, 0) + 1 + + # Save frequency counts + with open(os.path.join(output_dir, "frequency_summary.json"), "w") as f: + json.dump( + {"tasks": task_counts, "databases": db_counts, "software": sw_counts}, + f, + indent=2, + ) + + print(f"Summary files saved to {output_dir}") + + +def main(): + """Main function to run the script.""" + args = parse_arguments() + + # Set default output directory if not specified + if args.output_dir is None: + # Clean subject name for directory name (replace spaces with underscores, lowercase) + clean_subject = args.subject.lower().replace(" ", "_").replace("/", "_") + args.output_dir = f"./biorxiv_results_{clean_subject}_{args.limit}" + + # Create output directories + os.makedirs(args.output_dir, exist_ok=True) + os.makedirs(os.path.join(args.output_dir, "results"), exist_ok=True) + if args.save_pdfs: + os.makedirs(os.path.join(args.output_dir, "pdfs"), exist_ok=True) + + # Load papers from CSV + print(f"Loading papers from {args.metadata_path} in subject area: {args.subject}") + papers_df = load_papers_from_csv(args.metadata_path, args.subject, args.limit, args.random_sample) + + if len(papers_df) == 0: + print(f"No papers found for subject: {args.subject}") + return + + # Process papers + results = process_papers(papers_df, args) + + # Generate summary + generate_summary(results, args.output_dir) + + print("Done!") + + +if __name__ == "__main__": + main() diff --git a/BioScientist/agent_system/engines/v1_executor_backup/biorxiv_scripts/generate_function.py b/BioScientist/agent_system/engines/v1_executor_backup/biorxiv_scripts/generate_function.py new file mode 100644 index 0000000000000000000000000000000000000000..6d4f359ee1802bdcf0c7507206800031363aa5ec --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/biorxiv_scripts/generate_function.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python3 +"""Command-line tool to generate Python functions from task descriptions using the function_generator agent.""" + +import argparse +import json +import os + +from biomni.agent.function_generator import FunctionGenerator +from tqdm import tqdm + + +def main(): + """Main function for the command-line tool.""" + parser = argparse.ArgumentParser(description="Generate Python functions given task descriptions") + parser.add_argument( + "--task", + "-t", + type=str, + help="JSON file containing a list of task descriptions", + ) + parser.add_argument( + "--output-dir", + "-o", + type=str, + default="generated_functions", + help="Directory to save the generated functions (default: generated_functions)", + ) + parser.add_argument( + "--model", + "-m", + type=str, + default="claude-3-7-sonnet-latest", + help="LLM model to use (default: claude-3-7-sonnet-latest)", + ) + parser.add_argument( + "--temperature", + type=float, + default=0.7, + help="Temperature setting for the LLM (default: 0.7)", + ) + + args = parser.parse_args() + + with open(args.task) as f_tasks: + task_list = json.load(f_tasks) + task_descriptions = list(task_list["tasks"]) + + # Create the output directory if it doesn't exist + os.makedirs(args.output_dir, exist_ok=True) + + # Initialize the function generator agent + function_generator = FunctionGenerator(llm=args.model, temperature=args.temperature) + + if not task_list: + print("No tasks found.") + else: + # tqdm shows a progress bar, file names as description + for _i, desc in enumerate(tqdm(task_descriptions, desc="Generating Python scripts given task descriptions"), 1): + generated_script_name, generated_codes = function_generator.go(desc) + + # Save results + result_path = os.path.join(args.output_dir, generated_script_name) + + os.makedirs(os.path.dirname(result_path), exist_ok=True) + with open(result_path, "w") as f: + f.write(generated_codes) + + print("DONE") + + +if __name__ == "__main__": + main() diff --git a/BioScientist/agent_system/engines/v1_executor_backup/biorxiv_scripts/process_all_subjects.py b/BioScientist/agent_system/engines/v1_executor_backup/biorxiv_scripts/process_all_subjects.py new file mode 100644 index 0000000000000000000000000000000000000000..97c7dd90a012ab47bab6c5ff0c85bc39fd0d3890 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/biorxiv_scripts/process_all_subjects.py @@ -0,0 +1,315 @@ +#!/usr/bin/env python3 +"""Script to process all bioRxiv subjects and extract computational tasks from the top 100 papers in each.""" + +import argparse +import os +import subprocess +import sys +import time + +import pandas as pd +from tqdm import tqdm + +# Add the parent directory to the path so we can import the bioagentos package +sys.path.append("/dfs/user/kexinh/BioAgentOS/") + +# List of all bioRxiv subjects +BIORXIV_SUBJECTS = [ + "evolutionary biology", + "ecology", + "neuroscience", + "developmental biology", + "plant biology", + "microbiology", + "cancer biology", + "immunology", + "cell biology", + "biochemistry", + "genetics", + "bioinformatics", + "animal behavior and cognition", + "biophysics", + "genomics", + "systems biology", + "bioengineering", + "molecular biology", + "physiology", + "zoology", + "scientific communication and education", + "pathology", + "synthetic biology", + "paleontology", + "pharmacology and toxicology", +] + + +def parse_arguments(): + """Parse command line arguments.""" + parser = argparse.ArgumentParser(description="Process all bioRxiv subjects and extract tasks from papers.") + parser.add_argument( + "--papers-per-subject", + type=int, + default=100, + help="Number of papers to process per subject (default: 100)", + ) + parser.add_argument( + "--metadata-path", + type=str, + default="/dfs/user/kexinh/BioAgentOS/data/biorxiv_metadata.csv", + help="Path to bioRxiv metadata CSV file (default: data/biorxiv_metadata.csv)", + ) + parser.add_argument( + "--output-dir", + type=str, + default="./biorxiv_all_subjects", + help="Base directory to save results (default: ./biorxiv_all_subjects)", + ) + parser.add_argument( + "--model", + type=str, + default="claude-3-haiku-20240307", + help="LLM model to use for extraction (default: claude-3-haiku-20240307)", + ) + parser.add_argument( + "--max-paper-length", + type=int, + default=200000, + help="Maximum paper length in characters (default: 200000)", + ) + parser.add_argument( + "--chunk-size", + type=int, + default=10000, + help="Chunk size for text processing (default: 10000)", + ) + parser.add_argument( + "--chunk-overlap", + type=int, + default=400, + help="Chunk overlap for text processing (default: 400)", + ) + parser.add_argument("--save-pdfs", action="store_true", help="Save downloaded PDFs (default: False)") + parser.add_argument( + "--random-sample", + action="store_true", + help="Randomly sample papers instead of taking the first N (default: False)", + ) + parser.add_argument( + "--subjects", + type=str, + nargs="+", + help="Specific subjects to process (default: all subjects)", + ) + parser.add_argument( + "--delay", + type=int, + default=60, + help="Delay in seconds between processing subjects (default: 60)", + ) + parser.add_argument( + "--summary-only", + action="store_true", + help="Only generate the combined summary (default: False)", + ) + return parser.parse_args() + + +def check_subject_availability(metadata_path, subjects): + """Check which subjects have papers available in the metadata. + + Args: + metadata_path: Path to the metadata CSV file + subjects: List of subjects to check + + Returns: + List of subjects with available papers + + """ + try: + df_biorxiv = pd.read_csv(metadata_path) + available_subjects = [] + + for subject in subjects: + count = len( + df_biorxiv[(df_biorxiv.published != "NA") & (df_biorxiv.category.str.lower() == subject.lower())] + ) + if count > 0: + available_subjects.append((subject, count)) + print(f"Subject '{subject}' has {count} papers available") + else: + print(f"Subject '{subject}' has no papers available") + + return available_subjects + except Exception as e: + print(f"Error checking subject availability: {e}") + return [] + + +def process_subject(subject, args): + """Process a single subject by calling the extract_biorxiv_tasks.py script. + + Args: + subject: Subject to process + args: Command line arguments + + """ + # Clean subject name for command line + subject.replace(" ", "\\ ") + + # Build command + cmd = [ + "python", + "BioAgentOS/bioagentos/scripts/extract_biorxiv_tasks.py", + "--subject", + f'"{subject}"', + "--limit", + str(args.papers_per_subject), + "--metadata-path", + args.metadata_path, + "--model", + args.model, + "--max-paper-length", + str(args.max_paper_length), + "--chunk-size", + str(args.chunk_size), + "--chunk-overlap", + str(args.chunk_overlap), + ] + + # Add optional arguments + if args.save_pdfs: + cmd.append("--save-pdfs") + if args.random_sample: + cmd.append("--random-sample") + + # Convert command list to string + cmd_str = " ".join(cmd) + + print(f"\n{'=' * 80}\nProcessing subject: {subject}\n{'=' * 80}") + print(f"Running command: {cmd_str}") + + # Execute command + try: + subprocess.run(cmd_str, shell=True, check=True) + print(f"Successfully processed subject: {subject}") + except subprocess.CalledProcessError as e: + print(f"Error processing subject '{subject}': {e}") + + +def combine_summaries(base_dir, subjects, papers_per_subject): + """Combine frequency summaries from all subjects into a single summary. + + Args: + base_dir: Base directory containing subject results + subjects: List of subjects that were processed + papers_per_subject: Number of papers processed per subject + + """ + all_tasks = {} + all_databases = {} + all_software = {} + + for subject, _ in subjects: + # Clean subject name for directory name + clean_subject = subject.lower().replace(" ", "_").replace("/", "_") + subject_dir = f"biorxiv_results_{clean_subject}_{papers_per_subject}" + summary_path = os.path.join(subject_dir, "frequency_summary.json") + + try: + if os.path.exists(summary_path): + with open(summary_path) as f: + summary = json.load(f) + + # Merge tasks + for task, count in summary.get("tasks", {}).items(): + if task in all_tasks: + all_tasks[task] += count + else: + all_tasks[task] = count + + # Merge databases + for db, count in summary.get("databases", {}).items(): + if db in all_databases: + all_databases[db] += count + else: + all_databases[db] = count + + # Merge software + for sw, count in summary.get("software", {}).items(): + if sw in all_software: + all_software[sw] += count + else: + all_software[sw] = count + else: + print(f"Warning: Summary file not found for subject '{subject}'") + except Exception as e: + print(f"Error processing summary for subject '{subject}': {e}") + + # Sort by frequency (descending) + all_tasks = dict(sorted(all_tasks.items(), key=lambda item: item[1], reverse=True)) + all_databases = dict(sorted(all_databases.items(), key=lambda item: item[1], reverse=True)) + all_software = dict(sorted(all_software.items(), key=lambda item: item[1], reverse=True)) + + # Create combined summary + combined_summary = { + "tasks": all_tasks, + "databases": all_databases, + "software": all_software, + } + + # Save combined summary + combined_path = os.path.join(base_dir, "combined_summary.json") + os.makedirs(base_dir, exist_ok=True) + + with open(combined_path, "w") as f: + json.dump(combined_summary, f, indent=2) + + print(f"Combined summary saved to {combined_path}") + + # Create CSV files for each category + tasks_df = pd.DataFrame(list(all_tasks.items()), columns=["Task", "Frequency"]) + tasks_df.to_csv(os.path.join(base_dir, "tasks_frequency.csv"), index=False) + + db_df = pd.DataFrame(list(all_databases.items()), columns=["Database", "Frequency"]) + db_df.to_csv(os.path.join(base_dir, "databases_frequency.csv"), index=False) + + sw_df = pd.DataFrame(list(all_software.items()), columns=["Software", "Frequency"]) + sw_df.to_csv(os.path.join(base_dir, "software_frequency.csv"), index=False) + + print(f"CSV summaries saved to {base_dir}") + + +def main(): + """Main function to run the script.""" + args = parse_arguments() + + # Determine which subjects to process + subjects_to_process = args.subjects if args.subjects else BIORXIV_SUBJECTS + + # Check which subjects have papers available + available_subjects = check_subject_availability(args.metadata_path, subjects_to_process) + + if not available_subjects: + print("No subjects with available papers found. Exiting.") + return + + if not args.summary_only: + # Process each subject + for subject, _count in tqdm(available_subjects, desc="Processing subjects"): + process_subject(subject, args) + + # Add delay between subjects to avoid rate limiting + if args.delay > 0: + print(f"Waiting {args.delay} seconds before processing the next subject...") + time.sleep(args.delay) + + # Combine summaries from all subjects + combine_summaries(args.output_dir, available_subjects, args.papers_per_subject) + + print("All subjects processed successfully!") + + +if __name__ == "__main__": + import json # Import here to avoid circular import with the main script + + main() diff --git a/BioScientist/agent_system/engines/v1_executor_backup/know_how/__init__.py b/BioScientist/agent_system/engines/v1_executor_backup/know_how/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..8da6d01cfe04542de6325bb60f414a57fc8f39d5 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/know_how/__init__.py @@ -0,0 +1,9 @@ +"""Know-How library for Biomni agent. + +This module provides functionality to load and manage know-how documents +that contain best practices, protocols, and troubleshooting guides. +""" + +from .loader import KnowHowLoader + +__all__ = ["KnowHowLoader"] diff --git a/BioScientist/agent_system/engines/v1_executor_backup/know_how/__pycache__/__init__.cpython-311.pyc b/BioScientist/agent_system/engines/v1_executor_backup/know_how/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5680a460056b0cbb74b813312cb1f608b370f587 Binary files /dev/null and b/BioScientist/agent_system/engines/v1_executor_backup/know_how/__pycache__/__init__.cpython-311.pyc differ diff --git a/BioScientist/agent_system/engines/v1_executor_backup/know_how/__pycache__/loader.cpython-311.pyc b/BioScientist/agent_system/engines/v1_executor_backup/know_how/__pycache__/loader.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3f076b741f103115ea19e96ecab80e7f1e4e95a1 Binary files /dev/null and b/BioScientist/agent_system/engines/v1_executor_backup/know_how/__pycache__/loader.cpython-311.pyc differ diff --git a/BioScientist/agent_system/engines/v1_executor_backup/know_how/loader.py b/BioScientist/agent_system/engines/v1_executor_backup/know_how/loader.py new file mode 100644 index 0000000000000000000000000000000000000000..b4906d28f915dd729f3821a6a7ed221184ff86c3 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/know_how/loader.py @@ -0,0 +1,348 @@ +"""Loader for know-how documents.""" + +import glob +import os +from pathlib import Path + + +class KnowHowLoader: + """Load and manage know-how documents for the agent.""" + + def __init__(self, know_how_dir: str | None = None): + """Initialize the know-how loader. + + Args: + know_how_dir: Directory containing know-how documents. + If None, uses the default know_how directory. + + """ + if know_how_dir is None: + # Default to the know_how directory in the package + current_dir = Path(__file__).parent + know_how_dir = str(current_dir) + + self.know_how_dir = know_how_dir + self.documents = {} + self._load_documents() + + def _load_documents(self): + """Load all markdown documents from the know-how directory.""" + pattern = os.path.join(self.know_how_dir, "*.md") + md_files = glob.glob(pattern) + + for filepath in md_files: + filename = os.path.basename(filepath) + filename_without_ext = os.path.splitext(filename)[0] + + # Skip README, QUICK_START, and other meta documentation (all caps filenames) + if filename.upper() in ["README.MD", "QUICK_START.MD"] or filename_without_ext.isupper(): + continue + + # Read the document + with open(filepath) as f: + content = f.read() + + # Extract title, description, and metadata from the document + title, description, metadata = self._extract_metadata(content, filename) + + # Use short_description from metadata if available, otherwise fall back to extracted description + if "short_description" in metadata and metadata["short_description"]: + description = metadata["short_description"] + + # Store document info + doc_id = os.path.splitext(filename)[0] + self.documents[doc_id] = { + "id": doc_id, + "name": title, + "description": description, + "content": content, + "content_without_metadata": self._strip_metadata(content), + "filepath": filepath, + "metadata": metadata, + } + + def _extract_metadata(self, content: str, filename: str) -> tuple[str, str, dict]: + """Extract title, description, and metadata from markdown content. + + Args: + content: Markdown content + filename: Filename (used as fallback for title) + + Returns: + Tuple of (title, description, metadata_dict) + + """ + lines = content.split("\n") + + # Extract title (first h1) + title = None + for line in lines: + if line.startswith("# "): + title = line[2:].strip() + break + + if title is None: + # Fallback to filename + title = filename.replace("_", " ").replace(".md", "").title() + + # Extract metadata section + metadata = {} + in_metadata = False + current_field = None + + for _i, line in enumerate(lines): + if line.startswith("## Metadata"): + in_metadata = True + continue + elif in_metadata: + if line.startswith("##") and "Metadata" not in line: + # End of metadata section + break + elif line.startswith("**") and "**:" in line: + # New metadata field (e.g., **Authors**:) + field_match = line.split("**")[1] + current_field = field_match.lower().replace(" ", "_") + # Get the value after the colon if it exists on the same line + colon_idx = line.find("**:") + if colon_idx != -1: + value_part = line[colon_idx + 3 :].strip() + if value_part: + metadata[current_field] = value_part + else: + metadata[current_field] = "" + elif current_field and line.strip() and not line.startswith("---"): + # Continuation of current field + if current_field not in metadata: + metadata[current_field] = "" + if line.startswith("- "): + # List item + if metadata[current_field]: + metadata[current_field] += ", " + line[2:].strip() + else: + metadata[current_field] = line[2:].strip() + elif not line.startswith("```"): + # Regular text + if metadata[current_field]: + metadata[current_field] += " " + line.strip() + else: + metadata[current_field] = line.strip() + + # Extract description (content under ## Overview or first paragraph) + description = "" + in_overview = False + overview_lines = [] + + for _i, line in enumerate(lines): + if line.startswith("## Overview"): + in_overview = True + continue + elif in_overview: + if line.startswith("##"): + # End of overview section + break + elif line.strip(): + overview_lines.append(line.strip()) + + if overview_lines: + description = " ".join(overview_lines) + else: + # Fallback: get first non-empty paragraph after title + found_title = False + for line in lines: + if line.startswith("# "): + found_title = True + continue + if found_title and line.strip() and not line.startswith("#"): + description = line.strip() + break + + # Limit description length + if len(description) > 200: + description = description[:197] + "..." + + return title, description, metadata + + def _strip_metadata(self, content: str) -> str: + """Strip the metadata section from document content. + + Args: + content: Full document content with metadata + + Returns: + Content without metadata section + + """ + lines = content.split("\n") + result_lines = [] + in_metadata = False + skip_until_separator = False + found_first_h1 = False + + for line in lines: + # Track first H1 (title) + if line.startswith("# ") and not found_first_h1: + result_lines.append(line) + found_first_h1 = True + continue + + # Detect metadata section start + if line.startswith("## Metadata"): + in_metadata = True + continue + + # Skip separator lines before and after metadata + if line.strip() == "---": + if not in_metadata: + # This might be the separator before metadata + skip_until_separator = True + continue + else: + # This is the separator after metadata + in_metadata = False + skip_until_separator = False + continue + + # Skip lines in metadata section + if in_metadata or skip_until_separator: + # Check if we hit another H2 (end of metadata) + if line.startswith("##") and "Metadata" not in line: + in_metadata = False + skip_until_separator = False + result_lines.append(line) + continue + + # Keep all other lines + result_lines.append(line) + + # Join and clean up extra blank lines + result = "\n".join(result_lines) + + # Remove excessive blank lines (more than 2 consecutive) + while "\n\n\n\n" in result: + result = result.replace("\n\n\n\n", "\n\n\n") + + return result.strip() + + def get_all_documents(self) -> list[dict]: + """Get all know-how documents as a list. + + Returns: + List of document dictionaries with keys: id, name, description, content + + """ + return list(self.documents.values()) + + def get_document_by_id(self, doc_id: str) -> dict | None: + """Get a specific know-how document by ID. + + Args: + doc_id: Document identifier + + Returns: + Document dictionary or None if not found + + """ + return self.documents.get(doc_id) + + def get_document_summaries(self) -> list[dict]: + """Get summaries of all documents (without full content). + + Returns: + List of document summaries with keys: id, name, description + + """ + return [ + {"id": doc["id"], "name": doc["name"], "description": doc["description"]} for doc in self.documents.values() + ] + + def add_custom_document(self, doc_id: str, name: str, description: str, content: str, metadata: dict | None = None): + """Add a custom know-how document programmatically. + + Args: + doc_id: Unique identifier for the document + name: Document title + description: Brief description + content: Full document content + metadata: Optional metadata dictionary (authors, license, etc.) + + """ + if metadata is None: + metadata = {} + + self.documents[doc_id] = { + "id": doc_id, + "name": name, + "description": description, + "content": content, + "filepath": None, + "metadata": metadata, + } + + def get_document_metadata(self, doc_id: str) -> dict | None: + """Get metadata for a specific document. + + Args: + doc_id: Document identifier + + Returns: + Metadata dictionary or None if not found + + """ + doc = self.documents.get(doc_id) + return doc.get("metadata", {}) if doc else None + + def print_document_info(self, doc_id: str): + """Print formatted information about a document including metadata. + + Args: + doc_id: Document identifier + + """ + doc = self.documents.get(doc_id) + if not doc: + print(f"Document '{doc_id}' not found") + return + + print("=" * 70) + print(f"📚 {doc['name']}") + print("=" * 70) + print(f"\nDescription: {doc['description']}") + + metadata = doc.get("metadata", {}) + if metadata: + print("\n" + "-" * 70) + print("METADATA") + print("-" * 70) + + # Display key metadata fields + if "authors" in metadata: + print(f"Authors: {metadata['authors']}") + if "affiliations" in metadata: + print(f"Affiliations: {metadata['affiliations']}") + if "version" in metadata: + print(f"Version: {metadata['version']}") + if "last_updated" in metadata: + print(f"Last Updated: {metadata['last_updated']}") + if "license" in metadata: + print(f"License: {metadata['license']}") + if "commercial_use" in metadata: + print(f"Commercial Use: {metadata['commercial_use']}") + if "status" in metadata: + print(f"Status: {metadata['status']}") + + print("=" * 70) + + def remove_document(self, doc_id: str): + """Remove a know-how document. + + Args: + doc_id: Document identifier + + """ + if doc_id in self.documents: + del self.documents[doc_id] + + def reload(self): + """Reload all documents from disk.""" + self.documents = {} + self._load_documents() diff --git a/BioScientist/agent_system/engines/v1_executor_backup/know_how/resource/CRISPick_download_links.txt b/BioScientist/agent_system/engines/v1_executor_backup/know_how/resource/CRISPick_download_links.txt new file mode 100644 index 0000000000000000000000000000000000000000..3f7e86d4b202458215ef658bc91f4d0e78fcf6c6 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/know_how/resource/CRISPick_download_links.txt @@ -0,0 +1,238 @@ +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_8030_ICSASG_v2_SpyoCas9_CRISPRa_RS3seq-Chen2013_NCBI_20230421.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_8030_ICSASG_v2_SpyoCas9_CRISPRa_RS3seq-Chen2013_NCBI_20230421.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_8030_ICSASG_v2_SpyoCas9_CRISPRko_RS3seq-Chen2013+RS3target_NCBI_20230421.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_8030_ICSASG_v2_SpyoCas9_CRISPRko_RS3seq-Chen2013+RS3target_NCBI_20230421.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10029_CHOK1GS_HDv1_SaurCas9_CRISPRa_Azimuth_2.0_Ensembl_20241114.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10029_CHOK1GS_HDv1_SaurCas9_CRISPRa_Azimuth_2.0_Ensembl_20241114.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10029_CHOK1GS_HDv1_SaurCas9_CRISPRi_Azimuth_2.0_Ensembl_20241114.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10029_CHOK1GS_HDv1_SaurCas9_CRISPRi_Azimuth_2.0_Ensembl_20241114.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10029_CHOK1GS_HDv1_SaurCas9_CRISPRko_Azimuth_2.0_Ensembl_20241114.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10029_CHOK1GS_HDv1_SaurCas9_CRISPRko_Azimuth_2.0_Ensembl_20241114.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10029_CHOK1GS_HDv1_SpyoCas9_CRISPRa_RS3seq-Chen2013_Ensembl_20241114.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10029_CHOK1GS_HDv1_SpyoCas9_CRISPRa_RS3seq-Chen2013_Ensembl_20241114.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10029_CHOK1GS_HDv1_SpyoCas9_CRISPRko_RS3seq-Chen2013+RS3target_Ensembl_20241114.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10029_CHOK1GS_HDv1_SpyoCas9_CRISPRko_RS3seq-Chen2013+RS3target_Ensembl_20241114.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_74940_Otsh_v1.0_SpyoCas9_CRISPRa_RS3seq-Chen2013_NCBI_20230424.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_74940_Otsh_v1.0_SpyoCas9_CRISPRa_RS3seq-Chen2013_NCBI_20230424.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_74940_Otsh_v1.0_SpyoCas9_CRISPRko_RS3seq-Chen2013+RS3target_NCBI_20230424.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_74940_Otsh_v1.0_SpyoCas9_CRISPRko_RS3seq-Chen2013+RS3target_NCBI_20230424.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9913_ARS-UCD1.2_SpyoCas9_CRISPRa_RS3seq-Chen2013_NCBI_20230418.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9913_ARS-UCD1.2_SpyoCas9_CRISPRa_RS3seq-Chen2013_NCBI_20230418.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9913_ARS-UCD1.2_SpyoCas9_CRISPRko_RS3seq-Chen2013+RS3target_NCBI_20230418.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9913_ARS-UCD1.2_SpyoCas9_CRISPRko_RS3seq-Chen2013+RS3target_NCBI_20230418.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9615_CanFam3.1_SpyoCas9_CRISPRa_RS3seq-Chen2013_NCBI_20220923.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9615_CanFam3.1_SpyoCas9_CRISPRa_RS3seq-Chen2013_NCBI_20220923.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9615_CanFam3.1_SpyoCas9_CRISPRko_RS3seq-Chen2013+RS3target_NCBI_20220923.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9615_CanFam3.1_SpyoCas9_CRISPRko_RS3seq-Chen2013+RS3target_NCBI_20220923.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9615_ROS_Cfam_1.0_AsCas12a_CRISPRa_Seq-DeepCpf1_Ensembl_20251031.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9615_ROS_Cfam_1.0_AsCas12a_CRISPRa_Seq-DeepCpf1_Ensembl_20251031.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9615_ROS_Cfam_1.0_AsCas12a_CRISPRa_Seq-DeepCpf1_NCBI_20240611.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9615_ROS_Cfam_1.0_AsCas12a_CRISPRa_Seq-DeepCpf1_NCBI_20240611.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9615_ROS_Cfam_1.0_AsCas12a_CRISPRi_Seq-DeepCpf1_Ensembl_20251031.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9615_ROS_Cfam_1.0_AsCas12a_CRISPRi_Seq-DeepCpf1_Ensembl_20251031.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9615_ROS_Cfam_1.0_AsCas12a_CRISPRi_Seq-DeepCpf1_NCBI_20240611.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9615_ROS_Cfam_1.0_AsCas12a_CRISPRi_Seq-DeepCpf1_NCBI_20240611.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9615_ROS_Cfam_1.0_AsCas12a_CRISPRko_Seq-DeepCpf1_Ensembl_20251031.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9615_ROS_Cfam_1.0_AsCas12a_CRISPRko_Seq-DeepCpf1_Ensembl_20251031.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9615_ROS_Cfam_1.0_AsCas12a_CRISPRko_Seq-DeepCpf1_NCBI_20240611.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9615_ROS_Cfam_1.0_AsCas12a_CRISPRko_Seq-DeepCpf1_NCBI_20240611.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9615_ROS_Cfam_1.0_enAsCas12a_CRISPRa_enPAM+GB_Ensembl_20241031.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9615_ROS_Cfam_1.0_enAsCas12a_CRISPRa_enPAM+GB_Ensembl_20241031.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9615_ROS_Cfam_1.0_enAsCas12a_CRISPRa_enPAM+GB_NCBI_20240611.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9615_ROS_Cfam_1.0_enAsCas12a_CRISPRa_enPAM+GB_NCBI_20240611.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9615_ROS_Cfam_1.0_enAsCas12a_CRISPRi_enPAM+GB_Ensembl_20241031.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9615_ROS_Cfam_1.0_enAsCas12a_CRISPRi_enPAM+GB_Ensembl_20241031.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9615_ROS_Cfam_1.0_enAsCas12a_CRISPRi_enPAM+GB_NCBI_20240611.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9615_ROS_Cfam_1.0_enAsCas12a_CRISPRi_enPAM+GB_NCBI_20240611.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9615_ROS_Cfam_1.0_enAsCas12a_CRISPRko_enPAM+GB_Ensembl_20251031.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9615_ROS_Cfam_1.0_enAsCas12a_CRISPRko_enPAM+GB_Ensembl_20251031.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9615_ROS_Cfam_1.0_enAsCas12a_CRISPRko_enPAM+GB_NCBI_20240611.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9615_ROS_Cfam_1.0_enAsCas12a_CRISPRko_enPAM+GB_NCBI_20240611.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9615_ROS_Cfam_1.0_SpyoCas9_CRISPRa_RS3seq-Chen2013_Ensembl_20251031.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9615_ROS_Cfam_1.0_SpyoCas9_CRISPRa_RS3seq-Chen2013_Ensembl_20251031.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9615_ROS_Cfam_1.0_SpyoCas9_CRISPRa_RS3seq-Chen2013_NCBI_20240611.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9615_ROS_Cfam_1.0_SpyoCas9_CRISPRa_RS3seq-Chen2013_NCBI_20240611.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9615_ROS_Cfam_1.0_SpyoCas9_CRISPRi_RS3i-Chen2013_Ensembl_20251031.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9615_ROS_Cfam_1.0_SpyoCas9_CRISPRi_RS3i-Chen2013_Ensembl_20251031.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9615_ROS_Cfam_1.0_SpyoCas9_CRISPRko_RS3seq-Chen2013+RS3target_Ensembl_20241031.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9615_ROS_Cfam_1.0_SpyoCas9_CRISPRko_RS3seq-Chen2013+RS3target_Ensembl_20241031.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9615_ROS_Cfam_1.0_SpyoCas9_CRISPRko_RS3seq-Chen2013+RS3target_NCBI_20240611.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9615_ROS_Cfam_1.0_SpyoCas9_CRISPRko_RS3seq-Chen2013+RS3target_NCBI_20240611.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_7227_BDGP6.32_SpyoCas9_CRISPRa_RS3seq-Chen2013_Ensembl_20230407.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_7227_BDGP6.32_SpyoCas9_CRISPRa_RS3seq-Chen2013_Ensembl_20230407.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_7227_BDGP6.32_SpyoCas9_CRISPRko_RS3seq-Chen2013+RS3target_Ensembl_20230407.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_7227_BDGP6.32_SpyoCas9_CRISPRko_RS3seq-Chen2013+RS3target_Ensembl_20230407.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_59479_mRhiFer1_v1.p_SpyoCas9_CRISPRa_RS3seq-Chen2013_NCBI_20230427.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_59479_mRhiFer1_v1.p_SpyoCas9_CRISPRa_RS3seq-Chen2013_NCBI_20230427.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_59479_mRhiFer1_v1.p_SpyoCas9_CRISPRko_RS3seq-Chen2013+RS3target_NCBI_20230427.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_59479_mRhiFer1_v1.p_SpyoCas9_CRISPRko_RS3seq-Chen2013+RS3target_NCBI_20230427.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_60711_Chlorocebus_sabeus_1.1_AsCas12a_CRISPRa_Seq-DeepCpf1_NCBI_20220914.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_60711_Chlorocebus_sabeus_1.1_AsCas12a_CRISPRa_Seq-DeepCpf1_NCBI_20220914.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_60711_Chlorocebus_sabeus_1.1_AsCas12a_CRISPRi_Seq-DeepCpf1_NCBI_20220914.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_60711_Chlorocebus_sabeus_1.1_AsCas12a_CRISPRi_Seq-DeepCpf1_NCBI_20220914.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_60711_Chlorocebus_sabeus_1.1_AsCas12a_CRISPRko_Seq-DeepCpf1_NCBI_20220914.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_60711_Chlorocebus_sabeus_1.1_AsCas12a_CRISPRko_Seq-DeepCpf1_NCBI_20220914.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_60711_Chlorocebus_sabeus_1.1_enAsCas12a_CRISPRa_enPAM+GB_NCBI_20220914.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_60711_Chlorocebus_sabeus_1.1_enAsCas12a_CRISPRa_enPAM+GB_NCBI_20220914.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_60711_Chlorocebus_sabeus_1.1_enAsCas12a_CRISPRi_enPAM+GB_NCBI_20220914.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_60711_Chlorocebus_sabeus_1.1_enAsCas12a_CRISPRi_enPAM+GB_NCBI_20220914.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_60711_Chlorocebus_sabeus_1.1_enAsCas12a_CRISPRko_enPAM+GB_NCBI_20220914.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_60711_Chlorocebus_sabeus_1.1_enAsCas12a_CRISPRko_enPAM+GB_NCBI_20220914.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_60711_Chlorocebus_sabeus_1.1_SpyoCas9_CRISPRa_RS3seq-Chen2013_NCBI_20220914.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_60711_Chlorocebus_sabeus_1.1_SpyoCas9_CRISPRa_RS3seq-Chen2013_NCBI_20220914.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_60711_Chlorocebus_sabeus_1.1_SpyoCas9_CRISPRko_RS3seq-Chen2013+RS3target_NCBI_20220914.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_60711_Chlorocebus_sabeus_1.1_SpyoCas9_CRISPRko_RS3seq-Chen2013+RS3target_NCBI_20220914.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh37_SaurCas9_CRISPRa_Azimuth_2.0_NCBI_20241107.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh37_SaurCas9_CRISPRa_Azimuth_2.0_NCBI_20241107.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh37_SaurCas9_CRISPRi_Azimuth_2.0_NCBI_20241107.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh37_SaurCas9_CRISPRi_Azimuth_2.0_NCBI_20241107.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh37_SaurCas9_CRISPRko_Azimuth_2.0_NCBI_20241107.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh37_SaurCas9_CRISPRko_Azimuth_2.0_NCBI_20241107.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh37_SpyoCas9_CRISPRa_RS3seq-Chen2013_NCBI_20241107.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh37_SpyoCas9_CRISPRa_RS3seq-Chen2013_NCBI_20241107.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh37_SpyoCas9_CRISPRko_RS3seq-Chen2013+RS3target_NCBI_20241107.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh37_SpyoCas9_CRISPRko_RS3seq-Chen2013+RS3target_NCBI_20241107.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_AsCas12a_CRISPRa_Seq-DeepCpf1_Ensembl_20250806.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_AsCas12a_CRISPRa_Seq-DeepCpf1_Ensembl_20250806.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_AsCas12a_CRISPRa_Seq-DeepCpf1_NCBI_20250718.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_AsCas12a_CRISPRa_Seq-DeepCpf1_NCBI_20250718.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_AsCas12a_CRISPRi_Seq-DeepCpf1_Ensembl_20250806.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_AsCas12a_CRISPRi_Seq-DeepCpf1_Ensembl_20250806.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_AsCas12a_CRISPRi_Seq-DeepCpf1_NCBI_20250718.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_AsCas12a_CRISPRi_Seq-DeepCpf1_NCBI_20250718.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_AsCas12a_CRISPRko_Seq-DeepCpf1_Ensembl_20250806.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_AsCas12a_CRISPRko_Seq-DeepCpf1_Ensembl_20250806.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_AsCas12a_CRISPRko_Seq-DeepCpf1_NCBI_20250718.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_AsCas12a_CRISPRko_Seq-DeepCpf1_NCBI_20250718.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_enAsCas12a_CRISPRa_enPAM+GB_Ensembl_20250806.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_enAsCas12a_CRISPRa_enPAM+GB_Ensembl_20250806.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_enAsCas12a_CRISPRa_enPAM+GB_NCBI_20250718.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_enAsCas12a_CRISPRa_enPAM+GB_NCBI_20250718.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_enAsCas12a_CRISPRi_enPAM+GB_Ensembl_20250806.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_enAsCas12a_CRISPRi_enPAM+GB_Ensembl_20250806.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_enAsCas12a_CRISPRi_enPAM+GB_NCBI_20250718.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_enAsCas12a_CRISPRi_enPAM+GB_NCBI_20250718.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_enAsCas12a_CRISPRko_enPAM+GB_Ensembl_20250806.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_enAsCas12a_CRISPRko_enPAM+GB_Ensembl_20250806.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_enAsCas12a_CRISPRko_enPAM+GB_NCBI_20250718.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_enAsCas12a_CRISPRko_enPAM+GB_NCBI_20250718.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_SaurCas9_CRISPRa_Azimuth_2.0_Ensembl_20250806.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_SaurCas9_CRISPRa_Azimuth_2.0_Ensembl_20250806.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_SaurCas9_CRISPRa_Azimuth_2.0_NCBI_20250718.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_SaurCas9_CRISPRa_Azimuth_2.0_NCBI_20250718.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_SaurCas9_CRISPRi_Azimuth_2.0_Ensembl_20250806.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_SaurCas9_CRISPRi_Azimuth_2.0_Ensembl_20250806.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_SaurCas9_CRISPRi_Azimuth_2.0_NCBI_20250718.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_SaurCas9_CRISPRi_Azimuth_2.0_NCBI_20250718.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_SaurCas9_CRISPRko_Azimuth_2.0_Ensembl_20250806.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_SaurCas9_CRISPRko_Azimuth_2.0_Ensembl_20250806.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_SaurCas9_CRISPRko_Azimuth_2.0_NCBI_20250718.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_SaurCas9_CRISPRko_Azimuth_2.0_NCBI_20250718.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_SpyoCas9_CRISPRa_RS3seq-Chen2013_Ensembl_20250806.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_SpyoCas9_CRISPRa_RS3seq-Chen2013_Ensembl_20250806.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_SpyoCas9_CRISPRa_RS3seq-Chen2013_NCBI_20250718.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_SpyoCas9_CRISPRa_RS3seq-Chen2013_NCBI_20250718.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_SpyoCas9_CRISPRi_RS3i-Chen2013_Ensembl_20250806.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_SpyoCas9_CRISPRi_RS3i-Chen2013_Ensembl_20250806.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_SpyoCas9_CRISPRi_RS3i-Chen2013_NCBI_20250718.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_SpyoCas9_CRISPRi_RS3i-Chen2013_NCBI_20250718.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_SpyoCas9_CRISPRko_RS3seq-Chen2013+RS3target_NCBI_20241104.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_SpyoCas9_CRISPRko_RS3seq-Chen2013+RS3target_NCBI_20241104.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_SpyoCas9_CRISPRko_RS3seq-Chen2013+RS3target_Ensembl_20241028.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9606_GRCh38_SpyoCas9_CRISPRko_RS3seq-Chen2013+RS3target_Ensembl_20241028.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_AsCas12a_CRISPRa_Seq-DeepCpf1_NCBI_20250807.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_AsCas12a_CRISPRa_Seq-DeepCpf1_NCBI_20250807.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_AsCas12a_CRISPRa_Seq-DeepCpf1_Ensembl_20250724.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_AsCas12a_CRISPRa_Seq-DeepCpf1_Ensembl_20250724.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_AsCas12a_CRISPRi_Seq-DeepCpf1_NCBI_20250807.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_AsCas12a_CRISPRi_Seq-DeepCpf1_NCBI_20250807.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_AsCas12a_CRISPRi_Seq-DeepCpf1_Ensembl_20250724.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_AsCas12a_CRISPRi_Seq-DeepCpf1_Ensembl_20250724.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_AsCas12a_CRISPRko_Seq-DeepCpf1_NCBI_20250807.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_AsCas12a_CRISPRko_Seq-DeepCpf1_NCBI_20250807.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_AsCas12a_CRISPRko_Seq-DeepCpf1_Ensembl_20250724.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_AsCas12a_CRISPRko_Seq-DeepCpf1_Ensembl_20250724.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_enAsCas12a_CRISPRa_enPAM+GB_NCBI_20250807.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_enAsCas12a_CRISPRa_enPAM+GB_NCBI_20250807.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_enAsCas12a_CRISPRa_enPAM+GB_Ensembl_20250724.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_enAsCas12a_CRISPRa_enPAM+GB_Ensembl_20250724.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_enAsCas12a_CRISPRi_enPAM+GB_NCBI_20250807.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_enAsCas12a_CRISPRi_enPAM+GB_NCBI_20250807.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_enAsCas12a_CRISPRi_enPAM+GB_Ensembl_20250724.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_enAsCas12a_CRISPRi_enPAM+GB_Ensembl_20250724.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_enAsCas12a_CRISPRko_enPAM+GB_NCBI_20250807.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_enAsCas12a_CRISPRko_enPAM+GB_NCBI_20250807.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_enAsCas12a_CRISPRko_enPAM+GB_Ensembl_20250724.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_enAsCas12a_CRISPRko_enPAM+GB_Ensembl_20250724.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_SaurCas9_CRISPRa_Azimuth_2.0_NCBI_20250807.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_SaurCas9_CRISPRa_Azimuth_2.0_NCBI_20250807.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_SaurCas9_CRISPRa_Azimuth_2.0_Ensembl_20250724.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_SaurCas9_CRISPRa_Azimuth_2.0_Ensembl_20250724.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_SaurCas9_CRISPRi_Azimuth_2.0_NCBI_20250807.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_SaurCas9_CRISPRi_Azimuth_2.0_NCBI_20250807.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_SaurCas9_CRISPRi_Azimuth_2.0_Ensembl_20250724.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_SaurCas9_CRISPRi_Azimuth_2.0_Ensembl_20250724.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_SaurCas9_CRISPRko_Azimuth_2.0_NCBI_20250807.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_SaurCas9_CRISPRko_Azimuth_2.0_NCBI_20250807.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_SaurCas9_CRISPRko_Azimuth_2.0_Ensembl_20250724.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_SaurCas9_CRISPRko_Azimuth_2.0_Ensembl_20250724.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_SpyoCas9_CRISPRa_RS3seq-Chen2013_NCBI_20250807.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_SpyoCas9_CRISPRa_RS3seq-Chen2013_NCBI_20250807.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_SpyoCas9_CRISPRa_RS3seq-Chen2013_Ensembl_20250724.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_SpyoCas9_CRISPRa_RS3seq-Chen2013_Ensembl_20250724.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_SpyoCas9_CRISPRi_RS3i-Chen2013_NCBI_20250807.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_SpyoCas9_CRISPRi_RS3i-Chen2013_NCBI_20250807.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_SpyoCas9_CRISPRi_RS3i-Chen2013_Ensembl_20250724.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_SpyoCas9_CRISPRi_RS3i-Chen2013_Ensembl_20250724.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_SpyoCas9_CRISPRko_RS3seq-Chen2013+RS3target_NCBI_20240614.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_SpyoCas9_CRISPRko_RS3seq-Chen2013+RS3target_NCBI_20240614.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_SpyoCas9_CRISPRko_RS3seq-Chen2013+RS3target_Ensembl_20230403.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10090_GRCm38_SpyoCas9_CRISPRko_RS3seq-Chen2013+RS3target_Ensembl_20230403.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_8022_USDA_OmykA_1.1_SpyoCas9_CRISPRa_RS3seq-Chen2013_NCBI_20230419.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_8022_USDA_OmykA_1.1_SpyoCas9_CRISPRa_RS3seq-Chen2013_NCBI_20230419.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_8022_USDA_OmykA_1.1_SpyoCas9_CRISPRko_RS3seq-Chen2013+RS3target_NCBI_20230419.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_8022_USDA_OmykA_1.1_SpyoCas9_CRISPRko_RS3seq-Chen2013+RS3target_NCBI_20230419.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10116_mRatBN7.2_AsCas12a_CRISPRa_Seq-DeepCpf1_Ensembl_20241112.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10116_mRatBN7.2_AsCas12a_CRISPRa_Seq-DeepCpf1_Ensembl_20241112.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10116_mRatBN7.2_AsCas12a_CRISPRa_Seq-DeepCpf1_NCBI_20240131.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10116_mRatBN7.2_AsCas12a_CRISPRa_Seq-DeepCpf1_NCBI_20240131.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10116_mRatBN7.2_AsCas12a_CRISPRi_Seq-DeepCpf1_Ensembl_20241112.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10116_mRatBN7.2_AsCas12a_CRISPRi_Seq-DeepCpf1_Ensembl_20241112.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10116_mRatBN7.2_AsCas12a_CRISPRi_Seq-DeepCpf1_NCBI_20240131.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10116_mRatBN7.2_AsCas12a_CRISPRi_Seq-DeepCpf1_NCBI_20240131.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10116_mRatBN7.2_AsCas12a_CRISPRko_Seq-DeepCpf1_Ensembl_20241112.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10116_mRatBN7.2_AsCas12a_CRISPRko_Seq-DeepCpf1_Ensembl_20241112.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10116_mRatBN7.2_AsCas12a_CRISPRko_Seq-DeepCpf1_NCBI_20240131.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10116_mRatBN7.2_AsCas12a_CRISPRko_Seq-DeepCpf1_NCBI_20240131.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10116_mRatBN7.2_enAsCas12a_CRISPRa_enPAM+GB_Ensembl_20241112.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10116_mRatBN7.2_enAsCas12a_CRISPRa_enPAM+GB_Ensembl_20241112.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10116_mRatBN7.2_enAsCas12a_CRISPRa_enPAM+GB_NCBI_20240131.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10116_mRatBN7.2_enAsCas12a_CRISPRa_enPAM+GB_NCBI_20240131.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10116_mRatBN7.2_enAsCas12a_CRISPRi_enPAM+GB_Ensembl_20241112.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10116_mRatBN7.2_enAsCas12a_CRISPRi_enPAM+GB_Ensembl_20241112.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10116_mRatBN7.2_enAsCas12a_CRISPRi_enPAM+GB_NCBI_20240131.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10116_mRatBN7.2_enAsCas12a_CRISPRi_enPAM+GB_NCBI_20240131.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10116_mRatBN7.2_enAsCas12a_CRISPRko_enPAM+GB_Ensembl_20241112.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10116_mRatBN7.2_enAsCas12a_CRISPRko_enPAM+GB_Ensembl_20241112.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10116_mRatBN7.2_enAsCas12a_CRISPRko_enPAM+GB_NCBI_20240131.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10116_mRatBN7.2_enAsCas12a_CRISPRko_enPAM+GB_NCBI_20240131.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10116_mRatBN7.2_SpyoCas9_CRISPRa_RS3seq-Chen2013_Ensembl_20241112.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10116_mRatBN7.2_SpyoCas9_CRISPRa_RS3seq-Chen2013_Ensembl_20241112.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10116_mRatBN7.2_SpyoCas9_CRISPRa_RS3seq-Chen2013_NCBI_20240131.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10116_mRatBN7.2_SpyoCas9_CRISPRa_RS3seq-Chen2013_NCBI_20240131.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10116_mRatBN7.2_SpyoCas9_CRISPRko_RS3seq-Chen2013+RS3target_Ensembl_20241112.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10116_mRatBN7.2_SpyoCas9_CRISPRko_RS3seq-Chen2013+RS3target_Ensembl_20241112.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10116_mRatBN7.2_SpyoCas9_CRISPRko_RS3seq-Chen2013+RS3target_NCBI_20240131.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10116_mRatBN7.2_SpyoCas9_CRISPRko_RS3seq-Chen2013+RS3target_NCBI_20240131.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10116_Rnor_6.0_SaurCas9_CRISPRi_Azimuth_2.0_NCBI_20220907.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10116_Rnor_6.0_SaurCas9_CRISPRi_Azimuth_2.0_NCBI_20220907.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10116_Rnor_6.0_SaurCas9_CRISPRko_Azimuth_2.0_NCBI_20220907.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10116_Rnor_6.0_SaurCas9_CRISPRko_Azimuth_2.0_NCBI_20220907.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10116_Rnor_6.0_SpyoCas9_CRISPRa_RS3seq-Chen2013_NCBI_20220907.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10116_Rnor_6.0_SpyoCas9_CRISPRa_RS3seq-Chen2013_NCBI_20220907.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10116_Rnor_6.0_SpyoCas9_CRISPRko_RS3seq-Chen2013+RS3target_NCBI_20220907.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_10116_Rnor_6.0_SpyoCas9_CRISPRko_RS3seq-Chen2013+RS3target_NCBI_20220907.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9544_Mmul_10_SpyoCas9_CRISPRa_RS3seq-Chen2013_NCBI_20241025.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9544_Mmul_10_SpyoCas9_CRISPRa_RS3seq-Chen2013_NCBI_20241025.summary.txt +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9544_Mmul_10_SpyoCas9_CRISPRko_RS3seq-Chen2013+RS3target_NCBI_20241025.txt.gz +https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/sgRNA_design_9544_Mmul_10_SpyoCas9_CRISPRko_RS3seq-Chen2013+RS3target_NCBI_20241025.summary.txt diff --git a/BioScientist/agent_system/engines/v1_executor_backup/know_how/resource/addgene_grna_sequences.csv b/BioScientist/agent_system/engines/v1_executor_backup/know_how/resource/addgene_grna_sequences.csv new file mode 100644 index 0000000000000000000000000000000000000000..43ffcd9aef5563c42c3d09f042a40a9b5b21164e --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/know_how/resource/addgene_grna_sequences.csv @@ -0,0 +1,322 @@ +Application,Cas9 Species,Depositor,Plasmid ID,PubMed ID,Target Gene,Target Sequence,Target Species +cut,S. pyogenes,Goncalves,"58252","24870050",AAVS1,GGGGCCACTAGGGACAGGAT,H. sapiens +cut,S. pyogenes,Church,"41818","23287722",AAVS1,GGGGCCACTAGGGACAGGAT,H. sapiens +cut,S. pyogenes,Sabatini,"50662","24336569",AAVS1,GGGGCCACTAGGGACAGGAT,H. sapiens +cut,S. pyogenes,Sabatini,"70661","26472758",AAVS1,GGGGCCACTAGGGACAGGAT,H. sapiens +cut,S. pyogenes,Church,"41817","23287722",AAVS1,GTCCCCTCCACCCCACAGTG,H. sapiens +cut,S. pyogenes,Kanemaki,"72833","27052166",AAVS1,GGGGCCACTAGGGACAGGAT,H. sapiens +cut,S. pyogenes,Corn,"","26789497",AAVS1,TGTCCCTAGTGGCCCCACTG,H. sapiens +cut,S. pyogenes,Corn,"","26789497",AAVS1,ACAGTGGGGCCACTAGGGAC,H. sapiens +RNA targeting,S. pyogenes,Yeo,"74705","26997482",ACTB,UGGAGCGAGCAUCCCCCAAA,H. sapiens +cut,S. pyogenes,Jiang,"62552","25739462",actII-orf4,ATTACCAGGGACCGGAGTTC,S. coelicolor +cut,S. pyogenes,Zaratiegui,"52225","25352017",ade6+,TCTATTGTTCAGATGCCTCG,S. pombe +cut,S. pyogenes,Zaratiegui,"52227","25352017",ade6-L469,TCTATTGTTCAGATGCCTTG,S. pombe +cut,S. pyogenes,Zaratiegui,"52226","25352017",ade6-M210,TCTATTGTTCAGATGCTTCG,S. pombe +cut,S. pyogenes,Ventura,"64071","25337876",Alk and Eml,,M. musculus +nick,S. pyogenes,Shaw,"74374","26816379",AMPK alpha 1,GGCTGTCGCCATCTTTCTCC,H. sapiens +nick,S. pyogenes,Shaw,"74375","26816379",AMPK alpha 1,GAAGATCGGCCACTACATTC,H. sapiens +nick,S. pyogenes,Shaw,"74376","26816379",AMPK alpha 2,GTCAGCCATCTTCGGCGCGCG,H. sapiens +nick,S. pyogenes,Shaw,"74377","26816379",AMPK alpha 2,GAAGATCGGACACTACGTGC,H. sapiens +cut,S. pyogenes,Sabatini,"70660","26472758","Amplicon, JAK2",GAGGCATATTCTTCTCCTGG,H. sapiens +cut,S. pyogenes,Voytas,"70019","26541286",ANT1,TGTCGTTTATAATTTGTAGA,S. lycopersicum +cut,S. pyogenes,Voytas,"70018","26541286",ANT1,ACAATTTAATACACCTTTT,S. lycopersicum +cut,S. pyogenes,Kim,"","26479191",AOC,CAAAAGACTGTCAATTCCCT,N. attenuata +cut/nick,S. pyogenes,Yamamoto,"58780","24954249",APC,GAAGCGGGCAAAGGGGCGAC,H. sapiens +cut,S. pyogenes,Joung,"42241","23360964",apoea,GGATGAGCCAAGAAGCCGCT,D. rerio +activate,S. pyogenes,Sato,"64131","25619936",ASCL1,TGGATGGAGAGTTTGCAAGGAGC,H. sapiens +activate,S. pyogenes,Sato,"64130","25619936",ASCL1,TGGGCAGCCGCTCGCTGCAGCAG,H. sapiens +activate,S. pyogenes,Sato,"64129","25619936",ASCL1,TGGGGCTGGGTGTCCCATTGAAA,H. sapiens +activate,S. pyogenes,Sato,"64132","25619936",ASCL1,TGGTGTTTATTCAGCCGGGAGTC,H. sapiens +cut,S. pyogenes,Mashimo,"60968","24967838",Asip,ATGACAGGAGTCTAACTCAC,R. norvegicus +tag,S. pyogenes,Mendenhall,"64690","26355004",ATF1,TAGGAATCAAACACTTTTATTGG,H. sapiens +cut,S. pyogenes,Yamamoto,"58779","24954249",ATM,TGAATTGGGATGCTGTTTTT,H. sapiens +cut,S. pyogenes,Mello,"58981","24879462",avr-14,GATTGGAGAGTTAGACCACG,C. elegans +cut,S. pyogenes,Mello,"58982","24879462",avr-15,GTTTGCAATATAAGTCACCC,C. elegans +cut,S. pyogenes,Yamamoto,"58782","24954249",AXIN2,TATGTTGGTGACTTGCCTCC,H. sapiens +methylation,S. pyogenes,Zoldoš,"71828","26969735",BACH2,AATGTAGCGATTGAGAGTGTGGG,H. sapiens +cut,S. pyogenes,Sabatini,"70658","26472758",BCR/ABL amplicon,GGCTCCCTTCAAGTGGGATG,H. sapiens +cut,S. pyogenes,Corn,"","26789497",BFP,ATGGCGTGCAGTGCTTCAGC, +cut,S. pyogenes,Kim,"","26479191",BIN2,ATCACAGTGATGCTCGTCAA,L. sativa +cut,S. pyogenes,Hanna,"59724","25543152",BLIMP1,CGGATGGGGTAAACGACCCG,H. sapiens +cut,S. pyogenes,Kim,"","26479191",BRI1,TTTGAAAGATGGAAGCGCGG,A. thaliana +cut,S. pyogenes,Kim,"","26479191",BRI1,TGAAACTAAACTGGTCCACA,A. thaliana +interfere,S. pyogenes,Lu,"68892","26918244",BT1754,GAAAATGGGGTGTATCCTGC,B. thetaiotaomicron +interfere,S. pyogenes,Lu,"68891","26918244",BT1854,ATTGAAGAACAAAAGCAGTT,B. thetaiotaomicron +cut,S. pyogenes,Sabatini,"70650","26472758",C16orf80,CGATGCTGTAGAGGATGGAG,H. sapiens +cut,S. pyogenes,Sabatini,"70651","26472758",C16orf80,TGTCTGAGAAGTAAACCCGT,H. sapiens +cut,S. pyogenes,Sabatini,"70653","26472758",C3orf17,GGGCCAAATGGGGTTTGTGG,H. sapiens +cut,S. pyogenes,Sabatini,"70652","26472758",C3orf17,GTGTGAGAATCCCTAAGGCG,H. sapiens +cut,S. pyogenes,Sabatini,"70654","26472758",C9orf114,CAGGCGGGCTCACCTCCGTG,H. sapiens +cut,S. pyogenes,Sabatini,"70655","26472758",C9orf114,GCGGCAGAGAAGGAGGACCG,H. sapiens +cut,S. pyogenes,Church,"43803","23460208",CAN1,GATACGTTCTCTATGGAGGA,S. cerevisiae +cut,S. pyogenes,Bornhauser,"75164","27194728",Caspase-8,GCCTGGACTACATTCCGCAA,H. sapiens +cut,S. pyogenes,Corn,"","26789497",CCR5,TGACATCAATTATTATACAT,H. sapiens +interfere,S. pyogenes,Qi,"46918","23849981",CD71,GGACGCGCTAGTGTGAGTGC,H. sapiens +cut,S. pyogenes,Yamamoto,"58781","24954249",CDH1,TGACTTGCGAGGGACGCATT,H. sapiens +activate,S. pyogenes,Vale,"60905","25307933",CDKN1B,GAAGCCGGGACCTGGACCAG,H. sapiens +tag,S. pyogenes,Mendenhall,"64036","26355004",CEBPB,CTCCGGCCACTGCTAGCGCGG,H. sapiens +tag,S. pyogenes,Mendenhall,"64047","26355004",CEBPB,GCCGGCAGGGGGACGCGCGCGG,H. sapiens +cut,S. pyogenes,Ikawa,"50718","24284873",Cent1,GGCAACGTTTGACTTCCTGA,M. musculus +cut,S. pyogenes,Yamamoto,"58783","24954249",CFTR,TCTGTATCTATATTCATCAT,H. sapiens +tag,S. pyogenes,Mendenhall,"64940","26355004",CREB1,GCCACAAATCAGATTAATTTGG,H. sapiens +tag,S. pyogenes,Mendenhall,"64939","26355004",CREB1,GCCACAAATCAGATTAATTTGGG,H. sapiens +cut,S. pyogenes,Hong,"68060","Fungal Biology and Biotechnology 2015, 2:4",csr-1,GAGTGGGAGGGTCCCGTCCT,N. crassa +cut,S. pyogenes,Jacks,"59912","25119044",Ctnnb1,AGCTCCTTCCCTGAGTGGCA,M. musculus +cut,S. pyogenes,Jacks,"59911","25119044",Ctnnb1,CTGTGGTGGTGGCACCAGAA,M. musculus +interfere,S. pyogenes,Qi,"46917","23849981",CXCR4,GCAGGTAGCAAAGTGACGCCGA,H. sapiens +cut,S. pyogenes,Corn,"","26789497",CXCR4,CCTCTTTGTCATCACGCTTC,H. sapiens +activate,S. pyogenes,Lu,"64385","23977949",CYC1m promoter,ACAGAGCACATGCATGCCAT,S. cerevisiae +activate,S. pyogenes,Lu,"64387","23977949",CYC1m promoter,ACTAATACTTTCAACATTTT,S. cerevisiae +activate,S. pyogenes,Lu,"64382","23977949",CYC1m promoter,ATATCGAATTCCTGCAGCCC,S. cerevisiae +activate,S. pyogenes,Lu,"64380","23977949",CYC1m promoter,ATATTCTTTCCTTATACATT,S. cerevisiae +activate,S. pyogenes,Lu,"64379","23977949",CYC1m promoter,CTAGATATTAAAATGTCTAA,S. cerevisiae +activate,S. pyogenes,Lu,"64388","23977949",CYC1m promoter,GTTGAAAGTATTAGTTAAAG,S. cerevisiae +activate,S. pyogenes,Lu,"64381","23977949",CYC1m promoter,TACATACAGTAGGATCCTA,S. cerevisiae +activate,S. pyogenes,Lu,"64383","23977949",CYC1m promoter,TATAGTAATTTATGCTGCAA,S. cerevisiae +activate,S. pyogenes,Lu,"64384","23977949",CYC1m promoter,TGCAAAGGTCCTAATGTATA,S. cerevisiae +activate,S. pyogenes,Lu,"64386","23977949",CYC1m promoter,TGTATGTACATACAGTACCC,S. cerevisiae +activate,S. pyogenes,Lu,"64378","23977949",CYC1m promoter,TTACTGTATGTACATACAGT,S. cerevisiae +cut,S. pyogenes,Wente,"47932","23918387",ddx19,GGCAACAGATTCGTGGGCCC,D. rerio +cut,S. pyogenes,Sabatini,"70656","26472758",DDX3Y,GCAGTTTAGCGATATTGACA,H. sapiens +cut,S. pyogenes,Sabatini,"70657","26472758",DDX3Y,TCTTGTTGGGGCTAAAACCA,H. sapiens +cut,S. pyogenes,Church,"41822","23287722",DNMT3A,GAGATGATCGCCCCTTCTTC,H. sapiens +cut,S. pyogenes,Church,"41821","23287722",DNMT3A,GCATGATGCGCGGCCCAAGG,H. sapiens +cut,S. pyogenes,Church,"41823","23287722",DNMT3B,GAATTACTCACGCCCCAAGG,H. sapiens +cut,VRER Cas9 mutant,Fire,"71516","26680661",dpy-10,CGCTACCATAGGCACCACG,C. elegans +cut,S. pyogenes,Katic,"65630","26044730",dpy-10,GCTACCATAGGCACCACGAG,C.elegans +cut,S. pyogenes,Fire,"59933","25161212",dpy-10,GCTACCATAGGCACCACGAG,C. elegans +cut,VQR Cas9 variant,Fire,"71479","26680661",dpy-10,TCCGCTACCATAGGCACCA,C. elegans +cut,S. pyogenes,Seydoux,"70047","26187122",dpy‐10,GCTACCATAGGCACCACGAG,C. elegans +cut,S. pyogenes,Joung,"42242","23360964",drd3,GGAAACTACAGCCCAGCGTC,D. rerio +cut,S. pyogenes,Kim,"","26479191",DWD1,TGCATCGTCCAAGCGCACAG,O. sativa +cut,S. pyogenes,Kim,"","26479191",DWD1,CTACGACGTCAGGTTCTACC,O. sativa +cut,S. pyogenes,Christiaen,"59990","25336740",Ebf,GCTGAGGGTTGGACAACAGG,C. intestinalis +dCas9-FokI,S. pyogenes,Joung,"60071","24770325",EGFP,"multiple, see article",A. victoria +cut,S. pyogenes,Zhang,"51764","24336571",EGFP,GAAGTTCGAGGGCGACACCC,A. victoria +cut,S. pyogenes,Zhang,"51761","24336571",EGFP,GAGCTGGACGGCGACGTAAA,A. victoria +cut,S. pyogenes,Joung,"47512","23792628",EGFP,GATGCCGTTCTTCTGCTTGT,A. victoria +cut,S. pyogenes,Zhang,"51763","24336571",EGFP,GGAGCGCACCATCTTCTTCA,A. victoria +cut,S. pyogenes,Zhang,"51762","24336571",EGFP,GGCCACAAGTTCAGCGTGTC,A. victoria +cut,S. pyogenes,Del Bene,"61051","24179142",EGFP,GGCGAGGGCGATGCCACCTA,A. victoria +cut,S. pyogenes,Chen,"46760","23918387",EGFP,GGGCACGGGCAGCTTGCCGG,A. victoria +cut,S. pyogenes,Joung,"47511","23792628",EGFP,GGGCACGGGCAGCTTGCCGG,A. victoria +cut,S. pyogenes,Zhang,"51760","24336571",EGFP,GGGCGAGGAGCTGTTCACCG,A. victoria +cut,S. pyogenes,Zhang,"51765","24336571",EGFP,GGTGAACCGCATCGAGCTGA,A. victoria +cut,S. pyogenes,Joung,"47513","23792628",EGFP,GGTGGTGCAGATGAACTTCA,A. victoria +cut,S. pyogenes,Goncalves,"58255","24870050",EGFP,TGAAGAAGATGGTGCGCTC,A. victoria +cut,S. pyogenes,Moffat,"74187","26627737",EIF3D,TGTAGGTTGCCTCCATGGCC,H. sapiens +cut,S. pyogenes,Moffat,"74188","26627737",EIF3D,AGACGACCCTGTCATCCGCA,H. sapiens +cut,S. pyogenes,Zhang,"42337","23287718",Emx1,,H. sapiens +cut,S. pyogenes,Joung,"47508","23792628",EMX1,GAGTCCGAGCAGAAGAAGAA,H. sapiens +cut,S. pyogenes,Corn,"","26789497",EMX1,CGATGTCACCTCCAATGACT,H. sapiens +cut,S. pyogenes,Chen,"71288","26193878","ETC2, TRY, and CPC",,A. thaliana +cut,S. pyogenes,Bornhauser,"75166","27194728",FADD,ACTCCCGCACACGCTCTGTC,H. sapiens +cut,S. pyogenes,Joung,"47510","23792628",FANCF,GGAATCCCTTCTGCAGCACC,H. sapiens +cut,S. pyogenes,Seydoux,"65597","25249454",fbf-2,GTAGTCACGGCGATGATTA,C. elegans +cut,S. pyogenes,Seydoux,"65591","25249454",fbf-2,TAATCATCGCCGTGACTAC,C. elegans +cut,S. pyogenes,Joung,"42244","23360964",fh,GGAGCGAGCGGAGCGGTACA,D. rerio +cut,S. pyogenes,Joung,"42243","23360964",fh,GGAGCGGTACATGGCGACCG,D. rerio +tag,S. pyogenes,Mendenhall,"64254","26355004",GABPA,GAAAAGGATAATTGAGCCCCAGG,H. sapiens +tag,S. pyogenes,Mendenhall,"64255","26355004",GABPA,TTTGGAGTCTCAGAATGTCCTGG,H. sapiens +activate,S. pyogenes,Qi,"46916","23849981",GAL4 UAS,GAACGACTAGTTAGGCGTGTA, +activate,S. pyogenes,Qi,"46915","23849981",GAL4 UAS,GTTGGAGCACTGTCCTCCGAACGT, +activate,S. pyogenes,Sato,"64158","25619936",GAL4UAS,TGGGGACAGTACTCCGCTCGAGT, +activate,S. pyogenes,Sato,"64157","25619936",GAL4UAS,TGGGTCTTCGGAGGACAGTACTC, +activate,S. pyogenes,Sato,"64159","25619936",GAL4UAS,TGGTCCGTCTAGAAACTCGGTAC, +cut,S. pyogenes,Du,"65566","25849248",gfap,GTGCGCAACACATAGCACCA,D. rerio +interfere,S. pyogenes,Qi,"46914","23849981",GFP,GAATAGCTCAGAGGCCGAGG,A. victoria +cut,S. pyogenes,Church,"41820","23287722",GFP,GGAGCGCACCATCTTCTTCA,A. victoria +cut,S. pyogenes,Church,"41819","23287722",GFP,GTGAACCGCATCGAGCTGAA,A. victoria +cut,S. pyogenes,"Guigo, Johnson","72619","26493208",GFP,gRNA1: GAGCTGGACGGCGACGTAAA; gRNA2: CAGAACACCCCCATCGGCGA,Synthetic +interfere,S. pyogenes,Hudson,"73221","26689101",GFPmut3b,ACCATCTAATTCAACAAGAATT,A. victoria +interfere,S. pyogenes,Hudson,"73224","26689101",GFPmut3b,ACCATCTAATTCAACAAGAATT,synthetic +CRISPR-display,S. pyogenes,Rinn,"68422","26030444",GLuc,GATCTAGATACGACTCACTAT,synthetic +cut,S. pyogenes,Ye,"61833","24424410",gp78,GCCCAGCCTCCGCACCTACA,H. sapiens +cut,S. pyogenes,Joung,"42245","23360964",gsk3b,GGGACCTGACCGGCCGCAGG,D. rerio +cut,S. pyogenes,Jin,"64333","25281382",his3,ATTGCGATCTCTTTAAAGGG,S. cerevisiae +cut,S. pyogenes,Yan,"69539","26130722",HPRT,GACTGTAAGTGAATTACTT,H. sapiens +cut,S. pyogenes,Yamamoto,"58778","24954249",HPRT1,CTGATAAAATCTACAGTCAT,H. sapiens +cut,S. pyogenes,Yamamoto,"58771","24954249",HPRT1,TTATGCTGAGGATTTGGAAA,H. sapiens +activate,S. pyogenes,Sato,"64142","25619936",IL1RN,TGGACGCAGATAAGAACCAGTT,H. sapiens +activate,S. pyogenes,Sato,"64151","25619936",IL1RN,TGGCATCAAGTCAGCCATCAGC,H. sapiens +activate,S. pyogenes,Sato,"64152","25619936",IL1RN,TGGGAGTCACCCTCCTGGAAAC,H. sapiens +activate,S. pyogenes,Sato,"64140","25619936",IL1RN,TGGTGTACTCTCTGAGGTGCTC,H. sapiens +cut,S. pyogenes,Xue,"66582","26018130",inverted GFP,GAGCGGCCGCTCGAGTCTAG,A. victoria +cut,S. pyogenes,Xue,"66583","26018130",inverted GFP,GATATCGAATTCCTGCAGCC,A. victoria +cut,S. pyogenes,Xue,"66581","26018130",inverted GFP,GTATCGATACCGTCGACCTCG,A. victoria +cut,S. pyogenes,Xue,"66584","26018130",inverted GFP,GTTGATCCATAACTTCGTAT,A. victoria +purify,S. pyogenes,Fujii,"61079","23942116",IRF1,CCGGGGGCGCTGGGCTGTCCCGG,H. sapiens +purify,S. pyogenes,Fujii,"61080","25051498",IRF1,GCGCTTACACTTTAGGAGACACTC,H. sapiens +cut,S. pyogenes,Sabatini,"70679","26472758",JAK2 amplicon ,GGTTTAATGGAAGAGAAGGG,H. sapiens +cut,S. pyogenes,Seydoux,"66085","25249454",K08F4.2,AATCACTCCCTGTTTGTGT,C. elegans +cut,S. pyogenes,Seydoux,"66095","25249454",K08F4.2,CACGAGGTGGTATGCGCAG,C. elegans +cut,S. pyogenes,Seydoux,"66092","25249454",K08F4.2,CGCAGCGGTTTCCAAAATG,C. elegans +cut,S. pyogenes,Seydoux,"66087","25249454",K08F4.2,GCCTTAACCCAGAATAAGA,C. elegans +cut,S. pyogenes,Seydoux,"66089","25249454",K08F4.2,TATTAAATGCAGATAACCT,C. elegans +cut,S. pyogenes,Wolfe,"69238","26480473",KANK3,GCATGGGTGATGTCAATGCC,H. sapiens +cut,S. pyogenes,Mashimo,"60969","24967838",Kit-1,CATCTGTGCGGCCGTTGGCT,R. norvegicus +cut,S. pyogenes,Mashimo,"60970","24967838",Kit-2,CTAACGTTCCAGCGCTCGTT,R. norvegicus +cut,S. pyogenes,Mashimo,"60971","24967838",Kit-2,GTCAAGATGTCATCTTACGG,R. norvegicus +cut,S. pyogenes,Calarco,"46170","23817069",klp-12,GATCCACAAGTTACAATTGG,C. elegans +cut,S. pyogenes,Zhang,"60224","25263330","Kras, p53, and Lkb1","multiple, see article",M. musculus +cut,S. pyogenes,Zhang,"60225","25263330",LacZ,TGCGAATACGCCCACGCGAT,E. coli +cut,S. pyogenes,Moffat,"74179","26627737",LacZ,CCCGAATCTCTATCGTGCGG,E.coli +cut,S. pyogenes,Patron,"68256","26616834",lC.GA4a,GTTGAGAGGGGAGCCGGTGA,B. oleracea +cut,S. pyogenes,Patron,"68255","26616834",lC.GA4a,GTTTTCACTTGCGGCCGGAG,B. oleracea +cut,S. pyogenes,Jin,"64332","25281382",leu2,AATCACAGCCGAAGCCATTA,S. cerevisiae +cut,S. pyogenes,Winslow,"66894","26178787",Lkb1,GTGGTGGGCCGCAGTCACAA,M. musculus +cut,S. pyogenes,Xue,"66586","26018130",Lox-STOP-Lox,GCGTATAGCATACATTATACG,synthetic +cut,S. pyogenes,Xue,"66585","26018130",Lox-STOP-Lox,GCGTATAGTACACATTATACG,synthetic +cut,S. pyogenes,Wolfe,"69237","26480473",LRTM2,GCTGGCGGAAGACAGAGTGC,H. sapiens +cut,S. pyogenes,Moffat,"74190","26627737",Luciferase,ACAACTTTACCGACCGCGCC, +cut,S. pyogenes,Cate,"60847","25139909",LYP1,CATAATAACGTCCAATAAAT,S. cerevisiae +cut,S. pyogenes,"Guigo, Johnson","72620","26493208",Malat1,gRNA1: GAACCGGTGGGGCTGCGTCA; gRNA2: GGCAGGAGAGGCCAGTTGCG,H. sapiens +cut,S. pyogenes,"Guigo, Johnson","72621","26493208",Malat1,gRNA1: GCAACTTCCATTTTCAGTCT; gRNA2: GGAAGCCTCAGCTCGCCTGA,H. sapiens +cut,S. pyogenes,"Guigo, Johnson","72622","26493208",Malat1,gRNA1:GCTGGGGCTCAGTTGCGTAA; gRNA2:AGGTTTCTAAAACATGACGG,H. sapiens +cut,S. pyogenes,"Guigo, Johnson","72623","26493208",Malat1,gRNA1:GTTGAGATGAAGCTTCTTCA; gRNA2:TCAACCGTCCCTGCAAGGCT,H. sapiens +cut,S. pyogenes,"Guigo, Johnson","72624","26493208",Malat1,gRNA1: GAAACCTCGTGTAGCTATCA; gRNA2: AATGTGAAGGACTTTCGTAA,H. sapiens +nick,S. pyogenes,Hanna,"61514","25569111",Mettl14,GCCGCTCCCGGATCTCCTGC,M. musculus +nick,S. pyogenes,Hanna,"61515","25569111",Mettl14,GCGGCAGCTCCTAGCTCAGC,M. musculus +cut,S. pyogenes,Zhao,"69801","26293209",mitf,CTTTCGGATATAATCCACGG,S. scrofa  +cut,S. pyogenes,Chen,"47931","23918387",mitfa,GGTCTCTCGCAGGATGTTGC,D. rerio +cut,S. pyogenes,Bleris,"62715","25527740",mKate,ATGAGAATCAAGGCGGTCGA,synthetic +cut,S. pyogenes,Bornhauser,"75167","27194728",MLKL,ATCCCCGTGGATTCTGCTAA,H. sapiens +cut,S. pyogenes,Katsanis,"72890","26429889",mmp21,CGGAGCTGATCACTGACA,D. rerio +visualize,S. pyogenes,Qi,"51025","24360272",MUC4,GTGGCGTGACCTGTGGATGCTG,H. sapiens +activate,S. pyogenes,Sato,"64138","25619936",MYOD1,TGGCCTCCCTCCCTGCCCGGTAG,H. sapiens +activate,S. pyogenes,Sato,"64139","25619936",MYOD1,TGGGAGGTTTGGAAAGGGCGTGC,H. sapiens +activate,S. pyogenes,Sato,"64136","25619936",MYOD1,TGGGCCTGGGCTCCGGGGCGTTT,H. sapiens +activate,S. pyogenes,Sato,"64137","25619936",MYOD1,TGGGGGCCCCTGCGGCCACCCCG,H. sapiens +activate,S. pyogenes,Sato,"64156","25619936",NANOG,TGGCATATTCCTGATTTAAAAGT,H. sapiens +activate,S. pyogenes,Sato,"64153","25619936",NANOG,TGGCGCCAGGAGGGGTGGGTCTA,H. sapiens +activate,S. pyogenes,Sato,"64154","25619936",NANOG,TGGGCCTTGGTGAGACTGGTAGA,H. sapiens +activate,S. pyogenes,Sato,"64155","25619936",NANOG,TGGTGTCTTCAGGTTCTGTTGCT,H. sapiens +interfere,S. pyogenes,Lu,"68897","26918244",NanoLuc,AGCTTACGCCACCCTGTTCC,synthetic +interfere,S. pyogenes,Lu,"68898","26918244",NanoLuc,GACAGAACGATGCGCTGAAT,synthetic +interfere,S. pyogenes,Lu,"68895","26918244",NanoLuc,TCACGCTCACACCCAGGTTC,synthetic +interfere,S. pyogenes,Lu,"68896","26918244",NanoLuc,TTGATCCAAATTATAACCCG,synthetic +cut,S. pyogenes,Lu,"61270","25240928",NDM-1,GGGCAGTCGCTTCCAACGGTTTGATCGTCA, +cut,S. pyogenes,Cepko,"69992","25155555",near LoxP sites,CGAAGTTATATTAAGGGTTC,synthetic +interfere,S. pyogenes,Lu,"68893","26918244",negative control,CTGGAATGAATTGGCCTATG, +cut,S. pyogenes,Winslow,"66895","26178787",negative control,GCGAGGTATTCGGCTCCGCG,M. musculus +cut,S. pyogenes,Christiaen,"60006","25336740",negative control,GCTTTGCTACGATCTACATT,C. intestinalis +cut,S. pyogenes,Bleris,"64955","25527740",negative control,GTCAAGGCACTCTTGCCTA,synthetic +,S. pyogenes,Wolfe,"50927","24346702",negative control,GTTCCGCGTTACATAACTTA,H. sapiens +cut,S. pyogenes,Winslow,"67594","26178787",Neomycin,TCATGGCTGATGCAATGCGG, +cut,S. pyogenes,Zhang,"60227","25263330",NeuN,TCCGGTTCAGGGACCCCGAC,M. musculus +activate,S. pyogenes,Sato,"64161","25619936",Neurog2,GTCTCTATCACTGATAGGGA,H. sapiens +activate,S. pyogenes,Sato,"64160","25619936",Neurog2,GTGAATGATGATAATACGAT,H. sapiens +methylation,S. pyogenes,Zoldoš,"71830","26969735",Non-targeting,GTAGGCGCGCCGCTCTCTAC,H. sapiens +cut,S. pyogenes,Huangfu,"66989","26028531",OCT4,CTCCCATGCATTCAAACTG,H. sapiens +activate,S. pyogenes,Otonkoski,"69537","26352799",OCT4,"multiple, see article",H. sapiens +cut,N. meningitidis,Thomson,"47870","23940360",OCT4,GTTGTAGCTCCCTTTCTCATTTCG,H. sapiens +interfere,S. pyogenes,Wolfe,"50922","24346702",Oct4A (POU5F1),GGGGCGCCAGTTGTGTCTCC,H. sapiens +interfere,S. pyogenes,Wolfe,"50921","24346702",Oct4A (POU5F1),GTGGGACTGGGGAGGGAGAG,H. sapiens +cut,S. pyogenes,Kim,"","26479191",P450,CATATAGTTGGGTCATGGCA,O. sativa +cut,S. pyogenes,Sherwood,"71483","26527385",Pal1,GCTCTGTGACTAGTCACAGAG,synthetic +cut,S. pyogenes,Sherwood,"71484","26527385",Pal7,GGCTTAGTACTAGTACTAAGC,synthetic +cut,S. pyogenes,Zhang,"68466","26145478",PAX6,GATACTGGAGAAGCAGGGGC,H. sapiens +cut,S. pyogenes,Zhang,"68465","26145478",PAX6,GTAGATTTTGTATGCACTGC,H. sapiens +interfere,S. pyogenes,Lu,"68900","26918244",PcfiA,AAACAAAACCTCATCAGGCA, +interfere,S. pyogenes,Lu,"68899","26918244",PcfiA,GAAGCTCACTCCTTAGCACG, +interfere,S. pyogenes,Lu,"74068","26829286",pck,AGGGCGAGGCGCCGACCAAGAATA,C. glutamicum +interfere,S. pyogenes,Lu,"74069","26829286",pck,TCCAGTTCAGCAGTTCCTTATTCT,C. glutamicum +cut,S. pyogenes,Kamoun,"46966","23929340",PDS,GCCGTTAATTTGAGAGTCCA,N. benthamiana +cut,S. pyogenes,Kamoun,"49772","24112467",PDS1,"multiple, see article",N. benthamiana +cut,S. pyogenes,Sheen,"52255","23929339",PDS3,GGACTTTTGCCAGCCATGGT,A. thaliana +interfere,S. pyogenes,Lu,"74066","26829286",pgi,TGACCGATCATTACTCAAACTTCC,C. glutamicum +interfere,S. pyogenes,Lu,"74067","26829286",pgi,TTGCCTGGAAGTTTGAGTAATGAT,C. glutamicum +activate,S. pyogenes,Gersbach,"60719","25664691",pGL3-Basic-8x-gRNA-eGFP reporter,AAAGGTCGAGAAACTGCAAA,synthetic +cut,S. pyogenes,Ward,"61252","25491644",pha-1,ATGAATAACTTGATGAACAT,C. elegans +cut,S. pyogenes,Kim,"","26479191",PHYB,CACTAGGAGCAACACCCAA,A. thaliana +cut,S. pyogenes,Wolfe,"69240","26480473",PLXNB2,GGGCCCAACCTAGGGCATGG,H. sapiens +cut,S. pyogenes,Patron,"68253","26616834",PM19,GCTCTCCACTCTGGGCTCTT,H. vulgare +cut,S. pyogenes,Patron,"68254","26616834",PM19,GGCTGGCGTTGGTCGTAACA,H. vulgare +cut,S. pyogenes,Shaw,"79004","26944679",Prkaa1,TTATTGTCACAGGCATATGG,M. musculus +cut,S. pyogenes,Shaw,"79005","26944679",Prkaa2,ACAGGCATATGGTTGTCCAT,M. musculus +cut,S. pyogenes,Schmitt-Ulms,"61857","25490046",Prnp,GGTGGAACACCGGTGGAAGC,M. musculus +cut,S. pyogenes,Schmitt-Ulms,"61856","25490046",Prnp,TTGGCCCCATCCACCGCCAT,M. musculus +cut,N. meningitidis,Church,"48651","24076762",Protospacer A,TACCATCTCAAGCTTGTTGA,Synthetic +cut,S. thermophilus,Church,"48653","24076762",Protospacer A,TACCATCTCAAGCTTGTTGA,Synthetic +cut,T. denticola,Church,"48655","24076762",Protospacer A,TACCATCTCAAGCTTGTTGA,Synthetic +cut,N. meningitidis,Church,"48652","24076762",Protospacer B,ACTTTAAAAGTATTCGCCAT,Synthetic +cut,S. thermophilus,Church,"48654","24076762",Protospacer B,ACTTTAAAAGTATTCGCCAT,Synthetic +cut,T. denticola,Church,"48656","24076762",Protospacer B,ACTTTAAAAGTATTCGCCAT,Synthetic +cut,S. pyogenes,Moffat,"74184","26627737",PSMB2,ATGTTCTTGTCGCCTCCGAC,H. sapiens +cut,S. pyogenes,Moffat,"74185","26627737",PSMB2,AATATTGTCCAGATGAAGGA,H. sapiens +cut,S. pyogenes,Moffat,"74180","26627737",PSMD1,TGTGCGCTACGGAGCTGCAA,H. sapiens +cut,S. pyogenes,Moffat,"74181","26627737",PSMD1,ACCAGAGCCACAATAAGCCA,H. sapiens +cut,S. pyogenes,Jacks,"59909","25119044",Pten,AGATCGTTAGCAGAAACAAA,M. musculus +cut,S. pyogenes,Xue,"66588","26018130",Pten,GCTGTAGTAATATCTGCTAT,M. musculus +cut,S. pyogenes,Xue,"66587","26018130",Pten,GTTTCATAGCGGCCACGAAGT,M. musculus +interfere,S. pyogenes,Lu,"74070","26829286",pyk,AGATTGTATGTACCCTAGGCCCAG,C. glutamicum +interfere,S. pyogenes,Lu,"74072","26829286",pyk,ATTCCATCTGCACTAGCCACCGCT,C. glutamicum +tag,S. pyogenes,Mendenhall,"64057","26355004",RAD21,CCAAGGTTCCATATTATATAAGG,H. sapiens +cut,S. pyogenes,Fire,"59927","25161212",rde-1(D718),TGCCATTAACTATGTATGT,C. elegans +cut,S. pyogenes,Fire,"59928","25161212",rde-1(D801),GATATTGTAGTCTATCGAGA,C. elegans +cut,S. pyogenes,Fire,"59929","25161212",rde-1(H974),GATAAATGAGCATAATGAAC,C. elegans +interfere,S. pyogenes,Lu,"74075","26829286",rfp,AAGTTCGTATGGAAGGTTCCGTTAA, +cut,S. pyogenes,Joung,"42246","23360964",rgs4,GGAGAAGGTGAAGGACACTG,D. rerio +cut,S. pyogenes,Bornhauser,"75165","27194728",RIP3,TACACGAGTGATGGTTCGGT,H. sapiens +cut,S. pyogenes,Bornhauser,"75163","27194728",RIPK1,GCTCTGCTGGGAAGCGAATC,H. sapiens +cut,S. pyogenes,Joung,"47509","23792628",RNF2,GTCATCTTAGTCATTACCTG,H. sapiens +cut,S. pyogenes,Fire,"59930","25161212",rol-6(su1006),GTGAGACGTCAACAATATGG,C. elegans +cut,S. pyogenes,Kuhn,"64216","25803306",Rosa26,ACTCCAGTCTTTCTAGAAGA,M.musculus +cut,S. pyogenes,Marraffini,"44505","23360965",rpsL,AAAAAACCGAACTCCGCGCTGCGTAAAGTA,E. coli +interfere,S. pyogenes,Voigt,"62285","25422271",scramble,AACCCCTGATTGTATCCGCA,synthetic +cut,S. pyogenes,Chen,"47930","23918387",slc24a5 (golden),GGTCTCTCGCAGGATGTTGC,D. rerio +cut,S. pyogenes,Hanna,"59725","25543152",SOX17,GCCCAGCCCGGCCATCACCG,H. sapiens +activate,S. pyogenes,Wolfe,"50925","24346702",Sox17,GCTCCGGCTAGTTTTCCCGG,H. sapiens +activate,S. pyogenes,Wolfe,"50924","24346702",Sox17,GGAGGGGCAAGGGGCGGGCG,H. sapiens +activate,S. pyogenes,Wolfe,"50926","24346702",Sox17,GGGCAAGTACGTCGATTCCA,H. sapiens +activate,S. pyogenes,Wolfe,"50923","24346702",Sox17,GGGCGTGGGCCTAACGACGC,H. sapiens +cut,S. pyogenes,Fire,"59935","25161212",sqt-1,GGAAGGACATAGTTGTCAT,C. elegans +cut,S. pyogenes,Fire,"60212","25161212",sqt-1,TGTGGAGTTGGGGTAGCGT,C. elegans +activate/interfere,S. pyogenes,Qi,"62338","25533786",sv40 promoter,CATACTTCTGCCTGCTGGGGAGCCTG,synthetic +scaffold,S. pyogenes,Qi & Lim,"62340","25533786",SV40.NT1,GAATAGCTCAGAGGCCGAGG,H. sapiens +cut,S. pyogenes,Seydoux,"66100","25249454",swan-2,ACAAATTGATATCCAATCA,C. elegans +cut,S. pyogenes,Seydoux,"66099","25249454",swan-2,TGAAGAAAGTTATACTCGA,C. elegans +cut,S. pyogenes,Hanna,"59726","25543152",T (BRACHYURY),CACGCGCAGTTCGCGCTCTG,H. sapiens +cut,S. pyogenes,"Guigo, Johnson","72627","26493208",TCRC,gRNA1:GGGGAGCGGGAAAGCGGTCG; gRNA2:AACTGACCTTCAGGCCCGTA,H. sapiens +cut,N. meningitidis,Thomson,"47869","23940360",tdtomato,CGAAATGAGAAAGGGAGCTACAAC,Synthetic +scaffold,S. pyogenes,Qi & Lim,"62320","25533786",TEF,TTGATATTTAAGTTAATAAA,S. cerevisiae +interfere,S. pyogenes,Weissman,"46922","23849981",TEF1,TTGATATTTAAGTTAATAAA,S. cerevisiae +visualize,S. pyogenes,Qi,"51024","24360272",telomeres,GTTAGGGTTAGGGTTAGGGTTA,H. sapiens +scaffold,S. pyogenes,Qi & Lim,"62313","25533786",TET,ACTTTTCTCTATCACTGATA,S. cerevisiae +interfere,S. pyogenes,Weissman,"46923","23849981",TET promoter,TATCAGTGATAGAGAAAAGT, +activate/interfere,S. pyogenes,Qi,"62327","25533786",Tet3G,GTACGTTCTCTATCACTGATA,synthetic +cut,S. pyogenes,Shaw,"79006","26944679",Tfeb,AGCACTGTTGCCGGCCGAGG,M. musculus +RNA targeting,S. pyogenes,Yeo,"74709","26997482",TFRC,GCACUGACCAGAUAAGAAUG,H. sapiens +cut,S. pyogenes,"Guigo, Johnson","72626","26493208",TFRC,"gRNA1:GCAGCCTCAGAAATACAAAA, gRNA2CGGGATATCGGGTGGCGGCT",H. sapiens +cut,S. pyogenes,Wolfe,"69239","26480473",TGM2,CCTGGACCCAACGCCCCAGG,H. sapiens +cut,S. pyogenes,Sibley,"59855","25480939",TGME49_290860,ATTGGTCTGACAGCGATGTG,T. gondii +cut,S. pyogenes,Joung,"42247","23360964",th,GGATGCGCGTAAGGAGCGCG,D. rerio +cut,S. pyogenes,Du,"65565","25849248",th,GGGTTGTTACACTCATAAAG,D. rerio +cut,S. pyogenes,Joung,"42248","23360964",tia1l,GGTATGTCGGGAACCTCTCC,D. rerio +cut,S. pyogenes,Joung,"42249","23360964",tph1a,GGGAAAACACAACCGCAGCC,D. rerio +scaffold,S. pyogenes,Qi & Lim,"62325","25533786",TRE3G,GTACGTTCTCTATCACTGATA,H. sapiens +cut,S. pyogenes,Jin,"64331","25281382",trp1,GTCAATTGTTCTCTTTCTAT,S. cerevisiae +cut,S. pyogenes,Jacks,"59910","25119044",Trp53,CCTCGAGCTCCCTCTGAGCC,M. musculus +cut,S. pyogenes,Wolfe,"69234","26480473",TS2,GACCCCCTCCACCCCGCCTC,H. sapiens +cut,S. pyogenes,Wolfe,"69235","26480473",TS3,GGTGAGTGAGTGTGTGCGTG,H. sapiens +cut,S. pyogenes,Wolfe,"69236","26480473",TS4,GAGTCCGAGCAGAAGAAGAA,H. sapiens +cut,S. pyogenes,Goldstein,"47550","23995389",ttTi5605 Mos1 insertion site,ATATCAGTCTGTTTCGTAA,C. elegans +cut,S. pyogenes,Chen,"46761","23918387",tyr,CCCCAGAAGTCCTCCAGTCC,D. rerio +cut,S. pyogenes,Chen,"64250","25855067",tyr,GGACTGGAGGACTTCTGGGG,D. rerio +cut,S. pyogenes,Mashimo,"60966","24967838",Tyr (albino),TTTCCAGGATTATGTAATAG,R. norvegicus +cut,S. pyogenes,Mashimo,"60967","24967838",Tyr (wild type),TTTCCAGGATTACGTAATAG,R. norvegicus +cut,S. pyogenes,"Guigo, Johnson","72628","26493208",UCA1,gRNA1:GGTTTCCTTTTAGATGACGG; gRNA2:TCTGAAAAGAGAGTCAGCGA,H. sapiens +cut,S. pyogenes,Fire,"59932","25161212",unc-109(n499),GGAACTCGTGTCAAAACAAC,C. elegans +cut,S. pyogenes,Calarco,"46169","23817069",unc-119,GAATTTTCTGAAATTAAAGA,C. elegans +cut,S. pyogenes,Mello,"58202","24879462",unc-22,GAACCCGTTGCCGAATACAC,C. elegans +cut,S. pyogenes,Fire,"59931","25161212",unc-58(e665),TCCACGCACATGGTCACTA,C. elegans +cut,S. pyogenes,Sibley,"54467","24825012",UPRT,GGCGTCTCGATTGTGAGAGC,Toxoplasma gondii +cut,S. pyogenes,Jin,"64330","25281382",ura3,GAGTAAAAAATTGTACTTGG,S. cerevisiae +cut,S. pyogenes,Ye,"61812","24424410",USP13,GCCGCCCGGCATGCCGAACA,H. sapiens +cut,S. pyogenes,Joung,"47506","23792628",VEGF,GACCCCCTCCACCCCGCCTC,H. sapiens +cut,S. pyogenes,Joung,"47505","23792628",VEGF,GGGTGGGGGGAGTTTGCTCC,H. sapiens +cut,S. pyogenes,Joung,"47507","23792628",VEGF,GGTGAGTGAGTGTGTGCGTG,H. sapiens +interfere,S. pyogenes,Voigt,"62286","25422271",VR,TGCGCTCGGTCGTTCGGCTG,synthetic +nick,S. pyogenes,Yang,"73228","27213844",xylR,CGAGTTAGACATAATAGTGA,C. beijerinckii +cut,S. pyogenes,Ward,"61250","25491644",Y61A9LA.1,GGATGGATGTGTAGTCAATT,C. elegans +cut,S. pyogenes,Liu,"49331","24326186",yellow,GGTTTTGGACACTGGAACCG,D. melanogaster diff --git a/BioScientist/agent_system/engines/v1_executor_backup/know_how/sgRNA_design_guide.md b/BioScientist/agent_system/engines/v1_executor_backup/know_how/sgRNA_design_guide.md new file mode 100644 index 0000000000000000000000000000000000000000..5bdd56b98db61b99f4226c46759b346de489e59c --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/know_how/sgRNA_design_guide.md @@ -0,0 +1,419 @@ +# sgRNA Design Guide: Three-Tiered Approach + +--- + +## Metadata + +**Short Description**: Comprehensive guide for finding or designing sgRNAs using validated sequences, CRISPick datasets, or de novo design tools. + +**Authors**: Biomni Team + +**Version**: 1.0 + +**Last Updated**: November 2025 + +**License**: CC BY 4.0 + +**Commercial Use**: ✅ Allowed + +## Citations and Acknowledgments + +### If you use validated sgRNAs from our database (Option 1): +- **Database Source**: Addgene (https://www.addgene.org) +- **Citation**: Always cite the original publication associated with each sgRNA using the PubMed ID provided in the database +- **Acknowledgment**: "Validated sgRNA sequences obtained from Addgene (https://www.addgene.org/crispr/reference/grna-sequence/)" + +### If you use CRISPick designs (Option 2): +- **Acknowledgment Statement**: "Guide designs provided by the CRISPick web tool of the GPP at the Broad Institute" +- **Citation for Cas9 designs (SpCas9, SaCas9)**: Sanson KR, et al. Optimized libraries for CRISPR-Cas9 genetic screens with multiple modalities. Nat Commun. 2018;9(1):5416. PMID: 30575746 +- **Citation for Cas12a designs (AsCas12a, enAsCas12a)**: DeWeirdt PC, et al. Optimization of AsCas12a for combinatorial genetic screens in human cells. Nat Biotechnol. 2021;39(1):94-104. PMID: 32661438 + - Note: This paper describes enAsCas12a optimization; specify which variant you used in your methods + +--- + +## Overview + +This guide provides a three-tiered approach to sgRNA design, prioritizing validated sequences before moving to computational predictions. Always start with Option 1 and proceed to subsequent options only if needed. + + + +## Option 1: Search Validated sgRNA Sequences (Recommended First) + +### 1.1 Search for Validated sgRNAs + +**IMPORTANT**: You MUST complete BOTH Method 1 AND Method 2 before proceeding to Option 2. Do not skip Method 2 even if Method 1 finds no results. + +#### Method 1: Search Our Database (Fastest) + +We maintain a curated database of 300+ validated sgRNA sequences from Addgene with experimental evidence. + +**Location**: `biomni/know_how/resource/addgene_grna_sequences.csv` + +**Search the database**: +```python +import pandas as pd + +# Load the database +df = pd.read_csv('addgene_grna_sequences.csv') + +# Search for your gene +gene_name = "TP53" +results = df[df['Target_Gene'].str.upper() == gene_name.upper()] + +# Filter by species and application +results_filtered = results[ + (results['Target_Species'] == 'H. sapiens') & + (results['Application'] == 'cut') # or 'activate', 'RNA targeting' +] + +# Display results with references +print(results_filtered[['Target_Gene', 'Target_Sequence', + 'Plasmid_ID', 'PubMed_ID', 'Depositor']]) +``` + +**Database columns**: +- `Target_Gene`: Gene symbol +- `Target_Species`: Organism (H. sapiens, M. musculus, etc.) +- `Target_Sequence`: 20bp sgRNA sequence (5' to 3') +- `Application`: cut (knockout), activate (CRISPRa), RNA targeting (CRISPRi) +- `Cas9_Species`: S. pyogenes, S. aureus, etc. +- `Plasmid_ID`: Addgene plasmid number +- `Plasmid_URL`: Direct link to plasmid page +- `PubMed_ID`: **Publication reference** (cite this in your work) +- `PubMed_URL`: Direct link to paper +- `Depositor`: Research lab that contributed the sequence + +#### Method 2: Advanced Web Search (REQUIRED - Do Not Skip) + +**CRITICAL**: Even if Method 1 found no results, you MUST perform this literature search before moving to Option 2. Many validated sgRNAs are published in literature but not in the Addgene database. + +Use `advanced_web_search_claude` from `biomni.tool.literature` to find validated sgRNAs from literature and databases: + +```python +from biomni.tool.literature import advanced_web_search_claude + +# Example usage +results = advanced_web_search_claude("sgRNA TP53 validated H. sapiens experimental") +``` + +**Search queries to try (use multiple):** +``` +"sgRNA" OR "guide RNA" "[GENE_NAME]" validated experimental +"CRISPR knockout" "[GENE_NAME]" sgRNA sequence validated +"[GENE_NAME]" sgRNA "cutting efficiency" OR "on-target" +"[GENE_NAME]" "guide sequence" CRISPR validated +``` + +**Example for TP53:** +``` +"sgRNA" "TP53" validated "H. sapiens" experimental +"CRISPR knockout" "TP53" guide sequence validated +``` + +**What to search for in results:** +- Published papers with validated sgRNA sequences +- Supplementary materials containing sgRNA sequences +- Other CRISPR databases (e.g., GenScript, Horizon Discovery) +- Laboratory protocols with specific sgRNA sequences + +**IMPORTANT**: Spend adequate time searching literature. Look through at least the first 10-15 search results and check supplementary materials of relevant papers. + +#### What to Do with Results: + +✅ **If you find matching sgRNAs (from either method):** +1. **Record the sgRNA sequence** (20bp target sequence) +2. **Note the reference**: + - From database: Use `PubMed_ID` to cite the original paper + - From web search: Record the publication DOI/PubMed ID +3. **Record validation details**: Cell line, cutting efficiency, any reported off-targets + + +**Example result format:** +``` +Gene: TP53 +sgRNA sequence: GAGGTTGTGAGGCGCTGCCC +Species: H. sapiens (human) +Application: Knockout (cut) +Reference: PubMed ID 24336569 (Ran et al., 2013) +Validation: Tested in HEK293T cells, 85% cutting efficiency +``` + +❌ **If no matches found in BOTH Method 1 AND Method 2:** +Only then proceed to **Option 2: Download CRISPick Dataset** + + + +## Option 2: Download Pre-Computed sgRNAs from CRISPick + +### When to Use This Option? +- No validated sgRNAs found in Addgene +- Need comprehensive coverage of a gene +- Want multiple sgRNA options with predicted scores +- Working with genome-scale screening + +### 2.1 Overview of CRISPick + +**CRISPick** (from Broad Institute GPP) provides pre-computed sgRNA designs for entire genomes with 238 available datasets covering: +- Human (GRCh38, GRCh37) +- Mouse (GRCm38, GRCm39) +- Dog, Cow, Monkey, and other model organisms +- Multiple Cas enzymes (SpCas9, SaCas9, AsCas12a, enAsCas12a) + - **IMPORTANT**: AsCas12a and enAsCas12a are DIFFERENT enzymes + - **AsCas12a**: Wild-type Acidaminococcus sp. Cas12a + - **enAsCas12a**: Enhanced variant with improved activity + - **Critical**: sgRNAs designed for enAsCas12a may NOT work with wild-type AsCas12a + - Always match the dataset to your specific Cas12a variant +- Different applications (knockout, activation, inhibition) + +### 2.2 Find the Download Link + +**All 238 download links are available in**: `biomni/know_how/resource/CRISPick_download_links.txt` + +#### Step 1: Understand File Naming Convention + +Files are named: `sgRNA_design_{TAXID}_{GENOME}_{CAS}_{APPLICATION}_{ALGORITHM}_{SOURCE}_{DATE}.txt.gz` + +**Common datasets:** + +| Organism | Genome | Cas9 | Application | Search Pattern | +|-|--||-|-| +| Human | GRCh38 | SpCas9 | Knockout | `9606_GRCh38_SpyoCas9_CRISPRko` | +| Human | GRCh38 | SpCas9 | Activation | `9606_GRCh38_SpyoCas9_CRISPRa` | +| Human | GRCh38 | SaCas9 | Knockout | `9606_GRCh38_SaurCas9_CRISPRko` | +| Mouse | GRCm38 | SpCas9 | Knockout | `10090_GRCm38_SpyoCas9_CRISPRko` | +| Mouse | GRCm38 | SpCas9 | Activation | `10090_GRCm38_SpyoCas9_CRISPRa` | + +**Key components:** +- **TAXID**: `9606` (Human), `10090` (Mouse), `9615` (Dog), `9913` (Cow) +- **CAS**: + - `SpyoCas9` (SpCas9, NGG PAM) + - `SaurCas9` (SaCas9, NNGRRT PAM) + - `AsCas12a` (Wild-type Cas12a, TTTV PAM) + - `enAsCas12a` (Enhanced Cas12a, TTTV PAM) + - **WARNING**: Do NOT use AsCas12a datasets if you have enAsCas12a, and vice versa +- **APPLICATION**: `CRISPRko` (knockout), `CRISPRa` (activation), `CRISPRi` (inhibition) + +#### Step 2: Find Your Download URL + +```bash +# Search the download links file +grep "9606_GRCh38_SpyoCas9_CRISPRko" biomni/know_how/resource/CRISPick_download_links.txt + +# Or for mouse +grep "10090_GRCm38_SpyoCas9_CRISPRko" biomni/know_how/resource/CRISPick_download_links.txt +``` + +#### Step 3: Download and Extract + +```bash +# Copy the URL from download_links.txt, then: +wget [PASTE_URL_HERE] + +# Extract the file +gunzip sgRNA_design_*.txt.gz +``` + +**File sizes**: Knockout (300-700 MB), Activation (50-100 MB), Summary files (1-3 MB) + +### 2.4 Understanding the File Format + +The `.txt` file is tab-delimited. Column names differ between knockout and activation/inhibition datasets. + +**Essential Columns (All files):** +- **sgRNA Sequence**: The 20bp guide RNA sequence (5' to 3') +- **Target Gene Symbol**: Gene name (e.g., "TP53", "BRCA1") +- **Combined Rank**: Overall ranking (lower = better) - **Use this by default** +- **On-Target Rank**: Ranking by efficiency only (lower = better) +- **Off-Target Rank**: Ranking by specificity only (lower = better) +- **PAM Sequence**: The PAM sequence (e.g., "AGG", "TGG") + +**Knockout-specific columns:** +- **sgRNA Cut Position (1-based)**: Genomic coordinate of cut site +- **Exon Number**: Which exon is targeted +- **Target Cut %**: Percentage of protein affected + +**Activation/Inhibition-specific columns:** +- **sgRNA 'Cut' Position**: Position relative to gene +- **sgRNA 'Cut' Site TSS Offset**: Distance from transcription start site (bp) +- **DHS Score**: DNase hypersensitivity score (for CRISPRa) + +### 2.5 Extract and Select sgRNAs + +#### Step 1: Load Data and Filter for Your Gene + +```python +import pandas as pd + +# Load the dataset +df = pd.read_csv('sgRNA_design_9606_GRCh38_SpyoCas9_CRISPRko_*.txt', + sep='\t', low_memory=False) + +# Filter for your gene +gene_name = "TP53" +gene_sgrnas = df[df['Target Gene Symbol'] == gene_name].copy() + +print(f"Found {len(gene_sgrnas)} sgRNAs for {gene_name}") +``` + +#### Step 2: Select Top sgRNAs + +**Default: Use Combined Rank (balances efficiency and specificity)** +```python +# Sort by Combined Rank (lower is better) +top_sgrnas = gene_sgrnas.nsmallest(10, 'Combined Rank') + +print(top_sgrnas[['sgRNA Sequence', 'Combined Rank', + 'Exon Number', 'sgRNA Cut Position (1-based)']]) +``` + +**Option A: Prioritize On-Target Efficiency** +```python +# Sort by On-Target Rank (for maximum cutting efficiency) +efficient_sgrnas = gene_sgrnas.nsmallest(10, 'On-Target Rank') +``` + +**Option B: Prioritize Off-Target Specificity** +```python +# Sort by Off-Target Rank (for maximum specificity) +specific_sgrnas = gene_sgrnas.nsmallest(10, 'Off-Target Rank') +``` + +#### Step 3: Filter by Custom Criteria (Optional) + +**Filter by Exon Number:** +```python +# Target specific exon (e.g., exon 5) +exon5_sgrnas = gene_sgrnas[gene_sgrnas['Exon Number'] == 5] +top_exon5 = exon5_sgrnas.nsmallest(5, 'Combined Rank') +``` + +**Filter by Genomic Position:** +```python +# Target specific genomic range +position_filtered = gene_sgrnas[ + (gene_sgrnas['sgRNA Cut Position (1-based)'] >= 7572000) & + (gene_sgrnas['sgRNA Cut Position (1-based)'] <= 7575000) +] +``` + +**Target Early Exons for Knockout:** +```python +# Get sgRNAs from first 3 exons +early_exons = gene_sgrnas[gene_sgrnas['Exon Number'] <= 3] +top_early = early_exons.nsmallest(10, 'Combined Rank') +``` + +**Filter by Target Cut Percentage:** +```python +# Target sgRNAs that affect significant portion of protein +high_impact = gene_sgrnas[gene_sgrnas['Target Cut %'] <= 50] # Cut in first 50% +top_high_impact = high_impact.nsmallest(10, 'Combined Rank') +``` + +#### Step 4: Select Multiple sgRNAs for Validation + +```python +# Get top 4 sgRNAs from different exons for redundancy +final_selection = gene_sgrnas.sort_values('Combined Rank').groupby('Exon Number').head(1).head(4) + +# Save results +final_selection.to_csv(f'{gene_name}_selected_sgRNAs.csv', index=False) + +print("\nSelected sgRNAs:") +print(final_selection[['sgRNA Sequence', 'Exon Number', 'Combined Rank']]) +``` + +### 2.6 What to Do with Results + +✅ **Once you have selected sgRNAs:** +1. Choose **3-4 sgRNAs** (use Combined_Rank by default) + +❌ **If dataset doesn't cover your gene or organism:** +Proceed to **Option 3: De Novo sgRNA Design** + + + +## Option 3: General sgRNA Design Guidelines (Last Resort) + +### When to Use This Option? +- Gene not covered in CRISPick datasets +- Non-model organism +- Custom design requirements + +### General Design Rules + +#### Essential Requirements: +1. **Length**: + - 20 bp for SpCas9 and SaCas9 + - 23-25 bp for Cas12a variants (AsCas12a, enAsCas12a) +2. **PAM sequence**: + - **SpCas9**: Requires **NGG** immediately after target (3' end) + - **SaCas9**: Requires **NNGRRT** immediately after target (3' end) + - **AsCas12a** (wild-type): Requires **TTTV** before target (5' end) + - **enAsCas12a** (enhanced): Requires **TTTV** before target (5' end) + - **CRITICAL**: Guides designed for enAsCas12a may not work with wild-type AsCas12a due to different activity profiles +3. **GC content**: 40-60% is optimal +4. **Avoid**: + - TTTT sequences (terminates transcription) + - Long runs of same nucleotide (>4 repeats) + +#### Target Location: +- **For knockout**: Target early exons (first 50% of gene) +- **For activation**: Target -200 to +1 bp from transcription start site (TSS) +- **For inhibition**: Target -50 to +300 bp from TSS + +#### Best Practices: +- **Test 3-4 different sgRNAs** per target gene +- Select sgRNAs with high efficiency scores (>0.5) and minimal off-targets +- Validate experimentally with Sanger sequencing + + + +## Quick Start Examples + +### Example 1: Knockout TP53 in Human Cells + +**Step 1**: Check Addgene +```python +df = pd.read_csv('addgene_grna_sequences.csv') +tp53_results = df[(df['Target_Gene'] == 'TP53') & + (df['Target_Species'] == 'H. sapiens') & + (df['Application'] == 'cut')] +# Result: Found 0 entries → Proceed to Option 2 +``` + +**Step 2**: Download CRISPick dataset +```bash +# Download human GRCh38 SpCas9 knockout dataset +wget https://portals.broadinstitute.org/gppx/public/sgrna_design/api/downloads/\ +sgRNA_design_9606_GRCh38_SpyoCas9_CRISPRko_RS3seq-Chen2013+RS3target_NCBI_20241104.txt.gz + +gunzip sgRNA_design_9606_GRCh38_SpyoCas9_CRISPRko_*.txt.gz +``` + +**Step 3**: Extract TP53 sgRNAs +```python +df = pd.read_csv('sgRNA_design_9606_GRCh38_SpyoCas9_CRISPRko_*.txt', sep='\t') +tp53 = df[df['Gene_Symbol'] == 'TP53'] +top_sgrnas = tp53[ + (tp53['sgRNA_score'] > 0.6) & + (tp53['Off_target_stringency'] > 0.5) +].sort_values('sgRNA_score', ascending=False).head(4) + +print(top_sgrnas[['sgRNA_sequence', 'sgRNA_score', 'Exon_ID']]) +``` + +### Example 2: Activate OCT4 in Human iPSCs + +**Step 1**: Check Addgene +```python +oct4_results = df[(df['Target_Gene'] == 'OCT4') & + (df['Application'] == 'activate')] +# Found 1 validated sgRNA! +print(oct4_results['Target_Sequence'].values[0]) +# Use this sequence ✅ +``` + + + +**Remember**: Always start with validated sequences (Option 1), then move to pre-computed designs (Option 2), and only use de novo design (Option 3) when necessary. Testing 3-4 sgRNAs per gene is standard practice regardless of prediction scores. diff --git a/BioScientist/agent_system/engines/v1_executor_backup/know_how/single_cell_annotation.md b/BioScientist/agent_system/engines/v1_executor_backup/know_how/single_cell_annotation.md new file mode 100644 index 0000000000000000000000000000000000000000..3ac3c31796441f1444455258c3ec29376984d193 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/know_how/single_cell_annotation.md @@ -0,0 +1,223 @@ +# Single Cell RNA-seq Cell Type Annotation + +--- + +## Metadata + +**Short Description**: Best practices for annotating cell types in single-cell RNA-seq data using marker-based, automated, and reference-based approaches. + +**Authors**: Distilled from "Single-cell best practices" by Luecken, M.D. et al. + +**Affiliations**: Helmholtz Munich, Wellcome Sanger Institute, Harvard Medical School, and contributors + +**Version**: 1.0 + +**Last Updated**: January 2025 + +**License**: CC BY 4.0 + +**Commercial Use**: ✅ Allowed + +**Source**: https://www.sc-best-practices.org/cellular_structure/annotation.html + +**Citation**: Luecken, M.D., Theis, F.J. et al. (2023). Current best practices in single-cell RNA-seq analysis: a tutorial. Molecular Systems Biology. + +--- + +## Overview + +Cell type annotation is the process of assigning cell type labels to clusters or individual cells in single-cell RNA-seq data. This guide covers three main approaches and their practical implementation. + +## Three Annotation Approaches + +### 1. Manual Marker-Based Annotation +Identify cell types by examining expression of known marker genes in each cluster. + +**Tools**: Scanpy, Seurat +**Best for**: Small datasets, novel cell types, high confidence needs + +### 2. Automated Annotation +Use pre-trained classifiers to automatically assign cell type labels. + +**Tools**: CellTypist, scAnnotate +**Best for**: Standard tissues, quick preliminary annotation, large datasets + +### 3. Reference-Based Label Transfer +Transfer labels from annotated reference datasets to your query data. + +**Tools**: scArches, scANVI, Azimuth, SingleR +**Best for**: Well-characterized tissues, integration with public data + +## Recommended Workflow + +### Step 1: Quality Control First +- **Remove low-quality cells before annotation** +- Filter doublets (expected doublet rate: 0.8% per 1000 cells) +- Check for ambient RNA contamination +- Verify cluster quality and resolution + +### Step 2: Initial Marker-Based Assessment + +```python +# Scanpy example +import scanpy as sc + +# Calculate marker genes for clusters +sc.tl.rank_genes_groups(adata, 'leiden', method='wilcoxon') + +# Visualize top markers +sc.pl.rank_genes_groups(adata, n_genes=25, sharey=False) + +# Plot known markers +markers = { + 'T cells': ['CD3D', 'CD3E', 'CD4', 'CD8A'], + 'B cells': ['CD19', 'MS4A1', 'CD79A'], + 'Monocytes': ['CD14', 'FCGR3A', 'LYZ'], + 'NK cells': ['NCAM1', 'NKG7', 'GNLY'] +} + +sc.pl.dotplot(adata, markers, groupby='leiden') +``` + +### Step 3: Use Automated Tools for Validation + +```python +# CellTypist example (fast, accurate for immune cells) +import celltypist +from celltypist import models + +# Download immune cell model +model = models.Model.load(model='Immune_All_Low.pkl') + +# Predict cell types +predictions = celltypist.annotate(adata, model=model, majority_voting=True) +adata = predictions.to_adata() +``` + +### Step 4: Reference-Based Refinement + +```python +# scArches example for label transfer +import scarches as sca + +# Load pre-trained reference model +model = sca.models.SCANVI.load_query_data( + adata=adata, # Your query data + reference_model="path/to/reference_model" +) + +# Transfer labels +model.train(max_epochs=100) +adata.obs['transferred_labels'] = model.predict() +``` + +## Best Practices + +### Do's: +1. **Always combine multiple approaches** - Use marker-based validation even with automated tools +2. **Check cluster purity** - Ensure clusters represent single cell types +3. **Validate with multiple marker sets** - Don't rely on single markers +4. **Consider biological context** - Tissue type, disease state, developmental stage +5. **Document confidence levels** - Note uncertain annotations +6. **Use hierarchical annotation** - Broad categories first, then subtypes + +### Don'ts: +1. **Don't over-cluster** - Too fine resolution creates artificial distinctions +2. **Don't ignore batch effects** - Correct before annotation +3. **Don't trust automation blindly** - Always validate predictions +4. **Don't mix cell states with cell types** - Activated vs. resting cells are states, not types +5. **Don't annotate low-quality cells** - Remove them first + +## Common Pitfalls + +### 1. Doublet Clusters +**Problem**: Clusters with markers from multiple cell types +**Solution**: Use doublet detection tools (Scrublet, DoubletFinder) before annotation + +### 2. Ambient RNA +**Problem**: Background markers in all cells +**Solution**: Use SoupX or CellBender for decontamination + +### 3. Over-interpretation of Small Clusters +**Problem**: Rare clusters may be technical artifacts +**Solution**: Require minimum cell count (e.g., >25 cells), validate with independent data + +### 4. Reference Mismatch +**Problem**: Reference from different tissue/species/condition +**Solution**: Use tissue-matched references, check marker overlap before transfer + +## Tool Selection Guide + +| Scenario | Recommended Tool | Why | +|----------|------------------|-----| +| Immune cells (human) | CellTypist | Pre-trained on large immune atlases | +| Mouse tissues | scArches + Mouse Cell Atlas | Comprehensive mouse reference | +| Novel cell types | Manual + Scanpy/Seurat | Need domain expertise | +| Large datasets (>100k cells) | CellTypist | Fast, scalable | +| Cross-species | Manual markers | Limited reference transfer | +| Developmental data | scArches | Handles continuous states | + +## Key Marker Genes by Cell Type + +### Blood/Immune: +- **T cells**: CD3D, CD3E (all T cells); CD4, CD8A (subtypes) +- **B cells**: CD19, MS4A1 (CD20), CD79A +- **Monocytes/Macrophages**: CD14, CD68, LYZ +- **NK cells**: NCAM1 (CD56), NKG7, KLRD1 +- **Dendritic cells**: FCER1A, CD1C + +### Epithelial: +- **General epithelial**: EPCAM, KRT18, KRT19 +- **Lung AT1**: AGER, PDPN +- **Lung AT2**: SFTPC, SFTPA1 +- **Intestinal**: VIL1, MUC2 + +### Stromal: +- **Fibroblasts**: COL1A1, DCN, LUM +- **Endothelial**: PECAM1 (CD31), VWF, CDH5 +- **Smooth muscle**: ACTA2, MYH11, TAGLN + +## Validation Checklist + +- [ ] Cluster purity: >80% cells with same label per cluster +- [ ] Marker consistency: Top DE genes match expected markers +- [ ] Biological plausibility: Expected proportions for tissue type +- [ ] Cross-method agreement: Manual and automated annotations align +- [ ] Reference quality: >70% cells successfully transferred +- [ ] Doublet check: No clusters with multi-lineage markers +- [ ] Documentation: Record confidence levels and uncertain calls + +## Resources + +### Tools: +- **Scanpy**: https://scanpy.readthedocs.io/ +- **CellTypist**: https://www.celltypist.org/ +- **scArches**: https://scarches.readthedocs.io/ +- **Seurat**: https://satijalab.org/seurat/ + +### References: +- **PanglaoDB**: Database of marker genes +- **CellMarker**: Curated cell marker database +- **Human Cell Atlas**: Reference datasets + +### Pre-trained Models: +- **CellTypist models**: 30+ tissue-specific models +- **Azimuth references**: PBMC, lung, kidney, etc. +- **scArches models**: Multiple tissue references + +## Troubleshooting + +**Issue**: All clusters look similar +→ Increase clustering resolution, check if data is normalized + +**Issue**: Too many small clusters +→ Decrease resolution, merge similar clusters based on markers + +**Issue**: Automated tool gives inconsistent results +→ Check input normalization, try multiple tools, fall back to manual + +**Issue**: Can't find clear markers for cluster +→ May be transitional state, doublet, or low-quality cells + +**Issue**: Reference transfer fails +→ Check batch correction, ensure overlapping gene sets, verify tissue match diff --git a/BioScientist/agent_system/engines/v1_executor_backup/model/__init__.py b/BioScientist/agent_system/engines/v1_executor_backup/model/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/BioScientist/agent_system/engines/v1_executor_backup/model/__pycache__/__init__.cpython-311.pyc b/BioScientist/agent_system/engines/v1_executor_backup/model/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8d7632c66b88c0873399b180a9a9baa2c21acc99 Binary files /dev/null and b/BioScientist/agent_system/engines/v1_executor_backup/model/__pycache__/__init__.cpython-311.pyc differ diff --git a/BioScientist/agent_system/engines/v1_executor_backup/model/__pycache__/retriever.cpython-311.pyc b/BioScientist/agent_system/engines/v1_executor_backup/model/__pycache__/retriever.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8d2978e2ee67cc03d0d91ec277e3a1701002df05 Binary files /dev/null and b/BioScientist/agent_system/engines/v1_executor_backup/model/__pycache__/retriever.cpython-311.pyc differ diff --git a/BioScientist/agent_system/engines/v1_executor_backup/model/retriever.py b/BioScientist/agent_system/engines/v1_executor_backup/model/retriever.py new file mode 100644 index 0000000000000000000000000000000000000000..1d5fbc0b90c9a48871a3f94b1cda5404b14c6056 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/model/retriever.py @@ -0,0 +1,203 @@ +import contextlib +import re + +from langchain_core.messages import HumanMessage +from langchain_openai import ChatOpenAI + + +class ToolRetriever: + """Retrieve tools from the tool registry.""" + + def __init__(self): + pass + + def prompt_based_retrieval(self, query: str, resources: dict, llm=None) -> dict: + """Use a prompt-based approach to retrieve the most relevant resources for a query. + + Args: + query: The user's query + resources: A dictionary with keys 'tools', 'data_lake', 'libraries', and 'know_how', + each containing a list of available resources + llm: Optional LLM instance to use for retrieval (if None, will create a new one) + + Returns: + A dictionary with the same keys, but containing only the most relevant resources + + """ + # Build prompt sections for available resources + prompt_sections = [] + prompt_sections.append(f""" +You are an expert biomedical research assistant. Your task is to select the relevant resources to help answer a user's query. + +USER QUERY: {query} + +Below are the available resources. For each category, select items that are directly or indirectly relevant to answering the query. +Be generous in your selection - include resources that might be useful for the task, even if they're not explicitly mentioned in the query. +It's better to include slightly more resources than to miss potentially useful ones. + +AVAILABLE TOOLS: +{self._format_resources_for_prompt(resources.get("tools", []))} + +AVAILABLE DATA LAKE ITEMS: +{self._format_resources_for_prompt(resources.get("data_lake", []))} + +AVAILABLE SOFTWARE LIBRARIES: +{self._format_resources_for_prompt(resources.get("libraries", []))}""") + + # Add know-how section if available + if "know_how" in resources and resources["know_how"]: + prompt_sections.append(f""" +AVAILABLE KNOW-HOW DOCUMENTS (Best Practices & Protocols): +{self._format_resources_for_prompt(resources.get("know_how", []))}""") + + # Build response format based on available categories + response_format = """ +For each category, respond with ONLY the indices of the relevant items in the following format: +TOOLS: [list of indices] +DATA_LAKE: [list of indices] +LIBRARIES: [list of indices]""" + + if "know_how" in resources and resources["know_how"]: + response_format += "\nKNOW_HOW: [list of indices]" + + response_format += """ + +For example: +TOOLS: [0, 3, 5, 7, 9] +DATA_LAKE: [1, 2, 4] +LIBRARIES: [0, 2, 4, 5, 8]""" + + if "know_how" in resources and resources["know_how"]: + response_format += "\nKNOW_HOW: [0, 1]" + + response_format += """ + +If a category has no relevant items, use an empty list, e.g., DATA_LAKE: [] + +IMPORTANT GUIDELINES: +1. Be generous but not excessive - aim to include all potentially relevant resources +2. ALWAYS prioritize database tools for general queries - include as many database tools as possible +3. Include all literature search tools +4. For wet lab sequence type of queries, ALWAYS include molecular biology tools +5. For data lake items, include datasets that could provide useful information +6. For libraries, include those that provide functions needed for analysis +7. For know-how documents, include those that provide relevant protocols, best practices, or troubleshooting guidance +8. Don't exclude resources just because they're not explicitly mentioned in the query +9. When in doubt about a database tool or molecular biology tool, include it rather than exclude it +""" + + prompt = "\n".join(prompt_sections) + response_format + + # Use the provided LLM or create a new one + if llm is None: + llm = ChatOpenAI(model="gpt-4o") + + # Invoke the LLM + if hasattr(llm, "invoke"): + # For LangChain-style LLMs + response = llm.invoke([HumanMessage(content=prompt)]) + response_content = response.content + else: + # For other LLM interfaces + response_content = str(llm(prompt)) + + # Parse the response to extract the selected indices + selected_indices = self._parse_llm_response(response_content) + + # Get the selected resources + selected_resources = { + "tools": [ + resources["tools"][i] for i in selected_indices.get("tools", []) if i < len(resources.get("tools", [])) + ], + "data_lake": [ + resources["data_lake"][i] + for i in selected_indices.get("data_lake", []) + if i < len(resources.get("data_lake", [])) + ], + "libraries": [ + resources["libraries"][i] + for i in selected_indices.get("libraries", []) + if i < len(resources.get("libraries", [])) + ], + } + + # Add know-how if present + if "know_how" in resources and resources["know_how"]: + selected_resources["know_how"] = [ + resources["know_how"][i] + for i in selected_indices.get("know_how", []) + if i < len(resources.get("know_how", [])) + ] + + return selected_resources + + def _format_resources_for_prompt(self, resources: list) -> str: + """Format resources for inclusion in the prompt.""" + formatted = [] + for i, resource in enumerate(resources): + if isinstance(resource, dict): + # Handle dictionary format (from tool registry or data lake/libraries with descriptions) + name = resource.get("name", f"Resource {i}") + description = resource.get("description", "") + formatted.append(f"{i}. {name}: {description}") + elif isinstance(resource, str): + # Handle string format (simple strings) + formatted.append(f"{i}. {resource}") + else: + # Try to extract name and description from tool objects + name = getattr(resource, "name", str(resource)) + desc = getattr(resource, "description", "") + formatted.append(f"{i}. {name}: {desc}") + + return "\n".join(formatted) if formatted else "None available" + + def _parse_llm_response(self, response) -> dict: + """Parse the LLM response to extract the selected indices. + + Accepts either a plain string or a Responses API-style list of content blocks. + """ + # Normalize response to string if it's a list of content blocks (Responses API) + if isinstance(response, list): + parts = [] + for item in response: + # LangChain Responses API returns list of dicts like {"type": "text", "text": "..."} + if isinstance(item, dict): + if item.get("type") == "text" and "text" in item: + parts.append(str(item.get("text", ""))) + # If it's a tool_call or other block, ignore for this simple parsing + elif isinstance(item, str): + parts.append(item) + response = "\n".join([p for p in parts if p]) + elif not isinstance(response, str): + response = str(response) + selected_indices = {"tools": [], "data_lake": [], "libraries": [], "know_how": []} + + # Extract indices for each category + tools_match = re.search(r"TOOLS:\s*\[(.*?)\]", response, re.IGNORECASE) + if tools_match and tools_match.group(1).strip(): + with contextlib.suppress(ValueError): + selected_indices["tools"] = [int(idx.strip()) for idx in tools_match.group(1).split(",") if idx.strip()] + + data_lake_match = re.search(r"DATA_LAKE:\s*\[(.*?)\]", response, re.IGNORECASE) + if data_lake_match and data_lake_match.group(1).strip(): + with contextlib.suppress(ValueError): + selected_indices["data_lake"] = [ + int(idx.strip()) for idx in data_lake_match.group(1).split(",") if idx.strip() + ] + + libraries_match = re.search(r"LIBRARIES:\s*\[(.*?)\]", response, re.IGNORECASE) + if libraries_match and libraries_match.group(1).strip(): + with contextlib.suppress(ValueError): + selected_indices["libraries"] = [ + int(idx.strip()) for idx in libraries_match.group(1).split(",") if idx.strip() + ] + + # Extract know-how indices + know_how_match = re.search(r"KNOW[-_]HOW:\s*\[(.*?)\]", response, re.IGNORECASE) + if know_how_match and know_how_match.group(1).strip(): + with contextlib.suppress(ValueError): + selected_indices["know_how"] = [ + int(idx.strip()) for idx in know_how_match.group(1).split(",") if idx.strip() + ] + + return selected_indices diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/__pycache__/__init__.cpython-311.pyc b/BioScientist/agent_system/engines/v1_executor_backup/tool/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..06109761d505da9dc9c00f803bb97d5977bb4b02 Binary files /dev/null and b/BioScientist/agent_system/engines/v1_executor_backup/tool/__pycache__/__init__.cpython-311.pyc differ diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/__pycache__/literature.cpython-311.pyc b/BioScientist/agent_system/engines/v1_executor_backup/tool/__pycache__/literature.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a8211f847b91521c7abd572c9e8226638106ce30 Binary files /dev/null and b/BioScientist/agent_system/engines/v1_executor_backup/tool/__pycache__/literature.cpython-311.pyc differ diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/__pycache__/molecular_biology.cpython-311.pyc b/BioScientist/agent_system/engines/v1_executor_backup/tool/__pycache__/molecular_biology.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cfde4e26e863d958179df0c0322856a7b5a11f2a Binary files /dev/null and b/BioScientist/agent_system/engines/v1_executor_backup/tool/__pycache__/molecular_biology.cpython-311.pyc differ diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/__pycache__/protocols.cpython-311.pyc b/BioScientist/agent_system/engines/v1_executor_backup/tool/__pycache__/protocols.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..986c64c61e1bb58281a3841075d4b58b64441543 Binary files /dev/null and b/BioScientist/agent_system/engines/v1_executor_backup/tool/__pycache__/protocols.cpython-311.pyc differ diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/__pycache__/support_tools.cpython-311.pyc b/BioScientist/agent_system/engines/v1_executor_backup/tool/__pycache__/support_tools.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ea98b0d57d8141c2f7b8459bf38503fe8fb73552 Binary files /dev/null and b/BioScientist/agent_system/engines/v1_executor_backup/tool/__pycache__/support_tools.cpython-311.pyc differ diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/__pycache__/tool_registry.cpython-311.pyc b/BioScientist/agent_system/engines/v1_executor_backup/tool/__pycache__/tool_registry.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..68525b4303fb8264cb9d9a0a9fefcbe0004a0b1d Binary files /dev/null and b/BioScientist/agent_system/engines/v1_executor_backup/tool/__pycache__/tool_registry.cpython-311.pyc differ diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/bioengineering.py b/BioScientist/agent_system/engines/v1_executor_backup/tool/bioengineering.py new file mode 100644 index 0000000000000000000000000000000000000000..e2263ca12ae822cd18953ed53c14447a3e6c75ea --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/bioengineering.py @@ -0,0 +1,1387 @@ +def analyze_cell_migration_metrics( + image_sequence_path, + pixel_size_um=1.0, + time_interval_min=1.0, + min_track_length=10, + output_dir="./", +): + """Analyze cell migration metrics from time-lapse microscopy images. + + Parameters + ---------- + image_sequence_path : str + Path to the directory containing time-lapse images or path to a multi-frame TIFF file + pixel_size_um : float + Conversion factor from pixels to micrometers (default: 1.0) + time_interval_min : float + Time interval between consecutive frames in minutes (default: 1.0) + min_track_length : int + Minimum number of frames a cell must be tracked to be included in analysis (default: 10) + output_dir : str + Directory to save output files (default: "./") + + Returns + ------- + str + Research log summarizing the cell migration analysis process and results + + """ + import os + + import matplotlib.pyplot as plt + import numpy as np + import pandas as pd + import trackpy as tp + from skimage import io + + # Create output directory if it doesn't exist + os.makedirs(output_dir, exist_ok=True) + + # Load image sequence + if os.path.isdir(image_sequence_path): + # Load from directory of images + image_files = sorted( + [f for f in os.listdir(image_sequence_path) if f.endswith((".tif", ".tiff", ".png", ".jpg", ".jpeg"))] + ) + frames = [io.imread(os.path.join(image_sequence_path, f)) for f in image_files] + else: + # Load multi-frame TIFF + frames = io.imread(image_sequence_path) + if frames.ndim == 3: # Check if it's a time series + pass + else: + return "Error: Input is not a valid time-lapse image sequence" + + # Step 1: Detect cells in each frame + features_list = [] + for i, frame in enumerate(frames): + # Detect cells (particles) in the frame + features = tp.locate(frame, diameter=15, minmass=100) + if features is not None and not features.empty: + features["frame"] = i + features_list.append(features) + + if not features_list: + return "Error: No cells detected in the image sequence" + + # Combine all features + all_features = pd.concat(features_list) + + # Save raw detections to output directory + raw_detections_file = os.path.join(output_dir, "raw_cell_detections.csv") + all_features.to_csv(raw_detections_file, index=False) + + # Step 2: Link features into cell trajectories + trajectories = tp.link_df(all_features, search_range=10, memory=3) + + # Save linked trajectories before filtering + # Reset index to ensure frame is a column, not an index level + trajectories_reset = trajectories.reset_index(drop=True) + all_trajectories_file = os.path.join(output_dir, "all_trajectories.csv") + trajectories_reset.to_csv(all_trajectories_file, index=False) + + # Step 3: Filter trajectories to get only the ones that appear in enough frames + trajectories = tp.filter_stubs(trajectories, threshold=min_track_length) + + if trajectories.empty: + return "No complete cell tracks found. Try adjusting parameters." + + # Save filtered trajectories + filtered_trajectories_file = os.path.join(output_dir, "filtered_trajectories.csv") + # Reset index again to be safe + trajectories = trajectories.reset_index(drop=True) + trajectories.to_csv(filtered_trajectories_file, index=False) + + # Step 4: Calculate migration metrics for each cell + cell_ids = trajectories["particle"].unique() + metrics = [] + + for cell_id in cell_ids: + cell_track = trajectories[trajectories["particle"] == cell_id].sort_values("frame") + + # Convert pixel positions to micrometers + cell_track["x_um"] = cell_track["x"] * pixel_size_um + cell_track["y_um"] = cell_track["y"] * pixel_size_um + + # Calculate displacements between consecutive frames + dx = np.diff(cell_track["x_um"]) + dy = np.diff(cell_track["y_um"]) + + # Calculate step distances + step_distances = np.sqrt(dx**2 + dy**2) + + # Calculate total path length + path_length = np.sum(step_distances) + + # Calculate net displacement (straight-line distance from start to end) + start_x, start_y = cell_track.iloc[0][["x_um", "y_um"]] + end_x, end_y = cell_track.iloc[-1][["x_um", "y_um"]] + net_displacement = np.sqrt((end_x - start_x) ** 2 + (end_y - start_y) ** 2) + + # Calculate directionality ratio (net displacement / path length) + directionality = net_displacement / path_length if path_length > 0 else 0 + + # Calculate speed (μm/min) + time_tracked = (cell_track["frame"].max() - cell_track["frame"].min()) * time_interval_min + speed = path_length / time_tracked if time_tracked > 0 else 0 + + metrics.append( + { + "cell_id": cell_id, + "frames_tracked": len(cell_track), + "speed_um_per_min": speed, + "directionality": directionality, + "displacement_um": net_displacement, + "path_length_um": path_length, + } + ) + + # Convert metrics to DataFrame + metrics_df = pd.DataFrame(metrics) + + # Save metrics to CSV + metrics_file = os.path.join(output_dir, "cell_migration_metrics.csv") + metrics_df.to_csv(metrics_file, index=False) + + # Calculate summary statistics + summary = { + "num_cells_tracked": len(metrics_df), + "avg_speed": metrics_df["speed_um_per_min"].mean(), + "std_speed": metrics_df["speed_um_per_min"].std(), + "avg_directionality": metrics_df["directionality"].mean(), + "std_directionality": metrics_df["directionality"].std(), + "avg_displacement": metrics_df["displacement_um"].mean(), + "std_displacement": metrics_df["displacement_um"].std(), + } + + # Save summary statistics + summary_file = os.path.join(output_dir, "migration_summary.csv") + pd.DataFrame([summary]).to_csv(summary_file, index=False) + + # Save trajectories visualization + fig, ax = plt.figure(figsize=(8, 8)), plt.gca() + tp.plot_traj(trajectories, ax=ax) + plt.title("Cell Migration Trajectories") + plt.xlabel("x position (pixels)") + plt.ylabel("y position (pixels)") + + trajectories_file = os.path.join(output_dir, "cell_trajectories.png") + plt.savefig(trajectories_file) + plt.close() + + # Create a rose plot to show migration directionality + fig, ax = plt.subplots(subplot_kw={"projection": "polar"}, figsize=(8, 8)) + + # Calculate angles for each cell (end position relative to start) + angles = [] + for cell_id in cell_ids: + cell_track = trajectories[trajectories["particle"] == cell_id].sort_values("frame") + start_x, start_y = cell_track.iloc[0][["x", "y"]] + end_x, end_y = cell_track.iloc[-1][["x", "y"]] + dx, dy = end_x - start_x, end_y - start_y + angle = np.arctan2(dy, dx) + angles.append(angle) + + # Plot the histogram + bins = np.linspace(-np.pi, np.pi, 16) + ax.hist(angles, bins=bins) + ax.set_title("Cell Migration Directionality") + + # Save the rose plot + rose_plot_file = os.path.join(output_dir, "rose_plot.png") + plt.savefig(rose_plot_file) + plt.close() + + # Create a displacement plot + plt.figure(figsize=(10, 6)) + plt.bar(range(len(metrics_df)), metrics_df["displacement_um"]) + plt.xlabel("Cell ID") + plt.ylabel("Displacement (μm)") + plt.title("Cell Displacements") + + # Save the displacement plot + displacement_plot_file = os.path.join(output_dir, "track_displacement_plot.png") + plt.savefig(displacement_plot_file) + plt.close() + + # Generate research log + log = f""" +Cell Migration Analysis Research Log: + +1. Analyzed time-lapse sequence with {len(frames)} frames +2. Detected and tracked {len(cell_ids)} cells that persisted for at least {min_track_length} frames +3. Calculated key migration metrics: + - Average speed: {summary["avg_speed"]:.2f} ± {summary["std_speed"]:.2f} μm/min + - Average directionality ratio: {summary["avg_directionality"]:.2f} ± {summary["std_directionality"]:.2f} + - Average displacement: {summary["avg_displacement"]:.2f} ± {summary["std_displacement"]:.2f} μm + +4. Files saved: + - Raw cell detections: {raw_detections_file} + - All cell trajectories: {all_trajectories_file} + - Filtered trajectories: {filtered_trajectories_file} + - Detailed cell metrics: {metrics_file} + - Summary statistics: {summary_file} + - Cell trajectories visualization: {trajectories_file} + - Direction rose plot: {rose_plot_file} + - Cell displacement plot: {displacement_plot_file} + +Note: Analysis used pixel size of {pixel_size_um} μm and time interval of {time_interval_min} min between frames. + """ + + return log.strip() + + +def perform_crispr_cas9_genome_editing(guide_rna_sequences, target_genomic_loci, cell_tissue_type): + """Simulates CRISPR-Cas9 genome editing process including guide RNA design, delivery, and analysis. + + Parameters + ---------- + guide_rna_sequences : list of str + List of guide RNA sequences (20 nucleotides each) targeting the genomic region of interest + + target_genomic_loci : str + Target genomic sequence to be edited (should be longer than guide RNA and contain the target sites) + + cell_tissue_type : str + Type of cell or tissue being edited (affects delivery efficiency and editing outcomes) + + Returns + ------- + str + Research log detailing the CRISPR-Cas9 editing process, including steps taken and results + + """ + import os + import random + from datetime import datetime + + # Initialize research log + log = "CRISPR-Cas9 Genome Editing Research Log\n" + log += f"Date: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n" + log += f"Cell/Tissue Type: {cell_tissue_type}\n\n" + + # Step 1: Validate guide RNA sequences + log += "STEP 1: Guide RNA Validation\n" + valid_guides = [] + + for i, guide in enumerate(guide_rna_sequences): + if len(guide) != 20: + log += f" Guide {i + 1}: INVALID - Guide RNA must be 20 nucleotides (current length: {len(guide)})\n" + continue + + if not all(n in "ATGC" for n in guide.upper()): + log += f" Guide {i + 1}: INVALID - Guide RNA contains invalid nucleotides\n" + continue + + # Calculate GC content (affects guide efficiency) + gc_content = (guide.upper().count("G") + guide.upper().count("C")) / len(guide) * 100 + efficiency_score = 0 + + if 40 <= gc_content <= 60: + efficiency_score += 1 + gc_quality = "Optimal" + else: + gc_quality = "Suboptimal" + + log += f" Guide {i + 1}: VALID - {guide} (GC content: {gc_content:.1f}% - {gc_quality})\n" + valid_guides.append((guide, efficiency_score)) + + if not valid_guides: + log += "\nNo valid guide RNAs found. Genome editing cannot proceed.\n" + return log + + # Step 2: Target site identification + log += "\nSTEP 2: Target Site Identification\n" + + target_seq = target_genomic_loci.upper() + target_matches = [] + + for i, (guide, score) in enumerate(valid_guides): + # Find guide RNA target in genomic sequence (including PAM site NGG) + guide.upper() + "NGG" + + # Check if guide sequence is in target (simplified) + if guide.upper() in target_seq: + position = target_seq.find(guide.upper()) + # Check if there's a PAM sequence (NGG) after the guide + if position + len(guide) + 2 <= len(target_seq): + potential_pam = target_seq[position + len(guide) : position + len(guide) + 3] + if potential_pam[1:3] == "GG": + pam_quality = "Found" + score += 2 + else: + pam_quality = "Not found" + else: + pam_quality = "Out of bounds" + + log += f" Guide {i + 1}: Found at position {position} (PAM: {pam_quality})\n" + target_matches.append((guide, position, score)) + else: + log += f" Guide {i + 1}: No match found in target sequence\n" + + if not target_matches: + log += "\nNo matching target sites found. Genome editing cannot proceed.\n" + return log + + # Step 3: Simulate CRISPR-Cas9 delivery + log += "\nSTEP 3: CRISPR-Cas9 Delivery Simulation\n" + + # Cell-specific delivery efficiencies (simplified model) + delivery_efficiencies = { + "hek293": 0.85, + "hela": 0.75, + "ipsc": 0.60, + "primary_neuron": 0.40, + "hematopoietic_stem_cell": 0.55, + "mouse_embryo": 0.70, + "plant_cell": 0.30, + } + + # Get delivery efficiency based on cell type (default to 0.5 if unknown) + cell_type_key = cell_tissue_type.lower().replace(" ", "_") + delivery_efficiency = delivery_efficiencies.get(cell_type_key, 0.5) + + log += f" Delivery method: Lipofection for {cell_tissue_type}\n" + log += f" Estimated delivery efficiency: {delivery_efficiency * 100:.1f}%\n" + + # Step 4: Simulate genome editing + log += "\nSTEP 4: Genome Editing Simulation\n" + + # Select best guide based on score + best_guide, best_position, best_score = sorted(target_matches, key=lambda x: x[2], reverse=True)[0] + + log += f" Selected guide RNA: {best_guide} (highest efficiency score)\n" + log += f" Target position: {best_position} to {best_position + len(best_guide) - 1}\n" + + # Simulate editing outcome + edit_success_rate = delivery_efficiency * (0.5 + (best_score * 0.1)) # Between 50-90% based on guide quality + + # Cut site (typically 3 bases upstream of PAM) + cut_position = best_position + len(best_guide) - 3 + log += f" Predicted cut site: Between positions {cut_position} and {cut_position + 1}\n" + + # Simulate editing outcomes + indel_size = random.randint(1, 5) # Random indel size between 1-5 bp + + # Create modified sequence (simulate a deletion for simplicity) + modified_sequence = target_seq[:cut_position] + target_seq[cut_position + indel_size :] + + log += f" Simulated edit: {indel_size}bp deletion at cut site\n" + log += f" Predicted editing efficiency: {edit_success_rate * 100:.1f}%\n" + + # Step 5: Analysis of editing outcomes + log += "\nSTEP 5: Editing Outcome Analysis\n" + + # Calculate basic stats + log += f" Original sequence length: {len(target_seq)} bp\n" + log += f" Modified sequence length: {len(modified_sequence)} bp\n" + + # Save sequences to files + os.makedirs("crispr_results", exist_ok=True) + + original_file = "crispr_results/original_sequence.txt" + with open(original_file, "w") as f: + f.write(f">Original_Sequence\n{target_seq}\n") + + modified_file = "crispr_results/modified_sequence.txt" + with open(modified_file, "w") as f: + f.write(f">Modified_Sequence\n{modified_sequence}\n") + + log += f" Original sequence saved to: {original_file}\n" + log += f" Modified sequence saved to: {modified_file}\n" + + # Summary + log += "\nSUMMARY:\n" + log += f" CRISPR-Cas9 editing successfully simulated for {cell_tissue_type}\n" + log += f" {indel_size}bp deletion introduced at position {cut_position}\n" + log += f" Expected success rate in cell population: {edit_success_rate * 100:.1f}%\n" + + return log + + +def analyze_calcium_imaging_data(image_stack_path, output_dir="./"): + """Analyze calcium imaging data to quantify neuronal activity metrics. + + This function processes fluorescence microscopy images of GCaMP-labeled neurons + to extract quantitative metrics of neuronal activity, including cell counts, + event rates, decay times, and signal-to-noise ratios. + + Parameters + ---------- + image_stack_path : str + Path to the time-series stack of fluorescence microscopy images (TIFF format) + output_dir : str, optional + Directory to save output files (default: "./") + + Returns + ------- + str + Research log summarizing the analysis steps and results + + """ + import os + + import numpy as np + import pandas as pd + from scipy import ndimage, signal + from scipy.optimize import curve_fit + from skimage import feature, filters, io, measure, segmentation + + # Create output directory if it doesn't exist + os.makedirs(output_dir, exist_ok=True) + + # Step 1: Load the image stack + log = "CALCIUM IMAGING ANALYSIS LOG\n" + log += "===========================\n\n" + log += f"Loading image stack from: {image_stack_path}\n" + + try: + image_stack = io.imread(image_stack_path) + num_frames, height, width = image_stack.shape + log += f"Successfully loaded {num_frames} frames of size {height}x{width}\n\n" + except Exception as e: + return f"Error loading image stack: {str(e)}" + + # Step 2: Calculate mean image for segmentation + log += "Step 1: Preprocessing and neuron segmentation\n" + mean_image = np.mean(image_stack, axis=0) + + # Apply Gaussian filter to reduce noise + smooth_mean = filters.gaussian(mean_image, sigma=2) + + # Step 3: Segment neurons using watershed + # Find local maxima (potential cell centers) + distance = ndimage.distance_transform_edt(smooth_mean) + # Create a mask for local maxima instead of using indices=False parameter + coordinates = feature.peak_local_max(distance, min_distance=10) + + # Handle case where no local maxima are found + if len(coordinates) == 0: + log += "No local maxima detected. Using simple thresholding instead.\n" + # Create a simple binary mask using thresholding as fallback + binary_mask = smooth_mean > filters.threshold_otsu(smooth_mean) + markers = measure.label(binary_mask) + else: + local_max = np.zeros_like(distance, dtype=bool) + for coord in coordinates: + local_max[coord[0], coord[1]] = True + markers = measure.label(local_max) + + # Watershed segmentation + segmented = segmentation.watershed(-smooth_mean, markers, mask=smooth_mean > filters.threshold_otsu(smooth_mean)) + + # Get region properties + regions = measure.regionprops(segmented) + cell_count = len(regions) + log += f"Detected {cell_count} neurons in the field of view\n\n" + + # Step 4: Extract time-series data for each neuron + log += "Step 2: Extracting fluorescence time-series for each neuron\n" + time_series_data = [] + + for _i, region in enumerate(regions): + mask = segmented == region.label + cell_time_series = [] + + for frame in range(num_frames): + intensity = np.mean(image_stack[frame][mask]) + cell_time_series.append(intensity) + + time_series_data.append(cell_time_series) + + time_series_array = np.array(time_series_data) + + # Step 5: Detect calcium events and calculate metrics + log += "Step 3: Calculating neuronal activity metrics\n" + + # Function to fit exponential decay + def exp_decay(x, a, tau, c): + return a * np.exp(-x / tau) + c + + event_rates = [] + decay_times = [] + snr_values = [] + + for i, ts in enumerate(time_series_data): + # Normalize time series + baseline = np.percentile(ts, 20) + ts_norm = [(x - baseline) / baseline for x in ts] + + # Simple event detection (threshold crossing) + threshold = np.std(ts_norm) * 2 + events = [] + in_event = False + + for j, val in enumerate(ts_norm): + if not in_event and val > threshold: + events.append(j) + in_event = True + elif in_event and val < threshold: + in_event = False + + # Calculate event rate (events per minute, assuming 10 Hz acquisition) + acquisition_rate = 10 # Hz (assumption) + recording_time_minutes = num_frames / acquisition_rate / 60 + event_rate = len(events) / recording_time_minutes + event_rates.append(event_rate) + + # Calculate decay times for detected events + cell_decay_times = [] + for event_start in events: + if event_start + 30 < len(ts_norm): # Ensure enough frames after event + event_window = ts_norm[event_start : event_start + 30] + peak_idx = np.argmax(event_window) + decay_segment = event_window[peak_idx:] + + try: + # Fit exponential decay + x_data = np.arange(len(decay_segment)) + popt, _ = curve_fit( + exp_decay, + x_data, + decay_segment, + p0=[decay_segment[0], 5, decay_segment[-1]], + bounds=([0, 0, 0], [np.inf, np.inf, np.inf]), + ) + tau = popt[1] # Decay time constant + cell_decay_times.append(tau / acquisition_rate) # Convert to seconds + except Exception: + # Skip if curve fitting fails + pass + + if cell_decay_times: + decay_times.append(np.mean(cell_decay_times)) + else: + decay_times.append(np.nan) + + # Calculate signal-to-noise ratio + signal = np.mean([ts_norm[e] for e in events]) if events else 0 # noqa: F811 + noise = np.std([ts_norm[i] for i in range(len(ts_norm)) if all(abs(i - e) > 5 for e in events)]) + snr = signal / noise if noise > 0 else 0 + snr_values.append(snr) + + # Step 6: Compile and save results + cell_metrics = pd.DataFrame( + { + "Cell_ID": range(1, cell_count + 1), + "Event_Rate_per_min": event_rates, + "Decay_Time_sec": decay_times, + "SNR": snr_values, + } + ) + + metrics_file = os.path.join(output_dir, "neuron_activity_metrics.csv") + cell_metrics.to_csv(metrics_file, index=False) + + # Save time series data + time_series_file = os.path.join(output_dir, "neuron_time_series.csv") + time_series_df = pd.DataFrame(time_series_array.T) + time_series_df.columns = [f"Cell_{i + 1}" for i in range(cell_count)] + time_series_df.to_csv(time_series_file, index=False) + + # Step 7: Summarize results + log += f"Cell count: {cell_count}\n" + log += f"Average event rate: {np.nanmean(event_rates):.2f} events/min\n" + log += f"Average decay time: {np.nanmean(decay_times):.2f} seconds\n" + log += f"Average SNR: {np.nanmean(snr_values):.2f}\n\n" + + log += "Step 4: Results saved to files\n" + log += f"Neuron activity metrics saved to: {metrics_file}\n" + log += f"Time series data saved to: {time_series_file}\n" + + return log + + +def analyze_in_vitro_drug_release_kinetics( + time_points, + concentration_data, + drug_name="Drug", + total_drug_loaded=None, + output_dir="./", +): + """Analyzes in vitro drug release kinetics from biomaterial formulations. + + Parameters + ---------- + time_points : list or numpy.ndarray + Time points at which drug concentrations were measured (in hours) + concentration_data : list or numpy.ndarray + Measured drug concentration at each time point + drug_name : str, optional + Name of the drug being analyzed (default: "Drug") + total_drug_loaded : float, optional + Total amount of drug initially loaded in the formulation. + If None, the maximum concentration is used as 100% (default: None) + output_dir : str, optional + Directory to save output files (default: "./") + + Returns + ------- + str + Research log summarizing the analysis steps, results, and saved file locations + + """ + import os + from datetime import datetime + + import matplotlib.pyplot as plt + import numpy as np + import pandas as pd + from scipy.optimize import curve_fit + + # Ensure output directory exists + os.makedirs(output_dir, exist_ok=True) + + # Convert inputs to numpy arrays + time_points = np.array(time_points) + concentration_data = np.array(concentration_data) + + # Calculate cumulative release percentage + if total_drug_loaded is None: + total_drug_loaded = np.max(concentration_data) + + cumulative_release = (concentration_data / total_drug_loaded) * 100 + + # Create a DataFrame for easier manipulation + release_df = pd.DataFrame( + { + "Time (hours)": time_points, + "Concentration": concentration_data, + "Cumulative Release (%)": cumulative_release, + } + ) + + # Calculate release rate (simple approximation using differences) + release_df["Release Rate"] = np.gradient(release_df["Cumulative Release (%)"], release_df["Time (hours)"]) + + # Define kinetic models + def zero_order(t, k): + return k * t + + def first_order(t, k): + return 100 * (1 - np.exp(-k * t)) + + def higuchi(t, k): + return k * np.sqrt(t) + + def korsmeyer_peppas(t, k, n): + return 100 * (k * t) ** n + + # Fit data to different kinetic models + models = {} + r2_values = {} + + # Zero-order kinetics + try: + params, _ = curve_fit(zero_order, time_points, cumulative_release) + y_pred = zero_order(time_points, *params) + ss_total = np.sum((cumulative_release - np.mean(cumulative_release)) ** 2) + ss_residual = np.sum((cumulative_release - y_pred) ** 2) + r2 = 1 - (ss_residual / ss_total) + models["Zero-order"] = { + "params": params, + "equation": f"Release = {params[0]:.4f} * t", + "pred": y_pred, + } + r2_values["Zero-order"] = r2 + except Exception: + models["Zero-order"] = { + "params": None, + "equation": "Fitting failed", + "pred": None, + } + r2_values["Zero-order"] = 0 + + # First-order kinetics + try: + params, _ = curve_fit(first_order, time_points, cumulative_release, bounds=(0, [1])) + y_pred = first_order(time_points, *params) + ss_total = np.sum((cumulative_release - np.mean(cumulative_release)) ** 2) + ss_residual = np.sum((cumulative_release - y_pred) ** 2) + r2 = 1 - (ss_residual / ss_total) + models["First-order"] = { + "params": params, + "equation": f"Release = 100 * (1 - exp(-{params[0]:.4f} * t))", + "pred": y_pred, + } + r2_values["First-order"] = r2 + except Exception: + models["First-order"] = { + "params": None, + "equation": "Fitting failed", + "pred": None, + } + r2_values["First-order"] = 0 + + # Higuchi model + try: + params, _ = curve_fit(higuchi, time_points, cumulative_release) + y_pred = higuchi(time_points, *params) + ss_total = np.sum((cumulative_release - np.mean(cumulative_release)) ** 2) + ss_residual = np.sum((cumulative_release - y_pred) ** 2) + r2 = 1 - (ss_residual / ss_total) + models["Higuchi"] = { + "params": params, + "equation": f"Release = {params[0]:.4f} * sqrt(t)", + "pred": y_pred, + } + r2_values["Higuchi"] = r2 + except Exception: + models["Higuchi"] = {"params": None, "equation": "Fitting failed", "pred": None} + r2_values["Higuchi"] = 0 + + # Korsmeyer-Peppas model + try: + # Only use the first 60% of release data for Korsmeyer-Peppas model + mask = cumulative_release <= 60 + if sum(mask) >= 3: # Need at least 3 points for fitting + params, _ = curve_fit( + korsmeyer_peppas, + time_points[mask], + cumulative_release[mask], + bounds=([0, 0], [1, 1]), + ) + y_pred = korsmeyer_peppas(time_points, *params) + ss_total = np.sum((cumulative_release - np.mean(cumulative_release)) ** 2) + ss_residual = np.sum((cumulative_release - y_pred) ** 2) + r2 = 1 - (ss_residual / ss_total) + models["Korsmeyer-Peppas"] = { + "params": params, + "equation": f"Release = 100 * ({params[0]:.4f} * t)^{params[1]:.4f}", + "pred": y_pred, + } + r2_values["Korsmeyer-Peppas"] = r2 + else: + models["Korsmeyer-Peppas"] = { + "params": None, + "equation": "Insufficient data points", + "pred": None, + } + r2_values["Korsmeyer-Peppas"] = 0 + except Exception: + models["Korsmeyer-Peppas"] = { + "params": None, + "equation": "Fitting failed", + "pred": None, + } + r2_values["Korsmeyer-Peppas"] = 0 + + # Determine best model based on R² value + best_model = max(r2_values, key=r2_values.get) + + # Calculate half-life (time to 50% release) + try: + # Use best model to calculate half-life + if best_model == "Zero-order": + k = models[best_model]["params"][0] + half_life = 50 / k if k > 0 else float("inf") + elif best_model == "First-order": + k = models[best_model]["params"][0] + half_life = -np.log(0.5) / k if k > 0 else float("inf") + elif best_model == "Higuchi": + k = models[best_model]["params"][0] + half_life = (50 / k) ** 2 if k > 0 else float("inf") + elif best_model == "Korsmeyer-Peppas": + k, n = models[best_model]["params"] + half_life = (0.5 ** (1 / n)) / k if k > 0 else float("inf") + else: + # Interpolate from data if model fitting failed + from scipy.interpolate import interp1d + + if np.max(cumulative_release) >= 50: + f = interp1d(cumulative_release, time_points) + half_life = float(f(50)) + else: + half_life = "Not reached" + except Exception: + half_life = "Could not calculate" + + # Create plots + timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") + + # 1. Cumulative release plot with model fits + plt.figure(figsize=(10, 6)) + plt.plot(time_points, cumulative_release, "o-", label="Experimental data") + + for model_name, model_data in models.items(): + if model_data["pred"] is not None: + plt.plot( + time_points, + model_data["pred"], + "--", + label=f"{model_name} (R² = {r2_values[model_name]:.4f})", + ) + + plt.xlabel("Time (hours)") + plt.ylabel("Cumulative Release (%)") + plt.title(f"In Vitro Release Profile of {drug_name}") + plt.legend() + plt.grid(True, linestyle="--", alpha=0.7) + cumulative_plot_path = os.path.join(output_dir, f"cumulative_release_{timestamp}.png") + plt.savefig(cumulative_plot_path, dpi=300, bbox_inches="tight") + plt.close() + + # 2. Release rate plot + plt.figure(figsize=(10, 6)) + plt.plot(time_points, release_df["Release Rate"], "o-") + plt.xlabel("Time (hours)") + plt.ylabel("Release Rate (%/hour)") + plt.title(f"Release Rate of {drug_name}") + plt.grid(True, linestyle="--", alpha=0.7) + rate_plot_path = os.path.join(output_dir, f"release_rate_{timestamp}.png") + plt.savefig(rate_plot_path, dpi=300, bbox_inches="tight") + plt.close() + + # Save data to CSV + csv_path = os.path.join(output_dir, f"drug_release_data_{timestamp}.csv") + release_df.to_csv(csv_path, index=False) + + # Generate research log + log = f""" +# In Vitro Drug Release Kinetics Analysis for {drug_name} + +## Analysis Summary +- **Date/Time:** {datetime.now().strftime("%Y-%m-%d %H:%M:%S")} +- **Drug Analyzed:** {drug_name} +- **Time Range:** {min(time_points)} to {max(time_points)} hours +- **Number of Data Points:** {len(time_points)} +- **Maximum Release Achieved:** {max(cumulative_release):.2f}% + +## Kinetic Models Analysis +The release data was fitted to four standard kinetic models: + +1. **Zero-order Model:** {models["Zero-order"]["equation"]} (R² = {r2_values["Zero-order"]:.4f}) +2. **First-order Model:** {models["First-order"]["equation"]} (R² = {r2_values["First-order"]:.4f}) +3. **Higuchi Model:** {models["Higuchi"]["equation"]} (R² = {r2_values["Higuchi"]:.4f}) +4. **Korsmeyer-Peppas Model:** {models["Korsmeyer-Peppas"]["equation"]} (R² = {r2_values["Korsmeyer-Peppas"]:.4f}) + +**Best-fitting Model:** {best_model} (R² = {r2_values[best_model]:.4f}) + +## Release Metrics +- **Half-life (t50%):** {half_life if isinstance(half_life, str) else f"{half_life:.2f} hours"} +- **Initial Release Rate:** {release_df["Release Rate"].iloc[0]:.4f} %/hour +- **Average Release Rate:** {np.mean(release_df["Release Rate"]):.4f} %/hour + +## Files Generated +1. Cumulative Release Plot: {cumulative_plot_path} +2. Release Rate Plot: {rate_plot_path} +3. Data CSV: {csv_path} + +## Interpretation +The drug release profile of {drug_name} best follows a { + best_model + } kinetic model, which suggests that the release mechanism is primarily driven by { + "diffusion through a porous matrix" + if best_model == "Higuchi" + else "diffusion with erosion" + if best_model == "Korsmeyer-Peppas" and 0.43 <= models[best_model]["params"][1] <= 0.85 + else "Fickian diffusion" + if best_model == "Korsmeyer-Peppas" and models[best_model]["params"][1] < 0.43 + else "case-II transport" + if best_model == "Korsmeyer-Peppas" and models[best_model]["params"][1] > 0.85 + else "concentration-dependent diffusion" + if best_model == "First-order" + else "constant release rate independent of concentration" + if best_model == "Zero-order" + else "complex mechanisms" + }. +""" + + return log.strip() + + +def analyze_myofiber_morphology( + image_path, + nuclei_channel=2, + myofiber_channel=1, + threshold_method="otsu", + output_dir="./", +): + """Quantifies morphological properties of myofibers in microscopy images of tissue sections. + + Parameters + ---------- + image_path : str + Path to the microscopy image file (typically a multichannel image with nuclei and myofiber staining) + nuclei_channel : int, default=2 + Channel index containing nuclei staining (DAPI, Hoechst, etc.) + myofiber_channel : int, default=1 + Channel index containing myofiber staining (α-Actinin, etc.) + threshold_method : str, default='otsu' + Method for thresholding ('otsu', 'adaptive', or 'manual') + output_dir : str, default='./' + Directory to save output files + + Returns + ------- + str + Research log summarizing the analysis steps and results + + """ + import os + from datetime import datetime + + import numpy as np + import pandas as pd + from skimage import exposure, filters, io, measure, morphology + from skimage.color import label2rgb + + # Create output directory if it doesn't exist + os.makedirs(output_dir, exist_ok=True) + + # Load the image + image = io.imread(image_path) + + # Extract channels (assuming multichannel image) + if len(image.shape) > 2: + if len(image.shape) == 3: + # RGB image + nuclei_img = image[:, :, nuclei_channel] if nuclei_channel < image.shape[2] else image[:, :, 0] + myofiber_img = image[:, :, myofiber_channel] if myofiber_channel < image.shape[2] else image[:, :, 1] + else: + # Multichannel image (e.g., from confocal) + nuclei_img = image[nuclei_channel, :, :] if nuclei_channel < image.shape[0] else image[0, :, :] + myofiber_img = image[myofiber_channel, :, :] if myofiber_channel < image.shape[0] else image[1, :, :] + else: + # Single channel image - can't separate nuclei and myofibers + return "Error: Input image must be multichannel to separate nuclei and myofibers" + + # Enhance contrast + nuclei_img = exposure.equalize_adapthist(nuclei_img) + myofiber_img = exposure.equalize_adapthist(myofiber_img) + + # Segment nuclei + if threshold_method == "otsu": + nuclei_thresh = filters.threshold_otsu(nuclei_img) + elif threshold_method == "adaptive": + nuclei_thresh = filters.threshold_local(nuclei_img, block_size=35) + else: # manual + nuclei_thresh = np.mean(nuclei_img) * 1.5 + + nuclei_binary = nuclei_img > nuclei_thresh + nuclei_binary = morphology.remove_small_objects(nuclei_binary, min_size=30) + nuclei_binary = morphology.binary_closing(nuclei_binary) + + # Label nuclei + nuclei_labels = measure.label(nuclei_binary) + nuclei_props = measure.regionprops(nuclei_labels) + + # Segment myofibers + if threshold_method == "otsu": + myofiber_thresh = filters.threshold_otsu(myofiber_img) + elif threshold_method == "adaptive": + myofiber_thresh = filters.threshold_local(myofiber_img, block_size=101) + else: # manual + myofiber_thresh = np.mean(myofiber_img) * 1.2 + + myofiber_binary = myofiber_img > myofiber_thresh + myofiber_binary = morphology.remove_small_objects(myofiber_binary, min_size=500) + myofiber_binary = morphology.binary_closing(myofiber_binary, morphology.disk(3)) + + # Label myofibers + myofiber_labels = measure.label(myofiber_binary) + myofiber_props = measure.regionprops(myofiber_labels) + + # Count nuclei inside myofibers + nuclei_inside = 0 + nuclei_total = len(nuclei_props) + + for nucleus in nuclei_props: + y, x = nucleus.centroid + y, x = int(y), int(x) + if myofiber_binary[y, x]: + nuclei_inside += 1 + + percent_inside = nuclei_inside / nuclei_total * 100 if nuclei_total > 0 else 0 + + # Calculate myofiber morphological properties + myofiber_data = [] + for fiber in myofiber_props: + myofiber_data.append( + { + "Area": fiber.area, + "Perimeter": fiber.perimeter, + "Eccentricity": fiber.eccentricity, + "Solidity": fiber.solidity, + "Orientation": fiber.orientation, + } + ) + + # Save results + timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") + results_file = f"{output_dir}/myofiber_analysis_{timestamp}.csv" + + if myofiber_data: + df = pd.DataFrame(myofiber_data) + df.to_csv(results_file, index=False) + + # Calculate summary statistics + mean_area = df["Area"].mean() + mean_perimeter = df["Perimeter"].mean() + mean_eccentricity = df["Eccentricity"].mean() + else: + mean_area = mean_perimeter = mean_eccentricity = 0 + + # Save labeled image + labeled_image = label2rgb(myofiber_labels, image=myofiber_img) + labeled_image_path = f"{output_dir}/labeled_myofibers_{timestamp}.png" + io.imsave(labeled_image_path, (labeled_image * 255).astype(np.uint8)) + + # Create research log + log = f""" +MYOFIBER MORPHOLOGICAL ANALYSIS REPORT +====================================== +Date: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")} +Image: {image_path} + +ANALYSIS STEPS: +1. Loaded multichannel microscopy image +2. Extracted nuclei (channel {nuclei_channel}) and myofiber (channel {myofiber_channel}) signals +3. Enhanced contrast using adaptive histogram equalization +4. Segmented nuclei using {threshold_method} thresholding +5. Segmented myofibers using {threshold_method} thresholding +6. Performed morphological operations to refine segmentation +7. Identified and measured individual myofibers and nuclei + +RESULTS: +- Total myofibers detected: {len(myofiber_props)} +- Total nuclei detected: {nuclei_total} +- Nuclei inside myofibers: {nuclei_inside} ({percent_inside:.2f}%) +- Mean myofiber area: {mean_area:.2f} pixels +- Mean myofiber perimeter: {mean_perimeter:.2f} pixels +- Mean myofiber eccentricity: {mean_eccentricity:.2f} + +FILES GENERATED: +- Morphological measurements: {results_file} +- Labeled myofiber image: {labeled_image_path} +""" + + return log + + +def decode_behavior_from_neural_trajectories(neural_data, behavioral_data, n_components=10, output_dir="./"): + """Model neural activity trajectories and decode behavioral variables. + + Parameters + ---------- + neural_data : numpy.ndarray + Neural spiking activity data, shape (n_timepoints, n_neurons) + behavioral_data : numpy.ndarray + Behavioral data, shape (n_timepoints, n_behavioral_variables) + n_components : int, optional + Number of principal components to use for dimensionality reduction, default is 10 + output_dir : str, optional + Directory to save output files, default is "./" + + Returns + ------- + str + Research log summarizing the steps taken and results + + """ + import os + import pickle + + import matplotlib.pyplot as plt + import numpy as np + from pykalman import KalmanFilter + from sklearn.decomposition import PCA + from sklearn.metrics import mean_squared_error + from sklearn.model_selection import train_test_split + + # Create output directory if it doesn't exist + if not os.path.exists(output_dir): + os.makedirs(output_dir) + + # Initialize research log + log = "# Neural Trajectory Modeling and Decoding Research Log\n\n" + + # Step 1: Preprocess the data + log += "## Step 1: Data Preprocessing\n" + log += f"- Neural data shape: {neural_data.shape}\n" + log += f"- Behavioral data shape: {behavioral_data.shape}\n" + + # Check for NaN values and replace with zeros + neural_data = np.nan_to_num(neural_data) + behavioral_data = np.nan_to_num(behavioral_data) + + # Split data into training and testing sets + X_train, X_test, y_train, y_test = train_test_split(neural_data, behavioral_data, test_size=0.2, random_state=42) + log += f"- Training set size: {X_train.shape[0]} samples\n" + log += f"- Testing set size: {X_test.shape[0]} samples\n\n" + + # Step 2: Dimensionality reduction with PCA + log += "## Step 2: Dimensionality Reduction\n" + log += f"- Reducing neural data from {neural_data.shape[1]} dimensions to {n_components} components\n" + + pca = PCA(n_components=n_components) + X_train_pca = pca.fit_transform(X_train) + X_test_pca = pca.transform(X_test) + + explained_variance = np.sum(pca.explained_variance_ratio_) * 100 + log += f"- Total variance explained: {explained_variance:.2f}%\n\n" + + # Save PCA components visualization + try: + plt.figure(figsize=(10, 6)) + plt.bar(range(1, n_components + 1), pca.explained_variance_ratio_) + plt.xlabel("Principal Component") + plt.ylabel("Explained Variance Ratio") + plt.title("PCA Components Explained Variance") + plt.xticks(range(1, n_components + 1)) + plt.tight_layout() + + pca_plot_path = os.path.join(output_dir, "pca_explained_variance.png") + plt.savefig(pca_plot_path, dpi=300) + plt.close() + + log += f"- PCA components visualization saved to: {pca_plot_path}\n\n" + except Exception as e: + log += f"- Error creating PCA visualization: {str(e)}\n\n" + + # Step 3: Train a Kalman filter for decoding + log += "## Step 3: Trajectory Modeling and Decoding\n" + log += "- Training Kalman filter to decode behavioral variables from neural trajectories\n" + + # Initialize and train Kalman filter + kf = KalmanFilter(initial_state_mean=np.zeros(y_train.shape[1]), n_dim_obs=X_train_pca.shape[1]) + + # Fit the Kalman filter to the data + kf.em(X_train_pca, y_train) + + # Step 4: Decode behavioral variables + log += "## Step 4: Decoding Behavioral Variables\n" + + # Use the Kalman filter to predict behavioral variables + y_pred, _ = kf.filter(X_test_pca) + + # Evaluate performance + mse = mean_squared_error(y_test, y_pred) + log += f"- Mean squared error on test set: {mse:.4f}\n\n" + + # Save the decoded trajectories visualization + try: + if y_test.shape[1] >= 2: + # Create visualization of true vs. predicted trajectories (first 2 dimensions) + plt.figure(figsize=(12, 6)) + + # First behavioral variable + plt.subplot(1, 2, 1) + plt.plot(y_test[:, 0], label="True") + plt.plot(y_pred[:, 0], label="Predicted") + plt.xlabel("Time steps") + plt.ylabel("Behavioral Variable 1") + plt.title("Decoding Performance - Variable 1") + plt.legend() + + # Second behavioral variable + plt.subplot(1, 2, 2) + plt.plot(y_test[:, 1], label="True") + plt.plot(y_pred[:, 1], label="Predicted") + plt.xlabel("Time steps") + plt.ylabel("Behavioral Variable 2") + plt.title("Decoding Performance - Variable 2") + plt.legend() + + plt.tight_layout() + + trajectory_plot_path = os.path.join(output_dir, "decoded_trajectories.png") + plt.savefig(trajectory_plot_path, dpi=300) + plt.close() + + log += f"- Decoded trajectories visualization saved to: {trajectory_plot_path}\n" + except Exception as e: + log += f"- Error creating trajectory visualization: {str(e)}\n" + + # Save the results as a pickle file + results = { + "true_behavior": y_test, + "predicted_behavior": y_pred, + "pca_model": pca, + "kalman_filter": kf, + "mse": mse, + } + + results_file = os.path.join(output_dir, "neural_decoding_results.pkl") + with open(results_file, "wb") as f: + pickle.dump(results, f) + + # Also save a CSV with the first few predicted vs. actual values for easier inspection + try: + import pandas as pd + + n_samples = min(100, y_test.shape[0]) + n_vars = y_test.shape[1] + + results_data = {} + for i in range(n_vars): + results_data[f"true_var{i + 1}"] = y_test[:n_samples, i] + results_data[f"pred_var{i + 1}"] = y_pred[:n_samples, i] + + results_df = pd.DataFrame(results_data) + csv_path = os.path.join(output_dir, "decoding_results_sample.csv") + results_df.to_csv(csv_path, index=False) + + log += f"- Sample of decoding results saved to: {csv_path}\n" + except Exception as e: + log += f"- Error creating CSV results: {str(e)}\n" + + log += "\n## Results\n" + log += f"- Full decoded behavioral trajectories saved to: {results_file}\n" + log += f"- Decoder performance (MSE): {mse:.4f}\n" + + # Save the log to a file + log_file = os.path.join(output_dir, "neural_decoding_log.txt") + with open(log_file, "w") as f: + f.write(log) + + log += f"- Analysis log saved to: {log_file}\n" + + return log + + +def simulate_whole_cell_ode_model( + initial_conditions, + parameters, + ode_function=None, + time_span=(0, 100), + time_points=1000, + method="LSODA", +): + """Simulate a whole-cell model represented as a system of ordinary differential equations (ODEs). + + Parameters + ---------- + initial_conditions : dict or array-like + Initial values for each state variable in the model. If dict, keys are variable names + and values are initial concentrations/values. If array-like, order must match the + order expected by the ODE function. + parameters : dict + Model parameters required by the ODE function. Keys are parameter names and + values are parameter values. + ode_function : callable, optional + Function defining the system of ODEs. Should take arguments ``(t, y, *args)`` where + ``t`` is time, ``y`` is the state vector, and ``args`` contains additional parameters. + If None, a simple example whole-cell model will be used. + time_span : tuple, default=(0, 100) + Tuple of (start_time, end_time) for the simulation. + time_points : int, default=1000 + Number of time points to evaluate. + method : str, default='LSODA' + Numerical integration method to use (e.g., 'RK45', 'LSODA', 'BDF'). + + Returns + ------- + str + Research log summarizing the simulation steps and results. Results are saved + to a CSV file and the filename is included in the log. + + """ + from datetime import datetime + + import numpy as np + import pandas as pd + from scipy.integrate import solve_ivp + + # Define a default ODE function if none is provided + if ode_function is None: + + def default_whole_cell_model(t, y, params): + # Unpack state variables + # Simple model with: + # - mRNA (y[0]) + # - Protein (y[1]) + # - Metabolite (y[2]) + # - ATP (y[3]) + mRNA, protein, metabolite, atp = y + + # Unpack parameters + k_transcription = params["k_transcription"] # mRNA synthesis rate + k_translation = params["k_translation"] # Protein synthesis rate + k_mrna_deg = params["k_mrna_deg"] # mRNA degradation rate + k_protein_deg = params["k_protein_deg"] # Protein degradation rate + k_metabolism = params["k_metabolism"] # Metabolite production rate + k_atp_production = params["k_atp_production"] # ATP production rate + k_atp_consumption = params["k_atp_consumption"] # ATP consumption rate + + # ODEs + dmRNA_dt = k_transcription - k_mrna_deg * mRNA + dprotein_dt = k_translation * mRNA * atp - k_protein_deg * protein + dmetabolite_dt = k_metabolism * protein - k_atp_production * metabolite + datp_dt = k_atp_production * metabolite - k_atp_consumption * atp - k_translation * mRNA * atp + + return [dmRNA_dt, dprotein_dt, dmetabolite_dt, datp_dt] + + ode_function = default_whole_cell_model + + # Prepare initial conditions as array + if isinstance(initial_conditions, dict): + y0_values = list(initial_conditions.values()) + variable_names = list(initial_conditions.keys()) + else: + y0_values = initial_conditions + variable_names = [f"Variable_{i}" for i in range(len(initial_conditions))] + + # Set up time points + t_eval = np.linspace(time_span[0], time_span[1], time_points) + + # Start research log + log = [] + log.append("# Whole-Cell ODE Model Simulation") + log.append(f"Date: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") + log.append("\n## Simulation Setup") + log.append(f"- Integration method: {method}") + log.append(f"- Time span: {time_span[0]} to {time_span[1]} time units") + log.append(f"- Number of time points: {time_points}") + log.append(f"- Number of state variables: {len(y0_values)}") + log.append("\n## Initial Conditions") + for _i, (name, value) in enumerate(zip(variable_names, y0_values, strict=False)): + log.append(f"- {name}: {value}") + + log.append("\n## Model Parameters") + for param, value in parameters.items(): + log.append(f"- {param}: {value}") + + # Solve the ODE system + log.append("\n## Running Simulation") + try: + solution = solve_ivp( + lambda t, y: ode_function(t, y, parameters), + time_span, + y0_values, + method=method, + t_eval=t_eval, + ) + + # Check if simulation was successful + if solution.success: + log.append("Simulation completed successfully.") + log.append(f"- Number of function evaluations: {solution.nfev}") + log.append(f"- Number of Jacobian evaluations: {solution.njev}") + log.append(f"- Number of steps: {len(solution.t)}") + + # Create DataFrame with results + results_df = pd.DataFrame(solution.y.T, columns=variable_names) + results_df.insert(0, "Time", solution.t) + + # Save results to CSV + filename = f"whole_cell_simulation_results_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv" + results_df.to_csv(filename, index=False) + + log.append("\n## Results Summary") + log.append(f"Simulation results saved to: {filename}") + + # Calculate some basic statistics + final_state = results_df.iloc[-1].drop("Time").to_dict() + log.append("\n## Final State") + for var, value in final_state.items(): + log.append(f"- {var}: {value:.6f}") + + else: + log.append(f"Simulation failed with message: {solution.message}") + + except Exception as e: + log.append(f"Error during simulation: {str(e)}") + + # Return the research log + return "\n".join(log) diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/example_mcp_tools/pubmed_mcp.py b/BioScientist/agent_system/engines/v1_executor_backup/tool/example_mcp_tools/pubmed_mcp.py new file mode 100644 index 0000000000000000000000000000000000000000..a9cc2bb99d6a8316150286038ea41c9bf837244a --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/example_mcp_tools/pubmed_mcp.py @@ -0,0 +1,38 @@ +import os + +from Bio import Entrez +from mcp.server.fastmcp import FastMCP +from pydantic import BaseModel + +Entrez.email = os.getenv("NCBI_EMAIL") or "YOUR_EMAIL" +mcp = FastMCP("pubmed-live") + + +class Article(BaseModel): + pmid: str + title: str | None = None + journal: str | None = None + year: str | None = None + abstract: str | None = None + + +@mcp.tool() +def search_pubmed(query: str, max_results: int = 10) -> list[Article]: + ids = Entrez.read(Entrez.esearch(db="pubmed", term=query, retmax=max_results))["IdList"] + summaries = Entrez.read(Entrez.esummary(db="pubmed", id=",".join(ids))) if ids else [] + articles: list[Article] = [] + for s in summaries: + articles.append( + Article(pmid=s["Id"], title=s["Title"], journal=s.get("FullJournalName", ""), year=s.get("PubDate", "")[:4]) + ) + return articles + + +@mcp.tool() +def get_article_abstract(pmid: str) -> str: + with Entrez.efetch(db="pubmed", id=pmid, rettype="abstract", retmode="text") as h: + return h.read() + + +if __name__ == "__main__": + mcp.run() diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ AAV Production.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ AAV Production.txt new file mode 100644 index 0000000000000000000000000000000000000000..ee75d596f9fd64f7a0b797e3a08284fc5ccd485e --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ AAV Production.txt @@ -0,0 +1,325 @@ +PROTOCOL: AAV Production +SOURCE: https://www.addgene.org/protocols/aav-production-hek293-cells/ +================================================================================ + +INTRODUCTION +================================================================================ + +This protocol can be used to produce AAV from one Five Chambers Cell-Stack (CS5) +(3,180 cm² - the same surface area as 21 x T-175 flasks). Cell stacks provide an +efficient means to scale-up without having to handle a large number of T-175 +flasks. + + +WORKFLOW TIMELINE +================================================================================ + +Day 0: Seed cells in CS2 + +Day 2: Seed cells in CS5 + +Day 3 (am): Transfect cells + +Day 7 (am): Harvest cells + + +EQUIPMENT +================================================================================ + +• Class II, Type A2 Biological Safety Cabinet +• 0.5–10 µL single channel pipette +• 2–20 µL single channel pipette +• 20–200 µL single channel pipette +• 200–1000 µL single channel pipette +• Hemocytometer or cell counter +• Ice bucket +• CO₂ incubator +• Pipet controller +• Hazardous waste container +• pH meter +• Stir plate +• Magnetic stir bar +• Sonicator +• Ear protection +• Vortex + + +REAGENTS +================================================================================ + +• Adherent HEK293T cells (ideally AAV-293T clones) + + 💡 PRO TIP: While adherent, these cells are very loosely attached to the dish + surface and should be handled carefully. Avoid touching the cells when replacing + media. + +• T-175 flask, Corning 430825, 175 cm² +• Cellstack 5, Corning 3319, 3180 cm² +• Cellstack 2, Corning 3269, 1272 cm² +• Heat-inactivated FBS (HI-FBS) + + 💡 PRO TIP: Different brands and lots of FBS can promote or inhibit + transfection. Test a variety of brands and lots of FBS to find one suitable for + your protocols. FBS can be purchased already heat-inactivated, or it can be + inactivated in the lab by heating to 56 °C for 30 minutes. + +• 0.45 μm polyethersulfone (PES) filter system, Nalgene, 565-0010 (or for larger + volumes 1000 mL 0.45 µm Rapid-Flow PES Filtration Unit, Nalgene 167-0045) + + 💡 PRO TIP: Do not use filters made of materials other than PES. AAV particles + stick to many other surfaces, but do not stick to PES. Using a PES filter will + maximize titer. + +• DMEM high glucose, Corning 10-013-CV +• DMEM, low glucose (1 g/L) glucose, sodium pyruvate, Corning 10-014-CV (optional) +• 7.5% sodium bicarbonate, Corning 25-035-CI (optional) +• 1 M HEPES, HyClone SH30237.01 (optional) +• L-alanyl-L-glutamine (or alternative stable glutamine such as glutaGRO, + Corning 25-015-CI) +• Opti-MEM, Thermo Fisher 31985-070 +• 0.05% Trypsin/EDTA (e.g. TrypLE, Thermo Fisher, 12605010) +• 1X PBS pH 7.4 without calcium or magnesium, Corning 21-040-CV (cations can + affect the attachment of adherent cells) +• 1 mg/mL Polyethylenimine (PEI) 25 kDa MW + + 💡 PRO TIP: Other transfection reagents may be used in this protocol, but their + conditions must be optimized. + +• Plasmids for transfection: pHelper; pRC (Rep-Cap), plasmid expressing your gene + of interest +• Triton X-100 +• Benzonase/DNAse I (Millipore 71205-3) +• 40% Polyethylene Glycol 8000 (PEG) + 0.5 M NaCl +• Cell lysis buffer (50 mM Tris HCl, 150 mM NaCl, 2 mM MgCl₂) + + +REAGENT PREPARATION +================================================================================ + +DMEM Complete: 10% v/v FBS and 4 mM L-alanyl-L-glutamine (or stable alternative, +such as glutaGRO) + +To a 500 mL bottle of DMEM high glucose, add 55 mL of heat-inactivated FBS and 5 +mL of glutaGRO 11 mL of 200 mM L-alanyl-L-glutamine. Store at 4 °C. + +D1 + 0.1 M sorbitol (optional): DMEM low glucose + 1% v/v HI-FBS + 0.1 M sorbitol + +In our hands, we have found that a lower glucose, lower FBS media causes less +filter clogging during harvesting. The addition of sorbitol has been shown to +increase viral titers by up to 1.8-fold (Rego et al., 2018). + +To prepare D1 + 0.1 M sorbitol, add 57 mL of 1.46 M sorbitol, 7.5 mL HI-FBS, and +7.5 mL 100X glutaGRO, 7.5 mL of 7.5% Sodium Bicarbonate, 7.5 mL 1 M HEPES to 750 +mL DMEM + 1 g/L glucose. + +1 mg/mL polyethylenimine (PEI) solution: + +1. Dissolve 100 mg of PEI powder into 100 mL of deionized water. + +2. While stirring, slowly add hydrochloric acid until the solution clears. + +3. Check the pH of the solution and use hydrochloric acid or sodium hydroxide to + adjust the pH to 7.0. + + 💡 PRO TIP: The pH of this solution will drift pretty rapidly upon addition + of acid or base. Add only a few drops at a time. Allow them to mix and recheck + the pH to prevent over or undershooting the desired pH. + +4. Allow the solution to mix for 10 min and then recheck the pH to ensure that it + has not drifted. + +5. Filter the solution through a 0.22 μm membrane. + +6. Aliquot 500–1000 μL into sterile tubes. + +7. Store the tubes at -80 °C. + +8. After thawing, the solution can be stored at 4 °C for up to 2 months. After 2 + months, discard the tube and thaw a new working stock. + +40% POLYETHYLENE GLYCOL (PEG) 8000 solution: + +1. Dissolve 400 g of PEG 8000 and 24 g of NaCl into deionized water and adjust to + a final volume of 1000 mL. + +2. Stir at RT until fully dissolved. + + 💡 PRO TIP: This step is challenging due to the high viscosity of PEG. + Stirring under medium heat will promote faster dissolution. + +3. Adjust the pH to ~7.4. + +4. Autoclave or sterile filter. + + 💡 PRO TIP: Stirring during the cooling period is recommended or the solution + may separate into phases. + +5. Aliquot and store at 4 °C. + +Cell Lysis Buffer: 50 mM Tris HCl, 150 mM NaCl, 2 mM MgCl₂ + +1. Add the following to the 2 L sterile bottle: 1836 mL deionized water + 100 mL + of 1 M Tris HCl pH 8.5 + 60 mL of 5 M Sodium Chloride + 4 mL of 1 M Magnesium + Chloride + +2. Close the bottle and mix by inverting multiple times + +3. Adjust pH to ~8.5 + +4. Filter sterilize through a 0.22 μm membrane. + +5. Store at 4 °C. + + +CONSIDERATIONS BEFORE YOU START +================================================================================ + +• The health of the HEK293T cells is critical for optimal AAV yield. + +• Do not overgrow your cells. Pass the cells twice a week during the maintenance + phase and do not allow cells to reach 100% confluence (80–90% is ideal). + +• Pass and plate the cells the day before the transfection. + +• Thaw a new vial of cells after 30 passages. + + +PROCEDURE +================================================================================ + +1. Trypsinize and resuspend the HEK293T cells from 2 x T-175 flasks. Cells should + be at ~80% confluence. For each T-175 flask: + • Aspirate culture media and rinse once with 10 mL of PBS. + • Aspirate PBS and add 2 mL of 0.05% Trypsin/EDTA. Wait ~2 min. + • Neutralize trypsin by adding 10 mL of DMEM Complete. + • Pipet back and forth vigorously multiple times to obtain a single cell + suspension (no clumps of cells). + +2. Pool cells from 2 x T-175 flasks. Adjust volume to 300 mL with DMEM complete + media and mix. + +3. Seed all cells in 1 CS2. Return to incubator for 48 h. + +4. Trypsinize and resuspend cells from the CS2. Cells should be at ~80% + confluence. + • Aspirate culture media and rinse once with 60 mL PBS. + • Aspirate PBS and add 35 mL of 0.05% Trypsin/EDTA. + • Wait ~2-3 minutes for cells to detach. + • Gently tap the sides of the CS2 to help detach the cells, add 200 mL of DMEM + complete media, then transfer the cells into a sterile bottle. + • Rinse the CS2 with 100 mL of DMEM complete medium and pool with the cells + harvested in the previous step. + • Pipette back and forth or shake vigorously to obtain a single cell suspension + (no clumps). + +5. Count cells using a hemocytometer or cell counter. + +6. Seed 350 million cells from the CS2 into one CS5 with a total volume of 850 mL. + Return to the incubator for 24 h–36 h. + +7. Proceed with transfection: + • Calculate the amount of each plasmid needed to have a 1:1:1 molar ratio with 2 + mg total DNA per CS5 + + Example calculations: + - RepCap (7,265 bp): 582.1 μg = 582.1 μL (at 1.00 μg/μL) + - pHelper (11,854 bp): 949.8 μg = 949.8 μL (at 1.00 μg/μL) + - Transfer Plasmid (5,842 bp): 468.1 μg = 468.1 μL (at 1.00 μg/μL) + + • Aliquot 100 mL of OptiMEM into a sterile 250 mL bottle. + + • Aliquot 774 mL of DMEM + 2% HI-FBS into a sterile 1 L bottle. + + • Add each plasmid DNA into the bottle containing the Opti-MEM. Mix well. + + • Add 4 mL of PEI (1:2 μg DNA to μg PEI ratio). Shake the bottle up/down + vigorously for 30 sec (it's okay to make bubbles). + + • Incubate at RT for 15 min. Note that longer incubation times can reduce + transfection efficiency. + + • Add the OptiMEM + DNA + PEI solution to the bottle containing 774 mL of DMEM + + 2% HI-FBS. Mix well. + +8. Take the CS5 out of the incubator and pour the media into a waste container. + +9. Carefully add the OptiMEM + DNA + PEI solution to the CS5. Make sure that all + five layers are covered with media. 293T cells are delicate and detach very + easily - media should always be added away from the cells (not poured on them) + and can be adjusted by carefully tilting the CS5 back and forth. + + 💡 PRO TIP: To help distribute the media amongst the five layers, tilt the CS5 + such that the media goes toward the cap. If the media touches the cap, replace + it with a new one before putting the CS5 in the incubator. + +10. Return the CS5 to the incubator for 96 h. This incubation time can be adjusted + depending upon the serotype. Often AAV2 are harvested at 48–72 h, while other + serotypes are harvested at 96–120 h. + +11. Optional: perform a media exchange at ~18 h post transfection. Changing the + media can reduce toxicity associated with PEI and allow for the addition of + other components, such as sorbitol and sodium bicarbonate, sorbitol has been + found to increase viral titers by up to 1.8-fold. See the recipe for D1 + 0.1 M + sorbitol above. + • Carefully pour off the media into a waste container. + • Gently pour new media into the CS5. + • Distribute the media evenly between the layers. + • Return the CS5 to the incubator for ~72 h. + +12. Harvest cells and media by tapping the sides of the CS5. Cells should detach + easily. + +13. Transfer cells and media into 500 mL conical vessels. + +14. Rinse CS5 once with 100 mL of PBS and add to the harvested media and cells. + +15. Centrifuge at 3900 rpm for 20 min at 4 °C to pellet the cells. + +16. Keep the cell pellet on ice and transfer supernatant to a sterile 500 mL + bottle. + +17. Process the supernatant as follows: + • Filter through a 0.45 μm PES membrane. + • Add 40% PEG such that the final PEG concentration is 8%. + • Add 25 mL of PEG solution to each 100 mL of supernatant. Split into 2 x 500 + mL sterile bottles as needed. + • Add stir bar and stir slowly at 4 °C for 1 h, then keep at 4 °C for 3 h + without stirring to allow full precipitation. Precipitation of the viruses + can proceed overnight at 4 °C if needed. + • Transfer the entire sample to 3 x 500 mL conical bottles and centrifuge at + 3900 rpm for 15 min at 4 °C. + • Discard the supernatant and resuspend the pellets in a total of 5 mL of cell + lysis buffer (recipe above). Pipet back and forth to resuspend each pellet + completely. + • Combine resuspended pellets and keep on ice. + +18. Process the cell pellet from above as follows: + • Resuspend and lyse the cells by adding a total of 12.5 mL of cell lysis + buffer. Pipet back and forth to resuspend each pellet completely. + • Combine all resuspended cell pellets and sonicate 5 x 1 sec pulses with at + least 5 minutes on ice between each pulse, 50% amplitude. Return to ice + between each round of sonication to avoid overheating of the sample. Mix + well between rounds of sonication. + • Sonicate until no live cells can be seen when stained with Trypan Blue. + • Pellet cell debris by centrifugation at 3900 rpm for 10 min at 4 °C. + • Transfer the cleared lysate to the tube containing the resuspended virus from + step 17 above. + +19. Add 50 units of benzonase per mL of viral suspension (you should have ~18 mL + from steps 17 & 18). Benzonase is an endonuclease that will degrade any + residual DNA carried over from the packaging process. + +20. Incubate at 37 °C for 45 min. + +21. You are now ready to purify your prep. The clarified supernatant can be kept + overnight at 4 °C before proceeding with the purification protocol. + + +SAMPLE DATA +================================================================================ + +HEK293T cells at various confluencies. This AAV production protocol should be +started with cells that are ~80% confluent (center panel). These cells were +imaged with a 10X objective and were split 2 days before these images were taken. + +Last reviewed on: October 10, 2023 diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ AAV Purification.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ AAV Purification.txt new file mode 100644 index 0000000000000000000000000000000000000000..fd3a9a690b43d5bef82724dc59fa9e812cbdc875 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ AAV Purification.txt @@ -0,0 +1,244 @@ +PROTOCOL: AAV Purification +SOURCE: https://www.addgene.org/protocols/aav-purification-iodixanol-gradient-ultracentrifugation/ +================================================================================ + +INTRODUCTION +================================================================================ + +This protocol can be used to purify AAV of any serotype. + +In medicine, iodixanol can be used as an intravenous isomolar contrast agent. In +research, iodixanol is used as an isomolar density gradient medium suitable for +virus purification and isolation of cells, organelles, lipoproteins, and +macromolecules. Importantly, iodixanol is inert and non-toxic to mammalian cells. +Therefore, and unlike other density gradient media, it is reportedly not +necessary to remove iodixanol prior to use of your purified virus. Nonetheless, +we recommend performing a buffer exchange before using the purified AAV in vivo. + +The iodixanol gradient in this protocol is composed of steps that separate out +contaminants from an impure AAV preparation. The 15% iodixanol step has 1M NaCl to +destabilize ionic interactions between macromolecules. The 40% and 25% steps are +used to remove contaminants with lower densities, including empty capsids. The 60% +step serves as a cushion for genome-containing virions. Phenol red is added to +clearly distinguish the steps. This method will help enrich the prep with full +(genome containing) particles. On average, iodixanol-purified AAV preparations +contain ~20% empty particles. + +60% iodixanol solution is available under the name OptiPrep from Sigma-Aldrich. + + +WORKFLOW TIMELINE +================================================================================ + +Day 1: Purify + +Day 2: Buffer exchange and concentration + +Note: Both steps could be completed in one (long) day. + + +EQUIPMENT +================================================================================ + +• Ultracentrifuge +• T70i rotor or equivalent + + +REAGENTS +================================================================================ + +• Opti-Prep (60% Iodixanol) +• QuickSeal tubes +• QuickSeal tube spacers +• 16 ga needle +• 18 ga needle +• 10 mL syringe +• 18 ga blunt edge needles, Hamilton +• 1X PBS pH 7.4 +• 1X PBS-MK buffer +• 100X Poloxamer 188 +• NaCl +• MgCl₂ +• KCl +• Centrifugal filter units (MWCO 100 kDa) + + +REAGENT PREPARATION +================================================================================ + +1 M NaCl/PBS-MK buffer: + +Dissolve 5.84 g of NaCl, 26.3 mg of MgCl₂ and 14.91 mg of KCl in 1× PBS in a +final volume of 100 mL. Sterilize by passing through a 0.22 μm filter and store +at 4 °C. + +1X PBS-MK buffer: + +Dissolve 26.3 mg of MgCl₂, and 14.91 mg of KCl in 1× PBS in a final volume of +100 mL. Sterilize by passing through a 0.22 μm filter and store at 4 °C. + +0.1% Poloxamer 188 in PBS (A): + +Add 500 µL of 10% Poloxamer 188 to 49.5 mL PBS + +0.01% Poloxamer 188 in PBS (B): + +Add 5 mL of Buffer A to 45 mL PBS + +0.001% Poloxamer 188 in PBS + 200 mM NaCl (C) (formulation buffer): + +Add 5 mL of Buffer B and 2 mL of 5 M NaCl to 43 mL PBS + + +PROCEDURE +================================================================================ + +Preparation and loading of the iodixanol gradient: + +1. Prepare the gradient steps: + • 15% iodixanol step: mix 4.5 mL of 60% iodixanol and 13.5 mL of 1 M + NaCl/PBS-MK buffer + • 25% iodixanol step: mix 5 mL of 60% iodixanol and 7 mL of 1X PBS-MK buffer + and 30 μL of phenol red + • 40% iodixanol step: mix 6.7 mL of 60% iodixanol and 3.3 mL of 1X PBS-MK + buffer + • 60% iodixanol step: mix 10 mL of 60% iodixanol and 45 μL of phenol red + +2. Underlay each solution into a QuickSeal tube in the order below using a 10 mL + syringe and a blunt edge 18 ga Hamilton needle, taking care to avoid bubbles: + • 8 mL of 15% iodixanol step + • 5 mL of 25% iodixanol step + • 5 mL of 40% iodixanol step + • 3 mL of 60% iodixanol step + +3. Carefully add up to 5 mL of clarified supernatant on top of the gradient. Use + 1X PBS (or formulation buffer) to top off the tube. + +4. Seal the QuickSeal tubes. + +5. Centrifuge at 350,000 x g for 90 min in a T70i rotor at 10 °C. + + 💡 PRO TIP: If you need more time, you can alternatively centrifuge for 2 h at + 200,000 x g at 18 °C. + +6. Carefully take the QuickSeal tubes out of the rotor and place them in a stable + rack. + + **Make sure not to disturb the gradient!** + +Collect Fractions + +Option #1: + +1. Prepare a row of roughly 20 open 1.5 mL microcentrifuge tubes in a rack. + These will be used to collect fractions from the gradient. You can collect fewer + fractions once you have a good idea when the virus elutes from the gradients. + +2. In a biosafety cabinet, carefully puncture the QuickSeal tube at the interface + of the 60% and 40% gradient (see Figure 2) with an 18 ga needle. + +3. Place the first microcentrifuge tube under the needle's opening to collect the + fractions. + +4. Puncture the top of the QuickSeal tube with a 16 ga needle and start + collecting 0.5 mL to 1 mL fractions per tube. + +5. Avoid the proteinaceous material near the 40–25% interface. + + 💡 PRO TIP: As soon as the top of the tube is punctured, AAV-containing + Iodixanol solution will flow from the needle set at the 40–60% interface. + Make sure that the microcentrifuge tubes are well positioned to collect the + solution, or you will lose a significant amount of your virus. When the first + fraction is collected, move the rack to the next empty tube to collect the next + fraction. The flow will be rapid at first and will progressively slow down. + +Option #2: + +1. Puncture the QuickSeal tube at the bottom using an 18 ga needle. + +2. Immediately start collecting 0.5 to 1 mL fractions in microcentrifuge tubes. + +3. Repeat for each QuickSeal tube. + +4. The first 3 mL collected corresponds to the 60% phase and can be discarded. + +5. The fractions obtained from the 40% phase contain the purified AAV. + +Option #3: + +1. Puncture the QuickSeal tube slightly below the 60–40% interface with an 18 ga + needle attached to a 10 mL syringe. + +2. The bevel of the needle should be up, facing the 40% step. + +3. Collect up to 5 mL per tube, taking care to avoid collecting the + proteinaceous material at the 40–25% interface. + +4. Repeat for each QuickSeal tube. + +5. (Optional) For first time users, it is a good idea to assay each fraction by + silver stain or SYPRO Ruby stain to determine purity. Only the cleanest + fractions should be kept and pooled for dialysis. + +6. Pool clean fractions. + +Concentration and buffer exchange: + +Stocks of Poloxamer 188: +• Poloxamer 188, 10% solution +• A: 0.1% in PBS: 49.5 mL PBS + 500 µl Poloxamer 188 +• B: 0.01% in PBS: 45 mL PBS + 5 ml A +• C: 0.001% in PBS: 45 mL PBS + 5 ml B + 200 mM NaCl + +Procedure: + +1. Cover the filter membrane with 15 mL of 0.1% Poloxamer 188 PBS and incubate + for 10 min at RT + +2. Spin at 3000 rpm for 5 min at 4 °C and discard the flow through. + +3. Add 15 mL of 0.01% Poloxamer 188 PBS and incubate for 10 min at RT. + +4. Spin at 3000 rpm for 5 min at 4 °C and discard the flow through. + +5. Add 15 mL of 0.001% Poloxamer 188 + 200mM NaCl PBS. + +6. Spin at 3000 rpm for 5 min at 4 °C and discard the flow through. + +7. Add your sample. + +8. Spin at 3500 rpm for 5–8 min at 4 °C, discard the flow through. + +9. Add more sample and spin 3500 rpm for 2–5 min at 4 °C, discard the flow + through. + +10. Repeat this step as needed. + + Please note that iodixanol is not easily removed. After each spin, add more + formulation buffer and sample and make sure to pipet back and forth a few + times to mix the iodixanol that has settled at the bottom of the column. + +11. We recommend concentrating to a minimum of 500 µL. If the concentrate volume + is less than 500 µL, bring up the volume with formulation buffer. + +12. Use a P1000 to the bottom of the filter and pipette up/down and wash off the + walls of the filter to recover as much virus as possible. + +13. Store at 4 °C for short term (2 weeks), or aliquot and store at -80 °C for + long term. + + +SAMPLE DATA +================================================================================ + +Iodixanol gradient before ultracentrifugation. The steps are clearly +distinguishable thanks to the use of phenol red. + +Iodixanol gradient after ultracentrifugation. The arrow indicates the 60–40% +interface. The vertical black line indicates the location of the purified AAV. + +Example of an SDS-PAGE gel of 10 consecutive gradient fractions followed by +silver stain. Note the increased number of contaminants in each fraction. * AAV +capsid proteins VP1, VP2, VP3; M protein marker. + +Last reviewed on: November 7, 2023 diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ AAV Titration by qPCR.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ AAV Titration by qPCR.txt new file mode 100644 index 0000000000000000000000000000000000000000..3a149d75eab97e8e8018942e5de324818d570e0b --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ AAV Titration by qPCR.txt @@ -0,0 +1,264 @@ +PROTOCOL: AAV Titration by qPCR +SOURCE: https://www.addgene.org/protocols/aav-titration-qpcr-using-sybr-green-technology/ +================================================================================ + +INTRODUCTION +================================================================================ + +The AAV Titration protocol can be used to determine the number of +genome-containing particles of an AAV prep using SYBR green technology. + +This protocol was validated using an internal reference AAV of known titer, +100837-AAV1, and by measuring the titer of samples obtained from academic viral +vector cores. Our titers were similar to those reported by these institutions. + +This protocol is for a 96-well plate with 20 μL reaction volume. + +Last Update: February 13, 2019 + +Estimate of time required: ~3 h + + +WORKFLOW TIMELINE +================================================================================ + +Plate set-up: 2 h + +qPCR run: 1.5 h + +Data analysis: 30 min + + +EQUIPMENT +================================================================================ + +• qPCR instrument +• Heating plate +• Pipettors +• 1–10 µL single channel pipette +• 20–200 µL single channel pipette +• 200–1000 µL single channel pipette +• 1–10 µL multichannel pipette +• 2–50 µL multichannel pipette +• 20–200 µL multichannel pipette + + +REAGENTS +================================================================================ + +• Universal SYBR Master Mix 2X +• Primer pair targeting AAV2 ITR (Aurnhammer et al., 2012) + - fwd ITR primer, 5'-GGAACCCCTAGTGATGGAGTT + - rev ITR primer, 5'-CGGCCTCAGTGAGCGA +• ITR-containing plasmid for standard curve +• RNase-free DNase +• 10X DNase buffer +• Nuclease-free water +• Microcentrifuge tubes +• 96-well optical plate +• Pipette tips + + +GENERAL CONSIDERATIONS +================================================================================ + +• Always run standards and samples in duplicate at least + +• If possible, include an AAV reference sample of known titer. The reference + material should have a titer within 1-log of the expected titer of the samples + being tested. + +• Always include a No Template Control (NTC), i.e master mix + water + +• Whenever possible use a multichannel pipet to minimize pipetting error and + variability + +• Mix samples very well by pipetting back and forth multiple times at each step + + +REAGENT PREPARATION +================================================================================ + +Master Mix: + +Count the number of samples (n) and prepare master mix for an additional 10 +samples (n+10 – the additional amount will ensure that there is enough master mix +for all samples). Each sample requires 15 μL of master mix. + +💡 PRO TIPS: + +• Use a "Universal" SYBR master mix which contains a high-quality DNA polymerase + and a blend of dTTP/dUTP to minimize carryover contamination. The master mix + should also contain an internal passive reference (typically ROX dye), to + normalize non-PCR–related fluorescence fluctuations and to minimize well-to-well + variability that result from a variety of causes, such as pipetting error and + sample evaporation. + +• Make the master mix after all the samples have been added to the qPCR plate. + Start by adding water, then SYBR master mix, then the forward and reverse + primers. Vortex briefly, immediately before use. + +• Use a reservoir and a multichannel pipette to dispense the master mix into the + wells. + +Master Mix Recipe: + +Reagent | Amount for ONE Reaction | Amount for 100 reactions +---------------------------|------------------------|-------------------------- +Universal SYBR Master Mix | 10 μL | 1,000 μL +2X | | +100 μM Forward Primer | 0.15 μL | 15 μL +100 μM Reverse Primer | 0.15 μL | 15 μL +Nuclease Free Water | 4.7 μL | 470 μL + + +PROCEDURE +================================================================================ + +1. Prepare a plasmid stock of 2 x 10⁹ molecules/μL to generate a standard curve: + + One option is to use plasmid #59462 from Addgene. The values highlighted below + in red were calculated using this plasmid, but will change if you use a + different plasmid. + + Sample Calculation: + • Size in bp of Addgene plasmid #59462: 6208 bp + • Concentration of Addgene plasmid #59462: 1.07 μg/μL + • Molecular Weight: 6208 bp × 650 dalton/bp = 4.03 × 10⁶ g/mole + • Moles/μl: 1.07 μg/μL × 1 g/10⁶ μg × 1 / 4.03 × 10⁶ g/mole = 2.65 × 10⁻¹³ + moles/μL + • Molecules/μl: 2.65 × 10⁻¹³ moles/μL × 6.022145 × 10²³ molecules/mole = 1.59 + × 10¹¹ molecules/μL + • To obtain a solution at 2 × 10⁹ molecules/μL: 1.59 × 10¹¹ / 2 × 10⁹ = 79.8X + dilution + • Therefore we need to dilute 1.25 μL stock into 98.74 μL H₂O + + 💡 PRO TIP: Once a validated standard curve is obtained, make a small aliquot + of each standard (enough for 1 or 2 plates) and store at -20 °C. Once a + standard is thawed do not freeze it again but store at 4 °C and use within 1 + week. + + Keep track of the Ct value for each standard over time. They should remain + within 0.5 Ct of their initial value. If the Ct value of the standard starts + to drift, it's time to make a new one. + + When developing the assay multiple plasmids containing ITR were tested. + Plasmid #59462 is one plasmid that gave reliable and consistent results. Use + the recommended plasmid, or test multiple plasmids to find a suitable one. + + Some labs have reported better results when the plasmid is linearized. + +2. Treat the purified AAV samples with DNase I to eliminate any contaminating + plasmid DNA carried over from the production process (DNase does not penetrate + the virion). + + • 5 μL sample + 39 μL H₂O + 5 μL 10X DNase buffer + 1 μL DNase + • Gently mix sample (do not vortex) + • Incubate 30 min at 37 °C + • Transfer to ice + + ** Critical: do NOT treat your plasmid standard with DNase ** + +3. Make 6 serial dilutions, in duplicate, of your standard curve plasmid (2 × + 10⁹ stock made in step #1): + + Volume of 2 × 10⁹ stock | Volume of nuclease-free | Molecules per μL + or previous dilution | water (uL) | + (μL) | | + ------------------------|-------------------------|------------------ + 10 | 90 | 2 × 10⁸ + 10 of 2 × 10⁸ dilution | 90 | 2 × 10⁷ + 10 of 2 × 10⁷ dilution | 90 | 2 × 10⁶ + 10 of 2 × 10⁶ dilution | 90 | 2 × 10⁵ + 10 of 2 × 10⁵ dilution | 90 | 2 × 10⁴ + 10 of 2 × 10⁴ dilution | 90 | 2 × 10³ + + 💡 PRO TIP: To help stabilize the standards add carrier DNA to a final + concentration of 4 ug/mL to each standard dilution. + +4. Dilute DNase-treated and AAV reference samples according to the dilution + scheme in the table below: + + Dilution Series | Volume of sample | Volume of nuclease | Dilution | Total + | (uL) | free water (uL) | factor | dilution + ----------------|------------------|--------------------|----------|---------- + Dilution 1 | 5 uL AAV stock | 45 uL | 10X | 10X + (DNase step) | | | | + Dilution 2 | 5 uL Dil. 1 | 95 uL | 20X | 200X + Dilution 3 | 20 uL Dil. 2 | 80 uL | 5X | 1000X + Dilution 4 | 20 uL Dil. 3 | 80 uL | 5X | 5000X + Dilution 5 | 20 uL Dil. 4 | 80 uL | 5X | 25000X + Dilution 6 | 20 uL Dil. 5 | 80 uL | 5X | 125000X + Dilution 7 | 20 uL Dil. 6 | 80 uL | 5X | 625000X + Dilution 8 | 20 uL Dil. 7 | 80 uL | 5X | 3125000X + + Dilutions highlighted in green are the ones loaded onto the qPCR plate for + most samples. + + • If sample is expected to have a titer <1 × 10¹² GC/mL, use dilutions 3–6 + • If sample is expected to have a titer >3 × 10¹³ GC/mL, use dilutions 5–8 + + Note: at Addgene, samples typically range from 1 × 10¹² GC/mL to >2 × 10¹³ + GC/mL and we use an internal reference virus that is 1 × 10¹³ GC/mL. We + recommend always using a reference within 1-log of the expected titer. + + 💡 PRO TIPS: + • The quality of the sample dilution series is critical. Make sure to pipet + each dilution up and down at least 10 times, and use at least half of the + final volume (mix with >50 uL if your well contains 100 uL) + • Use a multichannel pipette to load the standards and samples onto the qPCR + plate + +5. Set up and load the 96-well plate: + • Load 5 μL of each standard in duplicate + • Load 5 μL of each sample in duplicate. Do not forget to include a no + template control (NTC = master mix + water). + • Add 15 μL of Master Mix per well and mix well by pipetting back and forth + at least 5 times. + • Seal plate with transparent film. + • Centrifuge at 3,000 rpm for 2 min to bring the sample to the bottom of the + tube. + +6. Run the following protocol in your qPCR instrument using SYBR detection: + + 98 °C 3 min / 98 °C 15 sec / 58 °C 30 sec / read plate/ repeat 39x from step + 3 / melt curve + +7. Perform data analysis using the instrument's software. Determine the physical + titer of samples (viral genomes (vg)/mL) based on the standard curve and the + sample dilutions. + + 💡 PRO TIP: Make sure that the qPCR is valid by checking to the following: + • Standard curve: R² (coefficient of correlation) ~ 1.0, E (efficiency of PCR) + ~100% (90%–110% range is acceptable) + • Baseline removal: all samples will have some small amount of background + signal that is most evident during initial PCR cycles. This background + signal must be removed to accurately determine differences between samples. + • Melt curve analysis: a single peak should be seen. The presence of a second + peak at a temperature of ~70–75 °C usually indicates the presence of primer + dimers which can increase background signal and alter the Ct values of your + samples. + • Quality of your standard curve: you should observe differences in Ct values + that make sense for your dilutions (~3.3 difference Ct for a 10-fold dilution + is appropriate). + • Quality of duplicates: Exclude duplicates from analyses if there is more than + a 0.5 Ct difference between them. + + +SAMPLE DATA +================================================================================ + +Example of a valid 8-point standard curve. + +Example of the amplification plots obtained from an AAV sample. Each curve +represents a dilution. + + +REFERENCES +================================================================================ + +Aurnhammer C, Haase M, Muether N, Hausl M, Rauschhuber C, Huber I, Nitschko H, +Busch U, Sing A, Ehrhardt A, Baiker A. Universal real-time PCR for the detection +and quantification of adeno-associated virus serotype 2-derived inverted +terminal repeat sequences. Hum Gene Ther Methods. 2012 Feb;23(1):18-28. PMID: +22428977 diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ AAV ddPCR Titration.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ AAV ddPCR Titration.txt new file mode 100644 index 0000000000000000000000000000000000000000..12dbeb0c3b8dd715fd7493f9ae5b89b2e49e546b --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ AAV ddPCR Titration.txt @@ -0,0 +1,318 @@ +PROTOCOL: AAV ddPCR Titration +SOURCE: https://www.addgene.org/protocols/aav-ddpcr-titration/ +================================================================================ + +INTRODUCTION +================================================================================ + +This protocol describes how to use droplet digital PCR (ddPCR) to titer purified +recombinant Adeno-associated viral vectors (AAV). This protocol specifically uses +primers and probes targeting the ITR elements in the viral vectors but can be +modified for other targets. The dilution series outlined in this protocol are +based on an AAV titer range of 5E+12–5E+13 GC/mL, where GC is genome copies and +generally represents the physical number of viral particles. Users may need to +run lower or higher dilutions depending on their particular sample. For +additional tips on AAV titering using ddPCR, read this blog post on ddPCR for +AAV quantification. + +This protocol was modified from the publication Lock et al. (2014). + + +BEFORE STARTING +================================================================================ + +• To reduce the risk of contaminating reagents we recommend making small aliquots + of master mixes, primers, and probes prior to use. + +• Thaw the master mix, primers, and probe on ice before use. + +• Wipe down all pipettes and surfaces with 10% bleach. + + +SAFETY WARNINGS +================================================================================ + +AAV is generally considered biosafety level 1 but may require BSL-2 handling +depending on the insert. Please ensure that you are in compliance with your +institution's biosafety regulations. + + +EQUIPMENT +================================================================================ + +• Class II, Type A2 Biological Safety Cabinet, Labconco 302411100 +• Droplet Digital PCR System, Bio-Rad, DX200 +• Thermal Cycler, Bio-Rad, T100 +• PCR Plate Sealer, Bio-Rad, PX1 +• 1–10 µL single channel pipette +• 20–200 µL single channel pipette +• 200–1000 µL single channel pipette +• 1–10 µL multichannel pipette +• 2–50 µL multichannel pipette +• 20–200 µL multichannel pipette +• Vortex, VWR, 10153-688 +• Mini Centrifuge, Thermo Scientific, 10199-452 +• Ice bucket +• 96-well freezer blocks (x 3) + + +REAGENTS +================================================================================ + +• Molecular Biology Grade Water, Hyclone, SH30538.02 +• GeneAmp 10X PCR Buffer, Applied Biosystems, N8080129 +• ddPCR Supermix for Probes no dUTP, Bio-Rad,1863023 +• 10% Poloxamer 188, Thermo Fisher, 24040032 +• Droplet generation oil, Bio-Rad, 1863005 +• DG8 cartridge, Bio-Rad, 1864008 +• DG8 gasket, Bio-Rad, 1863009 +• DG8 cartridge holder, Bio-Rad, 1863051 +• 8-strip PCR tubes, Axygen, PCR-02-FCP-C +• ddPCR 96-well PCR plates, Bio-Rad, 12001925 +• 48-well dilution plate, Bio-Rad, MLL4801 +• Pierceable Foil Heat Seal, Bio-Rad, 1814040 +• Microseal adhesive seal, Bio-Rad, MSB1001 +• Polystyrene Reservoirs, VWR, 89094-662 +• Microcentrifuge tubes, VWR, 87003-294 + +Primers/probe targeting ITR: +• ITR Forward Primer: 5'-CGGCCTCAGTGAGCGA +• ITR Reverse Primer: 5'-GGAACCCCTAGTGATGGAGTT +• ITR Probe: -FAM-CACTCCCTCTCTGCGCGCTCG-BBQ- + + +REAGENT PREPARATION +================================================================================ + +1X PCR Buffer containing 0.05% Poloxamer 188: + +Prepare immediately before use and vortex before using. + +• 500 µL of GeneAmp 10X Buffer +• 25 µL of 10% Poloxamer 188 +• 4475 µL Molecular Biology Grade Water + + +PROCEDURE +================================================================================ + +Preparation + +1. Before handling any viruses, get materials ready. + +2. Ensure that primers, probe, 10X PCR buffer, and master mix are thawed. + +3. Vortex primers, probe and master mix for 15 sec then spin 10 sec in a mini + centrifuge and place on ice. + +4. Wipe down a DG8 cartridge holder with bleach and place in the Biological + Safety Cabinet (BSC). + +5. Make sure that the BSC to be used for dilution and the BSC to be used for + droplet generation are supplied with sufficient pipette tips and reagent + reservoirs. + + 💡 PRO TIP: Prepare the viral dilutions in a separate biological safety + cabinet (dilution BSC) than that used for master mix preparation and droplet + generation (droplet generation BSC) to ensure no contamination of the PCR + reagents and the NTC with virus. + +6. Pre-warm the 96-well plate sealer by gently touching the screen. + +Prepare the Serial Dilution + +1. Place a 48-well dilution plate in a chilled 96-well freezer block and place in + the dilution BSC. + +2. Prepare 1X dilution buffer (see recipe above). + +3. Save ~25 µL of 1X dilution buffer in a microcentrifuge tube to be used as + the NTC. + +4. Pour the 1X dilution buffer into a polystyrene reagent reservoir. + +5. Using a 20–200 µL multichannel pipette, carefully add the dilution buffer to + the dilution plate according to the dilution scheme listed in step 13. + +6. Use a single channel 1–10 µL pipette to add 5 µL of each viral sample to + Dilution 1 in the 48-well dilution plate and pipette 5–10 times to mix. + +7. Dilute the virus as follows: Mix dilutions thoroughly, but pipette slowly to + avoid generating aerosols. Be sure to change tips each time. + + • Dilution 1 (20X): 5 µL in 95 µL 1X PCR buffer (1:20) + • Dilution 2 (20X): 5 µL in 95 µL 1X PCR buffer (1:400) + • Dilution 3 (20X): 5 µL in 95 µL 1X PCR buffer (1:8,000) + • Dilution 4 (20X): 5 µL in 95 µL 1X PCR buffer (1:160,000) + • Dilution 5 (20X): 5 µL in 95 µL 1X PCR buffer (1:3,200,000) + • Dilution 6 (2X): 50 µL in 50 µL 1X PCR buffer (1:6,400,000) + • Dilution 7 (2X): 50 µL in 50 µL 1X PCR buffer (1:12,800,000) + • Dilution 8 (2X): 50 µL in 50 µL 1X PCR buffer (1:25,600,000) + +8. Use multichannel pipettes for the dilution series. + • For dilutions 1–5, use the 1–10 µL multichannel pipette set to 5 µL. + • For dilutions 6–8, use the 20–200 µL multichannel pipette set to 50 µL. + • For mixing between dilutions, use the 20–200 µL multichannel pipette set to + 90 µL and mix by pipetting the liquid up and down 10–20 times. + +9. Gently cover the entire dilution plate with Microseal adhesive seal - do not + press the film, just gently cover so nothing falls into the plate. + +10. Leave dilutions on the chilled 96-well freezer block in the BSC until ready + to use. + +Prepare the Master Mix + +1. Place a ddPCR plate onto a chilled 96-well freezer block and set aside in the + droplet generation BSC to cool. + +2. Prepare the ITR master mix in a microcentrifuge tube as shown below. For 8 + samples prepare enough master mix for 9 samples. + + ITR Master Mix: + + Component | Volume | 9X Volume | Final Concentration + ---------------------------------|--------|-----------|-------------------- + 2X ddPCR Supermix for Probes, | 10 µL | 90 µL | 1X + no dUTP | | | + 10 µM ITR probe (FAM) | 0.5 µL | 4.5 µL | 250 nM + Forward ITR Primer (10 µM) | 1.8 µL | 16.2 µL | 900 nM + Reverse ITR Primer (10 µM) | 1.8 µL | 16.2 µL | 900 nM + Nuclease-free water | 5.9 µL | 71.55 µL | + Total Volume | 20 µL | | + +3. Vortex the master mix for 15 sec and spin in a mini centrifuge for 10 sec + before use. + +4. Place an 8-well PCR tube strip into a chilled 96-well freezer block. + +5. Add 20 µL of the master mix to each PCR tube. Be careful to dispense to the + bottom of the tube without collecting drops along the side of the tube. + +6. Cap gently - do not push the cap in all the way, just ensure the samples are + covered. + +7. Bring the PCR tubes to the BSC used for dilutions. + +8. Without disturbing the liquid in the tube, gently uncap the PCR tubes. + +9. Add 5 µL of dilutions 6–8 to the appropriate PCR tubes. Pipette back and + forth 5 times. + +10. Lightly cap the PCR tubes. + +Generate the Droplets + +1. Bring the PCR tubes to the droplet generation BSC. + +2. Without disturbing the liquid in the tube, gently uncap the tubes. + +3. Add 5 µL of the previously aliquoted 1X dilution buffer from step 9 to the + NTC tube. + +4. Place a DG8 cartridge into the cartridge holder. + +5. Using a 2–50 µL multichannel pipet, load 20 µL of the reaction mixtures into + the middle wells of the cartridge. + +6. Add 800 µL of droplet generation oil to a polystyrene reagent reservoir. + +7. Using the 20–200 µL multichannel pipet, load 70 µL of droplet generation oil + into the bottom row of wells. + +8. Cover the cartridge with the DG8 gasket, making sure that it is secure. + +9. Transfer the cartridge holder to the droplet generator. Close the lid and wait + for the droplets to be generated. + +10. Once the droplets have been generated, use a 20–200 µL multichannel pipet to + aspirate 40 µL of droplets. + + 💡 PRO TIP: To ensure that the droplets are not disrupted, insert the pipette + tips directly in the center of the well and tilt to a 45° angle. Count to 20 + while slowly and gently aspirating the droplets. + +11. Transfer the droplets to a prechilled PCR plate. + + 💡 PRO TIP: To ensure that the droplets are not disrupted insert the pipette + tips and gently touch the bottom of the well. Lift the tips ~1 mm. Touch the + side of the well and tilt the pipette tips at a 45° angle. Count to 20 while + slowly and gently dispensing the droplets down the side of the tube. + +12. Place a Pierceable Foil Heat Seal on the PCR plate with the red line facing + up. If the plate sealer is not at temperature, touch the screen on the plate + sealer to allow it to get to temperature. Once the temperature is reached, + place the PCR plate with the foil onto the metal support block. Place the + block in the plate sealer and press the 'Seal' button. + +13. After the plate has been sealed, proceed to thermocycling. + +Thermal Cycling + +Run the following PCR parameters: + +Cycling Step | Temperature (°C) | Time (min) | Ramp Rate (°C/sec) | # Cycles +----------------------|------------------|------------|-------------------|---------- +Denaturation | 95 | 10 | 2 | 1 +Denaturation | 95 | 0.5 | 2 | 50 +Annealing/Extension | 60 | 1 | 2 | 50 +Signal Stabilization | 98 | 10 | 2 | 1 +Hold | 4 | ∞ | 2 | 1 + +After PCR is complete, transfer the plate to the Droplet Reader. + +1. Open the QuantaSoft software to set up a new plate layout. Designate the + sample name, experiment type, supermix type (ddPCR Supermix for Probes), the + target names and target types. + +2. When the plate layout is complete, select 'Run' to begin the droplet reading. + +3. When the droplet reading is complete, export the data from all wells as a CSV + file and use the following equation to calculate the titer for each sample: + + T = (R × C × D × 1000) / V + + Where: + • T = Titer, GC/mL + • R = Reaction volume (20 µL) + • C = Copies/µL + • D = Dilution factor of virus + • V = Volume of virus in reaction mix (4 µL) + + +SAMPLE DATA +================================================================================ + +When analyzing data there should be a clear distinction between negative droplets +(black) and positive droplets (blue). + +The no template control (NTC) should be close to zero (B08). At Addgene, we +consider runs with an NTC > 10 to be invalid. + +To reduce NTC values, we recommend wiping down all pipettes and equipment with +10% bleach prior to use and keeping all reagents and samples on ice or +pre-chilled 96-well freezer blocks during use. + +In this protocol, a dilution series is prepared for each AAV sample, and the +three final dilutions are assayed. The samples that are assayed are diluted +2-fold serially, therefore the concentration obtained by ddPCR should decrease by +a factor of 2 across the dilutions. + +In the example below, 2-fold serial dilutions of a sample were loaded in wells +A04, A05 and A06. As shown in the image (Figure 1) and table below, the +concentration of positive droplets decreases by a factor of ~2. + +To increase the accuracy of the titer, take the average of several measurements. + +Example dilutions and titrations: + +Sample | Dilution | Concentration | Titer (GC/mL) | Average Titer (GC/mL) +------------|----------|---------------|---------------|---------------------- +AAV Sample 1| 6400000 | 965 | 3.09E+13 | 3.2E+13 +AAV Sample 1| 12800000 | 474 | 3.03E+13 | +AAV Sample 1| 25600000 | 271 | 3.47E+13 | +NTC | N/A | 2.5 | N/A | N/A + +For additional tips on AAV titering using ddPCR, read our blog post. + +Last reviewed on: August 31, 2023 diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Affinity Purification of Recombinant Antibodies with Protein A or Protein G.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Affinity Purification of Recombinant Antibodies with Protein A or Protein G.txt new file mode 100644 index 0000000000000000000000000000000000000000..9a87b9856389ce65baa64f3b19b4e9028b41bc35 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Affinity Purification of Recombinant Antibodies with Protein A or Protein G.txt @@ -0,0 +1,310 @@ +PROTOCOL: Affinity Purification of Recombinant Antibodies with Protein A or Protein G +SOURCE: https://www.addgene.org/protocols/affinity-purification-recombinant-antibodies/ +================================================================================ + +INTRODUCTION +================================================================================ + +This protocol describes how to affinity purify recombinant antibodies from cell +culture supernatant using Protein A or Protein G columns. + +Last Update: February 7, 2022 + + +SAFETY WARNINGS +================================================================================ + +Sodium azide is toxic. When handling, use proper personal protective equipment +including laboratory coat, laboratory goggles, and gloves. Sodium azide containing +waste should be properly disposed of following your institution's hazardous waste +procedures. + + +WORKFLOW TIMELINE +================================================================================ + +Day 1: Purify antibody + +Day 2 or later: Buffer exchange + + +EQUIPMENT +================================================================================ + +• Class II, Type A2 Biological Safety Cabinet +• 4 °C Refrigerator +• Pipette controller +• Benchtop centrifuge compatible with 50 mL conical tubes +• NanoDrop spectrophotometer +• 37 °C, 5% CO₂ incubator with shaking platform set to 120 rpm +• 37 °C bead bath +• Clamp stand and clamps +• Autoclave +• 0.1–1 mL single channel pipette +• 0.5–10 µL single channel pipette +• 20–200 µL single channel pipette +• 2–20 µL single channel pipette + + +REAGENTS +================================================================================ + +• Aspirating pipette, VWR 414004-265 +• 5 mL pipette, VWR 89130-896 +• 10 mL pipette, VWR 89130-898 +• 25 mL pipette, VWR 89130-900 +• 50 mL pipette, VWR 89130-902 +• 50 mL conical tubes, VWR 89039-656 +• Microcentrifuge tubes, VWR 89126-724 +• Filtering system 0.2 µm PES, VWR 431098 +• Sodium phosphate monobasic monohydrate, Millipore Sigma 71507-250G +• Sodium phosphate dibasic, Millipore Sigma S7907-500G +• 1 M Trizma hydrochloride solution pH 9.0, Millipore Sigma T2819-1L +• 250 mL sterile bottle, VWR 430281 +• 0.45 µm PES complete filtration unit, 500 mL, rapid-flow, VWR 73520-984 +• Syringes, 30 mL, VWR BD302832 +• Filter, 0.2 µm (luer-lock), VWR 431229 +• IgG Elution Buffer, Thermo Fisher 21028 +• Protein G GraviTrap columns, Cytiva 28-9852-55 or rProtein A GraviTrap + columns, Cytiva 28-9852-54 +• LabMate PD10 Buffer Reservoir, Millipre Sigma GE18-3216-03 +• 5% Sodium Azide, 500 mL, VWR 7144.8-16 +• PBS, 1X pH 7.4, VWR 45000-446 +• Benzamide, Millipore Sigma 12072 +• Antipain, Millipore Sigma 10791 +• Leupeptin, Millipore Sigma L2884 +• Aprotinin, Millipore Sigma A6279 +• Zeba Spin Desalting Columns, 7 kDa MWCO, 10 mL, Thermo Fisher 89893 +• Amicon Ultra-15 30 kDa MWCO column, Millipore Sigma UFC903024 +• 50 mL LoBind tubes, VWR 76289-498 + + +BEFORE STARTING +================================================================================ + +• Wipe down all pipettes and equipment with 10% bleach prior to use. + +• Warm the affinity column, binding buffer, and elution buffer to room + temperature (RT) before use. + + +REAGENT PREPARATION +================================================================================ + +1 M sodium phosphate monobasic monohydrate (NaH₂PO₄∙H₂O), pH 7.0: + +• 138 g NaH₂PO₄∙H₂O +• 1 L deionized water +• Adjust pH to 7.0 +• Autoclave or filter sterilize + +1 M sodium phosphate dibasic (Na₂HPO₄), pH 7.0: + +• 142 g of Na₂HPO₄∙H₂O +• 1 L deionized water +• Adjust pH to 7.0 +• Autoclave or filter sterilize + +1 M of sodium phosphate buffer, pH 7.0: + +• 390 mL of sterile sodium phosphate monobasic monohydrate (NaH₂PO₄∙H₂O) +• 610 mL of sterile sodium phosphate dibasic (Na₂HPO₄) +• Store up to 1 month at 4 °C +• Adjust pH to 7.0 +• Autoclave or filter sterilize + +Protein A/G binding buffer (20 mM sodium phosphate buffer, pH 7.0): + +• 20 mL 1M sodium phosphate buffer +• 980 mL of deionized water +• Adjust pH to 7.0 +• Autoclave or filter sterilize + +1000X protease inhibitor cocktail: + +• 25 mg leupeptin +• 50 mg antipain +• 250 mg benzamidine +• 25 mL of 2 mg/mL aprotinin +• Mix well and sterilize through a 0.2 µm PES filter. +• Aliquot and freeze upright at -20 °C + + +PROCEDURE +================================================================================ + +Section 1: Affinity chromatography + +1. Equilibrate filtered tissue culture supernatant containing the recombinant + antibody to room temperature (see Transfection for Recombinant Antibody + protocol). + + 💡 PRO TIP: Add protease inhibitors to 1X if this has not already been done. + We typically start with about 250 mL of supernatant and add 250 µL of 100X + protease inhibitor cocktail. + +2. Add 1 part Protein A/G binding buffer to 1 part tissue culture supernatant + and mix well. + +3. Uncap the Protein G Gravitrap or rProtein A Gravitrap columns and gently pour + off the ethanol storage buffer. + +4. Tightly attach LabMate PD10 Buffer Reservoirs to the top of the Gravitrap + column. + + 💡 PRO TIP: Gravitrap columns have a finite binding capacity. If your sample + exceeds the capacity, divide the sample among multiple columns. For + information about the total binding capacity for your columns, refer to the + manufacturer's instructions. + +5. Attach the Gravitrap column to a clamp on a clamp stand. + +6. Use scissors to cut the bottom of the Gravitrap column at the indentation in + the tip. + +7. Equilibrate the column with 10 mL of RT Protein A/G binding buffer. + +8. Collect the flow-through in a 50 mL conical tube and dispose after use. + +9. Carefully pour the filtered and diluted cell culture supernatant into the + Gravitrap column. + +10. Collect the flow through in a 250 mL bottle. + +11. Repeat steps 9–10 such that the supernatant passes through the column a total + of 2x. + + 💡 PRO TIP: This will ensure depletion of the recombinant antibody from the + supernatant. + +12. Wash the column with 25 mL of Protein A/G binding buffer 2x. + +13. Add 50 µL of 1 M Trizma hydrochloride pH 9.0 to 10 microcentrifuge tubes. + +14. Cap the Gravitrap columns at the bottom. + +15. Add 5 mL of Pierce IgG Elution Buffer to the capped Gravitrap column and + incubate for 10 min at RT. + +16. Uncap the column and collect 500 µL fractions into the tubes containing 50 µL + 1 M Trizma hydrochloride pH 9.0. + +17. Cap the tubes and vortex for 5 s to mix. + +18. Determine the protein concentration of each fraction on the NanoDrop + Spectrophotometer using the A280 IgG setting. + +19. Combine all eluates with measurable protein. + +20. Determine the protein concentration of the pooled sample on the NanoDrop + Spectrophotometer using the A280 IgG setting. + +21. If the concentration of the pooled sample is above 1.0 mg/mL proceed to Option + 1 with a buffer exchange using a Zeba Spin 7 kDa MWCO desalting column. + +22. If the concentration of the pooled sample is below 1.0 mg/mL proceed to + Option 2 with a buffer exchange/concentration using an Amicon 30 kDa MWCO buffer + exchange column. + +23. (Optional) Regenerate the column by washing with 25 mL of Protein A/G binding + buffer and store in 20% ethanol at 4 °C. + + 💡 PRO TIP: Columns may be re-used up to 5x when purifying the same + recombinant antibody. + +Section 2: Buffer exchange + +Choose Option 1 or Option 2 based on the concentration of the pooled sample above. + +Option 1: Buffer exchange using a desalting column + +The 10 mL Zeba Spin Desalting Columns can accommodate up to 4 mL of recombinant +antibody sample. + +💡 PRO TIP: If the volume of the sample is greater than 4 mL, then divide it into +2 columns. + +1. Twist off the 10 mL Zeba Spin Desalting Column's bottom closure and loosen cap. + +2. Place column in a 50 mL conical collection tube. + +3. Centrifuge column at 1000 x g for 2 min to remove storage solution. + +4. Place a mark on the side of the column where the compacted resin is slanted + upward. Place column in centrifuge with the mark facing outward in all + subsequent centrifugation step + + 💡 PRO TIP: Resin will appear compacted after centrifugation. + +5. Discard the flow through into a waste container. + +6. Add 5 mL PBS to the column. + +7. Centrifuge at 1000 x g for 2 min to remove PBS. + +8. Repeat Steps 6–7 3x, discarding buffer from the collection tube each time. + +9. Place column in a new 50 mL LoBind collection tube. + +10. Slowly apply the sample to the center of the compact resin bed. + + 💡 PRO TIP: For sample volumes <1.5 mL top off the sample with 0.2 mL PBS to + aid protein recovery. + +11. Allow the resin bed to fully absorb the sample. + +12. Centrifuge at 1000 x g for 2 min to collect the sample. + +13. Discard column after use. + +14. Determine antibody concentration on the NanoDrop Spectrophotometer. + +15. Dilute antibody to 1 mg/mL with PBS if needed. + +16. For long term storage, add sterile sodium azide to 1 mM. + +Option 2: Buffer exchange and concentration with an Amicon column + +1. Apply 15 mL of PBS to the reservoir of a Amicon Ultra-4 30 kDa MWCO column. + +2. Incubate for 10 min at RT. + +3. Centrifuge at 3100 x g for 8 min. + +4. Discard the flow through into a waste container. + +5. Add the recombinant antibody sample to the reservoir of the column. + +6. Fill the remaining space in the column with PBS and pipette several times to + mix. + +7. Centrifuge at 3100 x g for 8 min. + +8. Discard the flow through into a waste container. + +9. Repeat steps 5-8 at least 4 additional times to ensure a full buffer exchange. + +10. Discard the flow through into a waste container. + +11. Fill the remaining space in the column with PBS and pipette several times to + mix. + +12. Centrifuge at 3100 x g for 8 min. + +13. Remove a small aliquot of your sample from the filter reservoir to check the + concentration on the NanoDrop Spectrophotometer to see if the sample has + reached the desired concentration. + +14. If the sample concentration is still too low, repeat the centrifugation until + the volume of the sample is reduced enough to reach the desired concentration. + + 💡 PRO TIP: Periodically check the concentration on the NanoDrop + Spectrophotometer to see if the sample has reached the desired concentration. + +15. Gently transfer the sample from the reservoir to a LoBind tube. + + 💡 PRO TIP: Do not scrape the filter with the pipette tip. + +16. Determine the concentration of the sample on the NanoDrop Spectrophotometer. + +17. For long term storage, add sterile sodium azide to 1 mM. diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Antibody Validation Using the Indirect ELISA Method.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Antibody Validation Using the Indirect ELISA Method.txt new file mode 100644 index 0000000000000000000000000000000000000000..2fe7e49cd410f370e6a57ff5d8e2c684e6d20b2d --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Antibody Validation Using the Indirect ELISA Method.txt @@ -0,0 +1,280 @@ +PROTOCOL: Antibody Validation Using the Indirect ELISA Method +SOURCE: https://www.addgene.org/protocols/ab-validation-indirect-elisa/ +================================================================================ + +INTRODUCTION +================================================================================ + +This protocol describes how to run an indirect Enzyme-Linked ImmunoSorbent Assay +(ELISA) against a purified antigen to validate an antibody. This protocol will +describe how to create a standard curve using known concentrations of the antigen +and how to probe with an antibody against the target to show a dose response. + + +GENERAL CONSIDERATIONS +================================================================================ + +The ELISA can be completed in a single day or broken up over several days by +incubating certain steps at 4 °C instead of room temperature or 37 °C. The +protocol notes when there are different incubation options available. + +Caution: Use the Stop Solution in a well ventilated area and avoid breathing in +the vapors. + + +WORKFLOW TIMELINE +================================================================================ + +Day 1: Antigen Coating + +Day 2: Blocking + +Day 3: Primary antibody incubation + +Day 4: Secondary antibody incubation and plate read + + +EQUIPMENT +================================================================================ + +• Spectrophotometer compatible with 96-well plates +• 1–10 µL single channel pipette +• 2–20 µL single channel pipette +• 20–200 µL single channel pipette +• 200–1000 µL single channel pipette +• 20–200 µL multichannel pipette +• Multichannel pipette reagent reservoirs +• Pipette controller +• Microcentrifuge +• Microplate shaker +• ELISA plate washer (optional) +• Scale +• Microsoft Excel or similar software + + +REAGENTS +================================================================================ + +• Purified antigen +• Purified recombinant antibody +• Isotype control antibody +• HRP-conjugated isotype-specific secondary antibody +• ELISA 96-well microplate, Corning 9018 +• Bovine serum albumin (BSA), VWR 10273-264 +• 50 mL conical tubes, VWR 89039-656 +• 96-well polyester (clear) microplate seal, Thermo Scientific 5701 +• Microcentrifuge tubes, Neptune 3745.X +• Pipette tips, 1000 µL, VWR 76322-154 +• Pipette tips, 10 µL, VWR 76322-132 +• Pipette tips, 200 µL, VWR 76322-150 +• Pipette tips, 20 µL, VWR 76322-134 +• Pipettes, 10 mL, VWR 89130-898 +• 1 L polystyrene bottle, Corning 430518 +• PBS, 1X pH 7.4, VWR 45000-446 +• TMB (3,3',5,5'-tetramethyl-[1,1'-biphenyl]-4,4'-diamine) substrate kit, Pierce + 34021 +• Tween-20, VWR 0777-1L +• Foil + + +BEFORE STARTING +================================================================================ + +Warm reagents to room temperature. + + +PROCEDURE +================================================================================ + +Section 1: Prepare the Antigen Standard and coat the plate + +1. Dilute purified antigen to 20 ng/µL in a microfuge tube and vortex. + + 💡 PRO TIP: You may need to try a few different concentrations of antigen to + determine the ideal concentration. + +2. Prepare serial dilutions of the purified antigen as follows: + • 2 ng/µL: Add 100 µL of 20 ng/µL stock into 900 µL PBS in a microfuge tube + and vortex. + • 1 ng/µL: Add 450 µL of 2 ng/µL stock into 450 uL PBS in a microfuge tube and + vortex. + • 0.5 ng/µL: Add 450 µL of 1 ng/µL stock into 450 µL PBS in a microfuge tube + and vortex. + • 0.25 ng/µL: Add 450 µL of 0.5 ng/µL stock into 450 µL PBS in a microfuge tube + and vortex. + • 0.125 ng/µL: Add 450 µL of 0.25 ng/µL stock into 450 µL PBS in a microfuge + tube and vortex. + • 0 ng/µL: 450 µL PBS only. + +3. Pipette 50 µL into the first three wells of each row, using a different + standard solution for each row of a 96-well ELISA microplate. + +4. Cover the plate with a 96-well plate seal and incubate at 37 °C for 30 min, + or overnight at 4 °C. + +Section 2: Block the plate + +1. Prepare the wash buffer (0.05% Tween-20 in PBS) as follows: + • Pipette 0.5 mL of Tween-20 to into 999.5 mL 1X PBS + • Cap the bottle and invert several times to mix. + +2. Carefully remove the plate seal from the 96-well plate and set aside. + +3. Aspirate the wells and use a multichannel pipette to add 200 µL wash buffer to + each well. Washing can be done by hand but if available, use an automated ELISA + plate washer. + +4. Seal the plate. + +5. Place the plate on a microplate shaker set at 400 rpm and shake for 1 min. + +6. Repeat steps 3–5 twice for a total of three washes. + +7. After the final wash, aspirate the wash buffer from the wells. + +8. Prepare the blocking buffer (1% BSA in PBS) as follows: + • Add 250 mg of BSA to 25 mL of PBS. + • Cap the tube and invert several times to mix. + +9. Using a multichannel pipette, add 200 µL of blocking buffer to each well. + +10. Cover the plate with a plate seal and incubate on a microplate shaker set to + 400 rpm for 2 h at room temperature or overnight at 4 °C. + +Section 3: Primary antibody incubation + +1. Carefully remove the plate seal from the 96-well plate and set aside. + +2. Aspirate the wells and use a multichannel pipette to add 200 µL wash buffer to + each well. Washing can be done by hand but if available, use an automated ELISA + plate washer. + +3. Seal the plate. + +4. Place the plate on a microplate shaker set at 400 rpm and shake for 1 min. + +5. Repeat steps 2–4 twice for a total of three washes. + +6. After the final wash, aspirate the wash buffer from the wells. + +7. Prepare antibody dilution buffer (0.1% BSA in PBS) as follows: + • Dilute 50 mg BSA into 50 mL PBS. + • Cap the tube and invert several times to mix. + +8. Dilute the primary antibody and an isotype control antibody to the desired + concentrations in the antibody dilution buffer. + + 💡 PRO TIP: The ideal antibody concentration will vary and needs to be + empirically determined. We suggest starting with three concentrations between + 1–10 µg/mL. + +9. Cap and invert the tubes several times to mix. + +10. Using a multichannel pipette, add 100 µL of primary antibody solution to the + appropriate wells. + +11. Cover the plate with a plate seal and incubate on a microplate shaker set to + 400 rpm for 2 h at room temperature or overnight at 4 °C. + +Section 4: Secondary antibody incubation + +1. Carefully remove the plate seal from the 96-well plate and set aside. + +2. Aspirate the wells and use a multichannel pipette to add 200 µL wash buffer to + each well. Washing can be done by hand but if available, use an automated ELISA + plate washer. + +3. Seal the plate. + +4. Place the plate on a microplate shaker set at 400 rpm and shake for 1 min. + +5. Repeat steps 2–4 twice for a total of three washes. + +6. After the final wash, aspirate the wash buffer from the wells. + +7. Dilute the HRP-conjugated isotype-specific secondary antibody to the desired + concentrations in the antibody dilution buffer. + +8. Cap and invert the tube several times to mix. + +9. Using a multichannel pipette, add 100 µL of secondary antibody to each well. + +10. Cover the plate with a plate seal and incubate on a microplate shaker set to + 400 rpm for 2 h at room temperature or overnight at 4 °C. + +Section 5: TMB reaction + +1. Carefully remove the plate seal from the 96-well plate and set aside. + +2. Aspirate the wells and use a multichannel pipette to add 200 µL wash buffer to + each well. Washing can be done by hand but if available, use an automated ELISA + plate washer. + +3. Seal the plate. + +4. Place the plate on a microplate shaker set at 400 rpm and shake for 1 min. + +5. Repeat steps 2–4 twice for a total of three washes. + +6. After the final wash, aspirate the wash buffer from the wells. + +7. Immediately before use, mix 5 mL TMB Solution and 5 mL Peroxide Solution from + the TMB substrate kit. + +8. Cap the tube and invert several times to mix. + +9. Using a multichannel pipette, add 100 µL of the TMB/Peroxide mix to each well. + +10. Cover the plate with a plate seal and wrap in foil. + +11. Incubate plate at room temperature on a microplate shaker set at 400 rpm for + 15–30 min. + + 💡 PRO TIP: Check the plate periodically to determine when the desired color + change has occurred. The color will change from yellow to blue and generally + takes between 15 to 30 min. High concentrations of HRP yield a greenish + solution. Stop the reaction before any wells display a green product. A + precipitated product indicates the presence of too much HRP and the need to + optimize experimental conditions. + +12. When the desired color change has occurred, gently remove the plate seal. + +13. Using a multichannel pipette, add 100 µL of TMB Stop Solution directly to the + wells to stop the reaction. + +14. Measure the absorbance of each well at 450 nm on the spectrophotometer. Use the + spectrophotometer to generate a standard curve. If you don't see any color + change or dose response, your antibody concentration may have been too low. In + this case, use higher antibody concentrations. If the reaction is saturated and + you don't see any dose response, your antibody concentration may have been too + high. In this case, use lower antibody concentrations. The ideal range of the + standard curve will vary between targets and needs to be empirically determined. + The dilution series created in section 1, step 2 is a suggested starting point. + If your unknown sample's absorbance falls above the range of the standard curve + you will need to either include higher concentrations in the standard curve or + dilute the unknown sample (don't forget to factor in that dilution when + calculating the original sample concentration!). + + +TIPS AND TROUBLESHOOTING +================================================================================ + +• The optimal concentration of primary antibody to use will vary and needs to be + empirically determined. If possible, run an initial test with serially diluted + primary antibody and determine the best concentration for your assay. + +• Washing steps can be done by hand but if available, use an automated ELISA plate + washer. + + +SAMPLE DATA +================================================================================ + +The plate was coated with serial dilutions of human recombinant purified Desmin +(blue) or a negative control protein, Apolipoprotein L3 (red) overnight, +blocked, and incubated overnight with Anti-Desmin [D7]. Plates were incubated with +HRP-linked anti-Human IgG secondary antibody for 2 hours, reacted with TMB +substrate and the reaction stopped after 15 minutes. Absorbance was read at 450 nm +and plotted against the micrograms of antigen loaded. + +Last reviewed on: October 8, 2024 diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ CRISPR Library Amplification.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ CRISPR Library Amplification.txt new file mode 100644 index 0000000000000000000000000000000000000000..4027b74d6164dcd91eb99758d43dc3331bb26c5b --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ CRISPR Library Amplification.txt @@ -0,0 +1,330 @@ +PROTOCOL: CRISPR Library Amplification +SOURCE: https://www.addgene.org/protocols/pooled-library-amplification/ +================================================================================ + +INTRODUCTION +================================================================================ + +Please refer to our pooled library material pages for amplification protocols that +have been developed by the depositor for a specific pooled library available at +Addgene. We recommend following the depositor's specific protocol if one is +available. If a pooled library does not yet have an amplification protocol, the +following protocol can be used as a starting point for CRISPR libraries. + +This protocol allows the amplification of a pooled-plasmid library in +Escherichia coli cells. Pooled libraries contain tens to millions of different +plasmids in a single sample. They are often used for screening, barcoding, or +other high throughput multiplexed experiments. These pooled plasmids differ by +only a short region of DNA: guide RNAs targeting different genes in an organism's +genome, for example. + +Amplification is usually necessary to produce sufficient quantities of library for +experimental applications. Repeated amplifications should be avoided as best as +possible due to the inherent possibility of altering the composition of the +library. Bottlenecks, fitness differences, and plasmid recombination can all +impact the representation of individual plasmids in the pooled library during +amplification. This protocol is designed to be as general as possible but note +that individual libraries may require modifications dictated by the originating +laboratory for optimal results. If you obtained the pooled library from Addgene, +these protocols can be found on the Pooled Library page for the specific library. + +This protocol assumes familiarity with standard bacterial transformation and +basic knowledge of the library being amplified. Please see our protocol on +Bacterial Transformation. The generalized pooled library amplification protocol +is expected to obtain satisfactory results for libraries up to 200,000 individual +plasmids and can be scaled according to the actual number. + + +REQUIRED QUALITY CONTROL (QC) +================================================================================ + +Pooled libraries can be challenging and expensive to ensure adequate quality, but +this upfront cost will save headaches and expense later. + +At a minimum we recommend the use of a diagnostic digest and high-throughput next +generation sequencing (NGS). Select a restriction enzyme for digest that will +cut the shared plasmid backbone a single time and visualize that digestion on an +agarose gel (see restriction digest protocol here). Lentiviral plasmids can +recombine between their LTRs resulting in a smaller plasmid containing only the +elements required for bacterial propagation (origin of replication and antibiotic +selection). This recombination, at a low rate, is not typically a problem as +these sequences are not efficiently packaged into lentiviral particles. See below +for options if the recombinant band makes up a significant proportion of the DNA +pool. + +Last Update: August 17, 2023 + + +WORKFLOW TIMELINE +================================================================================ + +Day 1: Transform, recover, set up overnight growth (Estimated time 2-3 hours) + + Transformation should be performed at the end of the day to ensure that + growth times are limited. + +Day 2: Harvest cells and purify DNA (Estimated time 3-4 hours) + + Cells should be harvested first thing in the morning to ensure that outgrowth + and competition are limited. + + +EQUIPMENT +================================================================================ + +• Table top centrifuge +• BioRad Electroporator (MicroPulser TM, Bio-Rad 1652100) + + +REAGENTS +================================================================================ + +• 200 µL electrocompetent cells (Default: 4 tubes of Endura Duos, Lucigen, + 60242-1) + + Alternatives include Stbl4 cells or other ultra-high efficiency + electrocompetent cells that are suitable for unstable or recombination-prone + DNA. + + The use of electrocompetent cells is essential to ensure high efficiency + uptake of plasmid library DNA. + + This quantity of cells is sufficient for libraries up to 200,000 individual + plasmids. For larger libraries scale the number of cells and DNA accordingly. + + 💡 PRO TIP: Use of extreme high efficiency (1×10¹⁰ cfu/µg) commercially + prepared electrocompetent cells is strongly recommended. + +• 800 ng pooled library DNA (100 ng plasmid DNA per 25 µL electrocompetent cells) + + Less library DNA can be used but this dramatically increases the chances of + individual plasmids being lost from the pool and/or increasing the skewness of + the pool. + +• 8 electroporation cuvettes (BioRad, Micropulser, 0.1 cm) +• 20 mL SOC recovery media (Lucigen, 80026-1) +• 8X LB Agar + Antibiotic 245 mm bioassay plates (Molecular Devices, X602) + + 💡 PRO TIP: Pour these plates at least one day in advance to allow adequate + time to fully gel and to dry slightly. We routinely use 350 mL of LB Agar per + bioassay plate. + +• 14 mL Vented Falcon Tubes (BD Biosciences, 352059) +• 3X LB Agar + Antibiotic 65 mm Petri dish (VWR, 11019-552) +• 4 MaxiPreps (Qiagen HiSpeed Max, Catalog #12663) +• Tips (1000 µL, 200 µL, 10 µL) +• Bacti Cell Spreaders (VWR, 60828-680) +• 5 mL and 10 mL Serological pipettes +• Ice slurry (Ice bucket with ice and water to create slurry) +• 100 mL LB + + At Addgene we use premixed LB (VWR 101414-072) for convenience but any brand + or house-made LB that supports normal growth is expected to work. + +• 50 mL Falcon Conical tubes (Fisher, 14-432-22) + + +REAGENT PREPARATION +================================================================================ + +• Prepare, sterilize, and pour all LB Agar + Antibiotic plates. + +• Prewarm 12 mL recovery media at 37 °C (for at least 15 minutes). + +• Prewarm 3X LB Agar + Antibiotic plates at 37 °C. + +• Prewarm 8X LB Agar + Antibiotic Bioassay plates. + +• Prechill Micropulser cuvettes on ice. + +• Thaw 4 tubes of electrocompetent cells on ice for 15-20 minutes or until + completely thawed. + +• Chill a box of 200 µL micropipette tips in a -20 °C freezer. + +• Aliquot 3 mL SOC into each of four 14 mL Vented Falcon Tubes and have 1 mL SOC + per electroporation readily available for post-electroporation recovery of + cells. + +• Ensure access to autoclaved, sterile reagents for all steps. + + +PROCEDURE +================================================================================ + +Day 1 + +1. Add 200 ng DNA to each 50 µL aliquot of thawed Endura Duos on ice. Flick + gently to mix. + +2. Electroporate cells (one at a time for a total of eight electroporations): + + Electroporator Conditions: Bio-Rad Micropulser Ec1 0.1 cm cuvette, 1.8 kV, 1 + pulse. + + a. Aliquot 25 µL DNA-Endura into pre-chilled cuvette. + b. Pulse. + + Caution: Electroporation involves the use of high voltages, please use + caution when activating pulse and follow all specifications described in the + equipment manual. + + c. Immediately add 1 mL SOC to cuvette. + d. Remove all liquid from cuvette and add to 14 mL vented Falcon Tube + containing 3 mL SOC. + e. Repeat for each of the 25 µl aliquots of cell/DNA mixture used (8 in the + described protocol) using a new vented falcon tube for every two + transformations. Each of the four 14 mL Vented Falcon Tubes should contain + a total of 5 mL (3 mL SOC + 2 mL transformed Endura from two separate + transformations). + + 💡 PRO TIP: Do not pipette repeatedly or mix when removing SOC containing + transformed DNA-Endura from cuvette. + +3. Shake four 14 mL Vented Falcon Tubes at 30-37 ℃, 225 rpm for 1 hour. + +4. After the 1 hour shaking period, pool and gently mix the four tubes. + +5. Perform sequential 1:100 dilutions of the cells (add 10 µL of the pool to 990 + µL LB then perform a second and then third 1:100 dilution). Plate 100 µL of + each dilution onto a prewarmed Petri dish. + +6. Incubate plates at 30 ℃ overnight. + +7. Plate 2.5 mL of the transformed cells on each of the eight bioassay plates (two + plates per tube). Distribute evenly with a sterile spreader until all liquid + has been absorbed by the agar. This usually takes 1-2 minutes. + + Critical: Be careful not to rip or shred the agar. Do so by gentle spreading. + Some spreaders have a sharp edge that can scrape plates more abrasively at a + certain angle. + +8. Incubate plates upside down at 30 ℃ overnight. + + Critical: Ensure at this stage that no unabsorbed media drips onto the lid. + Let plates remain agar side up until dried before overnight incubation if + needed. + +9. Place 100 mL sterile LB at 4 ℃. + +Day 2 (morning) + +1. Before beginning, prechill at least four conical tubes on ice and ensure + access to sterile scraper and cold LB. + + 💡 PRO TIP: Prepare one to two more conical tubes on ice in case you need to + spread out the harvested cells further than four Maxipreps worth. + +2. Count colonies on the most dilute Petri dish. + + Total colony yield = count × 100 × 100 × 100 ÷ 0.1 + + This number should be at least 1000X greater than number of perturbations in + library. + + Example: At least 10 colonies on the most diluted plate for 1000x coverage of + a library of 100,000 plasmids. + + Colonies may appear small and require extra incubation time in order to be + enumerated accurately. + + Frequently the number of colonies can be too great to count. Ideally, + dilutions would have been sufficient to enumerate single colonies but as long + as one can ensure more than the required colonies are present. If colonies are + not present on the most dilute plate, count the second plate (ie. the 1:10,000 + dilution). + +3. After 12-18 hours of growth, use spreader and cold LB to scrape bioassay + plates and remove bacteria. + + • Use one scraper for all plates. + • Use two 10 mL pipettes (one for dispensing cold LB and one for removing LB + containing bacteria from plate). + + 💡 PRO TIP: Scraped bacteria in LB can clog the pipette either mix gently up + and down avoiding introducing bubbles or pour off plates into conical tubes as + needed. + +4. Add 10 mL cold LB to each plate for each scrape and use spreader to scrape + plates. + + 💡 PRO TIP: Pushing motion is better than pulling motion. Take care not to + split or gouge agar during the scraping process. + +5. Add each scrape into a 50 mL conical tube on ice pooling the scrapings of two + plates into each tube. Keep each tube on ice while scraping. + +6. Repeat addition of 10 mL cold LB and scrape for each plate until agar is clear + (all bacteria have been removed). This should produce 25 mL cold LB-bacteria + per plate. + +7. Centrifuge tubes (4000 G, 4 ℃, 15 minutes) to pellet bacteria. + +8. Decant LB and weigh pellet. The total weight of each pellet should be ~1-2 g. + + 💡 PRO TIP: Make sure to weigh the empty tube beforehand! If you've already + gone too far, weigh an identical empty tube. It will be close enough for the + purpose of a Maxiprep. + +9. Purify plasmid DNA using the Qiagen HiSpeed Maxi Kit (one conical is its own + Maxiprep). + + Critical: Do not freeze pellets for later purification. Immediately purify them! + Commercial Maxipreps rely on incremental, ordered cell lysis. E. coli cells + are subject to lysis by freeze-thaw if not suspended in cryoprotectant like + Glycerol or DMSO solutions. + +10. Quantify the individual Maxipreps by Nanodrop, Picogreen, or Qubit. + + Each different DNA measurement type can report slightly different + concentrations of DNA. In our hands fluorescent dye methods tend to report + lower values than Nanodrop, although most protocols have been designed with + Nanodrop as the quantification method. + +11. If all Maxipreps appear to contain sufficient DNA for use, pool samples, and + continue with analysis. + + "Sufficient" DNA will vary upon intended use. Typically yields range from + several hundred micrograms to a milligram of total plasmid DNA. + + +TIPS AND TROUBLESHOOTING +================================================================================ + +What do I do if my transformation efficiency is not high enough? + +Repeat the experiment with more cells, more DNA, gentler practices, and colder +reagents (not including the recovery media!). Do not proceed with Maxipreps or +NGS until adequate transformation efficiency is obtained. Ensure that +electrocompetent cells are being used. Chemically competent cells will not +provide adequate transformation efficiency! Ensure that no arcing is taking place +during electroporation. Arcing would manifest as a loud pop often accompanied by +some light in the cuvette during the electroporation step. + +I got a heavy recombined band by digest. + +Recombination is thought to be in part related to selective pressure. These +recombined plasmids are much smaller and are a smaller nutritional burden on the +bacteria. Bacteria that contain a recombinant plasmid likely grow faster in the +closed system of a crowded plate or culture. Try restricting growth to the bare +minimum by growing at 30 ℃, limiting growth time further, or potentially +spreading less bacteria on a given plate (example: by increasing the total number +of bioassay plates used). Scaling up the experiment using a Gigaprep can be used +to obtain sufficient intact pooled library even in the face of a recombined +fraction but care must be taken to perform adequate NGS based QC to ensure no +change in representation compared to the pre-amplified stock. A last option is +to perform a gel extraction of either the original sample or the amplified +sample, followed by reamplification of the DNA, but please note that NGS should +be performed to ensure representation is maintained. + +Maxipreps - Less is more: + +Do not overload the Maxipreps as yield can dramatically plateau and sometimes fall +off entirely if the column or reagents are significantly overloaded. If you find +that your pellet outstrips the capacity listed in the Maxiprep protocol, scale +the reagent volume and column number as needed. The use of Mega or Gigapreps is +acceptable when scaling up or reducing the number of tandem purifications. Consult +the manufacturers handbooks for appropriate volumes and numbers of tandem +purifications. + +Visit our Help Center to get details on how to process your Addgene pooled library diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Centrifugation.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Centrifugation.txt new file mode 100644 index 0000000000000000000000000000000000000000..efa1d2b49694cb2b2e247549cd75c9977f07a2ec --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Centrifugation.txt @@ -0,0 +1,129 @@ +PROTOCOL: Centrifugation +SOURCE: https://www.addgene.org/protocols/centrifugation/ +================================================================================ + +INTRODUCTION +================================================================================ + +A centrifuge is a common piece of laboratory equipment used to separate different +components in a liquid sample. It achieves this by using centrifugal force, which +is generated by spinning the sample at a high speed. Being able to separate solids +from a liquid or separate liquids of different densities is essential to many +different experimental procedures, such as minipreps and RNA extractions. Plus, +centrifuges are useful for simply collecting liquid to the bottom of a tube. + +You will likely encounter several different types of centrifuges that can +accommodate different sized containers, spin at different speeds, or keep samples +at specific temperatures. This protocol will cover the general procedure and +features to keep in mind when using any centrifuge. However, each centrifuge may +have specific instructions so be sure to check in with someone familiar with your +lab's instrument before use. + +Last Update: September 2022 + + +EQUIPMENT +================================================================================ + +• Centrifuge +• Microfuge tubes or other suitable container +• Personal protective equipment (PPE) appropriate for the biosafety level of the + lab space + + +REAGENTS +================================================================================ + +• Sample to be centrifuged +• Water + + +BACKGROUND INFORMATION +================================================================================ + +Types and Parts + +There are several types of centrifuges: + +• Mini or Tabletop Centrifuges: Sit on your benchtop and typically hold the + common 1.5 mL microfuge tubes used in labs, though some larger models can hold + larger conical tubes. Depending on the centrifuge their speed ranges can vary, + but are typically lower than some other centrifuge types. + +• Floor Centrifuges: Sit on the floor and can be about bench height. They often + spin at similar speeds to their smaller cousins, but can hold much larger + containers. + +• Ultracentrifuges: Also generally floor sized centrifuges that can hold larger + containers, but they can also rotate at much higher speeds and are used for + more specialized techniques. + +Regardless of the type of centrifuge you use, most will have essentially the same +components. The photo to the left shows a front view of an open tabletop +microcentrifuge with the lid open, the rotor with microfuge tubes in place, and +the control panel where you can set the time and speed needed for your experiment. + + +PROCEDURE +================================================================================ + +How to Centrifuge + +Now that you know the different parts of a centrifuge, you're ready to begin using +the centrifuge. + +1. Determine the type of centrifuge needed. This decision should be based on the + size of tubes you are using and the speed at which you need to spin your + samples. For example, spinning down samples in 1.5 mL microfuge tubes at + 10,000 rpm would require a tabletop microcentrifuge like the one in the picture + above. + +2. Wear PPE appropriate for the lab space in which you are working. Even if your + samples may not require specific PPE, you never know what else has been placed + in the centrifuge before you and may still be on the equipment. + +3. Before using the centrifuge for your samples, ensure that the centrifuge is + clean and that everything appears to be working smoothly. + +4. Place your sample tubes into the rotor so that they are distributed evenly + around the center (see image to right). Even distribution ensures that the + centrifuge is balanced. Using the centrifuge in an unbalanced state can damage + the centrifuge and be dangerous for the user. If you do not have a balanced + number of samples, you may need to add a blank. Blanks are often an extra + tube filled with water to the same volume as your samples. If your samples are + significantly higher density than water, then you may need to fill the blank + based on weight instead of volume. + + 💡 PRO TIP: For microfuge tubes, place them with the lid tabs pointing up or + out of the centrifuge so that the pellets form in approximately the same place + in each sample. + +5. Place the centrifuge's internal lid on the rotor (if it has one) and then + close the external lid. + +6. Adjust the centrifuge settings according to speed and time (and temperature, if + applicable) listed in your protocol. + + 💡 PRO TIP: Spin speed is often given as Relative Centrifugal Force (RCF) or + Revolutions Per Minute (RPM), these are not the same units and are not + directly interchangeable. If you need to convert between the two, use a + conversion calculator or chart like the G Force calculator. + +7. The centrifuge should come up to speed with a pleasant hum. If you hear loud + noises or the centrifuge begins to wobble or shake, this could indicate an + unbalanced or improperly loaded centrifuge. Immediately stop the centrifuge + and investigate the issue. + +8. When you are finished spinning your samples, carefully remove them from the + centrifuge so as to not dislodge any pellets or re-mix liquids. In cases where + you are separating solids from a liquid, pellets represent the solids in your + sample while the liquid portion is known as the supernatant. Depending on your + experiment, you may be required to save the pellet, the supernatant, or both. + + +CONCLUSION +================================================================================ + +Centrifuges are important tools for many different protocols. Improper use of a +centrifuge can damage the equipment, your samples, or you, so be sure to keep +your centrifuge clean and balanced. diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Colony Formation Titering Assay.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Colony Formation Titering Assay.txt new file mode 100644 index 0000000000000000000000000000000000000000..c40e7e3f7e4e92b20b3b9318ad70096efc29140e --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Colony Formation Titering Assay.txt @@ -0,0 +1,221 @@ +PROTOCOL: Colony Formation Titering Assay +SOURCE: https://www.addgene.org/protocols/colony-formation-titering-assay/ +================================================================================ + +INTRODUCTION +================================================================================ + +This protocol can be used to titer lentivirus preparations that confer antibiotic +resistance. Determining the titer of your lentiviral preparation allows you to +control the multiplicity of infection (MOI) in downstream studies. This protocol +was developed for A549 cells but can be adapted to a variety of target cell lines +and selection markers. Note this assay requires staining resistant colonies with +crystal violet solution and, therefore, the cells cannot be used for later +experiments. + + +WORKFLOW TIMELINE +================================================================================ + +Day 0: Seed and transduce cells + +Day 2: Replace media with fresh media containing selection reagent + +Days 3–14: Change media as needed + +Days 14–18: Stain cells and count resistant colonies + + +EQUIPMENT +================================================================================ + +• Class II, Type A2 Biological Safety Cabinet +• 0.5–10 µL single channel pipette +• 2–20 µL single channel pipette +• 20–200 µL single channel pipette +• 200–1000 µL single channel pipette +• Ice bucket +• CO₂ incubator +• Pipet controller +• Hazardous waste container + + +REAGENTS +================================================================================ + +• DMEM high glucose, Corning 10-013-CV +• L-alanyl-L-glutamine (or alternative stable glutamine such as glutaGRO, + Corning 25-015-CI) +• Heat-inactivated FBS +• Polybrene (10 mg/mL), Millipore TR-1003-G +• 1X PBS pH 7.4 without calcium or magnesium, Corning 21-040-CV (cations can + affect the attachment of adherent cells) +• 0.1% Crystal Violet, Ward's Scientific CC0456-500ML +• 0.22 µm luer-lock filter, Corning 431229 +• 10 mL luer-lock syringe, BD BD300912 +• 0.45 μm polyethersulfone filter, Nalgene, 565-0010 (for viral preps, if prep + was not previously filtered) +• Microcentrifuge tubes, Neptune 3745.X +• 6-well tissue culture treated dish, Corning 3516 +• 15 mL conical tubes, VWR 21008-216 +• Lentivirus preparation + + +REAGENT PREPARATION +================================================================================ + +DMEM Complete: 10% v/v FBS and 4 mM L-alanyl-L-glutamine (or stable alternative, +such as glutaGRO) + +To a 500 mL bottle of DMEM high glucose, add 55 mL of heat inactivated FBS and 5 +mL of 100X glutaGRO. Store at 4 °C. + +💡 PRO TIP: Different brands and lots of FBS can promote or inhibit +transfection. Test a variety of brands and lots of FBS to find one suitable with +your protocols. FBS can be purchased already heat-inactivated, or it can be +inactivated in the lab by heating to 56 °C for 30 min. + + +CONSIDERATIONS BEFORE YOU START +================================================================================ + +• The health of the target cell line is critical for obtaining accurate titers. + +• Check the cells for mycoplasma regularly. + +• Do not over or under-grow your cells. + +• Thaw a new vial of cells after 20–30 passages. + +• Do not add penicillin/streptomycin to the media, as it can affect viability and + transduction efficiency. + +• Titer will vary between cell lines. + +• It is not recommended that lentiviral supernatants be subjected to multiple + freeze-thaw cycles. + +• This protocol outlines the seeding of the cells at the same time as the + virus-mediated transduction. For some cell lines, transduction is optimized if + the cells are seeded the day before transduction. Note that in that case, + polybrene should only be added at the time of viral transduction, and not during + the cell seeding step. + + +PROCEDURE +================================================================================ + +1. Before beginning a colony formation assay, the dose of antibiotic required to + kill your target cell line needs to be empirically determined. Treat the + target cells with a range of doses of antibiotic. Determine the minimum + concentration required to kill all of the cells. Use this dose for the colony + formation assay. + +2. Prepare a batch of DMEM complete containing 10 μg/mL polybrene by diluting 20 + μL of 10 mg/mL polybrene into 20 mL of media. + +3. If using freshly collected virus, filter through a 0.45 μm polyethersulfone + filter to remove cells and debris. + +4. Lentiviral titer can decrease during cycles of freeze-thaw. If you are + freezing and aliquoting virus, it is recommended that you titer from the + frozen stock to account for any loss in titer associated with freeze-thaw. + +5. If using frozen virus, thaw the lentiviral aliquot on ice prior to use. + +6. Prepare 10-fold serial dilutions of the lentivirus into DMEM complete + containing 10 μg/mL polybrene: + + Dilution | Volume of Virus/Previous | Volume of DMEM Complete | Volume of Virus | Volume of Cells | Final Viral + | Dilution (μL) | + Polybrene (μL) | Added (μL) | Added (μL) | Dilution + --------------|--------------------------|-------------------------|-----------------|----------------|------------ + 1:10 | 100 of Stock Virus | 900 | 150 | 1,350 | 1:100 + 1:100 | 100 of 1:10 | 900 | 150 | 1,350 | 1:1,000 + 1:1,000 | 100 of 1:100 | 900 | 150 | 1,350 | 1:10,000 + 1:10,000 | 100 of 1:1,000 | 900 | 150 | 1,350 | 1:100,000 + 1:100,000 | 100 of 1:10,000 | 900 | 150 | 1,350 | 1:1,000,000 + + Mix the dilutions well. + + Note: the 1:10 dilution can usually be omitted because this dilution typically + produces a lawn of cells, which cannot be accurately quantified. + +7. Add 150 μL of a viral dilution to each well (each well gets one dilution). + +8. Also include an untransduced well by using 150 μL of media in place of virus. + +9. Seed 1,000 cells into each well of a 6-well dish. + + Prepare a batch of cells as follows: Dilute 7,000 cells into 9.45 mL of DMEM + complete containing 10 μg/mL polybrene. + +10. Mix well by pipetting or inverting. + +11. Aliquot 1.35 mL of the cell suspension into each well of the 6-well dish + directly on top of the virus. Swirl gently to mix and place the dish in the + incubator. + +12. Incubate for 48–72 h. + + 💡 PRO TIP: Different cells may be more sensitive to lentivirus or to + polybrene, in which case this incubation step can be reduced to 8 h and the + media can be replaced with DMEM complete. However, antibiotic-containing media + should not be added until 48–72 h after transduction. + +13. Gently aspirate the media from the cells. + +14. Add 1.5 mL of DMEM complete containing the appropriate antibiotic. + +15. Incubate the cells for ~2 weeks. All of the cells in the untransduced + (negative) control well should be killed and no colonies should be visible. + +16. Every 3–4 days, gently aspirate the media and replace it with fresh DMEM + complete containing the appropriate antibiotic. + +17. When the untransduced (negative control) cells have died and colonies are + visible in the transduced wells, aspirate the media from the wells. + +18. Gently wash the cells with 1 mL of PBS and aspirate wash. + +19. Filter 0.1% crystal violet solution through a 0.22 μm filter to remove any + precipitates. + +20. Stain each well with 1 mL of 0.1% crystal violet for 10 min at RT. + +21. Gently remove the stain. + +22. Wash cells 3x with 1 mL of PBS, being careful not to disturb the colonies. + +23. Count the colonies for at least 2 of the dilutions. + + 💡 PRO TIP: The higher dilution wells tend to provide more accurate titers as + the likelihood of multiple integration events decreases as the dilution + increases. + +24. Calculate the transduction units per mL (TU/mL) as follows: + + TU/mL = number of colonies / total volume in the well (mL) × dilution factor + + e.g., If the 1:100,000 well has 75 colonies, then there are 75 colonies / + 1.5 mL × 1,000,000 or 50,000,000 TU/mL + + For a more accurate titer, take the average of multiple dilutions. + + +SAMPLE DATA +================================================================================ + +A549 cells were transduced with the indicated serial dilutions of the lentiviral +vector pRosetta. The following day, cells were treated with puromycin. Colonies +were allowed to grow in the presence of selective reagent for 12 days with media +exchanges every 3–4 days. Colonies were then stained with 0.1% crystal violet +and counted. + +A549 cells were transduced with the indicated serial dilutions of the lentiviral +vector pHAGE EF1α dCas9-KRAB. The following day, cells were treated with +puromycin. Colonies were allowed to grow in the presence of selective reagent +for 12 days with media exchanges every 3–4 days. After 12 days of selection, no +cells have survived in the untransduced well, while lawns of cells are present in +the lower dilutions, and single colonies are visible in the higher dilutions. + +Last reviewed on: August 31, 2023 diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Coomassie Purity Stain of Recombinant Antibodies.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Coomassie Purity Stain of Recombinant Antibodies.txt new file mode 100644 index 0000000000000000000000000000000000000000..22d11796db09c03e3478351952fb1bdc66fa898a --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Coomassie Purity Stain of Recombinant Antibodies.txt @@ -0,0 +1,307 @@ +PROTOCOL: Coomassie Purity Stain of Recombinant Antibodies +SOURCE: https://www.addgene.org/protocols/coomassie-purity-stain-recombinant-antibodies/ +================================================================================ + +INTRODUCTION +================================================================================ + +This protocol describes how to determine the purity and concentration of +recombinant antibodies using ready-to-use bio-safe Coomassie G-250 stain +(Addgene uses SimplyBlue SafeStain) and ImageJ software. The sample is +separated by denaturing polyacrylamide gel electrophoresis alongside serial +dilutions of a standard antibody of known concentration. After staining with +Coomassie blue, protein band intensities are measured using ImageJ software and a +standard curve is generated. The ratio of the antibody protein content to the +total protein content of the sample is determined. + +Last Update: June 14, 2023 + + +WORKFLOW TIMELINE +================================================================================ + +Day 1: Run SDS-PAGE and stain gel + +Day 1 or later: Image analysis + + +EQUIPMENT +================================================================================ + +• Heat block +• 1–10 µL single channel pipette +• 2–20 µL single channel pipette +• 20–200 µL single channel pipette +• 200–1000 µL single channel pipette +• Pipette controller +• Microcentrifuge +• Electrophoresis chamber +• Power supply +• Rocking platform +• Fume hood +• Metal spatula +• Razor blade +• Plastic tray +• Gel imaging system +• ImageJ or similar software + + +REAGENTS +================================================================================ + +• Purified recombinant antibody, 0.9–1.1 mg/mL +• SimplyBlue SafeStain, Thermo Fisher, LC6060 +• 4-12% NuPage Novex bis-tris mini gel, 1mm thick, 10-well, Invitrogen NP0321BOX +• 20X MOPS SDS running buffer, Invitrogen NP0001 +• 4X NuPage sample buffer, Invitrogen NP0007 +• 10X NuPage sample reducing agent (500 mM dithiothreitol, DTT), Invitrogen + NP0009 +• PageRuler Plus Prestained protein ladder, Invitrogen 26619 +• Pipette tips, 10 µL, VWR 76322-132 +• Pipette tips, 20 µL, VWR 76322-134 +• Pipette tips, 200 µL, VWR 76322-150 +• Pipette tips, 1000 µL, VWR 76322-154 +• Pipettes, 5 mL, VWR 89130-896 +• Pipettes, 10 mL, VWR 89130-898 +• Pipettes, 25 mL, VWR 89130-900 +• Pipettes, 50 mL, VWR 89130-902 +• Gel loading tips, Corning 4853 +• Microcentrifuge tubes, Neptune 3745.X +• PBS, 1X pH 7.4, VWR 45000-446 +• 250 mL sterile bottles, Corning 430281 +• Deionized water +• IgG isotype standard 2.5 mg/mL - can use commercial standard or validate an + in-house standard + + +BEFORE STARTING +================================================================================ + +• Warm the hot plate to 100 °C. + +• Thaw IgG standard and prestained protein ladder on ice. + + +REAGENT PREPARATION +================================================================================ + +Prepare IgG Standard + +Dilute the 2.5 mg/mL IgG isotype standard in PBS as follows: + +• 1.5 mg/mL: 18 µL of 2.5 mg/mL with 12 µL PBS +• 1.0 mg/mL: 20 µL of 1.5 mg/mL with 10 µL PBS +• 0.75 mg/mL: 15 µL of 1.0 mg/mL with 5 µL PBS +• 0.5 mg/mL: 13.3 µL of 0.75 mg/mL with 6.7 µL PBS +• 0.25 mg/mL: 10 µL of 0.5 mg/mL with 10 µL PBS +• 0.125 mg/mL: 10 µL of 0.25 mg/mL with 10 µL PBS + +Transfer 5 µL of each standard to a microfuge tube. + +Add 8 µL of PBS to a total volume of 13 µL. + +Prepare the recombinant antibody + +1. Dilute or concentrate purified recombinant antibody to a concentration of + 0.9–1.1 mg/mL. + +2. Transfer 5 µL of recombinant antibody to a microfuge tube. + +3. Add 8 µL of PBS to total 13 µL. + +Prepare 1X MOPS buffer + +Dilute 25 mL of 20X MOPS buffer into 475 mL of deionized water. + +Gently invert to mix. + + +PROCEDURE +================================================================================ + +Section 1: SDS-PAGE + +1. Add 5 µL of 4X sample buffer to each sample. + +2. Add 2 µL 10X reducing agent to each sample. + +3. Spin the sample briefly in the microcentrifuge. + +4. Heat the samples for 10 min at 100 °C in a heat block. + +5. Spin the sample briefly in the microcentrifuge. + +6. Remove the gel from the plastic wrapper and rinse with deionized water. + +7. Gently remove the white sticker on the bottom of the gel. + +8. Place the gel in the electrophoresis chamber and secure it. + + Note: Check the manufacturer's instructions if you are unsure of the correct + orientation of the gel. + +9. Carefully remove the comb from the gel. + +10. Rinse each well with 200 µL 1X MOPS running buffer. + +11. Fill the chamber with 1X MOPS running buffer. + +12. Make sure that the chamber is sealed. + +13. Load 5 µL of the prestained protein ladder to the appropriate well. + + 💡 PRO TIP: When possible, skip one lane before loading samples. + +14. Load 20 µL of each recombinant antibody sample to the appropriate well. + + 💡 PRO TIP: Leaving clear lanes between samples will make quantifying the gel + easier. + +15. Cover the electrophoresis chamber and attach to a power supply. + +16. Run the gel at 150 V for 1 h. + + 💡 PRO TIP: If the samples are running unevenly and the dye front looks like a + "smile", reduce the voltage. + +17. Turn off the power supply and unplug the electrophoresis chamber. + +18. Remove the gel from the chamber. + +19. Use the metal spatula to gently break the gel cast open. + +20. Use a razor blade to cut the top of the wells and bottom part of the gel where + dye is visible. + +Section 2: Staining the Gel + +1. Place the gel in a plastic tray with 100 mL of deionized water. + +2. Rinse gel with deionized water for 5 min with gentle agitation on a rocking + platform. + +3. Pour off the water in the sink. + +4. Add 20 mL of SimplyBlue SafeStain and incubate for 1 h with gentle agitation on + a rocking platform. + +5. Pour off the SimplyBlue SafeStain in the sink. + +6. Add 100 mL of deionized water and incubate for 1 h with gentle agitation on a + rocking platform. + +7. Pour off the water in the sink. + +8. Add 100 mL of deionized water and incubate for 1 h with gentle agitation on a + rocking platform. + +9. Pour off the water in the sink. + +10. Take a brightfield image of the gel with an appropriate imaging system. + + Recombinant antibody preps should have 2 clear bands at ~50 kDa and ~25 kDa + corresponding to the heavy chain (HC) and light chain (LC) proteins, + respectively. There should be very little background staining. + + 💡 PRO TIP: A large shift in the electrophoretic mobility of the bands + (sample AR0016 in Figure 1) indicates that the samples may not have been + processed correctly in the cell (e.g., failure to cleave the signal peptide) + and may not be functional. This sample would fail Addgene QC and would not be + used. + +Section 3: Image Analysis + +Use ImageJ or a similar photo software to determine the relative intensity of the +protein bands to the overall lane. + +1. Import the gel image into ImageJ. + • Select File. + • Select Open. + • Choose the location of the file to open. + +2. Change the image type to 8-bit. + • Select Image. + • Select Type. + • Choose 8-bit. + +3. Determine each lane of the gel as follows: + • Using the box tool, draw a box around the entire first gel lane. + • Select Analyze. + • Select Gels. + • Select Select First Lane. + • Drag the box to the next lane. + • Select Analyze. + • Select Gels. + • Select Select Next Lane. + • Repeat for all lanes. + +4. Plot the area under the curves for the protein bands as follows: + • Select Analyze. + • Select Gels. + • Select Plot Lanes. + • One graph per lane will appear with peaks representing each protein band. + • Use the line tool to connect the bottom of each peak. + • Select the wand tool. + • Fill in each peak by selecting the center of the peak. + +5. Export results as a csv file. + • In the results table, select File and Save As. + +6. Determine the percent purity of the samples: + + P = ((H + L) / A) × 100 + + Where: + • P = Purity, % + • H = Area of HC peak + • L = Area of LC peak + • A = Total area of all bands in the lane + + Example for AR0018 (lane 2 in Figure 1): + • Peak 1 (contaminant): 310.142 + • Peak 2 (contaminant): 207.971 + • Peak 3 (HC): 11469.296 + • Peak 4 (LC): 4655.113 + • Total Area: 16642.522 + • HC + LC Area: 16124.409 + • Purity: 96.887% + + 💡 PRO TIP: Addgene only uses recombinant antibody preps that have a purity + of ≥90% but some labs use unpurified tissue culture supernatant routinely + without any issues. + +7. Plot the mg/mL versus the HC + LC Area column for the IgG standards in Google + Sheets. + • Open exported CSV file. + • Select import. + • Choose file. + • Format as needed. + • Select the Insert tab, then Chart. This will add a blank chart to your + spreadsheet. + • In the Chart Editor, select the Chart Type drop down menu and select Scatter + chart. + • Change the data range and select the cells where the x-axis is represented. + • Add a linear trendline for the standards. Google Sheets can calculate this + for you as follows: + - In the Chart Editor, select the Customize tab. + - Select the Series drop down menu. + - Select the Trendline checkbox. + +8. Determine the linear equation and the R² of the trendline in Google Sheets as + follows: + • In the Customize tab, select the Label drop down menu and choose Use + Equation. + • Select the Show R² checkbox. + + 💡 PRO TIP: The R² of the trendline should be between 0.95–1. + +9. Use the equation of the trendline to determine the concentration of your + samples based on your sample's HC + LC area. + + Example calculation: + If the sample HC + LC Area is 18179.442 and the linear equation of the + standard curve is y = 14725x + 3748.4, then substitute 18179.442 for y and + solve for x. + 18179.442 = 14725x + 3748.4 + x = 0.980 + The concentration of the sample is 0.980 mg/mL diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ DNA Quantification.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ DNA Quantification.txt new file mode 100644 index 0000000000000000000000000000000000000000..2a5545b4ed9fb90dbe3cac3ed2af12aabad8d9bc --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ DNA Quantification.txt @@ -0,0 +1,58 @@ +PROTOCOL: DNA Quantification +SOURCE: https://www.addgene.org/protocols/dna-quantification/ +================================================================================ + +BACKGROUND INFORMATION +================================================================================ + +During several different stages of molecular cloning, it is important to get a +quick and accurate reading of DNA concentration and purity. This can be done with a +spectrophotometer. A spectrophotometer uses the absorbance/transmission of light +through a liquid to determine the concentration of a particular substance in that +liquid. Molecules absorb different wavelengths of light to varying degrees and most +have a specific wavelength that they maximally absorb. By measuring the absorbance +of a liquid you can accurately estimate the concentration of a substance in that +liquid. + +In order to accurately measure the concentration of a substance based on its +absorbance, you need to know the wavelength of light that your substance maximally +absorbs. In the case of nucleic acid (DNA and RNA), the maximal absorbance is at +260nm. Protein maximally absorbs at 280nm and the ratio of nucleic acid to protein +(260/280) is generally used as an indicator of the purity of DNA samples. + +These days, many labs have a NanoDrop, which is a very small spectrophotometer that +can accurately read DNA concentration and purity in as little as 1μl. Regardless of +whether you have a NanoDrop, follow the manufacturer's instructions for the +spectrophotometer specific to your lab. + + +SPECTROPHOTOMETER TIPS +================================================================================ + +1. Before measuring any samples, be sure to 'blank' the spectrophotometer using + the solution the DNA is resuspended in, but with no DNA added. 'Blanking' + measures the background inherent to the machine and your solvent. + +2. If using a NanoDrop to measure your samples, place 1-2µL of mini-prepped DNA + onto the pedestal. + +3. Close the lid and click measure, be sure to record the concentration and purity. + + Note: Purity is measured under the 260/280 column (A good purity ranges from + 1.80-2.00). + +4. Repeat for each sample. + + +NOTES +================================================================================ + +• Keep in mind that despite the accuracy of the NanoDrop, if two consecutive + samples have significantly different concentrations, it is possible that the + difference between them has affected the accuracy of the NanoDrop. It is a good + idea to re-zero any spectrophotometer between samples if they are expected to + vary significantly in concentration. + +• DNA dissolved in water is going to have a greater variance in concentration + readings than a DNA sample dissolved in buffer (such as TE). You will get much + more accurate and consistent readings from DNA in a buffered solution. diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Fluorescence Titering Assay.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Fluorescence Titering Assay.txt new file mode 100644 index 0000000000000000000000000000000000000000..c2dab8b76c5d96266add8e5f8cdadb5572ec690d --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Fluorescence Titering Assay.txt @@ -0,0 +1,202 @@ +PROTOCOL: Fluorescence Titering Assay +SOURCE: https://www.addgene.org/protocols/fluorescence-titering-assay/ +================================================================================ + +INTRODUCTION +================================================================================ + +This protocol can be used to titer lentiviral preparations that carry a +fluorescence marker. Determining the titer of your lentiviral vector allows you to +control the multiplicity of infection (MOI) in downstream studies. This protocol +was developed for 293T cells but can be adapted to a variety of target cell lines +and selection markers. Note, because this protocol uses microscopy to determine +the percentage of fluorescent cells, these cells can still be used in downstream +applications. + + +SAFETY WARNINGS +================================================================================ + +Lentivirus is generally considered biosafety level 2+. Please ensure that you are +in compliance with your institution's biosafety regulations. + + +WORKFLOW TIMELINE +================================================================================ + +Day 0: Seed 293T cells + +Day 1: Transduce cells + +Day 2 (am): Remove media, replace with fresh media + +Day 4–5: Count fluorescent cells + + +EQUIPMENT +================================================================================ + +• Class II, Type A2 Biological Safety Cabinet +• 0.5–10 µL single channel pipette +• 2–20 µL single channel pipette +• 20–200 µL single channel pipette +• 200–1000 µL single channel pipette +• Ice bucket +• CO₂ incubator +• Pipet controller +• Hazardous waste container +• Inverted fluorescence microscope + + +REAGENTS +================================================================================ + +• DMEM high glucose, Corning 10-013-CV +• L-alanyl-L-glutamine (or alternative stable glutamine such as glutaGRO, + Corning 25-015-CI) +• Heat-inactivated FBS +• Polybrene (10mg/mL), Millipore TR-1003-G +• 1X PBS pH 7.4 without calcium or magnesium, Corning 21-040-CV (cations can + affect the attachment of adherent cells) +• 0.45 μm polyethersulfone filter, Nalgene, 565-0010 (for viral preps, if prep + was not previously filtered) +• Microcentrifuge tubes, Neptune 3745.X +• 6-well tissue culture treated dish, Corning 3516 +• 15 mL conical tubes, VWR 21008-216 +• Lentivirus preparation + + +REAGENT PREPARATION +================================================================================ + +DMEM Complete: 10% v/v FBS and 4 mM L-alanyl-L-glutamine (or stable alternative, +such as glutaGRO) + +To a 500 mL bottle of DMEM high glucose, add 55 mL of heat-inactivated FBS and 5 +mL of 100X glutaGRO. Store at 4 °C. + +💡 PRO TIP: Different brands and lots of FBS can promote or inhibit +transfection. Test a variety of brands and lots of FBS to find one suitable with +your protocols. FBS can be purchased already heat-inactivated, or it can be +inactivated in the lab by heating to 56 °C for 30 min. + + +CONSIDERATIONS BEFORE YOU START +================================================================================ + +• The health of the target cell line is critical for obtaining accurate titers. + +• Check the cells for mycoplasma regularly. + +• Do not over- or under-grow your cells. + +• Thaw a new vial of cells after 20–30 passages. + +• Do not add penicillin/streptomycin to the media, as it can affect viability and + transduction efficiency. + +• Titer will vary between cell lines. + +• It is not recommended to subject lentiviral supernatants to multiple + freeze-thaw cycles. + + +PROCEDURE +================================================================================ + +1. Seed 75,000 cells into each well of a 6-well dish. + + Prepare a batch of cells as follows: Dilute 525,000 cells into 14 mL of DMEM + complete. + +2. Mix well by pipetting or inverting. + +3. Aliquot 2 mL of cell suspension into each well of the 6-well dish. + +4. Incubate the cells overnight. + +5. If using freshly collected virus, filter through a 0.45 μm polyethersulfone + filter to remove cells and debris. + +6. Lentiviral titer can decrease during cycles of freeze-thaw. If you are + freezing and aliquoting virus, it is recommended that you titer from the + frozen stock to account for any loss in titer associated with freeze-thaw. + +7. If using frozen virus, rapidly thaw the lentiviral aliquot on ice prior to + use. + +8. Prepare dilutions of the lentivirus into DMEM complete containing 10 μg/mL + polybrene. Note, this protocol was developed using low titer lentiviral vectors + (10⁵ TU/mL). If you anticipate that your viral stock will be higher titer, + consider additional dilutions. + + Dilution | Volume of Lentivirus | Volume of DMEM | Volume of 10mg/mL + | Stock (μL) | complete (μL) | polybrene (μL) + ------------|----------------------|----------------|------------------ + 1:10 | 150 | 1348.5 | 1.5 + 1:25 | 60 | 1438.5 | 1.5 + 1:50 | 30 | 1468.5 | 1.5 + 1:75 | 20 | 1478.5 | 1.5 + 1:100 | 15 | 1483.5 | 1.5 + Untransduced| 0 | 1498.5 | 1.5 + +9. Mix the dilutions well. + +10. Gently aspirate media from the cells. + +11. Add 1.5 mL of a viral dilution to each well (each well gets one dilution with + one well remaining as the untransduced control). + +12. Count the cells in the remaining well, a cell count is required for + calculating the titer. + +13. Incubate for 48–72 h. + +14. Gently aspirate media and replace with 1 mL of PBS. + +15. Calculate the fraction of fluorescent-positive cells in each well. + + When calculating titer, only consider wells with less than 40% fluorescent + cells. Titering methods assume one integration event per cell. When the + percentage exceeds 40% you risk counting cells with multiple integration + events leading to underestimation of the true titer. + +16. Calculate the transduction units per mL (TU/mL) using either the dilution + factors (method 1) or the volume of virus (method 2): + + Method 1: T = (N × F × D) / V_T + + Where: + • T = Titer, TU/mL + • N = Number of cells transduced + • F = Fraction of cells with fluorescence + • D = Dilution Factor + • V_T = Transduction Volume, mL + + For example: If 150,000 cells were transduced in the 1:100 well, resulting in + 25% fluorescent cells, then the titer is: + (150,000 cells × 0.25 fluorescent × 100) / (1.5 mL) = 2.5×10⁶ TU/mL + + Method 2: T = (N × F) / V_V + + Where: + • T = Titer, TU/mL + • N = Number of cells transduced + • F = Fraction of cells with fluorescence + • V_V = Virus Volume, mL + + For example: If 15 µL of virus added to 150,000 cells resulted in 25% + fluorescent cells, then the titer is: + (150,000 cells × 0.25 fluorescent) / (0.015 mL) = 2.5×10⁶ TU/mL + + For a more accurate titer, take the average of multiple dilutions. + + +SAMPLE DATA +================================================================================ + +293T cells were transduced with a range of dilutions of pHAGE-TO-dCas9-3XmCherry. +72 h post transduction, cells were assayed for mCherry expression using +fluorescence microscopy. + +Last reviewed on: September 9, 2023 diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ General Transfection.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ General Transfection.txt new file mode 100644 index 0000000000000000000000000000000000000000..60acb80f202df38626b607f866aee3b51b82417b --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ General Transfection.txt @@ -0,0 +1,201 @@ +PROTOCOL: General Transfection +SOURCE: https://www.addgene.org/protocols/transfection/ +================================================================================ + +INTRODUCTION +================================================================================ + +This protocol describes a general method for transfecting mammalian cells using +linear polyethylenimine. Transfections allow for transient expression of a gene +of interest in a target cell line and can be useful for short term studies of +protein function. We specifically use this protocol with a subclone of HEK293T +cells optimized for viral production (AAVpro or Lenti-X), but any HEK293T cell +line should work. This approach can be adapted for different cell lines and +different transfection reagents. + + +WORKFLOW TIMELINE +================================================================================ + +Day 0: Seed HEK293T cells (or a subclone of HEK293T optimized for viral + production) + +Day 1: Transfect Cells + +Day 2 (am): 18 h post transfection - Remove media, replace with fresh media + +Day 3 or more (am): Observe fluorescence, harvest cells, or perform your + experiment + + +EQUIPMENT +================================================================================ + +• Class II, Type A2 Biological Safety Cabinet +• 0.5–10 µL single channel pipette +• 2–20 µL single channel pipette +• 20–200 µL single channel pipette +• 200–1000 µL single channel pipette +• Ice bucket +• CO₂ incubator +• Pipet controller +• Hazardous waste container + + +REAGENTS +================================================================================ + +• DMEM high glucose, Corning 10-013-CV +• L-alanyl-L-glutamine (or alternative stable glutamine such as glutaGRO, + Corning 25-015-CI) +• Heat-inactivated FBS +• Low serum medium such as Opti-MEM or Opti-Pro SFM, Thermo Fisher, 12309019 +• 25 mM chloroquine +• Polyethylenimine, linear MW 25,000 Da +• Microcentrifuge tubes, Neptune 3745.X +• 10 cm tissue culture dish, Corning 430167 +• Hydrochloric acid +• Sodium hydroxide +• 0.22 μm polyethersulfone (PES) filter +• Syringes for filtering + + +REAGENT PREPARATION +================================================================================ + +DMEM Complete: 10% v/v FBS and 4 mM L-alanyl-L-glutamine (or stable alternative +such as glutaGRO) + +To a 500 mL bottle of DMEM high glucose, add 55 mL of heat-inactivated FBS and 5 +mL of 100X glutaGRO. Store at 4 °C. + +💡 PRO TIP: Different brands and lots of FBS can promote or inhibit +transfection. Test a variety of brands and lots of FBS to find one suitable with +your protocols. FBS can be purchased already heat inactivated or it can be +inactivated in the lab by heating to 56 °C for 30 min. + +25 mM chloroquine diphosphate + +1. Dissolve 0.129 g of chloroquine diphosphate salt into 10 mL of sterile water. + +2. Filter sterilize through a 0.22 µm filter. + +3. Aliquot 50–100 µL and store at -20 °C. + +4. Aliquots can be thawed and stored at 4 °C prior to use. Thawed aliquots should + be discarded after 1–2 months. + +1 mg/mL polyethylenimine, linear MW 25,000 Da (PEI) + +1. Dissolve 100 mg of powder into 100 mL of deionized water. + +2. While stirring, slowly add hydrochloric acid until the solution clears. + +3. Check the pH of the solution. Use hydrochloric acid or sodium hydroxide to + adjust the pH to 7.0. Typically, the solution will be basic and will need + adjustment with hydrochloric acid first. + + 💡 PRO TIP: The pH of this solution will drift pretty rapidly upon addition of + acid or base. Add only a few drops at a time, allow them to mix and recheck the + pH to prevent over or undershooting the desired pH. + +4. Allow the solution to mix for 10 min and then recheck the pH to ensure that it + has not drifted. + +5. Filter the solution through a 0.22 µm membrane. + +6. Aliquot 500–1000 µL into sterile tubes. + +7. Store the tubes at -80 °C. + +8. After thawing the solution can be stored at 4 °C for up to 2 months. After 2 + months, discard the tube and thaw a new working stock. + + +CONSIDERATIONS BEFORE YOU START +================================================================================ + +• The health of the cell line is critical for obtaining high levels of virus. + +• HEK293T cells should be split 3 times a week: + - Monday: Plate 1x10⁶ cells in a 75 cm² flask in a volume of 15 mL. + - Wednesday: Plate 1x10⁶ cells in a T75 flask in a volume of 15 mL. + - Friday: Plate 8x10⁵ cells in a T75 flask in a volume of 15 mL. + +• Do not add antibiotics to the media. + +• Use cells that are below passage 20 for viral production. + +• The optimal mass DNA:mass PEI ratio will need to be empirically determined for + each new batch of 1 mg/mL PEI prepared. + +• There may be variation between batches of PEI depending on the user, + quantities of chemical used, volumes, pH adjustment etc. Consequently, each + batch needs to be validated and the best ratio of mass DNA:mass PEI determined. + + +PROCEDURE +================================================================================ + +1. Seed HEK293T cells at 3.8x10⁶ cells per plate in DMEM complete in 10 cm + tissue culture plates. + +2. Incubate the cells at 37 °C, 5% CO₂ for ~20 h. + +3. Gently aspirate media, add 10 mL fresh DMEM complete containing 25 µM + chloroquine diphosphate and incubate ~5 h. + + For 10 mL of DMEM complete, add 10 µL of 25 mM chloroquine diphosphate. + +4. Dilute 18.9 µg of DNA into 500 µL of Opti-Pro SFM. + + 💡 PRO TIP: Endotoxins can inhibit transfection; therefore, plasmid DNA + purification should include an endotoxin removal step. For high quality plasmid + DNA, the plasmid should also be propagated in an endonuclease negative E. coli + strain such as NEB stable. + +5. Dilute 1:3 (µg DNA:µg PEI) in 500 µL total of OptiPro SFM (per 10 cm plate). + + 56.7 µL of 1 mg/mL PEI, MW 25,000 Da in 443.3 µL of OptiPro SFM per 10 cm + plate + + 💡 PRO TIP: The ratio of µg DNA:µg PEI needs to be empirically determined. + Once a batch of PEI is prepared, transfect cells with a fluorescent plasmid + using a variety of ratios. Check the cells 1–2 days after transfection to + determine what ratio gives the highest percentage of GFP positive cells. + + Refer to the table below for a possible range of ratios to test: + + Ratio of DNA:PEI | Amount of DNA (μg) | Volume of 1 mg/mL PEI (μL) + -----------------|-------------------|--------------------------- + 1:1 | 18.9 | 18.9 + 1:2 | 18.9 | 37.8 + 1:3 | 18.9 | 56.7 + 1:4 | 18.9 | 75.6 + 1:5 | 18.9 | 94.5 + 1:6 | 18.9 | 113.4 + +6. Gently add the diluted PEI to the diluted DNA. Add the diluted PEI dropwise + while gently flicking the diluted DNA tube. Incubate the mixture 15–20 min at + RT. + +7. Carefully transfer the transfection mix to your HEK293T cells. Add the + transfection mix dropwise, being careful not to dislodge the cells. + +8. Incubate the cells for 18 h, or until the following morning. + +9. The following morning, carefully aspirate the media. Replace the media with + 15 mL of DMEM complete. + +10. Incubate the cells 24–48 h before checking for protein expression. + + +SAMPLE DATA +================================================================================ + +Lenti-X 293T cells were transfected using 1:1, 1:2, 1:3 and 1:6 µg of pRosetta:µg +of PEI. The 1:2 and 1:3 ratios provided high transfection efficiencies as can be +seen here by the amount of green fluorescent protein expression (green in the +right panels) with a limited effect on cell growth. + +Last reviewed on: November 7, 2023 diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Gibson Assembly Protocol.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Gibson Assembly Protocol.txt new file mode 100644 index 0000000000000000000000000000000000000000..a65259fc427a88694a00e8f248b31702cb1f6c02 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Gibson Assembly Protocol.txt @@ -0,0 +1,136 @@ +PROTOCOL: Gibson Assembly Protocol +SOURCE: https://www.addgene.org/protocols/gibson-assembly/ +================================================================================ + +SUMMARY +================================================================================ + +In 2009 Dr. Daniel Gibson and colleagues at the J. Craig Venter Institute +developed a novel method for the easy assembly of multiple linear DNA fragments +(Gibson et al., 2009). Regardless of fragment length or end compatibility, +multiple overlapping DNA fragments can be joined in a single isothermal reaction. +With the activities of three different enzymes, the product of a Gibson Assembly is +a fully ligated double-stranded DNA molecule. This has proven to be an efficient +and effective method for the assembly of plasmids, and molecular biologists now use +this method extensively. + +Why Gibson Cloning? + +• No need for specific restriction sites. Join almost any two fragments regardless + of sequence. +• No scar between joined fragments. +• Fewer steps. One tube reaction. +• Can combine many DNA fragments at once. + + +PROCEDURE +================================================================================ + +1. Design your plasmid and order primers (see figure to the right). + + When designing your plasmid, think about what DNA segments you will need to + join to create your final plasmid. Adjacent segments should have identical + sequences on the ends (sequences A and B in the figures). These identical + sequences can be created via PCR with primers that contain a 5′ end that is + identical to an adjacent segment and a 3′ end that anneals to the target + sequence. + + One strategy is to order primers that are 60 bp long, with 30 bp matching the + end of the adjacent fragment and 30 bp annealing to the target sequence. + + Avoid strong secondary structures in the homology region. Hairpins in this + region can significantly reduce the efficiency of two homologous ends + annealing. + + 💡 PRO TIP: Cut down on background and enrich for correctly assembled plasmids + by designing primers to split an antibiotic resistance gene to effectively + create an extra part, one part has half of the antibiotic gene and the adjacent + part has the other half. Any colonies should have at least the correctly + assembled antibiotic gene. This trick can also enable replacement of "inverse + PCR" reactions with a two-part Gibson reaction if you're only making a small + change in a plasmid (such as point mutations). + +2. Generate DNA segments by PCR. + +3. Run PCR product on an agarose gel to check for size and yield. If there are + significant amounts of undesired product, gel-purify DNA segments. Otherwise, + PCR purification or even the raw PCR mix can work fine in an assembly if you + want to save time. + +4. Working on ice, combine segments in the Gibson Assembly Reaction. + + 💡 PRO TIP: Yields will be best when the DNA fragments are present in equimolar + concentrations. + + The Gibson Assembly master mix (isothermal reaction mix) consists of three + different enzymes within a single buffer mixture and an optional SSB protein to + improve accuracy and efficiency. Each enzyme has a specific and unique function + for the reaction: + + • T5 Exonuclease: creates single-strand DNA 3' overhangs by chewing back from + the DNA 5' end. Complementary DNA fragments can subsequently anneal to each + other. + + • Phusion High-Fidelity DNA Polymerase: incorporates nucleotides to "fill in" + the gaps in the annealed DNA fragments. + + • Taq DNA Ligase: covalently joins the annealed complementary DNA fragments, + removing any nicks and creating a contiguous DNA fragment. + + 💡 PRO TIP: Add Extreme Thermostable Single-Stranded DNA-Binding protein (ET + SSB) to the isothermal reaction mix. ET SSB protects 3' ssDNA ends from the + ssDNA-specific endonuclease activity of T5 Exonuclease and furthermore reduces + secondary structure of ssDNA. (Rabe & Cepko, 2020). + +5. Incubate the mix for 1 hour at 50 °C or follow manufacturer's instructions. + You can purchase master mix or make your own. + +6. Transform bacteria with the DNA and screen for the correct plasmid product by + restriction digest. + +7. Sequence the important regions of your final plasmid, particularly the seams + between the assembled parts. + + +TIPS AND TROUBLESHOOTING +================================================================================ + +"Stitching" fragments together using oligos + +When you need intervening sequence between two PCR products, one method is to +"stitch" together several oligos. This technique is especially useful for +introducing promoters, terminators, and other short sequences into the assembly +and is used when the part to be inserted is too long to include on overlapping PCR +primers (>60 bp) but too short to make its own part (<150 bp). + +💡 PRO TIP: Please note that the way to design the "stitching" primers and the +amounts of primers to include in the Gibson reaction are different than with +normal PCR primers (Gibson et al., 2010). + +Number of fragments assembled simultaneously + +Multiple fragments can be assembled in one reaction. However, some labs have +observed a sharp decrease in success rate when assembling more than five fragments +at a time. + + +RESOURCES AND REFERENCES +================================================================================ + +New England Biolabs (NEB) sells DNA Assembly kits and master mixes, including +NEBuilder HiFi and Gibson Assembly. They also sell ET SSB. NEB has other resources, +such as a primer design tool. Gibson Assembly® is licensed to New England Biolabs +by TelesisBio. + +References: + +1. Gibson DG, Young L, Chuang RY, Venter JC, Hutchison CA, Smith HO. (2009). + Enzymatic assembly of DNA molecules up to several hundred kilobases. Nature + Methods, 6(5), 343–345. https://doi.org/10.1038/nmeth.1318 + +2. Gibson DG, Smith HO, Hutchison CA, Venter JC, Merryman C. (2010). Chemical + synthesis of the mouse mitochondrial genome. Nature Methods, 7(11), 901–903. + https://doi.org/10.1038/nmeth.1515 + +3. Rabe BA, Cepko C. (2020). A Simple Enhancement for Gibson Isothermal Assembly. + bioRxiv. https://doi.org/10.1101/2020.06.14.150979 diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Handling Plasmids from Addgene - Purifying Plasmid DNA.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Handling Plasmids from Addgene - Purifying Plasmid DNA.txt new file mode 100644 index 0000000000000000000000000000000000000000..c44f7b94bef423f182c273912f97bd9c87975566 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Handling Plasmids from Addgene - Purifying Plasmid DNA.txt @@ -0,0 +1,277 @@ +PROTOCOL: Handling Plasmids from Addgene - Purifying Plasmid DNA +SOURCE: https://www.addgene.org/protocols/purify-plasmid-dna/ +================================================================================ + +INTRODUCTION +================================================================================ + +Many molecular biology techniques require highly purified and concentrated plasmid +DNA. This page will discuss the general procedure for purifying plasmid DNA from +bacterial culture. For details on how to streak a plate to get individual +colonies and to generate liquid bacterial cultures, please see those pages. + +Several companies, such as NEB, Qiagen, Invitrogen, and Promega sell kits for +isolating plasmid DNA in quantities as low as a few micrograms to as much as +several milligrams and at concentrations ranging from 150 ng/μL to several μg/μL. +The protocol below is meant to describe the general procedure for purifying +plasmid DNA from bacterial cultures. If you will be using a kit, follow the kit's +instructions. If you want to perform plasmid purification without using a kit, +you can find a protocol for kit-free plasmid mini-prep at the bottom of this page. + +Last Update: Feb. 8, 2018 + + +EQUIPMENT +================================================================================ + +• Desktop microcentrifuge +• Desktop vortexer +• Vacuum (optional) + + +REAGENTS +================================================================================ + +• Overnight culture of bacteria transformed with your plasmid +• Resuspension buffer +• Denaturing solution +• Renaturing solution +• 2 mg/mL RNase A +• TE or water-saturated phenol-chloroform +• Chloroform +• 100% ethanol or isopropanol +• 90% ethanol +• 70% ethanol +• TE buffer +• 3 M Na-acetate (pH 4.8) + + +PROTOCOL: GENERALIZED DNA PURIFICATION +================================================================================ + +1. Grow an overnight culture of bacteria. + + 💡 PRO TIP: Refer to appropriate DNA prep protocol for volume of bacteria to + grow (low copy plasmids require larger cultures). + +2. Centrifuge the culture to pellet the bacteria before proceeding with DNA + preparation. + + 💡 PRO TIP: If your entire overnight culture cannot fit into a single + centrifuge tube, aliquot it into several tubes/bottles. + +3. Remove the supernatant and resuspend the bacteria in buffer. + + Note: This step gets all of the bacteria back into suspension, but within a + smaller volume of buffer that is compatible with the next solution. + +4. Add a denaturing solution to the resuspended bacteria. + + Note: This step causes the bacteria to lyse, releasing their contents, + including plasmid DNA, into solution. + +5. Add a renaturing solution to the denatured bacteria. + + Note: This step brings the pH back down causing the proteins and genomic DNA + to precipitate, while leaving the smaller plasmids free in solution. + +6. Pellet the proteins and genomic DNA by centrifugation, and remove the + plasmid-containing supernatant. + +7. Add either ethanol or isopropanol to precipitate the plasmid DNA. + +8. Either spin to pellet the DNA or apply the solution to a column that will bind + the now precipitated DNA. + +9. Wash the pellet or column with 70% ethanol to remove excess salt. + +10. Resuspend the DNA pellet, or elute the DNA off of the column using water or a + neutral buffer such as TE. + +You will now have plasmid DNA that has been purified away from the bacterial +proteins and genomic DNA. Depending on the method used, the DNA concentration and +purity will vary. For more information on determining DNA concentration and purity +click here. + + +PROTOCOL: KIT-FREE ALKALINE LYSIS PLASMID MINIPREP +================================================================================ + +Prepare the following solutions: + +Solution I - Resuspension Buffer: +• 25 mM Tris-HCl (pH 8) +• 50 mM glucose +• 10 mM EDTA +• Store Solution I at 4°C + +Solution II - Denaturing Solution: +• 0.2 N NaOH +• 1.0% SDS +• Store Solution II at room temperature + +Solution III - Renaturing Solution (Potassium Acetate): +• 120 mL 5M Potassium acetate +• 23 mL glacial acetic acid +• 57 mL of dH₂O +• Store Solution III at 4°C + +Procedure: + +1. Grow 2 mL overnight cultures from single colonies of bacteria containing your + plasmid of interest. + +2. Add 1.5 mL of the stock culture to a 1.75 mL microfuge tube. + +3. Centrifuge in microfuge tube at 10,000 g for 30 sec. + +4. Pour off the supernatant, being careful not to disturb the bacterial pellet. + +5. Resuspend the pellet in 100 μL of cold Solution I. + +6. Vortex the solution for 2 min or until all bacteria are fully resuspended. + +7. Add 200 μL of Solution II and invert the tube carefully 5 times to mix the + contents. The contents will become clear and thicker as the proteins and DNA + are denatured. + + 💡 PRO TIP: Do not vortex at this stage or the genomic DNA will become sheared + and will therefore contaminate your purified plasmid DNA. + +8. Incubate solution on ice for 5 min. + +9. Add 150 μL of cold Solution III to each tube. + +10. Mix by inverting several times. A white precipitate will be formed which + contains the bacterial proteins and genomic DNA. + +11. Incubate tube on ice for 5 min. + +12. Centrifuge the tube for 5 min at 12,000 g. + + Notes: + • Pellet contains proteins, cell fragments, salt and other extra particles + from solutions. + • Supernatant contains the plasmid DNA separated from bacterial chromosomes. + +13. Collect the supernatant into a new tube by pipetting or carefully pouring. + +14. Optional: Add 5 μL of 2 mg/mL RNase A to the supernatant in the new tube and + incubate at 37 °C for 5 min. + + Note: Ribonuclease A (RNase A) is a pancreatic ribonuclease that digests + single-stranded RNA. + +15. Optional: Perform phenol-chloroform extraction - see protocol below. + + Note: Phenol-chloroform extraction removes remaining contaminant proteins and + RNase A from the DNA sample. When phenol is mixed with the aqueous solution + containing DNA, proteins will move into the phenol phase and will be + separated from the aqueous DNA. + +16. Add either 700 μL of cold 100% ethanol or 350 μL room temperature isopropanol + to the solution to precipitate the plasmid DNA; see detailed protocol below. + + 💡 PRO TIP: If precipitating with ethanol, it is often thought that an + incubation of 20 min to overnight at -20 °C or -80 °C will improve + precipitation. + +17. Pour out the supernatant. + +18. Optional: Wash the pellet with 70% ethanol. + + Note: This step removes excess salt from the pellet which can cause problems + with some common reactions. + +19. Air dry the pellet (can be done by inverting the tube at an angle over + kimwipe) for 20-30 min. + +20. Resuspend pellet with 25-50 μL of TE. + + +PROTOCOL: PHENOL-CHLOROFORM EXTRACTION OF DNA SAMPLES +================================================================================ + +1. Add an equal volume of TE-saturated phenol-chloroform to the aqueous DNA + sample. + + 💡 PRO TIP: Water-saturated phenol-chloroform can be used if TE-saturated is + not available. + +2. Vortex microfuge tube for 30-60 sec. + +3. Centrifuge the tube for 5 min at room temperature on the highest setting. + + Note: You should see clearly separated layers: + • Top Phase - Aqueous DNA phase + • Middle phase - A white layer may appear, consisting of precipitated protein + particles + • Bottom phase - Organic phase (protein) + +4. Pipet the aqueous DNA layer and place it in a new microfuge tube. + +5. Add equal volume of chloroform to the recovered aqueous DNA layer. + +6. Repeat steps 2-4. + + Note: Phenol-chloroform is a hazardous waste - DO NOT pour down sink. + + +PROTOCOL: ETHANOL PRECIPITATION +================================================================================ + +1. To your DNA solution, add 2-2.5 volumes 95% or 100% ethanol and 1/10 volume + of 3 M Na-acetate (pH 4.8). + +2. Invert the microfuge tube to mix. + +3. Optional: Place the tube either at -20 °C overnight OR -80 °C for 30 min OR on + dry ice for 5 min. + + Note: This freezing may help the DNA to precipitate. + +4. Centrifuge solution at high speed (at least 12,000 rpm) for 15-30 min at 4°C. + + Notes: + • Pellet contains the precipitated DNA. + • Supernatant contains residues, salts, and water. + +5. Pour out the supernatant in the sink. + +6. Open and invert the tubes on a paper towel to drain them out. + +7. Wash pellet by adding 500 µL cold 70% ethanol. + + Note: This helps to remove excess salt from the DNA pellet. + +8. Centrifuge solution at high speed (at least 12,000 rpm) for 5 min at room + temp. + +9. Pour out the supernatant in the sink. + + 💡 PRO TIP: Be careful, the pellet is harder to see and less well attached to + the tube after the 70% ethanol wash. You can also pipet the supernatant out of + the tube if you are worried about losing the pellet. + +10. Dry with vacuum or by inverting over paper towel for 5-20 min. + +11. Resuspend dry DNA with TE (10 mM Tris-HCl pH 8, 0.1 mM EDTA). + + 💡 PRO TIP: DNA resuspension can take time, it is a good idea to let it sit + for several hours to overnight at room temperature before quantifying and + using. + +12. Store DNA at 4°C. + + +TIPS AND FAQ +================================================================================ + +• Plasmid purification kits provide the fastest way to obtain a high + concentration of clean plasmid DNA. To improve the purity of plasmid DNA + purified without a kit it is advisable to perform a phenol/chloroform + extraction of the supernatant after step 6 and before step 7. This will help + to remove proteins and other contaminants from the plasmid DNA. + +• It is also advisable to add RNAse to the supernatant after step 6 to eliminate + RNA contamination. This is included in the resuspension buffer of most kits. diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Immunocytochemistry.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Immunocytochemistry.txt new file mode 100644 index 0000000000000000000000000000000000000000..88650441c1a94a61c47e667fe89d0fadddcef46d --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Immunocytochemistry.txt @@ -0,0 +1,204 @@ +PROTOCOL: Immunocytochemistry +SOURCE: https://www.addgene.org/protocols/immunocytochemistry/ +================================================================================ + +INTRODUCTION +================================================================================ + +Immunocytochemistry is a technique that uses antibodies to detect antigens in +cells. Here we describe the basic steps for fixing and labeling cells in culture +with a primary antibody against a target protein and a fluorescent secondary +antibody. This protocol outlines the steps for fixing and labeling HeLa cells for +a target protein using the formaldehyde fixation method. The protocol may need to +be optimized for different cells, target proteins, etc. + +Last Update: January 20, 2022 + + +WORKFLOW TIMELINE +================================================================================ + +Day 1: Seed cells + +Day 3-4: Fix and label cells + + +EQUIPMENT +================================================================================ + +• Pipette controller +• Pipette tips and pipettes +• Rocking platform +• Tweezers +• Fluorescent microscope +• 0.5–10 µL single channel pipette +• 2–20 µL single channel pipette +• 20–200 µL single channel pipette +• 200–1000 µL single channel pipette + + +REAGENTS +================================================================================ + +• 1X PBS +• Microcentrifuge tubes +• Sterile Poly-D-lysine coated coverslips +• HeLa cells +• 24-well plate +• 4% Paraformaldehyde +• 5 mg/mL 4′,6-diamidino-2-phenylindole (DAPI) +• Bovine serum albumin (BSA) +• Triton X-100 +• Primary antibody +• Secondary antibody +• Deionized water +• Microscope slide +• Anti-fade mounting medium +• Laboratory wipes +• 15 mL conical tubes +• 50 mL conical tubes + + +BEFORE STARTING +================================================================================ + +• Refer to the manufacturer's instructions for additional information specific to + your antibodies, such as antibody concentrations, incubation times, and + recommended compatible reagents. + +• Secondary antibodies must match the host species of the primary antibody. For + example, use an anti-mouse secondary antibody for primary antibodies raised in + a mouse. + + +REAGENT PREPARATION +================================================================================ + +Permeabilization buffer: +Dilute 20 µL of Triton X-100 in 10 mL PBS. + +Blocking buffer: +Dilute 0.5 g BSA and 30 µL Triton X-100 in 10 mL PBS. + +Antibody dilution buffer: +Dilute 0.5 g BSA and 150 µL Triton X-100 in 50 mL PBS. + +300 nM DAPI working solution: +1. Prepare a 300 µM DAPI stock solution by diluting 2.1 µL of the 5 mg/mL DAPI + solution to 100 µL PBS. Protect from light. + +2. Prepare a 300 nM DAPI working solution by diluting 5 µL of the 300 µM DAPI + stock solution into 5 mL PBS. Protect from light. + + +PROCEDURE +================================================================================ + +Section 1: Seeding cells + +1. Place a sterile poly-D-lysine coated coverslip in each well of a 24-well cell + culture treated plate. + +2. Seed 5 x 10³ HeLa cells per well. + +3. Allow the HeLa cells to grow to the desired density before labeling. + +Section 2: Fixing and permeabilizing cells + +1. Gently aspirate the media from the 24-well plate. + +2. Wash each well with 500 µL of PBS, remove the wash, and dispose of it in an + appropriate waste container. + +3. Fix each well with 500 µL of cold 4% paraformaldehyde in PBS on ice for 15 + min. + + 💡 PRO TIP: While 4% Paraformaldehyde fixation works well for many target + proteins, it may not be the best fixation method for all. Alternative fixation + methods such as methanol or acetone may be better for some applications. + +4. Remove the paraformaldehyde and follow your institution's laboratory safety + guidelines for disposing of waste in the appropriate container. + +5. Wash 3x for 5 min in 500 µL PBS on a rocking platform. + +6. Permeabilize cells for 10 min at room temperature (RT) on a rocking platform + in 500 µL permeabilization buffer. + +7. Remove the permeabilization buffer and dispose of it in an appropriate waste + container. + +8. Wash 3x for 5 min in 500 µL PBS on a rocking platform. + +Section 3: Labeling with antibody + +1. Block for 20 min at RT on a rocking platform in 500 µL blocking buffer. + +2. Remove the blocking buffer and dispose of it in an appropriate waste + container. + +3. Dilute the primary antibody to the desired concentration in antibody dilution + buffer. + + 💡 PRO TIP: The optimal antibody concentration will vary but generally ranges + from 1-10 µg/mL. + +4. Add 500 µL of the diluted antibody to the wells and incubate 2 h at RT. + +5. Remove the primary antibody and dispose of it in an appropriate waste + container. + +6. Wash 3x for 5 min in 500 µL PBS on a rocking platform. + +7. Dilute the fluorescently-labeled secondary antibody to the desired + concentration in antibody dilution buffer. + + 💡 PRO TIP: The optimal antibody concentration will vary but generally ranges + from 1-10 µg/mL. + +8. Add 500 µL fluorescently-labeled secondary antibody to the wells and + incubate 30 min at RT in the dark. + + 💡 PRO TIP: The plate can be wrapped in foil to block light. + +9. Remove the secondary antibody and dispose of it in an appropriate waste + container. + +10. Wash 3x for 5 min in 500 µL PBS on a rocking platform. + +11. (Optional) Counterstain nuclei with 500 µL of 300 nM DAPI working solution + for 10 min at RT in the dark. + +12. Remove the DAPI and dispose of it in an appropriate waste container. + +13. Wash 3x for 5 min in 500 µL PBS on a rocking platform. + +14. Use tweezers to gently remove the coverslip. + +15. Blot the coverslip with a laboratory wipe to remove excess liquid. + +16. Add 1 drop of anti-fade mounting medium to the microscope slide. + +17. Gently place the coverslip on the microscope slide with the cell side facing + down. + +18. Observe the cell labeling on a microscope with appropriate fluorescent + filters. + + +TIPS AND TROUBLESHOOTING +================================================================================ + +• The optimal fixation method will vary depending on the sample type and the + protein of interest. You may need to try a variety of fixation methods to find + the best conditions for your target. + +• The optimal antibody concentration will vary between antibodies. Review the + manufacturer's instructions before starting your experiment and consider + titrating your antibody to determine the optimal dose. + +• To ensure that your antibody is both functioning as expected and specific, + include a positive control sample that you know expresses the protein, such as + cells transfected with a plasmid to express the protein of interest, and a + negative control sample such as cells that do not express the protein of + interest. diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Isolating a Monoclonal Cell Population by Limiting Dilution.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Isolating a Monoclonal Cell Population by Limiting Dilution.txt new file mode 100644 index 0000000000000000000000000000000000000000..0c04f2c9da202d676e61c42ae1a1788dedfe4271 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Isolating a Monoclonal Cell Population by Limiting Dilution.txt @@ -0,0 +1,239 @@ +PROTOCOL: Isolating a Monoclonal Cell Population by Limiting Dilution +SOURCE: https://www.addgene.org/protocols/limiting-dilution/ +================================================================================ + +INTRODUCTION +================================================================================ + +This protocol describes how to generate a monoclonal cell line from a polyclonal +pool of stable cells. + +Transducing cells with lentivirus results in a heterogenous polyclonal population +that varies in the number of integration events and the site(s) of proviral +integration across cells. Selective pressure on this heterogeneous cell pool +could lead to reduced transgene expression over time, as the lower expressing +clones take over the polyclonal cell pool. Generating a monoclonal cell line by +limiting dilution results in cell populations that are more likely to retain +stable transgene expression. Other methods of generating a monoclonal cell line +include single-cell sorting or isolating individual cells with cloning cylinders. + + +WORKFLOW TIMELINE +================================================================================ + +This protocol begins with a stable cell pool. For details, see our protocol for +generating stable cell lines with lentivirus. + +Day 0: (optional) Seed cells for the generation of conditioned medium (see below + for more details) + +Day 1: Seed individual cells in a 96-well plate + +Day 2–14: Monitor cells for growth and expand cells + +Day 14–30: Analyze and expand monoclonal lines of interest + + +EQUIPMENT +================================================================================ + +• Class II, Type A2 Biological Safety Cabinet +• 0.5–10 µL single channel pipette +• 2–20 µL single channel pipette +• 20–200 µL single channel pipette +• 200–1000 µL single channel pipette +• CO₂ incubator +• Pipet controller +• Hazardous waste container +• Microscope +• Hemocytometer or other cell counter + + +REAGENTS +================================================================================ + +• Polyclonal stable cell pool +• DMEM high glucose, Corning 10-013-CV +• L-alanyl-L-glutamine (or alternative stable glutamine such as glutaGRO, + Corning 25-015-CI) +• Heat-inactivated FBS +• 1X PBS pH 7.4 without calcium or magnesium, Corning 21-040-CV (cations can + affect the attachment of adherent cells) +• Trypsin EDTA (TrypLE, Thermo Fisher 12605-010) +• 6-well tissue culture treated dish, Corning 3516 +• 96-well plate, Corning 3596 +• 0.45 μm polyethersulfone filter, Nalgene, 565-0010 (optional) +• 40 µm cell strainer mesh (optional) +• 10 cm tissue culture dish, Corning 430167 (optional) + + +REAGENT PREPARATION +================================================================================ + +DMEM Complete: 10% v/v FBS and 4 mM L-alanyl-L-glutamine (or stable alternative, +such as glutaGRO) + +To a 500 mL bottle of DMEM high glucose, add 55 mL of heat-inactivated FBS and 5 +mL of 100X glutaGRO. Store at 4 °C. + +Polyclonal stable cell pool: see our protocol for generating stable cell lines +with lentivirus. + +💡 PRO TIP: Because the polyclonal cell pool is always undergoing selection, it's +best to generate monoclonal cell lines from the polyclonal pool as early as +possible, though in theory a monoclonal line could be generated at any time. + + +CONSIDERATIONS BEFORE YOU START +================================================================================ + +• Some cell lines tend not to grow well in sparse/individual cultures due to + lack of secreted growth factors, so not every cell type will be able to grow + under the conditions described in this protocol. + +• Conditioned medium (details below) can be used to enhance the growth of cells + in individual cultures. Other methods for enhancing single cell growth, such + as using culture medium with increased serum concentrations, may be optimal for + different cell types. + +• Before starting this procedure, be sure that the cell pool has been + sufficiently selected with the appropriate antibiotic so that every cell in + the culture has, in theory, been transduced. There are various schools of + thought on using selective medium throughout subsequent experiments. When + selective medium is used, it may have additional biological effects on the cell + line. In the absence of selective medium, there is a chance that the integrated + transgene could be lost through recombination. Some researchers choose to + maintain cells in selective medium at a reduced antibiotic concentration (e.g., + half the concentration that was used for the initial selection). Addgene + recommends that the use of selective medium throughout experiments be determined + empirically, and that the cell population be monitored regularly for transgene + expression. + +• This protocol has been optimized for adherent cells but can be modified for + suspension cells. + +• The number of monoclonal lines generated using this protocol will vary based + on several factors, including the growth properties of the cell lines, the + effects of the transgene, and the specific conditions used. Each 96-well plate + described in this protocol could, in theory, give rise to a maximum of 48 + monoclonal cell lines. When this protocol was performed at Addgene on the A549 + cells described in our sample data, each 96-well plate gave rise to 15–20 + monoclonal lines. + + +PROCEDURE +================================================================================ + +Generating Conditioned Medium (optional) + +1. Seed stable cells such that the next day they will be approximately 50–60% + confluent. For 293T cells this is about 2 × 10⁶ cells in a 10 cm dish. Each + 10 cm dish should be seeded in 10 mL DMEM complete, which will generate enough + conditioned medium for one 96-well plate. + +2. Allow the cells to grow overnight. + +3. Replace the medium on the cells and collect the used (conditioned) media. + +4. Remove any cells from the conditioned medium by filtration through a 0.45 µm + PES filter or centrifugation at >500 x g for 5 minutes. Do not use the medium + if the cells are overly confluent or the medium is acidified (i.e., the medium + appears orange/yellow if using a standard phenol red pH indicator) because the + buildup of waste products could be suboptimal for cell growth. This conditioned + medium will be used to make a cell solution later in this protocol. + +Isolating a Monoclonal Cell Population by Limiting Dilution + +1. Isolate cells from the stable cell pool by trypsinization and break up any + cell clumps into individual cells by passing several times through a + serological pipet or by passing through a 40 µm cell strainer mesh. Count the + cell concentration in this homogenized cell solution using a hemocytometer or + other cell counter. + + 💡 PRO TIP: Prepare a relatively dilute cell solution (<10⁶ cells/mL) before + counting the cells. When you ultimately transfer approximately 50–100 cells to + the conditioned medium, it will be more accurate if a higher volume of + homogenized cell solution is transferred. + +2. Transfer cells from the homogenized cell solution into the conditioned medium + prepared above to make a new cell solution at a concentration of 5 cells/mL. + Prepare approximately 10 mL of this cell solution for each 96-well plate you + plan to seed. If you choose not to use conditioned medium, prepare this cell + solution in fresh complete medium. This 5 cells/mL solution will be used to + seed the 96-well plate. + + Sample Calculation: + • First, use a hemocytometer to quantitate the homogenized cell solution. + • Homogenized cell solution concentration: 4 × 10⁵ cells/mL + • To seed one 96-well plate, make 10 mL of a 5 cell/mL solution. Calculate + the total cells needed: 10 mL × 5 cells/mL = 50 cells + • Determine the volume of homogenized cell solution that corresponds to 50 + cells: (50 cells)/(4 × 10⁵ cells/mL) = 0.125 µL + • Because this is such a small volume, first make 1 mL of a 1:100 dilution of + the homogenized cell solution by adding 10 µL homogenized cell solution to + 990 µL complete medium. Instead of transferring 0.125 µL, now transfer 100 + times that volume, which is 12.5 µL. + • To make the final 5 cell/mL solution, transfer 12.5 µL of the 1:100 dilution + to 10 mL of conditioned medium. + +3. Transfer 100 µL of the 5 cells/mL solution into each well of a 96-well plate. + By doing this, you are seeding the plate at an average density of 0.5 + cells/well. Seeding an average of 0.5 cells/well ensures that some wells + receive a single cell, while minimizing the likelihood that any well receives + more than one cell. + + 💡 PRO TIP: In each 96-well plate, seed one of the corner wells with ~1000 + cells. This will help you focus the microscope later when scanning the plate + for individual cells, which can be difficult to find. + +4. Leave the cells undisturbed in an incubator for 7–14 days. After ~7 days, scan + the plate for cell growth. If you do not observe any colonies, continue + incubating the cells. + + 💡 PRO TIP: Use the well with 1000 cells to focus the microscope, then you can + easily scan the plate for individual cells, which should be on the same focal + plane. + +5. Scan the entire plate and make note of each well in which you see growth. At + this time, the cells will appear as colonies in the well (Figure 1). You will + be able to tell if there was more than a single cell seeded in a well because + you will observe more than one colony. Wells with more than a single colony do + not contain a monoclonal population and should be discarded. + + 💡 PRO TIP: When scanning the plate, be sure to look thoroughly within each + well, especially in the corner of the well as cells tend to settle there. + +6. Once the cells have expanded but before they become over-confluent, trypsinize + the cells and expand them to larger culture dishes, being sure not to cross + contaminate the independent monoclonal lines. + + 💡 PRO TIP: When trypsinizing cells from the 96-well plate, use a microscope + to ensure that the cells have detached from the plate and can be isolated. + When trypsinized, detached cells will exhibit a rounded morphology. + +7. After the monoclonal lines have been sufficiently expanded, screen the lines + for transgene expression and/or other phenotypes. For example, perform Western + blotting to screen for lines with the highest or lowest transgene expression + (Figure 2). + + +SAMPLE DATA +================================================================================ + +Generation of monoclonal cell lines from expansion of individual A549 cells +stably expressing Cas9. A549 cells were transduced with lentiCas9-Blast and then +selected with 1 μg/mL blasticidin for 9 days. Single cells were then plated in +individual wells of a 96-well plate and left undisturbed for 13 days. Colonies +formed in individual wells of a 96-well plate after expansion of single cells for +13 days. Note that growth rate differences can be inferred by the differences in +colony size. + +Cas9 expression in monoclonal cell lines generated from A549 cells transduced with +lentiCas9-Blast. A549 cells were transduced (MOI = 37) and selected with 1 μg/mL +blasticidin for 9 days. Single cells from a stable cell pool were then expanded +for an additional 3 weeks under blasticidin selection. Anti-Cas9 Western blotting +was performed on whole-cell extracts from the initial stable cell pool (pool) and +from individual cell expansions (monoclonal, 1-5). Wild-type A549 cells do not +express Cas9 and are included as a control (WT). Vinculin is a loading control. + +Last reviewed on: September 9, 2023 diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Kit Free RNA Extraction.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Kit Free RNA Extraction.txt new file mode 100644 index 0000000000000000000000000000000000000000..6f8ad908fb71cbeb706704b4e172b99f4e5c6924 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Kit Free RNA Extraction.txt @@ -0,0 +1,266 @@ +PROTOCOL: Kit Free RNA Extraction +SOURCE: https://www.addgene.org/protocols/kit-free-rna-extraction/ +================================================================================ + +INTRODUCTION +================================================================================ + +This protocol describes how to extract RNA from tissues or cells without a kit. The +general steps of this protocol include homogenization/lysis of cells or tissues, +extraction of RNA, precipitation, and resuspension. This protocol provides two +options: using Solution D (see reagent section for recipe) or using an all-in-one +acid guanidinium thiocyanate-phenol solution such as TRIzol®. For the precipitation +step, two options are also included: using Isopropanol or Lithium Chloride. + +This protocol was adapted from Chomczynski P and Sacchi N, 2006 and TRIzol® User +Guide from ThermoFisher Scientific. + + +BEFORE STARTING +================================================================================ + +RNA is not as stable as DNA and is susceptible to degradation by heat, RNases, and +other enzymes. + +💡 PRO TIPS: + +• Always wear gloves, and whenever possible, keep RNA sample and reagents cold and + work quickly to reduce RNA degradation. + +• Keep work area, equipment, and reagents RNase-free (Use an RNase decontamination + solution, such as RNaseZap® or RNase AWAY®, may be used). + +• For more tips on working with RNA, read this blog post on RNA extraction without + a kit. + +Last Update: April 10, 2020 + + +EQUIPMENT +================================================================================ + +• Refrigerated microcentrifuge + (If you only have a non-refrigerated microcentrifuge, see step 4 of either + protocol before you start.) +• Homogenizer +• Vortexer +• -20°C freezer +• -80°C freezer + + +REAGENTS +================================================================================ + +• Solution D (for Protocol Option #1): + - 4 M Guanidinium Thiocyanate + - 25 mM Sodium Citrate, pH 7.0 + - 0.5% (wt/vol) N-laurosylsarcosine (Sarkosyl) + - 0.1 M 2-mercaptoethanol + +• TRIzol® or similar product such as TRI Reagent®, RNAzol®, QIAzol® (for Protocol + Option #2) + +• Water-saturated Phenol + +• 2 M Sodium Acetate pH 4 + +• Chloroform/Isoamyl alcohol (49:1) + +• 75% Ethanol + +• RNase-free water or TE solution + +• RNase free tubes: microcentrifuge tubes, 4 mL polypropylene tubes + +• RNase decontamination solution like RNase AWAY® or RNaseZAP® + +• Isopropanol (for precipitation step, Option A) + +• 7.5 M Lithium Chloride (for precipitation step, Option B) + +• Glycogen (Optional) + +Caution: Make sure to read the SDS (Safety Data Sheet) for safety warnings and +hazards for these reagents. Work in a well-ventilated space and under a fume hood +when working with the volatile reagents in the list above. + + +PROCEDURE +================================================================================ + +Option #1 - Solution D Protocol + +Before starting this protocol, make sure to prepare solution D (see reagent +section above for the recipe). If using TRIzol®, jump down to the Option #2 - +TRIzol® Protocol section below. + +1. Homogenize or lyse tissues or cells in Solution D. + • For tissues: use 1 mL of Solution D per 100 mg of cells. + • For cultured cells: use 1 mL of Solution D per 1 X 10⁷ cells. + +2. Allow sample(s) to sit at room temperature for 5 minutes to allow for + dissociation of the nucleoprotein complexes. + + The effectiveness of your RNA isolation will depend on how effective your cell + lysis protocol is. While simple homogenization is effective for most mammalian + tissues; more hardy tissues such as bone, or bacteria/yeast/plant samples will + require additional steps to effectively lyse open the cells. + +3. Extract RNA from the homogenized sample(s). Transfer tissue/cell lysate to a 4 + mL tube. Add the following sequentially to 1 mL of lysate: + • Add 0.1 mL of 2 M sodium acetate (pH 4.0), mix thoroughly by inversion. + • Add 1 mL water-saturated phenol, mix thoroughly by inversion. + • Add 0.2 mL of Chloroform/Isoamyl alcohol (49:1) and then shake vigorously by + hand for 10 seconds. + +4. Incubate sample(s) for 15 minutes on ice and centrifuge the sample(s) for 15 + minutes at 12,000 × g at 4°C to separate RNA from the rest of the tissue/cell + lysate. + + 💡 PRO TIP: Having your samples spin at 4°C helps reduce RNA degradation. If + you don't have access to a refrigerated centrifuge, you can carefully bring a + centrifuge into a cold room for centrifugation. Once you're done using the + centrifuge, bring this equipment back to room temperature, as prolonged storage + in the cold room may damage it. + +5. Using a pipettor, transfer the top, aqueous phase to a new RNAse-free tube. + + The mixture separates into a bottom organic layer, an interphase layer, and a + top, aqueous layer. Take care to not disturb or collect the interphase layer + with your pipette tip. + + 💡 PRO TIP: To collect as much of the top aqueous phase without disturbing the + interphase layer, consider using a lower volume pipettor like a p200 to collect + a majority of the aqueous phase. You may have to collect twice or more from the + same tube, but unlike using a p1000 tip it will give you more control of where + you're aiming your tip in the tube. + +6. Precipitate your sample(s). You can use either Isopropanol or Lithium Chloride + for this step. + + Isopropanol (Option A): Add 1 volume of Isopropanol to the extracted aqueous + layer. Incubate at -20°C for 1 hour. + + Lithium Chloride (Option B): LiCl selectively precipitates RNA versus DNA or + proteins. Add the correct amount of 7.5 M LiCl solution to bring the + concentration of LiCl in the extracted aqueous layer to 2.5 M. Incubate at + -20°C for 1 hour. + + 💡 PRO TIPS: + • If you anticipate your RNA yield to be small, RNase-free Glycogen may be used + as a carrier to facilitate RNA precipitation. This does not affect the quality + of RNA or downstream applications. + • To improve yield of RNA, instead of incubating at -20°C for 1 hour, you can + try incubating at -80°C overnight. + +7. Centrifuge for 20 minutes at 10,000 x g at 4°C and discard the supernatant. + There should be a gel-like white pellet of total RNA in the bottom of the tube. + +8. Wash the RNA by resuspending the pellet in 0.5–1 ml of 75% Ethanol and vortex + for a few seconds. Centrifuge for 5 minutes at 10,000 x g at 4 °C and remove + the supernatant. + +9. Remove as much of the ethanol wash as possible without disturbing the pellet. + Air-dry the pellet for 5-10 minutes. + + Critical: It is important to not let the pellet get too dry before resuspending, + as this affects the solubility of the RNA. + + 💡 PRO TIP: To prevent overdrying, watch the pellet and carefully remove any + residual ethanol wash and add RNase-free water or TE as soon as the entire tube + is dried but while the white pellet is still visible. + +10. Resuspend RNA pellet in RNase-free water or TE. Quantify and assess the quality + of your RNA sample(s) using a spectrophotometer (such as a Nanodrop), agarose + gel, or bioanalyzer. For more information on nucleic acid quantification, see + our protocol for DNA quantification, which can be modified for RNA. Store your + RNA sample(s) at -80 °C to prevent RNA degradation and avoid multiple + freeze-thaw cycles. + + 💡 PRO TIP: To avoid multiple freeze-thaw cycles of your entire RNA sample, + consider making smaller aliquots of it and storing those in -80°C. + +Option #2 - TRIzol® Protocol + +1. Homogenize or lyse tissues or cells in TRIzol® or a similar product. + • For tissues: use 1 mL of TRIzol® per 100 mg of cells. + • For cultured cells: use 1 mL of TRIzol® per 1 X 10⁷ cells. + +2. Allow sample(s) to sit at room temperature for 5 minutes to allow for + dissociation of the nucleoprotein complexes. + + The effectiveness of your RNA isolation will depend on how effective your cell + lysis protocol is. While simple homogenization is effective for most mammalian + tissues; more hardy tissues such as bone, or bacteria/yeast/plant samples will + require additional steps to effectively lyse open the cells. + +3. Extract RNA from the homogenized sample(s). Add 0.2 mL of Chloroform/Isoamyl + alcohol (49:1) per 1 mL of TRIzol® used. Shake vigorously by hand for 10 + seconds. + +4. Incubate the sample(s) for 2-3 minutes on ice and centrifuge for 15 minutes at + 12,000 × g at 4°C to separate RNA from the rest of the tissue/cell lysate. + + 💡 PRO TIP: Having your samples spin at 4°C helps reduce RNA degradation. If + you don't have access to a refrigerated centrifuge, you can carefully bring a + centrifuge into a cold room for centrifugation. Once you're done using the + centrifuge, bring this equipment back to room temperature, as prolonged storage + in the cold room may damage it. + +5. Using a pipettor, transfer the top, aqueous phase to a new RNAse-free tube. + + The mixture separates into a bottom organic layer, an interphase layer, and a + top, aqueous layer. If using TRIzol®, the bottom layer will be a red-pink + color. Take care to not disturb or collect the interphase layer with your + pipette tip. + + 💡 PRO TIP: To collect as much of the top aqueous phase without disturbing the + interphase layer, consider using a lower volume pipettor like a p200 to collect + a majority of the aqueous phase. You may have to collect twice or more from the + same tube, but unlike using a p1000 tip it will give you more control of where + you're aiming your tip in the tube. + +6. Precipitate your sample(s). You can use either Isopropanol or lithium Chloride + for this step. + + Isopropanol (Option A): Add 1 volume of Isopropanol to the extracted aqueous + layer. Incubate at -20°C for 1 hour. + + Lithium Chloride (Option B): LiCl selectively precipitates RNA versus DNA or + proteins. Add the correct amount of 7.5 M LiCl solution to bring the + concentration of LiCl in the extracted aqueous layer to 2.5 M. Incubate at + -20°C for 1 hour. + + 💡 PRO TIPS: + • If you anticipate your RNA yield to be small, RNase-free Glycogen may be used + as a carrier to facilitate RNA precipitation. This does not affect the quality + of RNA or downstream applications. + • To improve yield of RNA, instead of incubating at -20°C for 1 hour, you can + try incubating at -80°C overnight. + +7. Centrifuge for 20 minutes at 10,000 x g at 4°C and discard the supernatant. + There should be a gel-like white pellet of total RNA in the bottom of the tube. + +8. Wash the RNA by resuspending the pellet in 0.5–1 ml of 75% Ethanol and vortex + for a few seconds. Centrifuge for 5 minutes at 10,000 x g at 4 °C and remove + the supernatant. + +9. Remove as much of the ethanol wash as possible without disturbing the pellet. + Air-dry the pellet for 5-10 minutes. + + Critical: It is important to not let the pellet get too dry before resuspending, + as this affects the solubility of the RNA. + + 💡 PRO TIP: To prevent overdrying, watch the pellet and carefully remove any + residual ethanol wash and add RNase-free water or TE as soon as the entire tube + is dried but while the white pellet is still visible. + +10. Resuspend RNA pellet in RNase-free water or TE. Quantify and assess the quality + of your RNA sample(s) using a spectrophotometer (such as a Nanodrop), agarose + gel, or bioanalyzer. For more information on nucleic acid quantification, see + our protocol for DNA quantification, which can be modified for RNA. Store your + RNA sample(s) at -80 °C to prevent RNA degradation and avoid multiple + freeze-thaw cycles. + + 💡 PRO TIP: To avoid multiple freeze-thaw cycles of your entire RNA sample, + consider making smaller aliquots of it and storing those in -80°C. diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Lab Safety for Biosafety Levels One and Two.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Lab Safety for Biosafety Levels One and Two.txt new file mode 100644 index 0000000000000000000000000000000000000000..5d30c410cfb17208e7fc47d81a374d4834721328 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Lab Safety for Biosafety Levels One and Two.txt @@ -0,0 +1,134 @@ +PROTOCOL: Lab Safety for Biosafety Levels One and Two +SOURCE: https://www.addgene.org/protocols/lab-safety/ +================================================================================ + +INTRODUCTION +================================================================================ + +There are four biosafety levels. This protocol provides information for both +biosafety level 1 (BSL-1) and biosafety level 2 (BSL-2). The purpose of the four +levels is to distinguish between different types of hazards and to provide +protective measures for each level, as each level has different safety +requirements. BSL-1 is designated for those working with microbes that don't cause +disease in healthy humans, for example, non-pathogenic E. coli. BSL-2 is for labs +that work with pathogens including organisms such as Staphylococcus aureus or +Vibrio cholerae. BSL-2 includes all of the precautions needed in BSL-1, along with +additional precautions to prevent injuries, ingestion, and exposures to hazardous +materials. + + +EQUIPMENT +================================================================================ + +• Lab coat +• Close-toed shoes +• Gloves +• Eye protection or face shields +• Eye wash +• Safety shower +• Sharps container +• Biohazard waste container +• Fire blanket +• Fire extinguisher + + +GUIDELINES +================================================================================ + +BSL-1 Guidelines + +Before You Work + +1. Right after entering the lab, put on the proper personal protective equipment + (PPE) and wear it the whole time you are working in the lab. + +2. Do not eat, drink, chew gum, or apply makeup in the laboratory. + +3. Before you start your experiment, make sure your workspace is clean and + uncluttered. Disinfect your workspace with appropriate materials. For example, + you may use 70% ethanol, quaternary ammonium, or bleach solutions. Ask your lab + supervisor what is available and the appropriate contact times for each agent. + Make sure you have enough space to work at your lab bench. + +4. It's possible that while working, you may accidentally come into contact with + hazardous materials. A sink, eyewash station, safety shower, fire blanket, and + extinguisher are also required to be present in the room. Make sure that you + know where these are located before you start. + +5. Use the eyewash station if unwanted or biohazardous materials are splashed onto + your face and/or get into your eyes. + +6. Wash your hands before and after working in the lab. + +7. Ensure that a designated chemical waste accumulation site is present, and that + you have received hazardous waste safety training before starting the work. + Before working with chemicals, first review their material safety data sheets + (MSDS). + +While You Work + +1. Dispose of sharps in a designated sharps container. Sharps include anything that + can pierce your skin, including, but not limited to broken glass or needles. + Sharps containers must be thick walled, impenetrable by a needle, and must be + able to close securely. + +2. Biohazard signs should be placed in all areas containing biohazardous materials, + including biohazardous waste. Dispose of waste that may be contaminated with + pathogens or chemicals that present a danger to people and the environment in + biohazard containers. Biohazardous materials are decontaminated prior to + disposal, commonly done with an autoclave. + +3. Only mechanical pipetting should be done in the laboratory. Don't mouth pipette! + +4. There may be some times when you may be working with a protocol that requires + shaking or mixing, which may produce aerosols or splashes. These procedures + should be done underneath a hood. + +5. Clean any spills immediately, and decontaminate as necessary. For large spills + that cannot be easily cleaned, evacuate and close off the area and alert the + chemical hygiene officer. + +BSL-2 Guidelines + +Remember, the BSL-1 laboratory guidelines above are expected to be followed in +addition to BSL-2 guidelines below, including PPE protocols. + +1. Working in a BSL-2 laboratory requires laboratory glasses in addition to coat + and gloves. This lab coat should not be worn outside of the BSL-2 area. + +2. BSL-2 laboratories must be clearly marked as "BSL-2." The names and contact + information of the laboratory manager should be clearly visible in the room and + on the door. + +3. BSL-2 centrifugation steps require an aerosol-tight lid and rotors should be + loaded and unloaded in a biosafety cabinet. + +4. BSL-2 safety protocols require bloodborne pathogens training. It is strongly + recommended that anyone participating in BSL-2 work receives a hepatitis B + vaccination or titer prior to starting work in the laboratory. + +5. For some biohazardous waste, an autoclave or other method for decontaminating + must be used for proper disposal. Liquid BSL-2 waste can be decontaminated in + a final concentration of 10% bleach for 30 minutes before pouring down the + drain. Solid BSL-2 waste can be collected in designated biohazardous waste + containers that can be autoclaved. + + +CONCLUSION +================================================================================ + +Although simple, following appropriate BSL-1 and BSL-2 protocol goes a long way. +It is the easiest way to ensure that you're doing your work in the safest way +possible. Protecting yourself and working smart in the lab is important! + + +DISCLAIMER +================================================================================ + +The SOP presented here has been designed by the Addgene nonprofit plasmid +repository and is being shared outside of Addgene for informational purposes only. +If you choose to reuse or repurpose this SOP in another location, please note that +you do so at your own risk; you should ensure that any local guidance is also +adhered to. None of the authors, contributors, administrators, or anyone else +associated with Addgene, can be held responsible for your use of the information +contained in or linked to from these web pages. diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Lentivirus Production Protocol.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Lentivirus Production Protocol.txt new file mode 100644 index 0000000000000000000000000000000000000000..9100b87232188932a4e4f43190faa1d11f288028 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Lentivirus Production Protocol.txt @@ -0,0 +1,224 @@ +PROTOCOL: Lentivirus Production Protocol +SOURCE: https://www.addgene.org/protocols/lentivirus-production/ +================================================================================ + +INTRODUCTION +================================================================================ + +This protocol can be used to produce lentivirus from a lentiviral vector +transfected into 293T cells using a polyethylenimine (PEI) transfection protocol. +This procedure can be modified for alternative packaging cell lines or +transfection reagents. Once produced, lentivirus can be used for a variety of +downstream applications such as stable-cell line generation. + + +WORKFLOW TIMELINE +================================================================================ + +Day 0: Seed 293T packaging cells + +Day 1 (pm): Transfect packaging cells + +Day 2 (am): 18 h post-transfection. Remove media, replace with fresh media. + +Day 3-4 (am): Harvest virus + + +EQUIPMENT +================================================================================ + +• Class II, Type A2 Biological Safety Cabinet +• 0.5–10 µL single channel pipette +• 2–20 µL single channel pipette +• 20–200 µL single channel pipette +• 200–1000 µL single channel pipette +• Ice bucket +• CO₂ incubator +• Pipet controller +• Hazardous waste container +• pH meter +• Stir plate +• Magnetic Stir Bar + + +REAGENTS +================================================================================ + +• DMEM high glucose, Corning 10-013-CV +• L-alanyl-L-glutamine (or alternative stable glutamine such as glutaGRO, + Corning 25-015-CI) +• Low serum medium such as Opti-MEM or Opti-Pro SFM, Thermo Fisher, 12309019 +• 25 mM chloroquine +• Polyethylenimine, linear MW 25,000 Da +• Heat-inactivated FBS +• 1x PBS pH 7.4 without calcium or magnesium, Corning 21-040-CV (cations can + affect the attachment of adherent cells) +• 0.45 μm polyethersulfone filter, Nalgene, 565-0010 +• Microcentrifuge tubes, Neptune 3745.X +• 10 cm tissue culture dish, Corning 430167 +• 15 mL conical tubes, VWR 21008-216 +• Hydrochloric acid +• Sodium hydroxide +• 0.22 μm polyethersulfone (PES) filter +• Transfection grade DNAs: Lentiviral Packaging plasmid(s), Envelope plasmid, and + Transfer plasmid encoding your insert of interest + + +REAGENT PREPARATION +================================================================================ + +DMEM Complete (also known as D10): 10% v/v FBS and 4 mM L-alanyl-L-glutamine +(or stable alternative, such as glutaGRO) + +To a 500 mL bottle of DMEM high glucose, add 55 mL of heat-inactivated FBS and 5 +mL of glutaGRO. Store at 4 °C. + +💡 PRO TIP: Different brands and lots of FBS can promote or inhibit +transfection. Test a variety of brands and lots of FBS to find one suitable with +your protocols. FBS can be purchased already heat inactivated or it can be +inactivated in the lab by heating to 56°C for 30 min. + +1 mg/mL polyethylenimine, linear MW 25,000 Da (PEI) + +1. Dissolve 100 mg of powder in 100 mL of deionized water. + +2. While stirring, slowly add hydrochloric acid until the solution clears. + +3. Check the pH of the solution. Use hydrochloric acid or sodium hydroxide to + adjust the pH to 7.0. Typically, the solution will be basic and will need + adjustment with hydrochloric acid first. + + 💡 PRO TIP: The pH of this solution will drift rapidly upon addition of acid + or base. Add only a few drops at a time, allow them to mix and recheck the pH + to prevent over or undershooting the desired pH. + +4. Allow the solution to mix for 10 min and then recheck the pH to ensure that it + has not drifted. + +5. Filter the solution through a 0.22 μm membrane. + +6. Aliquot 500–1000 μL into sterile tubes. + +7. Store the tubes at -20 °C or -80 °C. + +8. After thawing, the solution can be stored at 4 °C for up to 2 months. After 2 + months, discard the tube and thaw a new working stock. + +9. The optimal mass DNA:mass PEI ratio will need to be empirically determined for + each new batch of 1 mg/mL PEI and for each cell line. + + +CONSIDERATIONS BEFORE YOU START +================================================================================ + +• The health of the packaging cell line is critical for obtaining high viral + titer. + +• 293T cells should be split 3 times a week: + - Monday: Plate 1×10⁶ cells in a T75 flask in 15 mL DMEM Complete. + - Wednesday: Plate 1×10⁶ cells in a T75 flask in 15 mL DMEM Complete. + - Friday: Plate 8×10⁵ cells in a T75 flask in 15 mL DMEM Complete. + +• Do not add pen-strep to the media. + +• Use cells that are below passage 15 for viral production. + + +PROCEDURE +================================================================================ + +1. Seed 293T packaging cells at 3.8×10⁶ cells per plate in DMEM Complete in 10 cm + tissue culture plates. + +2. Incubate the cells at 37 °C, 5% CO₂ for ~20 h. + +3. Prepare a mixture of the three transfection plasmids into OptiPro SFM: + + Reagent | Amount per 10 cm dish* + ---------------------------|------------------------ + Packaging Plasmid (psPAX2) | 1.3 pmol + Envelope Plasmid (pMD2.G) | 0.72 pmol + Transfer Plasmid* | 1.64 pmol + OptiPro SFM to total | 500 μL + + *Plasmid concentrations and ratios should be optimized for each transfer + plasmid. + + 💡 PRO TIP: Endotoxins can inhibit transfection; therefore, plasmid DNA + purification should include an endotoxin removal step. For high quality plasmid + DNA, the plasmids should also be propagated in an endonuclease negative E. + coli strain such as NEB stable. + +4. Make a mixture of a total of 500 μL PEI-OptiPro SFM with enough PEI such that + the ratio of μg DNA:μg PEI is 1:3 (1000 μL total per 10 cm dish). + + Using transfer plasmid pHAGE TRE dCas9-KRAB (total μg of plasmid DNA 27.8 μg), + this would be 83.4 μL of 1 mg/mL PEI in 416.6 μL of OptiPro SFM per 10 cm + dish. + + 💡 PRO TIP: There can be batch to batch variation when making the PEI working + stock, therefore the ratio of μg DNA:μg PEI needs to be empirically determined. + Once a batch of PEI is prepared, transfect cells with a fluorescent plasmid + using a variety of ratios. Check the cells 1-2 days after transfection to + determine what ratio gives the highest percentage of GFP positive cells. + + Refer to the table below for a possible range of ratios to test: + + Ratio of DNA:PEI | μg of DNA | μL of 1 mg/mL PEI + -----------------|-----------|------------------ + 1:1 | 18.9 | 18.9 + 1:2 | 18.9 | 37.8 + 1:3 | 18.9 | 56.7 + 1:4 | 18.9 | 75.6 + 1:5 | 18.9 | 94.5 + 1:6 | 18.9 | 113.4 + +5. Gently add the diluted PEI mixture to the diluted DNA mixture. Add the diluted + PEI dropwise while gently flicking the diluted DNA tube. Incubate the mixture + 12–15 min at RT. + +6. During the incubation, add 10 mL of DMEM Complete to a 15 mL conical and an + appropriate amount of 25 mM chloroquine to the conical so that the final + concentration in the dish (once transfection mixes are added) will be 25 uM of + chloroquine. + +7. After the incubation, add the DNA:PEI-Max mix to the conical containing the + media and chloroquine and mix well. + +8. Gently aspirate the media out of the previously seeded 10 cm plate. + +9. Slowly pipette the transfection mix onto the 10 cm plate, being careful not to + disturb the cells. + +10. Incubate the cells for 18 h, or until the following morning. + +11. The following morning, carefully aspirate the media. Replace the media with + 10 mL of DMEM Complete or OptiPro SFM. + +12. Incubate the cells. + +13. Virus can be harvested at 48, 72, and 96 h post transfection in individual + harvests or a combined harvest where all the individual harvests are pooled. + If pooling harvests, transfer the harvested media to a polypropylene storage + tube and store at 4 °C between harvest. + +14. Centrifuge the viral supernatant at 2100 rcf for 5 minutes to pellet any + packaging cells that were collected during harvesting. + +15. Filter supernatant through a 0.45 μm PES filter. + +16. The viral supernatant can be stored at 4 °C for several hours but should be + aliquoted and snap frozen in liquid nitrogen and stored at -80 °C as soon as + possible to avoid loss of titer. + + +SAMPLE DATA +================================================================================ + +293T cells were transfected with the GFP-expression plasmid pRosetta using μg +total DNA to μg PEI ratios of 1:1, 1:2, 1:3 and 1:6. The 1:2 and 1:3 total +DNA:PEI μg ratios provided high transfection efficiencies as measured by the +highest proportion of GFP positive cells without limiting cell growth. Left +panels: bright field images; right panels: GFP channel images. + +Last reviewed on: August 2, 2023 diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Lentivirus ddPCR Titration.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Lentivirus ddPCR Titration.txt new file mode 100644 index 0000000000000000000000000000000000000000..616110bfa1be5000cb5a5c6913e3f82577784e17 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Lentivirus ddPCR Titration.txt @@ -0,0 +1,420 @@ +PROTOCOL: Lentivirus ddPCR Titration +SOURCE: https://www.addgene.org/protocols/lentivirus-ddpcr-titration/ +================================================================================ + +INTRODUCTION +================================================================================ + +This protocol describes how to use droplet digital PCR (ddPCR) to titer lentivirus +vectors. This protocol specifically uses primers and probes targeting integrated +copies of the Rev response element (RRE) in the target cells but can be modified +for other targets. Primers and a probe against the cellular ribonuclease P/MRP 30 +kDa subunit (RPP30) are used as a control for normalization. The dilution series +outlined in this protocol is based on an LV titer range of 1E+05–1E+09 TU/mL, +where TU is transducing units and generally represents the number of infectious +viral particles. Users may need to run lower or higher dilutions depending on +their particular sample. + +This protocol was modified from the publication Wang et al. (2018). + + +BEFORE STARTING +================================================================================ + +• Thaw the master mix, primers/probe mixes and samples on ice before use. + +• Wipe down all pipettes and surfaces with 10% bleach. + + +SAFETY WARNINGS +================================================================================ + +Lentivirus is generally considered biosafety level 2+. Please ensure that you are +in compliance with your institution's biosafety regulations. + +Last Update: July 7, 2023 + + +WORKFLOW TIMELINE +================================================================================ + +Day 1: Seed and transduce cells + +Day 4: Treat cells with Benzonase and harvest cells + +Day 4+: ddPCR and analysis + + +EQUIPMENT +================================================================================ + +• Class II, Type A2 Biological Safety Cabinet +• Aspirating unit +• Microcentrifuge, Eppendorf, 5425R +• Droplet digital PCR System, Bio-Rad, DX200 +• Thermal Cycler, Bio-Rad, T100 +• PCR Plate Sealer, Bio-Rad, PX1 +• 1–10 µL single channel pipette +• 20–200 µL single channel pipette +• 200–1000 µL single channel pipette +• 2–50 µL multichannel pipette +• 20–200 µL multichannel pipette +• Ice bucket +• 96-well freezer blocks +• Vortex, VWR, 10153-688 +• Mini Centrifuge, Thermo Scientific, 10199-452 + + +REAGENTS +================================================================================ + +• GeneJet Genomic DNA Purification Kit, Thermo Fisher, K0721 +• 6-well tissue culture treated dish, VWR, 29442-042 +• DMEM, high glucose, pyruvate, Corning, 10-013-CV +• Heat-inactivated FBS +• L-alanyl-L-glutamine (or alternative stable glutamine such as glutaGRO, + Corning 25-015-CI) +• 1X PBS pH 7.4 without calcium or magnesium, Corning 21-040-CV (cations can + affect the attachment of adherent cells) +• Trypsin EDTA (TrypLE, Thermo Fisher, 12605010) +• Ethanol, VWR, EX0276-1 +• Benzonase 250 U/µl, Millipore #71205-3 +• Polybrene 10 mg/mL, Millipore, TR-1003-G +• Molecular Biology Grade Water, Hyclone, SH30538.02 +• ddPCR Supermix for Probes no dUTP, Bio-Rad,1863023 +• Droplet generation oil, Bio-Rad, 1863005 +• DG8 cartridge, Bio-Rad, 1864008 +• DG8 gasket, Bio-Rad, 1863009 +• DG8 cartridge holder, Bio-Rad, 1863051 +• 8-strip PCR tubes, Axygen, PCR-02-FCP-C +• ddPCR 96-well PCR plates, Bio-Rad, 12001925 +• Pierceable foil heat seal, Bio-Rad, 1814040 +• Polystyrene reservoirs, VWR, 89094-662 +• Microcentrifuge tubes, VWR, 87003-294 + +Primers/probe targeting RRE: +• forward primer: tgtgccttggaatgctagt +• probe (FAM): tttggaatcacacgacct +• reverse primer: aatttctctgtcccactccatc + +• PrimePCR ddPCR Copy Number Assay: RPP30, Human, Bio-Rad, 10031244 + + +REAGENT PREPARATION +================================================================================ + +DMEM Complete: +• 500 mL DMEM, high glucose, pyruvate +• 55 mL heat inactivated premium grade, fetal bovine serum +• 5 mL glutaGRO + +50 U/mL benzonase: +• 15 mL DMEM Complete +• 3 µL of 250 U/µL benzonase + + +PROCEDURE +================================================================================ + +Transducing Cells + +1. Thaw the virus on ice. + +2. Prepare the following dilution series of virus in DMEM complete: + • Prepare 7 microcentrifuge tubes with the appropriate amount of media volume + listed in the chart below. + • For the first virus dilution, add 160 µL of viral stock to 240 µL of media. + • When adding the virus to the diluent, pipette 10 times, to remove virus from + pipette tip. + • To mix the dilution, set the P200 pipette to 200 µL and pipette 10–20 times. + • Use a new pipette tip to transfer 200 µL of the first dilution into the next + dilution. + • Repeat for all dilutions as indicated in the chart below. + + Dilution Factor | Virus Volume to Dilute | Media Volume | Total Volume + ----------------|------------------------|--------------|------------- + 2.5 | 160 µL viral stock | 240 µL | 400 µL + 5 | 200 µL of 2.5-fold | 200 µL | 400 µL + | dilution | | + 10 | 200 µL of 5-fold | 200 µL | 400 µL + | dilution | | + 20 | 200 µL of 10-fold | 200 µL | 400 µL + | dilution | | + 40 | 200 µL of 20-fold | 200 µL | 400 µL + | dilution | | + 80 | 200 µL of 40-fold | 200 µL | 400 µL + | dilution | | + 160 | 200 µL of 80-fold | 200 µL | 400 µL + | dilution | | + +3. Add 150 µL of each viral dilution to a well of a 6-well plate (1 dilution per + well). Leave one well untransduced (add 150 µL of DMEM complete instead of a + viral dilution). + + Remember, this is an additional 10-fold dilution of the virus stock! Don't + forget to factor this into your calculations later (see calculation example + below). + +4. Seed 300,000 cells/well in 1350 µL media and 11.1 µg/mL Polybrene into the + wells containing the virus and the untransduced control. + + 💡 PRO TIP: For even seeding, prepare a batch for 10 wells with 3,000,000 + cells in 13.5 mL of media and 11.1 µg/mL Polybrene. Mix the cell suspension + well before seeding. + +5. Mix each well with a 1 mL pipette 5–10 times. + +6. The final volume in the well is 1.5 mL, and the final Polybrene concentration + is 10 µg/mL. + +7. Mix well and incubate 72 h. + +Benzonase Digestion and Cell Harvest + +1. Gently aspirate media from the 6-well plates. Be sure to use a new aspirating + pipette for each well as to not contaminate cell conditions with others. + +2. Gently add 1.5 mL of 50 U/mL Benzonase in DMEM complete to each well. + +3. Incubate at 37 °C for 30 min. + +4. Gently aspirate media from wells, using a new aspirating pipette for each well. + +5. Wash wells with 1 mL of 1X PBS and aspirate, using a new aspirating pipette + for each well. + +6. Detach cells by incubating with 200 µL TrypLE for 1–2 min. + +7. Resuspend cells in 500 µL DMEM complete and transfer to a microcentrifuge tube. + +8. Centrifuge for 5 min at 100 x g. + +9. Gently aspirate supernatant. + +10. Wash cell pellets in 500 µL PBS. + +11. Centrifuge for 5 min at 100 x g. + +12. Gently aspirate supernatant. + +13. Extract genomic DNA according to the GeneJet Genomic DNA Purification Kit + instructions. + +14. Determine the concentration of each sample on a spectrophotometer. + +15. Prepare 25 ng/µL stocks of each sample. Samples can be used for ddPCR + immediately or stored at -20 °C until ready to use. + +Preparing for ddPCR + +1. Thaw samples, primers/probe mixes, and master mix on ice. + +2. Before handling any virus dilutions, get materials ready. + +3. Vortex primers/probe mixes and master mix for 15 sec then spin 10 sec in a + mini centrifuge and place on ice. + +4. Wipe down a DG8 cartridge holder with bleach and place it in the Biological + Safety Cabinet (BSC). + +5. Make sure that the BSC is supplied with sufficient pipette tips. + +6. Pre-warm the 96-well plate sealer by gently touching the screen. + +Preparation of the Master Mix + +1. Place a ddPCR plate onto a chilled 96-well freezer block and set aside in the + BSC to cool. + +2. Prepare the RRE/RPP30 master mix in a microcentrifuge tube as shown below. For + 8 samples prepare enough master mix for 9 samples. + + RRE/RPP30 Master Mix: + + Component | Volume | 9X Volume | Final Concentrations + ---------------------------------|--------|-----------|--------------------- + 2X ddPCR Supermix for Probes, | 10 µL | 90 µL | 1X + no dUTP | | | + 20X RRE target primers/probe | 1 µL | 9 µL | 900 nM, 250 nM + (FAM) | | | + 20X RPP30 primers/probe | 1 µL | 9 µL | 900 nM, 250 nM + (HEX/VIC) | | | + Nuclease-free water | 4 µL | 36 µL | + Total Volume | 16 µL | 144 µL | + +3. Vortex the master mix for 15 sec and spin in a mini centrifuge for 10 sec + before use. + +4. Place an 8-well PCR tube strip into a chilled 96-well freezer block. + +5. Add 16 µL of the master mix to each PCR tube. Be careful to dispense to the + bottom of the tube without collecting drops along the side of the tube. + +6. Add 4 µL of the 25 ng/µL samples to the appropriate PCR tubes. Pipette back + and forth 10 times to mix. + +Generating the Droplets + +1. Place a DG8 cartridge into the cartridge holder. + +2. Using a 2–50 µL multichannel pipet, load 20 µL of the reaction mixtures into + the middle wells of the cartridge. + +3. Add 800 µL of droplet generation oil to a polystyrene reagent reservoir. + +4. Using the 20–200 µL multichannel pipet, load 70 µL of droplet generation oil + into the bottom row of wells. + +5. Cover the cartridge with the DG8 gasket, making sure that it is secure. + +6. Transfer the cartridge holder to the droplet generator. Close the lid and wait + for the droplets to be generated. + +7. Once the droplets have been generated, use a 20–200 µL multichannel pipette to + collect 40 µL of droplets. + + 💡 PRO TIP: To ensure that the droplets are not disrupted, insert the pipette + tips directly in the center of the well and tilt to a 45° angle. Count to 20 + while slowly and gently pipetting the droplets. + +8. Transfer the droplets to a prechilled PCR plate. + + 💡 PRO TIP: To ensure that the droplets are not disrupted, insert the pipette + tips and gently touch the bottom of the well. Lift the tips ~1mm. Touch the + side of the well and tilt the pipette tips at a 45° angle. Count to 20 while + slowly and gently dispensing the droplets down the side of the tube. + +9. Place a Pierceable Foil Heat Seal on the PCR plate with the red line facing up. + If the plate sealer is not at temperature, touch the screen on the plate sealer + to allow it to get to temperature. Once the temperature is reached, place the + PCR plate with the foil onto the metal support block. Place the block in the + plate sealer and press the 'Seal' button. + +10. After the plate has been sealed, proceed to thermocycling. + +Thermal Cycling + +Run the following PCR parameters: + +Cycling Step | Temperature (°C) | Time (min) | Ramp Rate (°C/sec) | # Cycles +--------------------|------------------|------------|-------------------|---------- +Enzyme Activation | 95 | 10 | 2 | 1 +Denaturation | 94 | 0.5 | 2 | 40 +Annealing/Extension | 60 | 1 | 2 | 40 +Enzyme Deactivation | 98 | 10 | 2 | 1 +Hold | 4 | ∞ | 2 | 1 + +After PCR is complete, transfer the plate to the Droplet Reader. + +1. Open the QuantaSoft software to set up a new plate layout. Designate the + sample name, experiment type, supermix type (ddPCR Supermix for Probes), the + target names and target types. + +2. When the plate layout is complete, select 'Run' to begin the droplet reading. + +3. When the droplet reading is complete, export the data from all wells as a CSV + file which will be used to calculate the titer. + + +CALCULATIONS +================================================================================ + +In the experimental setup above, the following virus dilutions were used to +transduce cells: + +Initial dilution factor | Dilution factor after additional 10-fold dilution into +of virus stock | 6-well plate +------------------------|------------------------------------------------------- +2.5 | 25 +5 | 50 +10 | 100 +20 | 200 +40 | 400 +80 | 800 +160 | 1600 + +To calculate the titers, first calculate the number of viruses per cellular +genome: + +V = 2 × (copies RRE / copies RPP30) + +Since the cellular gene RPP30 is used as a reference to the cellular genome, it +is assumed that there are two copies of RPP30 in diploid cells, thus the reason +for multiplying by 2. + +Use the viruses/genome to calculate the infectious titer: + +T = (V × C × D) / v + +Where: +• T = Infectious titer, TU/mL +• V = Viruses per genome +• C = # Cells per well +• D = Dilution factor +• v = Virus volume, mL + +*In the experimental setup above, the cells per well is 300,000 and the virus +volume refers to the total volume the cells were transduced, which is 1.5 mL per +well. + +Take the average infectious titer obtained from the appropriate dilutions to +calculate the final infectious titer. + + +TIPS AND TROUBLESHOOTING +================================================================================ + +• We recommend wiping down all pipettes and equipment with 10% bleach prior to + use and keeping all reagents and samples on ice or pre-chilled 96-well freezer + blocks during use. + +• To reduce the risk of contaminating reagents we recommend making small aliquots + of master mixes, and primers/probe mixes prior to use. + + +SAMPLE DATA +================================================================================ + +When analyzing data there should be a clear distinction between negative droplets +(black) and positive droplets (blue/green). + +The concentration of RRE positive droplets in the untransduced control should be +close to zero (A01). + +In this protocol, the lentiviral particles are serially diluted and used to +transduce HEK293T cells. Genomic DNA is extracted from the target cells and +assayed for integrated copies of RRE. Since the samples that are assayed are +diluted 2-fold serially, the concentration of RRE positive droplets should +decrease by a factor of 2 across the dilutions. RPP30 copies should be relatively +constant across samples. + +In the RRE example below, 2-fold serial dilutions of a sample were loaded in wells +B01-H01. As shown in the image (Figure 1) and table below, the concentration of +RRE positive droplets increases by a factor of ~2 as you progress from the higher +dilutions to the lower dilutions (blue). + +As shown in the image (Figure 2) below, the concentration of RPP30 positive +droplets stays relatively even across samples (green). + +To increase the accuracy of the titer, calculate an average of several dilutions. + +Example dilutions and titrations: + +Sample ID | Dilution | Copies/20 µL RRE | Copies/20 µL RPP30 | Viruses/genome | Infectious titer (TU/mL) | Average +----------|----------|------------------|---------------------|----------------|--------------------------|-------- +1 | 800 | 428 | 22020 | 0.03887375114 | 6.22E+06 | +2 | 400 | 768 | 18360 | 0.08366013072 | 6.69E+06 | +3 | 200 | 1620 | 15840 | 0.2045454545 | 8.18E+06 | +4 | 100 | 3180 | 20540 | 0.3096397274 | 6.19E+06 | +5 | 50 | 8960 | 17080 | 1.049180328 | 1.05E+07 | +6 | 25 | 14440 | 24260 | 1.190436933 | 5.95E+06 | + | | | | | | 7.29E+06 +7 | Untransduced | 1 | 6.4 | 17940 | 0.0007134894091 | 1.43E+02 + + +REFERENCES +================================================================================ + +Wang Y, Bergelson S, Feschenko M. Determination of Lentiviral Infectious Titer by +a Novel Droplet Digital PCR Method. Hum Gene Ther Methods. 2018 Apr;29(2):96-103. +doi: 10.1089/hgtb.2017.198. PMID: 29378428 diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Ligation Independent Cloning.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Ligation Independent Cloning.txt new file mode 100644 index 0000000000000000000000000000000000000000..cad8be235b81935d6a5e9418f88a921c53cfa528 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Ligation Independent Cloning.txt @@ -0,0 +1,113 @@ +PROTOCOL: Ligation Independent Cloning +SOURCE: https://www.addgene.org/protocols/lic/ +================================================================================ + +OVERVIEW +================================================================================ + +Ligation Independent Cloning (LIC) obviates the need for the time-consuming +ligation step of traditional cloning methods. In traditional cloning, +base-pairing in the short overlapping regions (usually 4 bp) does not provide +enough stability to hold the plasmid together through the +transformation/replication process. LIC employs long overhangs to form a stable +association between fragments, allowing for transformation without ligation. +Because of its dual polymerase/exonuclease functions, T4 DNA polymerase can +create overhangs of varying length (typically 10-12 bp) based on a specific +sequence. The annealed but nicked vector product is then repaired during the +replication cycle. + +Empty vectors for LIC typically employ type II restriction enzymes (e.g. BsaI), +which cut at a specified distance from their recognition sequence. This can +create multiple distinct overhangs with a single enzyme, and remove the restriction +sites from the final product (no "cloning scars"). A "stuffer" sequence allows +for electrophoretic separation of linearized vector from the reaction mixture, and +may provide counter-selection for negative clones as in the example shown here. The +manufacturer of an LIC-specific vector will provide the homologous sequence which +must be built into the 5' end of the respective primers. Below we use +pNIC28-Bsa4 as an example of LIC experimental design. + + +PROTOCOL +================================================================================ + +Step 1: Design Your Primers + +Primer design for LIC is often as simple as using the backbone manufacturer's +suggested leader sequence fused to your gene of interest, in frame with the +start codon or tag sequences (where appropriate). The primer length is dependent +on the T4 Pol "chew back" reaction, in which a single dNTP is included to stop +the exonuclease function of the enzyme and shift its activity back to polymerase. +In our case, dGTP will be used in the reaction, meaning that T4 Pol will remove +bases from the 3' end of the cut site until the first G is reached (shown in +blue), at which point it will add back the G and become stalled. Therefore, the +primer must begin with the following T, so that there are no gaps in the final +assembly. In this case, 15 bp of homologous sequence is used, plus a minimum of +18 bp of your template sequence. 5' and 3' primers will have different leader +sequences, but operate on the same principle (homologous to the first G on 3'-5' +strand from cut site). For simplicity, only the 5' primer is shown here. + +Note: Use web-based primer design software to ensure a melting temperature +between 50-60°C for your PCR primers. + +Step 2: Linearize Vector + +In this example, the vector is cut at two points by the enzyme BsaI, removing the +stuffer sequence and sacB counter-selection marker (see our restriction digest +protocol). After the digest is complete, you will need to separate the +linearized vector from the reaction mixture by gel electrophoresis followed by +gel purification. The cut vector end will now look like this: + +Note: Elute your purified digestion and PCR products with sterile water (instead +of TE buffer) to ensure optimal salt concentrations in subsequent reactions. + +Step 3: Create Vector Overhangs + +Treat the linearized vector with T4 DNA polymerase to "chew back" the free 3' +ends, following the manufacturer's instructions. In this case, we will include +the free nucleotide dGTP in the reaction (exclude all other nucleotides from +standard polymerase protocol), causing the enzyme to perform exonuclease activity +until the first "G" in the sequence. Because the polymerase reaction is favored +over the exonuclease reaction, the polymerase will add back the guanosine residue +and become stalled. A typical T4 Pol reaction is shown. Mix the components (add +the T4 last) and incubate at room temperature for 30 minutes. Inactivate T4 Pol +by heating to 75° for 20 minutes. + +T4 DNA Polymerase Reaction: + +Volume (μl) | Reagent | Final Conc. +------------|----------------------|------------ +4 | 10X Buffer | 1X +20-30 | Eluted DNA | 10-50 ng/μl +1 | dGTP (100mM) | 2.5 mM +2 | DTT (100 mM) | 5 mM +1 | BSA (10 μg/μl) | 0.25 μg/μl +1 | T4 DNA polymerase | 0.075 units/μl +sterile dH₂O to 40 μl + +Step 4: Amplify Insert by PCR + +Perform PCR amplification of your insert following the instructions provided by +your polymerase manufacturer. It is very important to remove all free nucleotides +from your PCR product before proceeding, as they will interfere with the +exonuclease activity of T4 Pol in the following step. This may be accomplished +by gel purification. + +Step 5: Create Insert Overhangs + +Treat your purified PCR product with T4 Pol in the presence of dCTP (not dGTP), +corresponding to the first base removed by the restriction digest to create the +free 5' end of the cut vector (shown in blue here). The T4 reaction may be +stopped by heating to 75° for 20 minutes. + +Step 6: Anneal and Transform + +Mix your treated vector and insert at a molar ratio of 1:2 or 1:3, using between +20 and 50 ng of vector per annealing reaction. This should be done in a small +volume with no additional water (<5 μl). It is advisable to set up multiple +reactions by holding the vector concentration fixed across multiple +concentrations of insert, thereby increasing your chances of success. Set up a +vector only control with water instead of the insert. Incubate the annealing +reaction for 5 minutes at room temperature, then add 1 μl of 25 mM EDTA, +followed by another 5 minutes at room temperature. The reaction is now ready for +transformation. Use 1-2 μl of annealing reaction for each transformation, +following a standard protocol. diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Molecular Biology Protocol - Restriction Digest of Plasmid DNA.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Molecular Biology Protocol - Restriction Digest of Plasmid DNA.txt new file mode 100644 index 0000000000000000000000000000000000000000..d1dac17553931bc6c407b02fcd143252593cb350 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Molecular Biology Protocol - Restriction Digest of Plasmid DNA.txt @@ -0,0 +1,144 @@ +PROTOCOL: Restriction Digest of Plasmid DNA +SOURCE: https://www.addgene.org/protocols/restriction-digest/ +================================================================================ + +INTRODUCTION +================================================================================ + +Restriction enzyme digestion takes advantage of naturally occurring enzymes that +cleave DNA at specific sequences. There are hundreds of different restriction +enzymes, allowing scientists to target a wide variety of recognition sequences. +For a list of many commonly used restriction enzymes, visit NEB. + +Restriction enzyme digestion is commonly used in molecular cloning techniques, +such as PCR or restriction cloning. It is also used to quickly check the identity +of a plasmid by diagnostic digest. + +Last Upload: Oct. 11th, 2016 + + +EQUIPMENT +================================================================================ + +• Electrophoresis chamber +• Pipetman + + +REAGENTS +================================================================================ + +• Liquid DNA aliquot of your plasmid of interest (see below for recommend + amounts) +• Appropriate restriction enzyme (see manufacturer's instructions for proper + amount) +• Appropriate restriction digest buffer (see manufacturer's instructions) +• Gel loading dye +• Electrophoresis buffer +• Pipet tips + + +PROCEDURE +================================================================================ + +1. Select restriction enzymes to digest your plasmid. + + 💡 PRO TIP: To determine which restriction enzymes will cut your DNA sequence + (and where they will cut), use a sequence analysis program such as Addgene's + Sequence Analyzer. + +2. Determine an appropriate reaction buffer by reading the instructions for your + enzyme. + + 💡 PRO TIP: If you are conducting a double digest (digesting with two enzymes + at the same time), you will need to determine the best buffer that works for + both of your enzymes. Most companies will have a compatibility chart, such as + the double digest finder tool from NEB. + +3. In a 1.5mL tube combine the following: + • DNA + • Restriction Enzyme(s) + • Buffer + • BSA (if recommended by manufacturer) + • dH₂O up to total volume + + 💡 PRO TIPS: + • The amount of DNA that you cut depends on your application. A diagnostic + digest typically involves ∼500 ng of DNA, while molecular cloning often + requires 1 µg of DNA. The total reaction volume usually varies from 10-50 µL + depending on application and is largely determined by the volume of DNA to + be cut. + + • A typical restriction digestion reaction could look like this: + - 1 µg DNA + - 1 µL of each Restriction Enzyme + - 3 µL 10x Buffer + - 3 µL 10x BSA (if recommended) + - x µL dH₂O (to bring total volume to 30µL) + + • The amount of restriction enzyme you use for a given digestion will depend on + the amount of DNA you want to cut. By definition: one unit of enzyme will + cut 1 µg of DNA in a 50 µL reaction in 1 hour. Using this ratio, you can + calculate the minimal amount of enzyme for your reaction. However, keep in + mind that restriction enzyme activity is determined under ideal conditions + with very clean DNA, so using a little more enzyme is advisable. Reactions + are often performed with 0.2-0.5 µL of enzyme because it is difficult to + pipette less volume than this; 0.2-0.5 µL will likely be more enzyme than + you will need, but that's okay because a little more enzyme is usually + better. + +4. Mix gently by pipetting. + +5. Incubate tube at appropriate temperature (usually 37 °C) for 1 hour. Always + follow the manufacturer's instructions. + + 💡 PRO TIP: Depending on the application and the amount of DNA in the reaction, + incubation time can range from 45 mins to overnight. For diagnostic digests, + 1-2 hours is often sufficient. For digests with >1 µg of DNA used for cloning, + it is recommended that you digest for at least 4 hours. + +6. If you will be using the digested DNA for another application (such as a + digestion with another enzyme in a different buffer), but will not be gel + purifying it, you may need to inactivate the enzyme(s) following the digestion + reaction. This may involve incubating the reaction at 70 °C for 15 mins, or + purifying the DNA via a purification kit, such as a QIAGEN DNA cleanup kit. + See the enzyme manufacturer's instructions for more details. + +7. To visualize the results of your digest, conduct gel electrophoresis. + + +TIPS AND FAQ +================================================================================ + +• Restriction enzymes MUST be placed in an ice bucket immediately after removal + from the -20 °C freezer because heat can cause the enzymes to denature and lose + their function. + +• If you are having difficulty finding an enzyme that cuts your vector's + multiple cloning site (MCS), but does not cut your insert, you could try using + two different enzymes that have compatible sticky ends. See NEB's compatible + cohesive ends chart. + +• If you cannot find compatible sticky ends, you will need to fill in the + overhangs and conduct a blunt end ligation. Use T4 DNA Polymerase or Klenow + DNA Polymerase I for 3′ overhang removal and 5′ overhang fill-in. + +• If you are using blunt ends or a single enzyme to cut the vector, you will need + to use a phosphatase to prevent re-circularization of the vector if you are + cloning in an insert. CIP (calf alkaline phosphatase) or SAP (shrimp alkaline + phosphatase) are commonly used. Follow the manufacturer's instructions. + +• If your enzyme did not cut, check to make sure that it isn't methylation + sensitive. Plasmids grown in Dam or Dcm methylase positive strains will be + resistant to cleavage at certain restriction sites. See NEB's table of + methylation sensitive restriction sites. + +• Sometimes enzymes cut sequences which are similar, but not identical, to their + recognition sites. This is due to "Star Activity" and can happen for a variety + of reasons, including high glycerol concentration. Learn more at NEB's website + about star activity. + +• If you are digesting a large number of plasmids with the same enzyme(s) (for + instance, in a diagnostic digest), you can create a "Master Mix" consisting of + all of the reaction components except for the DNA. Aliquot your DNA into + individual tubes and then add the appropriate amount of Master Mix to each + tube. This will save you time and ensure consistency across the reactions. diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Personal Protective Equipment (PPE) for BSL-1 and BSL-2 Labs.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Personal Protective Equipment (PPE) for BSL-1 and BSL-2 Labs.txt new file mode 100644 index 0000000000000000000000000000000000000000..4e12be18b229d1daa57ba32e0bc47237d2a446a1 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Personal Protective Equipment (PPE) for BSL-1 and BSL-2 Labs.txt @@ -0,0 +1,80 @@ +PROTOCOL: Personal Protective Equipment (PPE) for BSL-1 and BSL-2 Labs +SOURCE: https://www.addgene.org/protocols/ppe/ +================================================================================ + +INTRODUCTION +================================================================================ + +There are four biosafety levels. This protocol provides information for both +biosafety level 1 (BSL-1) and biosafety level 2 (BSL-2). The BSL-1 classification is +for labs working with low-risk microbes posing little to no threat of infection or +disease in healthy humans. Many of the precautions are meant to protect individuals +from potential accidents such as spills. BSL-2 is different because it includes +labs that work with agents associated with diseases in healthy humans. BSL-2 +includes all of the precautions needed in BSL-1, however there are additional +precautions that lie beyond PPE. + + +EQUIPMENT +================================================================================ + +• Lab coat +• Close-toed shoes +• Gloves +• Eye protection and face shields, as needed + + +GUIDELINES +================================================================================ + +1. Your lab coat should be buttoned to protect your body and clothing from + potential spills. + +2. Gloves should fit well enough to be snug to your hand, but not so tight that + you cannot perform your duties. Be sure to try out different sizes to know your + fit. It is best to not reuse gloves. Dispose your gloves in a biohazard waste + container. + +3. Your lab coat and gloves should not be worn in "common areas" such as the lunch + room, offices, and bathroom. These items should remain in the laboratory. When + traveling between lab spaces, take your glove off of one hand and use your bare + hand to open doors. + +4. For those with latex allergies, be aware that some gloves may contain latex. + Consider nitrile gloves as an alternative. + +5. For extra precautions, tuck your sleeves into your gloves to prevent potential + spills down your sleeve. This may or may not be possible depending on the type + of sleeve. + +6. Lastly, don't touch your face! + +7. Close-toed shoes and long pants should be worn to protect your legs and feet + from potential spills. If wearing open-toed shoes, cloth coverings or + "booties" can be used to protect your feet. + + 💡 PRO TIP: If they are able, sometimes scientists work for a long time while + standing. Wear comfortable shoes that cushion your feet. + +8. Eye protection such as goggles and/or face shields can be used as needed. For + BSL-2 work always wear glasses/goggles in addition to the BSL-1 requirements. + + +CONCLUSION +================================================================================ + +Although simple, following appropriate PPE protocol goes a long way. It is the +easiest way to ensure that you're doing your work in the safest way possible. +Protecting yourself is important! + + +DISCLAIMER +================================================================================ + +The SOP presented here has been designed by the Addgene nonprofit plasmid +repository and is being shared outside of Addgene for informational purposes only. +If you choose to reuse or repurpose this SOP in another location, please note that +you do so at your own risk; you should ensure that any local guidance is also +adhered to. None of the authors, contributors, administrators, or anyone else +associated with Addgene, can be held responsible for your use of the information +contained in or linked to from these web pages. diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Pipetting Protocol.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Pipetting Protocol.txt new file mode 100644 index 0000000000000000000000000000000000000000..ac74a638b4e90bbc1b9cee32533e775f0c2bba61 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Pipetting Protocol.txt @@ -0,0 +1,184 @@ +PROTOCOL: Pipetting Protocol +SOURCE: https://www.addgene.org/protocols/pipetting/ +================================================================================ + +INTRODUCTION +================================================================================ + +The pipette is an essential tool for nearly anyone in molecular biology. You'll use +a pipette in many scenarios to accurately dispense small amounts of liquid (think: +0.1 µL to 1 mL). When working in a laboratory, properly dispensing liquid ensures +the accuracy of your experiment and any changes to the amount you are dispensing can +negatively impact your experimental results. This protocol will guide you in +selecting the correct pipette and pipette tip and using the pipette. + +Last Update: September 2022 + + +EQUIPMENT +================================================================================ + +• Pipettes +• Pipette tips +• Waste container +• Containers to hold measured liquid (ex: microfuge tube, bottle, etc.) +• Labels for containers + + +REAGENTS +================================================================================ + +• Liquid for pipetting + + +BACKGROUND INFORMATION +================================================================================ + +Anatomy of a Pipette + +This front view photo of a P1000 pipette shows the plunger at the top, which is +used to draw and expel liquid into the pipette tip, the volume display which shows +the set volume for the the pipette, and the tip ejector ring at the bottom which +pushes the pipette tip off of the pipette. + +This side view photo of a P1000 pipette shows the volume adjustment ring right +below the plunger. This ring changes the pipette volume. Below that is the tip +ejector button which is used to push the tip ejector down the pipette to remove the +tip. + +Choosing a Pipette and Pipette Tips + +Although there are many different types of pipettes that have different mechanisms +to disperse liquids, this protocol is focused on single channel pipettes. These come +in standard sizes: P2, P10, P20, P200, and P1000. The table shows the pipette with +the appropriate dispense volume: + +Pipette | Dispense Volume +-----------|---------------- +P2 | 0.2 to 2 µL +P10 | 1 to 10 µL +P20 | 2 to 20 µL +P100 | 10 to 100 µL +P200 | 20 to 200 µL +P1000 | 100 to 1,000 µL + +Each pipette should be used with the appropriate tips, which are made in a number of +sizes and colors depending on the pipette they are used with and the volume to be +dispensed. The boxes that the tips come in often indicate a volume range that the +tip can hold. This should give you an idea of what pipette to use with it. + +The purpose of the pipette tip is so that the same pipette can be used for +measuring different samples without cross contamination as long as the tip is +changed between samples. Tips can come loose in a bag, or can come preloaded into +tip boxes. In either case, once assembled into their boxes, pipette tips can be +sterilized in an autoclave as needed to prevent contamination. When not in use, the +tip box should be closed to prevent contamination. + +Reading the Volume on the Pipette + +Although each pipette performs the same function, the numbers are read differently +on each type of pipette. This section will help you understand how to read each +display to dispense the correct amount of liquid reagent. + +• P1000: The first red digit is thousands of µL, the middle is hundreds, and the + third is tens. Therefore, 1000 µL would read as 100 from top to bottom, while + 650 µL would read as 065. + +• P200: The first digit is hundreds of µL, the second is tens, and the third is + ones. Therefore 100 µL would read as 100 from top to bottom, while 95 µL would + read as 095. + +• P20: The first digit is tens of µL, the second is ones, and the third (red) + digit is tenths. Therefore, 10 µL would read as 100, while 2.2 µL would read as + 022. + +• P2: The first digit is ones of µL, the second red digit is tenths, and the + third (red) digit is hundredths. Therefore, 1 µL would read as 100, while 0.5 µL + would read as 050. + +Each volume display on these pipettes will also have small tick marks at the bottom. +For the P1000, this represents the ones. For the P200, this represents the first +decimal place. For the P20, this represents the second decimal place, and for the +P2 this represents the third decimal place. + + +PROCEDURE +================================================================================ + +How to Pipette + +Now that you know the different parts of the pipette, how to select tips, and how to +read a pipette, you're ready to begin using the pipette. To the right is a photo of +how you might hold a pipette. + +1. Without moving past the maximum possible setting on the pipette, set the desired + volume of the liquid on the pipette. Depending on the pipette you're using, you + will be rotating dials behind the numerical display or the top of the plunger of + the pipette. + +2. Select the pipette tip that is designed to fit your pipette. To load a tip onto + a pipette, open the tip box and push the end of the pipette onto the tip. Do not + touch the tips with your fingers to avoid contaminating the tip or puncturing + your glove. Ensure that the tip is properly set on the pipette to ensure + pipetting accuracy. + +3. Once the pipette is set and you have the liquid you wish to pipette ready, push + down the plunger. There will be multiple "stops" on the plunger, where you feel + resistance while pressing down on the pipette. Stop at the first "stop." The + first stop expels enough air from the pipette for an accurate measurement in the + next step. The second stop is meant to expel excess liquid from the tip once + you've reached step 8. + +4. Continuing to hold down the plunger, gently lower the pipette tip into the + liquid. Do not submerge the pipette itself into the liquid and avoid touching + the pipette to the inside of the tube. Only the tip should be in the liquid. + + 💡 PRO TIP: If pipetting from a relatively large container holding a small volume + of liquid, tilt the container holding the liquid so that it's easier for the + pipette tip to reach the liquid. Aim to let only the pipette tip into the + container in order to avoid contaminating the contents. + +5. Once the end of the tip is submerged, slowly release the plunger, allowing it to + go back to its resting position. + +6. Wait for the liquid to stop flowing into the pipette tip. Liquids of various + viscosity have different flow rates. The more viscous a liquid, the lower the + flow rate into the pipette tip. + +7. Once the liquid has finished drawing into the pipette tip, lift the pipette so + that the tip exits the liquid. When you lift the pipette tip out of the liquid, + no liquid should drip from the tip. This could indicate that the tip is not on + the pipette properly. + +8. Place the pipette tip into the container you are using to hold the measured + liquid (ex: another microcentrifuge tube, a bottle etc.). If there is already + other liquid in the receiving tube, place the pipette tip into the liquid. If + this is a new container, place the tip near the bottom of and gently in contact + with the container (capillary action between the container and the liquid will + help draw the liquid out of the pipette tip). Then, slowly press down on the + plunger all the way to the second stop to release the liquid. + + 💡 PRO TIP: Dispense until the first stop, wait, and then dispense to the second + stop to expel any residual liquid in the tip. + +9. Before releasing the plunger, lift the pipette tip out of the liquid. Once you + are clear of the liquid you can slowly release the plunger. Remove the entire + pipette from the container making sure not to touch the sides of the container + with the pipette. + +10. Discard the pipette tip by holding the pipette tip over your dedicated waste + container and pressing on the tip ejector button. If pipetting biohazardous + materials, be sure to discard into a biohazardous waste container. + + +CONCLUSION +================================================================================ + +Pipetting accurately and precisely is important since even small changes in the +volume could affect your experiments. Beyond knowing the proper way to pipette, +it's important for scientists to calibrate their pipettes to make sure that they +are properly tuned to dispense the correct amounts of liquid. + +If you are pipetting the same amount of liquid into different tubes or into wells +of a microplate, you may consider using a multichannel pipette. Please watch +Addgene's protocol on multichannel pipetting to learn more. diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Plasmid Cloning by PCR (with Protocols).txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Plasmid Cloning by PCR (with Protocols).txt new file mode 100644 index 0000000000000000000000000000000000000000..a4fdc0472fc4b977b6ef2b1920befcc44db0daba --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Plasmid Cloning by PCR (with Protocols).txt @@ -0,0 +1,91 @@ +Title: Addgene: Plasmid Cloning by PCR (with Protocols) +URL: https://www.addgene.org/protocols/pcr-cloning/ +================================================================================ + +Protocols +Plasmid Cloning by PCR +Plasmid Cloning by PCR +You may also like... +Restriction Digest of Plasmid DNA +DNA Ligation +Bacterial Transformation +Summary +PCR based cloning is incredibly versatile and allows for nearly any piece of DNA to be placed into a backbone vector of choice with minimal limitations. +Background +In its simplest form, PCR based cloning is about making a copy of a piece of DNA and at the same time adding restriction sites to the ends of that piece of DNA so that it can be easily cloned into a plasmid of interest. +For this example, we will describe how to copy a cDNA from one vector into a new vector that is better suited for analyzing the gene’s function. The process is shown graphically in the following cartoon, in which we are adding EcoRI and NotI sites to Your Gene of Interest (YGOI) for ligation into a recipient plasmid. +Designing Primers for PCR Based Cloning +The basic PCR primers for molecular cloning consist of: +Leader Sequence: +Extra base pairs on the 5' end of the primer assist with restriction enzyme digestion (usually 3-6bp). +Restriction Site: +Your chosen restriction site for cloning (usually 6-8bp). +Hybridization Sequence: +The region of the primer that binds to the sequence to be amplified (usually 18-21bp). +When selecting restriction sites, you should use a DNA analysis tool, such as +Addgene’s Sequence Analyzer +, to allow you to identify which restriction sites are present in a given sequence. You want to choose enzymes that: +Do not cut within your insert. +Are in the desired location in your recipient plasmid (usually in the Multiple Cloning Site (MCS)), but do not cut elsewhere on the plasmid. +Bonus: It is helpful to choose restriction enzymes that can both function in the same buffer, as this will save time later. +In our example, we will use EcoRI and NotI to ligate our cDNA into the recipient plasmid. Remember to insert your DNA in the correct orientation in the recipient plasmid by viewing the MCS and fusing the upstream restriction site to the forward primer and the downstream restriction site to the reverse primer. +Next, we need to examine the DNA sequence that we want to amplify and design primers that will bind to and replicate it. The following image shows the ends of the ORF and how these are used for primer design: +Because we are cloning an ORF, we want to clone from the start codon (ATG) to the stop codon (TGA, in this example). Assuming you are amplifying from plasmid DNA (rather than from genomic DNA or a cDNA library), roughly 18-21bp is usually sufficient to give specificity and to also be compatible with a standard PCR reaction. Therefore, our Forward Primer will use the sequence 5'-ATGTGGCATATCTCGAAGTAC-3' for the region that binds the ORF and we will add the EcoRI restriction site (GAATTC) to the 5’ end of this primer, making our Forward Primer 5'-GAATTCATGTGGCATATCTCGAAGTAC-3'. +Many restriction enzymes do not cut DNA efficiently at the end of a linear piece (see +(Link opens in a new window) +NEB +for more information). Thus, we recommend that you add 3-6 bases upstream of your restriction site to improve cutting efficiency. You can generally add any 6 bases, but you should ensure that the bases do not result in the formation of a hairpin structure within your primer. In our case, we will add TAAGCA, resulting in a final Forward Primer sequence of 5'-TAAGCAGAATTCATGTGGCATATCTCGAAGTAC-3'. +For the Reverse Primer, the design is similar, but we need to use the reverse complement to get PCR amplification. We can start similarly, taking the final 18bases of the ORF, including the stop codon (5'-TGGCATATCTCGAAGTACTGA-3'), then adding NotI (GCGGCCGC) and then TAAGCA to improve restriction enzyme digestion. This gives us a sequence of 5'-TGGCATATCTCGAAGTACTGAGCGGCCGCTAAGCA-3' (30bp with 18bp of homology to the ORF). We now need to generate the reverse-complement of this sequence so that we can successfully amplify the ORF. You can generate the reverse-complement using existing software (a quick internet search will lead you to +(Link opens in a new window) +here +and many others). If we put the sequence we chose for our reverse primer (5’-TGGCATATCTCGAAGTACTGAGCGGCCGCTAAGCA-3’) into this calculator we get a final Reverse Primer sequence of 5’-TGCTTAGCGGCCGCTCAGTACTTCGAGATATGCCA-3’. +Experimental Procedure +Run PCR and Purify the PCR Product +Run PCR to amplify your insert DNA. It is important to use a high fidelity taq polymerase to minimize mutations. The fidelity of the polymerase becomes more important the longer the expected PCR product is. You should select an annealing temperature based on the melting temperature (Tm) of the portion of the primer that hybridizes to the sequence to be amplified (the ORF in this case), not the Tm of the entire primer. If you are amplifying from a plasmid or simple template, there is very little chance for mis-priming, so you can use a pretty wide range of annealing temperatures, but you may need to increase your primer length and increase the Tm if you are trying to clone from genomic DNA, a cDNA library, or by RT-PCR. +Isolate your PCR product from the rest of the PCR reaction using a kit, such as the +(Link opens in a new window) +QIAquick PCR Purification Kit +. The PCR product is now ready for restriction digestion. +Digest Your DNA +Set up +restriction digests +for your PCR product and recipient plasmid. Because you lose some DNA during the gel purification step, it is important to digest plenty of starting material. We recommend using your entire PCR reaction and 1μg of recipient plasmid. It is also critical that as much of the recipient plasmid as possible be cut with both enzymes, and therefore it is important that the digest goes at least 4 hours and as long as overnight. +If you are going to use only one restriction enzyme, or enzymes that have compatible overhangs or no overhangs after digestion, you will need to use a phosphatase to prevent re-circularization of the vector. You should treat your digested recipient vector with a phosphatase prior to the ligation step or prior to the gel purification step, depending on the phosphatase you choose. CIP (calf alkaline phosphatase) or SAP (shrimp alkaline phosphatase) are commonly used. Follow the manufacturer’s instructions. +Isolate Your Insert and Vector by Gel Purification +Run your digest DNA on an +agarose gel +and conduct a +gel purification +to isolate the DNA. When running a gel for purification purposes it is important to have nice crisp bands and to have space to cut out the bands. Because of this we recommend that you use a wide gel comb, run the gel on the slower side, and skip lanes between samples. In addition to a DNA ladder standard, it is also a good idea to run an uncut sample of each vector to help with troubleshooting if your digests don’t look as you expected. +When cloning by PCR, it is especially important to run the product on a gel. This allows you to visualize that your PCR product is the anticipated size and that your band is strong (indicating that the PCR reaction worked and that you have a sufficient amount of DNA). +Once you have cut out and purified your insert and vector bands away from the gel, it is important to +determine the concentration of recovered DNA +. +Ligate Your Insert Into Your Vector +Conduct a +DNA Ligation +to fuse your insert to your recipient plasmid. +We recommend around 100ng of total DNA in a standard ligation reaction. You ideally want a recipient plasmid to insert ratio of approximately 1:3. Since the number of base pairs for each varies, it is difficult to calculate this based on DNA concentration alone. One method is to conduct 2 ligations for each plasmid you are trying to create, with varying ratios of recipient plasmid to insert. +It is also important to set up negative controls in parallel. For instance, a ligation of the recipient plasmid DNA without any insert will tell you how much background you have of uncut or self-ligating recipient plasmid backbone. +Transformation +Proceed with the +transformation +according to the manufacturer’s instructions for your competent cells. +For most standard cloning, you can transform 1-2μl of your ligation reaction into competent cells such as DH5alpha or TOP10. If using much less total DNA (<1ng) or if you are having trouble getting colonies, you might want to use higher competency cells. Additionally, if your final product is going to be very large (>10kb) you might want to use electro-competent cells instead of the more common chemically-competent cells. +The number of bacterial colonies resulting from your transformation will give you the first indication as to whether your transformation worked. Your recipient plasmid + insert plate should have significantly more colonies than the recipient plasmid alone plate. The recipient plasmid alone control will tell you your “background” level or more specifically it will tell you how many colonies you can expect on your recipient plasmid + insert plate that are not correct. +If you have a high number of colonies on your recipient plasmid alone plate, you can try ligating the recipient plasmid alone in the presence and absence of ligase. If the colonies are a result of uncut empty plasmid, you will still have colonies when you do not add ligase. If the colonies are a result of recipient plasmid self-ligation, you will see significantly more colonies when you add ligase. +If you do not see any colonies, you should conduct a positive control to ensure that your transformation worked. You could also try varying the amount of recipient plasmid to insert. +Isolate the Finished Plasmid +Finally, you will need to pick individual bacterial colonies and check them for successful ligations. Pick 3-10 colonies depending on the number of background colonies on your control plate (the more background, the more colonies you will need to pick) and grow overnight cultures for DNA purification. +After +purifying the DNA +, conduct a +diagnostic restriction digest +of 100-300ng of your purified DNA with the enzymes you used for the cloning. Run your digest on an +agarose gel +. You should see two bands, one the size of your vector and one the size of your new insert. +Verify your Plasmid by Sequencing +PCR based cloning carries a much higher risk for mutation than restriction enzyme based cloning. DNA replication by PCR has error rates that range from roughly 1 per 500bp to roughly 1 per 10 million bp depending on the polymerase used. Because of this, no matter which taq polymerase you use, it is important that you sequence the final product. +Reference Page +Top +Index diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Plasmid Cloning by Restriction Enzyme Digest (with Protocols).txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Plasmid Cloning by Restriction Enzyme Digest (with Protocols).txt new file mode 100644 index 0000000000000000000000000000000000000000..712c035ffe1fa025e134b6022ce64d1932297e2f --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Plasmid Cloning by Restriction Enzyme Digest (with Protocols).txt @@ -0,0 +1,168 @@ +PROTOCOL: Plasmid Cloning by Restriction Enzyme Digest (with Protocols) +SOURCE: https://www.addgene.org/protocols/subcloning/ +================================================================================ + +SUMMARY +================================================================================ + +The following technique can be used to easily move any piece of DNA from one +vector to another as long as it is already bounded by restriction sites that are +also present in the same orientation on your target vector. If you are not sure +what vector to use, you can check out our Empty Backbone Reference. + + +BACKGROUND +================================================================================ + +Subcloning by restriction digest is a commonly used lab technique. For the +purposes of this tutorial we will discuss how to move a cDNA from one plasmid to +another. However, the same technique can be used to move promoters, selectable +markers, or any other DNA element between plasmids. + +Let's assume that you are beginning a new project on your gene of interest (YGOI +for short). You might need to express YGOI in cultured mammalian cells. The +problem is that the only version of full-length cDNA you can find for YGOI is in a +bacterial expression vector. Using subcloning, you can easily move YGOI into a +mammalian expression vector. + + +DESIGN (CHOOSING ENZYMES) +================================================================================ + +Many DNA analysis tools, including Addgene's Sequence Analyzer, allow you to +identify which restriction sites are present in a given sequence. When selecting +restriction enzymes, you want to choose enzymes that: + +• Flank your insert, but do not cut within your insert + +• Are in the desired location in your recipient plasmid (usually in the Multiple + Cloning Site (MCS)), but do not cut elsewhere on the plasmid + +• Will result in your insert being in the correct orientation in the recipient + plasmid. (You don't want to express the antisense version of your gene!) + +• Are in frame with tags or fusion proteins in the recipient plasmid (if you are + creating a fusion protein) + +Ideally, you will find two different restriction enzymes for your subcloning. It +is also possible to use a single enzyme, but this will require phosphatase +treatment of your recipient plasmid as well as a specifically designed test digest +later to verify that the insert was cloned in the correct orientation. + +If you cannot find enzymes that meet these criteria, do not fear. You have other +options, such as: + +Adding desired restriction sites to flank your insert: You can use PCR Based +Cloning and add restriction sites to the ends of your oligos. This will allow +you to produce a version of your insert flanked by restriction sites compatible +with the recipient plasmid's MCS. However, you still need to avoid restriction +enzymes that cut within your insert. + +Adding desired restriction sites to your recipient plasmid: You can modify the +MCS of your recipient plasmid using Annealed-oligo Cloning. + +If you are lucky enough to have multiple options for enzymes that flank your +insert and will result in correct orientation in the recipient plasmid, it is +useful to see if one set of enzymes will work in the same restriction enzyme +buffer (see New England Biolabs for more information about restriction enzyme +buffers). If you select enzymes that can function in the same buffer, it will +save you time in future steps. + + +EXPERIMENTAL PROCEDURE +================================================================================ + +1. Digest your DNA + + Set up restriction digests for your donor and recipient plasmids. Because you + lose some DNA during the gel purification step, it is important to digest plenty + of starting material. We recommend 1.5-2μg of donor plasmid and 1μg of + recipient plasmid. It is also critical that as much of the recipient plasmid as + possible be cut with both enzymes, and therefore it is important that the + digest go at least 4 hours and as long as overnight. + + If you are going to use only one restriction enzyme, or enzymes that have + compatible overhangs or no overhangs after digestion, you will need to use a + phosphatase to prevent re-circularization of the recipient plasmid. You should + treat your digested recipient plasmid with a phosphatase prior to the ligation + step or prior to the gel purification step, depending on the phosphatase you + choose. CIP (calf alkaline phosphatase) or SAP (shrimp alkaline phosphatase) are + commonly used. Follow the manufacturer's instructions. + +2. Isolate your insert and vector by gel purification + + Run your digested DNA on an agarose gel and conduct a gel purification to + isolate the DNA. When running a gel for purification purposes it is important + to have nice crisp bands and to have space to cut out the bands. Because of + this we recommend that you use a wide gel comb, run the gel on the slower side, + and skip lanes between samples. In addition to a DNA ladder standard, it is + also a good idea to run an uncut sample of each plasmid to help with + troubleshooting if your digests don't look as you expected. + + Once you have cut out and purified your insert and recipient plasmid backbone + bands away from the gel via your favorite gel purification method, it is + important to determine the concentration of recovered DNA. + +3. Ligate your insert into your vector + + Conduct a DNA Ligation to fuse your insert to your recipient plasmid. + + We recommend around 100ng of total DNA in a standard ligation reaction. You + ideally want a recipient plasmid to insert ratio of approximately 1:3. Since + the number of base pairs for each varies, it is difficult to calculate this + based on DNA concentration alone. One method is to conduct 2 ligations for each + plasmid you are trying to create, with varying ratios of recipient plasmid to + insert. + + It is also important to set up negative controls in parallel. For instance, a + ligation of the recipient plasmid DNA without any insert will tell you how much + background you have of uncut or self-ligating recipient plasmid backbone. + +4. Transformation + + Transform your ligation reaction into your bacterial strain of choice. Follow + the manufacturer's instructions for your competent cells. + + For most standard cloning, you can transform 1-2μl of your ligation reaction + into competent cells such as DH5alpha or TOP10. If using much less total DNA + (<1ng) or if you are having trouble getting colonies, you might want to use + higher competency cells. Additionally, if your final product is going to be very + large (>10kb) you might want to use electro-competent cells instead of the + more common chemically-competent cells. + + The number of bacterial colonies resulting from your transformation will give + you the first indication as to whether your transformation worked. Your recipient + plasmid + insert plate should have significantly more colonies than the + recipient plasmid alone plate. The recipient plasmid alone control will tell + you your "background" level or more specifically it will tell you how many + colonies you can expect on your recipient plasmid + insert plate that are not + correct. + + If you have a high number of colonies on your recipient plasmid alone plate, you + can try ligating the recipient plasmid alone in the presence and absence of + ligase. If the colonies are a result of uncut empty plasmid, you will still have + colonies when you do not add ligase. If the colonies are a result of recipient + plasmid self-ligation, you will see significantly more colonies when you add + ligase. + + If you do not see any colonies, you should conduct a positive control to ensure + that your transformation worked. You should also verify that you are plating on + the appropriate antibiotic and try varying the amount of recipient plasmid to + insert in the ligation reaction. + +5. Isolate the Finished Plasmid + + Finally, you will need to pick individual bacterial colonies and check them for + successful ligations. Pick 3-10 colonies depending on the number of background + colonies on your control plate (the more background, the more colonies you will + need to pick) and grow overnight cultures for DNA purification. + + After purifying the DNA, conduct a diagnostic restriction digest of 100-300ng + of your purified DNA with the enzymes you used for the cloning. Run your digest + on an agarose gel. You should see two bands, one the size of your vector and + one the size of your new insert. If you used only one enzyme or used enzymes + with compatible overhangs you will need to verify the orientation of your + insert, so you may want to design a diagnostic digest for this purpose. + +Congratulations, you now have YGOI in a mammalian expression vector and can +begin your studies. diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Plasmid modification by Annealed Oligo Cloning by.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Plasmid modification by Annealed Oligo Cloning by.txt new file mode 100644 index 0000000000000000000000000000000000000000..925d2dfb1c595d6eeb65c3a5dc092afd31b71d2b --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Plasmid modification by Annealed Oligo Cloning by.txt @@ -0,0 +1,117 @@ +PROTOCOL: Plasmid Modification by Annealed Oligo Cloning +SOURCE: https://www.addgene.org/protocols/annealed-oligo-cloning/ +================================================================================ + +SUMMARY +================================================================================ + +Oligo overlap cloning can be used anytime you need to add a short stretch of DNA +to a plasmid, such as: +• Changing a Multiple Cloning Site (MCS) +• Adding short tags - ex: HA or Flag +• Cloning shRNAs + + +BACKGROUND +================================================================================ + +For the purposes of this tutorial we will discuss how to add new restriction sites +to the MCS of an empty vector. However, the following technique can be used just as +easily to add short tags or shRNAs to any vector (the procedure will simply differ +in terms of primer design). + +Let's assume that your favorite vector has a relatively limited MCS (BamHI - +EcoRI - SalI) and you want to expand that with the addition of NdeI, PacI, AscI, +and MfeI. With oligo overlap cloning, you can design a set of oligos containing +your desired restriction sites and add them to your existing vector. It is a +couple days of work that will pay off for years to come. + + +DESIGN +================================================================================ + +Briefly, we will design overlapping oligos that once annealed can be cloned +directly into the overhangs generated by restriction digest of existing sites in +the original vector. + +Designing oligos + +To add NdeI, PacI, AscI and MfeI sites between the EcoRI and SalI sites of the +vector, we design a top oligo with each of the additional sites in tandem (NdeI - +CATATG, PacI - TTAATTAA, AscI - GGCGCGCC, MfeI - CAATTG). The bottom oligo will +be the reverse compliment so that they can anneal. + +Top oligo: 5' - CATATG TTAATTAA GGCGCGCC CAATTG - 3' = 28 bp + +Bottom oligo: 3' - GTATAC AATTAATT CCGCGCGG GTTAAC - 5' = 28 bp + +We also need to include additional bases to complement the overhangs generated +when digesting the vector with EcoRI and SalI. To do this, we add 5' - AATTC and +G - 3' to the top oligo and 3' - G and CAGCT - 5' to the bottom oligo, making +our final oligos 34 bp each: + +Top oligo: 5' - AATTC CATATG TTAATTAA GGCGCGCC CAATTG G - 3' + +Bottom oligo: 3' - G GTATAC AATTAATT CCGCGCGG GTTAAC CAGCT - 5' + +Note: We could leave off the 3' G on each oligo (and the complementary C of the +other oligo), but this would destroy the EcoRI and SalI sites in the final vector. + +Order the following oligos from your favorite oligo synthesis company: + +Top oligo: 5' - AATTCCATATGTTAATTAAGGCGCGCCCAATTGG - 3' + +Bottom oligo: 5' - TCGACCAATTGGGCGCGCCTTAATTAACATATGG - 3' + +Note: If you plan to phosphatase treat your cut vector it is necessary to use +5'-phosphorylated oligos. This is an option that can be added when ordering them +or can be performed enzymatically later. + + +EXPERIMENTAL PROCEDURE +================================================================================ + +Digest and purify vector + +While waiting for your oligos to arrive, conduct a restriction digest of 1μg of +vector with EcoRI and SalI. + +Run an agarose gel and cut out the band containing your vector DNA. + +Gel purify your DNA away from the agarose using a commercially available kit or +standard protocol. + +Anneal oligos + +The oligos should be resuspended in annealing buffer (10mM Tris, pH7.5-8.0, 50mM +NaCL, 1mM EDTA) and mixed in equimolar concentrations. We recommend mixing 2μg +each in a total volume of 50μL - add additional annealing buffer if necessary to +get to 50μL. Efficient annealing can be achieved by one of two methods: + +Method #1: +1. Place the mixed oligos in a 1.5mL microfuge tube. +2. Place tube in 90-95°C hot block and leave for 3-5 minutes. +3. Remove the hot block from the heat source (turn off or move block to bench top) + allowing for slow cooling to room temperature (~45 minutes). + +Method #2: +1. Place mixed oligos in a PCR tube. +2. Place tube in a thermocycler programmed to start at 95°C for 2 minutes. +3. Then, gradually cool to 25°C over 45 minutes. + +Ligation + +1. Dilute 5μL of annealed oligos with 45μL nuclease-free water and quantify the + concentration (should be about 8ng/μl). + +2. Mix the annealed oligos with cut vector in molar ratios (vector:insert) between + 4:3 and 1:6 in a standard ligation reaction (ex. to ligate an annealed oligo + insert of 50bp in length into a 5kb vector, mix 100ng of the vector with + 0.75-6 ng of annealed oligos). + +Transform + +1. Transform 2-3μL into your favorite competent bacteria and plate. + +2. Be sure to pick multiple colonies for mini-prepping and verify insert by + sequencing. diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Pouring LB Agar Plates.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Pouring LB Agar Plates.txt new file mode 100644 index 0000000000000000000000000000000000000000..5b45c27e63f8c50d2d3e197508b79ee58ab75f4a --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Pouring LB Agar Plates.txt @@ -0,0 +1,249 @@ +PROTOCOL: Pouring LB Agar Plates +SOURCE: https://www.addgene.org/protocols/pouring-lb-agar-plates/ +================================================================================ + +INTRODUCTION +================================================================================ + +Plasmids can carry one or more antibiotic resistance genes, which confer resistance +to a specific antibiotic to the bacteria carrying them. The presence of an +antibiotic resistance gene on a plasmid allows researchers to easily isolate +bacteria containing that plasmid from bacteria that do not contain it by +artificial selection (i.e. growing the bacteria in the presence of the antibiotic). + +Luria broth (LB) is a nutrient-rich media commonly used to culture bacteria in +the lab. The addition of agar to LB results in the formation of a gel that +bacteria can grow on, as they are unable to digest the agar but can gather +nutrition from the LB within. The addition of an antibiotic to this gel allows +for the selection of only those bacteria with resistance to that antibiotic - +usually conferred by a plasmid carrying the antibiotic resistance gene. The +following protocol will allow you to make your own LB/agar plates with your +antibiotic of interest. + +Last Upload: September 14, 2016 + + +EQUIPMENT +================================================================================ + +• Autoclave +• Water bath +• Pipetman + + +REAGENTS +================================================================================ + +• 37 g pre-mixed powder consisting of: + - 5.0 g yeast extract + - 10.0 g peptone from casein + - 10.0 g sodium chloride + - 12.0 g agar-agar +• 1 L Sterile H₂O +• Sterile plates of your desired size - we usually use 60 mm x 15 mm plates which + can hold 5-10 mL of agar and on which you can individually distinguish a maximum + of ~100 colonies + + 💡 PRO TIP: If you will be screening a large number of colonies, we recommend + using larger plates. Many labs use 100 mm x 15 mm plates which can hold 10 - 15 + mL of agar. + +• Autoclavable flasks +• Sterile pipettes +• Ice bucket to hold antibiotic +• Antibiotic at 1000 x concentration dissolved in the appropriate liquid solvent. + See table below for appropriate antibiotic concentrations. + +Antibiotic Concentrations: + +Antibiotic | Recommended Stock Concentration | Recommended Working Concentration +----------------|--------------------------------|----------------------------------- +Ampicillin | 100 mg/mL | 100 µg/mL +Bleocin | 5 mg/mL | 5 µg/mL +Carbenicillin* | 100 mg/mL | 100 µg/mL +Chloramphenicol | 25 mg/mL (dissolve in EtOH) | 25 µg/mL +Coumermycin | 25 mg/mL (dissolve in DMSO) | 25 µg/mL +Gentamycin | 10 mg/mL | 10 µg/mL +Kanamycin | 50 mg/mL | 50 µg/mL +Spectinomycin | 50 mg/mL | 50 µg/mL +Tetracycline | 10 mg/mL | 10 µg/mL + +Notes: +• Unless otherwise indicated, the antibiotic powder can be dissolved in dH₂O. +• *Carbenicillin can be used in place of ampicillin. Carbenicillin is more stable, + so it is potentially more effective at selecting only bacteria containing the + plasmids of interest (for example, fewer satellite colonies will grow). However, + it is also more expensive. + + +PROCEDURE +================================================================================ + +1. Measure 37g of pre-mixed LB-agar powder per L of molten agar you'd like to + make. The precise mass you measure out will be based on the number of plates + you'd like to pour. + + For example: + • Because we'd like to make 20 plates, and our plates can hold a maximum of + 10 mL, we'll want 200 mL of media total. + • Importantly, we'll actually make a bit more than 200 mL (~220 mL) just in + case we spill anything or have small errors in measurement. You should also + always make a bit more gel-agar mix than you think you'll need. + • So for 220 mL of LB-agar, we'll need: (37 g pre-mixed LB-agar powder/L) × + (0.220 L) = 8.14 g pre-mixed LB-agar powder. + +2. Transfer the LB-agar powder you've measured out into an appropriately sized + bottle for autoclaving. We make 400 mL of agar in 1 L bottles and 200 mL of + agar in 500 mL bottles. The extra empty volume is necessary to prevent your + molten agar from boiling over in the autoclave. + +3. Transfer the sterile water (in our case 220 mL) to the same bottle and swirl to + form a medium/agar colloid. + +4. Cover the opening of the bottle with its cap or aluminum foil (but do not make + an air-tight seal!) and tape the bottle with autoclave tape. The autoclave tape + will darken during the autoclave process if your sample has spent at least 10 + min at 121 ℃. Use lab tape to label the bottle with your initials, the date, + and the bottle contents. This will clear up any confusion later if you forget + your bottle in the autoclave. + +5. Place the gel mix in the autoclave and run on a setting that gets the sample to + at least 121 ℃ under 20 psi for at least 30 min. The high pressure will prevent + your gel mix from boiling over at high temperature. + + 💡 PRO TIP: Although our recommended temperature should kill most potential + contaminants, certain types of spores will stubbornly survive even under the + harsh conditions in the autoclave. Be sure to check the literature for an + appropriate sterilization technique if you are working with any weird and + wonderful organisms. + +6. While your samples are sterilizing in the autoclave, you should prepare your + plate pouring station: + • Find an empty section of lab bench with a working flame. + • Spray down the bench with a 70% ethanol solution and wipe down with a paper + towel. + • Count out the appropriate number of plates and stack them on your lab bench. + • Label the plates with the date and the medium they will contain including the + identity of the antibiotic. + + 💡 PRO TIP: We batch label our plates with colored marker - particular colors + correspond to particular antibiotics. + + • Position the flame just to the side of where you'll be pouring your plates - + be sure to leave room for your bottle of molten gel mix, a tube rack + containing the appropriate antibiotics, and a section for active pouring. + +7. Prepare your antibiotics. Prior to adding your antibiotic to the molten gel + mix, you should create a 1000x stock solution. + + For example: + • If you'll be preparing plates with a final concentration of 100 ug/mL + ampicillin, you should make a stock solution of 100,000 ug/mL (100 mg/mL). + Simply measure out 100 mg of ampicillin powder, add it to 1 mL of water, + dissolve by vortexing, and filter sterilize. + +8. Prepare a water bath at 60 ℃ with sufficient water to submerge ~75% of the + bottle containing your molten gel mixture. + + 💡 PRO TIP: You will cool the molten agar in the water bath prior to adding + the antibiotic. 60 ℃ is a good temperature because the molten agar will remain + liquid at this temperature but most antibiotics will not break down at this + temperature. Check with your antibiotic's manufacturer to make sure this is + true in your case. + +9. Retrieve your molten agar mix from the autoclave. + + 💡 PRO TIP: Once your autoclave cycle is complete, we recommend opening the door + to the autoclave just a crack and leaving it open that way for ~10 min. This + will allow any steam to escape from the autoclave and will cool your gel-mix + slightly. Even so, you should always use thermally insulated gloves when + removing anything from the autoclave. + +10. Partially submerge your molten gel-mix in the 60 ℃ water bath. + + 💡 PRO TIP: You should leave the molten gel-mix in the water bath for at least + 5 min. Do not let any of the water bath water touch the neck or top of the + bottle as this water is not likely to be sterile. Cooled agar should be warm + to the touch; as a rule of thumb, if you cannot take the molten agar out of the + water bath wearing only lab gloves, it's not likely cool enough to add + antibiotic to. To be certain your agar is at the right temperature, we + recommend using a laser thermometer. + +11. Light the flame at the plate pouring station and dilute your antibiotic into + your ~60 ℃ molten gel mix using sterile technique. + +12. Swirl the agar bottle to ensure even distribution of the antibiotic throughout + the agar. + +13. Open one plate at a time next to the flame and begin pouring. Measure your + desired amount of agar with a pipette for the first plate to get a good idea + of what that volume looks like in your particular plate. + +14. For the remainder of the plates, pour directly from the bottle. + + 💡 PRO TIPS: + • Be sure to swirl your plates after pouring to remove bubbles and ensure an + even distribution of agar over the bottom of the plate. Cap each plate after + pouring and stack as you pour. + • If your agar partially solidifies in the bottle while you're pouring, you + should stop pouring and re-make the gel-mix. If you're making plates without + any antibiotic you can alternatively re-liquefy the agar by running it + through the autoclave again or by microwaving (if you microwave, beware of + over-boiling!). + +15. Leave your plates out on the bench to solidify. + + 💡 PRO TIP: It takes roughly 30 min for our plates to solidify at room + temperature, however we leave them out at room temperature overnight to allow + them to dry. After overnight drying, we place the plates in a plastic bag with + an absorbent material to reduce condensation. The plates are then stored at 4 ℃ + until use. + +16. Once your plates have solidified and dried, you should test them to make sure + the antibiotic functions properly: + • Take out two plates. + • On the first plate, streak out a strain that you know to be resistant to + the antibiotic. + • On the second plate, streak out a strain that's not resistant to the + antibiotic. + • Incubate both plates overnight at the appropriate growth temperature and + check for growth. See our sample data section below for positive and negative + test results. + + +SAMPLE DATA +================================================================================ + +In all cases below (-) indicates that the tested strain is not supposed to be +resistant to the antibiotic, (+) indicates that the tested strain is supposed to +be resistant to the antibiotic. + +Positive Result: Only the Resistant Strain Grows + +If everything was prepared properly, you should see growth of only the resistant +strain. If you get this final result, your plates are ready for use or storage at +4 ℃. You should not store your plates for longer than 1 month at any temperature +and should always check for contamination prior to use. + +Negative Result 1: Both Strains Grow + +Assuming the appropriate strains were streaked on the appropriate plates, then if +both strains grow, it's possible that: +• The antibiotic broke down. +• You forgot to add the antibiotic. +• You added the antibiotic at too low a concentration for selection. + +Negative Result 2: Neither Strain Grows + +If neither strain grows, it's possible that: +• You used the wrong antibiotic. +• Your antibiotic is at too high a concentration. +• One or both of your strains are no longer viable. + +You can check for this possibility by streaking out both strains on plates without +any antibiotic. + +Negative Result 3: Only the Non-resistant Strain Grows + +If only the non-resistant strain grows, it's likely that you've used the wrong +antibiotic, or confused your strains. diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Protocol - Bacterial Transformation.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Protocol - Bacterial Transformation.txt new file mode 100644 index 0000000000000000000000000000000000000000..58f56c20c66c96f9b55e5c80b5a524083d8a26c6 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Protocol - Bacterial Transformation.txt @@ -0,0 +1,154 @@ +PROTOCOL: Bacterial Transformation +SOURCE: https://www.addgene.org/protocols/bacterial-transformation/ +================================================================================ + +INTRODUCTION +================================================================================ + +Transformation is the process by which foreign DNA is introduced into a cell. +Transformation of bacteria with plasmids is important not only for studies in +bacteria but also because bacteria are used as the means for both storing and +replicating plasmids. Because of this, nearly all plasmids (even those designed +for mammalian cell expression) carry both a bacterial origin of replication and +an antibiotic resistance gene for use as a selectable marker in bacteria. + +Scientists have made many genetic modifications to create bacterial strains that +can be more easily transformed and that will help to maintain the plasmid without +rearrangement of the plasmid DNA. Additionally, specific treatments have been +discovered that increase the transformation efficiency and make bacteria more +susceptible to either chemical or electrical based transformation, generating what +are commonly referred to as 'competent cells.' + +Many companies sell competent cells, which come frozen and are prepared for optimal +transformation efficiencies upon thawing. + +For the highest transformation efficiency, we recommend that you follow the +instructions that came with your competent cells. + +💡 PRO TIPS: + +• Commercial competent cells range significantly in their transformation + efficiency. The lowest efficiency cells (usually the least expensive) are fine + for transforming plasmid DNA for the purposes of storage and amplification. + Higher efficiency cells are more important if you will be transforming with very + small amounts of DNA or if you're multiple plasmids at once. + +• To save money, many labs also make their own competent cells. This is a + relatively simple procedure and is useful for performing low efficiency + transformations. + +Last Update: Nov. 13, 2017 + + +EQUIPMENT +================================================================================ + +• Shaking incubator at 37 °C +• Stationary incubator at 37 °C +• Water bath at 42 °C +• Ice bucket filled with ice +• Microcentrifuge tubes +• Sterile spreading device + + +REAGENTS +================================================================================ + +• LB agar plate (with appropriate antibiotic) +• LB or SOC media +• Competent cells +• DNA you'd like to transform + + +PROCEDURE +================================================================================ + +1. Take competent cells out of -80°C and thaw on ice (approximately 20-30 mins). + +2. Remove agar plates (containing the appropriate antibiotic) from storage at 4°C + and let warm up to room temperature and then (optional) incubate in 37°C + incubator. + +3. Mix 1 - 5 μl of DNA (usually 10 pg - 100 ng) into 20-50 μL of competent cells + in a microcentrifuge or falcon tube. GENTLY mix by flicking the bottom of the + tube with your finger a few times. + + 💡 PRO TIP: Transformation efficiencies will be approximately 10-fold lower + for ligation of inserts to vectors than for an intact control plasmid. + +4. Incubate the competent cell/DNA mixture on ice for 20-30 mins. + +5. Heat shock each transformation tube by placing the bottom 1/2 to 2/3 of the + tube into a 42°C water bath for 30-60 secs (45 secs is usually ideal, but this + varies depending on the competent cells you are using). + +6. Put the tubes back on ice for 2 min. + +7. Add 250-1,000 μl LB or SOC media (without antibiotic) to the bacteria and grow + in 37°C shaking incubator for 45 min. + + 💡 PRO TIP: This outgrowth step allows the bacteria time to generate the + antibiotic resistance proteins encoded in the plasmid backbone so that they will + be able to grow once plated on the antibiotic containing agar plate. This step + is not critical for Ampicillin resistance but is much more important for other + antibiotic resistances. + +8. Plate some or all of the transformation onto a 10 cm LB agar plate containing + the appropriate antibiotic. + + 💡 PRO TIPS: + • We recommend that you plate 50 μL on one plate and the rest on a second plate. + This gives the best chance of getting single colonies, while allowing you to + recover all transformants. + • If the culture volume is too big, gently collect the cells by centrifugation + and resuspend in a smaller volume of LB so that there isn't too much liquid + media on the agar plates. If the agar plate doesn't dry adequately before the + cells begin dividing, the bacteria diffuse through the liquid and won't grow + in colonies. + +9. Incubate plates at 37°C overnight. + + +TIPS AND FAQ +================================================================================ + +How can I save time when carrying out transformations? + +If you are not concerned with transformation efficiency (such as when you have a +tube of plasmid DNA and just need to transform bacteria so that you can grow up +more of the plasmid) you can save a lot of time by shortening or skipping many +steps and will still get enough colonies for your next step. Remember that each of +these shortcuts will reduce the efficiency of the transformation, so when higher +efficiency is needed follow the complete protocol. + +• Thaw the competent cells in your hand instead of on ice +• Reduce step 4 from 20 - 30 mins to 2 mins on ice before heat-shock +• Shorten or skip the outgrowth (for Ampicillin resistance it is ok to completely + skip the outgrowth, for the other antibiotics it is a good idea to outgrow for at + least 20-30 mins) + +I get very few if any transformants when transforming large plasmids (>10 kb) or +BACs, what can I do? + +Chemically competent cells are fast and easy to use, but are less efficient at +taking up larger plasmids. If you need to transform large plasmids, it is a good +idea to use electro-competent cells. Instead of relying on the heat-shock to cause +the cells to take up the DNA, an electro-magnetic field is applied to the +cell/DNA mixture to induce membrane permeability. To do this you will need to +have access to an electroporator and the appropriate cuvettes. Follow the +manufacturer's instructions for each. + +I got no transformants. What went wrong? + +Check that you are plating on an LB Agar plate containing the correct antibiotic. +The resistance gene on your plasmid must match the antibiotic on the plate. You +should also add a positive control (many companies include a positive control +plasmid with their competent cells) to ensure that your transformation procedure +is working. + +TIP: Sometimes less is more. + +Although it may be counter-intuitive, you will often get higher transformation +efficiencies with less DNA, especially when using highly competent cells. If you +used 100-1000 ng of total DNA in a ligation you will often get more colonies if +you use 1 μl of a 1:5 or 1:10 dilution rather than 1 μl directly. diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Protocol - How to Create a Bacterial Glycerol Stock.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Protocol - How to Create a Bacterial Glycerol Stock.txt new file mode 100644 index 0000000000000000000000000000000000000000..cf462e050435a4b3c802365e82109c43c8445c02 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Protocol - How to Create a Bacterial Glycerol Stock.txt @@ -0,0 +1,68 @@ +PROTOCOL: How to Create a Bacterial Glycerol Stock +SOURCE: https://www.addgene.org/protocols/create-glycerol-stock/ +================================================================================ + +BACKGROUND INFORMATION +================================================================================ + +Bacterial glycerol stocks are important for long-term storage of plasmids. +Although you can store your plasmid DNA at -20°C, many labs also create bacterial +glycerol stocks of their plasmids. This way, when you want to make more plasmid +DNA, the plasmid will already be in your desired bacterial strain and you will not +need to obtain more competent cells and retransform. + +Bacteria on an LB agar plate can be stored at 4°C for a few weeks. However, if +you want to store bacteria for a longer time, you will need to establish glycerol +stocks. The addition of glycerol stabilizes the frozen bacteria, preventing damage +to the cell membranes and keeping the cells alive. A glycerol stock of bacteria +can be stored stably at -80°C for many years. + + +PROCEDURE +================================================================================ + +1. Follow the steps for Inoculating an Overnight Liquid Culture. + +2. After you have bacterial growth, add 500 μL of the overnight culture to 500 μL + of 50% glycerol in a 2 mL screw top tube or cryovial and gently mix. + + Notes: + • Make the 50% glycerol solution by diluting 100% glycerol in dH₂O. + • Snap top tubes are not recommended as they can open unexpectedly at -80°C. + +3. Freeze the glycerol stock tube at -80°C. The stock is now stable for years, as + long as it is kept at -80°C. Subsequent freeze and thaw cycles reduce shelf + life. + +4. To recover bacteria from your glycerol stock, open the tube and use a sterile + loop, toothpick or pipette tip to scrape some of the frozen bacteria off of the + top. Do not let the glycerol stock unthaw! + +5. Streak the bacteria onto an LB agar plate. + +6. Grow your bacteria overnight at the appropriate temperature. Growth conditions, + including copy number and growth temperature, can be found on your plasmid's + information page. The next day you will be able to start an overnight culture + for plasmid DNA prep the following day. + + +TIPS AND FAQ +================================================================================ + +• The optimal concentration of long-term glycerol storage is unknown. Most labs + store bacteria in 15-25% glycerol. + +• You can prepare the glycerol stock the same time you prepare your plasmid DNA. + In the morning, when you retrieve your liquid bacterial culture, take 500 μL of + culture to make your glycerol stock before you begin your plasmid mini-prep. + +• Try not to freeze/thaw your glycerol stock too many times. Placing the glycerol + stock on dry ice while streaking onto LB agar will prevent it from thawing + completely and will improve the shelf life. + +• It is very important that you shake the glycerol before freezing (5-6 times). + Make sure that you see one uniform solution, and there are no layers present. + +• Be sure to label both the lid and the tube of a glycerol stock before you place + the sample at -80°C. Frozen tubes are hard to write on and samples stored for + long periods at -80°C can lose labels stuck to tube! diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Protocol - How to Design Primers.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Protocol - How to Design Primers.txt new file mode 100644 index 0000000000000000000000000000000000000000..f31085e91091614af43f8e064a2bc33898b00484 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Protocol - How to Design Primers.txt @@ -0,0 +1,53 @@ +PROTOCOL: How to Design Primers +SOURCE: https://www.addgene.org/protocols/primer-design/ +================================================================================ + +INTRODUCTION +================================================================================ + +Oligonucleotide primers are necessary when running a PCR reaction. One needs to +design primers that are complementary to the template region of DNA. They are +synthesized chemically by joining nucleotides together. One must selectively block +and unblock repeatedly the reactive groups on a nucleotide when adding a nucleotide +one at a time. The main property of primers is that they must correspond to +sequences on the template molecule (must be complementary to template strand). +However, primers do not need to correspond to the template strand completely; it is +essential, however, that the 3' end of the primer corresponds completely to the +template DNA strand so elongation can proceed. Usually a guanine or cytosine is +used at the 3' end, and the 5' end of the primer usually has stretches of several +nucleotides. Also, both of the 3' ends of the hybridized primers must point toward +one another. + +The size of the primer is very important as well. Short primers are mainly used +for amplifying a small, simple fragment of DNA. On the other hand, a long primer +is used to amplify a eukaryotic genomic DNA sample. However, a primer should not be +too long (> 30-mer primers) or too short. Short primers produce inaccurate, +nonspecific DNA amplification product, and long primers result in a slower +hybridizing rate. On average, the DNA fragment that needs to be amplified should be +within 1-10 kB in size. + +The structure of the primer should be relatively simple and contain no internal +secondary structure to avoid internal folding. One also needs to avoid +primer-primer annealing which creates primer dimers and disrupts the amplification +process. When designing, if unsure about what nucleotide to put at a certain +position within the primer, one can include more than one nucleotide at that +position termed a mixed site. One can also use a nucleotide-based molecular insert +(inosine) instead of a regular nucleotide for broader pairing capabilities. + + +PRIMER PROPERTIES +================================================================================ + +Taking into consideration the information above, primers should generally have the +following properties: + +• Length of 18-24 bases +• 40-60% G/C content +• Start and end with 1-2 G/C pairs +• Melting temperature (Tm) of 50-60°C +• Primer pairs should have a Tm within 5°C of each other +• Primer pairs should not have complementary regions + +Note: If you will be including a restriction site at the 5' end of your primer, +note that a 3-6 base pair "clamp" should be added upstream in order for the enzyme +to cleave efficiently (e.g. GCGGCG-restriction site-your sequence). diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Protocol - How to Inoculate a Bacterial Culture.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Protocol - How to Inoculate a Bacterial Culture.txt new file mode 100644 index 0000000000000000000000000000000000000000..f25002d5884ab0c5287df68f3a896624ea938d75 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Protocol - How to Inoculate a Bacterial Culture.txt @@ -0,0 +1,140 @@ +PROTOCOL: How to Inoculate a Bacterial Culture +SOURCE: https://www.addgene.org/protocols/inoculate-bacterial-culture/ +================================================================================ + +INTRODUCTION +================================================================================ + +Plasmids can carry one or more antibiotic resistance genes, which confer +resistance to a specific antibiotic to the bacteria carrying them. The presence of +an antibiotic resistance gene on a plasmid allows researchers to easily isolate +bacteria containing that plasmid from bacteria that do not contain it by +artificial selection (i.e., growing the bacteria in the presence of the +antibiotic). + +Luria broth (LB) is a nutrient-rich media commonly used to culture bacteria in +the lab. LB agar plates are frequently used to isolate individual (clonal) +colonies of bacteria carrying a specific plasmid. However, a liquid culture is +capable of supporting a higher density of bacteria and is used to grow up +sufficient numbers of bacteria necessary to isolate enough plasmid DNA for +experimental use. The following protocol is for inoculating an overnight culture +of liquid LB with bacteria. + + +PROCEDURE +================================================================================ + +1. Prepare liquid LB. For example, to make 400 mL of LB, weigh out the following + into a 500 mL glass bottle: + • 4 g NaCl + • 4 g Tryptone + • 2 g Yeast Extract + • and dH₂O to 400 mL + + Note: If your lab has pre-mixed LB agar powder, use the suggested amount, + instead of the other dry ingredients above. + +2. Loosely close the cap on the bottle (do NOT close all the way or the bottle may + explode!) and then loosely cover the entire top of the bottle with aluminum + foil. Autoclave and allow to cool to room temperature. Now screw on the top of + the bottle and store the LB at room temperature. + +3. When ready to grow your culture, add liquid LB to a tube or flask and add the + appropriate antibiotic to the correct concentration (see Preparing Antibiotics + below). + + Note: If you intend to do a miniprep, you will usually want to start 2 mL in a + Falcon tube. For larger preps, you might want to use as much as a liter of LB + in a 2 L Erlenmeyer flask. + +4. Using a sterile pipette tip or toothpick, select a single colony from your LB + agar plate. + +5. Drop the tip or toothpick into the liquid LB + antibiotic and swirl. + + Note: You can also use a long toothpick to select the colony, swirl it in the + LB, and remove prior to incubating. + +6. Loosely cover the culture with sterile aluminum foil or a cap that is not air + tight. Alternatively, you could use vented bioreactor tubes, dual position + snap-cap tubes, or permeable film to allow for aeration. + +7. Incubate bacterial culture at 37 °C for 12–18 h in a shaking incubator. + + Note: Some plasmids or strains require growth at 30 °C. If so, you will likely + need to grow for a longer time to get the correct density of bacteria since + they will grow more slowly at lower temperatures. + +8. After incubation, check for growth, which is characterized by a cloudy haze in + the media (Figure 1). + + Notes: + • Some protocols require bacteria to be in the log phase of growth. Check the + instructions for your specific protocol and conduct an OD600 to measure the + density of your culture if needed. + • A good negative control is LB media + antibiotic without any bacteria + inoculated. You should see no growth in this culture after overnight + incubation. + +9. Optional: For long term storage of the bacteria, you can proceed with creating + a glycerol stock. + +10. You can now isolate your plasmid DNA from the bacterial culture by following + the Isolating Your Plasmid DNA protocol. + + +PREPARING ANTIBIOTICS +================================================================================ + +Create a stock solution of your antibiotic. Unless otherwise indicated, the +antibiotic powder can be dissolved in dH₂O. Addgene recommends making 1000X stock +solutions and storing aliquots at -20 °C. + +To use, dilute your antibiotic into your LB medium at 1:1,000. For example, to +make 100 mL of LB/ampicillin growth media, add 100 μL of a 100 mg/mL ampicillin +stock (1000X stock) to 100 mL of LB. + +Antibiotic Concentrations: + +Commonly Used Antibiotics | Recommended Concentration +--------------------------|------------------------- +Ampicillin | 100 µg/mL +Bleocin | 5 µg/mL +Carbenicillin | 100 µg/mL +Chloramphenicol | 25 µg/mL +Coumermycin | 25 µg/mL +Gentamycin | 10 µg/mL +Kanamycin | 50 µg/mL +Spectinomycin | 50 µg/mL +Tetracycline | 10 µg/mL + + +TIPS AND FAQ +================================================================================ + +What is the difference between high copy and low copy plasmids? + +The copy number refers to the number of copies of an individual plasmid within a +single bacterial cell (Figure 2). Large plasmids usually have a low copy number +(approximately one or two copies per cell) and they need to grow for longer +periods of time (approximately 18–30 h). On the other hand, smaller plasmids can +be present in large numbers, 50 or more per cell, and have a high copy number. +High copy number plasmids should only need to be grown for 12–16 h on average. +Certain features of a plasmid may render it low copy regardless of plasmid size. +See the plasmid's info page to determine if your plasmid is high or low copy. + +I didn't get any growth after overnight incubation. What went wrong? + +• Try growing the culture for more time. Some bacterial cultures grow more slowly. + Also, bacteria incubated at 30 °C rather than 37 °C often require longer + incubation times. + +• Double check that the antibiotic in your LB media matches the antibiotic + resistance on your plasmid. + +• If the bacteria on your LB agar plates are not fresh, you should streak your + bacteria onto a new LB agar plate before growing in liquid culture. + +• More aeration may help to increase the density of the culture. Normally cultures + shake at 150–250 rpm, increase this to 350–400 rpm to obtain a higher cell + density. diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Protocol - How to Ligate Plasmid DNA.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Protocol - How to Ligate Plasmid DNA.txt new file mode 100644 index 0000000000000000000000000000000000000000..ab61f01d13fe775218fee476c5176081b2d1e184 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Protocol - How to Ligate Plasmid DNA.txt @@ -0,0 +1,122 @@ +PROTOCOL: How to Ligate Plasmid DNA +SOURCE: https://www.addgene.org/protocols/dna-ligation/ +================================================================================ + +BACKGROUND INFORMATION +================================================================================ + +The final step in the construction of a recombinant plasmid is connecting the +insert DNA (gene or fragment of interest) into a compatibly digested vector +backbone. This is accomplished by covalently connecting the sugar backbone of the +two DNA fragments. This reaction, called ligation, is performed by the T4 DNA +ligase enzyme. The DNA ligase catalyzes the formation of covalent phosphodiester +linkages, which permanently join the nucleotides together. After ligation, the +insert DNA is physically attached to the backbone and the complete plasmid can be +transformed into bacterial cells for propagation. + +The majority of ligation reactions involve DNA fragments that have been generated +by restriction enzyme digestion. Most restriction enzymes digest DNA +asymmetrically across their recognition sequence, which results in a single +stranded overhang on the digested end of the DNA fragment. The overhangs, called +"sticky ends", are what allow the vector and insert to bind to each other. When +the sticky ends are compatible, meaning that the overhanging base pairs on the +vector and insert are complementary, the two pieces of DNA connect and ultimately +are fused by the ligation reaction. + +Usually, scientists select two different enzymes for adding an insert into a +vector (one enzyme on the 5' end and a different enzyme on the 3' end). This +ensures that the insert will be added in the correct orientation and prevents the +vector from ligating to itself during the ligation process. If the sticky ends on +either side of the vector are compatible with each other, the vector is much more +likely to ligate to itself rather than to the desired insert. If you are in this +situation, it is important to treat the digested vector backbone with a +phosphatase before performing the ligation reaction (phosphatase removes the 5' +phosphate and therefore prevents the ligase from being able to fuse the two ends +of the vector together). + + +PROTOCOL: STANDARD INSERT + VECTOR DNA LIGATION +================================================================================ + +Before setting up the ligation reaction itself, it is important to determine the +amount of cut insert and vector to use for the ligation reaction. The volume of +vector DNA and insert DNA used in the ligation will vary depending on the size of +each and their concentration. However, for most standard cloning (where the +insert is smaller than the vector) a 3 insert : 1 vector molar ratio will work +just fine. We recommend around 100ng of total DNA in a standard ligation reaction. +Use a ligation calculator to easily quantify how much vector and insert DNA to use. + +1. Combine the following in a PCR or Eppendorf tube: + • Vector DNA + • Insert DNA + • Ligase Buffer (1μL/10μL reaction for 10X buffer, and 2μL/10μL reaction for + 5X buffer) + • 0.5-1μL T4 DNA Ligase + • H₂O to a total of 10μL + + Notes: + • If the DNA concentrations are low such that you cannot get all 100ng of DNA, + buffer and ligase into a 10μL reaction, scale the reaction size as necessary + - being sure to increase the amount of buffer proportionally. 1μL of ligase + should be sufficient for larger ligation reactions. + • Because ligase buffer contains ATP, which degrades upon freeze/thaw cycles, + it is a good idea to take a fresh tube, thaw it one time and aliquot + individual tubes of 5, 10 or 20μL for storage at -20°C. Whenever you need to + set up ligations in the future you can thaw a new tube that you know has only + been thawed once before. + • Always do controls. See Tips and FAQ below for details. + • Try different vector to insert ratios to optimize the ligation reaction. See + Tips and FAQ below for details on optimization. + +2. Incubate at room temperature for 2hr, or at 16°C overnight (following the + manufacturer's instructions). + + Note: For many ligation reactions, especially if using "high concentration" + ligase, 5min at room temperature is enough. For trickier ligations (such as + ligation of annealed oligos) the efficiency of ligation can be improved by + incubation at 37°C. + +3. Proceed with bacterial transformation. + + +TIPS AND FAQ +================================================================================ + +Do controls + +When doing ligations you should ALWAYS do a vector alone + ligase control. This +will allow you to verify that the vector was completely digested and if +phosphatase treated, that the phosphatase treatment worked. This control should, in +principle, be free of colonies, but the reality is that it will have some amount +of background. What you want to see is that your vector + insert ligation has many +more colonies than your vector alone ligation. + +Additional controls are encouraged, but may only be required for troubleshooting +failed ligations. The following table indicates the various controls: + +Control | Ligase | Interpretation +--------------|--------|------------------------------------------ +Uncut vector | - | Checks viability of competent cells and + | | verifies the antibiotic resistance of the + | | plasmid +Cut vector | - | Background due to uncut vector +Cut vector | + | Background due to vector re-circularization + | | - most useful for phosphatase treated vector +Insert or | + | Any colonies indicate contamination of intact +water | | plasmid in ligation or transformation reagents + +Optimizing the Vector:Insert Ratio + +Although a 3:1 insert to vector ratio is usually sufficient, you can optimize +the amount of insert and vector to improve ligation efficiency in situations where +the 3:1 ratio is not working or when doing more complicated cloning. While 3:1 +will get you in the ballpark for average size genes and vectors, this ratio is +really meant to refer to the molarity of DNA ends available for ligation. Simply +put, there are only two ends on any given piece of DNA no matter how long it is, +and therefore we need to adjust the amount of DNA used in a ligation based on the +length of the DNA to get a proper ratio of 3 available insert ends for every +available vector end. + +Ligation calculators are easily found on the web. Just enter the concentration, +lengths of your insert and vector, and what ratio you want, and it will tell you +exactly how much of each to use. diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Protocol - How to Perform Sequence Analysis.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Protocol - How to Perform Sequence Analysis.txt new file mode 100644 index 0000000000000000000000000000000000000000..418ea2d1100bf333aa50f9526cfaba1d43f5dada --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Protocol - How to Perform Sequence Analysis.txt @@ -0,0 +1,108 @@ +PROTOCOL: How to Perform Sequence Analysis +SOURCE: https://www.addgene.org/protocols/sequence-analysis/ +================================================================================ + +INTRODUCTION +================================================================================ + +Sequence verification of important plasmid features (such as the gene/insert, +fusion proteins, point mutations, deletions, etc.) involves selecting one or more +unique oligonucleotide primers that flank the regions of your plasmid that you +wish to confirm. Addgene's plasmid information pages recommend 5' and 3' +sequencing primers. These primers typically anneal to the backbone and can help +you verify the ends of the insert. Longer genes may require internal primers that +anneal to a specific region of the insert. + +You can find Addgene's sequencing results by clicking on the "View Sequences" link +on the Plasmid Information Pages. Addgene sequences the plasmid to verify tags, +mutations and a portion of the insert, but we do not sequence the entire plasmid. +Addgene strongly recommends that you sequence any portion of the plasmid that is +important for your experiments. + + +FACTORS TO CONSIDER WHEN SELECTING SEQUENCING PRIMERS +================================================================================ + +Is the primer unique? + +Make sure the primer only anneals once within the entire construct. + +Is the primer an appropriate distance from the target? + +The primer should be a minimum of 50 nucleotides and a maximum of 300 nucleotides +from your target. + +Are there commercially available primers that can be used for sequencing? + +There are many widely used, common primers that are often found within the +plasmid backbone (See Addgene's Sequencing Primers for reference). Many +sequencing cores have a list of common primers that can be requested for no +additional charge. + +What primers were used by Addgene during quality control? + +Addgene lists the primers used to obtain each result above the posted sequence in +the "View Sequence" link. + +Is your custom primer found within the Addgene sequencing results? + +If you require additional sequencing and need to design a custom primer, Addgene +recommends using Addgene's sequencing results as a reference for primer design. + + +SEQUENCING RESULTS +================================================================================ + +A good sequencing reaction will produce between 300-900 base pairs of useable +sequence. You should receive your sequencing results as a trace file (.ab1) which +graphically depicts the sequence as a series of colored peaks corresponding to +one of the four nucleotide bases. This is an example of a trace file from a +high-quality portion of a sequencing reaction. + +Sequence near the beginning or end of a sequencing reaction is often unreliable. +Although your sequencing results may indicate bases at specific locations, by +looking at the trace file, you will see that these base calls are unreliable. +This is an example of a trace file from a portion of a sequencing reaction with +high background. + +If you obtain a different sequence than expected and wish to contact Addgene about +the accuracy of your plasmid, please email [email protected] and include: +• The sequencing result +• The original trace file (.ab1 file) provided by your sequencing company or + core facility +• The corresponding primer sequence used for each reaction + + +TIPS AND FAQs +================================================================================ + +My sequence doesn't match Addgene's sequencing result, what should I do? + +Check your trace file first; the apparent mismatch/mutation may be the result of a +mis-called peak in the trace file. If the mutation is not an artifact, please +email [email protected] with the sequence, trace file, and primer used. + +What program can I use to view my trace file? + +There are many free programs available that can open .ab1 files, such as: +• 4Peaks (Mac) +• SnapGene Viewer (Mac/PC) +• FinchTV (Mac/PC) +• Sequence Scanner (PC) +• Chromas (PC) + +How can I tell if a peak is mis-called? + +Open the trace file and use the search feature in the program to locate the +incorrect sequence. Look at the peaks in the area and make sure they are +justifiable peaks. For instance, in the trace file below, you can see that just +after base 70 there are multiple peaks in the same location. Looking at the trace +file will give you more information than simply looking at the bases provided by +your sequencing provider. + +My sequence has "N"s in it- what does that mean? + +"N" is the letter used to denote that the position could be any of the 4 bases. +Check the trace file and see if you can manually call the correct base at the +position. Sometimes an "N" is the result of an erroneous insertion by the +sequencing reaction. diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Protocol - How to Perform a Diagnostic Digest.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Protocol - How to Perform a Diagnostic Digest.txt new file mode 100644 index 0000000000000000000000000000000000000000..a523ea1d87d1bdea27a58be6578f674624bffb3f --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Protocol - How to Perform a Diagnostic Digest.txt @@ -0,0 +1,115 @@ +PROTOCOL: How to Perform a Diagnostic Digest +SOURCE: https://www.addgene.org/protocols/diagnostic-digest/ +================================================================================ + +INTRODUCTION +================================================================================ + +Restriction enzymes are naturally occurring bacterial endonucleases that recognize +a large range of DNA sequences. Given the variety of these enzymes and the unique +sites they recognize, restriction digests have become the most widely used method +scientists employ to selectively move a specific piece of DNA from one plasmid to +another. A diagnostic restriction enzyme digest takes advantage of the fact that +restriction enzymes cleave DNA at specific sequences called restrictions sites. +Often, the size of the plasmid insert and vector backbone are known and thus this +technique can be quickly used to verify your plasmid. + +The goal of a diagnostic digest is to cut your plasmid into specific sized pieces +and analyze the resulting fragments by gel electrophoresis. The pattern of the +fragments on the gel can indicate if the plasmid contains the expected size insert. +By selecting the appropriate enzyme(s), one can either linearize a plasmid to +determine the size of the entire construct or excise some or all of an insert from +it. + +Before beginning your diagnostic digest, you will need to select a restriction +enzyme or enzymes that cut your plasmid. Many DNA analysis tools, including +Addgene's Sequence Analyzer, allow you to identify which restriction sites are +present in a given sequence. + +For a list of the commonly used commercially available restriction enzymes, see +New England Biolabs' website. + +Last Upload: May 18, 2018 + + +EQUIPMENT +================================================================================ + +• Electrophoresis chamber +• Pipetman +• Pipet tips + + +REAGENTS +================================================================================ + +• Liquid DNA aliquot of your plasmid of interest (see below for recommended + amounts) +• Appropriate restriction enzyme (see manufacturer's instructions for proper + amount) +• Appropriate restriction digest buffer (see manufacturer's instructions) +• Gel loading dye +• Electrophoresis buffer + + +VERIFYING TOTAL PLASMID SIZE -OR- INSERT AND BACKBONE SIZE +================================================================================ + +The simplest form of diagnostic digest is one in which you just want to verify +that the plasmid that you have is the expected size, or that it is composed of a +backbone and insert of expected sizes. This is frequently done after performing +either PCR - or restriction enzyme -based cloning to test individual clones +before use of more expensive forms of plasmid verification, such as DNA sequencing. +In the example above, digestion with enzyme RE1 will linearize the 6200bp plasmid +into one single 6200bp fragment. Alternatively, digestion with both RE1 and RE2 +will result in two bands; the 1200bp insert and the 5000bp backbone. + + +VERIFYING PLASMID IDENTITY BY "PLASMID FINGERPRINTING" +================================================================================ + +Often, it will be enough to know that you have a 1,200bp insert in a 5,000bp +backbone, but there are many plasmids out there that, when digested with +restriction enzymes common to multiple cloning sites, will result in similar +sized bands, thus making this simple digest less informative. This is particularly +true if you receive a plasmid from someone in another lab, or dig one out of the +freezer and you are not 100% sure it is what you are looking for, but you have a +map and know exactly what it should be. A useful restriction enzyme based +technique for verifying plasmids like this is "plasmid fingerprinting", where you +cut the plasmid into 3-8 pieces such that all (or most) fragments are small enough +to be accurately sized on a gel and also such that they are different enough in +size to be easily resolved from each other. However, by choosing an enzyme or +enzymes that will cut your plasmid into multiple fragments, you can get a very +unique pattern that will distinguish one 5kb backbone with a 1.2kb insert from all +others. + +When choosing restriction enzymes for this approach, it is often a good idea to +choose two different enzymes that will give you unique but distinct patterns so +that you get double confirmation. In the example above, digestion with either RE3 +or RE4 will give a very predictable pattern of bands on the gel, but by digesting +with both and seeing both patterns you can be incredibly confident that you have +the correct plasmid. + + +VERIFYING INSERT ORIENTATION BY RESTRICTION DIGEST +================================================================================ + +If you clone an insert into a vector by a single restriction enzyme, you will need +to verify that it has be cloned in the correct orientation - this can be done by +restriction digest. Although this is never an ideal cloning strategy, sometimes it +cannot be avoided. If you do have to do so, there is no way to control which +orientation the insert is ligated into the vector backbone and therefore the only +thing left to do is identify the clone(s) in which the insert is in the correct +orientation. + +In the example below we want to know how to differentiate between two clones that +differ only in the orientation of the insert. By choosing an enzyme (or enzymes) +that cuts within the insert, but significantly off center (ideally around 1/3 of +the way from one end), and also cuts in the backbone on one side of the insert, +you can get a very obvious verification of the orientation so long as the +expected products from each orientation are different sizes. Simply run the +digest products on a gel and those clones with the appropriately sized products +should have the correct orientation. + +For detailed protocols as well as tips and tricks see the Restriction Digest and +Gel Electrophoresis pages. diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Protocol - How to Purify DNA from an Agarose Gel.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Protocol - How to Purify DNA from an Agarose Gel.txt new file mode 100644 index 0000000000000000000000000000000000000000..7bd87c51989b5fcbd51b169f28f5fba8a0e8eeca --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Protocol - How to Purify DNA from an Agarose Gel.txt @@ -0,0 +1,88 @@ +PROTOCOL: How to Purify DNA from an Agarose Gel +SOURCE: https://www.addgene.org/protocols/gel-purification/ +================================================================================ + +BACKGROUND INFORMATION +================================================================================ + +Gel purification allows you to isolate and purify DNA fragments based on size. The +procedure starts with standard agarose gel electrophoresis, which separates DNA by +their length in base pairs. Following electrophoresis, you can cut DNA bands out of +the agarose gel and purify the DNA samples. This is a commonly used technique for +molecular cloning, such as PCR- or restriction enzyme-based cloning. + + +PROTOCOL: GEL PURIFICATION +================================================================================ + +Follow the Agarose Gel Electrophoresis Protocol with the following amendments: + +Notes: +• Gel purification is most efficient with lower % agarose gels, so you will want to + stay in the 0.7-0.8% range if possible. + +• You will want nice crisp bands. This can be achieved by using a wider gel comb + and running the gel at a lower voltage. + +• You will want to have enough space around each band to cut without having DNA in + other lanes contaminating your sample. To accomplish this, it is best to skip + lanes between samples and between the ladder and nearest sample. + +• To minimize the risk of DNA damage, it is best to limit the UV exposure of the + DNA. Therefore, it is a bad idea to use a gel imager to take a picture of the + gel before cutting out the bands and you will want to use long-wavelength UV for + as short a time as possible to get the bands cut out. + +1. Once you have run your gel, move it to an open UV box (be sure to wear proper + UV protection - especially for your eyes!), remove it from any gel tray as + plastic will block much of the UV and with a clean, sterile razor blade, slice + the desired DNA fragment from the gel. + + Notes: + • To protect the UV box, it is a good idea to place the gel on a glass plate if + available. Unlike the plastic tray, this will not significantly reduce the + UV, but will protect the UV box from being cut by the razor blade. + • Try to get as little excess gel around the band as possible. To do so, it is + often important to take the excised band, lay it down on the UV box and trim + the top, bottom and sides with the razor blade. This is especially important + during the DNA purification step, as many kits cannot handle more than a + certain total volume of gel per reaction. + +2. Place the gel in a labeled microfuge tube. + +3. Using a scale, weigh the tube with the gel fragment after zeroing the scale with + an empty tube. Alternatively, you can just subtract the weight of the empty tube + from the weight of the tube with the gel fragment. The weight of the gel is + directly proportional to its liquid volume and this is used to determine how + much of each buffer to add during the DNA isolation step. + +4. Finally, you will want to isolate the DNA from the gel. This is most commonly + done with a commercial gel purification kit, such as the QIAquick Gel Extraction + Kit. Always follow the manufacturer's instructions. + + Note: It is usually important to determine the concentration of the DNA that you + isolated before proceeding to your next intended step with the now gel purified + DNA. Find more information about DNA quantification here. + + +TIPS AND FAQ +================================================================================ + +How do you get better resolution of bands? + +A couple simple ways to increase the resolution (crispness) of your DNA bands +include: a) running the gel at a lower voltage for a longer period of time; b) +using a wider gel comb; or c) loading less DNA in the well. + +How do you get better separation of bands? + +If you have similarly sized bands that are running too close together you can +adjust the gel percentage to get better separation. A higher percentage agarose +gel will help resolve smaller bands from each other, and a lower percentage gel +will help separate larger bands. + +10% Rule + +For each sample you want to load on a gel, make 10% more volume than needed because +several microliters can be lost in pipetting. For example, if you want to load 1.0 +μg in 10μL, make 1.1μg in 11μL. diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Protocol - How to Run an Agarose Gel.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Protocol - How to Run an Agarose Gel.txt new file mode 100644 index 0000000000000000000000000000000000000000..54ab07e5c1062376e7e380305c81164fd070d9e1 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Protocol - How to Run an Agarose Gel.txt @@ -0,0 +1,104 @@ +Title: Addgene: Protocol - How to Run an Agarose Gel +URL: https://www.addgene.org/protocols/gel-electrophoresis/ +================================================================================ + +Protocols +Agarose Gel Electrophoresis +Agarose Gel Electrophoresis +You may also like... +Restriction Digest of Plasmid DNA +Purifying DNA from an Agarose Gel +DNA Ligation +Introduction +Gel electrophoresis is the standard lab procedure for separating DNA by size (e.g., length in base pairs) for visualization and purification. Electrophoresis uses an electrical field to move the negatively charged DNA through an agarose gel matrix toward a positive electrode. Shorter DNA fragments migrate through the gel more quickly than longer ones. Thus, you can determine the approximate length of a DNA fragment by running it on an agarose gel alongside a DNA ladder (a collection of DNA fragments of known lengths). +Last Update: Feb. 20, 2018 +Protocol Video +Watch the protocol video below to learn how to perform gel electrophoresis. +Equipment +Casting tray +Well combs +Voltage source +Gel box +UV light source +Microwave +Reagents +TAE ( +recipe here +) +Agarose +Ethidum bromide (stock concentration of 10 mg/mL) +Gel loading buffer, New England Biolabs B7022S +Procedure +Pouring a Standard 1% Agarose Gel: +Measure 1 g of agarose. +Pro-Tip +Agarose gels are commonly used in concentrations of 0.7% to 2% depending on the size of bands needed to be separated - +see FAQs below +. Simply adjust the mass of agarose in a given volume to make gels of other agarose concentrations (e.g., 2 g of agarose in 100 mL of TAE will make a 2% gel). +Mix agarose powder with 100 mL 1xTAE in a microwavable flask. See +TAE Recipe +. +Pro-Tip +TBE can be used instead of TAE, labs usually use one or the other, but there is very little difference between the two. +Note: +Make sure to use the same buffer as the one in the gel box (do not mix different buffers and do not use water). +Microwave for 1-3 min until the agarose is completely dissolved (but do not overboil the solution, as some of the buffer will evaporate and thus alter the final percentage of agarose in the gel. Many people prefer to microwave in pulses, swirling the flask occasionally as the solution heats up.). +Caution +HOT! Be careful stirring, eruptive boiling can occur. +Pro-Tip +It is a good idea to microwave for 30-45 sec, stop and swirl, and then continue towards a boil. Keep an eye on it the solution has a tendancy to boil over. Placing saran wrap over the top of the flask can help with this, but is not necessary if you pay close attention. +Let agarose solution cool down to about 50 °C (about when you can comfortably keep your hand on the flask), about 5 mins. +Optional +: Add ethidium bromide (EtBr) to a final concentration of approximately 0.2-0.5 μg/mL (usually about 2-3 μl of lab stock solution per 100 mL gel). EtBr binds to the DNA and allows you to visualize the DNA under ultraviolet (UV) light. +Caution +EtBr is a known mutagen. Wear a lab coat, eye protection and gloves when working with this chemical. +Note: +If you add EtBr to your gel, you will also want to add it to the running buffer when you run the gel. If you do not add EtBr to the gel and running buffer, you will need to soak the gel in EtBr solution and then rinse it in water before you can image the gel. +Pour the agarose into a gel tray with the well comb in place. +Pro-Tip +Pour slowly to avoid bubbles which will disrupt the gel. Any bubbles can be pushed away from the well comb or towards the sides/edges of the gel with a pipette tip. +Place newly poured gel at 4 °C for 10-15 mins OR let sit at room temperature for 20-30 mins, until it has completely solidified. +Pro-Tip +If you are in a hurry, the gel will set more quickly if you place the gel tray at 4 °C earlier so that it is already cold when the gel is poured into it. +Loading Samples and Running an Agarose Gel: +Add loading buffer to each of your DNA samples and mix well. Use 5 µl of loading buffer per 25 µl of sample. +Note: +Loading buffer serves two purposes: 1) it provides a visible dye that helps with gel loading and allows you to gauge how far the DNA has migrated; 2) it contains a high percentage of glycerol that increases the density of your DNA sample causing it settle to the bottom of the gel well, instead of diffusing in the buffer. +Once solidified, place the agarose gel into the gel box (electrophoresis unit). +Fill gel box with 1xTAE (or TBE) until the gel is covered. +Pro-Tip +Remember, if you added EtBr to your gel, add some to the buffer as well. EtBr is positively charged and will run the opposite direction from the DNA. So if you run the gel without EtBr in the buffer you will reach a point where the DNA will be in the bottom portion of the gel, but all of the EtBr will be in the top portion and your bands will be differentially intense. If this happens, you can just soak the gel in EtBr solution and rinse with water to even out the staining after the gel has been run, just as you would if you had not added EtBr to the gel in the first place. +Carefully load a molecular weight ladder into the first lane of the gel. +Note: +When loading the sample in the well, maintain positive pressure on the sample to prevent bubbles or buffer from entering the tip. Place the very top of the tip of the pipette into the buffer just above the well. Very slowly and steadily, push the sample out and watch as the sample fills the well. After all of the sample is unloaded, push the pipettor to the second stop and carefully raise the pipette straight out of the buffer. +Carefully load your samples into the additional wells of the gel. +Run the gel at 80-150 V until the dye line is approximately 75-80% of the way down the gel. A typical run time is about 1-1.5 hours, depending on the gel concentration and voltage. +Note: +Black is negative, red is positive. The DNA is negatively charged and will run towards the positive electrode. +Always Run to Red. +Turn OFF power, disconnect the electrodes from the power source, and then carefully remove the gel from the gel box. +Optional: +If you did not add EtBr to the gel and buffer, place the gel into a container filled with 100 mL of TAE running buffer and 5 μL of EtBr, place on a rocker for 20-30 mins, replace EtBr solution with water and destain for 5 mins. +Using any device that has UV light, visualize your DNA fragments. The fragments of DNA are usually referred to as ‘bands’ due to their appearance on the gel. +Pro-Tip +If you will be purifying the DNA for later use, use long-wavelength UV and expose for as little time as possible to minimize damage to the DNA. +Note: +When using UV light, protect your skin by wearing safety goggles or a face shield, gloves and a lab coat. +Analyzing Your Gel: +Using the DNA ladder in the first lane as a guide (the manufacturer's instruction will tell you the size of each band), you can infer the size of the DNA in your sample lanes. For more details on doing diagnostic digests and how to interpret them please see the +Diagnostic Digest +page. +Purifying DNA from Your Gel: +If you are conducting certain procedures, such as molecular cloning, you will need to purify the DNA away from the agarose gel. For instructions on how to do this, visit the +Gel Purification +page. +Tips and FAQ +How do you get better resolution of bands? +A few simple ways to increase the resolution (crispness) of your DNA bands include: a) running the gel at a lower voltage for a longer period of time; b) using a wider/thinner gel comb; or c) loading less DNA into the well. Another method for visualizing very short DNA fragments is polyacrylamide gel electrophoresis (PAGE), which is typically used to separate 5 - 500 bp fragments. +How do you get better separation of bands? +If you have similarly sized bands that are running too close together, you can adjust the agarose percentage of the gel to get better separation. A higher percentage agarose gel will help resolve smaller bands from each other, and a lower percentage gel will help separate larger bands. +10% Rule +For each sample you want to load on a gel, make 10% more volume than needed because several microliters can be lost in pipetting. For example, if you want to load 1.0 μg in 10 μL, make 1.1 μg in 11 μL. +Reference Page +Top +Index diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Protocol - How to Streak a Plate.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Protocol - How to Streak a Plate.txt new file mode 100644 index 0000000000000000000000000000000000000000..e8b54c2cf6234be65f067de41c48e08de17b9bea --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Protocol - How to Streak a Plate.txt @@ -0,0 +1,91 @@ +PROTOCOL: How to Streak a Plate +SOURCE: https://www.addgene.org/protocols/streak-plate/ +================================================================================ + +INTRODUCTION +================================================================================ + +If you have a glycerol stock or stab culture of bacteria and need to purify plasmid +DNA from it, you will want to isolate an individual clonal population (single +colony) of bacteria from this stock. Using a single colony from a freshly streaked +agar plate to inoculate a bacterial culture for DNA purification will minimize the +chance of having a mixture of plasmids in your purified DNA. This protocol explains +how to isolate a single bacterial colony by streaking it onto an LB agar plate. + +Last Update: Feb. 28, 2017 + + +EQUIPMENT +================================================================================ + +• Sterile toothpicks or wire loop +• Bunsen burner (or other small flame source) +• Incubator +• Marker + + +REAGENTS +================================================================================ + +• LB agar plate (with appropriate antibiotic) +• Bacterial stab + + +PROCEDURE +================================================================================ + +1. Obtain an LB agar plate with appropriate antibiotic. + +2. Label the bottom of the plate with the plasmid name and the date. It is also a + good idea to add the antibiotic resistance and your initials. Labeling within a + laboratory setting is important for organization, and it is recommended that you + keep a standard labeling system for all your objects/solutions. + +3. Sterilize your lab bench by spraying it down with 70% ethanol and wiping it down + with a paper towel. Maintain sterility by working near a flame or bunsen burner. + +4. Obtain the appropriate bacterial stab or glycerol stock. + +5. Using a sterile loop, pipette tip or toothpick, touch the bacteria growing within + the punctured area of the stab culture or the top of the glycerol stock. + + 💡 PRO TIP: If you use a wire loop you can sterilize it by passing it through a + flame, just be sure to allow enough time for the loop to cool before touching it + to the bacteria. + +6. Gently spread the bacteria over a section of the plate, as shown in the diagram + above, to create streak #1. + + 💡 PRO TIPS: + • Hold your tooth pick at an angle, the way you would hold a pencil, so that you + can make a broad stroke. Only touch the surface of the plate, do NOT dig into + the agar. + • Another very popular technique is to draw in discontinuous lines. Start by + streaking a vertical line of bacteria along one edge of the plate. Then streak + horizontal lines in another section of the plate, and then diagonal lines in + another section of the plate. Make sure that the first line (and only the + first) in each new section crosses at least one line of the previous section + so that it will contain some bacteria. + +7. Using a fresh, sterile toothpick, or freshly sterilized loop, drag through + streak #1 and spread the bacteria over a second section of the plate, to create + streak #2. + +8. Using a third sterile pipette tip, toothpick, or sterilized loop, drag through + streak #2 and spread the bacteria over the last section of the plate, to create + streak #3. + +9. Incubate plate with newly plated bacteria overnight (12-18 hours) at 37 °C. + + 💡 PRO TIP: Some plasmids or bacteria need to be grown at 30 °C instead of 37 °C. + This is often true for large unstable plasmids, which sometimes recombine at 37 + °C. Be sure to check this before incubating your plate. + +10. In the morning, single colonies should be visible. A single colony should look + like a white dot growing on the solid medium. This dot is composed of millions + of genetically identical bacteria that arose from a single bacterium. If the + bacterial growth is too dense and you do not see single colonies, re-streak + onto a new agar plate to obtain single colonies. + +11. Once you have single colonies, you can proceed to Recovering Plasmid DNA or use + the individual colonies for other experiments. diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Protocol - Over-Agar Antibiotic Plating.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Protocol - Over-Agar Antibiotic Plating.txt new file mode 100644 index 0000000000000000000000000000000000000000..d66cf0d2f75414ce872e7652846cfba8e10362e1 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Protocol - Over-Agar Antibiotic Plating.txt @@ -0,0 +1,113 @@ +PROTOCOL: Over-Agar Antibiotic Plating +SOURCE: https://www.addgene.org/protocols/over-agar-antibiotic-plating/ +================================================================================ + +INTRODUCTION +================================================================================ + +This protocol describes methodology for plating antibiotic over-agar for the +selection of transformed E. coli. Over-agar spreading of antibiotic makes it +easy for an investigator to conveniently plate and select transformed cells +containing plasmids differing in their resistance genes, as one does not need to +prepare separate batches of antibiotic-containing agar. This protocol will focus +specifically on selection with carbenicillin; however it can be adapted for any +antibiotic through the use of a selection curve to determine optimal antibiotic +concentration. + +Last Update: Oct. 27, 2017 + + +EQUIPMENT +================================================================================ + +• Pipette tips for both pipetting and spreading +• Bunsen burner (or other small flame source) +• Incubator + + +REAGENTS +================================================================================ + +• 6 cm diameter LB/agar plates without antibiotic +• High concentration (100 mg/mL, 1000x) carbenicillin stock solution in sterile + water (or other antibiotic) +• E. coli transformed with a plasmid containing the carbenicillin (amp) resistance + gene (or other antibiotic resistance) + + +PROCEDURE +================================================================================ + +Day 1 + +1. Prepare carbenicillin to a concentration of 1 mg/mL – 4 mg/mL in LB medium. + + The concentration of antibiotic required for effective over-agar selection has + been empirically determined. See selection curve below. + + Carbenicillin is used here in place of ampicillin because carbenicillin is more + stable, so it is potentially more effective at selecting only bacteria containing + the plasmids of interest (for example, fewer satellite colonies will grow). It + is, however, more expensive. + +2. With a 6 cm diameter petri plate containing solidified LB-agar, pipette 150 µL + of carbenicillin on top of the agar and gently spread over the surface until the + liquid is mostly absorbed (there is a very small visible volume of pooled liquid + remaining on the surface). + + We use the micropipette tip itself to do the spreading; the tip is gently bent + to create an "L" shape, and then used like a cell spreader. Several other + devices may be used for this purpose, provided that they fit your petri plate. + +3. Incubate the plate at room temperature for at least 30 minutes with the lid on + to give the antibiotic time to more fully absorb. + +4. During the incubation, transform DH5α E. coli cells by heatshock with the + plasmid of interest. See our transformation page for a detailed heatshock + transformation protocol. + +5. Plate 50 µL of transformed E. coli/rescue media suspension onto the agar and + gently spread over the surface until the liquid is mostly absorbed. + + The spreading of cells can be done in the same way as the antibiotic, using + either a bent micropipette tip or other cell spreading device that fits the + plate. + +6. Incubate plates at 37 ℃ for 18 hours. + +Day 2 + +7. Observe plates for colony formation. Shown below are the results from an + experiment optimizing the concentration of carbenicillin, plated over-agar for + selection of transformed E. coli. + + +SAMPLE DATA +================================================================================ + +Selection of E.coli on LB-agar using different concentrations of carbenicillin +plated over-agar. + +Control Plate with No Carbenicillin: +Plate shows a lawn of E. coli and no selection. + +150 µL of 0.1 mg/mL Carbenicillin plated over-agar: +Plate shows a lawn of E. coli and no apparent selection. + +150 µL of 1 mg/mL Carbenicillin plated over-agar: +Plate shows several individual colonies and effective selection. + +150 µL of 2 mg/mL Carbenicillin plated over-agar: +Plate shows less individual colonies than the 1 mg/mL plate and effective selection. + +150 µL of 4 mg/mL Carbenicillin plated over-agar: +Plate shows several individual colonies with smaller size than the 1 mg/mL and 2 +mg/mL plates and effective selection. + +Selection Curve of Transformed E. coli after Over-Agar Plating of Carbenicillin. + +The above graph displays the stock concentration of Carbenicillin stock used (150 +µL per plate). Please note we have found that there is generally a broad range of +antibiotic concentrations that will work for this assay, and the above result +represents a single experiment. For publishable data, the experiment would need to +be repeated to account for variability. diff --git "a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Protocol - pLKO.1 \342\200\223 TRC Cloning Vector.txt" "b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Protocol - pLKO.1 \342\200\223 TRC Cloning Vector.txt" new file mode 100644 index 0000000000000000000000000000000000000000..eeefc92dd2d9cead3476eebf639e7c4da8efc608 --- /dev/null +++ "b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Protocol - pLKO.1 \342\200\223 TRC Cloning Vector.txt" @@ -0,0 +1,630 @@ +PROTOCOL: pLKO.1 – TRC Cloning Vector +SOURCE: https://www.addgene.org/protocols/plko/ +================================================================================ + +Addgene Plasmid 10878. Protocol Version 1.0. December 2006. + +Copyright Addgene 2006, All Rights Reserved. This protocol is provided for your +convenience. See "warranty information" in appendix. + + +A. pLKO.1-TRC CLONING VECTOR +================================================================================ + +A.1 The RNAi Consortium + +The pLKO.1 cloning vector is the backbone upon which The RNAi Consortium has built +a library of shRNAs directed against 15,000 human and 15,000 mouse genes. Addgene +is working with the TRC to make this shRNA cloning vector available to the +scientific community. Please cite Moffat et al., Cell 2006 Mar; 124(6):1283-98 +(PubMed PMID 16564017) in all publications arising from the use of this vector. + +A.2 Map of pLKO.1 + +pLKO.1 is a replication-incompetent lentiviral vector chosen by the TRC for +expression of shRNAs. pLKO.1 can be introduced into cells via direct transfection, +or can be converted into lentiviral particles for subsequent infection of a target +cell line. Once introduced, the puromycin resistance marker encoded in pLKO.1 +allows for convenient stable selection. + +pLKO.1 contains an shRNA insert. The original pLKO.1-TRC cloning vector has a 1.9kb +stuffer that is released by digestion with AgeI and EcoRI. shRNA oligos are cloned +into the AgeI and EcoRI sites in place of the stuffer. The AgeI site is destroyed +in most cases (depending on the target sequence), while the EcoRI site is preserved. +For a complete map of pLKO.1 containing the 1.9kb stuffer, visit +www.addgene.org/10878/. + +Vector Elements: + +• U6: Human U6 promoter drives RNA Polymerase III transcription for generation of + shRNA transcripts. + +• cPPT: Central polypurine tract, cPPT, improves transduction efficiency by + facilitating nuclear import of the vector's preintegration complex in the + transduced cells. + +• hPGK: Human phosphoglycerate kinase promoter drives expression of puromycin. + +• Puro R: Puromycin resistance gene for selection of pLKO.1 plasmid in mammalian + cells. + +• sin 3'LTR: 3' Self-inactivating long terminal repeat. + +• f1 ori: f1 bacterial origin of replication. + +• Amp R: Ampicillin resistance gene for selection of pLKO.1 plasmid in bacterial + cells + +• pUC ori: pUC bacterial origin of replication. + +• 5'LTR: 5' long terminal repeat. + +• RRE: Rev response element. + +A.3 Related Products + +The following plasmids available from Addgene are recommended for use in conjunction +with the pLKO.1 TRC-cloning vector: + +• pLKO.1 – TRC control: Negative control vector containing non-hairpin insert. + +• pLKO.1 – scramble shRNA: Negative control vector containing scrambled shRNA. + +• psPAX2: Packaging plasmid for producing viral particles. + +• pMD2.G: Envelope plasmid for producing viral particles. + +Note: pLKO.1 can also be used with packaging plasmid pCMV-dR8.2 dvpr and envelope +plasmid pCMV-VSVG from Robert Weinberg's lab. For more information, visit Addgene's +Mammalian RNAi Tools page. + +Several other laboratories have deposited pLKO derived vectors that may also be +useful for your experiment. To see these vectors, visit Addgene's website and +"search for "pLKO"". + + +B. DESIGNING shRNA OLIGOS FOR pLKO.1 +================================================================================ + +B.1 Determining the Optimal 21-mer Targets in your Gene + +Selection of suitable 21-mer targets in your gene is the first step toward +efficient gene silencing. Methods for target selection are continuously being +improved. Below are suggestions for target selection. + +1. Use an siRNA selection tool to determine a set of top-scoring targets for your + gene. For example, the Whitehead Institute for Biomedical Research hosts an + siRNA Selection Program that can be accessed after a free registration. + +2. Guidelines for designing siRNAs with effective gene silencing: + • Starting at 25nt downstream of the start codon (ATG), search for 21nt sequences + that match the pattern AA(N₁₉). If no suitable match is found, search for + NAR(N₁₇)YNN, where N is any nucleotide, R is a purine (A,G), and Y is a + pyrimidine (C,U). + • G-C content should be 36-52%. + • Sense 3' end should have low stability – at least one A or T between position + 15-19. + • Avoid targeting introns. + • Avoid stretches of 4 or more nucleotide repeats, especially repeated Ts because + polyT is a termination signal for RNA polymerase III. + + Note that these were the prevailing guidelines when the pLKO.1 vector was + created. + + Additional design rules can be found at the Broad Institute's TRC shRNA Design + Process. + +3. To minimize degradation of off-target mRNAs, use NCBI's BLAST program. Select + sequences that have at least 3 nucleotide mismatches to all unrelated genes. + + TIP: Addgene recommends that you select multiple target sequences for each gene. + Some sequences will be more effective than others. In addition, demonstrating + that two different shRNAs that target the same gene can produce the same + phenotype will alleviate concerns about off-target effects. + +B.2 Ordering Oligos Compatible with pLKO.1 + +To generate oligos for cloning into pLKO.1, insert your sense and antisense +sequences from step B.1 into the oligos below. Do not change the ends; these bases +are important for cloning the oligos into the pLKO.1 TRC-cloning vector. + +Forward oligo: 5' CCGG—21bp sense—CTCGAG—21bp antisense—TTTTTG 3' + +Reverse oligo: 5' AATTCAAAAA—21bp sense—CTCGAG—21bp antisense 3' + +For example, if the target sequence is (AA)TGCCTACGTTAAGCTATAC, the oligos would +be: + +Forward oligo: 5' CCGG AATGCCTACGTTAAGCTATAC CTCGAG GTATAGCTTAACGTAGGCATT TTTTTG 3' + +Reverse oligo: 5' AATTCAAAAA AATGCCTACGTTAAGCTATAC CTCGAG GTATAGCTTAACGTAGGCATT 3' + + +C. CLONING OLIGOS INTO pLKO.1 +================================================================================ + +The pLKO.1-TRC cloning vector contains a 1.9kb stuffer that is released upon +digestion with EcoRI and AgeI. The oligos from section B contain the shRNA sequence +flanked by sequences that are compatible with the sticky ends of EcoRI and AgeI. +Forward and reverse oligos are annealed and ligated into the pLKO.1 vector, +producing a final plasmid that expresses the shRNA of interest. + +C.1 Recommended Materials + +• AgeI, New England Biolabs (NEB) #R0552S +• EcoRI, NEB #R0101S +• NEB buffer 1, NEB #B7001S +• NEB buffer 2, NEB #B7002S +• T4 DNA ligase, NEB #M0202S +• T4 DNA ligase buffer, NEB #B0202S +• DH5 alpha competent cells, Invitrogen #18258-012 +• Qiaquick gel extraction kit, Qiagen #28704 +• Low melting point agarose, Sigma #A9414 +• Luria Broth Agar (LB agar), American Bioanalytical: #AB01200-02000 +• Ampicillin, VWR: #7177-48-2. Use at 100 μg/mL. +• Carbenicillin, VWR: #80030-956. Use at 100 μg/mL. + +C.2 Annealing Oligos + +1. Resuspend oligos in ddH₂O to a concentration of 20 μM, then mix: + • 5 μL Forward oligo + • 5 μL Reverse oligo + • 5 μL 10x NEB buffer 2 + • 35 μL ddH₂O + +2. Incubate for 4 minutes at 95°C in a PCR machine or in a beaker of boiling water. + +3. If using a PCR machine, incubate the sample at 70°C for 10 minutes then slowly + cool to room temperature over the period of several hours. If using a beaker of + water, remove the beaker from the flame, and allow the water to cool to room + temperature. This will take a few hours, but it is important for the cooling to + occur slowly for the oligos to anneal. + +C.3 Digesting pLKO.1 TRC Cloning Vector + +The following steps were the prevailing guidelines when the pLKO.1 vector was +created. For alternative options, please refer to the enzyme manufacturer's +resources, such as NEB's online tool NEBcloner, to help guide your reaction buffer +selection when setting up double digests. + +1. Digest pLKO.1 TRC-cloning vector with AgeI. Mix: + • 6 μg pLKO.1 TRC-cloning vector (maxiprep or miniprep DNA) + • 5 μL 10x NEB buffer 1 + • 1 μL AgeI + • add ddH₂O to bring to 50 μL final volume + +2. Incubate at 37°C for 2 hours. + +3. Purify with Qiaquick gel extraction kit. Elute in 30 μL of ddH₂O. + +4. Digest eluate with EcoRI. Mix: + • 30 μL pLKO.1 TRC-cloning vector digested with AgeI + • 5 μL 10x NEB buffer for EcoRI + • 1 μL EcoRI + • 14 μL ddH₂O + +5. Incubate at 37°C for 2 hours. + +6. Run digested DNA on 0.8% low melting point agarose gel until you can distinctly + see 2 bands, one 7kb and one 1.9kb. Cut out the 7kb band and place in a sterile + microcentrifuge tube. + + TIP: When visualizing DNA fragments to be used for ligation, use only + long-wavelength UV light. Short wavelength UV light will increase the chance of + damaging the DNA. + +7. Purify the DNA using a Qiaquick gel extraction kit. Elute in 30 μL of ddH₂O. + +8. Measure the DNA concentration. + +C.4 Ligating and Transforming into Bacteria + +1. Use your ligation method of choice. For a standard T4 ligation, mix: + • 2 μL annealed oligo from step C.2 + • 20 ng digested pLKO.1 TRC-cloning vector from step C.3 (If you were unable to + measure the DNA concentration, use 1 μL) + • 2 μL 10x NEB T4 DNA ligase buffer + • 1 μL NEB T4 DNA ligase + • add ddH₂O to bring to 20 μL final volume + +2. Incubate at 16°C for 4-20 hours. + +3. Transform 2 μL of ligation mix into 25 μL competent DH5 alpha cells, following + manufacturer's protocol. Plate on LB agar plates containing 100 μg/mL ampicillin + or carbenicillin (an ampicillin analog). + + Due to the long terminal repeats found in lentiviral plasmids, Addgene + currently recommends using a strain that reduces the frequency of homologous + recombination of unstable regions, such as Invitrogen Stbl3™ or NEB Stable + cells. This will ensure that the repeats will be maintained and often results in + a greater yield of DNA. + + +D. SCREENING FOR INSERTS +================================================================================ + +You may screen for plasmids that were successfully ligated by restriction enzyme +digestion. However, once you have identified the positive clones, it is important +to verify the insert by conducting a sequencing reaction. + +D.1 Recommended Materials + +• DNA Miniprep Kit, Qiagen #27104 +• EcoRI, NEB #R0101S +• NcoI, NEB #R0193S +• Agarose, Sigma #A9539 + +D.2 Screening for Inserts + +Day 1: + +1. Inoculate 5 colonies from each ligation into LB + 100 μg/mL ampicillin or + carbenicillin. + +Day 2: + +2. Spin down the cultures and use a miniprep kit to obtain DNA. + +3. Conduct a restriction digest with EcoRI and NcoI: + • 1 μg miniprep DNA + • 2 μL 10x NEB buffer for EcoRI + • 0.8 μL EcoRI + • 0.8 μL NcoI + • add ddH₂O to bring to 20 μL final volume + +4. Incubate at 37°C for 1-2 hours. + +5. Run the digestion products on a 1% agarose gel. You should see two fragments, a + 2kb fragment and a 5kb fragment. + +6. Sequence positive clones with pLKO.1 sequencing primer (5' CAA GGC TGT TAG AGA + GAT AAT TGG A 3'). + + TIP: You may need to adjust the sequencing conditions if the DNA polymerase has + difficulty reading through the secondary structure of the hairpin sequence. + + +E. PRODUCING LENTIVIRAL PARTICLES +================================================================================ + +Before this step, you must contact your institution's Bio-Safety office to receive +permission and institution-specific instructions. You must follow safety procedures +and work in an environment (e.g. BL2+) suitable for handling HIV-derivative +viruses. + +For transient knockdown of protein expression, you may transfect plasmid DNA +directly into the target cells. The shRNA will be expressed, but the DNA is +unlikely to be integrated into the host genome. + +For stable loss-of-function experiments, Addgene recommends that you generate +lentiviral particles and infect the target cells. Addition of puromycin will allow +you to select for cells that stably express your shRNA of interest. + +E.1 Recommended Materials + +• psPAX2, Addgene #12260 +• pMD2.G, Addgene #12259 +• HEK-293T cells, GenHunter: #Q401 +• FuGENE® 6 Transfection Reagent, Roche Applied Biosciences: #11814443001 +• OPTI-MEM® serum-free media, Invitrogen: #31985 +• Dulbecco's Modified Eagle Medium (DMEM), Invitrogen: #11995 +• Fetal Bovine Serum (FBS), Invitrogen: #16000 +• Penicillin/Streptomycin, Invitrogen: #15140-122 +• Polypropylene tubes, VWR: #87003-290 + +Note: pLKO.1 could also be packaged using pCMV-dR8.2 dvpr and pCMV-VSVG from the +Robert Weinberg lab. For more information, visit Addgene's Mammalian RNAi Tools +page. + +E.2 Protocol for Producing Lentiviral Particles + +This protocol is for transfection in a 6 cm plate. The protocol can be scaled to +produce different amounts of virus as needed. + +Day 1: + +a. For each plasmid to be transfected, plate 7×10⁵ HEK-293T cells in 5 mL of media + in a 6 cm tissue culture plate. Incubate cells at 37°C, 5% CO₂ overnight. + + Although cells should regularly be passaged in DMEM + 10% FBS with + penicillin/streptomycin, cells should be plated at this step in DMEM + 10% FBS + without antibiotics (no penicillin or streptomycin). + +Day 2: + +b. Perform the transfection in the late afternoon because the transfection mix + should only be incubated with the cells for 12-15 hours. + +c. In polypropylene microfuge tubes (do NOT use polystyrene tubes), make a cocktail + for each transfection: + • 1 μg pLKO.1 shRNA plasmid + • 750 ng psPAX2 packaging plasmid + • 250 ng pMD2.G envelope plasmid + • to 20 μl serum-free OPTI-MEM + + TIP: You may want to vary the ratio of shRNA plasmid, packaging plasmid, and + envelope plasmid to obtain the ratio that gives you the optimal viral production. + +d. Create a master mix of FuGENE® 6 transfection reagent in serum-free OPTI-MEM. + Calculate the amount of Fugene® and OPTI-MEM necessary given that each reaction + will require 6 μL FuGENE® + 74 μL OPTI-MEM. For example: + • 1x master mix: 6 μL FuGENE® + 74 μL OPTI-MEM + • 5x master mix: 30 μL FuGENE® + 370 μL OPTI-MEM + • 10x master mix: 60 μL FuGENE® + 740 μL OPTI-MEM + + In a polypropylene tube, add OPTI-MEM first. Pipette FuGENE® directly into the + OPTI-MEM – do not allow FuGENE® to come in contact with the walls of the tube + before it has been diluted. Mix by swirling or gently flicking the tube. + Incubate for 5 minutes at room temperature. + +e. Add 80 μL of FuGENE® master mix to each tube from step c for a total volume of + 100 μL. Pipette master mix directly into the liquid and not onto the walls of + the tube. Mix by swirling or gently flicking the tube. + +f. Incubate for 20-30 minutes at room temperature. + +g. Retrieve HEK-293T cells from incubator. The cells should be 50-80% confluent and + in DMEM that does not contain antibiotics. + +h. Without touching the sides of the dish, gently add DNA:FuGENE® mix dropwise to + cells. Swirl to disperse mixture evenly. Do not pipette or swirl too vigorously, + as you do not want to dislodge the cells from the plate. + +i. Incubate cells at 37°C, 5% CO₂ for 12-15 hours. + +Day 3: + +j. In the morning, change the media to remove the transfection reagent. Replace with + 5 mL fresh DMEM + 10% FBS + penicillin/streptomycin. Pipette the media onto the + side of the plate so as not to disturb the transfected cells. + +k. Incubate cells at 37°C, 5% CO₂ for 24 hours. + +Day 4: + +l. Harvest media from cells and transfer to a polypropylene storage tube. The media + contains your lentiviral particles. Store at 4°C. + +m. Add 5 mL of fresh media containing antibiotics to the cells and incubate at 37°C, + 5% CO₂ for 24 hours. + +Day 5: + +n. Harvest media from cells and pool with media from Day 4. Spin media at 1,250 rpm + for 5 minutes to pellet any HEK-293T cells that were inadvertently collected + during harvesting. + + TIP: In lieu of centrifugation, you may filter the media through a 0.45 μm + filter to remove the cells. Do not use a 0.2 μm filter, as this is likely to + shear the envelope of your virus. + +o. Virus may be stored at 4°C for a few days, but should be frozen at -20°C or + -80°C for long-term storage. + + TIP: Freeze/thaw cycles decrease the efficiency of the virus, so Addgene + recommends that you use the virus immediately or aliquot the media into smaller + tubes to prevent multiple freeze/thaw cycles. + + +F. INFECTING TARGET CELLS +================================================================================ + +Lentiviral particles can efficiently infect a broad range of cell types, including +both dividing and non-dividing cells. Addition of puromycin will allow you to +select for cells that are stably expressing your shRNA of interest. + +F.1. Recommended Materials + +• Hexadimethrine bromide (polybrene)*, Sigma-Aldrich: #H9268 +• Protamine Sulfate*, MP Biomedicals: #194729 +• Puromycin*, Sigma-Aldrich: #P8833 +• Target cells (varies based on your experiment) +• Culture media for target cells (varies based on your experiment) +• Materials for assay (varies based on your experiment) + +Detailed protocols for preparing polybrene, protamine sulfate, and puromycin are +located in the "Appendix". + +F.2. Determining the Optimal Puromycin Concentration + +Each cell line responds differently to puromycin selection. Addgene strongly +recommends that you determine the optimal puromycin concentration for your cell +line before initiating your experiment. + +Day 1: + +a. Plate target cells in ten 6 cm plates and grow at 37°C, 5% CO₂ overnight. + +Day 2: + +b. The target cells should be approximately 80-90% confluent. + +c. Dilute puromycin in the preferred culture media for your target cells. The final + concentration of puromycin should be from 1-10 μg/mL in 1 μg/mL increments. + +d. Label plates from 1-10 and add appropriate puromycin-containing media to cells. + +Days 3+: + +e. Examine cells each day and change to fresh puromycin-containing media every + other day. + +f. The minimum concentration of puromycin that results in complete cell death after + 3-5 days is the concentration that should be used for selection in your + experiments. (You may wish to repeat this titration with finer increments of + puromycin to determine a more precise optimal puromycin concentration.) + +F.3. Protocol for Lentiviral Infection and Selection + +Day 1: + +a. Plate target cells and incubate at 37°C, 5% CO₂ overnight. + +Day 2: + +b. Target cells should be approximately 70% confluent. Change to fresh culture + media containing 8 μg/mL polybrene. + + TIP: Polybrene increases the efficiency of viral infection. However, polybrene + is toxic to some cell lines. In these cell lines, substitute protamine sulfate + for polybrene. + +c. Add lentiviral particle solution from step E. For a 6 cm target plate, add + between 0.5–1 mL virus (add 0.5 mL for a high MOI, and 0.1 mL for a low MOI). + Scale the amount of virus added depending on the size of your target plate. + + TIP: MOI (multiplicity of infection) refers to the number of infecting viral + particles per cell. Addgene recommends that you test a range of MOIs to + determine the optimal MOI for infection and gene silencing in your target cell + line. + +d. Incubate cells at 37°C, 5% CO₂ overnight. + +Day 3: + +e. Change to fresh media 24 hours after infection. + + TIP: If viral toxicity is observed in your cell line, you may decrease the + infection time to between 4 – 20 hours. Remove the virus-containing media and + replace with fresh media. Do not add puromycin until at least 24 hours after + infection to allow for sufficient expression of the puromycin resistance gene. + +f. To select for infected cells, add puromycin to the media at the concentration + determined in step F.2. + + Addgene recommends that you maintain one uninfected plate of cells in parallel. + This plate will serve as a positive control for the puromycin selection. + +Days 4+: + +g. Change to fresh puromycin-containing media as needed every few days. + +h. Assay infected cells. The following recommendations are guidelines for the + number of days you should wait until harvesting your cells. However, you should + optimize the time based on your cell line and assay: + + Assay | Days post-infection + ------------------------|-------------------- + mRNA knockdown | ≥3 days + (quantitative PCR) | + Protein knockdown | ≥4 days + (western blot) | + Phenotypic assay | ≥4 days + + +G. SAFETY +================================================================================ + +BL2 safety practices should be followed when preparing and handling lentiviral +particles. Personal protective clothing should be worn at all times. Use plastic +pipettes in place of glass pipettes or needles. Liquid waste should be +decontaminated with at least 10% bleach. Laboratory materials that come in contact +with viral particles should be treated as biohazardous waste and autoclaved. +Please follow all safety guidelines from your institution and from the CDC and NIH +for work in a BL2 facility. + +If you have any questions about what safety practice to follow, please contact your +institution's safety office. + +For more information, please see Addgene's Biosafety Guide. + + +H. REFERENCES +================================================================================ + +H.1. Published Articles + +• Functional siRNAs and miRNAs exhibit strand bias. Khvorova A et. al. Cell. 2003. + 115:209-216. + +• A lentiviral RNAi library for human and mouse genes applied to an arrayed viral + high-content screen. Moffat J et. al. Cell. 2006. 124:1283-1298. + +• In vivo gene delivery and stable transduction of nondividing cells by a lentiviral + vector. Naldini L et. al. Science. 1996 272:263-267. + +• Asymmetry in the assembly of the RNAi enzyme complex. Schwarz DS et. al. Cell. + 2003. 115:199-208. + +• Lentivirus-delivered stable gene silencing by RNAi in primary cells. Stewart SA + et. al. RNA. 2003. 9(4):493-501. + +• Multiply attenuated lentiviral vector achieves efficient gene delivery in vivo. + Zufferey R et. al. Nat Biotechnol. 1997. 15(9):871-5. + +• Self-inactivating lentivirus vector for safe and efficient in vivo gene delivery. + Zufferey R et. al. J Virol. 1998. 72(12):9873-80. + +H.2. Web resources + +• Addgene's mammalian RNAi website: www.addgene.org/mammalianrnai + +• The RNAi Consortium (TRC): www.broad.mit.edu/genome_bio/trc/rnai.html + +• Background on RNAi mechanism: RNAi animation + +• Whitehead siRNA Selection Program: http://sirna.wi.mit.edu/ + + +I. APPENDIX +================================================================================ + +I.1. Sequence of pLKO.1 TRC-Cloning Vector + +Click here to see the sequence of pLKO.1 TRC-cloning vector. The vector is 8901 +base pairs total, and the stuffer insert is shown in all capital letters. + +I.2. Recipes + +Luria Broth Agar (LB agar) + antibiotic + +Per 40 grams of powder from American Bioanalytical catalog # AB01200-02000, LB +contains: +• 10g tryptone +• 5g yeast extract +• 10g sodium chloride +• 15g agar + +Prepare LB agar solution by dissolving 40g of LB powder in 1L of distilled water. +Autoclave and cool to 55°C. Add 1mL of 100mg/mL ampicillin or carbenicillin to +obtain a final concentration of 100 μg/mL antibiotic. Pour plates and store at +4°C. + +Hexadimethrine Bromide (Polybrene) + +Prepare a 1mg/mL solution of polybrene (Sigma-Aldrich catalog #H9268) in 0.9% +NaCl. Autoclave to sterilize. Stock solution is stable at 4°C for up to one year. +The powder form of polybrene is stable at 4°C for several years. + +Protamine Sulfate + +Store protamine sulfate (MP Biomedicals catalog #194729) at 4°C. Freely soluble +in hot water and slightly soluble in cold water. + +Puromycin + +Prepare a 50mg/mL stock solution of puromycin (Sigma-Aldrich catalog #P8833) in +distilled water. Sterilize by passing through a 0.22 μm filter. Store aliquots at +-20°C. + +I.3. Warranty Information + +Addgene is committed to providing scientists with high-quality goods and services. +Addgene makes every effort to ensure the accuracy of its literature, but realizes +that typographical or other errors may occur. Addgene makes no warranty of any kind +regarding the contents of any literature. Literature are provided to you as a guide +and on an "AS IS" "AS AVAILABLE" basis without warranty of any kind either +expressed or implied, including but not limited to the implied warranties of +fitness for a particular purpose, non-infringement, typicality, safety and +accuracy. + +The distribution of any literature by Addgene is not meant to carry with it, and +does not grant any license or rights of access or use to the materials described in +the literature. + +The distribution of materials by Addgene is not meant to carry with it, and does +not grant any license, express or implied, under any patent. All transfers of +materials from Addgene to any party are governed by Addgene's Terms of Use, +Addgene's Terms of Purchase, and applicable Material Transfer Agreements between +the party that deposited the material at Addgene and the party receiving the +material. diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Transfection for Recombinant Antibodies.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Transfection for Recombinant Antibodies.txt new file mode 100644 index 0000000000000000000000000000000000000000..bbfc959c00b7b451abf57111d2039de65d43312f --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Transfection for Recombinant Antibodies.txt @@ -0,0 +1,231 @@ +Title: Addgene: Transfection for Recombinant Antibodies +URL: https://www.addgene.org/protocols/transfection-for-recombinant-antibodies/ +================================================================================ + +Protocols +Transfection for Recombinant Antibodies +Transfection for Recombinant Antibodies +You may also like... +Antibody Plasmid Collection +Antibodies Blog Posts +Antibody Guide +General Transfection Protocol +Recombinant Antibody Purification Protocol +Introduction +Transfections allow for transient expression of a gene of interest in cell culture. This protocol describes how to transfect suspension HEK293 cells with recombinant antibody plasmids using Polyethylenimine Max as a transfection reagent. After transfection and expression, the recombinant antibody can be purified for use in a variety of applications. +Sharing speeds science. +We believe that sharing the full details of our protocols supports reproducibility and accelerates science. Here, we list the specific equipment, reagents, and methods that we use in our lab at Addgene. Equipment and reagents from other vendors should produce similar outcomes when using these protocols. However, please be aware that your protocol may need to be adjusted to accommodate slight differences between products. Addgene does not endorse or recommend specific products or equipment. Inclusion of this information is solely for transparency intended to support reproducibility in science. +General Considerations +For antibody-expressing plasmids containing the SV40 origin of replication use a HEK293 line stably expressing the SV40 large T antigen. +For antibody-expressing plasmids containing the Epstein-Barr virus origin of replication use a HEK293 line stable expressing Epstein Barr nuclear antigen (EBNA). +Safety Warnings +HEK293 cells are considered biosafety level 2. Please ensure that you are in compliance with your institution’s biosafety regulations. +Last Update: February 18, 2022 +Workflow Timeline +Day 1: +Seed cells +Day 2: +Transfect cells +Day 3-6: +Feed cells +Day 7: +Harvest antibody +Equipment +Biosafety Cabinet +4 °C Refrigerator +Micropipettes and tips +Pipettor and pipettes +Benchtop centrifuge compatible with 50 mL conical tubes +Automated cell counter +37 °C, 5% CO +2 +incubator with shaking platform set to 120 rpm +37 °C bead bath +Vortex +Stir bar +Magnetic stir plate +pH meter +Reagents +HEK293 cells +Recombinant antibody plasmid DNA +500 mL vented flask +50 mL conical tubes +Microcentrifuge tubes +Cell counting chamber slide +30 mL luer-lock syringe, BD BD302832 +0.2 µm luer-lock filter, VWR 431229 +0.22 µm PES filtering system, 1000 mL, VWR 431098 +0.45 µm PES filtering system, 500 mL, VWR 430770 +Trypan Blue, Thermo Fisher T10282 +Valproic acid sodium salt, Sigma Aldrich P4543-10G +Polyethylenimine hydrochloride, M.W. 40000 (PEI-MAX), Linear, Transfection Grade, VWR 75800-188 +10% Poloxamer 188, Thermo Fisher 24040032 +Glutagro, Corning 25-015-CI +BalanCD HEK293 Media, Irvine Scientific 91165-1L +BalanCD HEK293 Feed, Irvine Scientific 91166-500ML +Benzamide, Millipore Sigma 12072 +Antipain, Millipore Sigma 10791 +Leupeptin, Millipore Sigma L2884 +Aprotinin saline solution, Millipore Sigma A6279 +Before Starting +Warm the DNA and working stock of PEI-MAX to room temperature before use, and warm the BalanCD HEK293 transfection media (BCD TFX) to 37 °C. See below for other Reagent Preparation instructions. +Wipe down all pipettes and equipment with 10% bleach prior to use. +Reagent Preparation +100 mM Valproic Acid +Dissolve +2.88 g +valproic acid in +200 mL +deionized water +Sterilize by passage through a sterile 0.22 µm filter. +Prepare 10 mL aliquots and store the solution at -20 °C. +1 mg/mL PEI-MAX +Add +1 g +of PEI-MAX powder to +900 mL +deionized water in a 1 L bottle and stir on a magnetic stir plate. +Stir until all particles have dissolved. Note: The powder should dissolve rapidly (with 20 min) but check for the presence of particles still in solution. Continue to stir until all particles have dissolved. This may take several hours. +Adjust to +pH 7.0 +with 10 N sodium hydroxide (NaOH) or 5 N hydrochloric acid (HCl). Note: Adjust the pH slowly, adding no more than 200 µL of NaOH or 20 µL of HCl at a time. +Add deionized water to a final volume of +1 L +and recheck pH to ensure that it has not drifted. +Filter the solution through a 0.22 µm filter. +Prepare aliquots and store at -20 °C until use. +BCD TFX +1000 mL +BalanCD HEK293 Media +10 mL +10% Poloxamer 188 +40 mL +200 mM Glutagro +Do not add selective reagents +Store at 4 °C until use. We suggest preparing fresh solutions after one month. +BCD Feed +500 mL +BalanCD HEK293 Feed +20 mL +200 mM Glutagro +Store at 4 °C until use. We suggest preparing fresh solutions after one month. +1000X protease inhibitor cocktail +25 mg +Leupeptin +50 mg +Antipain +250 mg +Benzamidine +25 mL +Aprotinin saline solution (2 mg/mL) +Mix well and sterilize through a 0.2 µm PES syringe filter. +Aliquot and freeze upright at -20 °C. +Procedure +Section 1: Seeding cells +The day prior to transfecting, seed a +108 mL +culture of HEK293 cells at a density of +0.9 x 10 +6 +cells/mL +in a 500 mL vented flask.Incubate in a +37 °C, 5% CO +2 +incubator on a shaking platform set to 120 rpm. +Pro-Tip +Do not use cells that are over 30 passages. +Section 2: Transfection +Check the cell density and viability: +Using a 5 mL pipette, transfer +0.5 mL +of HEK293 cell suspension into a clean microcentrifuge tube. +Pro-Tip +Cells settle quickly and need to be resuspended before sampling. Gently swirl the flask 5–10 times before sampling. +Transfer +10 µL +of trypan blue into a clean microcentrifuge tube. +Vortex the cell suspension. +Transfer +10 µL +of cell suspension into the microfuge tube containing the trypan blue. +Pipette 10 times to mix. +Load +10 µL +of the cell suspension/trypan blue mix into a cell counting chamber. +Load the cell counting chamber on an automated cell counter and measure the live cell density and viability of the culture. +Pro-Tip +Culture should be between +1.5–2 x 10 +6 +cells/mL +with +>95% +viability to proceed with transfection. +Transfect the flask containing 108 mL cells: +Transfer +6 mL +of BCD TFX into each of two 50 mL tubes. +Cap the tubes and incubate for +1 h +in the +37 °C +bead bath. +Transfer the PEI-MAX and recombinant antibody plasmid DNA sample to the biosafety cabinet and incubate for +1 h +at room temperature. +After the BCD TFX has warmed in the bead bath, transfer the tubes to the biosafety cabinet. +Add +180 µg +of recombinant antibody plasmid DNA to one tube of 6 mL BCD TFX. Cap the tube and vortex for 5 s to mix. +Add +450 µL +of 1 mg/mL PEI-MAX to the second tube of 6 mL BCD TFX (for a 1 mg/mL stock solution of PEI-MAX, 450 µg = 450 µL). Cap the tube and vortex for 5 s to mix. +Pro-Tip +The optimal ratio of DNA:PEI may vary significantly and should be empirically determined for your sample. Typical ratios may range from 1:1 to 1:6. +Add the diluted PEI-MAX to the diluted DNA. Cap the tube and vortex with three 1 s pulses. +Incubate for +3 min +at room temperature. +Transfer the flask of HEK293 cells to the biosafety cabinet. +Add +12 mL +of PEI-MAX/DNA mix to the flask dropwise. +Cap the flasks and swirl 5–10 times to mix. +Return the flask to the incubator. +Section 3: BCD Feed and valproic acid supplementation +During the +24–144 h +post-transfection, supplement the flask with 4% BCD Feed. +Pro-Tip +The feed can be repeated up to 4 times for a total of 16% of the culture volume. +At +72-96 h +post-transfection, supplement the flask with +3.75 mM +valproic acid. +Example feeding schedule: +Thursday: Transfect cells. +Friday (24 h post-transfection): Add 4% BCD Feed. +Monday (96 h post-transfection): Add valproic acid to 3.75 mM, add 4% BCD Feed. +Tuesday (120 h post-transfection): Add 4% BCD Feed. +Wednesday (144 h post-transfection): Add 4% BCD Feed. +Thursday (168 h post-transfection): Harvest antibody. +Section 4: Harvest antibody +At 168 hours (1 week) post-transfection, harvest the antibody. +Transfer the HEK293 cells and media to 50 mL conical tubes. +Centrifuge for +15 min +at +3100 x +g +to pellet the cells. +Filter the supernatant through a 0.45 µm PES filter. +Add +1X +protease inhibitor cocktail to the supernatant. +The supernatant containing the recombinant antibody can be used as-is or the recombinant antibody can be purified from the supernatant (see our +Recombinant Antibody Purification Protocol +). +Store the supernatant at +4 °C +until ready to use. diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Using a Light Microscope Protocol.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Using a Light Microscope Protocol.txt new file mode 100644 index 0000000000000000000000000000000000000000..c682eefb1e3156a800a9a2b0d906477df42f537a --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Using a Light Microscope Protocol.txt @@ -0,0 +1,151 @@ +PROTOCOL: Using a Light Microscope Protocol +SOURCE: https://www.addgene.org/protocols/light-microscope/ +================================================================================ + +INTRODUCTION +================================================================================ + +Microscopes are emblematic of biological research and are found in many different +types of laboratories. These tools allow you to observe specimens much smaller than +you would be able to with your naked eye, like microbes in a drop of pond water or +the cells in your cell culture dish. Microscopes come in a huge range of shapes and +sizes - from phone-sized, foldable microscopes that aren't very powerful (but are +cheap and accessible) to massive transmission electron microscopes that allow us to +see cellular components with science-fiction levels of detail. You can take entire +courses on microscopy and still have more to learn, so, for this protocol, we'll +focus on one of the most common types that you're likely to encounter: the compound +light microscope. + +As the name suggests, light microscopes take advantage of the physical properties of +light to detect small objects. Two of the most important properties of a microscope +are magnification (the ability to make an image larger) and resolution (the ability +to distinguish between two discrete objects). Figure 1 depicts an image of a compound +light microscope with the main components labeled: + +Main Components: +• Base +• Light Source +• Condenser and Diaphragm +• Stage +• Objective Lenses +• Focus Knobs (Fine and Coarse) +• Nosepiece +• Arm +• Ocular Lens (Eyepiece) + +The route the light follows from the source to your eyes is called the light path. +Light travels from the light source through a condenser that helps concentrate the +light onto the sample, and then through the sample. However, some of that light +won't make it through the sample because different components of the specimen will +refract and reflect the light. These differences create contrast, which allows you +to distinguish objects within the sample. You can increase contrast by a) adjusting +the aperture of the condenser diaphragm to limit the amount of light hitting the +sample or b) using dyes or stains that add color to some components of the sample +but not others. + +The light that does pass through the sample then travels through the objective lens +which magnifies the image, then the ocular lens, where the image is further +magnified before it finally reaches your eyes. These lenses determine the +magnification of the image and the resolution your microscope can achieve. You +achieve the highest resolution when your image is in focus, which you can control +using the focus knobs on the side of the microscope. + +You may be wondering why there are multiple objective lenses. Each objective performs +essentially the same task but has different magnifying powers. When you look at the +side of an objective, you will see several pieces of information, but the most +important (for now) is the magnification power, such as 4x, 10x, or 20x. A 4x +objective magnifies the image four times the actual size, the 10x objective +magnifies it 10 times, and so on. + +The ocular lens also provides magnification and the power should be provided on the +microscope; often this lens provides 10x magnification. To determine the final +magnification of your image, multiply the magnification of your objective lens by +the magnification of your ocular lens. For example, if you observe something using +the 10x objective and your ocular lens is also 10x, you would actually be seeing a +100x magnified image of that object! + + +EQUIPMENT +================================================================================ + +• Light Microscope +• Prepared Slides (or other sample that can fit on a microscope stage) + + +REAGENTS +================================================================================ + +None needed + + +PROCEDURE +================================================================================ + +1. Set up your microscope by removing any protective cover that may be on it and + plugging in the power source for the light. + + 💡 PRO TIP: If you have to move your microscope around the lab, be sure to + carry it with two hands - one hand supporting the base and the other holding + the arm - or use a cart. + +2. Revolve the nosepiece so that the lowest power objective is directly over the + stage. It is best practice to start with the lowest power objective to find your + sample. + +3. Place your slide (or other sample type) on the microscope stage. If using a + slide, you can secure it into place using the metal clips on the stage. + +4. Turn on the power source and use the stage arm to move the stage so that the + light shines onto your sample. + +5. To ensure that your sample is adequately illuminated, look through the + eyepiece. Adjust the power of the light source so that you can look through the + eyepiece comfortably. Then, close down the diaphragm and use the coarse focus + adjustment knob (the larger of the two focus knobs) until you can see the edges + of the aperture are in focus. Center the aperture in your field of view and + then slowly open the diaphragm until the edges are just out of view. + + 💡 PRO TIP: Looking through a microscope's eyepiece can take some practice. + Try to keep both eyes open and adjust the position of the eyepiece so that you + can see your image through both sides. + +6. Once you are happy with the lighting, use the coarse focus knob to bring your + sample into focus. Once your sample is in focus, use the stage arm to move the + stage (and ultimately your slide) until your field of view is centered on a + region of interest. If needed, you can also use the fine focus knob (the smaller + of the focus knobs) to make minor adjustments to the focus. + +7. After you are happy with the positioning and focus of your image on the lowest + magnification, you are ready to move up to the next objective. Take your eyes + away from the eyepiece and carefully revolve the nosepiece so that the next + objective is in position over your sample. As you increase magnification, you + will notice that the objectives get larger. Be careful to avoid hitting your + sample with the objective! + +8. Once on the higher objective, you will likely need to re-adjust lighting and + focus. Increase the power of the light source by opening the diaphragm so that + you can easily see your sample. Then use the focus knobs to bring the sample + into focus. + + 💡 PRO TIP: As you increase your magnification, remember that the objectives + are larger. Adjust your focus slowly so that you don't accidentally hit your + slide and risk damaging the lens or your sample. + +9. You can repeat steps 7 and 8 with progressively higher magnification lenses. + +10. Depending on why you are using the microscope you may wish to record your + observations. Some microscopes have digital cameras attached to them that + allow you to capture images directly to a computer, but many microscopes do + not and you may have to dust off your drawing skills. Regardless of your image + capture method, be sure to record the magnification used, any stains used in + your sample, and sample information so that you or others can interpret your + images in the future. + + +CONCLUSION +================================================================================ + +Like any important laboratory instrument, you should be sure to take care of your +microscope. Bumps, scratches, and dust can easily impair microscope performance. Be +sure to clean up your work area and microscope after use and store the microscope +appropriately. diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Virus Protocol - Generating Stable Cell Lines.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Virus Protocol - Generating Stable Cell Lines.txt new file mode 100644 index 0000000000000000000000000000000000000000..9bc463a2141166813273b544bdaf786c150f0db0 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Virus Protocol - Generating Stable Cell Lines.txt @@ -0,0 +1,127 @@ +Title: Addgene: Virus Protocol - Generating Stable Cell Lines +URL: https://www.addgene.org/protocols/generating-stable-cell-lines/ +================================================================================ + +Protocols +Generating Stable Cell Lines with Lentivirus +Generating Stable Cell Lines with Lentivirus +You may also like... +Viral Vector Guides +Virus Blog Posts +Mol Bio Protocols +Viral Service +Introduction +This protocol can be used to generate stable cell lines expressing a gene of interest from an integrated lentiviral vector. Unlike the short-term protein expression observed using transient transfection approaches, generating cell lines using lentiviral vectors enables long-term protein expression studies. Moreover, repeating experiments in a stable cell line, as opposed to transiently-transfected cells, increases reproducibility, as it eliminates the variation associated with repeated transient transfection. +Some lentiviral vectors deliver mammalian antibiotic resistance (e.g., puromycin, blasticidin), which enables selection of a stable cell culture after transduction. Performing antibiotic selection on transduced cells enables elimination of untransduced cells, resulting in a more homogenous (but still polyclonal) cell population. Depending on the transducibility of the cell line used, this antibiotic selection may be a vital step for obtaining a population of cells that have taken up the lentiviral transgene. Note that not all lentiviral vectors deliver antibiotic resistance. +This protocol was established using 293T cells but can be adapted to alternative cell lines. +Workflow Timeline +Day 0: +Seed and transduce Cells +Day 2–3 (am): +Remove media, replace with fresh media containing selection reagent +Day 3–14: +Change media as needed +Day 14–18: +Expand and harvest stable cell lines +Equipment +Class II, Type A2 Biological Safety Cabinet +0.5–10 µL single channel pipette +2–20 µL single channel pipette +20–200 µL single channel pipette +200–1000 µL single channel pipette +Ice bucket +CO +2 +incubator +Pipet controller +Hazardous waste container +Reagents +DMEM high glucose, Corning 10-013-CV +L-alanyl-L-glutamine (or alternative stable glutamine such as glutaGRO, Corning 25-015-CI) +Heat-inactivated FBS +Polybrene (10 mg/mL), Millipore TR-1003-G +1X PBS pH 7.4 without calcium or magnesium, Corning 21-040-CV (cations can affect the attachment of adherent cells) +0.45 μm polyethersulfone filter, Nalgene, 565-0010 (for viral preps, if prep was not previously filtered) +Microcentrifuge tubes, Neptune 3745.X +6-well tissue culture treated dish, Corning 3516 +15 mL conical tubes, VWR 21008-216 +Lentivirus preparation +Appropriate antibiotic for selection (e.g. puromycin, blasticidin) +Reagent Preparation +DMEM Complete: 10% v/v FBS and 4 mM L-alanyl-L-glutamine (or stable alternative, such as glutaGRO) +To a 500 mL bottle of DMEM high glucose, add 55 mL of heat-inactivated FBS and 5mL of 100X glutaGRO. Store at 4 °C. +Pro-Tip +Different brands and FBS lots can promote or inhibit transfection. Test a variety of brands and FBS lot numbers to find one suitable with your protocols. FBS can be purchased already heat-inactivated, or it can be inactivated in the lab by heating to 56 °C for 30 min. +Considerations Before You Start +The health of the target cell line is critical for obtaining accurate results. +Check the cells for +mycoplasma +(Link opens in a new window) +regularly +Do not over or under-grow your cells. +Thaw a new vial of cells after 20-30 passages. +Do not add penicillin/streptomycin to the media, as it can affect viability and transduction efficiency. +Infection efficiency will vary between cell lines. +It is not recommended that lentiviral supernatants be subjected to multiple freeze-thaw cycles. +Procedure +Before beginning, determine the optimal dose of selective reagent for your target cell line. To do this, treat target cells with a range of doses of antibiotic and determine the lowest dose that kills all of the cells. +Prepare a batch of DMEM complete + 10 µg/mL polybrene by diluting 20 µL of 10 mg/mL polybrene into 20 mL media. +Thaw the lentiviral aliquot on ice prior to use. +Prepare a range of dilutions of the lentivirus in DMEM complete + 10 µg/mL polybrene. Note, this is just a sample of possible dilutions. You may want to try higher/lower dilutions depending on your downstream applications. If you’ve titered your virus beforehand, you can narrow this range according to the results of your titration. +Mix the dilutions well. +Dilution +Volume of Lentivirus (μL) +Volume of DMEM complete + 10 µg/mL polybrene (µL) +0 +0 +500 +1:5 +300 +200 +1:10 +150 +350 +1:50 +30 +470 +1:100 +15 +485 +1:500 +3 +497 +Add 0.5 mL of a single viral dilution to each well (each well gets one dilution, so a 6-well plate will hold 5 dilutions plus one 'no virus' control well). +Perform a "reverse transduction" by seeding 50,000 cells into each well of the 6-well dish. These cells will be added to the wells that already contain 0.5 mL of virus solutions at various dilution. Make sure to use the polybrene-containing media to make the cell solution in this step. To seed the cells: +Prepare a batch of cells as follows: Dilute 350,000 cells into a total volume of 7 mL of DMEM complete + 10 µg/mL polybrene. +Mix well by pipetting or inverting the tube. +Aliquot 1 mL of cell suspension (i.e., 50,000 cells) into each well of the 6-well dish. This brings the total volume in each well up to 1.5 mL. Since all the media in these wells was made with DMEM complete + 10 µg/mL polybrene, the final concentration of polybrene in each well should be 10 µg/mL. +Pro-Tip +Transducing too many cells relative to the number of virus particles reduces the transduction efficiency, resulting in massive cell death upon antibiotic selection. The number of cells transduced should be enough that they can grow out in a reasonable amount of time, but not so many that they vastly outnumber the virus particles. +Incubate the cells with the virus for 48–72 h. +Gently aspirate the media from the cells. +Add 1.5 mL of DMEM complete containing the appropriate antibiotic. This is the beginning of the selection process, which will begin the selection of a stable cell pool. +Observe the dish every day to ensure that the cells in the untransduced well (0 µL lentivirus, above) are dying. Perform regular media changes and monitor the growth of the cells. +Pro-Tips +Depending on the efficiency of your transduction, you will see different degrees of cell death upon antibiotic selection. It is important to monitor these cells regularly and replace the cell media. Cell death by some cells in the culture may adversely affect the surviving cells in the culture, so it is important to do regular media changes and maintain optimal growth conditions for the surviving cells. Even in the absence of cell death, the cell media should be changed every 2–3 days to maintain the dose of antibiotic, which may not be stable at 37 °C. +To achieve a stable cell pool, the antibiotic selection should last at least as long as it takes the control (untransduced) cells to completely die. After that, the cells may undergo additional selection while the population expands. At this time, some researchers reduce the concentration of the antibiotic in culture, or remove the antibiotic entirely. If the antibiotic is reduced or removed from the culture, check the cells regularly to confirm transgene expression. +As polyclonal populations of resistant cells start proliferating and the individual wells become confluent, expand into larger vessels. A confluent well of a 6-well dish can be expanded into a 10 cm dish. A confluent 10 cm dish can be expanded into two 75 cm +2 +flasks, etc. +Pro-Tip +This selection method results in a polyclonal cell population, meaning that the transgene has integrated in different locations in the various cells in the culture. This is because lentiviral integration is random. Given the MOI of the lentivirus used, cells may also exhibit varying numbers of integration events. In other words, if an MOI >1 was used, some cells may have 1 copy of the transgene, while others have >1 copy of the transgene in their genome. This can result in varying expression levels of the transgene from different cells in the population. +Once the polyclonal populations are growing well and have been sufficiently expanded, prepare cell stocks and/or harvest to test for protein expression. +Typically, cells transduced with lower dilutions of the virus will have higher levels of expression. Consider expanding populations transduced with a variety of dilutions and pick the population that has the most desirable level of expression. +Over time, transgene expression in a polyclonal population may drop. This is because cells that express high levels of the transgene may have reduced growth rates, especially if that transgene is toxic. Eventually, the rapidly growing low-level transgene expressors may take over the culture. To overcome this, consider +generating monoclonal lines +from the early polyclonal populations. +Sample Data +Figure 1: +Generation of monoclonal cell lines from expansion of individual A549 cells stably expressing Cas9. A549 cells were transduced with +lentiCas9-Blast +and then selected with 1 µg/mL blasticidin for 9 days. Single cells were then plated in individual wells of a 96-well plate and left undisturbed for 13 days. (a, b, c) Colonies formed by expansion of single cells for 13 days. lentiCas9-Blast was a gift from Feng Zhang (Addgene plasmid +#52962 +) and is described in +Improved vectors and genome-wide libraries for CRISPR screening. Sanjana NE, Shalem O, Zhang F. Nature Methods. 2014 Aug;11(8):783-4 +(Link opens in a new window) +. +Last reviewed on: September 9, 2023 diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Water Bath Protocol.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Water Bath Protocol.txt new file mode 100644 index 0000000000000000000000000000000000000000..fbe505ce5f2252a1979809ac9d8b1c3802dbcea0 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Water Bath Protocol.txt @@ -0,0 +1,92 @@ +PROTOCOL: Water Bath Protocol +SOURCE: https://www.addgene.org/protocols/water-bath/ +================================================================================ + +INTRODUCTION +================================================================================ + +A water bath is a piece of laboratory equipment that helps bring your materials to +a particular temperature, catalyze chemical reactions such as restriction digests +needed in molecular biology, and thaw cell lines. There are many different types of +water baths that exist as scientists work with tubes and bottles of different sizes +in the lab. Some water baths contain individual slots for heating up tubes while +other water baths hold many liters of water to incubate bottles and containers. +Water baths can also be placed in walk-in refrigerators to achieve a temperature +between 4°C and room temperature. This general protocol suits almost any water bath. + + +EQUIPMENT +================================================================================ + +• Water Bath +• 10% bleach or 70% ethanol +• Distilled water +• Disinfectant +• Thermometer +• Water bath weights and floats + + +REAGENTS +================================================================================ + +None needed + + +PROCEDURE +================================================================================ + +1. Ensure that the water bath and water bath cover are cleaned before filling the + water bath with water. You may use a 10% bleach solution or a 70% ethanol + solution to wipe down the inside of the water bath. + + 💡 PRO TIP: To properly maintain the water bath, empty and clean it regularly. + +2. Determine the amount of water needed to fill the water bath, and be sure to + know what the maximum fill capacity is. Look for a "fill" line inside the water + bath or read the user manual. If you're filling up a water bath with individual + slots for tubes, remember that when you add the tube to the slots, it can cause + the water level to rise up and flow over the edge of the slide. + +3. Fill the water bath with distilled water, not tap water, to prevent salts from + accumulating on the surfaces of the water bath as the water evaporates from the + tub. Disinfectant may be added to prevent growth of bacteria or fungi. There are + disinfectants designed to be used in water baths with instructions on the + bottle, for example, number of drops per liter. + +4. Place a thermometer in the water bath. Oftentimes, the water bath will have a + spot to secure the thermometer in place. + +5. Turn the water bath on and set the appropriate temperature as described in your + protocol. How to set the temperature will vary depending on the model of water + bath, but will likely involve a dial or a digital display you can set to the + correct temperature. Set up your water bath so that it will reach the desired + temperature by the time you need it for your experiment. Water baths tend to + heat up relatively slowly. Place the water bath cover on the top of the water + bath to prevent evaporation and maintain the desired temperature. This also + helps the water bath heat up quicker. + + 💡 PRO TIP: Set up the water bath 30 minutes to 1 hour before you need to use + it to allow the temperature to stabilize. + +6. Use water resistant markers, such as permanent markers, to label your tubes + and/or containers that will go into the water bath. If you'll need to sterilize + your items after removing them from the water bath, be sure to use a marker that + is also resistant to chemicals such as ethanol. Writing on the tops of the + tubes and lids of items to be placed in the water bath is often better than + writing on the side of the tube. This way, as items are floating, you do not + need to necessarily maneuver the bottles or tubes to identify them. + +7. Once the water bath is at the correct temperature, remove the lid and place your + tubes or bottles into the water bath. Many items may float in the water bath + when they are placed inside. Water bath floats can be used to secure tubes in + place and water bath weights can hold bottles in place. + +8. After putting your tubes or bottles in the water bath, place the lid back on. + Note the time that you've put your materials in the water bath so that you know + when to take them out after your incubation is over. + +Note: If you regularly use a water bath in the lab, you can leave the water in it +from previous uses. However, you will still need to regularly clean out the water +bath even if you are using disinfectants as described above in step 3. You will +also need to maintain the appropriate water level in the water bath so before use, +make sure that there is enough water inside. diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Weighing Reagents Protocol.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Weighing Reagents Protocol.txt new file mode 100644 index 0000000000000000000000000000000000000000..896d67ac98b11b0b648d73933cce24e808d216e7 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Weighing Reagents Protocol.txt @@ -0,0 +1,102 @@ +PROTOCOL: Weighing Reagents Protocol +SOURCE: https://www.addgene.org/protocols/weighing-reagents/ +================================================================================ + +INTRODUCTION +================================================================================ + +For many experiments, you'll need to make buffers, media, or other solutions. A key +part of this task is making sure you're weighing all reagents precisely to create +the solution you expect. Understanding how to obtain the correct amounts of materials +for an experiment or reagents for a stock mixture is an essential laboratory +technique, as imprecise measurements can affect the outcome of your experiment. In +this protocol, you will learn the basics of how to weigh reagents. Wear the +appropriate personal protective equipment (PPE) prior to handling the materials. + + +EQUIPMENT +================================================================================ + +• Weighing boats or weighing paper +• Balance +• Scoopula or spatula +• Container (beaker, tube, flask, etc.) + + +REAGENTS +================================================================================ + +• Material that will be weighed out + + +PROCEDURE +================================================================================ + +The balance in the photo above has a capacity of 200 g, as indicated by the number +above the "Zero" button. + +1. Before weighing out your reagents, determine the amount that you need to weigh. + +2. Gather the reagent you will be weighing out, a weighing boat or weighing paper + to contain the reagent while on the balance, and an appropriately sized container + to put the reagent in. For some reagents, you might need to weigh it out in the + fume hood to prevent exposure. Read the reagent's material safety data sheet + (MSDS) to determine if this is best. + +3. Check that the balance has the correct capacity for the material that you are + weighing by looking for a weight range on the scale. Make sure that the weight + of the material you're weighing out is within this range. If you need less than + a gram of material, use an analytical scale. This will provide more accuracy as + these types of scales display more decimal places. + + 💡 PRO TIP: If you're weighing out an amount larger than the capacity of your + balance or weighing boat, you can weigh out the reagents in batches. For + example, if you need 300 g of sucrose, you can weigh out 100 g three times, + placing the sucrose in your container after each time. + +4. Place the weighing boat or weighing paper onto the balance. These are used to + contain the material you're weighing and prevent cross-contamination with other + substances. They also help you transfer the material to your tube or container. + + 💡 PRO TIP: If you're using weighing paper, fold it in half first to create a + crease and then place it unfolded onto the balance. This will help you remove it + from the scale later on as otherwise, the paper could stick to the surface. + +5. Tare the weighing boat or paper. You need to do this because you don't want to + include the weight of the weighing boat or paper into your measurement. Hit the + tare button (or zero button) to set the balance to zero. + + 💡 PRO TIP: If you're weighing a minute amount of reagent that will be + resuspended in a small volume (e.g. 0.02 g to resuspend in 1 mL), you may place + a microcentrifuge tube on the balance and then tare it. Then add the material + directly to the tube to weigh it. + +6. Make sure that your scoopula or spatula is clean, and sterile (if necessary), + to prevent any potential contamination. + +7. Scoop out the material you are weighing onto the weighing boat or paper. If you + weighed out too much material, don't put any extra back into the original + container. Dispose of the excess material into an appropriate waste container if + the material is biohazardous. Check your lab's material safety data sheets + (MSDS) to understand how to properly dispose of reagents that you are working + with. + + 💡 PRO TIP: When you weigh out a reagent, you may leave trace amounts of it on + the balance. Therefore, it's best to clean the balance before adding your next + weighing boat for the next reagent. + +8. Once you've weighed out the correct amount of your reagent, transfer it into + your container. + +9. Make sure that any spills produced during the protocol are cleaned up. Discard + the weighing boat or weighing paper in the trash if the material weighed is not + biohazardous. If it is biohazardous, discard the weighing boat or paper in the + biohazard solid waste container. + + +CONCLUSION +================================================================================ + +Appropriately weighing reagents is important to ensure the accurate composition of +your solutions and buffers. Now that you have your reagents weighed out, you can +begin making your solutions! diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Western Blot.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Western Blot.txt new file mode 100644 index 0000000000000000000000000000000000000000..d77cb1b797180badc37743004dcdac4ee8f0a130 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ Western Blot.txt @@ -0,0 +1,308 @@ +PROTOCOL: Western Blot +SOURCE: https://www.addgene.org/protocols/western-blot/ +================================================================================ + +INTRODUCTION +================================================================================ + +Western blot is a technique used to separate proteins by size followed by +detection using antibodies specific to the protein of interest. This protocol +describes the basic steps for lysing cells, determining total protein +concentration in the lysate, running a precast SDS-PAGE gel, and immunoblotting. + +General Guidelines + +• Acrylamide percentage varies in SDS-PAGE gels. Use lower percentage acrylamide + when immunoblotting high molecular weight proteins and higher percentage + acrylamide when immunoblotting low molecular weight proteins. + +• This protocol uses a dry transfer device but can be adapted for wet and + semi-dry transfer approaches. + +Last Update: January 24, 2022 + + +WORKFLOW TIMELINE +================================================================================ + +Day 1: Prepare lysates, run SDS-PAGE, transfer, block, incubate with primary + antibody + +Day 2: Incubate with secondary antibody + + +EQUIPMENT +================================================================================ + +• Microcentrifuge +• 0.5–10 µL single channel pipette +• 2–20 µL single channel pipette +• 20–200 µL single channel pipette +• 200–1000 µL single channel pipette +• Pipette controller +• Pipette tips and pipettes +• Spectrophotometer +• Heat block +• Mini gel tank chamber +• Power supply +• iBlot 2 Gel Transfer Device +• Roller +• Spatula +• Platform shaker +• Cold room +• Gel imager +• -80 °C freezer + + +REAGENTS +================================================================================ + +• 1X PBS +• Lysis buffer e.g., RIPA lysis buffer +• Microcentrifuge tubes +• BCA Assay, Thermo Fisher 23227 +• β-mercaptoethanol +• 4X protein loading buffer +• Precast SDS-PAGE gel +• SDS-PAGE running buffer +• Prestained protein ladder +• Ethanol +• iBlot 2 PVDF Mini Stack, Thermo Fisher IB24002 +• 20X TBS +• Tween-20 +• Nonfat milk powder +• 96-well microtiter plate +• Chemiluminescence substrate +• Plastic wrap +• Primary antibody +• Secondary antibody +• Deionized water + + +BEFORE STARTING +================================================================================ + +• Refer to the manufacturer's instructions for additional information specific to + your antibody, such as ideal blocking buffer and optimal antibody + concentrations. Consider titrating your antibody to determine the optimal dose. + +• Secondary antibodies must match the host species of the primary antibody. For + example, use an anti-mouse secondary antibody for primary antibodies raised in + a mouse. + + +PROCEDURE +================================================================================ + +Section 1: Lyse cells + +1. Centrifuge 5 x 10⁶ cells for 5 min at 100 x g. + +2. Gently remove supernatant. + +3. Resuspend cell pellet in 1 mL of 1X PBS and transfer to a microcentrifuge + tube. + +4. Centrifuge for 5 min at 100 x g. + +5. Carefully remove supernatant. + +6. Resuspend cell pellet in appropriate volume of cold lysis buffer. + + 💡 PRO TIP: The volume of lysis buffer will vary depending on the size of your + cell pellet but will generally be between 250–1000 µL. + + 💡 PRO TIP: The ideal lysis buffer will vary depending on the cellular location + of the protein of interest. RIPA buffer is suitable for most proteins but more + stringent buffers and a sonication step may be required for hard to extract + proteins such as those in the nucleus. + +7. Incubate on ice for 30 min. + +8. Centrifuge lysate for 15 min at 14,000 x g at 4 °C. + +9. Transfer supernatant to a clean microcentrifuge tube. + +10. Use the lysate immediately or store at -80 °C until ready to use. + +Section 2: Determine the total protein concentration and prepare the lysate for +SDS-PAGE + +1. Determine the protein concentration using a Pierce BCA Assay Kit or other + preferred method for protein determination. + +2. Prepare a 50:1 Reagent A to Reagent B dilution of the BCA assay. + +3. Prepare serial dilutions of the BSA standard that range from 0–2000 µg/mL. + +4. In duplicate, dilute 10 µL of standard, blank, and lysate samples into 200 µL + of BCA reagent in a 96-well microtiter plate. + +5. Incubate for 30 min at 37 °C. + +6. Determine the absorbance at 590 nm. + +7. Calculate the average absorbance of the duplicate samples on the plate. + +8. Subtract the average absorbance of the blank from all of the samples. + +9. Plot a standard curve of BSA standard concentration versus absorbance. + +10. Extrapolate the total protein concentration of the sample from the standard + curve. + +11. Determine the volume of sample required to load an equivalent amount of total + protein for each sample. + + 💡 PRO TIP: The ideal total protein loaded will vary between samples and + target proteins but is typically between 10–50 µg. If the protein is in low + abundance in the sample you will need to load a greater amount of total + protein. + +12. Prepare sample for loading as follows: + • Add 10% v/v β-mercaptoethanol to the 4X protein loading buffer. + • Dilute 4X protein loading buffer in the sample to 1X. + • Boil the samples for 10 min at 100 °C. + +Section 3: SDS-PAGE + +1. Prepare the precast gel as follows: + • Remove the gel from the plastic packaging. + • Remove tape and plastic comb. + • Rinse the wells with deionized water 3x. + • Shake the gel gently between washes to remove residual water. + +2. Load the gel into the chamber of the SDS-PAGE gel tank. + + 💡 PRO TIP: Different SDS-PAGE gel tanks will have different gel orientations. + Refer to the instructions for your specific tank. + +3. Close the clamp. + +4. Prepare 1X running buffer as follows: + • Dilute 25 mL of 20X running buffer to 500 mL with deionized water. Mix well. + +5. Fill the chamber of the SDS-PAGE gel tank with the 1X running buffer. + +6. Load the samples into the gel. + +7. Load 5–10 µL of the prestained protein ladder. + +8. Place the lid on the tank and plug the electrode cords into the power supply. + +9. Run the gel at 100 V for 10–15 min or until the samples have moved out of the + wells and into the gel. + +10. Increase the voltage to 150 V and continue running the gel until you have + obtained the desired separation. + +11. Gently open the gel with the spatula. + +Section 4: Dry transfer + +1. Soak the gel for 15 min in 20% ethanol in deionized water. + + To prepare 20% ethanol, dilute 2 mL of ethanol into 8 mL of deionized water + and mix well. + +2. Assemble the transfer sandwich as follows: + • Unseal the iBlot 2 PVDF Mini transfer stack. + • Set the Top Stack to one side and discard the white separator. + • Keep the Bottom Stack in the plastic tray. + • Place the Bottom Stack on the blotting surface. + • Align the electrical contacts on the blotting surface of the iBlot 2 Gel + Transfer Device. + • Wet the pre-run gel in deionized water and place it on the transfer membrane + of the bottom stack. + • Soak a piece of iBlot Filter Paper in deionized water. + • Place the pre-soaked iBlot Filter Paper on the gel and remove the air bubbles + with the roller. + • Place the Top Stack over the pre-soaked filter paper. + • Remove air bubbles using the roller. + • Place the Absorbent Pad on top of the Top Stack such that the electrical + contacts are aligned with the corresponding electrical contacts on the + blotting surface of the iBlot 2 Gel Transfer Device. + +3. Close the lid of the device. + +4. Select the desired method and make sure the parameters are correct. + +5. Transfer for 5–6 min for proteins <30 kDa. + +6. Transfer for 8–10 min for proteins >150 kDa. + +7. Select Start Run. + +8. When the run is complete, select Done. + +Section 5: Blocking + +1. Prepare 1X TBST as follows: + • 25 mL of 20X TBS + • 2.5 mL of Tween-20 + • 472.5 mL of deionized water + • Mix well + +2. Prepare blocking buffer as follows: + • Dilute 5% w/v non-fat milk into 1X TBST + • Example: 5 g of non-fat milk into 100 mL of 1X TBST. + + 💡 PRO TIP: The ideal blocking buffer will vary between antibodies. Refer to + the manufacturer's information before running your experiment. + +3. Remove the membrane from the transfer device and place it in a container with + 1X TBST, protein side up. + +4. Block the membrane in blocking buffer for 1 h at RT on a shaking platform. + +5. Wash the membrane 3x for 5 min in 1X TBST at RT on a shaking platform. + +Section 6: Antibody incubation + +1. Dilute the primary antibody to the desired concentration in blocking buffer. + + 💡 PRO TIP: The optimal concentration will vary between antibodies but is + typically between 1–10 μg/mL. + +2. Incubate the membrane overnight in primary antibody at 4 °C on a rocking + platform. + + 💡 PRO TIP: Primary antibody incubation can be reduced to 2 h at RT but may + result in more non-specific binding. + +3. Wash the membrane 3x for 5 min in 1X TBST at RT on a shaking platform. + +4. Dilute the horseradish peroxidase-conjugated secondary antibody to the desired + concentration in blocking buffer. + + 💡 PRO TIP: The optimal concentration will vary between antibodies but is + typically between 1–10 μg/mL. + +5. Incubate the membrane with secondary antibody for 60 min at RT on a shaking + platform. + +6. Wash the membrane 3x for 5 min in 1X TBST at RT on a shaking platform. + +7. Prepare the chemiluminescence substrate by mixing 1:1 reagent A to reagent B. + +8. Gently incubate the membrane in the chemiluminescence reagent for 5 min at RT. + +9. Cover the membrane with clear plastic and use a gel imager with + chemiluminescence detection or a dark room to detect the bands. + + +TIPS AND TROUBLESHOOTING +================================================================================ + +• The optimal lysis buffer will vary depending on the sample type and cellular + location of the protein of interest. You may need to try a variety of lysis + buffers to find the best for your target. + +• The optimal concentration and blocking buffer will vary between antibodies. + Review the instructions before starting your experiment and consider titrating + your antibody to determine the optimal dose. + +• To ensure that your antibody is both functioning as expected and is specific, + include a positive control sample that you know expresses the protein, such as + cells transfected with the protein of interest, and a negative control sample + that does not express the protein of interest. diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ What is Polymerase Chain Reaction (PCR).txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ What is Polymerase Chain Reaction (PCR).txt new file mode 100644 index 0000000000000000000000000000000000000000..3c7c7863aad0394b7db61a2aac5b9dce9ddfcd1d --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/addgene/Addgene_ What is Polymerase Chain Reaction (PCR).txt @@ -0,0 +1,226 @@ +PROTOCOL: What is Polymerase Chain Reaction (PCR) +SOURCE: https://www.addgene.org/protocols/pcr/ +================================================================================ + +BACKGROUND INFORMATION +================================================================================ + +A standard Polymerase Chain Reaction (PCR) is an in vitro method that allows a +single, short region of a DNA molecule (single gene perhaps) to be copied multiple +times by Taq Polymerase. From a single copy of DNA (the template), a researcher can +create thousands of identical copies using a simple set of reagents and a basic +heating and cooling (denaturing and annealing) cycle. The process became automated +with the discovery of a heat resistant DNA polymerase from the thermophilic +bacterium, Thermus aquaticus (Taq). Taq polymerase can withstand many heating and +cooling cycles, which would denature DNA polymerases from other species. + +In addition to the template DNA and the Taq polymerase, PCR requires free +nucleotides [dNTPs; adenine (A), cytosine (C), guanine (G), thymine (T)] in an +equal molar ratio. It also requires two unique single stranded DNA oligonucleotide +(oligo) primers, which anneal to the regions upstream (5') and downstream (3') of +the DNA segment to be amplified. When these reagents are combined in an appropriate +buffer, a series of heating (denaturing) and cooling (annealing) steps allow the +Taq polymerase to copy the DNA in between the oligo primers. This molecular biology +technique creates several micrograms of target DNA from just a few nanograms of +template DNA through several cycles of denaturation, annealing, and synthesis. After +the PCR is complete, the product can be verified based on size by gel +electrophoresis. + + +BASIC PCR PROGRAM +================================================================================ + +1. Initial Denaturation for 2 minutes at 94°C: + This initiation step heats the double stranded DNA template strand to the point + where the strands start denaturing and the hydrogen bonds are broken between the + nucleotide base pairs. The initial denaturation step is commonly performed at + 94–98°C. + +2. Denature 30 seconds at 94°C: + Continued denaturation of double stranded DNA. + +3. Anneal primers for 30 seconds at 55°C: + The forward and reverse primers are stable within this temperature range to + anneal to each of the single stranded DNA template strands. The DNA polymerase + is also stable enough to now bind to the primer DNA sequence. + +4. Extend DNA for 1 minute at 72°C: + The Taq polymerase has an optimal temperature around 70-75°C so this step enables + the DNA polymerase to synthesize and elongate the new target DNA strand + accurately and rapidly. + +5. Repeat steps 2-4 25-30 times. + +6. Final Extension for 5 minutes at 72°C: + A final extension to fill-in any protruding ends of the newly synthesized + strands. + + +MATERIALS LIST +================================================================================ + +Reagents for each 50µL PCR: + +• Thin-walled PCR tube +• Ice Bucket +• 2 μL Template DNA (10 ng-500 ng) +• 5 μl 10X Taq buffer with MgCl₂ +• 1 μl dNTP mix (10 mM each nt) +• 2.5 μL Forward Primer (10 μM stock) +• 2.5 μL Reverse Primer (10 μM stock) +• 36.8 μL Sterile dH₂O +• 0.2 μL Taq DNA Polymerase (5 units/μL) +• PCR Machine +• Agarose Gel + + +PROCEDURE +================================================================================ + +Primer Design and PCR + +1. Design Primers. See our protocol on how to design primers. + + Note: Primer3 is an excellent resource for choosing primers. + +2. Place thin-walled PCR tubes on ice. + +3. Set up a 50 μL reaction (Keep all your reagents on ice): + • 2 μL Template DNA (10 ng-500 ng) + • 5 μl 10X Taq buffer with MgCl₂ + • 1 μl dNTP mix (10 mM each nt) + • 2.5 μL Forward Primer (10 μM stock) + • 2.5 μL Reverse Primer (10 μM stock) + • 0.2 μL Taq DNA Polymerase (5 units/μL) + • 36.8 μL Sterile dH₂O (variable) + + Note: If you are doing multiple PCRs, save time by creating a "master mix," + which minimizes the number of small volumes you need to pipet. If you are using + the same template DNA for all your reactions, the Template DNA can be added to + the master mix. Forward and Reverse Primers DO NOT get added to a master mix. + +4. Place reaction tubes in PCR machine. + +5. Set annealing temperature 5°C below the primer melting temperature (Tm). + +6. Set extension step at 1-2 minutes per kilobase of product depending on whether + you are using a polymerase with proofreading capabilities. + + Note: See manufacturer's instructions for specific instructions about extension + time and temperatures. + +7. Initial Denaturation for 2 minutes at 94°C. + +8. Denature for 30 seconds at 94°C. + +9. Anneal primers for 30 seconds at 55°C (or 5°C below Tm). + +10. Extend DNA for 2 minutes at 72°C. + +11. Repeat steps 8-10 for 25-30 cycles. + +12. Final Extension for 5 minutes at 72°C. + +13. Run 2 μL on a gel to check size and concentration of PCR product. + +Master Mix Preparation + +1. Multiply the volume of each reagent by the number of individual PCRs you wish to + perform and add 10% extra to account for pipetting error. In this example, we + have 7 different reactions (7 unique primer pairs), so we multiply each volume + by 7. + +2. In a single 1.5mL tube combine the following: + • 10X Taq buffer with MgCl₂: 5μl x 7 reactions = 35μl total + 10% (3.5μl) = + 38.5μl + • dNTP mix (10 mM each nt): 1µl x 7 reactions = 7µl total + 10% (0.7µl) = + 7.7µl + • Template DNA: 2µl x 7 reactions = 14µl total + 10% (1.4µl) = 15.4µl + • Sterile dH₂O: 36.8µl x 7 reactions = 257.6µl + 10% (25.7µl) = 283.3µl + • Taq DNA polymerase: 0.2µl x 7 reactions = 1.4µl + 10% (0.14µl) = 1.54µl + +3. Mix the contents by gently pipetting up and down several times. Keep tube on ice. + +4. Add the forward and reverse primers to the thinned walled PCR tubes. + + Note: Do this before adding the master mix so you know that the primers have + been added, pipet the forward primer onto one side of the tube wall and the + reverse primer onto the other. + +5. Add the master mix to the thin walled PCR tubes. Put 50µl – 2.5µl (fwd primer) – + 2.5µl (rev primer) = 45µl volume of master mix to add to each PCR tube. + +6. Secure the tops to the PCR tubes, gently tap each tube to bring all the liquid + to the bottom before placing it in the PCR machine. + +Diluting Primers + +Most people order primers from a company, which synthesizes and ships them as a +lyophilized powder. The researcher then needs to reconstitute their primers in +liquid, normally sterile dH₂O. To make a 100uM stock of any primer, add a number of +µl of dH₂O equal to the number of nanomoles of DNA times 10. For example, if your +lyophilized DNA is 38.5nm, add 385µl of water. + +After making your 100uM stock, immediately make a working concentration of each +primer (10uM) by making a 1:10 dilution of the stock. For example, add 100µl of +primer stock to 900µl of dH₂O. + + +TIPS AND FAQ +================================================================================ + +Tips + +• If your target DNA sequence is GC-rich, increase the time of the denaturing. + +• Your 5' and 3' primers should be designed to have similar melting temperatures + (Tm). Set the annealing temperature to 5°C lower than the Tm of your primers. If + you are getting non-specific PCR products, increase the annealing temperature + step-wise by 1-2°C. + +• The rate of DNA synthesis is ~1-2 kb/min. The extension time can be adjusted + according to the length of the target sequence. + +FAQ + +How do I design primers? + +See our reference page on how to design primers for detailed instructions and +check out our protocol on plasmid cloning by PCR to learn how to design primers for +cloning purposes. + +What do I do if my PCR isn't working? + +Try adding 1µl of 25mM MgCl₂ and/or 1µl DMSO to each reaction. The ideal setup for +this troubleshooting step is to do one reaction with each, and one reaction with +both. MgCl₂ acts to supplement the amount supplied by the buffer stock, where it is +known to form a gradient when frozen. DMSO helps with denaturation of the DNA, +particularly for GC-rich templates. + +What does each ingredient specifically do? + +• Template DNA: Contains the portion of DNA that we are interested in amplifying + for analysis and manipulation. It is essential that the template DNA and primer + are complementary for a PCR to work efficiently. + +• Taq Buffer with MgCl₂: Provides an optimal and stable chemical environment for + the DNA polymerase to work adequately. Divalent cations such as Mg²⁺ and Mn²⁺ + stabilize the buffer solution. These cations can also be used for PCR-mediated DNA + mutagenesis. A higher cation concentration increases the error rate of the DNA + polymerase. + +• Deoxynucleoside Triphosphates (dNTPs): Are the building blocks added one at a time + to the new DNA strand by the DNA polymerase. + +• Forward and Reverse Primers: Hybridize and are complementary to the 3' ends of + the sense and anti-sense strands of the template DNA. They are strands of nucleic + acid that are starting points for DNA elongation and synthesis. + +• Taq DNA polymerase: Special DNA polymerase that can withstand radical + temperature changes during a typical PCR. The DNA polymerase has an optimum + temperature around 70°C and is the molecule responsible for driving the DNA + synthesis. + +• Sterile dH₂O: Used to fill the remaining 50 μL of the reaction mix. Its solvent + and buffer capabilities provide a suitable environment for the DNA amplification + reaction. diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/Actin Staining Protocol _ Thermo Fisher Scientific - US.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/Actin Staining Protocol _ Thermo Fisher Scientific - US.txt new file mode 100644 index 0000000000000000000000000000000000000000..58e3364a06944769ec235df056f277f29dc661d2 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/Actin Staining Protocol _ Thermo Fisher Scientific - US.txt @@ -0,0 +1,229 @@ +PROTOCOL: Actin Staining Protocol +SOURCE: https://www.thermofisher.com/us/en/home/references/protocols/cell-and-tissue-analysis/microscopy-protocol/actin-staining-protocol.html +================================================================================ + +INTRODUCTION +================================================================================ + +We offer several fluorescent and biotinylated phalloidin and phallacidin derivatives +for labeling F-actin. These phallotoxins, isolated from the deadly Amanita phalloides +mushroom, are bicyclic peptides that differ by two amino acid residues. They can be +used interchangeably in most applications and bind competitively to the same sites in +F-actin. Phalloidin and phallacidin contain an unusual thioether bridge between a +cysteine and tryptophan residue that forms an inner ring structure. At elevated pH, +this thioether is cleaved and the toxin loses its affinity for actin. + +Fluorescent and biotinylated phallotoxins stain F-actin at nanomolar concentrations +and are extremely water soluble, thus providing convenient probes for labeling, +identifying, and quantitating F-actin in tissue sections, cell cultures, or cell-free +experiments. Labeled phallotoxins have similar affinity for both large and small +filaments, binding in a stoichiometric ratio of about one phallotoxin molecule per +actin subunit in muscle and nonmuscle cells from many different species of plants and +animals. Unlike antibodies, the binding affinity does not change appreciably with +actin from different species or sources. Nonspecific staining is negligible, and the +contrast between stained and unstained areas is extremely large. It has been reported +that phallotoxins are unable to bind to monomeric G-actin. + +Phallotoxins shift the monomer/polymer equilibrium toward the polymer, lowering the +critical concentration for polymerization up to 30-fold. Phallotoxins also stabilize +F-actin, inhibiting depolymerization by cytochalasins, potassium iodide, and elevated +temperatures. + +Because the phallotoxin conjugates are small, with an approximate diameter of 12–15 Å +and molecular weight of <2000 daltons, a variety of actin-binding proteins—including +myosin, tropomyosin, troponin, and DNase I—can still bind to actin after treatment +with phallotoxins. Even more significantly, phallotoxin-labeled actin filaments +remain functional; labeled glycerinated muscle fibers still contract, and labeled +actin filaments still move on solid-phase myosin substrates. + +Fluorescent phallotoxins can also be used to quantitate the amount of F-actin in +cells. The unlabeled phallotoxins may be used as controls in blocking F-actin +staining or in promoting actin polymerization. Our biotin-XX phalloidin allows +researchers to visualize actin filaments by electron microscopy using standard +enzyme-mediated avidin/streptavidin techniques. Eosin phalloidin can potentially be +used for correlated fluorescence and electron microscopic studies. Deerinck and +co-workers reported that when eosin conjugates are excited in the presence of +diaminobenzidine (DAB), an insoluble, electron-dense DAB oxidation product is formed +that is easily visualized with either light or electron microscopy. + +Even though phallotoxins have an LD50 of approximately 2 mg/kg when injected into +the mouse, the toxins of A. phalloides that are responsible for most of the symptoms +and fatalities associated with poisoning by this mushroom are the structurally related +amatoxins. The major in vivo lesions produced by injected phallotoxin occur in the +liver and are associated with stabilization of polymeric actin. Phallotoxins, however, +tend not to be absorbed by the gastrointestinal tract even though they are stable +between pH 3 and pH 9. + + +MATERIALS +================================================================================ + +Storage and Safety + +Once reconstituted in methanol, the stock solutions are stable for at least one year +when stored frozen at –20°C, desiccated, and protected from light. It appears that +NBD phallacidin, and possibly all of these toxins, exhibit a small loss of activity +when stored in aqueous solution at 2–6°C for over three weeks. + +While the amount of toxin present in a vial could be lethal only to a mosquito (LD50 +of phalloidin = 2 mg/kg), it should be handled with care. + +Materials Required but Not Provided + +• Methanol +• PBS +• Methanol-free formaldehyde +• Acetone or Triton X-100 +• Fluorescent or enzyme-conjugated streptavidin, as prepared in step 1.9, for use + with biotin-XX phalloidin only +• BSA, optional +• Image-iT FX Signal Enhancer (I36933), optional +• lysopalmitoylphosphatidylcholine, optional + +Preparing the Stock Solution + +Fluorescent Phallotoxins + +The vial contents should be dissolved in 1.5 mL methanol to yield a final +concentration of 200 units/mL, which is equivalent to approximately 6.6 µM. One unit +of phallotoxin is defined as the amount of material used to stain one microscope +slide of fixed cells, according to the following protocol (see step 1.6), and is +equivalent to 5 µL of methanolic stock solution for the fluorescent phallotoxins. + +Biotin-XX Phalloidin + +Staining cells with biotin-XX phalloidin (B7474) requires 1) the use of a higher +concentration of the phallotoxin conjugate than when staining with fluorescent +phallotoxins and 2) the addition of a fluorescent or enzyme-conjugated avidin or +streptavidin detection reagent (see step 1.9). The vial contents should be dissolved +in 0.5 mL methanol to yield a final concentration of 100 units/mL, which is +equivalent to approximately 20 µM. For biotin-XX phalloidin, 10 µL of the +methanolic stock solution is equivalent to one unit of phallotoxin, which is defined +as the amount of material used to stain one microscope slide of fixed cells +according to the following protocol (see step 1.6). + +Unlabeled Phalloidin + +Solutions of this product should be prepared just like the fluorescent phallotoxins +described in Fluorescent Phallotoxins, taking into account the larger quantity of +material provided. + + +PROTOCOL +================================================================================ + +The procedure below was originally developed for use with NBD phallacidin. It has +been successfully used with all of Invitrogen Molecular Probes phallotoxin +conjugates. This procedure may not be optimum for a particular experimental system, +but has yielded consistent results in most instances. The following protocol +describes the staining procedure for adherent cells grown on glass coverslips. + +1. Formaldehyde-Fixed Cells + + 1.1. Wash cells twice with prewarmed phosphate-buffered saline, pH 7.4 (PBS). + + 1.2. Fix the sample in 3.7% formaldehyde solution in PBS for 10 minutes at room + temperature. + + Note: Methanol can disrupt actin during the fixation process. Therefore, + it is best to avoid any methanol containing fixatives. The preferred + fixative is methanol-free formaldehyde. + + 1.3. Wash two or more times with PBS. + + 1.4. Place each coverslip in a glass petri dish and extract it with a solution + of acetone at –20°C or 0.1% Triton X-100 in PBS for 3 to 5 minutes. + + 1.5. Wash two or more times with PBS. + + 1.6. When staining with any of the fluorescent phallotoxins, dilute 5 µL + methanolic stock solution into 200 µL PBS for each coverslip to be + stained. To reduce nonspecific background staining with these conjugates, + add 1% bovine serum albumin (BSA) to the staining solution. It may also be + useful to pre-incubate fixed cells with PBS containing 1% BSA or with the + Image-iT FX signal enhancer (I36933) for 20–30 minutes prior to adding + the phallotoxin staining solution. When staining with biotin-XX phalloidin + (B7474), dilute 10 µL of the methanolic stock solution into 200 µL PBS + for each coverslip to be stained. When staining more than one coverslip, + adjust volumes accordingly. For a stronger signal, use 2 or 3 units per + coverslip. + + 1.7. Place the staining solution on the coverslip for 20 minutes at room + temperature (generally, any temperature between 4°C and 37°C is suitable). + To avoid evaporation, keep the coverslips inside a covered container + during the incubation. + + 1.8. Wash two or more times with PBS. + + 1.9. When using biotin-XX phalloidin, incubate for 30 minutes with 100 µL of a + 10 µg/mL solution of fluorescent or enzyme-conjugated streptavidin + dissolved in 100 mM Tris-HCl, pH 7.5, 150 mM NaCl, 0.3% Triton X-100 and + 1% BSA. Incubate for 15 minutes at room temperature. After incubation, + wash the coverslip with PBS. To develop enzyme activity, follow a + procedure recommended for the specific enzyme. + + 1.10. For long-term storage, the cells should be air dried and then mounted in a + permanent mountant such as ProLong Gold reagent or Cytoseal. Specimens + prepared in this manner retain actin staining for at least six months + when stored in the dark at 2–6°C. + +2. Simultaneous Fixation, Permeabilization, and Fluorescent Phallotoxin Staining + + The phallotoxins appear to be stable for short periods in 4% formaldehyde + fixation buffers. This permits a rapid one-step fixation, permeabilization, + and labeling procedure as follows. + + 2.1. Prepare a 1 mL solution containing 50 to 100 µg/mL + lysopalmitoylphosphatidylcholine and 3.7% formaldehyde and then add 5–10 + units of fluorescent phallotoxin (approximately 25 to 50 µL of methanolic + stock solution). + + 2.2. Place this staining solution on cells and incubate for 20 minutes at 4°C. + + 2.3. Rapidly wash three times with buffer. + + 2.4. Mount coverslips and view. + + +TIPS FOR FLUORESCENCE MICROSCOPY +================================================================================ + +Photostability or resistance to photobleaching is a primary concern when making +fluorescence measurements. Invitrogen brand product lines such as Alexa Fluor, +Oregon Green, BODIPY, and rhodamine fluorophores (including Texas Red™-X) are +significantly more photostable than NBD and fluorescein and will therefore enable +more accurate photographic measurements. + +To further reduce photobleaching, minimize the exposure of fluorescently labeled +specimens to light with neutral density filters and expose samples only when +observing or recording a signal. Maximize collection of fluorescence by using a +minimum of optics, high–numerical aperture objectives, relatively low magnification, +high-quality optical filters, and high-speed film or high-efficiency detectors. + +Invitrogen Antifade reagents, including Molecular Probes SlowFade Gold and ProLong +Gold antifade reagents, can extend the useful lives of many fluorescent probes. +These reagents are also available in a formulation with DAPI. They can be used on +fixed cell preparations but are not compatible with living cells. Cytoseal also +appears to protect BODIPY fluorophores from photobleaching. + + +REFERENCES +================================================================================ + +1. Wieland, T. in Phallotoxins, Springer-Verlag, New York (1986). +2. J Muscle Res Cell Motil 9, 370 (1988). +3. Methods Enzymol 85, 514 (1982). +4. Eur J Biochem 165, 125 (1987). +5. J Cell Biol 105, 1473 (1987). +6. Nature 326, 805 (1987). +7. Proc Natl Acad Sci USA 83, 6272 (1986). +8. Blood 69, 945 (1987). +9. Anal Biochem 200, 199 (1992). +10. J Cell Biol 126, 901 (1994). +11. Proc Natl Acad Sci USA 77, 980 (1980). +12. Nature 284, 405 (1980). +13. CRC Crit Rev Biochem 5, 185 (1978). +14. J Cell Biol 106, 1229 (1988). +15. J Cell Biol 103, 265a (1986). +16. Eur J Cell Biol 24, 176 (1981). +17. Proc Natl Acad Sci USA 74, 5613 (1977). diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/ActinGreen 488 ReadyProbes Reagent Protocol _ Thermo Fisher Scientific - US.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/ActinGreen 488 ReadyProbes Reagent Protocol _ Thermo Fisher Scientific - US.txt new file mode 100644 index 0000000000000000000000000000000000000000..19a990ca04c9a2ff456012ee962bb950ab5314e1 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/ActinGreen 488 ReadyProbes Reagent Protocol _ Thermo Fisher Scientific - US.txt @@ -0,0 +1,67 @@ +PROTOCOL: ActinGreen 488 ReadyProbes Reagent Protocol +SOURCE: https://www.thermofisher.com/us/en/home/references/protocols/cell-and-tissue-analysis/protocols/actin-green-488-readyprobes-protocol.html +================================================================================ + +OVERVIEW +================================================================================ + +F-actin stain for fixed cells + +ActinGreen 488 ReadyProbes Reagent is a selective, high-affinity F-actin probe conjugated to our bright, photostable green-fluorescent Alexa Fluor 488 dye. Like other ReadyProbes reagents, the ActinGreen 488 reagent is formulated as a room temperature–stable solution and comes in a convenient dropper bottle. + +APPLICATIONS +================================================================================ + +This protocol can be used for: +• F-actin staining in fluorescence microscopy + +This protocol should not be used for: +• Flow cytometry + +MATERIALS REQUIRED +================================================================================ + +• Cells growing in culture +• ActinGreen 488 ReadyProbes Reagent (Cat. No. R37110) +• Fluorescence microscope + +PROTOCOL +================================================================================ + +Labeling fixed cells + +First, fix and permeabilize cultured cells with a protocol appropriate for your sample. Counterstain as desired. DAPI may be added directly to fixative. + +1. Wash the cells 1–3 times in PBS as needed. +2. Add two drops of ActinGreen 488 ReadyProbes Reagent per milliliter of medium. +3. Incubate for 30 minutes, protected from light. +4. Remove the stain solution. +5. Wash the cells 2–3 times in PBS. +6. Image the cells. + +SPECTRAL INFORMATION AND STORAGE +================================================================================ + +ActinGreen 488: +• Excitation/Emission (nm): 495/518 +• Standard filter set: FITC +• EVOS Light Cube: GFP +• Storage conditions: Room temperature + +PROTOCOL TIPS +================================================================================ + +• In some cases, more or fewer drops may be needed to achieve optimal staining intensity. +• Image quality may be improved by replacing the culture medium with Live Cell Imaging Solution (Cat. No. A14291DJ). + +EXAMPLE APPLICATION +================================================================================ + +Multicolor staining of HeLa cells. + +HeLa cells were grown on coverslips and were fixed and permeabilized using the Image-iT Fixation/Permeabilization Kit. Cells were then stained to detect actin (green fluorescence from ActinGreen 488 ReadyProbes Reagent), B-catenin (red-orange fluorescence), and nuclei (blue fluorescence). + +PRODUCT CATALOG NUMBER +================================================================================ + +R37110 diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/ActinRed 555 ReadyProbes Reagent Protocol _ Thermo Fisher Scientific - US.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/ActinRed 555 ReadyProbes Reagent Protocol _ Thermo Fisher Scientific - US.txt new file mode 100644 index 0000000000000000000000000000000000000000..e7ff1e89733e2135f3b6f7a4d45240a58b258608 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/ActinRed 555 ReadyProbes Reagent Protocol _ Thermo Fisher Scientific - US.txt @@ -0,0 +1,67 @@ +PROTOCOL: ActinRed 555 ReadyProbes Reagent Protocol +SOURCE: https://www.thermofisher.com/us/en/home/references/protocols/cell-and-tissue-analysis/protocols/actin-red-555-readyprobes-protocol.html +================================================================================ + +OVERVIEW +================================================================================ + +F-actin stain for fixed cells + +ActinRed 555 ReadyProbes Reagent is a selective, high-affinity F-actin probe conjugated to the red-orange fluorescent dye tetramethylrhodamine (TRITC). Like other ReadyProbes reagents, ActinRed 555 reagent is formulated as a room temperature–stable solution and comes in a convenient dropper bottle. + +APPLICATIONS +================================================================================ + +This protocol can be used for: +• F-actin staining in fluorescence microscopy + +This protocol should not be used for: +• Flow cytometry + +MATERIALS REQUIRED +================================================================================ + +• Cells growing in culture +• ActinRed 555 ReadyProbes Reagent (Cat. No. R37112) +• Fluorescence microscope + +PROTOCOL +================================================================================ + +Labeling fixed cells + +First, fix and permeabilize cultured cells with a protocol appropriate for your sample. Counterstain as desired. DAPI may be added directly to fixative. + +1. Wash the cells 1–3 times in PBS as needed. +2. Add two drops of ActinRed 555 ReadyProbes Reagent per milliliter of medium. +3. Incubate for 30 minutes, protected from light. +4. Remove the stain solution. +5. Wash the cells 2–3 times in PBS. +6. Image the cells. + +SPECTRAL INFORMATION AND STORAGE +================================================================================ + +ActinRed 555: +• Excitation/Emission (nm): 540/565 +• Standard filter set: TRITC +• EVOS Light Cube: TRITC +• Storage conditions: Room temperature + +PROTOCOL TIPS +================================================================================ + +• In some cases, more or fewer drops may be needed to achieve optimal staining intensity. +• Image quality may be improved by replacing the culture medium with Live Cell Imaging Solution (Cat. No. A14291DJ). + +EXAMPLE APPLICATION +================================================================================ + +Multicolor staining of BPAE cells. + +BPAE cells were fixed and permeabilized using the Image-iT Fixation/Permeabilization Kit. Actin was stained using ActinRed 555 ReadyProbes Reagent, and nuclei were stained with NucBlue Fixed Cell ReadyProbes Reagent. + +PRODUCT CATALOG NUMBER +================================================================================ + +R37112 diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/Adherent Cell Culture Protocol _ Thermo Fisher Scientific - US.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/Adherent Cell Culture Protocol _ Thermo Fisher Scientific - US.txt new file mode 100644 index 0000000000000000000000000000000000000000..2ea3f10f4fc6540a7182c6e71f5922d43fbd5a34 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/Adherent Cell Culture Protocol _ Thermo Fisher Scientific - US.txt @@ -0,0 +1,75 @@ +PROTOCOL: Adherent Cell Culture Protocol +SOURCE: https://www.thermofisher.com/us/en/home/references/gibco-cell-culture-basics/cell-culture-protocols/subculturing-adherent-cells.html +================================================================================ + +OVERVIEW +================================================================================ + +An adherent cell culture is characterized by the cell's ability to proliferate when attached to a growth-promoting substrate, a property known as "anchorage dependence." The following protocols detail various methods for dissociation of adherent cells from cultureware and subsequent procedures for subculturing, or splitting, adherent cells. + +MATERIALS FOR DETACHING AND PASSAGING ADHERENT CELLS +================================================================================ + +In addition to the catalog items below, detaching and passaging adherent cells also requires the following: + +• Adherent cells +• Tissue-culture treated flasks, plates or dishes +• Complete growth medium: basal medium, serum, and supplements pre-warmed to 37°C +• Disposable, sterile 15 mL tubes +• 37°C incubator with humidified atmosphere of 5% CO₂ +• Pipettes and pipette tips +• Automated cell counter such as the Countess Automated Cell Counter + +Catalog numbers: 13151014, 13150016, 14190144, 15400054, 15090046, 12604013, 15575020, 179693, 17105041, 15040066, 15250061 + +PROTOCOL FOR PASSAGING ADHERENT CELLS +================================================================================ + +The following adherent cell culture protocol describes how to subculture mammalian cells. Note that the procedure for subculturing insect cells differs from that for mammalian cells in several crucial steps. For more information, refer to "Considerations for passaging adherent insect cells" below. + +For passaging a particular cell line within your experiments, we recommend that you closely follow the instructions provided with each product you use, especially regarding formulation of your complete growth medium. The consequences of deviating from the culture conditions specified for a particular cell type can range from the expression of aberrant phenotypes to a complete failure of the cell culture. The SDSs for all Thermo Fisher Scientific products can be accessed here. + +Before passaging, ensure the solutions and equipment that come in contact with the cells are sterile. Use proper sterile technique throughout the subculture procedure and work in a laminar flow hood. + +Routinely monitor your cell's viability prior to subculturing. Adherent cells should be passaged at log phase with viability greater than 90% at the time of subculturing. + +1. Remove and discard the spent cell culture media from the culture vessel. + +2. Wash cells using a balanced salt solution without calcium and magnesium (approximately 2 mL per 10 cm² culture surface area). Gently add wash solution to the side of the vessel opposite the attached cell layer to avoid disturbing the cell layer and rock the vessel back and forth several times. The wash step removes any traces of serum, calcium, and magnesium that would inhibit the action of the dissociation reagent. + +3. Remove and discard the wash solution from the culture vessel. + +4. Add the pre-warmed dissociation reagent such as trypsin or TrypLE to the side of the flask; use enough reagent to cover the cell layer (approximately 0.5 mL per 10 cm²). Gently rock the container to get complete coverage of the cell layer. + +5. Incubate the culture vessel at room temperature for approximately 2 minutes. Note that the actual incubation time varies with the cell line used. + +6. Observe the cells under the microscope for detachment. If cells are less than 90% detached, increase the incubation time a few more minutes, checking for dissociation every 30 seconds. You may also tap the vessel to expedite cell detachment. + +7. When ≥ 90% of the cells have detached, tilt the vessel for a minimal length of time to allow the cells to drain. Add the equivalent of 2 volumes (twice the volume used for the dissociation reagent) of pre-warmed complete growth medium. Disperse the medium by pipetting over the cell layer surface several times. + +8. Transfer the cells to a 15 mL conical tube and centrifuge them at 200 x g for 5 to 10 minutes. Note that the centrifuge speed and time vary based on the cell type. + +9. Resuspend the cell pellet in a minimal volume of pre-warmed complete growth medium and remove a sample for counting. + +10. Determine the total number of cells and percent viability using a hemocytometer and the Trypan blue exclusion protocol, or the Invitrogen Countess Automated Cell Counter. If necessary, add growth media to the cells to achieve the desired cell concentration and recount the cells. + +11. Dilute cell suspension to the seeding density recommended for the cell line, and pipet the appropriate volume into new cell culture vessels and return the cells to the incubator. If using culture flasks, loosen the caps before placing them in the incubator to allow proper gas exchange unless you are using vented flasks with gas-permeable caps. + +CONSIDERATIONS FOR PASSAGING ADHERENT INSECT CELLS +================================================================================ + +While the general procedure for subculturing insect cells follows the same steps as mammalian cells, some key requirements of these culture systems are different. For the best results, always follow the instructions provided with each product you are using in your experiments. + +When to subculture adherent insect cells + +Passage insect cells at log phase, before they reach confluency, unless your cells are strongly adherent. If your insect cells are strongly adherent, you may passage them at confluency or slightly after when they are starting to pull away from the bottom of the flask because they will be easier to dislodge. However, insect cells that are repeatedly passaged at densities past confluency display decreased doubling times, decreased viability, and a decreased ability to attach. + +In contrast, passaging insect cells in adherent culture before they reach confluency requires more mechanical force to dislodge them from the monolayer. When repeatedly subcultured before confluency, these cells also display decreased doubling times, decreased viability, and are considered unhealthy. Densities lower than 20% confluency inhibit cell growth as well. + +How to subculture insect cells + +• Maintain insect cells at 27°C in a non-humidified environment. Cells can be maintained at room temperature on the bench top if protected from light or in a drawer. However, a 27°C controlled environment is recommended. +• CO₂ exchange is not recommended for insect cell culture. +• Use media specifically formulated for insect cell growth. Insect cells are cultured in growth media that are usually more acidic than those used for mammalian cells such as Grace's medium. +• Insect cells attach very tightly to substrates under serum-free conditions and require additional effort to detach. To dislodge the cells, you may need to give the flask one quick shake using a wrist-snapping motion. To avoid contamination, always tighten the cap before this procedure. +• Do not shake the flask vigorously, because it may result in damage to the cells. diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/Basic Sandwich ELISA Protocol _ Thermo Fisher Scientific - US.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/Basic Sandwich ELISA Protocol _ Thermo Fisher Scientific - US.txt new file mode 100644 index 0000000000000000000000000000000000000000..f5ae3352aee0f3b4090d759fc5b39b3ccf6d6786 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/Basic Sandwich ELISA Protocol _ Thermo Fisher Scientific - US.txt @@ -0,0 +1,98 @@ +PROTOCOL: Basic Sandwich ELISA Protocol +SOURCE: Thermo Fisher Scientific - US +URL: https://www.thermofisher.com/us/en/home/references/protocols/cell-and-tissue-analysis/elisa-protocol/general-elisa-protocol.html +================================================================================ + +OVERVIEW +================================================================================ + +The sandwich ELISA (enzyme-linked immunosorbent assay) is a highly sensitive immunoassay technique used to detect and quantify specific proteins or antigens in samples. This method uses two antibodies: a capture antibody that binds to the target antigen, and a detection antibody that recognizes a different epitope on the same antigen. The detection antibody is conjugated to an enzyme (such as horseradish peroxidase or alkaline phosphatase) that produces a measurable signal. + +MATERIALS REQUIRED +================================================================================ + +• 96-well microplate (pre-coated with capture antibody or uncoated for manual coating) +• Capture antibody (specific to target antigen) +• Detection antibody (conjugated to HRP or AP, specific to target antigen) +• Blocking buffer (e.g., 1% BSA or 5% non-fat dry milk in PBS) +• Wash buffer (PBS with 0.05% Tween-20, PBST) +• Sample diluent (PBS or assay buffer) +• Standard/reference antigen (for standard curve) +• Substrate solution (TMB for HRP, or pNPP for AP) +• Stop solution (2N H2SO4 for TMB, or 3N NaOH for pNPP) +• Plate reader (capable of reading absorbance at appropriate wavelength) + +PROTOCOL +================================================================================ + +Day 1: Plate Coating (if using uncoated plates) + +1. Dilute capture antibody in coating buffer (typically 0.1 M carbonate-bicarbonate buffer, pH 9.6, or PBS) to the recommended concentration (usually 1-10 µg/mL). + +2. Add 100 µL of diluted capture antibody to each well of a 96-well microplate. + +3. Cover plate and incubate overnight at 4°C, or for 2 hours at room temperature. + +4. Remove the coating solution and wash plate 3 times with wash buffer (200-300 µL per well). Invert plate and tap on paper towels to remove excess liquid. + +Day 2: Blocking and Assay + +5. Add 200-300 µL of blocking buffer to each well. + +6. Incubate for 1-2 hours at room temperature, or overnight at 4°C. + +7. Wash plate 3 times with wash buffer as described in step 4. + +8. Prepare samples and standards: + - Dilute samples in sample diluent to appropriate concentration + - Prepare standard curve by serial dilution of reference antigen in sample diluent + - Include blank wells with sample diluent only + +9. Add 100 µL of samples and standards to appropriate wells in duplicate or triplicate. + +10. Cover plate and incubate for 1-2 hours at room temperature, or overnight at 4°C. + +11. Wash plate 3-5 times with wash buffer as described in step 4. + +12. Dilute detection antibody in blocking buffer or antibody diluent to recommended concentration (typically 0.5-2 µg/mL). + +13. Add 100 µL of diluted detection antibody to each well. + +14. Cover plate and incubate for 1-2 hours at room temperature. + +15. Wash plate 3-5 times with wash buffer as described in step 4. + +16. Prepare substrate solution according to manufacturer's instructions. + +17. Add 100 µL of substrate solution to each well. + +18. Incubate at room temperature, protected from light, for 5-30 minutes (or until desired color development). + +19. Add 50-100 µL of stop solution to each well (if using TMB or other substrates requiring stopping). + +20. Read plate immediately using a microplate reader at the appropriate wavelength: + - TMB: 450 nm (with 570 nm or 630 nm reference) + - pNPP: 405 nm + - OPD: 492 nm + +DATA ANALYSIS +================================================================================ + +1. Subtract the average absorbance of blank wells from all sample and standard values. + +2. Plot standard curve: absorbance (y-axis) vs. concentration (x-axis) using standard values. + +3. Use the standard curve to determine the concentration of unknown samples. + +4. For accurate results, ensure sample values fall within the linear range of the standard curve. + +PROTOCOL TIPS +================================================================================ + +• Always include negative controls (no antigen) and positive controls (known concentration of antigen) +• Use fresh substrate solutions and prepare just before use +• Avoid bubbles when adding solutions to wells +• Ensure consistent incubation times and temperatures +• Wash thoroughly between steps to reduce background signal +• Optimize antibody concentrations and incubation times for your specific assay +• For best results, use high-quality, validated antibody pairs diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/BestProtocols_ Annexin V Staining Protocol for Flow Cytometry _ Thermo Fisher Scientific - US.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/BestProtocols_ Annexin V Staining Protocol for Flow Cytometry _ Thermo Fisher Scientific - US.txt new file mode 100644 index 0000000000000000000000000000000000000000..9316471b540e457cdf6359c6ccdec595adab4e8a --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/BestProtocols_ Annexin V Staining Protocol for Flow Cytometry _ Thermo Fisher Scientific - US.txt @@ -0,0 +1,128 @@ +PROTOCOL: BestProtocols: Annexin V Staining Protocol for Flow Cytometry +SOURCE: https://www.thermofisher.com/us/en/home/references/protocols/cell-and-tissue-analysis/protocols/annexin-v-staining-flow-cytometry.html +================================================================================ + +OVERVIEW +================================================================================ + +Note: This protocol is intended for use with the specific products mentioned within it. Substituting different products is not recommended. + +The use of the annexin V apoptosis assay protocol is a common method for detecting apoptotic cells. The below protocols are recommended for use with the specific flow cytometry kits mentioned. Please see the Annexin V Staining page for a discussion about general experimental conditions and avoiding false positives, or to review a selection guide for all of our annexin V products. + +GENERAL NOTES +================================================================================ + +• Invitrogen Fixable Viability Dye (FVD) eFluor 450 is not recommended for use with Annexin V Apoptosis Detection Kits. +• Due to the calcium dependence of the Annexin V:PS interaction, it is critical to avoid buffers containing EDTA or other calcium chelators during Annexin V experiments. +• Annexin V can only be used as a marker of apoptosis in cells where the plasma membrane is intact. Destroying the integrity of the plasma membrane will allow binding of Annexin V to PS inside the cell. + +PROTOCOL A: ANNEXIN V STAINING PROTOCOL +================================================================================ + +Materials + +• 12 x 75 mm round-bottom tubes +• 1X PBS +• Annexin V Apoptosis Detection kit (any one of the kits listed). Each kit includes an Annexin V conjugate: + - eFluor 450 (Cat. Nos. 88-8006-72, 88-8006-74) + - FITC (Cat. Nos. 88-8005-72, 88-8005-74) + - PerCP-eFluor 710 (Cat. Nos. 88-8008-72, 88-8008-74) + - PE (Cat. Nos. 88-8102-72, 88-8102-74) + - PE-Cyanine7 (Cat. Nos. 88-8103-72, 88-8103-74) + - APC (Cat. Nos. 88-8007-72, 88-8007-74) +• 10X Binding buffer + +Note: PerCP-eFluor 710 (Cat. Nos. 88-8008-72, 88-8008-74) do not include a viability dye. We recommend using this format in combination with a Invitrogen Fixable Viability Dye (FVD) such as FVD eFluor 660 (Cat. Nos. 65-0864-14, 65-0864-18), FVD eFluor 506 (Cat. Nos. 65-0866-14, 65-0866-18), or FVD eFluor 780 (Cat. Nos. 65-0865-14, 65-8065-18). + +Experimental procedure + +1. Prepare 1X binding buffer by mixing 1 part of 10X binding buffer with 9 parts of distilled water. +2. Harvest cells. +3. Wash cells once in 1X PBS, then once in 1X binding buffer. +4. Resuspend cells in 1X Binding Buffer at 1-5 x 10⁶ cells/mL. +5. Add 5 μL of fluorochrome-conjugated Annexin V to 100 μL of the cell suspension. +6. Incubate 10-15 minutes at room temperature. Protect from light. +7. Add 2 mL 1X binding buffer and centrifuge at 400-600 x g for 5 minutes at room temperature. Discard supernatant. +8. Resuspend cells in 200 µL of 1X binding buffer. +9. Add 5 μL of Propidium Iodide Staining Solution or 7-AAD Viability Staining Solution and incubate 5-15 minutes on ice or at room temperature. + +Note: Propidium iodide and 7-AAD must remain in the buffer during acquisition. Do not wash cells after the addition of propidium iodide or 7-AAD. + +10. Analyze by flow cytometry. + +Note: Cells should be analyzed within 4 hours after the initial incubation period due to adverse effects on the viability of cells left in the presence of propidium iodide or 7-AAD for prolonged periods. Store at 2–8°C and protect from light until ready for analysis. + +PROTOCOL B: ANNEXIN V STAINING PROTOCOL WITH FIXABLE VIABILITY DYES +================================================================================ + +Materials + +• 12 x 75 mm round-bottom tubes +• 1X PBS +• Annexin V Apoptosis Detection kit (any one of the kits listed). Each kit includes an Annexin V conjugate: + - eFluor 450 (Cat. Nos. 88-8006-72, 88-8006-74) + - FITC (Cat. Nos. 88-8005-72, 88-8005-74) + - PerCP-eFluor 710 (Cat. Nos. 88-8008-72, 88-8008-74) + - PE (Cat. Nos. 88-8102-72, 88-8102-74) + - PE-Cyanine7 (Cat. Nos. 88-8103-72, 88-8103-74) + - APC (Cat. Nos. 88-8007-72, 88-8007-74) +• 10X Binding buffer +• Flow Cytometry Staining Buffer (Cat. No. 00-4222) +• PBS (azide- and serum/protein-free PBS) +• FVD eFluor 660 (Cat. Nos. 65-0864-14, 65-0864-18), FVD eFluor 506 (Cat. Nos. 65-0866-14, 65-0866-18) or FVD eFluor 780 (Cat. Nos. 65-0865-14, 65-8065-18) + +Note: FVD eFluor 450 is not recommended for use with the Annexin V Apoptosis Detection Kits. + +Experimental procedure + +1. Prepare 1X binding buffer by mixing 1 part of 10X binding buffer with 9 parts of distilled water. +2. Wash cells twice in azide-free and serum/protein-free PBS. +3. Resuspend cells at 1-10 x 10⁶ cells/mL in azide-free and serum/protein-free PBS. +4. Add 1 µL of FVD per 1 mL of cells and vortex immediately. +5. Incubate for 30 minutes at 2-8°C. Protect from light. +6. Wash cells twice with Flow Cytometry Staining Buffer or equivalent. +7. Wash cells once with 1X Binding Buffer. +8. Resuspend cells in 1X Binding Buffer at 1-5 x 10⁶ cells/mL. +9. Add 5 μL of fluorochrome-conjugated Annexin V to 100 μL of the cell suspension. +10. Incubate 10-15 minutes at room temperature. Protect from light. +11. Add 2 mL of 1X binding buffer and centrifuge at 400-600 x g for 5 minutes at room temperature. Discard supernatant. +12. Resuspend cells in 200 μL of 1X Binding Buffer. +13. Analyze by flow cytometry. + +PROTOCOL C: ANNEXIN V STAINING PROTOCOL WITH SURFACE AND INTRACELLULAR STAINING +================================================================================ + +Materials + +• 12 x 75 mm round-bottom tubes +• 1X PBS (azide- and serum/protein-free PBS) +• Flow Cytometry Staining Buffer Set (Cat. No. 00-4222) +• Foxp3/Transcription Factor Staining Buffer Set (Cat. No. 00-5523) or Intracellular Fixation & Permeabilization Buffer Set (Cat. No. 88-8824) +• Annexin V Apoptosis Detection kit (any one of the kits listed). Each kit includes an Annexin V conjugate: + - eFluor 450 (Cat. Nos. 88-8006-72, 88-8006-74) + - FITC (Cat. Nos. 88-8005-72, 88-8005-74) + - PerCP-eFluor 710 (Cat. Nos. 88-8008-72, 88-8008-74) + - PE (Cat. Nos. 88-8102-72, 88-8102-74) + - PE-Cyanine7 (Cat. Nos. 88-8103-72, 88-8103-74) + - APC (Cat. Nos. 88-8007-72, 88-8007-74) +• 10X Binding buffer +• FVD eFluor 660 (Cat. Nos. 65-0864-14, 65-0864-18), FVD eFluor 506 (Cat. Nos. 65-0866-14, 65-0866-18) or FVD eFluor 780 (Cat. Nos. 65-0865-14, 65-8065-18) + +Note: FVD eFluor 450 is not recommended for use with the Annexin V Apoptosis Detection Kits. + +Experimental procedure + +1. Prepare 1X binding buffer by mixing 1 part of 10X binding buffer with 9 parts of distilled water. +2. Stain cell surface antigen(s). Refer to 'Staining Cell Surface Targets, Protocol A'. +3. Wash cells twice in azide-free and serum/protein-free PBS. +4. Resuspend cells at 1-10 x 10⁶ cells/mL in azide-free and serum/protein-free PBS. +5. Add 1 µL of Fixable Viability Dye per 1 mL of cells and vortex immediately. +6. Incubate for 30 minutes at 2-8°C. Protect from light. +7. Wash cells twice in Flow Cytometry Staining Buffer or equivalent. +8. Wash cells once with 1X binding buffer. +9. Resuspend cells in 1X binding buffer at 1-5 x 10⁶ cells/mL. +10. Add 5 μL of fluorochrome-conjugated Annexin V to 100 μL of the cell suspension. +11. Incubate 10-15 minutes at room temperature. Protect from light. +12. Wash cells once with 1X binding buffer. +13. Stain intracellular antigen(s). Refer to 'Staining Intracellular Antigens, Protocol A or B'. +14. Analyze by flow cytometry. diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/BestProtocols_ Cell Preparation for Flow Cytometry Protocols _ Thermo Fisher Scientific - US.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/BestProtocols_ Cell Preparation for Flow Cytometry Protocols _ Thermo Fisher Scientific - US.txt new file mode 100644 index 0000000000000000000000000000000000000000..df504ef5d79119295f9c2f6b4ce161c473de4a32 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/BestProtocols_ Cell Preparation for Flow Cytometry Protocols _ Thermo Fisher Scientific - US.txt @@ -0,0 +1,135 @@ +PROTOCOL: BestProtocols: Cell Preparation for Flow Cytometry Protocols +SOURCE: https://www.thermofisher.com/us/en/home/references/protocols/cell-and-tissue-analysis/protocols/cell-preparation-flow-cytometry.html +================================================================================ + +OVERVIEW +================================================================================ + +Note: This protocol is intended for use with the specific products mentioned within it. Substituting different products is not recommended. + +Introduction + +Single-cell suspensions are required for all flow cytometry assays. Thus, peripheral blood cells or cells that grow in suspension are well suited for analysis by flow cytometry. Adherent cell lines, solid tissue samples, and tumors require processing into single-cell suspensions before they can be analyzed. Numerous protocols are available and may involve enzymatic digestion or mechanical dissociation of the tissue. Care should be used when chelation or enzymatic digestion are used, as these may result in the destruction of the antibody epitope. In all situations, removing cell clumps, dead cells, and debris is essential to eliminate false positives and obtain results of the highest quality. + +PROTOCOL A: TISSUE CULTURE CELLS +================================================================================ + +Materials + +• Invitrogen Accutase Enzyme Cell Detachment Medium (cat. no. 00-4555) or trypsin or ethylenediaminetetraacetic acid (EDTA) +• Flow Cytometry Staining Buffer (cat. no. 00-4222) +• 15- or 50-mL conical centrifuge tubes + +Experimental procedure + +1. For cells that grow in suspension, decant the cells into a conical centrifuge tube and perform a cell count and viability analysis. Proceed to Step 4. + +2. For adherent cells lines, detach cells from the plate using one of the following options: + - Cell scraper + - Trypsin + - EDTA (10 mM in phosphate-buffered saline) + - Accutase Enzyme Cell Detachment Medium + +3. Place cells into a conical centrifuge tube and use a Invitrogen Pipetman to dissociate any clumps, and then perform cell count and viability analysis. + +4. Centrifuge cells and resuspend in an appropriate volume of Flow Cytometry Staining Buffer so that the final cell concentration is 1 x 10⁷ cells/mL (other cell concentrations may be appropriate for different experiments). + +PROTOCOL B: LYMPHOID TISSUE +================================================================================ + +Mechanical disruption of lymphoid tissue is generally sufficient to release cells to a single cell suspension. + +Materials + +• 60 x 15 mm tissue culture dish +• 3-mL syringe or frosted glass microscope slides +• Cell strainer (nylon mesh) +• Flow Cytometry Staining Buffer (cat. no. 00-4222) or other buffer of choice +• 15- or 50-mL conical centrifuge tubes + +Experimental procedure + +Note: If cells are to be cultured, perform all steps using aseptic technique and buffers that do not contain azide. + +1. Harvest tissue (spleen; thymus; lymph nodes) into a tissue culture dish containing 10 mL of Flow Cytometry Staining Buffer or buffer of choice. Tease apart into a single-cell suspension by pressing with the plunger of a 3-mL syringe. Alternatively, mash tissue between the frosted ends of two microscope slides using 10 mL of Flow Cytometry Staining Buffer. + +2. Place a cell strainer on top of a 15- or 15-mL conical tube. Pass cells from the tissue culture dish through the cell strainer to eliminate clumps and debris. + +3. Centrifuge cell suspension at 300-400 x g for 4-5 minutes at 2-8°C. Discard the supernatant. + +4. Resuspend the cell pellet in an appropriate volume of Flow Cytometry Staining Buffer or buffer of choice and perform a cell count and viability analysis. + +5. Centrifuge cells as in Step 3 and resuspend in appropriate volume of Flow Cytometry Staining Buffer or buffer of choice so that the final cell concentration is 1 x 10⁷ cells/mL (other cell concentrations may be appropriate for different experiments). + +PROTOCOL C: NON-LYMPHOID TISSUE +================================================================================ + +Materials + +• Scissors or scalpel blade +• Phosphate-buffered saline (PBS) or other suitable physiologic buffer +• Enzymes for tissue digestion +• 60 x 15 mm tissue culture dish +• 3-mL syringe +• Cell strainer (nylon mesh) +• Flow Cytometry Staining Buffer (cat. no. 00-4222) or other buffer of choice +• 15- or 50-mL conical centrifuge tubes + +Experimental procedure + +Note: If cells are to be cultured, perform all steps using aseptic technique and buffers that do not contain azide. + +1. Harvest tissue and mince into 2-4 mm pieces using scissors or scalpel blade. + +2. Add appropriate amount of enzyme(s) diluted in PBS and incubate at the optimal temperature for the appropriate amount of time according to enzyme manufacturer instructions. + +3. Disperse cells by gentle pipetting and filter through a cell strainer to eliminate clumps and debris. Collect cell suspension in a conical tube. + +4. Centrifuge cells at 300-400 x g for 4-5 minutes at 2-8°C. Discard the supernatant. + +5. Resuspend the cell pellet in PBS. + +6. Centrifuge cells as in Step 4. + +7. Repeat Steps 5 and 6. + +8. Resuspend the cell pellet in an appropriate volume of Flow Cytometry Staining Buffer or buffer of choice and perform a cell count and viability analysis. + +9. Centrifuge cells as in Step 4 and resuspend in appropriate volume of Flow Cytometry Staining Buffer or buffer of choice so that the final cell concentration is 1 x 10⁷ cells/mL (other cell concentrations may be appropriate for different experiments). + +PROTOCOL D: ISOLATION OF PBMC FROM WHOLE BLOOD +================================================================================ + +Materials + +• PBS +• Invitrogen Ficoll Paque or other density separation medium +• Flow Cytometry Staining Buffer (cat. no. 00-4222) or other buffer of choice +• 15- or 50-mL conical centrifuge tubes + +Experimental procedure + +Note: If cells are to be cultured, perform all steps using aseptic technique and buffers that do not contain azide. + +1. Dilute blood sample at least 1:1 with PBS in a conical tube. + +2. Underlay the diluted sample with a volume of Ficoll that is equal to the original sample volume. + +3. Centrifuge at 400 x g for 20 minutes at room temperature with the brake OFF. + +4. Harvest PBMC located at the interface of the PBS and Ficoll layers into a fresh tube. + +5. Fill the tube with PBS to wash the cells. + +6. Centrifuge the cells at 300-400 x g for 4-5 minutes at 2-8°C. Discard supernatant. + +7. Resuspend the cell pellet in an appropriate volume of Flow Cytometry Staining Buffer or buffer of choice and perform a cell count and viability analysis. + +8. Centrifuge cells as in Step 4 and resuspend in appropriate volume of Flow Cytometry Staining Buffer or buffer of choice so that the final cell concentration is 1 x 10⁷ cells/mL (other cell concentrations may be appropriate for different experiments). + +USEFUL RESOURCES +================================================================================ + +Worthington tissue dissociation guide (https://www.worthington-biochem.com/tools-resources/tissue-dissociation-guide) + +The Worthington Tissue Dissociation Guide provides a useful summary and guide of the various methods that can be used for tissue dissociation. diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/BrdU Labeling & Detection Protocol _ Thermo Fisher Scientific - US.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/BrdU Labeling & Detection Protocol _ Thermo Fisher Scientific - US.txt new file mode 100644 index 0000000000000000000000000000000000000000..8b6aded27a344411049517ca78ad115b8cc6c539 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/BrdU Labeling & Detection Protocol _ Thermo Fisher Scientific - US.txt @@ -0,0 +1,93 @@ +PROTOCOL: BrdU Labeling & Detection Protocol +SOURCE: https://www.thermofisher.com/us/en/home/references/protocols/cell-and-tissue-analysis/protocols/brdu-labeling-and-detection-protocol.html +================================================================================ + +OVERVIEW +================================================================================ + +BrdU (5-bromo-2'-deoxyuridine) is a thymidine analog used in DNA synthesis–based cell proliferation assays. The BrdU assay principle involves the incorporation of BrdU into newly synthesized DNA during cell division. BrdU labeling and detection are achieved by using an anti-BrdU antibody, which binds to the incorporated BrdU, allowing for the imaging and quantification of proliferating cells. This process, often referred to as BrdU staining/labeling, is a critical component of the BrdU cell proliferation assay protocol and is detailed here. + +APPLICATIONS +================================================================================ + +This protocol can be used for: +• Detecting DNA synthesis using a fluorescence microscope + +This protocol should not be used for: +• Flow cytometry (see BrdU Staining Kit Protocol for Flow Cytometry) + +MATERIALS REQUIRED +================================================================================ + +You will need the following for this protocol: + +• Proliferating adherent cells in an appropriate vessel for imaging +• BrdU (5-Bromo-2´-Deoxyuridine) +• Invitrogen Anti-BrdU monoclonal antibody (find additional anti-brdu antibody options) +• Invitrogen Alexa Fluor–labeled secondary antibody, such as Goat anti-Mouse IgG (H+L) Cross-Adsorbed Secondary Antibody, Alexa Fluor 488 +• Complete tissue culture medium, such as DMEM +• DPBS or similar wash solution +• Fixative (i.e., 3.7% formaldehyde in PBS) +• Permeabilization buffer, such as 0.1% Invitrogen Triton X-100 in PBS +• 12 N HCl +• Phosphate/citric acid buffer, pH 7.4 (182 mL of 0.2 M Na₂HPO₄ + 18 mL 0.1 M citric acid) +• Antibody stain solution (PBS/0.1% Triton/5% normal goat serum) +• Ice bucket +• Fluorescence microscope + +PROTOCOL +================================================================================ + +Prepare stock solutions + +1. Dissolve 100 mg BrdU in 32.5 mL anhydrous DMSO (10 mM stock solution). +2. Dilute 10 µL of this stock solution in 10 mL of 37°C tissue culture medium to make a 10 µM labeling solution. + +Label cells with BrdU + +1. Culture cells in appropriate vessel for microscopy. +2. Remove culture medium from cells and replace with BrdU labeling solution. +3. Incubate cells at 37°C for 2 hours. +4. Remove labeling solution and wash two times with PBS. +5. Wash with PBS (3 times, 2 minutes each). + +Fix, permeabilize, and acid-wash + +1. Remove PBS and add 1 mL of 3.7% formaldehyde in PBS to each well. +2. Incubate for 15 minutes at room temperature. +3. Wash with PBS (3 times, 2 minutes each). +4. Remove PBS and add 1 mL of Triton X-100 permeabilization buffer to each well. +5. Incubate for 20 minutes at room temperature. +6. Remove permeabilization buffer and add 1 mL of 1 N HCl. +7. Incubate 10 minutes on ice. +8. Remove this solution and add 1 mL of 2 N HCl. +9. Incubate 10 minutes at room temperature. +10. Add 1 mL phosphate/citric acid buffer, pH 7.4. +11. Incubate 10 minutes at room temperature. +12. Wash with Triton X-100 permeabilization buffer (3 times, 2 minutes each). + +Detect incorporated BrdU + +1. Remove this solution and add 1 mL of antibody staining buffer. +2. Add anti-BrdU primary antibody. +3. Incubate overnight at room temperature. +4. Wash with Triton X-100 permeabilization buffer (3 times, 2 minutes each). +5. Add fluorescently labeled secondary antibody. +6. Incubate one hour at room temperature. + +Imaging + +1. Add PBS to each well. +2. Image cells with appropriate filters. + +PROTOCOL TIPS +================================================================================ + +• Leftover BrdU stock solution can be stored frozen for up to one year. +• Use short incubation time for rapidly proliferating cells, and longer incubation for slow-growing cells. +• Acid treatment separates DNA into single strands so the primary antibody can access the incorporated BrdU. + +PRODUCT CATALOG NUMBERS +================================================================================ + +B23151, B35130, A11001, 14040141, HFH10 diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/BrdU Staining Protocol for Flow Cytometry _ Thermo Fisher Scientific - US.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/BrdU Staining Protocol for Flow Cytometry _ Thermo Fisher Scientific - US.txt new file mode 100644 index 0000000000000000000000000000000000000000..5cef5b5529084d4edae5ed3b5edd5120cc2ccdfa --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/BrdU Staining Protocol for Flow Cytometry _ Thermo Fisher Scientific - US.txt @@ -0,0 +1,85 @@ +PROTOCOL: BrdU Staining Protocol for Flow Cytometry +SOURCE: https://www.thermofisher.com/us/en/home/references/protocols/cell-and-tissue-analysis/protocols/brdu-staining-flow-cytometry.html +================================================================================ + +OVERVIEW +================================================================================ + +The BrdU Staining Kits for flow cytometry provide all necessary reagents and buffers for identifying and analyzing proliferating cells using flow cytometry. BrdU, or 5-bromo-2'-deoxyuridine, is a synthetic analog of thymidine that integrates into newly synthesized DNA during the S-phase of mitosis. This kit allows for the staining of BrdU-incorporated DNA, facilitating the examination of cell proliferation alongside other cell surface or intracellular markers of interest. + +MATERIALS PROVIDED IN KIT +================================================================================ + +• BrdU (32.5 mM, 10 mg/mL): 5 x 1 mL sterile vials; store at ≤–70°C. Avoid multiple freeze-thaws. Vial should be opened under sterile conditions. +• DNase I (1 mg/mL; 0.3 mg/vial): 10 x 0.3 mL vials; store at ≤–70°C. Each vial can be used to treat 10 samples. Avoid multiple freeze-thaws. +• Anti-BrdU Antibody (clone BU20A), fluorochrome-conjugated: 1 x 100 test vial; store at 2–8°C. +• BrdU Staining Buffer Concentrate (4X): 1 x 30 mL bottle; store at 2–8°C. This buffer contains formaldehyde. Please handle appropriately. +• Fixation/Permeabilization Diluent: 1 x 100 mL bottle; store at 2–8°C. + +OTHER MATERIALS NEEDED +================================================================================ + +• Sterile 1X PBS +• Flow Cytometry Staining Buffer +• 12 x 75 mm round bottom test tubes +• Optional: + - Primary antibodies (directly conjugated) + - Fixable Viability Dye (FVD): eFluor 450, eFluor 660, eFluor 780, eFluor 506, eFluor 520, or eFluor 455UV + +NOTE: The antibodies used for surface staining can be added after BrdU and Fixable Viability Dye labeling (but before fixation). Alternatively, if the antibody(s) is known to recognize a formaldehyde-fixed epitope, it can be added concurrently with the BrdU antibody. + +BrdU staining buffer working solution preparation + +Prepare fresh 1X BrdU Staining Buffer working solution by diluting BrdU Staining Buffer Concentrate (1 part) with Fixation/Permeabilization Diluent (3 parts). Mix by gentle inversion, do not vortex. You will need 1 mL of the 1X BrdU Staining Buffer working solution for each sample. Use caution and handle appropriately as the buffer contains formaldehyde. + +PROTOCOL +================================================================================ + +Step 1: In vitro labeling of 10⁵ to 10⁸ dividing cells with 10 µM BrdU for 45 minutes at 37°C. + +1. Under sterile conditions thaw BrdU on ice and dilute to a working concentration of 1 mM with sterile 1X PBS. +2. Add 10 µM BrdU to each sample. (For example, add 10 µL of 1 mM BrdU directly to every milliliter of tissue culture medium.) +3. Incubate your cells long enough to allow incorporation of BrdU. The timing will be dependent on your culture conditions (e.g., stimulants used) and the proliferation kinetics of your cells. Therefore, the incubation time will need to be determined empirically. After the incubation, harvest the cells. +4. Wash cells by adding 2 mL of Flow Cytometry Staining Buffer (or azide-free PBS if proceeding to Step 2) and then centrifuge at 300–400 x g for 5 minutes at room temperature. Discard the supernatant. + +Step 2: [Optional] Stain with fixable viability dye (FVD) to label dead cells before fixation. + +Note: Allow the vial of Fixable Viability Dye to equilibrate to room temperature before opening. The dye must be used with azide-free PBS. For consistent staining of cells in tubes, do not stain in less than 0.5 mL. Please refer to our website Best Protocols (Viability Staining Protocol, Protocol C: Staining Dead Cells with Fixable Viability eFluor Dyes) for additional information. (Proceed to Step 3 if a FVD will not be used.) + +1. Wash cells one additional time with 2 mL of azide-free PBS, as described in step 4 above. +2. Resuspend cells at 1–10 x 10⁶ cells/mL in azide-free PBS. +3. Add 1 μL of Fixable Viability Dye per 1 mL of cells and vortex immediately. +4. Incubate for 30 minutes at 2–8°C in the dark. +5. Wash cells 1–2 times with Flow Cytometry Staining Buffer, as described in step 4 above. +6. Resuspend cells at 1–10 x 10⁶ cells/mL in Flow Cytometry Staining Buffer. + +Step 3: [Optional] Stain cell surface antigen(s). + +Note: For additional information, please refer to Staining Cell Surface Antigens for Flow Cytometry. Proceed to Step 4 if cell surface antigens will not be examined or if the antibody(s) is known to recognize a formaldehyde-fixed epitope. + +1. Aliquot 50 μL of cell suspension to each tube or well. The cell number should be determined empirically but can range from 10⁵ to 10⁸ cells/test per tube. +2. Add the recommended amount (refer to the Technical Data Sheet for each product) of each fluorochrome-conjugated primary antibody(s) in an appropriate volume of Flow Cytometry Staining Buffer such that the final staining volume is 100 μL. (For example, add 50 μL of an antibody mix to 50 μL of cells.) Mix gently. +3. Incubate for at least 30 minutes at 2–8°C in the dark. +4. Wash the cells twice with Flow Cytometry Staining Buffer, as described in step 4 under Step 1. + +Step 4: Fix cells and intracellularly stain with Anti-BrdU. + +1. Thaw DNase I solution on ice. Once thawed, prepare a working solution of DNase I by adding 300 µL of the DNase I solution to 700 µL of Flow Cytometry Staining Buffer and mix gently. Store on ice until ready for use in step 6 below. +2. If cells were not stained in Steps 2 or 3, aliquot 100 μL of cell suspension to each tube. The cell number should be determined empirically but can range from 10⁵ to 10⁸ cells/tube. +3. Gently resuspend the cells by pulse-vortexing once. This resuspension step is critical before the addition of the freshly prepared 1X BrdU Staining Buffer working solution. +4. Add 1 mL of freshly prepared 1X BrdU Staining Buffer working solution and mix gently. Incubate for 15 minutes at room temperature in the dark. Incubations may go longer (up to 14 hours) but should be determined empirically for each cell type. +5. Wash cells twice with Flow Cytometry Staining Buffer, as described in step 4 under Step 1. +6. Add 100 µL of the DNase I working solution that was prepared in step 1 to each sample. Incubate for 1 hour at 37°C in the dark. +7. Wash cells twice with Flow Cytometry Staining Buffer, as described in step 4 under Step 1. +8. Add 5 µL of Anti-BrdU fluorochrome-conjugated antibody per sample. Mix and incubate for 20–30 minutes at room temperature in the dark. + +NOTE: Antibodies against intracellular antigens or surface antigens not stained in Step 3 may be added here. The antibodies used for surface staining at this step must recognize a fixed epitope. If an antibody only recognizes a native epitope or if this information is unknown, we recommend surface staining at Step 3. + +9. Wash cells twice with Flow Cytometry Staining Buffer, as described in step 4 under Step 1. + +Step 5: Acquire data on a flow cytometer. + +PRODUCT CATALOG NUMBERS +================================================================================ + +8811-6600-42, 8817-6600-42, 8812-6600-42, 8848-6600-42, 8846-6600-42, 00-5525-00, 00-4222-26 diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/BrdU and EdU Double Staining Protocol _ Thermo Fisher Scientific - US.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/BrdU and EdU Double Staining Protocol _ Thermo Fisher Scientific - US.txt new file mode 100644 index 0000000000000000000000000000000000000000..4f21a41666bf4b2009fc6a131087f133d702c0e5 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/BrdU and EdU Double Staining Protocol _ Thermo Fisher Scientific - US.txt @@ -0,0 +1,90 @@ +PROTOCOL: BrdU and EdU Double Staining Protocol +SOURCE: Thermo Fisher Scientific - US +URL: https://www.thermofisher.com/us/en/home/references/protocols/cell-and-tissue-analysis/flow-cytometry-protocol/cell-proliferation/dual-pulse-labeling-of-cell-proliferation-using-edu-and-brdu-incorporation.html +================================================================================ + +Introduction +The measurement of cell proliferation is fundamental to the assessment of cell health, genotoxicity, and drug efficacy. Proliferation is traditionally assessed by incubating cells with a single "pulse" of a nucleoside analog that is incorporated into DNA and detected using radioactivity, antibodies, or click chemistry. Some applications, such as drug efficacy testing, benefit from the incorporation of two different analogs at different time points (dual pulse labeling), which can further define cell cycle kinetics. With the availability of new highly specific anti-BrdU antibodies, the BrdU labeling technique can be combined with click chemistry detection for a simplified method of dual pulse labeling. +Traditionally, the detection of cell proliferation has employed the incorporation of the thymidine analog BrdU (5-bromo-2´-deoxyuridine) during DNA synthesis, followed by detection with an anti-BrdU antibody [1–4]. This method is rapidly being replaced by the click chemistry–based Click-iT EdU assay [5,6], because unlike BrdU assays, Click-iT EdU assays are not antibody-based and therefore do not require DNA denaturation for detection of the incorporated nucleoside. Click-iT assays use a modified nucleoside, EdU (5-ethynyl-2´-deoxyuridine), that is incorporated during DNA synthesis and detected using a click reaction—a copper(I)-catalyzed reaction between an azide and an alkyne. + +Materials +- Jurkat cells in complete RPMI media/10%FBS +- BrdU (5-bromodeoxyuridin) (B23151) (10mM in DMSO) +- EdU (5-Ethynyl-2'-deoxyuridine) (10mM in DMSO) +- PBS pH7.2 (GIBCO(R)) +- 70% Ethanol, ice cold +- 4M HCl +- Phosphate/citric acid buffer, pH 7.4 (182 ml of 0.2M Na2HPO4+18ml 0.1M citric acid) +- Antibody Diluting buffer (PBS + 0.1% Triton-X100 + 1% BSA)—prepare fresh +- Purified anti-BrdU antibody(clone MoBU-1) (B35141) 0.1 mg/ml; use 2.5ul +- anti-BrdU- (clone Br3) pure MD5300 lot 0903 0.4mg/ml titer use: 2.5uL +- Goat anti-mouse IgG Alexa Fluor® 488 secondary antibody 2mg/ml, dilute 1:20 and use 2.5ul/test (0.25ug/test) (A11001) +- Tris Buffered Saline +- CuSo4 100mM +- 100mM ascorbate (Freshly prepared) +- AF647-azide 20uM DMSO A10277 +- FxCycle™ Violet 1mg/ml DI F10347 use 0.5µl/0.5ml + +Procedure +1. Use Jurkat cells in complete RPMI/10%FBS media, separate into 5 flasks: + - Flask 1: control + - Flask 2: 10uM BrdU 1 hour + - Flask 3: 20uM EdU 1 hour + - Flask 4: 10µM BrdU + 20µM EdU together 1 hour + - Flask 5: 20µM EdU one hour then 10µM BrdU one hour + Incubate 37°C/5% CO2. + +2. After incubation, centrifuge cells, pellet and remove supernatant. + +3. FIX cells: Add 10ml ice cold 70% Ethanol to a 15ml tube containing the cell pellet, adding dropwise at first while vortexing, mix well. + +4. Store at -20°C until use, 4 hours to several months. + +5. Centrifuge cells, pellet & discard supernatant; vortex pellet. + +6. Resuspend pellet in 2.0ml 4M HCl for 20 min at room temperature. + +7. Add 10ml phosphate/citric acid buffer, centrifuge and decant supernatant. Filter out large clumps. + +8. Resuspend in PBS/0.1%Triton/1%BSA (antibody stain solution) wash & pellet. + +9. Repeat wash. + +10. Resuspend in PBS/0.1%Triton/1%BSA (antibody stain solution), adjust concentration to 1x10⁷/ml. + +11. Add 100µl cell suspension to designated tubes. + +12. Prepare click reaction and add 0.5ml to designated tubes. + +13. Incubate 30 minutes at room temperature protected from light. + +14. Wash x1 PBS/0.1%Triton/1%BSA. + +15. Add anti-BrdU purified antibody to designated tubes. + +16. Incubate for 30 minutes at room temperature protected from light. + +17. Wash with 3ml PBS/0.1%Triton/1%BSA (antibody stain solution) spin & pellet. + +18. Add Goat anti-mouse IgG Alexa Fluor 488 secondary antibody, incubate for 30 minutes at room temperature, followed by wash as in step 15. + +19. Resuspend pellet in 0.5ml PBS/0.1%Triton/1%BSA (antibody stain solution). + +20. Add 0.5µL FxCycle Violet Stain. + +21. Incubate for 15-30 minute at room temperature protected from light. + +22. Run on LSRII. + +23. Analyze Alexa Fluor 488 using blue laser excitation and 525/50 emission filter, Alexa Fluor 647 using red laser excitation and 660/20 emission filter, and FxCycleViolet using violet laser excitation and 450/50 emission filter. + +24. Gate on main population cells and collect 10,000 gated events for single color data. For triple color samples, make a singlet gate on WvA and collect 20,000 singlet events. + +References +- Gratzner HG (1982) Science 218:474–475. +- Dolbeare F, Selden JR (1994) Methods Cell Biol 41:297–316. +- Li X, Darzynkiewicz Z (1995) Cell Prolif 28:571–579. +- Conboy MJ, Karasov AO, Rando TA (2007) PLoS Biology 5:1120–1126. +- Salic A, Mitchison TJ (2008) Proc Natl Acad Sci U S A 105:2415–2420. +- Buck SB, Bradford J, Gee KR et al. (2008) Biotechniques 44:927–929. +- Current Protocols in Cytometry Vol. 1, JP Robinson, Ed., John Wiley & Sons Inc. (2007) diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/Caspase Activity Assay Protocol _ Thermo Fisher Scientific - US.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/Caspase Activity Assay Protocol _ Thermo Fisher Scientific - US.txt new file mode 100644 index 0000000000000000000000000000000000000000..a47e1591e3434446ac8d25b340e90c74f839f25d --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/Caspase Activity Assay Protocol _ Thermo Fisher Scientific - US.txt @@ -0,0 +1,94 @@ +PROTOCOL: Caspase Activity Assay Protocol +SOURCE: Thermo Fisher Scientific - US +URL: https://www.thermofisher.com/us/en/home/references/protocols/cell-and-tissue-analysis/apoptosis-protocol.html +================================================================================ + +OVERVIEW +================================================================================ + +Caspases are a family of cysteine proteases that play essential roles in apoptosis (programmed cell death). Measuring caspase activity is a common method for detecting and quantifying apoptosis. This protocol describes methods for detecting caspase activity using fluorescent substrates in both live and fixed cells. + +APPLICATIONS +================================================================================ + +This protocol can be used for: +• Detecting apoptosis in cell cultures +• Quantifying caspase-3/7, caspase-8, or caspase-9 activity +• Screening for apoptosis-inducing compounds +• Time-course studies of apoptosis + +MATERIALS REQUIRED +================================================================================ + +• Cells in culture +• CellEvent Caspase-3/7 Green Detection Reagent or similar caspase substrate +• Cell culture medium +• Phosphate-buffered saline (PBS) +• Fluorescence microscope or microplate reader +• Optional: NucBlue Live ReadyProbes Reagent for nuclear counterstaining + +PROTOCOL +================================================================================ + +For live cell imaging (CellEvent Caspase-3/7 Green Detection Reagent) + +1. Prepare cells in appropriate culture vessel (coverslips, multiwell plates, etc.). + +2. Treat cells with apoptosis-inducing agent or control treatment. + +3. Prepare CellEvent Caspase-3/7 Green Detection Reagent: + - Add 100 µL of PBS to the dry powder to make a 100X stock solution. + - Dilute 1:100 in cell culture medium to make working solution (final concentration typically 2-5 µM). + +4. Remove cell culture medium from cells. + +5. Add CellEvent Caspase-3/7 Green Detection Reagent working solution to cells. + +6. Incubate for 30-60 minutes at 37°C, protected from light. + +7. Optional: Add NucBlue Live ReadyProbes Reagent (1 drop per mL) for nuclear counterstaining. + +8. Wash cells once with PBS or fresh culture medium. + +9. Image cells immediately using a fluorescence microscope with appropriate filter set (FITC/GFP filter for green fluorescence). + +For microplate reader detection + +1. Seed cells in 96-well microplate. + +2. Treat cells with apoptosis-inducing agent or control. + +3. Prepare CellEvent Caspase-3/7 Green Detection Reagent as described above. + +4. Add reagent to cells and incubate as described above. + +5. Read fluorescence using a microplate reader: + - Excitation: ~502 nm + - Emission: ~530 nm + +6. Calculate caspase activity relative to controls. + +For flow cytometry + +1. Prepare cell suspension. + +2. Treat cells with apoptosis-inducing agent. + +3. Prepare CellEvent Caspase-3/7 Green Detection Reagent working solution. + +4. Add reagent to cells and incubate for 30-60 minutes at 37°C. + +5. Wash cells with PBS. + +6. Analyze by flow cytometry using FITC/GFP channel. + +PROTOCOL TIPS +================================================================================ + +• Include positive control (cells treated with known apoptosis inducer) and negative control (untreated cells) +• Optimize incubation time based on your cell type and treatment +• Protect from light during incubation to prevent photobleaching +• For time-course studies, image at multiple time points +• Caspase activity typically peaks 2-6 hours after apoptosis induction +• Some caspase substrates are cell-permeant and work in live cells; others require cell fixation +• For fixed cells, follow manufacturer's instructions for fixation and permeabilization steps diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/CellTrace CFSE Cell Proliferation Kit Protocol _ Thermo Fisher Scientific - US.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/CellTrace CFSE Cell Proliferation Kit Protocol _ Thermo Fisher Scientific - US.txt new file mode 100644 index 0000000000000000000000000000000000000000..f7905e03ed32e0d988116f937ac3a5e600c1f9c7 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/CellTrace CFSE Cell Proliferation Kit Protocol _ Thermo Fisher Scientific - US.txt @@ -0,0 +1,94 @@ +PROTOCOL: CellTrace CFSE Cell Proliferation Kit Protocol +SOURCE: https://www.thermofisher.com/us/en/home/references/protocols/cell-and-tissue-analysis/protocols/celltrace-cfse-cell-proliferation-kit-protocol.html +================================================================================ + +OVERVIEW +================================================================================ + +The CellTrace CFSE Cell Proliferation Kit provides a robust method for evaluating cell proliferation through CFSE staining. CFSE, or carboxyfluorescein succinimidyl ester, is a fluorescent dye used in CFSE proliferation assays to monitor distinct generations of proliferating cells. The CFSE staining protocol involves covalently labeling live cells with this bright and stable dye, which dilutes evenly among daughter cells during cell division. Flow cytometric visualization then allows researchers to observe each generation as a separate peak on a flow cytometry histogram, offering precise insights into cell proliferation dynamics. The CellTrace CFSE protocol is essential for studies requiring accurate measurement of cell proliferation and is widely used in various research applications to evaluate cell division and growth. + +APPLICATIONS +================================================================================ + +This protocol can be used for: +• Detecting cell proliferation using flow cytometry + +This protocol should not be used for: +• Fluorescence microscopy or microplate readers + +MATERIALS REQUIRED +================================================================================ + +You will need the following for this protocol: + +• 20 mL of heparinized peripheral whole blood +• CellTrace CFSE Cell Proliferation Kit +• OpTmizer T Cell Expansion SFM +• Penicillin-Streptomycin-Glutamine (100X) +• PBS +• Ficoll-Paque Plus +• Cell counter such as the Countess 3 FL +• Dynabeads Human T-Activator CD3/CD28 + +PROTOCOL +================================================================================ + +Culture medium preparation + +To 1 L Gibco OpTmizer T Cell Expansion SFM, add the following: +• 26 mL of T Cell Expansion Supplement +• 10 mL of Penicillin-Streptomycin-Glutamine + +Complete medium is stable for 4 weeks when stored at 2–8°C in the dark. + +Mononuclear cell isolation from whole blood + +1. Dilute 10 mL whole blood in 10 mL PBS and mix well. +2. Add 15 mL Invitrogen Ficoll-Paque Plus to a 50 mL centrifuge tube and gently layer 20 mL diluted whole blood on top. +3. Centrifuge for 30 minutes at 400 x g. +4. Carefully remove lymphocyte layer and transfer to a new tube. +5. Resuspend cells in 25 mL DPBS buffer in a 50 mL conical tube. +6. Centrifuge for 5 minutes at 300 x g, pour off supernatant, and resuspend in 25 mL DPBS. +7. Repeat wash step and resuspend in 10 mL DPBS. +8. Count cells on the Invitrogen Countess Automated Counter or by another method; adjust concentration to 10⁶ cells/mL. + +Cell staining + +1. Add 18 µL DMSO to a vial of CellTrace CFSE staining solution. +2. Dilute this stock solution into 20 mL of PBS (warmed to 37°C) for a 5 µM staining solution. +3. Add 10 mL of cells to a 50 mL centrifuge tube. +4. Centrifuge cells for 5 minutes at 300 x g and carefully pour off supernatant. +5. Resuspend cells in 10 mL of CellTrace CFSE staining solution. +6. Incubate cells for 20 minutes in a 37°C water bath. +7. Add 40 mL OpTmizer T Cell Expansion SFM to the cells to absorb any unbound dye. +8. Incubate cells for 5 minutes. +9. Centrifuge cells for 5 minutes at 300 x g and resuspend the cell pellet in pre-warmed OpTmizer T Cell Expansion SFM. + +Stimulation and analysis + +1. Distribute aliquots of stained cells into culture plates or flasks. +2. Stimulate with 50 µL Invitrogen Dynabeads Human T-Activator CD3/CD28 per 1 mL of cells, or other stimulus. +3. Incubate for desired length of time under growth conditions. +4. Harvest cells and stain for other markers if appropriate. +5. Analyze using a flow cytometer with 488 nm excitation and emission filters appropriate for fluorescein. + +SPECTRAL INFORMATION AND STORAGE +================================================================================ + +CellTrace CFSE: +• Excitation/Emission (in nm): 492/517 +• Standard filter set: Invitrogen Alexa Fluor 488 +• Storage conditions: ≤–20°C + +PROTOCOL TIPS +================================================================================ + +• Reserve 1 mL of cells for unstained control and 1 mL of cells for a stained, but unstimulated control +• Dynabeads stimulation typically results in T cell division every 18–20 hr +• Analyze as many cells as possible from each sample +• Use a viability dye and gate on live cells + +PRODUCT CATALOG NUMBERS +================================================================================ + +C34554, A1048501, 10378016, 10010023, AMQAF2000, 11161D diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/CellTrace Far Red Cell Proliferation Kit Protocol _ Thermo Fisher Scientific - US.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/CellTrace Far Red Cell Proliferation Kit Protocol _ Thermo Fisher Scientific - US.txt new file mode 100644 index 0000000000000000000000000000000000000000..a4facf302f9da8507334462833c5e14fea289036 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/CellTrace Far Red Cell Proliferation Kit Protocol _ Thermo Fisher Scientific - US.txt @@ -0,0 +1,101 @@ +PROTOCOL: CellTrace Far Red Cell Proliferation Kit Protocol +SOURCE: https://www.thermofisher.com/us/en/home/references/protocols/cell-and-tissue-analysis/protocols/celltrace-far-red-cell-proliferation-kit-protocol.html +================================================================================ + +OVERVIEW +================================================================================ + +Flow cytometric visualization of cell generations + +The CellTrace Far Red kit is used to monitor distinct generations of proliferating cells by dye dilution. Live cells are covalently labeled with a very bright, stable dye. Every generation of cells appears as a different peak on a flow cytometry histogram. + +APPLICATIONS +================================================================================ + +This protocol can be used for: +• Detecting cell proliferation using flow cytometry + +This protocol should not be used for: +• Fluorescence microscopy or microplate readers + +MATERIALS REQUIRED +================================================================================ + +You will need the following for this protocol: + +• 20 mL of heparinized peripheral whole blood +• CellTrace Far Red Cell Proliferation Kit (Cat. No. C34564) +• OpTmizer T Cell Expansion SFM (Cat. No. A10485-01) +• Penicillin-Streptomycin-Glutamine (100X) (Cat. No. 10378-016) +• PBS (Cat. No. 10010-023) +• GE Ficoll-Paque™ Plus (Fisher Cat. No. 45-001-750) +• Cell counter such as the Countess II FL (Cat. No. AMQAF1000) +• Dynabeads Human T-Activator CD3/CD28 (Cat. No. 11161D) + +PROTOCOL +================================================================================ + +Culture medium preparation + +To 1 L OpTmizer T Cell Expansion SFM, add the following: +• 26 mL of T Cell Expansion Supplement (supplied in Cat. No. A10485-01) +• 10 mL of Penicillin-Streptomycin-Glutamine + +Complete medium is stable for 4 weeks when stored at 2–8°C in the dark. + +Mononuclear cell isolation from whole blood + +1. Dilute 20 mL whole blood in 20 mL PBS and mix well. +2. Add 15 mL Ficoll-Paque™ Plus to a 50 mL centrifuge tube and gently layer 20 mL diluted whole blood on top. +3. Centrifuge for 30 minutes at 400 x g. +4. Carefully remove lymphocyte layer and transfer to a new tube. +5. Resuspend cells in 25 mL DPBS buffer in a 50 mL conical tube. +6. Centrifuge for 5 minutes at 300 x g, pour off supernatant, and resuspend in 25 mL DPBS. +7. Repeat wash step and resuspend in 10 mL DPBS. +8. Count cells on the Countess Automated Counter or by another method; adjust concentration to 10⁶ cells/mL. + +Cell staining + +1. Add 20 µL DMSO to a vial of CellTrace Far Red staining solution. +2. Dilute this stock solution into 20 mL of PBS (warmed to 37°C) for a 1 µM staining solution. +3. Add 10 mL of cells to a 50 mL centrifuge tube. +4. Centrifuge cells for 5 minutes at 300 x g and carefully pour off supernatant. +5. Resuspend cells in 10 mL of CellTrace Far Red staining solution. +6. Incubate cells for 20 minutes in a 37°C water bath. +7. Add 40 mL OpTmizer T Cell Expansion SFM to the cells to absorb any unbound dye. +8. Incubate cells for 5 minutes. +9. Centrifuge cells for 5 minutes at 300 x g and resuspend the cell pellet in pre-warmed OpTmizer T Cell Expansion SFM. + +Stimulation and analysis + +1. Distribute aliquots of stained cells into culture plates or flasks. +2. Stimulate with 50 µL Dynabeads Human T-Activator CD3/CD28 per 1 mL of cells, or other stimulus. +3. Incubate for desired length of time under growth conditions. +4. Harvest cells and stain for other markers if appropriate. +5. Analyze using a flow cytometer with 633/635 nm excitation and a 660/20 bandpass emission filter. + +SPECTRAL INFORMATION AND STORAGE +================================================================================ + +CellTrace Far Red: +• Excitation/Emission (in nm): 630/661 +• Standard filter set: Alexa Fluor 647 +• Storage conditions: ≤–20°C + +PROTOCOL TIPS +================================================================================ + +• Reserve 1 mL of cells for unstained control and 1 mL of cells for a stained, but unstimulated control +• Dynabeads stimulation typically results in T cell division every 18–20 hr +• Analyze as many cells as possible from each sample +• Use a viability dye and gate on live cells + +EXAMPLE APPLICATION +================================================================================ + +Human T lymphocytes stained with CellTrace Far Red Cell Proliferation reagent and stimulated in culture for 5 days. The discrete peaks represent successive generations of live cells. The unstimulated parent generation is indicated in purple. Analysis was completed using an Attune Acoustic Focusing Cytometer with 638 nm excitation and a 660/20 nm bandpass emission filter. + +PRODUCT CATALOG NUMBER +================================================================================ + +C34564 diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/CellTrace Violet Cell Proliferation Kit Protocol _ Thermo Fisher Scientific - US.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/CellTrace Violet Cell Proliferation Kit Protocol _ Thermo Fisher Scientific - US.txt new file mode 100644 index 0000000000000000000000000000000000000000..83af8abd48f713acf15dfabb66527a005b42228d --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/CellTrace Violet Cell Proliferation Kit Protocol _ Thermo Fisher Scientific - US.txt @@ -0,0 +1,94 @@ +PROTOCOL: CellTrace Violet Cell Proliferation Kit Protocol +SOURCE: https://www.thermofisher.com/us/en/home/references/protocols/cell-and-tissue-analysis/protocols/celltrace-violet-cell-proliferation-kit-protocol.html +================================================================================ + +OVERVIEW +================================================================================ + +The CellTrace Violet (CTV) Cell Proliferation Kit is a powerful tool used for monitoring cell proliferation through dye dilution. In this CellTrace Violet protocol, live cells are covalently labeled with a very bright and stable dye which is retained within the cells and evenly distributed to daughter cells during cell division allowing researchers to track distinct generations of proliferating cells. This process, known as CTV staining, results in each cell generation appearing as a different peak on a flow cytometry histogram, facilitating precise evaluation of cell proliferation. These methods provide valuable insights into cellular behaviors and responses, making the CellTrace Violet kit a key tool for flow cytometric visualization of cell generations. + +APPLICATIONS +================================================================================ + +This protocol can be used for: +• Detecting cell proliferation using flow cytometry + +This protocol should not be used for: +• Fluorescence microscopy or microplate readers + +MATERIALS REQUIRED +================================================================================ + +You will need the following for this protocol: + +• 10 mL of heparinized peripheral whole blood +• CellTrace Violet Cell Proliferation Kit +• OpTmizer T Cell Expansion SFM +• Penicillin-Streptomycin-Glutamine (100X) +• PBS +• Ficoll-Paque Plus +• Cell counter such as the Countess 3 FL +• Dynabeads Human T-Activator CD3/CD28 + +PROTOCOL +================================================================================ + +Culture medium preparation + +To 1 L OpTmizer T Cell Expansion SFM, add the following: +• 26 mL of T Cell Expansion Supplement +• 10 mL of Penicillin-Streptomycin-Glutamine + +Complete medium is stable for 4 weeks when stored at 2–8°C in the dark. + +Mononuclear cell isolation from whole blood + +1. Dilute 10 mL whole blood in 10 mL PBS and mix well. +2. Add 15 mL Ficoll-Paque Plus to a 50 mL centrifuge tube and gently layer 20 mL diluted whole blood on top. +3. Centrifuge for 30 minutes at 400 x g. +4. Carefully remove lymphocyte layer and transfer to a new tube. +5. Resuspend cells in 25 mL DPBS buffer in a 50 mL conical tube. +6. Centrifuge for 5 minutes at 300 x g, pour off supernatant, and resuspend in 25 mL DPBS. +7. Repeat wash step and resuspend in 10 mL DPBS. +8. Count cells on the Countess Automated Counter or by another method; adjust concentration to 10⁶ cells/mL. + +Cell staining + +1. Add 20 µL DMSO to a vial of CellTrace Violet staining solution. +2. Dilute this stock solution into 20 mL of PBS (warmed to 37°C) for a 5 µM staining solution. +3. Add 10 mL of cells to a 50 mL centrifuge tube. +4. Centrifuge cells for 5 minutes at 300 x g and carefully pour off supernatant. +5. Resuspend cells in 10 mL of CellTrace Violet staining solution. +6. Incubate cells for 20 minutes in a 37°C water bath. +7. Add 40 mL OpTmizer T Cell Expansion SFM to the cells to absorb any unbound dye. +8. Incubate cells for 5 minutes. +9. Centrifuge cells for 5 minutes at 300 x g and resuspend the cell pellet in pre-warmed OpTmizer T Cell Expansion SFM. + +Stimulation and analysis + +1. Distribute aliquots of stained cells into culture plates or flasks. +2. Stimulate with 50 µL Dynabeads Human T-Activator CD3/CD28 per 1 mL of cells, or other stimulus. +3. Incubate for desired length of time under growth conditions. +4. Harvest cells and stain for other markers if appropriate. +5. Analyze using a flow cytometer with 405 nm excitation and a 450/40 bandpass emission filter. + +SPECTRAL INFORMATION AND STORAGE +================================================================================ + +CellTrace Violet: +• Excitation/Emission (in nm): 405/450 +• Standard filter set: Pacific Blue +• Storage conditions: ≤–20°C + +PROTOCOL TIPS +================================================================================ + +• Reserve 1 mL of cells for unstained control and 1 mL of cells for a stained, but unstimulated control +• Dynabeads stimulation typically results in T-cell division every 18–20 hr +• Analyze as many cells as possible from each sample +• Use a viability dye and gate on live cells + +PRODUCT CATALOG NUMBERS +================================================================================ + +C34557, A1048501, 10378016, 10010023, AMQAF2000, 11161D diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/DAPI Protocol for Fluorescence Imaging _ Thermo Fisher Scientific - US.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/DAPI Protocol for Fluorescence Imaging _ Thermo Fisher Scientific - US.txt new file mode 100644 index 0000000000000000000000000000000000000000..6556cbd2d09b572b32f83e625a53d8cdcefcb96c --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/DAPI Protocol for Fluorescence Imaging _ Thermo Fisher Scientific - US.txt @@ -0,0 +1,76 @@ +PROTOCOL: DAPI Protocol for Fluorescence Imaging +SOURCE: Thermo Fisher Scientific - US +URL: https://www.thermofisher.com/us/en/home/references/protocols/cell-and-tissue-analysis/protocols/dapi-protocol-fluorescence-imaging.html +================================================================================ + +OVERVIEW +================================================================================ + +DAPI (4',6-diamidino-2-phenylindole) is a blue-fluorescent DNA stain that binds strongly to A-T rich regions in DNA. It is widely used for nuclear staining in fluorescence microscopy applications. DAPI is cell-impermeant and is typically used to stain fixed cells, though it can also be used to stain live cells at higher concentrations. + +APPLICATIONS +================================================================================ + +This protocol can be used for: +• Nuclear staining in fixed cells for fluorescence microscopy +• Cell counting and nuclear morphology analysis +• Counterstaining in multicolor immunofluorescence experiments + +This protocol should not be used for: +• Flow cytometry (use DAPI Protocol for HCA Instruments instead) +• Live cell imaging (unless using higher concentrations and short exposure times) + +MATERIALS REQUIRED +================================================================================ + +• Fixed cells (on coverslips, slides, or in multiwell plates) +• DAPI stain (e.g., DAPI, dihydrochloride, Cat. No. D1306, or DAPI solution) +• Phosphate-buffered saline (PBS) +• Mounting medium (e.g., ProLong Gold Antifade Mountant with DAPI, or add DAPI to mounting medium) +• Fluorescence microscope with DAPI/UV filter set (excitation ~358 nm, emission ~461 nm) + +PROTOCOL +================================================================================ + +For fixed cells + +1. Fix and permeabilize cells according to your standard protocol. + +2. Wash cells 2-3 times with PBS. + +3. Prepare DAPI staining solution: + - For DAPI powder: Dissolve in water or PBS to make a 1-5 mg/mL stock solution. Store at 2-8°C, protected from light. + - Working solution: Dilute stock to 1-5 µg/mL in PBS or mounting medium. + +4. Option A: Staining before mounting + - Remove PBS from cells. + - Add DAPI working solution (1-5 µg/mL in PBS) to cover cells. + - Incubate for 5-10 minutes at room temperature, protected from light. + - Wash 2-3 times with PBS. + - Proceed to mounting. + +5. Option B: Staining in mounting medium (recommended) + - Remove PBS from cells. + - Add mounting medium containing DAPI (e.g., ProLong Gold Antifade Mountant with DAPI, or add DAPI to mounting medium at 1-5 µg/mL final concentration). + - Cover with coverslip and proceed to imaging. + +6. Image cells using a fluorescence microscope with DAPI/UV filter set. + +SPECTRAL INFORMATION +================================================================================ + +DAPI: +• Excitation maximum: ~358 nm (UV) +• Emission maximum: ~461 nm (blue) +• Standard filter set: DAPI/UV +• Compatible with: FITC, TRITC, Texas Red, Alexa Fluor dyes + +PROTOCOL TIPS +================================================================================ + +• DAPI is light-sensitive; protect from light during staining and storage +• Optimal concentration may vary; start with 1 µg/mL and adjust as needed +• Higher concentrations (5-10 µg/mL) may be needed for some tissue sections +• DAPI can be used in combination with other fluorescent stains (use appropriate filter sets) +• For live cells, use higher concentrations (5-10 µg/mL) and minimize exposure time +• DAPI-stained samples can be stored at 2-8°C, protected from light, for several weeks diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/ELISA Sample Preparation - Adherent and Suspension Cells _ Thermo Fisher Scientific - US.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/ELISA Sample Preparation - Adherent and Suspension Cells _ Thermo Fisher Scientific - US.txt new file mode 100644 index 0000000000000000000000000000000000000000..79b13e195488e334a9748785cc02d19b775da146 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/ELISA Sample Preparation - Adherent and Suspension Cells _ Thermo Fisher Scientific - US.txt @@ -0,0 +1,106 @@ +PROTOCOL: ELISA Sample Preparation - Adherent and Suspension Cells +SOURCE: Thermo Fisher Scientific - US +URL: https://www.thermofisher.com/us/en/home/references/protocols/cell-and-tissue-analysis/elisa-protocol/elisa-sample-preparation-protocols.html +================================================================================ + +OVERVIEW +================================================================================ + +Proper sample preparation is critical for successful ELISA experiments. This protocol describes methods for preparing samples from adherent and suspension cell cultures in a 96-well format. The prepared samples can be used directly in ELISA assays or stored for later analysis. + +MATERIALS REQUIRED +================================================================================ + +• Cells in culture (adherent or suspension) +• Cell culture medium +• Phosphate-buffered saline (PBS), ice-cold +• Cell lysis buffer (e.g., RIPA buffer, NP-40 lysis buffer, or commercial cell lysis buffer) +• Protease inhibitors (optional but recommended) +• Phosphatase inhibitors (if analyzing phosphoproteins) +• 96-well cell culture plate +• Cell scraper (for adherent cells) +• Centrifuge and microcentrifuge tubes +• BCA or other protein quantification assay kit + +PROTOCOL +================================================================================ + +For adherent cells + +1. Seed cells in a 96-well plate and culture until they reach the desired confluency or treatment endpoint. + +2. Remove cell culture medium and wash cells once with ice-cold PBS. + +3. Remove PBS completely. + +4. Add 50-100 µL of ice-cold cell lysis buffer containing protease inhibitors (and phosphatase inhibitors if needed) to each well. + +5. Incubate on ice for 10-30 minutes with gentle shaking or rocking. + +6. Scrape cells from the bottom of wells using a cell scraper or pipette tip. + +7. Transfer lysate to microcentrifuge tubes. + +8. Centrifuge at 10,000-14,000 x g for 10-15 minutes at 4°C to pellet cell debris. + +9. Transfer supernatant (containing soluble proteins) to new tubes. + +10. Quantify protein concentration using BCA assay or similar method. + +11. Dilute samples to appropriate concentration in sample diluent (typically PBS or assay buffer) for ELISA. + +12. Store samples at -80°C if not using immediately. + +For suspension cells + +1. Culture cells in appropriate vessel until they reach desired density or treatment endpoint. + +2. Transfer cell suspension to centrifuge tubes. + +3. Centrifuge at 300-500 x g for 5 minutes at 4°C to pellet cells. + +4. Remove supernatant and wash cell pellet once with ice-cold PBS. + +5. Centrifuge again and remove PBS completely. + +6. Resuspend cell pellet in ice-cold cell lysis buffer containing protease inhibitors (and phosphatase inhibitors if needed). + +7. Use 50-100 µL lysis buffer per 10⁶ cells, or adjust volume based on cell density. + +8. Incubate on ice for 10-30 minutes with occasional vortexing or pipetting. + +9. Centrifuge at 10,000-14,000 x g for 10-15 minutes at 4°C to pellet cell debris. + +10. Transfer supernatant (containing soluble proteins) to new tubes. + +11. Quantify protein concentration using BCA assay or similar method. + +12. Dilute samples to appropriate concentration in sample diluent for ELISA. + +13. Store samples at -80°C if not using immediately. + +For cell culture supernatant + +1. Culture cells in 96-well plate until treatment endpoint. + +2. Collect cell culture supernatant without disturbing cells. + +3. Centrifuge supernatant at 300-500 x g for 5 minutes at 4°C to remove any cells or debris. + +4. Transfer clarified supernatant to new tubes. + +5. Use supernatant directly in ELISA or store at -80°C. + +6. Note: Supernatant samples typically do not require lysis buffer, as secreted proteins are already in solution. + +PROTOCOL TIPS +================================================================================ + +• Always work on ice to minimize protein degradation +• Include protease inhibitors in lysis buffer to prevent protein degradation +• For phosphoprotein analysis, include phosphatase inhibitors +• Optimize lysis buffer volume based on cell number and protein concentration +• Avoid excessive pipetting or vortexing, which can cause protein denaturation +• Keep samples cold throughout the preparation process +• Aliquot samples to avoid repeated freeze-thaw cycles +• Include appropriate controls (untreated cells, positive controls if available) diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/Enzymatic and Non-Enzymatic Cell Dissociation Protocols _ Thermo Fisher Scientific - US.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/Enzymatic and Non-Enzymatic Cell Dissociation Protocols _ Thermo Fisher Scientific - US.txt new file mode 100644 index 0000000000000000000000000000000000000000..beaef81b65f3bae405477d8471782c7412bbef8b --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/Enzymatic and Non-Enzymatic Cell Dissociation Protocols _ Thermo Fisher Scientific - US.txt @@ -0,0 +1,170 @@ +PROTOCOL: Enzymatic and Non-Enzymatic Cell Dissociation Protocols +SOURCE: https://www.thermofisher.com/us/en/home/references/gibco-cell-culture-basics/cell-culture-protocols/cell-dissociation-protocol.html +================================================================================ + +OVERVIEW +================================================================================ + +Detachment, dissociation, and disaggregation are processes that require cellular material to be broken down from adherent conditions for study—without compromising the health of the cells or cultures involved. To do this, there are a wide range of dissociation methods and reagents available. These dissociation reagents are specially formulated with detachment agents tailored to specific cell types. Below you will find methods, protocols, and materials of the most common dissociation reagents used for gently detaching cells from a substrate or breaking down primary tissues. + +DETACHMENT METHODS +================================================================================ + +There are several detachment methods used to remove cells from substrates while maintaining the health of the cells to be harvested. Some cell lines require more gentle or assertive detachment methods, so it's imperative to understand your cell line's behavior and reaction to physical, enzymatic, or non-enzymatic dissociation methods. + +Table 1. Detachment methods + +Procedure | Dissociation agent | Applications +-----------------------|------------------------------------------------------|-------------------------------------------------------------------------------------------------- +Shake-off | Gentle shaking or rocking of culture vessel, or vigorous pipetting | Loosely adherent cells, mitotic cells +Scraping | Cell scraper | Cell lines sensitive to proteases; may damage some cells +Enzymatic dissociation | Trypsin | Strongly adherent cells +Enzymatic dissociation | Trypsin + collagenase | High density cultures, cultures that have formed multiple layers, especially fibroblasts +Enzymatic dissociation | Dispase | Detaching epidermal cells as confluent, intact sheets from the surface of culture dishes without dissociating the cells +Enzymatic dissociation | Gibco TrypLE dissociation enzyme | Strongly adherent cells; direct substitute for trypsin; applications that require animal origin-free reagents +Non-enzymatic dissociation | Cell dissociation buffer with salt solutions | Lightly adherent cells, gentle, applications requiring intact cell surface proteins, not recommended for strongly adherent cells + +ENZYMATIC CELL DISSOCIATION +================================================================================ + +The following is a general procedure to rapidly remove various cell lines from the substratum while maintaining cellular integrity. This procedure is not meant to be universally applicable for all cell lines. The optimal conditions and concentrations employed for individual systems should be determined empirically. Cell viability should be routinely monitored at the time of subculturing. Cell viability should be greater than 90%. + +1. Remove and discard spent cell culture media. + +2. Wash cells using a balanced salt solution without calcium and magnesium or wash with EDTA. Add wash solution to the side of the flask opposite the cells. Rinse the cell sheet by rocking the flask for 1 to 2 min and discard wash solution. + +3. Add the dissociation solution of choice at 2 to 3 mL/25 cm² to the side of the flask opposite the cells. Be certain that the dissociation solution covers the cell sheet. Incubate the flasks at 37°C. Rock the flasks gently. Generally, cells are dissociated in 5 to 15 min. The actual time needed to dissociate cells will vary according to cell line. Monitor the process carefully to avoid cell damage. In addition to rocking gently, flasks of cell lines that are characteristically difficult to remove from the substratum may be tapped to expedite removal. + +4. When the cells are completely detached, stand the flask in the upright position to allow the cells to drain to the bottom of the flask. Add complete media to the flask. Disperse the cells by pipetting the suspension repeatedly. + +5. Transfer cell suspension to a 15 mL conical tube and centrifuge at 100 × g for 5–10 minutes. + +6. Discard supernatant and resuspend cell pellet with 2–5 mL of pre-warmed complete medium. + +7. Determine viable cell density and percent viability using a Countess Automated Cell Counter (similar automated or manual methods may be used). + +8. Seed, incubate, and subculture according to normal protocols for your cell type. + +TRYPLE EXPRESS ENZYMES PROTOCOL +================================================================================ + +TrypLE Express Enzymes are formulated to allow direct substitution into your existing protocols. The following general procedure can be used to remove various cell lines from cultureware while maintaining cellular integrity. Optimal conditions and concentrations employed for individual systems should be determined empirically. + +Note: TrypLE Express Enzymes may be used at ambient room temperature for many types of cells. + +1. Pre-warm TrypLE Express Enzymes and complete growth medium to 37°C before use. Minimize dwell time. + +2. Aspirate spent medium and discard. + +3. Wash cell monolayer with 5 mL of Dulbecco's Phosphate Buffered Saline (DPBS) without calcium and magnesium. Aspirate and discard. + +4. Add an appropriate volume (e.g., 5 mL in a 75 cm² flask) of TrypLE Express Enzymes to flask. Ensure complete coverage of cell monolayer with TrypLE Express Enzymes. + +5. Incubate at 37°C until cells have detached. Observe cell monolayer using an inverted microscope to ensure complete cell detachment from the surface of the flask. Gently tap flask to dislodge cells if necessary. + +6. Add 5–10 mL of pre-warmed complete medium to flask. Tilt flask in all directions to thoroughly rinse flask and transfer cell suspension to a 15 mL conical tube. + +7. Centrifuge at 100 × g for 5–10 minutes. + +8. Discard supernatant and resuspend cell pellet with 2–5 mL of pre-warmed complete medium. + +9. Determine viable cell density and percent viability using a Countess Automated Cell Counter (similar automated or manual methods may be used). + +10. Seed, incubate and subculture according to normal protocols depending on your cell type. + +Note: Use of soybean trypsin inhibitors are not recommended post-dissociation. + +ENZYMATIC DISSOCIATION REAGENTS +================================================================================ + +Catalog numbers: 15090046, 12604013, 12605010, 17018029, 17101015, 17104019, 17105041 + +DISAGGREGATION AND TISSUE DISSOCIATION +================================================================================ + +A common method to obtain single cell suspensions from primary tissue is enzymatic disaggregation. Expose the cells to enzymes for a minimal amount of time to preserve maximum viability. The following procedures disaggregate whole tissue to obtain a high yield of viable cells. + +TRYPSIN PRIMARY TISSUE PROTOCOL +================================================================================ + +1. After dissecting off unusable tissue, mince the remaining tissue into 3 to 4 mm pieces with a sterile scalpel or scissors. Wash the tissue pieces by resuspending in a balanced salt solution without calcium and magnesium. Allow the tissue pieces to settle and remove the supernatant. Repeat the wash 2 or 3 times. + +2. Place the container with the tissue pieces on ice and remove any remaining supernatant. Add 0.25% trypsin in a balanced salt solution without calcium or magnesium (1 mL of trypsin for every 100 mg of tissue). + +3. Incubate at 4°C for 6 to 18 h to maximize penetration of the enzyme with little trypsin activity. + +4. Decant and discard the trypsin from the tissue pieces. Incubate the tissue pieces with residual trypsin at 37°C for 20 to 30 min. + +5. Add warm, complete media to the tissue pieces and gently disperse the tissue by pipetting. If using a serum-free medium, add soybean trypsin inhibitor. + +6. Filter the cell suspension through sterile, stainless-steel mesh (100 to 200 µM) to completely disperse any remaining tissue. Count and seed the cells for culture. + +COLLAGENASE PRIMARY TISSUE PROTOCOL +================================================================================ + +1. Mince tissue into 3–4 mm pieces with a sterile scalpel or scissors. + +2. Wash the tissue pieces several times with HBSS containing calcium and magnesium. + +3. Add sufficient HBSS with calcium and magnesium to submerge tissue. Add collagenase to 50–200 U/mL. + +4. Incubate at 37°C for 4–18 hours. Increased efficiency is obtained using a rocker platform and supplementing the digest with 3 mM CaCl₂. + +5. Disperse cells by passing through a sterile stainless steel or nylon mesh. Remaining tissue fragments may be disaggregated by addition to fresh collagenase solution and further incubation at 37°C. + +6. Wash dispersed cells several times by centrifugation in HBSS w/o collagenase. + +7. Resuspend cell pellet, after the final wash step, in culture medium. Determine viable cell density using a Countess Automated Cell Counter (alternate automated or manual methods may be used). + +8. Seed cells into culture vessels containing appropriate media. + +DISPASE PRIMARY TISSUE PROTOCOL +================================================================================ + +1. Mince tissue into 3–4 mm pieces with a sterile scalpel or scissors. + +2. Wash the tissue pieces several times in sterile DPBS without calcium and magnesium. + +3. Submerge tissue fragments in Dispase solution (0.6–2.4 U/mL) and incubate at 37°C. More efficient dissociation of tissue can be obtained by mixing the Dispase solution at 0.3–0.6 U/mL with collagenase (60–100 U/mL). + +4. Stir slowly at 37°C until the tissue is sufficiently dissolved. For compact tissues, we recommend incubating for 1 hour. Cells will not be adversely affected even after several hours in Dispase solution. + +5. If necessary, separate the dispersed cells from residual tissue by passing the mixture through a sterile stainless steel or nylon mesh or simply decant the cells after larger fragments have settled. Fresh Dispase solution may be added to the remaining tissue fragments if further disaggregation is required. + +6. Pellet cells by centrifugation and decant the enzyme solution. + +7. Resuspend the cell pellet in appropriate culture medium. Determine viable cell density using a Countess Automated Cell Counter (alternate automated or manual methods may be used). + +8. Seed cells into culture vessels containing appropriate culture medium and incubate under predetermined conditions. + +ENZYMATIC TISSUE DISSOCIATION REAGENTS +================================================================================ + +Catalog numbers: 15400054, 15050065, 15050057, 12604013, 12605028, 12605010, 17100017, 17018029, 17101015, 17104019, 17105041, 14190144 + +NON-ENZYMATIC CELL DISSOCIATION +================================================================================ + +The following is a general procedure to rapidly remove various cell lines from the substratum while maintaining cellular integrity. This procedure is not meant to be universally applicable for all cell lines. The optimal conditions and concentrations employed for individual systems should be determined empirically. Cell viability should be routinely monitored at the time of subculturing. Cell viability should be greater than 90%. + +1. Warm all reagents to 37°C prior to use. + +2. Remove growth medium from cells. + +3. Thoroughly rinse cell monolayers with 5 mL Ca²⁺- and Mg²⁺-free PBS per T75 flask or 100 mm dish. Gently rock the flask (or dish), allowing the solution to bathe the cells for 30 to 60 seconds at room temperature. Aspirate the rinse solution and discard. + +4. Repeat step 3. + +5. Add approximately 5 mL of Cell Dissociation Buffer per T75 flask or 100 mm dish and gently bathe cells by rocking at room temperature for 1 to 2 minutes. You may check for dissociation under the microscope. Aspirate solution and discard. + +6. Firmly tap flask or dish against palm of hand to dislodge cells. If cells do not detach quickly, allow to sit at room temperature for another 2 to 5 minutes and tap flask against palm of hand again. This may be repeated for cells that are more strongly adherent (with 5 more milliliters of dissociation buffer). After the cells are visibly detached, add at least 5 mL of complete growth medium. Resuspend cells in growth medium. + +NON-ENZYMATIC DISSOCIATION REAGENTS +================================================================================ + +Catalog numbers: 13150016, 13151014, 15040066 + +REFERENCES +================================================================================ + +Freshney, R. (1987) Culture of Animal Cells: A Manual of Basic Technique, p. 117, Alan R. Liss, Inc., New York. diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/F-Actin Staining _ Thermo Fisher Scientific - US.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/F-Actin Staining _ Thermo Fisher Scientific - US.txt new file mode 100644 index 0000000000000000000000000000000000000000..1c79a3641c298d1a4935ed30362f40c10d660991 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/F-Actin Staining _ Thermo Fisher Scientific - US.txt @@ -0,0 +1,43 @@ +PROTOCOL: F-Actin Staining +SOURCE: https://www.thermofisher.com/us/en/home/life-science/cell-analysis/cell-analysis-learning-center/molecular-probes-school-of-fluorescence/imaging-basics/protocols-troubleshooting/protocols/f-actin-staining.html +================================================================================ + +OVERVIEW +================================================================================ + +This protocol provides general instructions for labeling F-actin in fixed and permeabilized cells. Actin is one of the most abundant proteins found in cells and can be labeled with a fluorophore very easily when the monomers form a certain type of microfilament, referred to as F-actin. When phalloidin, a molecule that binds F-actin, is conjugated to a fluorophore, it becomes a very useful tool for cell biologists who are using fluorescence microscopy to study their cells. Labeling F-actin can help show the overall shape and structure of the cell and provide context for other fluorescent labels. + +Protocol tip: If you're using fluorescent phalloidin to visualize actin in your experiment, you'll get better results if you perm for 20 minutes instead of 15. + +MATERIALS REQUIRED +================================================================================ + +• Cells that have been fixed and permeabilized (See Fix, Perm, and Block protocol) +• Phosphate-buffered saline (PBS) +• Phalloidin conjugated to fluorophore +• Fluorescence microscope with filter set matched to your fluorophore + +PROTOCOL +================================================================================ + +F-actin dyes—basic labeling protocol + +For fixed and permeabilized cells. Can be used before or after immunolabeling. + +The volumes given in this protocol are good for a single well in a 6-well vessel or a single 35 mm vessel. + +1. Prepare 1 mL F-actin staining solution in PBS from conjugated fluorophore. Phalloidins are typically very water soluble and stain F-actin at 100–200 nM concentrations. If you are optimizing for dye concentration, you will need to prepare a staining solution for each concentration you want to test. + +2. Remove PBS from fixed and permeabilized cells. + +3. Add 1 mL of staining solution. + +4. Incubate for 20 minutes at room temperature. + +5. Remove dye solution. + +6. Wash 3 times with PBS. + +7. Image cells. + +8. Optional: To preserve your sample for long-term storage, you can also mount your sample in mounting medium. Before you start your staining experiment, it's a good idea to check that your fluorophores are compatible with the mounting medium you want to use. diff --git "a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/Fluorescence In Situ Hybridization using TSA\342\204\242 _ Thermo Fisher Scientific - US.txt" "b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/Fluorescence In Situ Hybridization using TSA\342\204\242 _ Thermo Fisher Scientific - US.txt" new file mode 100644 index 0000000000000000000000000000000000000000..7d80d93c7befb85866bd30e7ad551aa90dcb9061 --- /dev/null +++ "b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/Fluorescence In Situ Hybridization using TSA\342\204\242 _ Thermo Fisher Scientific - US.txt" @@ -0,0 +1,161 @@ +PROTOCOL: Fluorescence In Situ Hybridization using TSA™ +SOURCE: Thermo Fisher Scientific - US +URL: https://www.thermofisher.com/us/en/home/references/protocols/cell-and-tissue-analysis/microscopy-protocol/fluorescent-in-situ-hybridization-using-tsa.html +================================================================================ + +Introduction +This protocol describes steps for fluorescent in situ hybridization (FISH) to Drosophila embryos using Tyramide Signal Amplification (TSA™), and was developed in collaboration with Ethan Bier and Dave Kosman at UCSD. This protocol is demonstrated with Drosophila embryos, but should be easily amenable to any specimen or tissue. TSA provides enzymatic fluorescent signal amplification that is ideal for low-abundance DNA and RNA targets. This approach utilizes DNA or RNA probes that have been labeled with a hapten such as biotin, fluorescein, digoxigenin, or DNP. In brief, the haptenylated probe is hybridized to the specimen and then TSA performed to detect the hybridized probe in situ. The hapten is detected in one of two possible approaches. The hapten can be detected by first applying an appropriate anti-hapten primary antibody followed by the horse radish peroxidase (HRP)-secondary antibody provided in the kit. The Alexa Fluor dye tyramide is then incubated with the specimen to detect the hybridized probe. Alternatively, haptens can be developed with anti-hapten–antibody-HRP or streptavidin-HRP conjugates. For example, biotinylated probes are detected with a streptavidin HRP conjugate provided in the kit. Similarly, anti-fluorescein–HRP conjugates can be used to detect fluorescein-labeled probes (but not included in the kit). Our TSA kits are available with a selection of dye tyramides and HRP conjugates; please consult our full product line to determine which best fits your experimental design. Importantly, TSA can be performed sequentially for multiple haptens by simply inactivating one HRP conjugate before applying another. This approach is ideal for multiplex FISH studies. + +Before You Begin +Preparing Solutions for FISH in Drosophila Embryos + +PBT (2 L) +- 200 mL 10X PBS +- 2 mL Tween 20 +- To 2 L with water + +PBT+5% formaldehyde (15 mL)—make fresh +- 12.86 mL PBT +- 2.14 mL 37% formaldehyde + +Proteinase K (10 mg/mL stock) +- 100 µL 20 mg/mL proteinase K stock +- 100 µL water +- Divide into 10 µl aliquots and store at ≤–20°C. + +2X carbonate buffer for fragmentation (10 mL) +- 127.2 mg sodium carbonate +- 67.21 mg sodium bicarbonate +- To 10 mL with water and pH to 10.2 with NaOH; divide into 100 µL aliquots and store at ≤–20°C. + +Stop Solution: 0.2 M Sodium acetate, pH 6.0 (10 mL) +- 164.06 mg sodium acetate +- To 10 mL with water and pH to 6.0 with acetic acid; divide into 100 µL aliquots and store at ≤–20°C. + +Heparin (10 mg/mL stock in PCR-grade water) +- Divide into 250 µL aliquots and store at ≤–20°C. + +Hybridization solution (150 mL) +- 75 mL formamide +- 37.5 mL 20X SSC +- 1.5 mL herring sperm DNA (10 mg/mL) +- 750 µL heparin (10 mg/mL) +- 150 µL Tween 20 +- 35.1 mL water +- Store at 4°C. + +Preparing Solutions for TSA™ Procedure +Labeled Tyramide Solution +Add 150 µL of high-quality anhydrous DMSO to one vial labeled tyramide (the vial comes from the Molecular Probes™ Tyramide Signal Amplification Kit). Divide into 10 µL aliquots; store at ≤–20°C until required. + +Procedure +1. Fixing the Specimens +Note: All steps in this section are to be performed at room temperature unless stated otherwise. Prior to aspirating and discarding solutions from the tube containing the embryos, ensure that the embryos are settled to the bottom to avoid discarding them. + +1.1. Place embryos in a 1.5 mL tube and bring to 1 mL with 100% ethanol (EtOH) +1.2. Rock for 5 minutes. +1.3. Pour off most of the EtOH (leave ~100 µL). +1.4. Add ~900 µL of xylenes (so that the final solution is 90% xylenes and 10% EtOH). +1.5. Rock the tube for 1–2 hours. +1.6. Aspirate and discard the solution. +1.7. Wash the embryos 2 times with EtOH (1 mL each wash). +1.8. Aspirate and discard the last EtOH wash. +1.9. Add 1 mL fresh EtOH and rock for 5 minutes. +1.10. Aspirate and discard the EtOH. +1.11. Wash the embryos 2 times with 100% methanol (MeOH), 1 mL fresh MeOH each wash. +1.12. Add 1 mL fresh MeOH and rock for 5 minutes. +1.13. Aspirate and discard the MeOH. +1.14. Add 500 µL MeOH and 500 µL of PBT+5% formaldehyde to the embryos and rock for 5 minutes. +1.15. Wash the embryos one time with 1 mL PBT+5% formaldehyde. +1.16. Aspirate and discard the PBT+5% formaldehyde. +1.17. Add 1 mL fresh PBT+5% formaldehyde and rock for 25 minutes. +1.18. Aspirate and discard the PBT+5% formaldehyde. +1.19. Add 1 mL PBT and rock for 5 minutes. +1.20. Repeat the PBT wash step 3 more times (including 5 minutes' rocking each time) using fresh PBT each time. +1.21. Remove an aliquot of 10 mg/mL stock solution proteinase K from the freezer and dilute 1:1000 in PBT. +1.22. Aspirate and discard the last PBS wash from the embryos, add 1 mL of the 10 µg/mL proteinase K solution, and rock for 5–7 minutes. +1.23. Aspirate and discard the proteinase K solution. +1.24. Wash the embryos two times with PBT. +1.25. Remove and discard the last PBT wash, add 1 mL fresh PBT, and rock for 5 minutes. +1.26. Remove and discard the PBT. +1.27. Add 1 mL of PBT+5% formaldehyde and rock for 25 minutes. +1.28. Aspirate and discard the PBT+5% formaldehyde. +1.29. Add 1 mL PBT and rock for 5 minutes. +1.30. Repeat the PBT wash step 3 more times (including 5 minutes' rocking each time) using fresh PBT each time. +1.31. Make a solution of 50% PBT/50% hybridization solution (preparation above). +1.32. Aspirate and discard the last PBT wash, add 1 mL of 50% PBT/50% hybridization solution, and rock for 10 minutes. +1.33. Aspirate and discard the 50% PBT/50% hybridization solution. +1.34. Add 1 mL hybridization solution and incubate in a 55°C water bath for at least 1 hour (up to 3 hours). +1.35. If hybridization will be performed the same day, keep the embryos at 55°C until ready for use. Otherwise store the embryos at ≤–20°C until you are ready for the hybridization procedure, but note that extended storage in hybridization solution (more than two weeks) results in degraded morphology over time. + +2. Optional: Fragmenting the Probe +This optional step is intended to reduce the length of the RNA probe to 200–300 bases in order to increase penetration and improve S/N. This step may not be required for all probes, but should be considered as a means to increase S/N. As the incubation duration will determine the final RNA length, a few different times should be tested and the RNA product analyzed by gel electrophoresis. + +2.1. Add 25 µL of 2X carbonate buffer (preparation for 2X carbonate buffer above) to 10 µL of probe. +2.2. Mix well and incubate at 42°C for 30 minutes. +2.3. To the fragmented probe add: + - 50 µL of stop solution (preparation for stop solution above) + - 10 µL of 3 M sodium acetate, pH 5.2 + - 1 µL of glycogen + - 300 µL ice cold 100% EtOH +2.4. Mix well and store at ≤–20°C for 30 minutes (or longer). +2.5. Pellet the nucleic acid by centrifugation. +2.6. Wash the pellet with 400 µL of 70% ice cold ethanol. +2.7. Air dry to remove residual ethanol, but do not allow the pellet to dry out completely. +2.8. Add 5 µL of water and resuspend the pellet. +2.9. Measure the concentration of a small amount of the resuspended probe (≤2 µL). +2.10. Add hybridization buffer to the rest of the probe such that it is at a final concentration somewhere in the range of 5–50 ng/µL. +2.11. Store the probe stock at ≤–20°C until you are ready for the hybridization procedure. + +3. Hybridizing the Probe +3.1. Place the tube containing the embryos in a 55°C water bath until equilibrated. +3.2. Aliquot the embryos into individual 1.5 mL tubes (~25 µL of stirred-up embryos per tube). Make as many tubes as you have RNA probes for. +3.3. For each probe, make a solution containing 100 ng of probe in 100 µL of hybridization solution in a 1.5 mL tube. +3.4. Incubate the tube(s) containing the probe at 65°C for 10 minutes to denature the probe. +3.5. Aspirate and discard most of the hybridization solution from the tube(s) containing the embryos. +3.6. Add 100 µL of denatured probe to the tube containing the embryos, and stir the embryos by tapping the tube. +3.7. Incubate for 20–24 hours at 55°C. +Note: it is recommended that the embryos be stirred once (by tapping the tube) ~10 minutes into the 55°C incubation period and once again before leaving them overnight. Ensure that the water bath is covered during the incubation to minimize condensation in the tube. + +4. Post-hybridization +4.1. Stir up the embryos by tapping the tube with your finger. +4.2. Aspirate and discard as much of the hybridization solution as possible. +4.3. Add 1 mL of fresh hybridization solution, equilibrated to 55°C, to the embryos and gently invert tube 3-4 times. +4.4. Place tube in a 55°C water bath and incubate for 5 minutes. +4.5. Aspirate and discard the hybridization solution. +4.6. Add 1 mL of fresh hybridization solution, equilibrated to 55°C, to the embryos and incubate at 55°C for 30 minutes. During this incubation, periodically remove the tube from the bath and tap it to stir up the embryos. +4.7. Aspirate and discard the hybridization solution (ensure that the embryos have settled before aspiration). +4.8. Add 1 mL of fresh hybridization solution, equilibrated to 55°C, to the embryos and incubate at 55°C for 30 minutes. During this incubation, periodically remove the tube from the bath and tap it to stir up the embryos. +4.9. Make a solution of 50% PBT/50% hybridization solution (preparation above). +Note: Steps 4.10 through 4.15 are performed at room temperature. +4.10. Aspirate and discard the hybridization solution, add 1 mL of 50% PBT/50% hybridization solution, and rock for 10 minutes. +4.11. Aspirate and discard the 50% PBT/50% hybridization solution. +4.12. Add 1 mL PBT. +4.13. Aspirate and discard the PBT. +4.14. Repeat the PBT wash step 3 more times with 5 minutes' rocking each time using fresh PBT each time. + +5. TSA™ Procedure +All steps in the TSA Procedure are performed at room temperature. +5.1. Just before you begin the TSA procedure: + - Aspirate and discard the last PBT wash (from step 4.14). + - Add 1 mL of freshly prepared PBT+blocking reagent and rock for 30–60 minutes at room temperature or 37°C. +5.2. Aspirate and discard the PBT+blocking reagent. +5.3. Add antibody (1 mg/mL) diluted 1:100 in PBT+blocking reagent and rock for 2 hours at room temperature, protected from light. For example, add 4 µL antibody into 396 µL of PBT+blocking reagent. The final concentration should be 1 µg/mL. +5.4. Aspirate and discard the antibody solution. +5.5. Add 1 mL PBT. +5.6. Aspirate and discard the PBT. +5.7. Wash with PBT 4 times with 15 minutes' rocking each time, protected from light using fresh PBT each time. +5.8. Aspirate and discard the PBT. +5.9. Make mixture of 300 µL amplification buffer working solution (from step 5.1) and 3 µL of labeled tyramide solution (from freezer stock) and add it to the embryos. +5.10. Rock for 10–15 minutes. +5.11. Aspirate and discard the tyramide solution. +5.12. Wash the embryos 3 times with PBT (1 mL each wash). +5.13. Aspirate and discard the last PBT wash. +5.14. Add 1 mL PBT and rock for 5 minutes at room temperature. +5.15. If you are ready to image, aspirate and discard the PBT, add 1 mL 70% glycerol/30% PBT and rock for 10 minutes. Store at ≤–20°C until ready to image. We recommend that the embryos are stored no longer than 3 weeks prior to imaging. +5.16. Aspirate and discard the 70% glycerol/30% PBT. +5.17. Add 20 µL ProLong Gold antifade reagent (Invitrogen Cat. no. S36931 or S36935) to the embryos and deposit the sample onto a slide. +5.18. Cover with coverslip and image using appropriate filters (visit probes.thermofisher.com for the spectral characteristics of the dye you are using). + +Reference +1. Science 305, 846 (2004). diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/Functional Mitochondrial Staining _ Thermo Fisher Scientific - US.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/Functional Mitochondrial Staining _ Thermo Fisher Scientific - US.txt new file mode 100644 index 0000000000000000000000000000000000000000..4b44748c5016fb109c5c55910f744a35d29ae5b4 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/Functional Mitochondrial Staining _ Thermo Fisher Scientific - US.txt @@ -0,0 +1,43 @@ +PROTOCOL: Functional Mitochondrial Staining +SOURCE: https://www.thermofisher.com/us/en/home/life-science/cell-analysis/cell-analysis-learning-center/molecular-probes-school-of-fluorescence/imaging-basics/protocols-troubleshooting/protocols/functional-mitochondrial-staining.html +================================================================================ + +OVERVIEW +================================================================================ + +This protocol provides basic instructions to perform a fluorescence-based assay to detect functional mitochondria. Healthy mitochondrial membranes maintain a difference in electrical potential between the interior and exterior of the organelle, referred to as a membrane potential. Tetramethylrhodamine, methyl ester (TMRM) is a cell-permeant dye that accumulates in active mitochondria with intact membrane potentials. If the cells are healthy and have functioning mitochondria, the signal will be bright. Upon loss of the mitochondrial membrane potential, TMRM accumulation will cease and the signal will dim or disappear. + +Reminder: This assay is for live cells. + +MATERIALS REQUIRED +================================================================================ + +• Live cells +• Complete medium (whatever you are growing your cells in) +• Tetramethylrhodamine, methyl ester (TMRM) +• Phosphate-buffered saline (PBS), or any other saline-based buffer +• TRITC filter set for your fluorescence microscope + +PROTOCOL +================================================================================ + +Functional mitochondrial staining—basic labeling protocol + +Protocol tip: TMRM is often supplied as a powder. It's useful to make a stock solution in DMSO and store it at –20°C (for example, add 5 mL DMSO to 25 mg of TMRM to make a 10 mM stock solution). Once you're ready to use your stock, because TMRM is used at a low working concentration, you will need to make intermediate dilutions. + +• To make 50 µM intermediate dilution of TMRM → 1 µL 10 mM TMRM + 200 µL complete medium +• To make 250 nM staining solution of TMRM → 5 µL 50 µM TMRM + 1 mL complete medium + +The volumes given in this protocol are good for a single well in a 6-well vessel or a single 35 mm vessel. + +1. Prepare 1 mL of 250 nM TMRM staining solution in complete medium. If you are optimizing for dye concentration, you will need to prepare a staining solution for each concentration you want to test. + +2. Remove media from live cells. + +3. Add the TMRM staining solution. + +4. Incubate for 30 minutes at 37°C. + +5. Wash 3 times with PBS (or other clear buffer). + +6. Image using TRITC filter. diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/Hoechst 33342 Protocol for Imaging _ Thermo Fisher Scientific - US.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/Hoechst 33342 Protocol for Imaging _ Thermo Fisher Scientific - US.txt new file mode 100644 index 0000000000000000000000000000000000000000..1e1c0c1a60ae7b952c47120aaf8f40d5c7e1c339 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/Hoechst 33342 Protocol for Imaging _ Thermo Fisher Scientific - US.txt @@ -0,0 +1,98 @@ +PROTOCOL: Hoechst 33342 Protocol for Imaging +SOURCE: Thermo Fisher Scientific - US +URL: https://www.thermofisher.com/us/en/home/references/protocols/cell-and-tissue-analysis/protocols/hoechst-33342-protocol-imaging.html +================================================================================ + +OVERVIEW +================================================================================ + +Hoechst 33342 is a cell-permeant blue-fluorescent DNA stain that binds to the minor groove of double-stranded DNA, with preference for A-T rich regions. Unlike DAPI, Hoechst 33342 can readily enter live cells, making it useful for both live and fixed cell imaging applications. It is commonly used for nuclear staining and cell counting in fluorescence microscopy. + +APPLICATIONS +================================================================================ + +This protocol can be used for: +• Nuclear staining in live or fixed cells for fluorescence microscopy +• Cell counting and nuclear morphology analysis +• Counterstaining in multicolor immunofluorescence experiments +• Live cell imaging of nuclear structure + +This protocol should not be used for: +• Flow cytometry (use Hoechst 33342 Protocol for HCA Instruments instead) + +MATERIALS REQUIRED +================================================================================ + +• Cells (live or fixed, on coverslips, slides, or in multiwell plates) +• Hoechst 33342 stain (e.g., Hoechst 33342, trihydrochloride, trihydrate, Cat. No. H3570) +• Phosphate-buffered saline (PBS) or cell culture medium +• Mounting medium (for fixed cells, e.g., ProLong Gold Antifade Mountant) +• Fluorescence microscope with DAPI/Hoechst filter set (excitation ~350 nm, emission ~461 nm) + +PROTOCOL +================================================================================ + +For live cells + +1. Prepare Hoechst 33342 stock solution: + - Dissolve Hoechst 33342 powder in water or DMSO to make a 1-10 mg/mL stock solution. + - Store at 2-8°C, protected from light. Stable for at least 6 months. + +2. Prepare working solution: + - Dilute stock to 1-10 µg/mL in cell culture medium or PBS. + - For most applications, 1-5 µg/mL is sufficient. + +3. Remove cell culture medium from cells. + +4. Add Hoechst 33342 working solution to cover cells. + +5. Incubate for 10-30 minutes at 37°C (or room temperature), protected from light. + +6. For live cell imaging: + - Remove staining solution and replace with fresh culture medium or imaging buffer. + - Image immediately using a fluorescence microscope. + +7. For fixed cell imaging: + - After staining, fix cells according to your standard protocol. + - Wash 2-3 times with PBS. + - Mount and image. + +For fixed cells + +1. Fix and permeabilize cells according to your standard protocol. + +2. Wash cells 2-3 times with PBS. + +3. Prepare Hoechst 33342 working solution (1-5 µg/mL in PBS). + +4. Remove PBS from cells. + +5. Add Hoechst 33342 working solution to cover cells. + +6. Incubate for 10-20 minutes at room temperature, protected from light. + +7. Wash 2-3 times with PBS. + +8. Mount cells in mounting medium (without DAPI if using Hoechst 33342). + +9. Image cells using a fluorescence microscope with DAPI/Hoechst filter set. + +SPECTRAL INFORMATION +================================================================================ + +Hoechst 33342: +• Excitation maximum: ~350 nm (UV) +• Emission maximum: ~461 nm (blue) +• Standard filter set: DAPI/Hoechst +• Compatible with: FITC, TRITC, Texas Red, Alexa Fluor dyes + +PROTOCOL TIPS +================================================================================ + +• Hoechst 33342 is light-sensitive; protect from light during staining and storage +• Optimal concentration may vary by cell type; start with 1 µg/mL and adjust as needed +• For live cells, use lower concentrations (1-2 µg/mL) to minimize toxicity +• Higher concentrations may be needed for some tissue sections or thick samples +• Hoechst 33342 can be used in combination with other fluorescent stains +• For long-term live cell imaging, minimize exposure time and use lower concentrations +• Fixed cells stained with Hoechst 33342 can be stored at 2-8°C, protected from light, for several weeks diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/Mitochondrial Membrane Potential Assay Protocol _ Thermo Fisher Scientific - US.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/Mitochondrial Membrane Potential Assay Protocol _ Thermo Fisher Scientific - US.txt new file mode 100644 index 0000000000000000000000000000000000000000..97248a4404935a5a565cd645eb60564ae645ead0 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/Mitochondrial Membrane Potential Assay Protocol _ Thermo Fisher Scientific - US.txt @@ -0,0 +1,89 @@ +PROTOCOL: Mitochondrial Membrane Potential Assay Protocol +SOURCE: Thermo Fisher Scientific - US +URL: https://www.thermofisher.com/us/en/home/references/protocols/cell-and-tissue-analysis/apoptosis-protocol.html +================================================================================ + +OVERVIEW +================================================================================ + +Mitochondrial membrane potential (ΔΨm) is a key indicator of mitochondrial health and cellular viability. Loss of mitochondrial membrane potential is an early event in apoptosis. This protocol describes methods for measuring mitochondrial membrane potential using fluorescent dyes such as JC-1, TMRM, or MitoTracker dyes. + +APPLICATIONS +================================================================================ + +This protocol can be used for: +• Detecting early apoptosis +• Assessing mitochondrial health +• Screening for mitochondrial toxins +• Studying mitochondrial function + +MATERIALS REQUIRED +================================================================================ + +• Cells in culture +• JC-1 dye, TMRM, or MitoTracker dye +• Cell culture medium +• Phosphate-buffered saline (PBS) +• Fluorescence microscope or flow cytometer +• Optional: CCCP (carbonyl cyanide m-chlorophenyl hydrazone) as positive control + +PROTOCOL +================================================================================ + +Using JC-1 dye (ratiometric indicator) + +JC-1 exists as a monomer (green fluorescence) at low membrane potential and forms aggregates (red fluorescence) at high membrane potential. + +1. Prepare cells in appropriate culture vessel. + +2. Prepare JC-1 working solution: + - For JC-1 powder: Dissolve in DMSO to make 1-5 mg/mL stock. Store at -20°C. + - Working solution: Dilute to 1-10 µg/mL in cell culture medium or PBS. + +3. Remove cell culture medium. + +4. Add JC-1 working solution to cells. + +5. Incubate for 15-30 minutes at 37°C, protected from light. + +6. Wash cells 2-3 times with PBS or culture medium. + +7. For live cell imaging: + - Replace with fresh culture medium or imaging buffer. + - Image immediately using fluorescence microscope. + +8. For fixed cells: + - Fix cells according to standard protocol after JC-1 staining. + - Mount and image. + +9. Image analysis: + - Green fluorescence (monomer): excitation ~485 nm, emission ~530 nm + - Red fluorescence (aggregate): excitation ~535 nm, emission ~590 nm + - Calculate red/green ratio: higher ratio indicates higher membrane potential + +Using TMRM (Tetramethylrhodamine, methyl ester) + +1. Prepare TMRM stock solution (1-10 mM in DMSO). + +2. Prepare working solution (50-250 nM in cell culture medium). + +3. Add TMRM working solution to cells. + +4. Incubate for 20-30 minutes at 37°C, protected from light. + +5. Wash cells 2-3 times with PBS. + +6. Image using TRITC filter set (excitation ~540 nm, emission ~565 nm). + +7. Higher fluorescence intensity indicates higher membrane potential. + +PROTOCOL TIPS +================================================================================ + +• Include positive control (cells treated with CCCP or other mitochondrial uncoupler) to confirm assay is working +• Optimize dye concentration and incubation time for your cell type +• Protect from light during staining and imaging +• For JC-1, use ratiometric analysis (red/green) for more accurate results +• Some dyes may be toxic to cells at high concentrations; use lowest effective concentration +• For flow cytometry, use appropriate controls and compensation settings +• Fixed cells can be used, but live cell imaging provides more dynamic information diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/Staining 3D Cell Cultures for Imaging _ Thermo Fisher Scientific - US.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/Staining 3D Cell Cultures for Imaging _ Thermo Fisher Scientific - US.txt new file mode 100644 index 0000000000000000000000000000000000000000..add8edae45f18b7efee789ae5e8c7add2d9b3d68 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/Staining 3D Cell Cultures for Imaging _ Thermo Fisher Scientific - US.txt @@ -0,0 +1,171 @@ +PROTOCOL: Staining 3D Cell Cultures for Imaging +SOURCE: https://www.thermofisher.com/us/en/home/references/protocols/cell-and-tissue-analysis/protocols/staining-3d-cell-cultures-imaging.html +================================================================================ + +OVERVIEW +================================================================================ + +3D cell cultures and the study of organoids and spheroids require new approaches to be visualized with fluorescent microscopy. Unlike 2D cell cultures which can easily be visualized by light transmitted through the sample, 3D cultures may be too thick for light to effectively pass through. Clearing reagents are recommended when imaging fixed 3D cell cultures of various thickness, including organoids and spheroids. Clearing 3D culture samples enable optimal clarity for sharp, bright fluorescent images. + +MATERIALS REQUIRED +================================================================================ + +• 4% paraformaldehyde (e.g., Image-iT Fixative Solution, Cat. No. R37814) +• Nunclon Sphera 96-well plates (Cat. No. 174925) +• Nunclon 96-well optical-bottom plates (Cat. No. 164588) +• Microscope coverslips +• Phosphate buffer saline (e.g., Gibco PBS (10X), pH 7.4, Cat. No. 70011044) +• Primary antibody (e.g., Invitrogen Antibodies) +• Non-curing glass slide mountant (e.g., SlowFade Glass Soft-set Antifade Mountant, Cat. No. S36917) +• Clearing reagents (CytoVista 3D Cell Culture Clearing/Staining Kit, Cat. No. V11325). Kit includes: + - Tissue penetration buffer (CytoVista Antibody Penetration Buffer, Cat. No. V11310) + - Antibody dilution buffer (CytoVista Antibody Dilution Buffer, Cat. No. V11305) + - Blocking buffer (CytoVista Blocking Buffer, Cat. No. V11306) + - Wash buffer (CytoVista Wash Buffer, Cat. No. V11312) +• DAPI counterstain (e.g., NucBlue Fixed Cell ReadyProbes Reagent- DAPI, Cat. No. R37606) + +PROTOCOL +================================================================================ + +General Notes + +• We recommend that you cut your pipet tips to widen the openings. This will help to prevent shearing of the spheroids. +• This protocol is recommended for spheroids cultured up to 500 microns in thickness. +• Read instructions with fluorescent dyes and reagents—not all of them can be fixed and many need to be used pre-fixation. +• We strongly recommend you optimize the primary antibody before using the kit. Positive and negative samples should be stained with a serial dilution including 1:10, 1:100, 1:500, 1:1000. Thicker spheroids may need more antibody. + +Spheroid fixation and permeabilization + +Spheroids can be fixed within the tissue culture plate or transferred into a microcentrifuge tube for fixation. + +1. Centrifuge samples 500 g for 5 min. Gently remove cell culture media. + +2. Wash cells once with cold PBS. Centrifuge at 500 g for 5 min. Remove supernatant. + +3. (Optional) Add fluorescent cell reagents for viability (refer to protocol below) before fixation. We recommend using LIVE/DEAD fixable dye for viability staining. + +4. Add 4% paraformaldehyde at a volume that is approximately 10X the volume of the tissue. Ensure that the tissue is submerged in the fixative. Fix for 1 h at 37°C at room temperature with gentle agitation. + +5. Wash cells once with cold PBS. Centrifuge at 500 g for 5 min. Remove supernatant. + +6. Permeabilize the spheres for antibody access by incubating spheres for 15 min at room temperature. Suitable permeabilization reagents include CytoVista Antibody Penetration buffer with gentle agitation. + +7. Centrifuge at 500 g for 5 min. Remove supernatant. + +8. Wash samples twice with 1% fetal bovine serum in PBS. + +9. Centrifuge at 500 g for 5 min. Remove supernatant. + +10. Block the samples with blocking buffer such as the CytoVista Blocking Buffer for 2 h at 37°C with gentle agitation. + +Labeling + +Tip: Titrate the primary antibody concentration for optimal results. Too much or too little primary antibody can result in sub-optimal or no labeling. Antibody concentration can vary depending on the thickness of the tissue. + +1. Add primary antibodies prepared in CytoVista Antibody Dilution Buffer. + +2. Incubate samples overnight at room temperature with gentle agitation. + +3. Wash samples 3X with CytoVista Wash Buffer to remove any unbound excess antibody solution. Centrifuge at 500 g for 5 min. Remove supernatant. + +4. Add secondary antibodies prepared in CytoVista Antibody Dilution Buffer. + +Note: We recommend that you titrate the antibody to find the optimal concentration. + +5. Incubate samples overnight at room temperature with gentle agitation. + +6. Add 1 drop of counterstain, NucBlue per mL of sample or 300 nM DAPI. + +Note: 300 nm DAPI preparation: Add 2 mL of dimethylformamide (DMF) to the entire contents of the DAPI vial to make a 14.3 mM (5 mg/mL) DAPI stock solution. Add 2.1 µL of the 14.3 mM DAPI stock solution to 100 µL PBS to make a 300 µM DAPI intermediate dilution. Dilute the 300 µM DAPI intermediate dilution 1:1,000 in PBS as needed to make a 300 nM DAPI stain solution. + +7. Incubate sample for 30 min at room temperature with gentle agitation. + +8. Centrifuge at 500 g for 5 min. Remove supernatant. + +9. Wash sample 3X with CytoVista Wash Buffer. Centrifuge at 500 g for 5 min. Remove supernatant. + +Mounting + +SlowFade mountant can be pipetted to cells in glass bottom plates. Other options include pipetting spheres on a coverslip. Add 1-3 drops of SlowFade glass mount on top of the section. Place coverslip over microscope slide and image. + +Tip: Allow the SlowFade Antifade Mountants to warm to room temperature. If the vials are refrigerated or frozen, thaw for 1 hour at room temperature. Avoid shaking the bottle to prevent air bubbles. + +Imaging + +We recommend using a microscope with Z stack capabilities such as the Invitrogen EVOS M5000, EVOS M7000, or CellInsight CX7 high-content platform. Celleste 6 Image Analysis Software has 2D/3D- deconvolution features that can be used for sharper images. + +CELL REAGENTS FOR SPHEROID IMAGING +================================================================================ + +Perform cell viability assay + +We recommend the LIVE/DEAD Viability/Cytotoxicity Kit (Cat. No. L3224). + +Perform this assay before fixation. + +1. Add 5 µL component A and 20 µL component B to 10 mL DPBS to create staining solution. + +2. Add 100–200 µL of the staining solution directly to cells. + +3. Incubate for 2 hours at room temperature with gently agitation. Protect from light. + +Measure reactive oxygen species (ROS) in live spheroid cells + +We recommend CellROX Green Reagent (Cat. No. C10444). + +Perform this measurement before fixation. Only CellROX Green and DeepRed can be fixed and permeabilized. + +Tip: Generate control with spheroids treated with 100 μM Menadione (e.g., Fisher Chemicals Cat. No. ICN10225925). + +1. Add CellROX Green dye to media for a final concentration of 5 µM (e.g., 1 µl per 500 µl of media). + +2. Incubate for 2 hours at room temperature with gently agitation. Protect from light. + +3. Wash with PBS. Centrifuge at 500 g for 5 min. Gently remove supernatant. Repeat 3x. + +4. Follow with fixation. Compatible with antibody staining and counter staining with NucBlue Live ReadyProbes Reagent (Cat. No. R37605). + +Apoptosis assay using CellEvent Caspase 3/7 detection reagent (with NucBlue dye) + +Reagents and kits: +• NucBlue Live ReadyProbes Reagent (Cat. No. R37605) +• CellEvent Caspase 3/7 detection reagent Green (Cat. No. C10423) + +Note: Use before fixation. Only CellEvent Caspase 3/7 Green or Red are fixable. + +1. Add 100 µL of PBS to dry down powder to generate 100X stock solution. Dilute this 100X stock solution 1:100 in complete media. + +2. Add 2 μM of CellEvent Caspase 3/7 detection reagent and 1 drop NucBlue per milliliter of PBS. + +3. Incubate 2 hours with gentle agitation at room temperature. Protect from light. + +4. Wash with PBS. Centrifuge at 500 g for 5 min. Gently remove supernatant. + +5. Follow with fixation. + +Cell proliferation assay with Click-iT Plus EdU cell proliferation kit + +Reagents and kits: +• Click-iT Plus EdU cell proliferation kit, Alexa Fluor 488 (Cat. No. C10337) +• Click-iT Plus EdU cell proliferation kit, Alexa Fluor 555 (Cat. No. C10638) +• Click-iT Plus EdU cell proliferation kit, Alexa Fluor 594 (Cat. No. C10639) +• Click-iT Plus EdU cell proliferation kit, Alexa Fluor 647 (Cat. No. C10640) + +Note: Use when growing cells in culture. + +1. Optimize cell culture so spheroid size increases. The reagent will be incorporated during S-phase of the cell cycle. + +2. Add 2 mL Component C or an aqueous solution to Component A to make a 10 mM EdU stock solution. Store at –20°C. + +3. Make 1X Click-iT EdU reaction buffer by transferring the solution (4 mL) in the Component D bottle to 36 mL of deionized water. Store any remaining solution at 2–8°C. + +4. Make 10X Click-iT EdU buffer additive by adding 2 mL deionized water to Component F and mixing until fully dissolved. Store at –20°C. + +5. Add fresh media containing 20 μM EdU and incubated overnight at 37°C. Proliferating cells will incorporate EdU at this stage. + +REFERENCES +================================================================================ + +Sherman H, Gitschier HJ, Rossi AE. A Novel Three-Dimensional Immune Oncology Model for High-Throughput Testing of Tumoricidal Activity. Front Immunol. 2018;9:857. Published 2018 Apr 23. PMID: 29740450 + +Mittler F, Obeïd P, Rulina AV, Haguet V, Gidrol X, Balakirev MY. High-Content Monitoring of Drug Effects in a 3D Spheroid Model. Front Oncol. 2017;7:293. Published 2017 Dec 11. PMID: 29322028 diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/Suspension Cell Culture Protocol _ Thermo Fisher Scientific - US.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/Suspension Cell Culture Protocol _ Thermo Fisher Scientific - US.txt new file mode 100644 index 0000000000000000000000000000000000000000..7128eb2de3d758fc13437c50aeeae71f4c9967e1 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/Suspension Cell Culture Protocol _ Thermo Fisher Scientific - US.txt @@ -0,0 +1,82 @@ +PROTOCOL: Suspension Cell Culture Protocol +SOURCE: https://www.thermofisher.com/us/en/home/references/gibco-cell-culture-basics/cell-culture-protocols/subculturing-suspension-cells.html +================================================================================ + +OVERVIEW +================================================================================ + +A suspension cell culture is characterized by the cell's ability to reproduce in suspended medium or without attachment to a substrate. This makes subculturing suspension cells somewhat less complicated than subculturing adherent cells. Because the cells are already suspended in growth medium, there is no need to treat them enzymatically to detach them from the surface of the culture vessel, and the entire process is faster and less traumatic for the cells. + +The suspension cell culture protocols on this page detail how to concentrate and passage cultures in both shaker and spinner flasks. Usually, these cells are maintained by feeding them every 2 to 3 days until they reach confluency. This can be done by directly diluting the cells in the culture flask and continuing to expand them, or by withdrawing a portion of the cells from the culture flask and diluting the remaining cells down to a seeding density appropriate for the cell line. The lag period following the passaging of suspension cell cultures is generally shorter than with adherent cultures. + +MATERIALS REQUIRED +================================================================================ + +In addition to the vessel that contains your cell culture suspension, you will also need the following materials: + +• Complete growth medium: basal medium, serum, and supplements pre-warmed to 37°C +• 37°C incubator with humidified atmosphere of 5% CO₂ +• Magnetic stir plate (if using spinner flasks), roller rack (if using roller bottles), or shaking platform (if using conventional culture flasks or petri dishes) +• Pipettes and pipette tips +• Automated cell counter such as the Countess Automated Cell Counter +• Trypan blue for counting cells + +CULTURE VESSEL OPTIONS +================================================================================ + +Suspension cultures can be maintained in sterile culture flasks (i.e., shaker flasks without baffles) that are not tissue-culture treated; or spinner flasks (i.e., stirrer bottles) specifically designed for suspension cell culture allow for superior gas exchange and permit higher volumes of cells to be cultured. + +• If using a shaker flask, make sure that it does not have baffles (the indents at the bottom of the flask designed to provide agitation) because they disrupt the shaking rhythm. +• When using a spinner flask, ensure that the impeller mechanisms rotate freely and do not contact the vessel walls or the base, as cells are sensitive to physical shearing. The top of the paddles should be positioned slightly above the medium to ensure adequate aeration of the culture. Additionally, adjust the spinner mechanism so that the paddles clear the sides and the bottom of the vessel. +• For proper aeration, the total culture volume in a spinner flask should not exceed half of the flask's indicated volume. For example, a 500 mL spinner should contain no more than 250 mL of culture. It is recommended not to initiate a spinner culture in a flask larger than 500 mL. Instead, scale up from smaller spinners that have already been established. + +Table 1. Minimum media volumes for spinner flasks + +Size of spinner flask | Minimum media volume +----------------------|--------------------- +100 mL | 30 mL +250 mL | 80 mL +500 mL | 200 mL + +PROTOCOL FOR MAMMALIAN SUSPENSION CELL CULTURE +================================================================================ + +The following protocols describe general procedures for subculturing mammalian cells in suspension culture. Note that the procedure for passaging insect cells differs from that for mammalian cells on several crucial steps. For more information, refer to "Considerations for passaging insect cells in suspension culture" below. + +For passaging your own cell line, we recommend that you closely follow the instructions provided with each product you are using in your experiments, especially regarding formulation of your complete growth medium. The consequences of deviating from the culture conditions required for a particular cell type can range from the expression of aberrant phenotypes to a complete failure of the cell culture. The SDSs for all Thermo Fisher Scientific products can be accessed here. + +To promote successful cultures, all solutions and equipment that come in contact with the cells must be sterile. Always use proper sterile technique and work within a laminar flow hood. It is best to subculture cells when they are in log-phase growth before they reach confluency. You can identify suspension cultures that reach confluency, because the cells clump together, and the medium appears turbid when the culture flask is swirled. The maximum recommended cell density before passaging varies with cell lines; refer to the cell-specific product insert or manual for details. + +The following protocol describes a general procedure for passaging mammalian cells in suspension culture: + +1. Remove the flask from the incubator and take a small sample from the culture flask using a sterile pipette. If cells have settled down before taking the sample, swirl the flask to evenly distribute the cells in the medium. + +2. Transfer the cell suspension to a sterile centrifuge tube of appropriate size and centrifuge for 10 minutes at 800 x g. Certain cell lines are sensitive to centrifugal force, refer to your cell's protocols for additional instruction. + +3. Carefully remove the supernatant without disturbing the cell pellet. + +4. Add the desired volume of fresh complete medium gently to the side of the tube and slowly pipette up and down 2 to 3 times to resuspend the cell pellet. + +5. From the sample, determine the total number of cells and percent viability using the Countess Automated Cell Counter or a hemacytometer and trypan blue exclusion. + +6. Calculate the volume of media that you need to add to dilute the culture down to the recommended seeding density. + +7. Aseptically add the appropriate volume of pre-warmed growth medium into the culture flask. You may split the culture into multiple flasks if needed. + +8. The next step will vary based on the type of vessel you are using: + a. For shaker flasks: loosen the caps of the culture flasks one full turn to allow for proper gas exchange (or use a gas-permeable cap) and return the flasks to the shaking incubator. The shaking speed depends on the cell line. + b. For spinner flasks: loosen the side arm caps of the spinner flasks one full turn to allow for proper gas exchange and return the flasks to the incubator. The spinner speed depends on the cell line and the impeller type. Make sure that the spinner speed is kept within the recommended values to avoid damage to the cells from shear stress. + +9. To minimize the accumulation of cell debris and metabolic waste by-products in shaker cultures, gently centrifuge the cell suspension at 100 x g for 5 to 10 minutes and resuspend the cell pellet in fresh growth medium once every three weeks (or as needed). + +CONSIDERATIONS FOR PASSAGING INSECT CELLS IN SUSPENSION CULTURE +================================================================================ + +While the general procedure for subculturing insect cells follows the same steps as mammalian cells, some key requirements of these culture systems are different. For the best results, always follow the instructions provided with the insect cell lines you are using in your experiments. + +• It is recommended that insect cells are subcultured in log phase before confluency is reached. +• CO₂ exchange is not recommended for insect cell culture. +• Maintain insect cells at 27°C in a non-humidified environment. Cells can be maintained at room temperature on the bench top or in a drawer, however, a 27°C controlled environment is recommended. +• Use media specifically formulated for insect cell growth. +• Use a surfactant to decrease shearing. 0.1% Invitrogen Pluronic F-68 is recommended for spinner insect cultures. Pluronic F-68 (BASF) is a surfactant that decreases cell membrane shearing due to impeller forces. Some media such as Sf-900 II SFM and Gibco Express Five SFM already contain surfactants. +• Certain insect cell lines may require adaptation to suspension culture. For more information, refer to the cell-line specific product insert or manual. diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/TrypLE Protocol & Counting with an Automated Cell Counter _ Thermo Fisher Scientific - US.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/TrypLE Protocol & Counting with an Automated Cell Counter _ Thermo Fisher Scientific - US.txt new file mode 100644 index 0000000000000000000000000000000000000000..f46a291f3e0921fa21e0824007203d127dbfb1db --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/TrypLE Protocol & Counting with an Automated Cell Counter _ Thermo Fisher Scientific - US.txt @@ -0,0 +1,76 @@ +PROTOCOL: TrypLE Protocol & Counting with an Automated Cell Counter +SOURCE: https://www.thermofisher.com/us/en/home/references/gibco-cell-culture-basics/cell-culture-protocols/cell-counting-tryple-countess.html +================================================================================ + +OVERVIEW +================================================================================ + +Gibco TrypLE reagents are recombinant enzymes of high purity, which contain no components of animal origin. By conducting this cell dissociation protocol with TrypLE reagent, you will learn how TrypLE reagents were designed to gently remove adherent cells from the surface of plastic flasks and plates, offering a milder alternative to traditional trypsin cell dissociation methods. In addition, TrypLE reagents are room temperature stable and can be substituted for trypsin in existing protocols. + +The Invitrogen Countess Automated Cell Counter is a benchtop instrument which performs cell counting and viability measurements with trypan blue stain. This instrument offers fast, easy, and accurate cell counting without using a hemocytometer, thus eliminating the tedium and subjectivity of manual cell counting. + +MATERIALS REQUIRED +================================================================================ + +You will need the following materials to complete the TrypLE reagent cell dissociation protocol below: + +Catalog numbers: 12604013, 12605010, C10228, 14190144, 339650, 339651, 156499 + +CELL DISSOCIATION PROTOCOL +================================================================================ + +The purpose of using TrypLE Express Enzymes instead of trypsin in cell culture is to provide a gentler and more consistent method for removing adherent cells, reducing the risk of damaging sensitive cells and improving cell viability and recovery rates. + +The following protocol details how to use TrypLE Express to complete cell dissociation. + +1. Warm TrypLE reagent and complete growth medium to 37°C. + +2. Aspirate growth medium from the flask (or plate) and rinse the cells with 5 mL of Dulbecco's Phosphate Buffered Saline (DPBS) without calcium and without magnesium. Gently rock the vessel back and forth. Decant DPBS. + +3. Add an appropriate volume (e.g., 5 mL in a 75 cm² flask) of TrypLE reagent to the vessel. Ensure complete coverage of cell monolayer. Gently rock the vessel, allowing the solution to coat the cell sheet completely. + +4. Leave the cells incubating in TrypLE enzyme for 5–10–minute intervals at 37°C. Remove from the incubator when the cells are visibly detached. Gently tap the vessel to dislodge any cells that remain adhered to the vessel surface. + +5. Add 5-10 mL of pre-warmed complete growth medium to flask. Tilt flask in all directions to thoroughly rinse flask. + +6. Move the entire volume of the cell suspension to a 15 mL conical tube. + +7. Centrifuge at 100 x g for 5–10 minutes. + +8. Discard supernatant and re-suspend cell pellet with 2–5 mL of pre-warmed medium and pipette repeatedly to break up any clumps that may be present. + +DIRECT CELL COUNT PROTOCOL FOR AN AUTOMATIC CELL COUNTER +================================================================================ + +To accurately conduct a direct cell count with an automatic cell counter, it is essential to understand what is a direct cell count? A direct cell count involves counting individual cells, both live and dead, to get an accurate number of cells in your sample. In contrast, an indirect cell count involves counting the number of cells based on other properties of the cell, such as by nuclei staining or spectrophotometry. + +One advantage of direct cell counting using an automated cell counter is that you can save more time completing tedious cell counts than with a hemocytometer alone. Unlike a hemocytometer, which requires manual counting and can be prone to human error, the direct cell count using a cell counter enables automated, precise, and reproducible results, significantly improving efficiency and reliability in cell quantification. + +The following protocol details how to get a direct cell count and viability of your sample using the Countess Automated Cell Counter. + +1. Start the instrument. Automatic instrument functions and count parameters are defined in the Edit protocol screen. For more information on specific operating settings please use the Countess Automated Cell Counter User Guide. Or you can select Rapid capture at the top of the Home screen to set the parameters and perform a count as soon as the slide is inserted into the instrument. + +2. Take 10 μL of cell suspension from step 5 of the Cell Dissociation Protocol and add 10 μL of 0.4% trypan blue stain. Mix gently by pipetting the liquid up and down. + +3. Add 10 μL of the sample mixture into the half-moon shaped chamber port on one or both sides of the Countess cell counting chamber slide and let it settle for 30 seconds. + +4. Insert slide into the slide adapter until a soft click is heard. Slides are read one side at a time, so insert the side you intend to count first accordingly. + +5. Select your count protocol as described in Step 2. When the slide is inserted, the instrument automatically illuminates the sample, sets the intensity of brightfield illumination, and auto focuses on the cells. + +6. Press Count to obtain results. The instrument captures the image and displays the following results: total concentration, percentage and concentration of Live and Dead cells, and percentage of Aggregates (clusters of three or more cells with touching membranes). + +7. To calculate the volume of cell sample and buffer needed to reach a desired concentration based on the count results, press Calculators. + +8. To permanently save the results, press Save. + +9. To perform a new count, push the slide to eject, then insert a new sample slide or the alternate side of the current slide. + +For detailed instructions using all other available models of the Countess automated cell counter, refer to the manuals on thermofisher.com/countess + +REFERENCES +================================================================================ + +Boundless. 6.8.3: Measurements of Microbial Mass. LibreTexts Biology. + +Hoffman, Tracy L. (2006) Counting Cells. Cell Biology (Third Edition). Academic Press. pp 21–24. diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/Trypan Blue Exclusion _ Thermo Fisher Scientific - US.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/Trypan Blue Exclusion _ Thermo Fisher Scientific - US.txt new file mode 100644 index 0000000000000000000000000000000000000000..c0642310763ebace1b60b3589b29b4de73d13016 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/Trypan Blue Exclusion _ Thermo Fisher Scientific - US.txt @@ -0,0 +1,34 @@ +PROTOCOL: Trypan Blue Exclusion +SOURCE: https://www.thermofisher.com/us/en/home/references/gibco-cell-culture-basics/cell-culture-protocols/trypan-blue-exclusion.html +================================================================================ + +OVERVIEW +================================================================================ + +Trypan blue is regularly used to perform dye exclusion tests to assess cell viability. Trypan blue stains dead cells, while live cells are left unaffected. Trypan blue is excluded from intact cells because the dye is only absorbed by cells with a compromised cell membrane. Therefore, a live cell with a healthy cell membrane will remain unstained. This test is often performed while counting cells with the hemocytometer during routine subculturing but can be performed any time cell viability needs to be determined quickly and accurately. + +The following trypan blue protocol will enable you to accurately determine cell viability in your cultures. Cell viability is calculated as the number of viable cells divided by the total number of cells within the grids on the hemacytometer. If cells take up trypan blue, they are considered non-viable. + +MATERIALS REQUIRED +================================================================================ + +In addition to the materials below, hemocytometers may be obtained from Fisher Scientific. + +Catalog number: 15250061 + +PROTOCOL +================================================================================ + +The protocol for trypan blue staining is as follows: + +1. Determine the cell density of your cell line suspension using a hemacytometer. + +2. Add 10 μL of trypan blue solution, 0.4%, to 10 μL of cells. The ratio for trypan blue staining should remain 1:1—one part trypan blue solution to one part cell suspension. + +3. Load a hemacytometer with 10 μL of the cells and trypan blue solution and examine immediately under a microscope at low magnification. + +4. Count the number of blue stained cells and the number of total cells. Cell viability should be at least 95% for healthy log-phase cultures. + +5. To find the % viable cells = [1.00 – (Number of blue cells ÷ Number of total cells)] × 100 + +6. To calculate the number of viable cells per mL of culture, use the formula: Number of viable cells × 10⁴ = cells/mL culture. Remember to correct for the dilution factor. diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/Vybrant DyeCycle Green and Orange Stains _ Thermo Fisher Scientific - US.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/Vybrant DyeCycle Green and Orange Stains _ Thermo Fisher Scientific - US.txt new file mode 100644 index 0000000000000000000000000000000000000000..e9a6309d17fa772a2761277fa8759434026761ff --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/Vybrant DyeCycle Green and Orange Stains _ Thermo Fisher Scientific - US.txt @@ -0,0 +1,92 @@ +PROTOCOL: Vybrant DyeCycle Green and Orange Stains +SOURCE: https://www.thermofisher.com/us/en/home/references/protocols/cell-and-tissue-analysis/flow-cytometry-protocol/cell-cycle-analysis/vybrant-dyecycle-green-and-orange-stains.html +================================================================================ + +OVERVIEW +================================================================================ + +Live cell studies of cellular DNA content and cell cycle distribution are useful to detect variations of growth patterns due to a variety of physical, chemical, or biological means, to monitor apoptosis, and to study tumor behavior and suppressor gene mechanisms. In a given population, cells are distributed among three major phases of cell cycle: G0/G1 phase (one set of paired chromosomes per cell), S phase (DNA synthesis with variable amount of DNA), and G2/M phase (two sets of paired chromosomes per cell, prior to cell division). + +DNA content can be measured using fluorescent, DNA-selective stains that exhibit emission signals proportional to DNA mass. Flow cytometric analysis of these stained populations is then used to produce a frequency histogram that reveals the various cell cycle phases. This analysis is typically performed on permeabilized or fixed cells using a cell-impermeant nucleic acid stain, but is also possible using live cells and a cell-permeant nucleic acid stain. While the choices for fixed cell staining are varied, there are only a few examples of useful cell-permeant nucleic acid stains. + +The Vybrant™ DyeCycle™ Green and Orange stains are DNA-selective, cell membrane-permeant, and nonfluorescent stains for DNA content analysis in living cells. The Vybrant DyeCycle Green and Orange stains are fluorescent upon binding to double-stranded DNA. These stains take advantage of the commonly available 488 nm excitation source, placing cell cycle studies on live cells within reach of all flow cytometrists. Vybrant DyeCycle Green stain is excited at 488 nm with emission ~520 nm. Vybrant DyeCycle Orange stain is excited using both 488 nm and 532 nm laser lines with emission ~570 nm. + +The staining protocol is simple and includes incubating suspended cells in the presence of Vybrant DyeCycle stain and directly measuring the fluorescence without the need for any additional treatment or centrifugation steps. This live cell stain allows the simultaneous co-staining of the cell population for other parameters, and allows for the possibility of cell sorting based on DNA content. + +SPECTRAL CHARACTERISTICS +================================================================================ + +The Vybrant DyeCycle Green stain/DNA complex has fluorescence excitation and emission maxima of 506/534 nm, respectively. The Vybrant DyeCycle Orange stain/DNA complex has fluorescence excitation and emission maxima of 519/563 nm, respectively. + +MATERIALS PROVIDED +================================================================================ + +Table 1. Contents and storage information. + +Material | Amount | Concentration | Storage* | Stability +----------------------------|--------|----------------------------|----------|---------- +Vybrant DyeCycle Green stain | 400 μL | 5 mM solution in dimethyl sulfoxide (DMSO) | ≤–20°C Desiccate Protect from light | When stored as directed, this kit is stable for at least 6 months. +Vybrant DyeCycle Orange stain | 400 μL | 5 mM solution in dimethyl sulfoxide (DMSO) | ≤–20°C Desiccate Protect from light | When stored as directed, this kit is stable for at least 6 months. + +Number of assays: Sufficient material is supplied for approximately 200 flow cytometry assays based on a 1 mL test volume. + +Approximate fluorescence excitation/emission maxima: Vybrant DyeCycle Green stain: 506/534 nm, bound to DNA; Vybrant DyeCycle Orange stain: 519/563 nm, bound to DNA. + +MATERIALS REQUIRED BUT NOT PROVIDED +================================================================================ + +• Cells and culture medium +• Flow cytometer tubes + +CAUTION +================================================================================ + +The hazards posed by these stains have not been fully investigated. Since Vybrant DyeCycle Green and Orange stains are known to bind to nucleic acids, treat the stain as a potential mutagen and use with appropriate care. The stains are supplied as a solution in DMSO, which is known to facilitate the entry of organic molecules into tissues. Use the stain using equipment and practices appropriate for the hazards posed by such materials. Dispose of the reagents in compliance with all pertaining local regulations. + +PROTOCOL +================================================================================ + +The following staining protocol was optimized using Jurkat cells, a human T-cell leukemia line, in complete RPMI medium containing 10% fetal bovine serum with staining at 37°C, but can be adapted to most cell types. These stains can also be used for cells suspended in Hanks' Balanced Salt Solution (HBSS) or phosphate-buffered saline (PBS). Growth medium or buffer used, cell density, cell type variations, and other factors may influence staining. In initial experiments, try a range of dye concentrations to determine the one that yields optimal staining for the given cell type, buffer, and experimental condition. For a given experiment, each flow cytometry sample should contain the same number of cells, as sample-to-sample variation in cell number leads to significant differences in fluorescence signal. If a Vybrant DyeCycle stain is used in combination with other stains for multicolor applications, apply the other stain(s) to the sample first, following all manufacturers' instructions, including wash steps. The Vybrant DyeCycle stain should be the last stain applied to the sample, and do not wash or fix samples prior to flow cytometric analysis. + +General Guidelines + +For optimal DNA content cell cycle analysis, follow these guidelines: + +• Eliminate cell clumps and aggregates from the cell suspension before staining +• Use 37°C for incubation with the Vybrant DyeCycle stains, keep cells at 37°C until acquisition +• Staining may be performed at room temperature, with the staining time about twice as long as the 37°C incubation time +• Do not use glass containers with this stain +• Do not wash or fix cells after staining cells with Vybrant DyeCycle stains +• Validate flow cytometry instrument performance on the day of use +• Use linear amplification for DNA content +• Use low flow rate for acquisition +• Collect adequate numbers of events for the intended application +• Eliminate dead cells from the DNA content analysis of living cells using a dead cell discriminating stains such as SYTOX Green™, SYTOX Red™ or SYTOX AADvanced™ dead cell stains or LIVE/DEAD Fixable Dead cell stains such as Green, Red, Far Red, or Near-IR kits +• Eliminate or correct for cell aggregates during data analysis using gating or modeling software + +Vybrant DyeCycle Staining Protocol + +This basic protocol is optimized using Jurkat cells suspended in complete medium (RPMI/10% fetal bovine serum) and stained with Vybrant DyeCycle stain at 37°C. + +1. Remove the Vybrant DyeCycle Green stain or Vybrant DyeCycle Orange stain from the freezer and allow it to equilibrate to room temperature. + +2. Prepare flow cytometry tubes each containing 1 mL of cell suspension in complete media at a concentration of 1 × 10⁶ cells/mL. + +3. To each tube add 2 μL of Vybrant DyeCycle Green stain or Vybrant DyeCycle Orange stain. Final stain concentration is 10 μM. After use, seal the stain vial tightly. The stain in DMSO solution may be subjected to many freeze-thaw cycles without reagent degradation. + +4. Incubate at 37°C for 30 minutes, protected from light. + +5. For cells stained with Vybrant DyeCycle Green stain, analyze samples on flow cytometer using 488 nm excitation and green emission. For cells stained with Vybrant DyeCycle Orange stain, analyze samples on a flow cytometer using 488 nm excitation or 532 nm excitation and orange emission. + +PRODUCT CATALOG NUMBERS +================================================================================ + +V35004, V35005, 35003, V10273, V10309, S10349, S7020 + +REFERENCES +================================================================================ + +1. Current Protocols in Cytometry, 7.0.1–7.27.7 (2004) +2. Practical Flow Cytometry, 4th Ed., Shapiro H. M., Ed. (2003) +3. Methods Mol Biol 281, 301 (2004) +4. Cytometry A 58, 21 (2004) diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/Vybrant DyeCycle Violet Stain _ Thermo Fisher Scientific - US.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/Vybrant DyeCycle Violet Stain _ Thermo Fisher Scientific - US.txt new file mode 100644 index 0000000000000000000000000000000000000000..40fec9441ea9764051579ecd44fa2035ff946ddf --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/Vybrant DyeCycle Violet Stain _ Thermo Fisher Scientific - US.txt @@ -0,0 +1,96 @@ +PROTOCOL: Vybrant DyeCycle Violet Stain +SOURCE: https://www.thermofisher.com/us/en/home/references/protocols/cell-and-tissue-analysis/protocols/vybrant-dyecycle-violet-stain-protocol.html +================================================================================ + +OVERVIEW +================================================================================ + +Live cell studies of cellular DNA content and cell cycle distribution are useful to detect variations of growth patterns due to a variety of physical, chemical, or biological means, to monitor apoptosis, and to study tumor behavior and suppressor gene mechanisms. In a given population, cells are distributed among three major phases of cell cycle: G0/G1 phase (one set of paired chromosomes per cell), S phase (DNA synthesis with variable amount of DNA), and G2/M phase (two sets of paired chromosomes per cell, prior to cell division). + +DNA content can be measured using fluorescent, DNA-selective stains that exhibit emission signals proportional to DNA mass. Flow cytometric analysis of these stained populations is then used to produce a frequency histogram that reveals the various phases of the cell cycle. This analysis is typically performed on permeabilized or fixed cells using a cell-impermeant nucleic acid stain, but is also possible using live cells and a cell-permeant nucleic acid stain. While the choices for fixed cell staining are varied, there are only a few examples of useful cell-permeant nucleic acid stains. + +The Vybrant™ DyeCycle™ Violet stain is a DNA-selective, cell membrane-permeant, and nonfluorescent stain that uses the violet laser for DNA content analysis in living cells. The Vybrant DyeCycle Violet stain is fluorescent upon binding to double-stranded DNA. Well suited for the popular violet laser line, Vybrant DyeCycle Violet stain can also be used with UV excitation, having emission at ~440 nm. + +The staining protocol is simple and includes incubating suspended cells in the presence of Vybrant DyeCycle Violet stain and directly measuring the fluorescence without the need for any additional treatment or centrifugation steps. This live cell stain allows the simultaneous co-staining of the cell population for other parameters, and allows for the possibility of cell sorting based on DNA content. Vybrant DyeCycle Violet stain does efflux in rodent and human stem cells, making the Side Population (SP) technique now available with violet excitation. + +SPECTRAL CHARACTERISTICS +================================================================================ + +The Vybrant DyeCycle Violet stain/DNA complex has fluorescence excitation and emission maxima of 369/437 nm, respectively. + +MATERIALS PROVIDED +================================================================================ + +Table 1. Contents and storage information. + +Material | Amount | Concentration | Storage* | Stability +----------------------------|--------|----------------------------|----------|---------- +Vybrant DyeCycle Violet stain | 200 μL | 5 mM solution in deionized water | 2-6°C DO NOT FREEZE Protect from light | When stored as directed, this kit is stable for at least 6 months. + +Number of assays: Sufficient material is supplied for approximately 200 flow cytometry assays based on a 1 mL test volume. + +Approximate fluorescence excitation/emission maxima: Vybrant DyeCycle Violet stain: 369/437 in nm bound to DNA. + +MATERIALS REQUIRED BUT NOT PROVIDED +================================================================================ + +• Cells and culture medium +• Flow cytometer tubes + +CAUTION +================================================================================ + +The hazards posed by this stain have not been fully investigated. Since Vybrant DyeCycle Violet stain is known to bind to nucleic acids, treat the stain as a potential mutagen and use with appropriate care. The stain is supplied as a solution in DMSO, which is known to facilitate the entry of organic molecules into tissues. Use the stain using equipment and practices appropriate for the hazards posed by such materials. Dispose of the reagents in compliance with all pertaining local regulations. + +PROTOCOL +================================================================================ + +The following staining protocol was optimized using Jurkat cells, a human T-cell leukemia line, in complete RPMI medium containing 10% fetal bovine serum with staining at 37°C, but can be adapted to most cell types. Test samples comprise of 1 × 10⁶ cells per 1 mL. Growth medium or buffer used, cell density, cell type variations, and other factors may influence staining. In initial experiments, try a range of dye concentrations to determine the one that yields optimal staining for the given cell type, buffer, and experimental condition. For a given experiment, each flow cytometry sample should contain the same number of cells, as sample-to-sample variation in cell number leads to significant differences in fluorescence signal. + +If Vybrant DyeCycle Violet stain is used in combination with other stains for multicolor applications, apply the other stain(s) to the sample first, following all manufacturers' instructions, including wash steps. Vybrant DyeCycle Violet stain should be the last stain applied to the sample, and do not wash or fix samples prior to flow cytometric analysis. + +General Guidelines + +For optimal DNA content cell cycle analysis, follow these guidelines: + +• Eliminate cell clumps and aggregates from the cell suspension before staining +• Use 37°C for incubation with the Vybrant DyeCycle Violet stain +• Hanks' Balanced Salt Solution (HBSS) is recommended if media is not desired, however phosphate buffers are not recommended +• Do not use glass containers with this stain +• Do not wash or fix cells after staining cells with Vybrant DyeCycle Violet stain +• Validate flow cytometry instrument performance on the day of use +• Use linear amplification for DNA content +• Use low flow rate for acquisition +• Collect adequate numbers of events for the intended application +• Eliminate dead cells from the DNA content analysis of living cells using a dead cell discriminating stains such as SYTOX™ Green, SYTOX™ Red or SYTOX™ AADvanced™ dead cell stains or LIVE/DEAD™ Fixable Dead cell stains such as Green, Red, Far Red, or Near-IR kits +• Compensation may be required for Alexa Fluor 488 and PE channels +• Eliminate or correct for cell aggregates during data analysis using gating or modeling software +• Human and rodent stem cells efflux Vybrant DyeCycle Violet stain, and this is the basis for the Side Population (SP) technique; the efflux can be blocked with verapamil, Fumitremorgin C, or other such blocking agents, to prevent dye efflux for accurate DNA content analysis in these stem cells + +Vybrant DyeCycle Violet Staining Protocol + +This basic protocol is optimized using Jurkat cells suspended in complete medium (RPMI/10% fetal bovine serum) and stained with Vybrant DyeCycle Violet stain at 37°C. + +1. Remove the Vybrant DyeCycle Violet stain from the refrigerator and allow the vial to equilibrate to room temperature. + +2. Prepare flow cytometry tubes each containing 1 mL of cell suspension in complete media at a cell concentration of 1 × 10⁶ cells/mL. + +3. To each tube, add 1 μL of Vybrant DyeCycle Violet stain and mix well. Final stain concentration is 5 μM. + +4. Incubate at 37°C for 30 minutes, protected from light. Keep cells at 37°C until acquisition. + +5. Analyze samples without washing or fixing on a flow cytometer using ~405 nm excitation and ~440 nm emission. Vybrant DyeCycle Violet stain may also be excited with a UV light source. + +PRODUCT CATALOG NUMBERS +================================================================================ + +V35003, V10273, V10309, S10349, S7020, S34859, S11348, L23105, L34955, L34957, L34959, L23101, L23102, L10120, L10119, L34960 + +REFERENCES +================================================================================ + +1. Current Protocols in Cytometry, 7.0.1–7.27.7 (2004) +2. Practical Flow Cytometry, 4th Ed., Shapiro H. M., Ed. (2003) +3. Methods Mol Biol 281, 301 (2004) +4. Cytometry A 58, 21 (2004) +5. Stem Cells 25, 1029 (2007) diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/alamarBlue Assays for Cell Viability Protocol, for Microplates _ Thermo Fisher Scientific - US.txt b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/alamarBlue Assays for Cell Viability Protocol, for Microplates _ Thermo Fisher Scientific - US.txt new file mode 100644 index 0000000000000000000000000000000000000000..1dfff8ae997e86d71ba15dc5f6f5ab69c79debfe --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/protocols/thermofisher/alamarBlue Assays for Cell Viability Protocol, for Microplates _ Thermo Fisher Scientific - US.txt @@ -0,0 +1,80 @@ +PROTOCOL: alamarBlue Assays for Cell Viability Protocol, for Microplates +SOURCE: https://www.thermofisher.com/us/en/home/references/protocols/cell-and-tissue-analysis/protocols/alamarblue-cell-viability-reagent-for-microplates-protocol.html +================================================================================ + +OVERVIEW +================================================================================ + +Monitoring viability using cellular reducing environment + +The alamarBlue HS and alamarBlue Cell Viability Reagents are ready-to-use resazurin-based reagents that function as cell health indicators by using the reducing power of living cells to quantitatively measure viability. Upon entering living cells, resazurin is reduced to resorufin, a compound that is red in color and highly fluorescent. + +APPLICATIONS +================================================================================ + +This protocol can be used for: +• Identifying live mammalian, bacterial, plant, fungal cells using a microplate reader +• Higher cell densities +• Longer incubation times + +This protocol should not be used for: +• Flow cytometry + +MATERIALS REQUIRED +================================================================================ + +• Cells growing in culture +• One of the following: + - alamarBlue Cell Viability Reagent + • 25 mL (Cat. No. DAL1025) + • 100 mL (Cat. No. DAL1100) + - alamarBlue HS Cell Viability Reagent + • 25 mL (Cat. No. A50100) + • 100 mL (Cat. No. A50101) +• Phosphate-buffered saline (PBS) (Cat. No. 14190-144) +• Fluorescence or absorbance microplate reader + +PROTOCOL +================================================================================ + +1. Add cells in appropriate medium to microplate wells +2. Add either alamarBlue HS or alamarBlue reagent to microplate wells (see recommended volumes below) +3. Incubate at 37°C for 1–4 hours +4. Read fluorescence or absorbance (signal is stable for 7 hours) +5. Plot a curve of relative fluorescence units vs. drug concentration to generate quantitative results + +Note regarding subsequent culture: +After viability determination, the diluted alamarBlue HS or alamarBlue reagent can be replaced with complete media and returned to the incubator. The cells will continue to proliferate normally. + +RECOMMENDED VOLUMES +================================================================================ + +Table 1. alamarBlue HS and alamarBlue reagent recommended volumes. + +Both alamarBlue Cell Viability Reagents are supplied as 10X solutions. Add alamarBlue reagent directly to cells in culture medium. See below for example volumes: + +Format | Volume of cells + medium | Volume of alamarBlue HS or alamarBlue reagent +--------------------|--------------------------|------------------------------------------------ +Cuvette | 900 μL | 100 μL +96-well plate | 90 μL | 10 μL +384-well plate | 36 μL | 4 μL + +SPECTRAL INFORMATION AND STORAGE +================================================================================ + +alamarBlue HS or alamarBlue cell viability reagents: +• Excitation/Emission: 560/590 nm +• Absorbance: 570 nm (use 600 nm reference wavelength) +• Storage conditions: 4°C + +PROTOCOL TIPS +================================================================================ + +• Correct for background fluorescence by including control wells containing only cell culture medium (no cells) on each plate +• Fluorescence is more sensitive than absorbance and is the preferred detection method +• Bottom-read is more sensitive than top-read + +PRODUCT CATALOG NUMBERS +================================================================================ + +A50100, A50101, DAL1025, DAL1100 diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/biochemistry.cpython-311.pyc b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/biochemistry.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f39fafba3b72c8d4d0213ef99fc9a68fe0b7d7fc Binary files /dev/null and b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/biochemistry.cpython-311.pyc differ diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/bioengineering.cpython-311.pyc b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/bioengineering.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..46f26a155e5d816a19211bbf617f61025404e35e Binary files /dev/null and b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/bioengineering.cpython-311.pyc differ diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/bioimaging.cpython-311.pyc b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/bioimaging.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1c38f0fcb444f9e829f06d36e2b83b4b708b9c00 Binary files /dev/null and b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/bioimaging.cpython-311.pyc differ diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/biophysics.cpython-311.pyc b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/biophysics.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7b8490a9c6700d3c2596314ceff9bccef1a74fdd Binary files /dev/null and b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/biophysics.cpython-311.pyc differ diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/cancer_biology.cpython-311.pyc b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/cancer_biology.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d0eaab1438119133fe15290becc9729a4212f043 Binary files /dev/null and b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/cancer_biology.cpython-311.pyc differ diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/cell_biology.cpython-311.pyc b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/cell_biology.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1856911051edf080a0f0757eaf52284a4f46e151 Binary files /dev/null and b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/cell_biology.cpython-311.pyc differ diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/database.cpython-311.pyc b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/database.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f20e8dc300777f6ce1a219b5160f754f278d9f25 Binary files /dev/null and b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/database.cpython-311.pyc differ diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/genetics.cpython-311.pyc b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/genetics.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e0445f09b7bf7510111a811fdf04aec2a6aa5f90 Binary files /dev/null and b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/genetics.cpython-311.pyc differ diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/genomics.cpython-311.pyc b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/genomics.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..029798b5d8628c7395d6c6e666582d6d6305abfb Binary files /dev/null and b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/genomics.cpython-311.pyc differ diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/glycoengineering.cpython-311.pyc b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/glycoengineering.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c3dc84c505349bc060874034071e6a14cc936ca9 Binary files /dev/null and b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/glycoengineering.cpython-311.pyc differ diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/immunology.cpython-311.pyc b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/immunology.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..487d246d96efd2d7a15ac49282a2f7916a6e618a Binary files /dev/null and b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/immunology.cpython-311.pyc differ diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/lab_automation.cpython-311.pyc b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/lab_automation.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..11e178e62c446caf637a9aab3f4a4ad12816c47d Binary files /dev/null and b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/lab_automation.cpython-311.pyc differ diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/literature.cpython-311.pyc b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/literature.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a8fbcff472954bc47a32c78d9d70769a7ddd499e Binary files /dev/null and b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/literature.cpython-311.pyc differ diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/microbiology.cpython-311.pyc b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/microbiology.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..00e92bd087ad5e97ede2e4361765ada8ffa69634 Binary files /dev/null and b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/microbiology.cpython-311.pyc differ diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/molecular_biology.cpython-311.pyc b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/molecular_biology.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fc05e80eb0c1638a7a639ec9a484cd93b749bc27 Binary files /dev/null and b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/molecular_biology.cpython-311.pyc differ diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/pathology.cpython-311.pyc b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/pathology.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..87ba1616ef6a9b4fe0a38503f683106dd411d033 Binary files /dev/null and b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/pathology.cpython-311.pyc differ diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/pharmacology.cpython-311.pyc b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/pharmacology.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..65d752ee6d6ac431c84642ad4c9d364f6c83aec7 Binary files /dev/null and b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/pharmacology.cpython-311.pyc differ diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/physiology.cpython-311.pyc b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/physiology.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2dd8265c8582cce00911fadbb18d176642d848d2 Binary files /dev/null and b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/physiology.cpython-311.pyc differ diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/protocols.cpython-311.pyc b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/protocols.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..96552f47d4b33f21cd97a8d44c8e1ff8d73b880c Binary files /dev/null and b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/protocols.cpython-311.pyc differ diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/support_tools.cpython-311.pyc b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/support_tools.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0822ad83373ed0266d62ecad6b1ea8d0b2ad2494 Binary files /dev/null and b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/support_tools.cpython-311.pyc differ diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/synthetic_biology.cpython-311.pyc b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/synthetic_biology.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..477e17937b82af019b7d32520a6c535a4f4e2ce7 Binary files /dev/null and b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/synthetic_biology.cpython-311.pyc differ diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/systems_biology.cpython-311.pyc b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/systems_biology.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9b373afb751c87c8d6975c8103fbf7a89d2a9346 Binary files /dev/null and b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/__pycache__/systems_biology.cpython-311.pyc differ diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/biochemistry.py b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/biochemistry.py new file mode 100644 index 0000000000000000000000000000000000000000..64b544e48b758c3103aa4d75b3dd8a9f10afe6a9 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/biochemistry.py @@ -0,0 +1,243 @@ +description = [ + { + "description": "Analyzes circular dichroism (CD) spectroscopy data to " + "determine secondary structure and thermal stability.", + "name": "analyze_circular_dichroism_spectra", + "optional_parameters": [ + { + "default": None, + "description": "Temperature values (°C) for thermal denaturation experiment", + "name": "temperature_data", + "type": "list or numpy.ndarray", + }, + { + "default": None, + "description": "CD signal values at specific wavelength across different temperatures", + "name": "thermal_cd_data", + "type": "list or numpy.ndarray", + }, + { + "default": "./", + "description": "Directory to save result files", + "name": "output_dir", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": 'Name of the biomolecule sample (e.g., "Znf706", "G-quadruplex")', + "name": "sample_name", + "type": "str", + }, + { + "default": None, + "description": 'Type of biomolecule ("protein" or "nucleic_acid")', + "name": "sample_type", + "type": "str", + }, + { + "default": None, + "description": "Wavelength values in nm for CD spectrum", + "name": "wavelength_data", + "type": "list or numpy.ndarray", + }, + { + "default": None, + "description": "CD signal intensity values (typically in mdeg or Δε)", + "name": "cd_signal_data", + "type": "list or numpy.ndarray", + }, + ], + }, + { + "description": "Calculate numeric values for various structural features of an RNA secondary structure.", + "name": "analyze_rna_secondary_structure_features", + "optional_parameters": [ + { + "default": None, + "description": "The RNA sequence corresponding to " + "the structure. If provided, " + "sequence-dependent energy " + "calculations will be performed.", + "name": "sequence", + "type": "str", + } + ], + "required_parameters": [ + { + "default": None, + "description": "RNA secondary structure in " + "dot-bracket notation (e.g., " + '"(((...)))"). Parentheses represent ' + "base pairs, dots represent unpaired " + "bases.", + "name": "dot_bracket_structure", + "type": "str", + } + ], + }, + { + "description": "Analyze protease kinetics data from fluorogenic peptide " + "cleavage assays, fit the data to Michaelis-Menten kinetics, " + "and determine key kinetic parameters.", + "name": "analyze_protease_kinetics", + "optional_parameters": [ + { + "default": "protease_kinetics", + "description": "Prefix for output files", + "name": "output_prefix", + "type": "str", + }, + { + "default": "./", + "description": "Directory to save output files", + "name": "output_dir", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Array of time points (in seconds) at which measurements were taken", + "name": "time_points", + "type": "numpy.ndarray", + }, + { + "default": None, + "description": "2D array of fluorescence " + "measurements where each row " + "corresponds to a different " + "substrate concentration and each " + "column corresponds to a time point", + "name": "fluorescence_data", + "type": "numpy.ndarray", + }, + { + "default": None, + "description": "Array of substrate concentrations " + "(in μM) corresponding to each row " + "in fluorescence_data", + "name": "substrate_concentrations", + "type": "numpy.ndarray", + }, + { + "default": None, + "description": "Concentration of the protease enzyme (in μM)", + "name": "enzyme_concentration", + "type": "float", + }, + ], + }, + { + "description": "Performs in vitro enzyme kinetics assay and analyzes the dose-dependent effects of modulators.", + "name": "analyze_enzyme_kinetics_assay", + "optional_parameters": [ + { + "default": None, + "description": "Dictionary of modulators where keys " + "are modulator names and values are " + "lists of concentrations in μM", + "name": "modulators", + "type": "dict", + }, + { + "default": None, + "description": "Time points in minutes for time-course measurements", + "name": "time_points", + "type": "list or numpy.ndarray", + }, + { + "default": "./", + "description": "Directory to save output files", + "name": "output_dir", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Name of the purified enzyme being tested", + "name": "enzyme_name", + "type": "str", + }, + { + "default": None, + "description": "List of substrate concentrations in μM for kinetic analysis", + "name": "substrate_concentrations", + "type": "list or numpy.ndarray", + }, + { + "default": None, + "description": "Concentration of the enzyme in nM", + "name": "enzyme_concentration", + "type": "float", + }, + ], + }, + { + "description": "Analyzes isothermal titration calorimetry (ITC) data to " + "determine binding affinity and thermodynamic parameters.", + "name": "analyze_itc_binding_thermodynamics", + "optional_parameters": [ + { + "default": None, + "description": "Path to CSV or TSV file containing " + "ITC thermogram data with columns " + "for injection number, injection " + "volume, and heat released/absorbed.", + "name": "itc_data_path", + "type": "str", + }, + { + "default": None, + "description": "Raw ITC thermogram data as a numpy " + "array with shape (n_injections, 3) " + "containing injection number, " + "injection volume, and heat.", + "name": "itc_data", + "type": "numpy.ndarray", + }, + { + "default": 298.15, + "description": "Temperature in Kelvin at which the experiment was conducted.", + "name": "temperature", + "type": "float", + }, + { + "default": None, + "description": "Initial concentration of protein in the cell in molar (M).", + "name": "protein_concentration", + "type": "float", + }, + { + "default": None, + "description": "Concentration of ligand in the syringe in molar (M).", + "name": "ligand_concentration", + "type": "float", + }, + ], + "required_parameters": [], + }, + { + "description": "Perform multiple sequence alignment and phylogenetic " + "analysis to identify conserved protein regions.", + "name": "analyze_protein_conservation", + "optional_parameters": [ + { + "default": "./", + "description": "Directory to save output files", + "name": "output_dir", + "type": "str", + } + ], + "required_parameters": [ + { + "default": None, + "description": "List of protein sequences in FASTA format from multiple organisms.", + "name": "protein_sequences", + "type": "list of str", + } + ], + }, +] diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/bioengineering.py b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/bioengineering.py new file mode 100644 index 0000000000000000000000000000000000000000..a6dc862e0626d9ef5227f1e43dd88e2b941feec5 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/bioengineering.py @@ -0,0 +1,263 @@ +description = [ + { + "description": "Analyze cell migration metrics from time-lapse microscopy images.", + "name": "analyze_cell_migration_metrics", + "optional_parameters": [ + { + "default": 1.0, + "description": "Conversion factor from pixels to micrometers", + "name": "pixel_size_um", + "type": "float", + }, + { + "default": 1.0, + "description": "Time interval between consecutive frames in minutes", + "name": "time_interval_min", + "type": "float", + }, + { + "default": 10, + "description": "Minimum number of frames a cell must be tracked to be included in analysis", + "name": "min_track_length", + "type": "int", + }, + { + "default": "./", + "description": "Directory to save output files", + "name": "output_dir", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to the directory containing time-lapse images or path to a multi-frame TIFF file", + "name": "image_sequence_path", + "type": "str", + } + ], + }, + { + "description": "Simulates CRISPR-Cas9 genome editing process including guide " + "RNA design, delivery, and analysis.", + "name": "perform_crispr_cas9_genome_editing", + "optional_parameters": [], + "required_parameters": [ + { + "default": None, + "description": "List of guide RNA sequences (20 " + "nucleotides each) targeting the " + "genomic region of interest", + "name": "guide_rna_sequences", + "type": "List[str]", + }, + { + "default": None, + "description": "Target genomic sequence to be " + "edited (should be longer than guide " + "RNA and contain the target sites)", + "name": "target_genomic_loci", + "type": "str", + }, + { + "default": None, + "description": "Type of cell or tissue being edited (affects delivery efficiency and editing outcomes)", + "name": "cell_tissue_type", + "type": "str", + }, + ], + }, + { + "description": "Analyze calcium imaging data to quantify neuronal activity " + "metrics including cell counts, event rates, decay times, and " + "signal-to-noise ratios.", + "name": "analyze_calcium_imaging_data", + "optional_parameters": [ + { + "default": "./", + "description": "Directory to save output files", + "name": "output_dir", + "type": "str", + } + ], + "required_parameters": [ + { + "default": None, + "description": "Path to the time-series stack of fluorescence microscopy images (TIFF format)", + "name": "image_stack_path", + "type": "str", + } + ], + }, + { + "description": "Analyzes in vitro drug release kinetics from biomaterial formulations.", + "name": "analyze_in_vitro_drug_release_kinetics", + "optional_parameters": [ + { + "default": "Drug", + "description": "Name of the drug being analyzed", + "name": "drug_name", + "type": "str", + }, + { + "default": None, + "description": "Total amount of drug initially " + "loaded in the formulation. If None, " + "the maximum concentration is used " + "as 100%", + "name": "total_drug_loaded", + "type": "float", + }, + { + "default": "./", + "description": "Directory to save output files", + "name": "output_dir", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Time points at which drug concentrations were measured (in hours)", + "name": "time_points", + "type": "List[float] or numpy.ndarray", + }, + { + "default": None, + "description": "Measured drug concentration at each time point", + "name": "concentration_data", + "type": "List[float] or numpy.ndarray", + }, + ], + }, + { + "description": "Quantifies morphological properties of myofibers in microscopy images of tissue sections.", + "name": "analyze_myofiber_morphology", + "optional_parameters": [ + { + "default": 2, + "description": "Channel index containing nuclei staining (DAPI, Hoechst, etc.)", + "name": "nuclei_channel", + "type": "int", + }, + { + "default": 1, + "description": "Channel index containing myofiber staining (α-Actinin, etc.)", + "name": "myofiber_channel", + "type": "int", + }, + { + "default": "otsu", + "description": "Method for thresholding ('otsu', 'adaptive', or 'manual')", + "name": "threshold_method", + "type": "str", + }, + { + "default": "./", + "description": "Directory to save output files", + "name": "output_dir", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to the microscopy image file " + "(typically a multichannel image " + "with nuclei and myofiber staining)", + "name": "image_path", + "type": "str", + } + ], + }, + { + "description": "Model neural activity trajectories and decode behavioral variables.", + "name": "decode_behavior_from_neural_trajectories", + "optional_parameters": [ + { + "default": 10, + "description": "Number of principal components to use for dimensionality reduction", + "name": "n_components", + "type": "int", + }, + { + "default": "./", + "description": "Directory to save output files", + "name": "output_dir", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Neural spiking activity data, shape (n_timepoints, n_neurons)", + "name": "neural_data", + "type": "numpy.ndarray", + }, + { + "default": None, + "description": "Behavioral data, shape (n_timepoints, n_behavioral_variables)", + "name": "behavioral_data", + "type": "numpy.ndarray", + }, + ], + }, + { + "description": "Simulate a whole-cell model represented as a system of ordinary differential equations (ODEs).", + "name": "simulate_whole_cell_ode_model", + "optional_parameters": [ + { + "default": None, + "description": "Function defining the system of " + "ODEs. Should take arguments (t, y, " + "*args) where t is time, y is the " + "state vector, and args contains " + "additional parameters. If None, a " + "simple example whole-cell model " + "will be used.", + "name": "ode_function", + "type": "callable", + }, + { + "default": "(0, 100)", + "description": "Tuple of (start_time, end_time) for the simulation.", + "name": "time_span", + "type": "tuple", + }, + { + "default": 1000, + "description": "Number of time points to evaluate.", + "name": "time_points", + "type": "int", + }, + { + "default": "'LSODA'", + "description": "Numerical integration method to use (e.g., 'RK45', 'LSODA', 'BDF').", + "name": "method", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Initial values for each state " + "variable in the model. If dict, " + "keys are variable names and values " + "are initial concentrations/values. " + "If array-like, order must match the " + "order expected by the ODE function.", + "name": "initial_conditions", + "type": "dict or array-like", + }, + { + "default": None, + "description": "Model parameters required by the " + "ODE function. Keys are parameter " + "names and values are parameter " + "values.", + "name": "parameters", + "type": "dict", + }, + ], + }, +] diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/bioimaging.py b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/bioimaging.py new file mode 100644 index 0000000000000000000000000000000000000000..c9f4fb02de6f36046ecd5fbeefa9178a2f7e196a --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/bioimaging.py @@ -0,0 +1,510 @@ +description = [ + # Segmentation functions + { + "description": "Split a 4D NIfTI file into separate modality files for nnUNet processing. " + "Handles BRATS dataset format with FLAIR, T1w, t1gd, and T2w modalities.", + "name": "split_modalities", + "optional_parameters": [ + { + "default": "BRAT", + "description": "Base name for the case files", + "name": "case_name", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to the 4D NIfTI file to split", + "name": "input_file", + "type": "str", + }, + { + "default": None, + "description": "Directory to save the split modality files", + "name": "output_dir", + "type": "str", + }, + ], + }, + { + "description": "Prepare input data for nnUNet by handling both 4D and pre-split modality files. " + "Automatically detects file format and prepares data accordingly.", + "name": "prepare_input_for_nnunet", + "optional_parameters": [ + { + "default": "BRAT", + "description": "Base name for the case files", + "name": "case_name", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to input file or directory", + "name": "input_path", + "type": "str", + }, + { + "default": None, + "description": "Directory to save prepared files", + "name": "output_dir", + "type": "str", + }, + ], + }, + { + "description": "Segment images using nnUNet with proper environment setup. " + "Supports brain tumor segmentation and other medical image segmentation tasks.", + "name": "segment_with_nn_unet", + "optional_parameters": [ + { + "default": "3d_fullres", + "description": "Model type for segmentation", + "name": "model_type", + "type": "str", + }, + { + "default": [0, 1, 2, 3, 4], + "description": "Model folds to use for ensemble prediction", + "name": "folds", + "type": "list", + }, + { + "default": False, + "description": "Use test time augmentation", + "name": "use_tta", + "type": "bool", + }, + { + "default": 1, + "description": "Number of threads for preprocessing", + "name": "num_threads", + "type": "int", + }, + { + "default": True, + "description": "Use mixed precision for faster inference", + "name": "mixed_precision", + "type": "bool", + }, + { + "default": True, + "description": "Enable verbose logging", + "name": "verbose", + "type": "bool", + }, + { + "default": True, + "description": "Automatically prepare input for nnUNet", + "name": "auto_prepare_input", + "type": "bool", + }, + { + "default": None, + "description": "Path to nnUNet results folder", + "name": "results_folder", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to input image file or directory", + "name": "image_path", + "type": "str", + }, + { + "default": None, + "description": "Directory to save segmentation results", + "name": "output_dir", + "type": "str", + }, + { + "default": None, + "description": "Task identifier (e.g., 'Task001_BrainTumour')", + "name": "task_id", + "type": "str", + }, + ], + }, + { + "description": "Create and save visualization of segmentation results using nilearn. " + "Generates overlay plots and multiple anatomical views.", + "name": "create_segmentation_visualization", + "optional_parameters": [ + { + "default": "./visualization_output", + "description": "Directory to save visualization images", + "name": "output_dir", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to original MRI file", + "name": "original_mri", + "type": "str", + }, + { + "default": None, + "description": "Path to segmentation file", + "name": "segmentation", + "type": "str", + }, + ], + }, + # Image registration functions + { + "description": "Perform rigid image registration between two medical images using SimpleITK. " + "Rigid registration handles translation and rotation only, preserving shape and size. " + "Includes preprocessing, similarity metrics calculation, and visualization generation.", + "name": "quick_rigid_registration", + "optional_parameters": [ + { + "default": "mutual_information", + "description": "Similarity metric for registration: 'mutual_information', 'mean_squares', 'correlation', or 'normalized_correlation'", + "name": "metric", + "type": "str", + }, + { + "default": "gradient_descent", + "description": "Optimization method: 'gradient_descent', 'lbfgsb', 'powell', or 'amoeba'", + "name": "optimizer", + "type": "str", + }, + { + "default": True, + "description": "Whether to preprocess images (denoising and normalization)", + "name": "preprocess", + "type": "bool", + }, + { + "default": True, + "description": "Whether to create visualization plots", + "name": "create_visualizations", + "type": "bool", + }, + { + "default": 0.01, + "description": "Learning rate for gradient descent optimizer", + "name": "learning_rate", + "type": "float", + }, + { + "default": 100, + "description": "Maximum number of optimization iterations", + "name": "number_of_iterations", + "type": "int", + }, + { + "default": 1e-6, + "description": "Convergence tolerance for optimization", + "name": "gradient_convergence_tolerance", + "type": "float", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to the reference (fixed) image file (supports .nii, .nii.gz, .nrrd, .mha, .mhd formats)", + "name": "fixed_image_path", + "type": "str", + }, + { + "default": None, + "description": "Path to the image to be registered (moving image)", + "name": "moving_image_path", + "type": "str", + }, + { + "default": None, + "description": "Directory path to save registration results and outputs", + "name": "output_dir", + "type": "str", + }, + ], + }, + { + "description": "Perform affine image registration between two medical images using SimpleITK. " + "Affine registration handles translation, rotation, scaling, and shearing. " + "More flexible than rigid registration but still preserves parallel lines.", + "name": "quick_affine_registration", + "optional_parameters": [ + { + "default": "mutual_information", + "description": "Similarity metric for registration: 'mutual_information', 'mean_squares', 'correlation', or 'normalized_correlation'", + "name": "metric", + "type": "str", + }, + { + "default": "gradient_descent", + "description": "Optimization method: 'gradient_descent', 'lbfgsb', 'powell', or 'amoeba'", + "name": "optimizer", + "type": "str", + }, + { + "default": True, + "description": "Whether to preprocess images (denoising and normalization)", + "name": "preprocess", + "type": "bool", + }, + { + "default": True, + "description": "Whether to create visualization plots", + "name": "create_visualizations", + "type": "bool", + }, + { + "default": 0.01, + "description": "Learning rate for gradient descent optimizer", + "name": "learning_rate", + "type": "float", + }, + { + "default": 100, + "description": "Maximum number of optimization iterations", + "name": "number_of_iterations", + "type": "int", + }, + { + "default": 1e-6, + "description": "Convergence tolerance for optimization", + "name": "gradient_convergence_tolerance", + "type": "float", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to the reference (fixed) image file (supports .nii, .nii.gz, .nrrd, .mha, .mhd formats)", + "name": "fixed_image_path", + "type": "str", + }, + { + "default": None, + "description": "Path to the image to be registered (moving image)", + "name": "moving_image_path", + "type": "str", + }, + { + "default": None, + "description": "Directory path to save registration results and outputs", + "name": "output_dir", + "type": "str", + }, + ], + }, + { + "description": "Perform deformable (B-spline) image registration between two medical images using SimpleITK. " + "Deformable registration allows for local non-linear transformations, handling complex deformations. " + "Most flexible but computationally intensive registration method.", + "name": "quick_deformable_registration", + "optional_parameters": [ + { + "default": "mutual_information", + "description": "Similarity metric for registration: 'mutual_information', 'mean_squares', 'correlation', or 'normalized_correlation'", + "name": "metric", + "type": "str", + }, + { + "default": "gradient_descent", + "description": "Optimization method: 'gradient_descent', 'lbfgsb', 'powell', or 'amoeba'", + "name": "optimizer", + "type": "str", + }, + { + "default": True, + "description": "Whether to preprocess images (denoising and normalization)", + "name": "preprocess", + "type": "bool", + }, + { + "default": True, + "description": "Whether to create visualization plots", + "name": "create_visualizations", + "type": "bool", + }, + { + "default": 0.01, + "description": "Learning rate for gradient descent optimizer", + "name": "learning_rate", + "type": "float", + }, + { + "default": 100, + "description": "Maximum number of optimization iterations", + "name": "number_of_iterations", + "type": "int", + }, + { + "default": 1e-6, + "description": "Convergence tolerance for optimization", + "name": "gradient_convergence_tolerance", + "type": "float", + }, + { + "default": 4, + "description": "Number of B-spline control points per dimension for deformable registration", + "name": "number_of_control_points", + "type": "int", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to the reference (fixed) image file (supports .nii, .nii.gz, .nrrd, .mha, .mhd formats)", + "name": "fixed_image_path", + "type": "str", + }, + { + "default": None, + "description": "Path to the image to be registered (moving image)", + "name": "moving_image_path", + "type": "str", + }, + { + "default": None, + "description": "Directory path to save registration results and outputs", + "name": "output_dir", + "type": "str", + }, + ], + }, + { + "description": "Perform batch registration of multiple images to a single reference image. " + "Automatically processes all medical image files in a directory and registers them to the fixed reference. " + "Supports rigid, affine, or deformable registration for all images.", + "name": "batch_register_images", + "optional_parameters": [ + { + "default": "rigid", + "description": "Type of registration to perform: 'rigid', 'affine', or 'deformable'", + "name": "transform_type", + "type": "str", + }, + { + "default": "mutual_information", + "description": "Similarity metric for registration: 'mutual_information', 'mean_squares', 'correlation', or 'normalized_correlation'", + "name": "metric", + "type": "str", + }, + { + "default": "gradient_descent", + "description": "Optimization method: 'gradient_descent', 'lbfgsb', 'powell', or 'amoeba'", + "name": "optimizer", + "type": "str", + }, + { + "default": True, + "description": "Whether to preprocess images (denoising and normalization)", + "name": "preprocess", + "type": "bool", + }, + { + "default": True, + "description": "Whether to create visualization plots for each registration", + "name": "create_visualizations", + "type": "bool", + }, + { + "default": 0.01, + "description": "Learning rate for gradient descent optimizer", + "name": "learning_rate", + "type": "float", + }, + { + "default": 100, + "description": "Maximum number of optimization iterations", + "name": "number_of_iterations", + "type": "int", + }, + { + "default": 1e-6, + "description": "Convergence tolerance for optimization", + "name": "gradient_convergence_tolerance", + "type": "float", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to the reference (fixed) image file", + "name": "fixed_image_path", + "type": "str", + }, + { + "default": None, + "description": "Directory path containing multiple images to register (supports .nii, .nii.gz, .nrrd, .mha, .mhd formats)", + "name": "moving_images_dir", + "type": "str", + }, + { + "default": None, + "description": "Directory path to save registration results for all images", + "name": "output_dir", + "type": "str", + }, + ], + }, + { + "description": "Calculate similarity metrics between two medical images. " + "Supports mutual information, mean squared error, correlation, and normalized cross correlation.", + "name": "calculate_similarity_metrics", + "required_parameters": [ + { + "default": None, + "description": "Path to the first image file", + "name": "image1_path", + "type": "str", + }, + { + "default": None, + "description": "Path to the second image file", + "name": "image2_path", + "type": "str", + }, + ], + }, + { + "description": "Create visualization plots for registration results. " + "Generates comparison plots, difference images, overlays, and metric charts.", + "name": "create_registration_visualization", + "optional_parameters": [ + { + "default": "registration", + "description": "Prefix for output files", + "name": "prefix", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to the reference (fixed) image file", + "name": "fixed_image_path", + "type": "str", + }, + { + "default": None, + "description": "Path to the original moving image file", + "name": "moving_image_path", + "type": "str", + }, + { + "default": None, + "description": "Path to the registered image file", + "name": "registered_image_path", + "type": "str", + }, + { + "default": None, + "description": "Directory to save visualization files", + "name": "output_dir", + "type": "str", + }, + ], + }, +] diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/biophysics.py b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/biophysics.py new file mode 100644 index 0000000000000000000000000000000000000000..58292926ae553ce0e9162e6a3b1b5dd0fa3e7c4e --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/biophysics.py @@ -0,0 +1,83 @@ +description = [ + { + "description": "Predicts intrinsically disordered regions (IDRs) in a protein sequence using IUPred2A.", + "name": "predict_protein_disorder_regions", + "optional_parameters": [ + { + "default": 0.5, + "description": "The disorder score threshold above which a residue is considered disordered", + "name": "threshold", + "type": "float", + }, + { + "default": "disorder_prediction_results.csv", + "description": "Filename to save the per-residue disorder scores", + "name": "output_file", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "The amino acid sequence of the protein to analyze", + "name": "protein_sequence", + "type": "str", + } + ], + }, + { + "description": "Quantifies cell morphology and cytoskeletal organization from fluorescence microscopy images.", + "name": "analyze_cell_morphology_and_cytoskeleton", + "optional_parameters": [ + { + "default": "./results", + "description": "Directory to save output files", + "name": "output_dir", + "type": "str", + }, + { + "default": "otsu", + "description": "Method for cell segmentation ('otsu', 'adaptive', or 'manual')", + "name": "threshold_method", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to the fluorescence microscopy image file", + "name": "image_path", + "type": "str", + } + ], + }, + { + "description": "Quantify tissue deformation and flow dynamics from microscopy image sequence.", + "name": "analyze_tissue_deformation_flow", + "optional_parameters": [ + { + "default": "results", + "description": "Directory to save results", + "name": "output_dir", + "type": "str", + }, + { + "default": 1.0, + "description": "Physical scale of pixels (e.g., μm/pixel) for proper scaling of metrics", + "name": "pixel_scale", + "type": "float", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Sequence of microscopy images " + "(either a list of file paths or a " + "3D numpy array [time, height, " + "width])", + "name": "image_sequence", + "type": "list or numpy.ndarray", + } + ], + }, +] diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/cancer_biology.py b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/cancer_biology.py new file mode 100644 index 0000000000000000000000000000000000000000..f425b29f87da1bf85fd5289e901b0dca8fb1bccb --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/cancer_biology.py @@ -0,0 +1,242 @@ +description = [ + { + "description": "Analyze DNA Damage Response (DDR) network alterations and dependencies in cancer samples.", + "name": "analyze_ddr_network_in_cancer", + "optional_parameters": [ + { + "default": "./results", + "description": "Directory to save output files", + "name": "output_dir", + "type": "str", + } + ], + "required_parameters": [ + { + "default": None, + "description": "Path to gene expression data file (CSV format with genes as rows, samples as columns)", + "name": "expression_data_path", + "type": "str", + }, + { + "default": None, + "description": "Path to mutation data file (CSV " + "format with genes as rows, samples " + "as columns, values indicating " + "mutation status)", + "name": "mutation_data_path", + "type": "str", + }, + ], + }, + { + "description": "Analyze flow cytometry data to quantify senescent and apoptotic cell populations.", + "name": "analyze_cell_senescence_and_apoptosis", + "optional_parameters": [], + "required_parameters": [ + { + "default": None, + "description": "Path to the FCS file containing " + "flow cytometry data with " + "measurements for " + "senescence-associated " + "β-galactosidase (SA-β-Gal) and " + "Annexin V/7-AAD staining", + "name": "fcs_file_path", + "type": "str", + } + ], + }, + { + "description": "Detects and annotates somatic mutations in tumor samples " + "compared to matched normal samples using GATK Mutect2 for " + "variant calling, GATK FilterMutectCalls for filtering, and " + "SnpEff for functional annotation.", + "name": "detect_and_annotate_somatic_mutations", + "optional_parameters": [ + { + "default": "GRCh38.105", + "description": "SnpEff database to use for annotation", + "name": "snpeff_database", + "type": "str", + } + ], + "required_parameters": [ + { + "default": None, + "description": "Path to the tumor sample BAM file", + "name": "tumor_bam", + "type": "str", + }, + { + "default": None, + "description": "Path to the matched normal sample BAM file", + "name": "normal_bam", + "type": "str", + }, + { + "default": None, + "description": "Path to the reference genome FASTA file", + "name": "reference_genome", + "type": "str", + }, + { + "default": None, + "description": "Prefix for output files", + "name": "output_prefix", + "type": "str", + }, + ], + }, + { + "description": "Detects and characterizes structural variations (SVs) in " + "genomic sequencing data using LUMPY for SV detection " + "followed by annotation with COSMIC and/or ClinVar databases.", + "name": "detect_and_characterize_structural_variations", + "optional_parameters": [ + { + "default": None, + "description": "Path to the COSMIC database for cancer annotation", + "name": "cosmic_db_path", + "type": "str", + }, + { + "default": None, + "description": "Path to the ClinVar database for clinical annotation", + "name": "clinvar_db_path", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to the aligned sequencing data in BAM format", + "name": "bam_file_path", + "type": "str", + }, + { + "default": None, + "description": "Path to the reference genome in FASTA format", + "name": "reference_genome_path", + "type": "str", + }, + { + "default": None, + "description": "Directory where results will be saved", + "name": "output_dir", + "type": "str", + }, + ], + }, + { + "description": "Performs Non-negative Matrix Factorization (NMF) on gene " + "expression data to extract metagenes and their associated " + "sample weights for tumor subtype identification.", + "name": "perform_gene_expression_nmf_analysis", + "optional_parameters": [ + { + "default": 10, + "description": "Number of metagenes (components) to extract.", + "name": "n_components", + "type": "int", + }, + { + "default": True, + "description": "Whether to normalize the expression data before applying NMF.", + "name": "normalize", + "type": "bool", + }, + { + "default": "nmf_results", + "description": "Directory to save the output files.", + "name": "output_dir", + "type": "str", + }, + { + "default": 42, + "description": "Random seed for reproducibility.", + "name": "random_state", + "type": "int", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to a CSV or TSV file " + "containing gene expression data " + "with genes as rows and samples as " + "columns. Values should be " + "non-negative.", + "name": "expression_data_path", + "type": "str", + } + ], + }, + { + "description": "CNVkit-based copy number workflow performing CNV segmentation, purity & ploidy approximation, simplified HRD-style metrics, and focal amplification/deletion detection in selected genes.", + "name": "analyze_copy_number_purity_ploidy_and_focal_events", + "optional_parameters": [ + { + "name": "normal_bam", + "type": "str", + "default": None, + "description": "Path to matched normal BAM (recommended for CNVkit)", + }, + { + "name": "output_dir", + "type": "str", + "default": "cn_analysis_results", + "description": "Directory to store CNVkit workflow outputs", + }, + { + "name": "targets_bed", + "type": "str", + "default": None, + "description": "BED file of target regions for CNVkit (panel/exome)", + }, + { + "name": "antitargets_bed", + "type": "str", + "default": None, + "description": "BED file of antitarget regions for CNVkit", + }, + { + "name": "gene_bed", + "type": "str", + "default": None, + "description": "Gene BED (chrom, start, end, gene) for focal event annotation", + }, + { + "name": "focal_genes", + "type": "list[str]", + "default": None, + "description": "Genes to highlight for focal events (defaults: MYC, ERBB2, CDKN2A)", + }, + { + "name": "log2_amp_threshold", + "type": "float", + "default": 1.0, + "description": "Log2 ratio threshold for focal amplification calls", + }, + { + "name": "log2_del_threshold", + "type": "float", + "default": -1.0, + "description": "Log2 ratio threshold for focal deep deletion calls", + }, + ], + "required_parameters": [ + { + "name": "tumor_bam", + "type": "str", + "default": None, + "description": "Path to tumor BAM (indexed)", + }, + { + "name": "reference_genome", + "type": "str", + "default": None, + "description": "Path to reference genome FASTA", + }, + ], + }, +] diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/cell_biology.py b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/cell_biology.py new file mode 100644 index 0000000000000000000000000000000000000000..5d51a22c5c31adb1cd84facdc7dcb9addc73a141 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/cell_biology.py @@ -0,0 +1,163 @@ +description = [ + { + "description": "Quantify the percentage of cells in each cell cycle phase " + "using Calcofluor white stained microscopy images.", + "name": "quantify_cell_cycle_phases_from_microscopy", + "optional_parameters": [ + { + "default": "./results", + "description": "Directory to save results", + "name": "output_dir", + "type": "str", + } + ], + "required_parameters": [ + { + "default": None, + "description": "List of file paths to microscopy images of cells stained with Calcofluor white", + "name": "image_paths", + "type": "List[str]", + } + ], + }, + { + "description": "Quantify cell motility features from time-lapse microscopy " + "images and cluster cells based on motility patterns.", + "name": "quantify_and_cluster_cell_motility", + "optional_parameters": [ + { + "default": "./results", + "description": "Directory to save output files", + "name": "output_dir", + "type": "str", + }, + { + "default": 3, + "description": "Number of motility pattern clusters to identify", + "name": "num_clusters", + "type": "int", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to directory containing time-lapse microscopy images in sequential order", + "name": "image_sequence_path", + "type": "str", + } + ], + }, + { + "description": "Performs Fluorescence-Activated Cell Sorting (FACS) to " + "enrich cell populations based on fluorescence " + "characteristics.", + "name": "perform_facs_cell_sorting", + "optional_parameters": [ + { + "default": None, + "description": "Minimum threshold for the " + "fluorescence parameter. Cells below " + "this value will be excluded", + "name": "threshold_min", + "type": "float", + }, + { + "default": None, + "description": "Maximum threshold for the " + "fluorescence parameter. Cells above " + "this value will be excluded", + "name": "threshold_max", + "type": "float", + }, + { + "default": "sorted_cells.csv", + "description": "Filename to save the sorted cell population data", + "name": "output_file", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to the FCS file containing flow cytometry data", + "name": "cell_suspension_data", + "type": "str", + }, + { + "default": None, + "description": "The fluorescence parameter to use for sorting (e.g., 'GFP', 'FITC', 'PE')", + "name": "fluorescence_parameter", + "type": "str", + }, + ], + }, + { + "description": "Analyze flow cytometry data to identify and quantify " + "specific cell populations based on surface markers.", + "name": "analyze_flow_cytometry_immunophenotyping", + "optional_parameters": [ + { + "default": None, + "description": "Spillover/compensation matrix to correct for fluorescence overlap", + "name": "compensation_matrix", + "type": "numpy.ndarray", + }, + { + "default": "./results", + "description": "Directory to save the results", + "name": "output_dir", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to the FCS file containing flow cytometry data", + "name": "fcs_file_path", + "type": "str", + }, + { + "default": None, + "description": "Dictionary defining the gating " + "strategy. Each key is a population " + "name, and each value is a list of " + "tuples (marker, operator, " + "threshold)", + "name": "gating_strategy", + "type": "dict", + }, + ], + }, + { + "description": "Quantifies metrics of mitochondrial morphology and membrane " + "potential from fluorescence microscopy images.", + "name": "analyze_mitochondrial_morphology_and_potential", + "optional_parameters": [ + { + "default": "./output", + "description": "Directory to save output files", + "name": "output_dir", + "type": "str", + } + ], + "required_parameters": [ + { + "default": None, + "description": "Path to the fluorescence microscopy " + "image showing mitochondrial " + "morphology (e.g., MTS-GFP)", + "name": "morphology_image_path", + "type": "str", + }, + { + "default": None, + "description": "Path to the fluorescence microscopy " + "image showing mitochondrial " + "membrane potential (e.g., TMRE " + "staining)", + "name": "potential_image_path", + "type": "str", + }, + ], + }, +] diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/database.py b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/database.py new file mode 100644 index 0000000000000000000000000000000000000000..820eece7cc72ab8e595080d592946e9cf67909e3 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/database.py @@ -0,0 +1,731 @@ +description = [ + { + "description": "Query the UniProt REST API using either natural language or a direct endpoint.", + "name": "query_uniprot", + "optional_parameters": [ + { + "default": None, + "description": "Full or partial UniProt API endpoint URL to query directly (e.g., 'https://rest.uniprot.org/uniprotkb/P01308')", + "name": "endpoint", + "type": "str", + }, + {"default": 5, "description": "Maximum number of results to return", "name": "max_results", "type": "int"}, + ], + "required_parameters": [ + { + "default": None, + "description": 'Natural language query about proteins (e.g., "Find information about human insulin")', + "name": "prompt", + "type": "str", + } + ], + }, + { + "description": "Query the AlphaFold Database API for protein structure predictions or metadata; optionally download structures.", + "name": "query_alphafold", + "optional_parameters": [ + { + "name": "endpoint", + "type": "str", + "description": "Endpoint: 'prediction', 'summary', or 'annotations'", + "default": "prediction", + }, + {"name": "residue_range", "type": "str", "description": "Residue range as 'start-end'", "default": None}, + {"name": "download", "type": "bool", "description": "Whether to download structure file", "default": False}, + {"name": "output_dir", "type": "str", "description": "Directory to save downloaded files", "default": None}, + {"name": "file_format", "type": "str", "description": "Download format 'pdb' or 'cif'", "default": "pdb"}, + { + "name": "model_version", + "type": "str", + "description": "AlphaFold model version (e.g., v4)", + "default": "v4", + }, + {"name": "model_number", "type": "int", "description": "Model number (1-5)", "default": 1}, + ], + "required_parameters": [ + { + "name": "uniprot_id", + "type": "str", + "description": "UniProt accession ID (e.g., 'P12345')", + "default": None, + } + ], + }, + { + "description": "Query the InterPro REST API using natural language or a direct endpoint.", + "name": "query_interpro", + "optional_parameters": [ + {"name": "endpoint", "type": "str", "description": "Endpoint path or full URL", "default": None}, + {"name": "max_results", "type": "int", "description": "Max results per page", "default": 3}, + ], + "required_parameters": [ + { + "name": "prompt", + "type": "str", + "description": "Natural language query about protein domains/families", + "default": None, + } + ], + }, + { + "description": "Query the RCSB PDB database using natural language or a direct structured query.", + "name": "query_pdb", + "optional_parameters": [ + {"name": "query", "type": "dict", "description": "Direct RCSB Search API query JSON", "default": None}, + {"name": "max_results", "type": "int", "description": "Maximum results to return", "default": 3}, + ], + "required_parameters": [ + { + "name": "prompt", + "type": "str", + "description": "Natural language query about protein structures", + "default": None, + } + ], + }, + { + "description": "Retrieve detailed data and/or download files for PDB identifiers.", + "name": "query_pdb_identifiers", + "optional_parameters": [ + { + "name": "return_type", + "type": "str", + "description": "'entry', 'assembly', 'polymer_entity', etc.", + "default": "entry", + }, + {"name": "download", "type": "bool", "description": "Download PDB structure files", "default": False}, + { + "name": "attributes", + "type": "List[str]", + "description": "Specific attributes to retrieve", + "default": None, + }, + ], + "required_parameters": [ + {"name": "identifiers", "type": "List[str]", "description": "List of PDB identifiers", "default": None} + ], + }, + { + "description": "Take a natural language prompt and convert it to a structured KEGG API query.", + "name": "query_kegg", + "optional_parameters": [ + {"name": "endpoint", "type": "str", "description": "Direct KEGG endpoint to query", "default": None}, + {"name": "verbose", "type": "bool", "description": "Return detailed results", "default": True}, + ], + "required_parameters": [ + {"name": "prompt", "type": "str", "description": "Natural language query about KEGG data", "default": None} + ], + }, + { + "description": "Query the STRING protein interaction database using natural language or direct endpoint.", + "name": "query_stringdb", + "optional_parameters": [ + {"name": "endpoint", "type": "str", "description": "Full URL to query directly", "default": None}, + { + "name": "download_image", + "type": "bool", + "description": "Download image results if endpoint is image", + "default": False, + }, + {"name": "output_dir", "type": "str", "description": "Directory to save downloaded files", "default": None}, + {"name": "verbose", "type": "bool", "description": "Return detailed results", "default": True}, + ], + "required_parameters": [ + { + "name": "prompt", + "type": "str", + "description": "Natural language query about protein interactions", + "default": None, + } + ], + }, + { + "description": "Query the IUCN Red List API using natural language or a direct endpoint.", + "name": "query_iucn", + "optional_parameters": [ + { + "name": "prompt", + "type": "str", + "description": "Natural language query about species conservation status", + "default": None, + }, + {"name": "endpoint", "type": "str", "description": "Endpoint name or full URL", "default": None}, + {"name": "verbose", "type": "bool", "description": "Return detailed results", "default": True}, + ], + "required_parameters": [{"name": "token", "type": "str", "description": "IUCN API token", "default": ""}], + }, + { + "description": "Query the Paleobiology Database (PBDB) API using natural language or a direct endpoint.", + "name": "query_paleobiology", + "optional_parameters": [ + {"name": "endpoint", "type": "str", "description": "API endpoint name or full URL", "default": None}, + {"name": "verbose", "type": "bool", "description": "Return detailed results", "default": True}, + ], + "required_parameters": [ + { + "name": "prompt", + "type": "str", + "description": "Natural language query about fossil records", + "default": None, + } + ], + }, + { + "description": "Query the JASPAR REST API for transcription factor binding profiles.", + "name": "query_jaspar", + "optional_parameters": [ + {"name": "endpoint", "type": "str", "description": "API endpoint path or full URL", "default": None}, + {"name": "verbose", "type": "bool", "description": "Return detailed results", "default": True}, + ], + "required_parameters": [ + { + "name": "prompt", + "type": "str", + "description": "Natural language query about TF binding profiles", + "default": None, + } + ], + }, + { + "description": "Query the World Register of Marine Species (WoRMS) REST API using natural language or a direct endpoint.", + "name": "query_worms", + "optional_parameters": [ + {"name": "endpoint", "type": "str", "description": "Full URL or endpoint specification", "default": None}, + {"name": "verbose", "type": "bool", "description": "Return detailed results", "default": True}, + ], + "required_parameters": [ + { + "name": "prompt", + "type": "str", + "description": "Natural language query about marine species", + "default": None, + } + ], + }, + { + "description": "Query the cBioPortal REST API using natural language or a direct endpoint.", + "name": "query_cbioportal", + "optional_parameters": [ + {"name": "endpoint", "type": "str", "description": "API endpoint path or full URL", "default": None}, + {"name": "verbose", "type": "bool", "description": "Return detailed results", "default": True}, + ], + "required_parameters": [ + { + "name": "prompt", + "type": "str", + "description": "Natural language query about cancer genomics", + "default": None, + } + ], + }, + { + "description": "Convert a natural language prompt into a structured ClinVar search query and run it.", + "name": "query_clinvar", + "optional_parameters": [ + {"name": "search_term", "type": "str", "description": "Direct ClinVar search term", "default": None}, + {"name": "max_results", "type": "int", "description": "Maximum number of results", "default": 3}, + ], + "required_parameters": [ + { + "name": "prompt", + "type": "str", + "description": "Natural language query about genetic variants", + "default": None, + } + ], + }, + { + "description": "Query the NCBI GEO database (GDS/GEOPROFILES) using natural language or direct search term.", + "name": "query_geo", + "optional_parameters": [ + {"name": "search_term", "type": "str", "description": "Direct GEO search term", "default": None}, + {"name": "max_results", "type": "int", "description": "Maximum number of results", "default": 3}, + ], + "required_parameters": [ + { + "name": "prompt", + "type": "str", + "description": "Natural language query about expression data", + "default": None, + } + ], + }, + { + "description": "Query the NCBI dbSNP database using natural language or direct search term.", + "name": "query_dbsnp", + "optional_parameters": [ + {"name": "search_term", "type": "str", "description": "Direct dbSNP search term", "default": None}, + {"name": "max_results", "type": "int", "description": "Maximum number of results", "default": 3}, + ], + "required_parameters": [ + { + "name": "prompt", + "type": "str", + "description": "Natural language query about SNPs/variants", + "default": None, + } + ], + }, + { + "description": "Query the UCSC Genome Browser API using natural language or a direct endpoint.", + "name": "query_ucsc", + "optional_parameters": [ + {"name": "endpoint", "type": "str", "description": "Full URL or endpoint spec", "default": None}, + {"name": "verbose", "type": "bool", "description": "Return detailed results", "default": True}, + ], + "required_parameters": [ + { + "name": "prompt", + "type": "str", + "description": "Natural language query about genomic data", + "default": None, + } + ], + }, + { + "description": "Query the Ensembl REST API using natural language or a direct endpoint.", + "name": "query_ensembl", + "optional_parameters": [ + {"name": "endpoint", "type": "str", "description": "Direct Ensembl endpoint or full URL", "default": None}, + {"name": "verbose", "type": "bool", "description": "Return detailed results", "default": True}, + ], + "required_parameters": [ + { + "name": "prompt", + "type": "str", + "description": "Natural language query about genomic data", + "default": None, + } + ], + }, + { + "description": "Query the OpenTargets Platform API using natural language or a direct GraphQL query.", + "name": "query_opentarget", + "optional_parameters": [ + {"name": "query", "type": "str", "description": "Direct GraphQL query string", "default": None}, + {"name": "variables", "type": "dict", "description": "Variables for GraphQL", "default": None}, + {"name": "verbose", "type": "bool", "description": "Return detailed results", "default": False}, + ], + "required_parameters": [ + { + "name": "prompt", + "type": "str", + "description": "Natural language query about targets/diseases", + "default": None, + } + ], + }, + { + "description": "Query the Monarch Initiative API using natural language or a direct endpoint.", + "name": "query_monarch", + "optional_parameters": [ + {"name": "endpoint", "type": "str", "description": "Direct endpoint or full URL", "default": None}, + {"name": "max_results", "type": "int", "description": "Max results (adds limit param)", "default": 2}, + {"name": "verbose", "type": "bool", "description": "Return detailed results", "default": False}, + ], + "required_parameters": [ + { + "name": "prompt", + "type": "str", + "description": "Natural language query about genes/diseases/phenotypes", + "default": None, + } + ], + }, + { + "description": "Query the OpenFDA API using natural language or direct parameters.", + "name": "query_openfda", + "optional_parameters": [ + {"name": "endpoint", "type": "str", "description": "Direct endpoint or full URL", "default": None}, + {"name": "max_results", "type": "int", "description": "Max results (limit)", "default": 100}, + {"name": "verbose", "type": "bool", "description": "Return detailed results", "default": True}, + {"name": "search_params", "type": "dict", "description": "Search parameters mapping", "default": None}, + {"name": "sort_params", "type": "dict", "description": "Sort parameters mapping", "default": None}, + {"name": "count_params", "type": "str", "description": "Field to count", "default": None}, + {"name": "skip_results", "type": "int", "description": "Skip for pagination", "default": 0}, + ], + "required_parameters": [ + { + "name": "prompt", + "type": "str", + "description": "Natural language query about OpenFDA data", + "default": None, + } + ], + }, + { + "description": "Query the GWAS Catalog API using natural language or a direct endpoint.", + "name": "query_gwas_catalog", + "optional_parameters": [ + {"name": "endpoint", "type": "str", "description": "Endpoint name (e.g., 'studies')", "default": None}, + {"name": "max_results", "type": "int", "description": "Max results per page (size)", "default": 3}, + ], + "required_parameters": [ + {"name": "prompt", "type": "str", "description": "Natural language query about GWAS data", "default": None} + ], + }, + { + "description": "Query gnomAD for variants in a gene using natural language or direct gene symbol.", + "name": "query_gnomad", + "optional_parameters": [ + {"name": "gene_symbol", "type": "str", "description": "Gene symbol (e.g., 'BRCA1')", "default": None}, + {"name": "verbose", "type": "bool", "description": "Return detailed results", "default": True}, + ], + "required_parameters": [ + { + "name": "prompt", + "type": "str", + "description": "Natural language query about genetic variants", + "default": None, + } + ], + }, + { + "description": "Identify a DNA or protein sequence using NCBI BLAST.", + "name": "blast_sequence", + "optional_parameters": [], + "required_parameters": [ + {"name": "sequence", "type": "str", "description": "Query sequence", "default": None}, + {"name": "database", "type": "str", "description": "BLAST database (e.g., core_nt or nr)", "default": None}, + {"name": "program", "type": "str", "description": "BLAST program (blastn or blastp)", "default": None}, + ], + }, + { + "description": "Query the Reactome database using natural language or a direct endpoint; optionally download pathway diagrams.", + "name": "query_reactome", + "optional_parameters": [ + {"name": "endpoint", "type": "str", "description": "Direct endpoint or full URL", "default": None}, + { + "name": "download", + "type": "bool", + "description": "Download pathway diagram if available", + "default": False, + }, + {"name": "output_dir", "type": "str", "description": "Directory to save downloads", "default": None}, + {"name": "verbose", "type": "bool", "description": "Return detailed results", "default": True}, + ], + "required_parameters": [ + { + "name": "prompt", + "type": "str", + "description": "Natural language query about biological pathways", + "default": None, + } + ], + }, + { + "description": "Query the RegulomeDB database using natural language or direct endpoint.", + "name": "query_regulomedb", + "optional_parameters": [ + {"name": "endpoint", "type": "str", "description": "Direct RegulomeDB endpoint URL", "default": None}, + {"name": "verbose", "type": "bool", "description": "Return detailed results", "default": False}, + ], + "required_parameters": [ + { + "name": "prompt", + "type": "str", + "description": "Natural language query about regulatory elements", + "default": None, + } + ], + }, + { + "description": "Query the PRIDE proteomics database using natural language or a direct endpoint.", + "name": "query_pride", + "optional_parameters": [ + {"name": "endpoint", "type": "str", "description": "Full endpoint to query", "default": None}, + {"name": "max_results", "type": "int", "description": "Maximum number of results", "default": 3}, + ], + "required_parameters": [ + { + "name": "prompt", + "type": "str", + "description": "Natural language query about proteomics data", + "default": None, + } + ], + }, + { + "description": "Query the Guide to PHARMACOLOGY (GtoPdb) database using natural language or a direct endpoint.", + "name": "query_gtopdb", + "optional_parameters": [ + {"name": "endpoint", "type": "str", "description": "Full API endpoint to query", "default": None}, + {"name": "verbose", "type": "bool", "description": "Return detailed results", "default": True}, + ], + "required_parameters": [ + { + "name": "prompt", + "type": "str", + "description": "Natural language query about drug targets/ligands/interactions", + "default": None, + } + ], + }, + { + "description": "Query the ReMap database for regulatory elements and transcription factor binding.", + "name": "query_remap", + "optional_parameters": [ + {"name": "endpoint", "type": "str", "description": "Full API endpoint to query", "default": None}, + {"name": "verbose", "type": "bool", "description": "Return detailed results", "default": True}, + ], + "required_parameters": [ + { + "name": "prompt", + "type": "str", + "description": "Natural language query about TF binding sites", + "default": None, + } + ], + }, + { + "description": "Query the Mouse Phenome Database (MPD) using natural language or a direct endpoint.", + "name": "query_mpd", + "optional_parameters": [ + {"name": "endpoint", "type": "str", "description": "Full API endpoint to query", "default": None}, + {"name": "verbose", "type": "bool", "description": "Return detailed results", "default": True}, + ], + "required_parameters": [ + { + "name": "prompt", + "type": "str", + "description": "Natural language query about mouse phenotypes/strains", + "default": None, + } + ], + }, + { + "description": "Query the Electron Microscopy Data Bank (EMDB) using natural language or a direct endpoint.", + "name": "query_emdb", + "optional_parameters": [ + {"name": "endpoint", "type": "str", "description": "Full API endpoint to query", "default": None}, + {"name": "verbose", "type": "bool", "description": "Return detailed results", "default": True}, + ], + "required_parameters": [ + { + "name": "prompt", + "type": "str", + "description": "Natural language query about EM structures", + "default": None, + } + ], + }, + { + "description": "Query Synapse REST API for biomedical datasets/files using natural language or structured search parameters. Supports optional authentication via SYNAPSE_AUTH_TOKEN.", + "name": "query_synapse", + "optional_parameters": [ + { + "name": "query_term", + "type": "str|list[str]", + "description": "Search term(s) (AND logic across list)", + "default": None, + }, + { + "name": "return_fields", + "type": "list[str]", + "description": "Fields to return", + "default": ["name", "node_type", "description"], + }, + {"name": "max_results", "type": "int", "description": "Max results (20 typical, up to 50)", "default": 20}, + { + "name": "query_type", + "type": "str", + "description": "'dataset', 'file', or 'folder'", + "default": "dataset", + }, + { + "name": "verbose", + "type": "bool", + "description": "Return full API response or formatted", + "default": True, + }, + ], + "required_parameters": [ + { + "name": "prompt", + "type": "str", + "description": "Natural language query about biomedical data", + "default": None, + } + ], + }, + { + "description": "Query the PubChem PUG-REST API using natural language or a direct endpoint.", + "name": "query_pubchem", + "optional_parameters": [ + { + "name": "endpoint", + "type": "str", + "description": "Direct PubChem API endpoint or full URL", + "default": None, + }, + {"name": "max_results", "type": "int", "description": "Max results (rate-limited to 5 rps)", "default": 5}, + {"name": "verbose", "type": "bool", "description": "Return detailed results", "default": True}, + ], + "required_parameters": [ + { + "name": "prompt", + "type": "str", + "description": "Natural language query about chemical compounds", + "default": None, + } + ], + }, + { + "description": "Query the ChEMBL REST API via natural language, direct endpoint, or identifiers (chembl_id, smiles, molecule_name).", + "name": "query_chembl", + "optional_parameters": [ + { + "name": "endpoint", + "type": "str", + "description": "Direct ChEMBL API endpoint or full URL", + "default": None, + }, + {"name": "chembl_id", "type": "str", "description": "ChEMBL ID (e.g., 'CHEMBL25')", "default": None}, + {"name": "smiles", "type": "str", "description": "SMILES for similarity/substructure", "default": None}, + {"name": "molecule_name", "type": "str", "description": "Molecule name to search", "default": None}, + {"name": "max_results", "type": "int", "description": "Max results", "default": 20}, + {"name": "verbose", "type": "bool", "description": "Return detailed results", "default": True}, + ], + "required_parameters": [ + { + "name": "prompt", + "type": "str", + "description": "Natural language query about bioactivity data", + "default": None, + } + ], + }, + { + "description": "Query the UniChem 2.0 REST API using natural language or a direct endpoint.", + "name": "query_unichem", + "optional_parameters": [ + {"name": "endpoint", "type": "str", "description": "Direct UniChem endpoint or full URL", "default": None}, + {"name": "verbose", "type": "bool", "description": "Return detailed results", "default": True}, + ], + "required_parameters": [ + { + "name": "prompt", + "type": "str", + "description": "Natural language query about chemical cross-references", + "default": None, + } + ], + }, + { + "description": "Query the ClinicalTrials.gov API v2 using natural language or a direct endpoint.", + "name": "query_clinicaltrials", + "optional_parameters": [ + { + "name": "endpoint", + "type": "str", + "description": "Direct ClinicalTrials.gov endpoint or full URL", + "default": None, + }, + {"name": "max_results", "type": "int", "description": "Page size for results (pageSize)", "default": 10}, + {"name": "verbose", "type": "bool", "description": "Return detailed results", "default": True}, + ], + "required_parameters": [ + { + "name": "prompt", + "type": "str", + "description": "Natural language query about clinical trials", + "default": None, + } + ], + }, + { + "description": "Query the DailyMed RESTful API using natural language or a direct endpoint.", + "name": "query_dailymed", + "optional_parameters": [ + {"name": "endpoint", "type": "str", "description": "Direct DailyMed endpoint or full URL", "default": None}, + {"name": "format", "type": "str", "description": "'json' or 'xml'", "default": "json"}, + {"name": "verbose", "type": "bool", "description": "Return detailed results", "default": True}, + ], + "required_parameters": [ + { + "name": "prompt", + "type": "str", + "description": "Natural language query about drug labeling", + "default": None, + } + ], + }, + { + "description": "Query the QuickGO API using natural language or a direct endpoint.", + "name": "query_quickgo", + "optional_parameters": [ + {"name": "endpoint", "type": "str", "description": "Direct QuickGO endpoint or full URL", "default": None}, + {"name": "max_results", "type": "int", "description": "Max results (limit, up to 100)", "default": 25}, + {"name": "verbose", "type": "bool", "description": "Return detailed results", "default": True}, + ], + "required_parameters": [ + { + "name": "prompt", + "type": "str", + "description": "Natural language query about GO terms/annotations", + "default": None, + } + ], + }, + { + "description": "Query the ENCODE Portal API to locate functional genomics data (experiments, files, biosamples, datasets).", + "name": "query_encode", + "optional_parameters": [ + { + "name": "endpoint", + "type": "str", + "description": "Direct ENCODE Portal endpoint or full URL", + "default": None, + }, + { + "name": "max_results", + "type": "int|str", + "description": "Limit for search endpoints (number or 'all')", + "default": 25, + }, + {"name": "verbose", "type": "bool", "description": "Return detailed results", "default": True}, + ], + "required_parameters": [ + { + "name": "prompt", + "type": "str", + "description": "Natural language query about functional genomics data", + "default": None, + } + ], + }, + { + "description": "Given genomic coordinates, retrieve intersecting ENCODE SCREEN cCREs.", + "name": "region_to_ccre_screen", + "optional_parameters": [ + {"name": "assembly", "type": "str", "description": "Genome assembly (e.g., 'GRCh38')", "default": "GRCh38"} + ], + "required_parameters": [ + {"name": "coord_chrom", "type": "str", "description": "Chromosome (e.g., 'chr12')", "default": None}, + {"name": "coord_start", "type": "int", "description": "Start coordinate", "default": None}, + {"name": "coord_end", "type": "int", "description": "End coordinate", "default": None}, + ], + }, + { + "description": "Given a cCRE accession, return k nearest genes sorted by distance.", + "name": "get_genes_near_ccre", + "optional_parameters": [ + {"name": "k", "type": "int", "description": "Number of nearby genes to return", "default": 10} + ], + "required_parameters": [ + { + "name": "accession", + "type": "str", + "description": "ENCODE cCRE accession ID (e.g., 'EH38E1516980')", + "default": None, + }, + {"name": "assembly", "type": "str", "description": "Genome assembly (e.g., 'GRCh38')", "default": None}, + { + "name": "chromosome", + "type": "str", + "description": "Chromosome of the cCRE (e.g., 'chr12')", + "default": None, + }, + ], + }, +] diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/genetics.py b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/genetics.py new file mode 100644 index 0000000000000000000000000000000000000000..3115043d6d7d10eb194c33d2abf81a1c5ee19325 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/genetics.py @@ -0,0 +1,405 @@ +description = [ + { + "description": "Perform liftover of genomic coordinates between hg19 and " + "hg38 formats with detailed intermediate steps.", + "name": "liftover_coordinates", + "optional_parameters": [], + "required_parameters": [ + { + "default": None, + "description": "Chromosome number (e.g., '1', 'X')", + "name": "chromosome", + "type": "str", + }, + { + "default": None, + "description": "Genomic position", + "name": "position", + "type": "int", + }, + { + "default": None, + "description": "Input genome build ('hg19' or 'hg38')", + "name": "input_format", + "type": "str", + }, + { + "default": None, + "description": "Output genome build ('hg19' or 'hg38')", + "name": "output_format", + "type": "str", + }, + { + "default": None, + "description": "Path to liftover chain files", + "name": "data_path", + "type": "str", + }, + ], + }, + { + "description": "Performs Bayesian fine-mapping from GWAS summary statistics " + "using deep variational inference to compute posterior " + "inclusion probabilities and credible sets for putative " + "causal variants.", + "name": "bayesian_finemapping_with_deep_vi", + "optional_parameters": [ + { + "default": 5000, + "description": "Number of training iterations for the variational inference algorithm", + "name": "n_iterations", + "type": "int", + }, + { + "default": 0.01, + "description": "Learning rate for the optimization algorithm", + "name": "learning_rate", + "type": "float", + }, + { + "default": 64, + "description": "Hidden dimension size for the neural network", + "name": "hidden_dim", + "type": "int", + }, + { + "default": 0.95, + "description": "Threshold for defining the credible set (e.g., 0.95 for a 95% credible set)", + "name": "credible_threshold", + "type": "float", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to CSV or TSV file containing " + "GWAS summary statistics with " + "variant_id, effect_size, pvalue, " + "and optional se columns", + "name": "gwas_summary_path", + "type": "str", + }, + { + "default": None, + "description": "Linkage disequilibrium matrix with pairwise correlations between variants", + "name": "ld_matrix", + "type": "numpy.ndarray", + }, + ], + }, + { + "description": "Analyzes and categorizes mutations induced by Cas9 at target sites.", + "name": "analyze_cas9_mutation_outcomes", + "optional_parameters": [ + { + "default": None, + "description": "Dictionary mapping sequence IDs to " + "cell line information (e.g., " + "wildtype, knockout gene)", + "name": "cell_line_info", + "type": "dict", + }, + { + "default": "cas9_mutation_analysis", + "description": "Prefix for output files", + "name": "output_prefix", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Dictionary mapping sequence IDs to reference DNA sequences (strings)", + "name": "reference_sequences", + "type": "dict", + }, + { + "default": None, + "description": "Nested dictionary: {sequence_id: " + "{read_id: sequence}} containing the " + "edited/mutated sequences for each " + "reference", + "name": "edited_sequences", + "type": "dict", + }, + ], + }, + { + "description": "Analyzes CRISPR-Cas9 genome editing results by comparing original and edited sequences.", + "name": "analyze_crispr_genome_editing", + "optional_parameters": [ + { + "default": None, + "description": "The homology-directed repair template sequence, if used", + "name": "repair_template", + "type": "str", + } + ], + "required_parameters": [ + { + "default": None, + "description": "The original DNA sequence before CRISPR-Cas9 editing", + "name": "original_sequence", + "type": "str", + }, + { + "default": None, + "description": "The DNA sequence after CRISPR-Cas9 editing", + "name": "edited_sequence", + "type": "str", + }, + { + "default": None, + "description": "The CRISPR guide RNA (crRNA) sequence used for targeting", + "name": "guide_rna", + "type": "str", + }, + ], + }, + { + "description": "Simulate DNA sequences with specified demographic and coalescent histories using msprime.", + "name": "simulate_demographic_history", + "optional_parameters": [ + { + "default": 10, + "description": "Number of sample sequences to simulate", + "name": "num_samples", + "type": "int", + }, + { + "default": 100000, + "description": "Length of the simulated sequence in base pairs", + "name": "sequence_length", + "type": "int", + }, + { + "default": 1e-08, + "description": "Per-base recombination rate", + "name": "recombination_rate", + "type": "float", + }, + { + "default": 1e-08, + "description": "Per-base mutation rate", + "name": "mutation_rate", + "type": "float", + }, + { + "default": "constant", + "description": "Type of demographic model to " + "simulate (constant, bottleneck, " + "expansion, contraction, sawtooth)", + "name": "demographic_model", + "type": "str", + }, + { + "default": None, + "description": "Parameters specific to the chosen demographic model", + "name": "demographic_params", + "type": "dict", + }, + { + "default": "kingman", + "description": "Type of coalescent model to use (kingman, beta)", + "name": "coalescent_model", + "type": "str", + }, + { + "default": None, + "description": "Parameter for beta-coalescent model", + "name": "beta_coalescent_param", + "type": "float", + }, + { + "default": None, + "description": "Seed for random number generator", + "name": "random_seed", + "type": "int", + }, + { + "default": "simulated_sequences.vcf", + "description": "Filename to save the simulated sequences in VCF format", + "name": "output_file", + "type": "str", + }, + ], + "required_parameters": [], + }, + { + "description": "Identifies binding sites for a specific transcription factor in a genomic sequence.", + "name": "identify_transcription_factor_binding_sites", + "optional_parameters": [ + { + "default": 0.8, + "description": "Minimum score threshold for reporting binding sites (0.0-1.0)", + "name": "threshold", + "type": "float", + }, + { + "default": None, + "description": "Path to save the results", + "name": "output_file", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "The genomic DNA sequence to analyze", + "name": "sequence", + "type": "str", + }, + { + "default": None, + "description": "Name of the transcription factor to search for (e.g., 'Hsf1', 'GATA1')", + "name": "tf_name", + "type": "str", + }, + ], + }, + { + "description": "Fit a linear mixed model for genomic prediction using genotype and phenotype data.", + "name": "fit_genomic_prediction_model", + "optional_parameters": [ + { + "default": None, + "description": "Matrix of fixed effects (e.g., " + "environment, management), with " + "individuals in rows and effects in " + "columns.", + "name": "fixed_effects", + "type": "numpy.ndarray", + }, + { + "default": "additive", + "description": 'Type of genetic model to fit: "additive" or "additive_dominance".', + "name": "model_type", + "type": "str", + }, + { + "default": "genomic_prediction_results.csv", + "description": "File name to save the results.", + "name": "output_file", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Matrix of genotype data, with " + "individuals in rows and markers in " + "columns. Values are typically coded " + "as 0, 1, 2 for additive models or " + "with specific encoding for " + "dominance effects.", + "name": "genotypes", + "type": "numpy.ndarray", + }, + { + "default": None, + "description": "Vector or matrix of phenotype data, with individuals in rows and traits in columns.", + "name": "phenotypes", + "type": "numpy.ndarray", + }, + ], + }, + { + "description": "Performs PCR amplification of a target transgene and " + "visualizes results using agarose gel electrophoresis.", + "name": "perform_pcr_and_gel_electrophoresis", + "optional_parameters": [ + { + "default": None, + "description": "Forward primer sequence. If not provided, will be designed based on target_region", + "name": "forward_primer", + "type": "str", + }, + { + "default": None, + "description": "Reverse primer sequence. If not provided, will be designed based on target_region", + "name": "reverse_primer", + "type": "str", + }, + { + "default": None, + "description": "Tuple of (start, end) positions for the target region in the genomic DNA", + "name": "target_region", + "type": "tuple", + }, + { + "default": 58, + "description": "Annealing temperature for PCR in °C", + "name": "annealing_temp", + "type": "float", + }, + { + "default": 30, + "description": "Extension time in seconds", + "name": "extension_time", + "type": "int", + }, + { + "default": 35, + "description": "Number of PCR cycles", + "name": "cycles", + "type": "int", + }, + { + "default": 2.0, + "description": "Percentage of agarose gel", + "name": "gel_percentage", + "type": "float", + }, + { + "default": "pcr_result", + "description": "Prefix for output files", + "name": "output_prefix", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to file containing genomic DNA sequence in FASTA format or the sequence itself", + "name": "genomic_dna", + "type": "str", + } + ], + }, + { + "description": "Perform phylogenetic analysis on a set of protein sequences. " + "This function aligns sequences, constructs a phylogenetic " + "tree, and visualizes evolutionary relationships.", + "name": "analyze_protein_phylogeny", + "optional_parameters": [ + { + "default": "./", + "description": "Directory to save output files", + "name": "output_dir", + "type": "str", + }, + { + "default": "clustalw", + "description": 'Method for sequence alignment: "clustalw", "muscle", or "pre-aligned"', + "name": "alignment_method", + "type": "str", + }, + { + "default": "fasttree", + "description": 'Method for tree construction: "iqtree" or fallback to neighbor-joining', + "name": "tree_method", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to a FASTA file containing " + "protein sequences or a string with " + "FASTA-formatted sequences", + "name": "fasta_sequences", + "type": "str", + } + ], + }, +] diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/genomics.py b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/genomics.py new file mode 100644 index 0000000000000000000000000000000000000000..787ff80a16d92f8428fab16a0736702df228b811 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/genomics.py @@ -0,0 +1,840 @@ +description = [ + { + "description": "Annotate cell types based on gene markers and transferred " + "labels using LLM. After leiden clustering, annotate clusters " + "using differentially expressed genes and optionally " + "incorporate transferred labels from reference datasets.", + "name": "annotate_celltype_scRNA", + "optional_parameters": [ + { + "default": "leiden", + "description": "Clustering method to use for cell type annotation", + "name": "cluster", + "type": "str", + }, + { + "default": "claude-3-5-sonnet-20241022", + "description": "Language model instance for cell type prediction", + "name": "llm", + "type": "str", + }, + { + "default": None, + "description": "Transferred cell type composition for each cluster", + "name": "composition", + "type": "pd.DataFrame", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Name of the AnnData file containing scRNA-seq data", + "name": "adata_filename", + "type": "str", + }, + { + "default": None, + "description": "Directory containing the data files", + "name": "data_dir", + "type": "str", + }, + { + "default": None, + "description": 'Information about the scRNA-seq data (e.g., "homo sapiens, brain tissue, normal")', + "name": "data_info", + "type": "str", + }, + { + "default": None, + "description": "Path to the data lake", + "name": "data_lake_path", + "type": "str", + }, + ], + }, + { + "description": "Perform cell type annotation of single-cell RNA-seq data using Panhuman Azimuth Neural Network. " + "This function implements the Panhuman Azimuth workflow for cell type annotation using the " + "panhumanpy package, providing hierarchical cell type labels for tissues across the human body. ", + "name": "annotate_celltype_with_panhumanpy", + "optional_parameters": [ + { + "default": None, + "description": "Column name in adata.var containing gene symbols (default: None, uses index)", + "name": "feature_names_col", + "type": "str", + }, + { + "default": True, + "description": "Whether to perform additional label refinement for consistent granularity", + "name": "refine", + "type": "bool", + }, + { + "default": True, + "description": "Whether to generate ANN embeddings and UMAP", + "name": "umap", + "type": "bool", + }, + { + "default": "./output", + "description": "Directory to save results", + "name": "output_dir", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to the AnnData file containing scRNA-seq data", + "name": "adata_path", + "type": "str", + }, + ], + }, + { + "description": "Create scVI and scANVI embeddings for single-cell RNA-seq " + "data, saving the results to an AnnData object.", + "name": "create_scvi_embeddings_scRNA", + "optional_parameters": [], + "required_parameters": [ + { + "default": None, + "description": "Filename of the AnnData object to load", + "name": "adata_filename", + "type": "str", + }, + { + "default": None, + "description": "Column name in adata.obs for batch information", + "name": "batch_key", + "type": "str", + }, + { + "default": None, + "description": "Column name in adata.obs for cell type labels", + "name": "label_key", + "type": "str", + }, + { + "default": None, + "description": "Directory path where the AnnData file is located and where output will be saved", + "name": "data_dir", + "type": "str", + }, + ], + }, + { + "description": "Performs batch integration on single-cell RNA-seq data using " + "Harmony and saves the integrated embeddings.", + "name": "create_harmony_embeddings_scRNA", + "optional_parameters": [], + "required_parameters": [ + { + "default": None, + "description": "Filename of the AnnData object to load", + "name": "adata_filename", + "type": "str", + }, + { + "default": None, + "description": "Column name in adata.obs that defines the batch variable for integration", + "name": "batch_key", + "type": "str", + }, + { + "default": None, + "description": "Directory path where the input file is located and output will be saved", + "name": "data_dir", + "type": "str", + }, + ], + }, + { + "description": "Generate UCE embeddings for single-cell RNA-seq data and map " + "them to a reference dataset for cell type annotation.", + "name": "get_uce_embeddings_scRNA", + "optional_parameters": [ + { + "default": "/dfs/project/bioagentos/data/singlecell/", + "description": "Root directory for single-cell data storage", + "name": "DATA_ROOT", + "type": "str", + }, + { + "default": None, + "description": "Custom command line arguments to pass to the UCE script", + "name": "custom_args", + "type": "List[str]", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Filename of the AnnData object to process", + "name": "adata_filename", + "type": "str", + }, + { + "default": None, + "description": "Directory where the input data is stored and output will be saved", + "name": "data_dir", + "type": "str", + }, + ], + }, + { + "description": "Map cell embeddings from the input dataset to the Integrated " + "Megascale Atlas reference dataset using UCE embeddings.", + "name": "map_to_ima_interpret_scRNA", + "optional_parameters": [ + { + "default": None, + "description": "Dictionary of custom arguments " + "including 'n_neighbors' and " + "'metric' for nearest neighbor " + "search", + "name": "custom_args", + "type": "dict", + } + ], + "required_parameters": [ + { + "default": None, + "description": "Filename of the AnnData object to be mapped", + "name": "adata_filename", + "type": "str", + }, + { + "default": None, + "description": "Directory containing the AnnData file", + "name": "data_dir", + "type": "str", + }, + ], + }, + { + "description": "Given a gene name, fetch RNA-seq expression data showing the " + "top K tissues with highest transcripts-per-million (TPM) " + "values.", + "name": "get_rna_seq_archs4", + "optional_parameters": [ + { + "default": 10, + "description": "The number of tissues to return", + "name": "K", + "type": "int", + } + ], + "required_parameters": [ + { + "default": None, + "description": "The gene name for which RNA-seq data is being fetched", + "name": "gene_name", + "type": "str", + } + ], + }, + { + "description": "Returns a list of supported databases for gene set enrichment analysis.", + "name": "get_gene_set_enrichment_analysis_supported_database_list", + "optional_parameters": [], + "required_parameters": [], + }, + { + "description": "Perform enrichment analysis for a list of genes, with " + "optional background gene set and plotting functionality.", + "name": "gene_set_enrichment_analysis", + "optional_parameters": [ + { + "default": 10, + "description": "Number of top pathways to return", + "name": "top_k", + "type": "int", + }, + { + "default": "ontology", + "description": "Database to use for enrichment analysis (e.g., pathway, transcription, ontology)", + "name": "database", + "type": "str", + }, + { + "default": None, + "description": "List of background genes to use for enrichment analysis", + "name": "background_list", + "type": "list", + }, + { + "default": False, + "description": "Generate a bar plot of the top K enrichment results", + "name": "plot", + "type": "bool", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "List of gene symbols to analyze", + "name": "genes", + "type": "list", + } + ], + }, + { + "description": "Analyze chromatin interactions from Hi-C data to identify " + "enhancer-promoter interactions and TADs.", + "name": "analyze_chromatin_interactions", + "optional_parameters": [ + { + "default": "./output", + "description": "Directory to save output files", + "name": "output_dir", + "type": "str", + } + ], + "required_parameters": [ + { + "default": None, + "description": "Path to the Hi-C data file (.cool or .hic format)", + "name": "hic_file_path", + "type": "str", + }, + { + "default": None, + "description": "Path to BED file containing genomic " + "coordinates of regulatory elements " + "(enhancers, promoters, CTCF sites, " + "etc.)", + "name": "regulatory_elements_bed", + "type": "str", + }, + ], + }, + { + "description": "Perform comparative genomics and haplotype analysis on " + "multiple genome samples. Aligns genome samples to a " + "reference, identifies variants, analyzes shared and unique " + "genomic regions, and determines haplotype structure.", + "name": "analyze_comparative_genomics_and_haplotypes", + "optional_parameters": [ + { + "default": "./output", + "description": "Directory to store output files", + "name": "output_dir", + "type": "str", + } + ], + "required_parameters": [ + { + "default": None, + "description": "Paths to FASTA files containing whole-genome sequences to be analyzed", + "name": "sample_fasta_files", + "type": "List[str]", + }, + { + "default": None, + "description": "Path to the reference genome FASTA file", + "name": "reference_genome_path", + "type": "str", + }, + ], + }, + { + "description": "Perform ChIP-seq peak calling using MACS2 to identify " + "genomic regions with significant binding.", + "name": "perform_chipseq_peak_calling_with_macs2", + "optional_parameters": [ + { + "default": "macs2_output", + "description": "Prefix for output files", + "name": "output_name", + "type": "str", + }, + { + "default": "hs", + "description": "Effective genome size shorthand: 'hs' for human, 'mm' for mouse, etc.", + "name": "genome_size", + "type": "str", + }, + { + "default": 0.05, + "description": "q-value (minimum FDR) cutoff for peak calling", + "name": "q_value", + "type": "float", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to the ChIP-seq read data file (BAM, BED, or other supported format)", + "name": "chip_seq_file", + "type": "str", + }, + { + "default": None, + "description": "Path to the control/input data file (BAM, BED, or other supported format)", + "name": "control_file", + "type": "str", + }, + ], + }, + { + "description": "Find DNA sequence motifs enriched in genomic regions using the HOMER motif discovery software.", + "name": "find_enriched_motifs_with_homer", + "optional_parameters": [ + { + "default": "hg38", + "description": "Reference genome for sequence extraction", + "name": "genome", + "type": "str", + }, + { + "default": None, + "description": "Path to BED file with background " + "regions for comparison. If None, " + "HOMER will generate random " + "background sequences automatically", + "name": "background_file", + "type": "str", + }, + { + "default": "8,10,12", + "description": "Comma-separated list of motif lengths to discover", + "name": "motif_length", + "type": "str", + }, + { + "default": "./homer_motifs", + "description": "Directory to save output files", + "name": "output_dir", + "type": "str", + }, + { + "default": 10, + "description": "Number of motifs to find", + "name": "num_motifs", + "type": "int", + }, + { + "default": 4, + "description": "Number of CPU threads to use", + "name": "threads", + "type": "int", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to peak file in BED format " + "containing genomic regions to " + "analyze for motif enrichment", + "name": "peak_file", + "type": "str", + } + ], + }, + { + "description": "Analyze overlaps between two or more sets of genomic regions.", + "name": "analyze_genomic_region_overlap", + "optional_parameters": [ + { + "default": "overlap_analysis", + "description": "Prefix for output files", + "name": "output_prefix", + "type": "str", + } + ], + "required_parameters": [ + { + "default": None, + "description": "List of genomic region sets. Each " + "item can be either a string path to " + "a BED file or a list of " + "tuples/lists with format (chrom, " + "start, end) or (chrom, start, end, " + "name)", + "name": "region_sets", + "type": "list", + } + ], + }, + { + "description": "Transfer cell type labels from an annotated reference scRNA-seq dataset to an unannotated query dataset using popV. Loads both AnnData .h5ad files, prepares count layers for scVI, processes the query against the reference, and runs selected annotation methods (default: SCANVI_POPV). Saves predictions to 'output_folder/popv_output/predictions.csv'. This function allows you to use different annotaiton methods i.e. CELLTYPIST, KNN_BBKNN, KNN_HARMONY, KNN_SCANORAMA, KNN_SCVI, ONCLASS, Random_Forest, SCANVI_POPV, Support_Vector, XGboost. Based on you transfer task you can select the multiple best annotation methods. Beware each annotation method adds computational requirements for running the tool. By default it uses SCANVI_POPV method.", + "name": "unsupervised_celltype_transfer_between_scRNA_datasets", + "optional_parameters": [ + { + "default": None, + "description": "Column in query adata.obs with batch information, most likely you will get this from user", + "name": "query_batch_key", + "type": "str", + }, + { + "default": None, + "description": "Column in reference adata.obs with batch information, most likely you will get this from user", + "name": "ref_batch_key", + "type": "str", + }, + { + "default": False, + "description": "Enable CELLTYPiST (reference-based classifier). How it works: regularized logistic regression trained on curated references predicts per-cell probabilities; optional neighbor correction refines labels. Strengths: fast, scalable, strong on common human/mouse types. Weaknesses: depends on reference coverage; limited for novel or out-of-distribution cell types.", + "name": "CELLTYPIST", + "type": "bool", + }, + { + "default": False, + "description": "Enable KNN with BBKNN integration. How it works: builds a batch-balanced kNN graph by enforcing a fixed number of neighbors per batch, then uses this graph for downstream analyses. Strengths: simple, fast, preserves local neighborhood structure across batches. Weaknesses: limited global alignment; residual batch effects when shared cell types are sparse; sensitive to k/neighbor parameters.", + "name": "KNN_BBKNN", + "type": "bool", + }, + { + "default": False, + "description": "Enable KNN with Harmony integration. How it works: iteratively adjusts PCA embeddings via soft clustering and linear correction to minimize batch effects while preserving structure. Strengths: scalable, effective batch correction in low-D space, often preserves biology. Weaknesses: can overcorrect and merge true biological differences; depends on PCA/parameters.", + "name": "KNN_HARMONY", + "type": "bool", + }, + { + "default": False, + "description": "Enable KNN with Scanorama integration. How it works: identifies mutual nearest neighbors across datasets and performs manifold alignment/low-rank correction to merge 'panoramas'. Strengths: strong cross-dataset alignment for shared populations. Weaknesses: slower and more memory-intensive on large data; may distort rare or unique populations.", + "name": "KNN_SCANORAMA", + "type": "bool", + }, + { + "default": False, + "description": "Enable KNN with scVI integration (KNN in scVI latent space). How it works: trains a variational autoencoder (negative binomial likelihood) to learn a batch-corrected latent space; runs KNN in this space to transfer labels. Strengths: robust probabilistic embedding that models counts and batch; good transfer performance. Weaknesses: requires training (GPU preferred); sensitive to embedding quality and k.", + "name": "KNN_SCVI", + "type": "bool", + }, + { + "default": False, + "description": "Enable OnClass (ontology-aware classifier). How it works: embeds the Cell Ontology graph and trains a classifier over ontology nodes; uses semantic similarity to generalize to unseen labels (zero-shot). Strengths: leverages Cell Ontology; can map to unseen/fine-grained types; interpretable. Weaknesses: dependent on ontology completeness and mapping quality; may assign overly generic labels.", + "name": "ONCLASS", + "type": "bool", + }, + { + "default": False, + "description": "Enable Random Forest classifier. How it works: ensemble of decision trees trained on bootstrap samples with feature subsampling; predictions aggregated by majority vote/probabilities. Strengths: robust to noise and nonlinear signals; quick to train; feature importance available. Weaknesses: probability calibration can be poor; needs feature selection with sparse data; sensitive to class imbalance.", + "name": "Random_Forest", + "type": "bool", + }, + { + "default": True, + "description": "Enable scANVI via popV (default). How it works: extends scVI with a classification head to learn from labeled reference and unlabeled query (semi-supervised), yielding latent embeddings and probabilistic labels with uncertainty. Strengths: semi-supervised; models batch, label noise; leverages unlabeled data; provides uncertainty. Weaknesses: higher training time; GPU recommended; can degrade with severe label shift or noisy references.", + "name": "SCANVI_POPV", + "type": "bool", + }, + { + "default": False, + "description": "Enable Support Vector classifier. How it works: finds a maximum-margin hyperplane; with kernels (e.g., RBF) to model nonlinear boundaries. Strengths: effective in high-dimensional, small-sample settings; kernel flexibility. Weaknesses: hyperparameter tuning needed; not probabilistic by default; scales poorly to very large datasets.", + "name": "Support_Vector", + "type": "bool", + }, + { + "default": False, + "description": "Enable XGBoost classifier. How it works: gradient-boosted decision trees trained sequentially with second-order optimization and regularization to minimize loss. Strengths: high accuracy; captures nonlinear interactions; built-in regularization. Weaknesses: many hyperparameters; risk of overfitting noisy, sparse counts; less interpretable.", + "name": "XGboost", + "type": "bool", + }, + { + "default": 1, + "description": "Number of parallel jobs for popV", + "name": "n_jobs", + "type": "int", + }, + { + "default": "./tmp/", + "description": "Directory to save trained models and predictions", + "name": "output_folder", + "type": "str", + }, + { + "default": 10, + "description": "Number of samples per label (currently unused)", + "name": "n_samples_per_label", + "type": "int", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to annotated reference AnnData (.h5ad)", + "name": "path_to_annotated_h5ad", + "type": "str", + }, + { + "default": None, + "description": "Path to unannotated query AnnData (.h5ad)", + "name": "path_to_not_annotated_h5ad", + "type": "str", + }, + { + "default": None, + "description": "Column in reference adata.obs with cell type labels", + "name": "ref_labels_key", + "type": "str", + }, + ], + }, + { + "description": "Generate State embeddings for single-cell RNA-seq data using the SE-600M model. " + "This function downloads the SE-600M model from Hugging Face, installs required dependencies " + "(git-lfs, uv, arc-state), and generates embeddings for the input AnnData object. " + "The SE-600M model is a state-of-the-art embedding model for single-cell data that can capture " + "complex biological patterns and cell states. Features include real-time streaming output, " + "automatic retry with reduced batch size on failure, GPU detection and warnings, and input validation.", + "name": "generate_embeddings_with_state", + "optional_parameters": [ + { + "default": None, + "description": "Name of the output embeddings file. If None, will use input filename with '_state_embeddings' suffix", + "name": "output_filename", + "type": "str", + }, + { + "default": None, + "description": "Path to the specific model checkpoint. If None, uses the latest checkpoint in model_folder", + "name": "checkpoint", + "type": "str", + }, + { + "default": "X_state", + "description": "Name of key to store embeddings in the output AnnData object", + "name": "embed_key", + "type": "str", + }, + { + "default": None, + "description": "Path to protein embeddings override (.pt). If omitted, auto-detects in model folder", + "name": "protein_embeddings", + "type": "str", + }, + { + "default": 500, + "description": "Batch size for embedding forward pass. Increase to use more VRAM and speed up embedding", + "name": "batch_size", + "type": "int", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Name of the input AnnData file (.h5ad format)", + "name": "adata_filename", + "type": "str", + }, + { + "default": None, + "description": "Directory containing the input data file", + "name": "data_dir", + "type": "str", + }, + { + "default": None, + "description": "Directory where the SE-600M model will be downloaded and stored", + "name": "model_folder", + "type": "str", + }, + ], + }, + { + "description": "Convert ENSEMBL gene IDs between different species using BioMart homology mapping. " + "This function converts a list of ENSEMBL gene IDs from one species to their " + "homologous counterparts in another species using the Ensembl BioMart database. " + "The conversion is based on one-to-one ortholog mappings between species.", + "name": "interspecies_gene_conversion", + "optional_parameters": [], + "required_parameters": [ + { + "default": None, + "description": "List of ENSEMBL gene IDs to convert (e.g., ['ENSG00000007372', 'ENSG00000181449'])", + "name": "gene_list", + "type": "list[str]", + }, + { + "default": None, + "description": "Source species name. Supported species: human, mouse, rat, zebrafish, fly, " + "drosophila, worm, yeast, chicken, pig, cow, dog, macaque", + "name": "source_species", + "type": "str", + }, + { + "default": None, + "description": "Target species name. Same supported species as source_species", + "name": "target_species", + "type": "str", + }, + ], + }, + { + "description": "Generate average protein embeddings for a list of Ensembl gene IDs using ESM (Evolutionary Scale Modeling) " + "protein language models. This function fetches all protein isoform sequences for each gene, " + "computes embeddings for each isoform using the specified ESM model and layer, then averages " + "the embeddings across all isoforms to create a single representative embedding per gene. " + "The embeddings are saved as PyTorch tensors for future use. " + "Memory-friendly implementation with rolling averages, small batch processing, and automatic memory " + "management. Automatically handles GPU/CPU device selection and includes error recovery for out-of-memory " + "situations by falling back to single-sequence processing.", + "name": "generate_gene_embeddings_with_ESM_models", + "optional_parameters": [ + { + "default": "esm2_t6_8M_UR50D", + "description": "ESM model name to use for generating embeddings", + "name": "model_name", + "type": "str", + }, + { + "default": 6, + "description": "Which layer of the ESM model to extract embeddings from, generally use last layer", + "name": "layer", + "type": "int", + }, + { + "default": None, + "description": "Optional path to save embeddings as PyTorch dictionary", + "name": "save_path", + "type": "str", + }, + { + "default": 1, + "description": "Number of sequences to process at once to manage memory usage", + "name": "batch_size", + "type": "int", + }, + { + "default": 1024, + "description": "Maximum sequence length to process, longer sequences are filtered out", + "name": "max_sequence_length", + "type": "int", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "List of Ensembl gene IDs (e.g., ['ENSG00000012048', 'ENSG00000012049'])", + "name": "ensembl_gene_ids", + "type": "List[str]", + } + ], + }, + { + "description": "Generate Transcriptformer embeddings for single-cell RNA-seq data. " + "This function downloads model checkpoints, prepares the AnnData object with required fields " + "(ensembl_id, raw counts, assay metadata), and runs inference to generate cell or gene embeddings. " + "Transcriptformer is a transformer-based model that can learn rich representations of " + "single-cell gene expression data. The function automatically handles Ensembl ID pattern " + "detection, model downloading, data preprocessing, and creates missing assay metadata columns " + "with 'unknown' values if needed.", + "name": "generate_transcriptformer_embeddings", + "optional_parameters": [ + { + "default": None, + "description": "Name of the output embeddings file. If None, will use input filename with '_transcriptformer_embeddings' suffix", + "name": "output_filename", + "type": "str", + }, + { + "default": "tf-sapiens", + "description": "Type of transcriptformer model to download and use. Options: 'tf-sapiens', 'tf-exemplar', 'tf-metazoa'", + "name": "model_type", + "type": "str", + }, + { + "default": None, + "description": "Path to the transcriptformer checkpoint directory. If None, will use './checkpoints/{model_type}'", + "name": "checkpoint_path", + "type": "str", + }, + { + "default": 8, + "description": "Batch size for inference", + "name": "batch_size", + "type": "int", + }, + { + "default": "16-mixed", + "description": "Precision for inference. Options: '16-mixed', '32'", + "name": "precision", + "type": "str", + }, + { + "default": 30, + "description": "Maximum count value to clip to", + "name": "clip_counts", + "type": "int", + }, + { + "default": -1, + "description": "Which layer to extract embeddings from (-1 for last layer)", + "name": "embedding_layer_index", + "type": "int", + }, + { + "default": 1, + "description": "Number of GPUs to use", + "name": "num_gpus", + "type": "int", + }, + { + "default": 0, + "description": "Number of data loading workers", + "name": "n_data_workers", + "type": "int", + }, + { + "default": "ensembl_id", + "description": "Column name in AnnData.var containing gene identifiers", + "name": "gene_col_name", + "type": "str", + }, + { + "default": None, + "description": "Path to pretrained embeddings for out-of-distribution species", + "name": "pretrained_embedding", + "type": "str", + }, + { + "default": True, + "description": "Whether to filter genes to only those in the vocabulary", + "name": "filter_to_vocabs", + "type": "bool", + }, + { + "default": "None", + "description": "Whether to use raw counts from AnnData.raw.X (True), adata.X (False), or auto-detect (None/auto)", + "name": "use_raw", + "type": "str", + }, + { + "default": "cell", + "description": "Type of embeddings to extract: 'cell' for mean-pooled cell embeddings or 'cge' for contextual gene embeddings", + "name": "emb_type", + "type": "str", + }, + { + "default": False, + "description": "Remove duplicate genes if found instead of raising an error", + "name": "remove_duplicate_genes", + "type": "bool", + }, + { + "default": False, + "description": "Use map-style out-of-memory DataLoader (DistributedSampler-friendly)", + "name": "oom_dataloader", + "type": "bool", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Name of the input AnnData file (.h5ad format)", + "name": "adata_filename", + "type": "str", + }, + { + "default": None, + "description": "Directory containing the input data file", + "name": "data_dir", + "type": "str", + }, + ], + }, +] diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/glycoengineering.py b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/glycoengineering.py new file mode 100644 index 0000000000000000000000000000000000000000..a64877c99f94d755e20c135604353c6f5ce33cf3 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/glycoengineering.py @@ -0,0 +1,55 @@ +description = [ + { + "name": "find_n_glycosylation_motifs", + "description": "Scan a protein sequence for canonical N-glycosylation sequons (N-X-[S/T], X≠P). Returns positions and motifs.", + "required_parameters": [ + { + "name": "sequence", + "type": "str", + "description": "Protein sequence (one-letter AA codes)", + "default": None, + } + ], + "optional_parameters": [ + { + "name": "allow_overlap", + "type": "bool", + "description": "Allow overlapping motif detections", + "default": False, + } + ], + }, + { + "name": "predict_o_glycosylation_hotspots", + "description": "Heuristic O-glycosite hotspot prediction using local S/T density (lightweight baseline; see NetOGlyc 4.0 for SOTA).", + "required_parameters": [ + { + "name": "sequence", + "type": "str", + "description": "Protein sequence (one-letter AA codes)", + "default": None, + } + ], + "optional_parameters": [ + {"name": "window", "type": "int", "description": "Odd-sized window for local density (>=3)", "default": 7}, + { + "name": "min_st_fraction", + "type": "float", + "description": "Min S/T fraction in window to flag site", + "default": 0.4, + }, + { + "name": "disallow_proline_next", + "type": "bool", + "description": "Avoid S/T immediately followed by Proline", + "default": True, + }, + ], + }, + { + "name": "list_glycoengineering_resources", + "description": "Curated list of external glycoengineering tools and resources (links and notes) as referenced in issue #198.", + "required_parameters": [], + "optional_parameters": [], + }, +] diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/immunology.py b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/immunology.py new file mode 100644 index 0000000000000000000000000000000000000000..d6ac69d694b4c7deec193f6bd9ba8cdb5e864627 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/immunology.py @@ -0,0 +1,326 @@ +description = [ + { + "description": "Perform ATAC-seq peak calling and differential accessibility analysis using MACS2.", + "name": "analyze_atac_seq_differential_accessibility", + "optional_parameters": [ + { + "default": "./atac_results", + "description": "Directory to save output files", + "name": "output_dir", + "type": "str", + }, + { + "default": "hs", + "description": "Genome size parameter for MACS2", + "name": "genome_size", + "type": "str", + }, + { + "default": 0.05, + "description": "q-value cutoff for peak detection", + "name": "q_value", + "type": "float", + }, + { + "default": "atac", + "description": "Prefix for output file names", + "name": "name_prefix", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to the treatment condition BAM file with aligned ATAC-seq reads", + "name": "treatment_bam", + "type": "str", + }, + { + "default": None, + "description": "Path to the control condition BAM file with aligned ATAC-seq reads", + "name": "control_bam", + "type": "str", + }, + ], + }, + { + "description": "Analyzes bacterial growth curve data to determine growth " + "parameters such as doubling time, growth rate, and lag " + "phase.", + "name": "analyze_bacterial_growth_curve", + "optional_parameters": [ + { + "default": ".", + "description": "Directory where output files will be saved", + "name": "output_dir", + "type": "str", + } + ], + "required_parameters": [ + { + "default": None, + "description": "Time points of measurements in hours", + "name": "time_points", + "type": "List or numpy.ndarray", + }, + { + "default": None, + "description": "Optical density measurements corresponding to each time point", + "name": "od_values", + "type": "List or numpy.ndarray", + }, + { + "default": None, + "description": "Name of the bacterial strain being analyzed", + "name": "strain_name", + "type": "str", + }, + ], + }, + { + "description": "Simulates the isolation and purification of immune cells from tissue samples.", + "name": "isolate_purify_immune_cells", + "optional_parameters": [ + { + "default": "collagenase", + "description": "The enzyme used for tissue digestion", + "name": "enzyme_type", + "type": "str", + }, + { + "default": None, + "description": "Specific antibody for magnetic-assisted cell sorting", + "name": "macs_antibody", + "type": "str", + }, + { + "default": 45, + "description": "Digestion time in minutes", + "name": "digestion_time_min", + "type": "int", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "The type of tissue sample (e.g., 'adipose', 'kidney', 'liver', 'lung', 'spleen')", + "name": "tissue_type", + "type": "str", + }, + { + "default": None, + "description": "The immune cell population to isolate (e.g., 'macrophages', 'leukocytes', 'T cells')", + "name": "target_cell_type", + "type": "str", + }, + ], + }, + { + "description": "Estimate cell cycle phase durations using dual-nucleoside " + "pulse labeling data and mathematical modeling.", + "name": "estimate_cell_cycle_phase_durations", + "optional_parameters": [], + "required_parameters": [ + { + "default": None, + "description": "Dictionary containing experimental " + "data from flow cytometry with EdU " + "and BrdU labeling, including time " + "points and percentages of labeled " + "cells", + "name": "flow_cytometry_data", + "type": "dict", + }, + { + "default": None, + "description": "Initial estimates for cell cycle phase durations and death rates", + "name": "initial_estimates", + "type": "dict", + }, + ], + }, + { + "description": "Track immune cells under flow conditions and classify their behaviors.", + "name": "track_immune_cells_under_flow", + "optional_parameters": [ + { + "default": "./output", + "description": "Directory to save output files", + "name": "output_dir", + "type": "str", + }, + { + "default": 1.0, + "description": "Pixel size in micrometers", + "name": "pixel_size_um", + "type": "float", + }, + { + "default": 1.0, + "description": "Time interval between frames in seconds", + "name": "time_interval_sec", + "type": "float", + }, + { + "default": "right", + "description": "Direction of flow ('right', 'left', 'up', 'down')", + "name": "flow_direction", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to image sequence directory or video file", + "name": "image_sequence_path", + "type": "str", + } + ], + }, + { + "description": "Analyze CFSE-labeled cell samples to quantify cell division and proliferation.", + "name": "analyze_cfse_cell_proliferation", + "optional_parameters": [ + { + "default": "FL1-A", + "description": "Name of the channel containing CFSE fluorescence data", + "name": "cfse_channel", + "type": "str", + }, + { + "default": None, + "description": "Tuple of (min_fsc, max_fsc, min_ssc, max_ssc) for lymphocyte gating", + "name": "lymphocyte_gate", + "type": "tuple or None", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to the FCS file containing flow cytometry data from CFSE-labeled cells", + "name": "fcs_file_path", + "type": "str", + } + ], + }, + { + "description": "Analyze cytokine production (IFN-γ, IL-17) in CD4+ T cells after antigen stimulation.", + "name": "analyze_cytokine_production_in_cd4_tcells", + "optional_parameters": [ + { + "default": "./results", + "description": "Directory to save the results file", + "name": "output_dir", + "type": "str", + } + ], + "required_parameters": [ + { + "default": None, + "description": "Dictionary mapping stimulation " + "conditions to FCS file paths. " + "Expected keys: 'unstimulated', " + "'Mtb300', 'CMV', 'SEB'", + "name": "fcs_files_dict", + "type": "dict", + } + ], + }, + { + "description": "Analyze ELISA data to quantify EBV antibody titers in plasma/serum samples.", + "name": "analyze_ebv_antibody_titers", + "optional_parameters": [ + { + "default": "./", + "description": "Directory to save output files.", + "name": "output_dir", + "type": "str", + } + ], + "required_parameters": [ + { + "default": None, + "description": "Dictionary containing optical " + "density (OD) readings for each " + "sample. Format: {sample_id: " + "{'VCA_IgG': float, 'VCA_IgM': " + "float, 'EA_IgG': float, 'EA_IgM': " + "float, 'EBNA1_IgG': float, " + "'EBNA1_IgM': float}}", + "name": "raw_od_data", + "type": "dict", + }, + { + "default": None, + "description": "Dictionary containing standard " + "curve data for each antibody type. " + "Format: {antibody_type: " + "[(concentration, OD), ...]}", + "name": "standard_curve_data", + "type": "dict", + }, + { + "default": None, + "description": "Dictionary containing metadata for " + "each sample. Format: {sample_id: " + "{'group': str, 'collection_date': " + "str}}", + "name": "sample_metadata", + "type": "dict", + }, + ], + }, + { + "description": "Analyzes histological images of CNS lesions to quantify " + "immune cell infiltration, demyelination, and tissue damage.", + "name": "analyze_cns_lesion_histology", + "optional_parameters": [ + { + "default": "./output", + "description": "Directory to save output files", + "name": "output_dir", + "type": "str", + }, + { + "default": "H&E", + "description": 'Type of histological stain used (options: "H&E", "LFB", "IHC")', + "name": "stain_type", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to the microscopy image file of brain or spinal cord tissue section", + "name": "image_path", + "type": "str", + } + ], + }, + { + "description": "Analyzes immunohistochemistry images to quantify protein expression and spatial distribution.", + "name": "analyze_immunohistochemistry_image", + "optional_parameters": [ + { + "default": "Unknown", + "description": "Name of the protein being analyzed", + "name": "protein_name", + "type": "str", + }, + { + "default": "./ihc_results/", + "description": "Directory to save output files", + "name": "output_dir", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to the microscopy image of tissue section stained with antibodies", + "name": "image_path", + "type": "str", + } + ], + }, +] diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/lab_automation.py b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/lab_automation.py new file mode 100644 index 0000000000000000000000000000000000000000..890f31267c37597e30c1583342ae5329b354d219 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/lab_automation.py @@ -0,0 +1,52 @@ +description = [ + { + "description": "Test a PyLabRobot script based on the script content.", + "name": "test_pylabrobot_script", + "optional_parameters": [ + { + "default": False, + "description": "If True, enable tracking of the script execution", + "name": "enable_tracking", + "type": "bool", + }, + { + "default": 60, + "description": "Timeout in seconds for the script execution", + "name": "timeout_seconds", + "type": "int", + }, + { + "default": False, + "description": "If True, save the test results as a .json file", + "name": "save_test_report", + "type": "bool", + }, + { + "default": None, + "description": "Directory to save the test results. If provided, the test results will be saved as a .json file in this directory", + "name": "test_report_dir", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Script content to test", + "name": "script_input", + "type": "str", + } + ], + }, + { + "description": "Get the documentation for the liquid handling section of the PyLabRobot tutorial.", + "name": "get_pylabrobot_documentation_liquid", + "optional_parameters": [], + "required_parameters": [], + }, + { + "description": "Get the documentation for the material handling section of the PyLabRobot tutorial.", + "name": "get_pylabrobot_documentation_material", + "optional_parameters": [], + "required_parameters": [], + }, +] diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/literature.py b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/literature.py new file mode 100644 index 0000000000000000000000000000000000000000..39daa7c5849ee4742d70fed28b126b3dc6503842 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/literature.py @@ -0,0 +1,161 @@ +description = [ + { + "description": "Fetches supplementary information for a paper given its DOI " + "and saves it to a specified directory.", + "name": "fetch_supplementary_info_from_doi", + "optional_parameters": [ + { + "default": "supplementary_info", + "description": "Directory to save supplementary files", + "name": "output_dir", + "type": "str", + } + ], + "required_parameters": [ + { + "default": None, + "description": "The paper DOI", + "name": "doi", + "type": "str", + } + ], + }, + { + "description": "Query arXiv for papers based on the provided search query.", + "name": "query_arxiv", + "optional_parameters": [ + { + "default": 10, + "description": "The maximum number of papers to retrieve.", + "name": "max_papers", + "type": "int", + } + ], + "required_parameters": [ + { + "default": None, + "description": "The search query string.", + "name": "query", + "type": "str", + } + ], + }, + { + "description": "Query Google Scholar for papers based on the provided search " + "query and return the first search result.", + "name": "query_scholar", + "optional_parameters": [], + "required_parameters": [ + { + "default": None, + "description": "The search query string.", + "name": "query", + "type": "str", + } + ], + }, + { + "description": "Query PubMed for papers based on the provided search query.", + "name": "query_pubmed", + "optional_parameters": [ + { + "default": 10, + "description": "The maximum number of papers to retrieve.", + "name": "max_papers", + "type": "int", + }, + { + "default": 3, + "description": "Maximum number of retry attempts with modified queries.", + "name": "max_retries", + "type": "int", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "The search query string.", + "name": "query", + "type": "str", + } + ], + }, + { + "description": "Search using Google search and return formatted results.", + "name": "search_google", + "optional_parameters": [ + { + "default": 3, + "description": "Number of results to return", + "name": "num_results", + "type": "int", + }, + { + "default": "en", + "description": "Language code for search results", + "name": "language", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": 'The search query (e.g., "protocol text or search question")', + "name": "query", + "type": "str", + } + ], + }, + { + "description": "Extract the text content of a webpage using requests and BeautifulSoup.", + "name": "extract_url_content", + "optional_parameters": [], + "required_parameters": [ + { + "default": None, + "description": "Webpage URL to extract content from", + "name": "url", + "type": "str", + } + ], + }, + { + "description": "Extract text content from a PDF file.", + "name": "extract_pdf_content", + "optional_parameters": [], + "required_parameters": [ + { + "default": None, + "description": "URL of the PDF file", + "name": "url", + "type": "str", + } + ], + }, + { + "description": "Initiate an advanced web search by launching a specialized agent to collect relevant information and citations through multiple rounds of web searches for a given query.", + "name": "advanced_web_search_claude", + "optional_parameters": [ + { + "default": 1, + "description": "Maximum number of searches", + "name": "max_searches", + "type": "int", + }, + { + "default": 3, + "description": "Maximum number of retry attempts with modified queries.", + "name": "max_retries", + "type": "int", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "The search query string.", + "name": "query", + "type": "str", + } + ], + }, +] diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/microbiology.py b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/microbiology.py new file mode 100644 index 0000000000000000000000000000000000000000..f82ef18d3ad987abd7a4a637c7f72d86d9051138 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/microbiology.py @@ -0,0 +1,452 @@ +description = [ + { + "description": "Optimize anaerobic digestion process conditions to maximize VFA production or methane yield.", + "name": "optimize_anaerobic_digestion_process", + "optional_parameters": [ + { + "default": "methane_yield", + "description": "Target output to maximize, either 'vfa_production' or 'methane_yield'", + "name": "target_output", + "type": "str", + }, + { + "default": "rsm", + "description": "Method used for optimization, " + "either 'rsm' (Response Surface " + "Methodology) or 'genetic' (Genetic " + "Algorithm)", + "name": "optimization_method", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Dictionary containing waste " + "characteristics such as " + "total_solids, volatile_solids, and " + "cod", + "name": "waste_characteristics", + "type": "dict", + }, + { + "default": None, + "description": "Dictionary containing operational " + "parameters and their ranges for " + "hrt, olr, if_ratio, temperature, " + "and ph", + "name": "operational_parameters", + "type": "dict", + }, + ], + }, + { + "description": "Analyzes arsenic speciation in liquid samples using " + "HPLC-ICP-MS technique. Returns a research log summarizing " + "analysis steps and results.", + "name": "analyze_arsenic_speciation_hplc_icpms", + "optional_parameters": [ + { + "default": "Unknown Sample", + "description": "Name of the sample being analyzed", + "name": "sample_name", + "type": "str", + }, + { + "default": None, + "description": "Dictionary containing calibration " + "standards data with known " + "concentrations for each arsenic " + "species", + "name": "calibration_data", + "type": "dict", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Dictionary containing sample data " + "with keys as sample IDs and values " + "as dictionaries with retention " + "times (in minutes) as keys and " + "signal intensities as values", + "name": "sample_data", + "type": "dict", + } + ], + }, + { + "description": "Count bacterial colonies from an image of agar plate using computer vision techniques.", + "name": "count_bacterial_colonies", + "optional_parameters": [ + { + "default": 1, + "description": "Dilution factor of the plated sample", + "name": "dilution_factor", + "type": "float", + }, + { + "default": 65.0, + "description": "Area of the agar plate in square centimeters", + "name": "plate_area_cm2", + "type": "float", + }, + { + "default": "./output", + "description": "Directory to save output images and results", + "name": "output_dir", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to the image file containing bacterial colonies on agar plate", + "name": "image_path", + "type": "str", + } + ], + }, + { + "description": "Annotate a bacterial genome using Prokka to identify genes, proteins, and functional features.", + "name": "annotate_bacterial_genome", + "optional_parameters": [ + { + "default": "annotation_results", + "description": "Directory where annotation results will be saved", + "name": "output_dir", + "type": "str", + }, + { + "default": "", + "description": "Genus name for the organism", + "name": "genus", + "type": "str", + }, + { + "default": "", + "description": "Species name for the organism", + "name": "species", + "type": "str", + }, + { + "default": "", + "description": "Strain identifier", + "name": "strain", + "type": "str", + }, + { + "default": "", + "description": "Prefix for output files", + "name": "prefix", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to the assembled genome sequence file in FASTA format", + "name": "genome_file_path", + "type": "str", + } + ], + }, + { + "description": "Quantify bacterial concentration (CFU/mL) using serial dilutions and spot plating.", + "name": "enumerate_bacterial_cfu_by_serial_dilution", + "optional_parameters": [ + { + "default": 1.0, + "description": "Volume of the initial bacterial sample in milliliters", + "name": "initial_sample_volume_ml", + "type": "float", + }, + { + "default": 100000000.0, + "description": "Estimated concentration of bacteria in the initial sample (CFU/mL)", + "name": "estimated_concentration", + "type": "float", + }, + { + "default": 10, + "description": "Factor by which each dilution reduces the concentration", + "name": "dilution_factor", + "type": "int", + }, + { + "default": 8, + "description": "Number of serial dilutions to perform", + "name": "num_dilutions", + "type": "int", + }, + { + "default": 3, + "description": "Number of replicate spots to plate for each dilution", + "name": "spots_per_dilution", + "type": "int", + }, + { + "default": "cfu_enumeration_results.csv", + "description": "Filename to save the CFU enumeration results", + "name": "output_file", + "type": "str", + }, + ], + "required_parameters": [], + }, + { + "description": "Model bacterial population dynamics over time using ordinary differential equations.", + "name": "model_bacterial_growth_dynamics", + "optional_parameters": [ + { + "default": 24, + "description": "Total simulation time in hours", + "name": "simulation_time", + "type": "float", + }, + { + "default": 0.1, + "description": "Time step for simulation output", + "name": "time_step", + "type": "float", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Initial bacterial population size (CFU/ml or cells)", + "name": "initial_population", + "type": "float", + }, + { + "default": None, + "description": "Bacterial growth rate (per hour)", + "name": "growth_rate", + "type": "float", + }, + { + "default": None, + "description": "Rate at which bacteria are cleared from the system (per hour)", + "name": "clearance_rate", + "type": "float", + }, + { + "default": None, + "description": "Maximum carrying capacity of the environment (CFU/ml or cells)", + "name": "niche_size", + "type": "float", + }, + ], + }, + { + "description": "Quantifies biofilm biomass using crystal violet staining " + "assay data and returns a detailed research log.", + "name": "quantify_biofilm_biomass_crystal_violet", + "optional_parameters": [ + { + "default": None, + "description": "Names of the biofilm samples corresponding to od_values", + "name": "sample_names", + "type": "List[str]", + }, + { + "default": 0, + "description": "Index of the negative control sample in od_values", + "name": "control_index", + "type": "int", + }, + { + "default": None, + "description": "Path to save the results as CSV file", + "name": "save_path", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Optical density measurements from " + "crystal violet staining " + "representing absorbance readings " + "for samples", + "name": "od_values", + "type": "List[float] or numpy.ndarray", + } + ], + }, + { + "description": "Perform automated cell segmentation and quantify " + "morphological metrics from fluorescence microscopy images.", + "name": "segment_and_analyze_microbial_cells", + "optional_parameters": [ + { + "default": "./output", + "description": "Directory to save output files", + "name": "output_dir", + "type": "str", + }, + { + "default": 50, + "description": "Minimum cell size in pixels to filter noise", + "name": "min_cell_size", + "type": "int", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to the fluorescence microscopy image file", + "name": "image_path", + "type": "str", + } + ], + }, + { + "description": "Perform cell segmentation on fluorescence microscopy images " + "using deep learning with pre-trained models from the " + "Cellpose/Omnipose library.", + "name": "segment_cells_with_deep_learning", + "optional_parameters": [ + { + "default": "bact_fluor_omni", + "description": "Name of the pre-trained model to " + "use (Options include: " + "'bact_fluor_omni', 'cyto', " + "'nuclei', etc.)", + "name": "model_type", + "type": "str", + }, + { + "default": None, + "description": "Expected diameter of cells in pixels. If None, diameter is automatically estimated", + "name": "diameter", + "type": "float", + }, + { + "default": "segmentation_results", + "description": "Directory to save segmentation results", + "name": "save_dir", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to the fluorescence microscopy image file", + "name": "image_path", + "type": "str", + } + ], + }, + { + "description": "Simulate microbial community dynamics using the Generalized Lotka-Volterra (gLV) model.", + "name": "simulate_generalized_lotka_volterra_dynamics", + "optional_parameters": [ + { + "default": "glv_simulation_results.csv", + "description": "Filename to save the simulation results", + "name": "output_file", + "type": "str", + } + ], + "required_parameters": [ + { + "default": None, + "description": "Initial abundances of each microbial species (1D array)", + "name": "initial_abundances", + "type": "numpy.ndarray", + }, + { + "default": None, + "description": "Intrinsic growth rates for each microbial species (1D array)", + "name": "growth_rates", + "type": "numpy.ndarray", + }, + { + "default": None, + "description": "Matrix of interaction coefficients " + "where A[i,j] represents the effect " + "of species j on species i (2D " + "array)", + "name": "interaction_matrix", + "type": "numpy.ndarray", + }, + { + "default": None, + "description": "Time points at which to evaluate the model", + "name": "time_points", + "type": "numpy.ndarray", + }, + ], + }, + { + "description": "Predict the secondary structure of an RNA molecule using ViennaRNA.", + "name": "predict_rna_secondary_structure", + "optional_parameters": [ + { + "default": "rna_structure", + "description": "Prefix for output files", + "name": "output_prefix", + "type": "str", + } + ], + "required_parameters": [ + { + "default": None, + "description": "The RNA sequence (consisting of A, U, G, C nucleotides)", + "name": "rna_sequence", + "type": "str", + } + ], + }, + { + "description": "Performs stochastic simulation of microbial population dynamics using the Gillespie algorithm.", + "name": "simulate_microbial_population_dynamics", + "optional_parameters": [ + { + "default": 100, + "description": "Maximum simulation time", + "name": "max_time", + "type": "float", + }, + { + "default": 100, + "description": "Number of stochastic simulations to run", + "name": "num_simulations", + "type": "int", + }, + { + "default": 100, + "description": "Number of time points to record for trajectories", + "name": "time_points", + "type": "int", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Initial population sizes for each microbial species", + "name": "initial_populations", + "type": "List[int]", + }, + { + "default": None, + "description": "Per capita growth rates for each species", + "name": "growth_rates", + "type": "List[float]", + }, + { + "default": None, + "description": "Per capita death/clearance rates for each species", + "name": "clearance_rates", + "type": "List[float]", + }, + { + "default": None, + "description": "Maximum sustainable population for each species", + "name": "carrying_capacities", + "type": "List[float]", + }, + ], + }, +] diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/molecular_biology.py b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/molecular_biology.py new file mode 100644 index 0000000000000000000000000000000000000000..39a13d72f163dd45f2a0442efd34c1655c9b3b1a --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/molecular_biology.py @@ -0,0 +1,560 @@ +description = [ + { + "description": "Find all Open Reading Frames (ORFs) in a DNA sequence using " + "Biopython, searching both forward and reverse complement " + "strands.", + "name": "annotate_open_reading_frames", + "optional_parameters": [ + { + "default": False, + "description": "Whether to search the reverse complement strand", + "name": "search_reverse", + "type": "bool", + }, + { + "default": False, + "description": "Whether to filter out ORFs with same end but later start", + "name": "filter_subsets", + "type": "bool", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "DNA sequence to analyze", + "name": "sequence", + "type": "str", + }, + { + "default": None, + "description": "Minimum length of ORF in nucleotides", + "name": "min_length", + "type": "int", + }, + ], + }, + { + "description": "Annotate a DNA sequence using pLannotate's command-line interface.", + "name": "annotate_plasmid", + "optional_parameters": [ + { + "default": True, + "description": "Whether the sequence is circular", + "name": "is_circular", + "type": "bool", + } + ], + "required_parameters": [ + { + "default": None, + "description": "The DNA sequence to annotate", + "name": "sequence", + "type": "str", + } + ], + }, + { + "description": "Retrieves the coding sequence(s) of a specified gene from NCBI Entrez.", + "name": "get_gene_coding_sequence", + "optional_parameters": [ + { + "default": None, + "description": "Email address for NCBI Entrez (recommended)", + "name": "email", + "type": "str", + } + ], + "required_parameters": [ + { + "default": None, + "description": "Name of the gene", + "name": "gene_name", + "type": "str", + }, + { + "default": None, + "description": "Name of the organism", + "name": "organism", + "type": "str", + }, + ], + }, + { + "description": "Unified function to retrieve plasmid sequences from either " + "Addgene or NCBI. If is_addgene is True or identifier is " + "numeric, uses Addgene. Otherwise searches NCBI using the " + "plasmid name.", + "name": "get_plasmid_sequence", + "optional_parameters": [ + { + "default": None, + "description": "Force Addgene lookup if True, force " + "NCBI if False. If None, attempts to " + "auto-detect based on identifier " + "format.", + "name": "is_addgene", + "type": "bool", + } + ], + "required_parameters": [ + { + "default": None, + "description": "Either an Addgene ID or plasmid name", + "name": "identifier", + "type": "str", + } + ], + }, + { + "description": "Align short sequences (primers) to a longer sequence, " + "allowing for one mismatch. Checks both forward and reverse " + "complement strands.", + "name": "align_sequences", + "optional_parameters": [], + "required_parameters": [ + { + "default": None, + "description": "Target DNA sequence", + "name": "long_seq", + "type": "str", + }, + { + "default": None, + "description": "Single primer or list of primers", + "name": "short_seqs", + "type": "Union[str, List[str]]", + }, + ], + }, + { + "description": "Simulate PCR amplification with given primers and sequence.", + "name": "pcr_simple", + "optional_parameters": [ + { + "default": False, + "description": "Whether the sequence is circular", + "name": "circular", + "type": "bool", + } + ], + "required_parameters": [ + { + "default": None, + "description": "Either a sequence string or path to plasmid file", + "name": "sequence", + "type": "str", + }, + { + "default": None, + "description": "Forward primer sequence (5' to 3')", + "name": "forward_primer", + "type": "str", + }, + { + "default": None, + "description": "Reverse primer sequence (5' to 3')", + "name": "reverse_primer", + "type": "str", + }, + ], + }, + { + "description": "Simulates restriction enzyme digestion of a DNA sequence and " + "returns the resulting fragments with their properties.", + "name": "digest_sequence", + "optional_parameters": [ + { + "default": True, + "description": "Whether the DNA sequence is circular (True) or linear (False)", + "name": "is_circular", + "type": "bool", + } + ], + "required_parameters": [ + { + "default": None, + "description": "Input DNA sequence to be digested", + "name": "dna_sequence", + "type": "str", + }, + { + "default": None, + "description": "Names of restriction enzymes to use for digestion", + "name": "enzyme_names", + "type": "List[str]", + }, + ], + }, + { + "description": "Identifies restriction enzyme sites in a given DNA sequence for specified enzymes.", + "name": "find_restriction_sites", + "optional_parameters": [ + { + "default": True, + "description": "Whether the DNA sequence is circular (True) or linear (False)", + "name": "is_circular", + "type": "bool", + } + ], + "required_parameters": [ + { + "default": None, + "description": "Complete input DNA sequence", + "name": "dna_sequence", + "type": "str", + }, + { + "default": None, + "description": "List of restriction enzyme names to check", + "name": "enzymes", + "type": "List[str]", + }, + ], + }, + { + "description": "Finds common restriction enzyme sites in a DNA sequence and returns their cut positions.", + "name": "find_restriction_enzymes", + "optional_parameters": [ + { + "default": False, + "description": "Whether the sequence is circular", + "name": "is_circular", + "type": "bool", + } + ], + "required_parameters": [ + { + "default": None, + "description": "DNA sequence to analyze", + "name": "sequence", + "type": "str", + } + ], + }, + { + "description": "Compare query sequence against reference sequence to identify mutations.", + "name": "find_sequence_mutations", + "optional_parameters": [ + { + "default": 1, + "description": "The start position of the query sequence", + "name": "query_start", + "type": "int", + } + ], + "required_parameters": [ + { + "default": None, + "description": "The sequence being analyzed", + "name": "query_sequence", + "type": "str", + }, + { + "default": None, + "description": "The reference sequence to compare against", + "name": "reference_sequence", + "type": "str", + }, + ], + }, + { + "description": "Design sgRNAs for CRISPR knockout by searching pre-computed " + "sgRNA libraries. Returns optimized guide RNAs for targeting " + "a specific gene.", + "name": "design_knockout_sgrna", + "optional_parameters": [ + { + "default": "human", + "description": "Target organism species", + "name": "species", + "type": "str", + }, + { + "default": 1, + "description": "Number of guides to return", + "name": "num_guides", + "type": "int", + }, + ], + "required_parameters": [ + { + "default": None, + "description": 'Target gene symbol/name (e.g., "EGFR", "TP53")', + "name": "gene_name", + "type": "str", + }, + { + "default": None, + "description": "Path to the data lake", + "name": "data_lake_path", + "type": "str", + }, + ], + }, + { + "description": "Return a standard protocol for annealing oligonucleotides without phosphorylation.", + "name": "get_oligo_annealing_protocol", + "optional_parameters": [], + "required_parameters": [], + }, + { + "description": "Return a customized protocol for Golden Gate assembly based " + "on the number of inserts and specific DNA sequences.", + "name": "get_golden_gate_assembly_protocol", + "optional_parameters": [ + { + "default": 1, + "description": "Number of inserts to be assembled", + "name": "num_inserts", + "type": "int", + }, + { + "default": 75.0, + "description": "Amount of vector to use in ng", + "name": "vector_amount_ng", + "type": "float", + }, + { + "default": None, + "description": "List of insert lengths in bp", + "name": "insert_lengths", + "type": "List[int]", + }, + { + "default": False, + "description": "Whether this is for library preparation", + "name": "is_library_prep", + "type": "bool", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Type IIS restriction enzyme to be used", + "name": "enzyme_name", + "type": "str", + }, + { + "default": None, + "description": "Length of the destination vector in bp", + "name": "vector_length", + "type": "int", + }, + ], + }, + { + "description": "Return a standard protocol for bacterial transformation.", + "name": "get_bacterial_transformation_protocol", + "optional_parameters": [ + { + "default": "ampicillin", + "description": "Selection antibiotic", + "name": "antibiotic", + "type": "str", + }, + { + "default": False, + "description": "Whether the sequence contains repetitive elements", + "name": "is_repetitive", + "type": "bool", + }, + ], + "required_parameters": [], + }, + { + "description": "Design a single primer within the given sequence window.", + "name": "design_primer", + "optional_parameters": [ + { + "default": 20, + "description": "Length of the primer to design", + "name": "primer_length", + "type": "int", + }, + { + "default": 0.4, + "description": "Minimum GC content", + "name": "min_gc", + "type": "float", + }, + { + "default": 0.6, + "description": "Maximum GC content", + "name": "max_gc", + "type": "float", + }, + { + "default": 55.0, + "description": "Minimum melting temperature in °C", + "name": "min_tm", + "type": "float", + }, + { + "default": 65.0, + "description": "Maximum melting temperature in °C", + "name": "max_tm", + "type": "float", + }, + { + "default": 100, + "description": "Size of window to search for primers", + "name": "search_window", + "type": "int", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Target DNA sequence", + "name": "sequence", + "type": "str", + }, + { + "default": None, + "description": "Starting position for primer search", + "name": "start_pos", + "type": "int", + }, + ], + }, + { + "description": "Design Sanger sequencing primers to verify a specific region " + "in a plasmid. First tries to use primers from an existing " + "primer pool. If they cannot fully cover the region, designs " + "additional primers as needed.", + "name": "design_verification_primers", + "optional_parameters": [ + { + "default": None, + "description": "List of existing primers with their sequences and optional names", + "name": "existing_primers", + "type": "Optional[List[Dict[str, str]]]", + }, + { + "default": True, + "description": "Whether the plasmid is circular", + "name": "is_circular", + "type": "bool", + }, + { + "default": 800, + "description": "Typical read length for each primer in base pairs", + "name": "coverage_length", + "type": "int", + }, + { + "default": 20, + "description": "Length of newly designed primers", + "name": "primer_length", + "type": "int", + }, + { + "default": 0.4, + "description": "Minimum GC content for new primers", + "name": "min_gc", + "type": "float", + }, + { + "default": 0.6, + "description": "Maximum GC content for new primers", + "name": "max_gc", + "type": "float", + }, + { + "default": 55.0, + "description": "Minimum melting temperature in °C", + "name": "min_tm", + "type": "float", + }, + { + "default": 65.0, + "description": "Maximum melting temperature in °C", + "name": "max_tm", + "type": "float", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "The complete plasmid sequence", + "name": "plasmid_sequence", + "type": "str", + }, + { + "default": None, + "description": "Start and end positions to verify (0-based indexing)", + "name": "target_region", + "type": "Tuple[int, int]", + }, + ], + }, + { + "description": "Design complementary oligonucleotides with Type IIS " + "restriction enzyme overhangs for Golden Gate assembly based " + "on restriction site analysis of the backbone.", + "name": "design_golden_gate_oligos", + "optional_parameters": [ + { + "default": True, + "description": "Whether the backbone is circular", + "name": "is_circular", + "type": "bool", + } + ], + "required_parameters": [ + { + "default": None, + "description": "Complete backbone sequence", + "name": "backbone_sequence", + "type": "str", + }, + { + "default": None, + "description": "Sequence to be inserted (e.g., sgRNA target sequence)", + "name": "insert_sequence", + "type": "str", + }, + { + "default": None, + "description": "Type IIS restriction enzyme to be used", + "name": "enzyme_name", + "type": "str", + }, + ], + }, + { + "description": "Simulate Golden Gate assembly to predict final construct " + "sequences from backbone and fragment sequences.", + "name": "golden_gate_assembly", + "optional_parameters": [ + { + "default": True, + "description": "Whether the backbone is circular", + "name": "is_circular", + "type": "bool", + } + ], + "required_parameters": [ + { + "default": None, + "description": "Complete backbone sequence", + "name": "backbone_sequence", + "type": "str", + }, + { + "default": None, + "description": 'Type IIS restriction enzyme to be used (e.g., "BsmBI", "BsaI")', + "name": "enzyme_name", + "type": "str", + }, + { + "default": None, + "description": "List of fragments to insert, containing one of: " + "name + fwd_oligo + rev_oligo (oligo pair with matching overhangs) or " + "name + sequence (double-stranded DNA fragment containing restriction sites)", + "name": "fragments", + "type": "List[Dict[str, str]]", + }, + ], + }, +] diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/pathology.py b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/pathology.py new file mode 100644 index 0000000000000000000000000000000000000000..5661bb269b4eb09e5d4303004f39247718184d1f --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/pathology.py @@ -0,0 +1,213 @@ +description = [ + { + "description": "Analyze aortic diameter and geometry from cardiovascular " + "imaging data to measure aortic root diameter, ascending " + "aorta diameter, and calculate geometric parameters such as " + "tortuosity and dilation indices.", + "name": "analyze_aortic_diameter_and_geometry", + "optional_parameters": [ + { + "default": "./output", + "description": "Directory to save output files", + "name": "output_dir", + "type": "str", + } + ], + "required_parameters": [ + { + "default": None, + "description": "Path to the cardiovascular imaging data (DICOM, JPG, PNG)", + "name": "image_path", + "type": "str", + } + ], + }, + { + "description": "Analyze luminescence-based ATP assay data to determine intracellular ATP concentration.", + "name": "analyze_atp_luminescence_assay", + "optional_parameters": [ + { + "default": "cell_count", + "description": "Method used to normalize ATP values, either cell_count or protein_content", + "name": "normalization_method", + "type": "str", + }, + { + "default": None, + "description": "Path to CSV file with normalization " + "data or dictionary with sample IDs " + "as keys and normalization values", + "name": "normalization_data", + "type": "str or dict", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to CSV file containing " + "luminescence readings from samples " + "with columns for Sample_ID and " + "Luminescence_Value", + "name": "data_file", + "type": "str", + }, + { + "default": None, + "description": "Path to CSV file containing " + "standard curve data with columns " + "for ATP_Concentration (in nM) and " + "Luminescence_Value", + "name": "standard_curve_file", + "type": "str", + }, + ], + }, + { + "description": "Analyze histological images of thrombus samples stained with " + "H&E to identify and quantify different thrombus components " + "(fresh, cellular lysis, endothelialization, fibroblastic " + "reaction).", + "name": "analyze_thrombus_histology", + "optional_parameters": [ + { + "default": "./output", + "description": "Directory to save output files", + "name": "output_dir", + "type": "str", + } + ], + "required_parameters": [ + { + "default": None, + "description": "Path to the histological image of thrombus sample stained with H&E", + "name": "image_path", + "type": "str", + } + ], + }, + { + "description": "Analyzes intracellular calcium concentration using Rhod-2 " + "fluorescent indicator from microscopy images.", + "name": "analyze_intracellular_calcium_with_rhod2", + "optional_parameters": [ + { + "default": "./output", + "description": "Directory to save output files", + "name": "output_dir", + "type": "str", + } + ], + "required_parameters": [ + { + "default": None, + "description": "Path to the background image (no cells, just media)", + "name": "background_image_path", + "type": "str", + }, + { + "default": None, + "description": "Path to the control image (cells without calcium stimulus)", + "name": "control_image_path", + "type": "str", + }, + { + "default": None, + "description": "Path to the sample image (cells with calcium stimulus)", + "name": "sample_image_path", + "type": "str", + }, + ], + }, + { + "description": "Quantify the volume/density of immunofluorescence-labeled corneal nerve fibers.", + "name": "quantify_corneal_nerve_fibers", + "optional_parameters": [ + { + "default": "./output", + "description": "Directory to save output files", + "name": "output_dir", + "type": "str", + }, + { + "default": "otsu", + "description": "Method for thresholding ('otsu', 'adaptive', 'manual')", + "name": "threshold_method", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to the immunofluorescence microscopy image file", + "name": "image_path", + "type": "str", + }, + { + "default": None, + "description": "Type of nerve fiber marker (e.g., 'βIII-tubulin', 'SP', 'L1CAM')", + "name": "marker_type", + "type": "str", + }, + ], + }, + { + "description": "Segment cells and quantify protein expression levels from multichannel tissue images.", + "name": "segment_and_quantify_cells_in_multiplexed_images", + "optional_parameters": [ + { + "default": 0, + "description": "Index of the nuclear marker channel (typically DAPI)", + "name": "nuclear_channel_index", + "type": "int", + }, + { + "default": "./output", + "description": "Directory to save output files", + "name": "output_dir", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to the multichannel image file (tiff stack or similar format)", + "name": "image_path", + "type": "str", + }, + { + "default": None, + "description": "List of marker names corresponding to each channel in the image", + "name": "markers_list", + "type": "List[str]", + }, + ], + }, + { + "description": "Analyze bone microarchitecture parameters from 3D micro-CT " + "images to calculate bone mineral density, bone volume, " + "trabecular number, thickness, and separation.", + "name": "analyze_bone_microct_morphometry", + "optional_parameters": [ + { + "default": "./results", + "description": "Directory to save output files", + "name": "output_dir", + "type": "str", + }, + { + "default": None, + "description": "Threshold value for bone segmentation. If None, Otsu's method will be used", + "name": "threshold_value", + "type": "float", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to the micro-CT scan data file (TIFF stack or similar 3D format)", + "name": "input_file_path", + "type": "str", + } + ], + }, +] diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/pharmacology.py b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/pharmacology.py new file mode 100644 index 0000000000000000000000000000000000000000..c4b128fb1a75d7937d15edf07d4c5f3c977b7ea9 --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/pharmacology.py @@ -0,0 +1,774 @@ +description = [ + { + "description": "Run DiffDock molecular docking using a protein PDB file and " + "a SMILES string for the ligand, executing the process in a " + "Docker container.", + "name": "run_diffdock_with_smiles", + "optional_parameters": [ + { + "default": 0, + "description": "GPU device ID to use for computation", + "name": "gpu_device", + "type": "int", + }, + { + "default": True, + "description": "Whether to use GPU acceleration for docking", + "name": "use_gpu", + "type": "bool", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to the protein PDB file for docking", + "name": "pdb_path", + "type": "str", + }, + { + "default": None, + "description": "SMILES string representation of the ligand molecule", + "name": "smiles_string", + "type": "str", + }, + { + "default": None, + "description": "Local directory path where docking results will be saved", + "name": "local_output_dir", + "type": "str", + }, + ], + }, + { + "description": "Performs molecular docking using AutoDock Vina to predict " + "binding affinities between small molecules and a receptor " + "protein.", + "name": "docking_autodock_vina", + "optional_parameters": [ + { + "default": 1, + "description": "Number of CPU cores to use for docking", + "name": "ncpu", + "type": "int", + } + ], + "required_parameters": [ + { + "default": None, + "description": "List of SMILES strings representing small molecules to dock", + "name": "smiles_list", + "type": "List[str]", + }, + { + "default": None, + "description": "Path to the receptor protein structure PDB file", + "name": "receptor_pdb_file", + "type": "str", + }, + { + "default": None, + "description": "3D coordinates [x, y, z] of the docking box center", + "name": "box_center", + "type": "List[float]", + }, + { + "default": None, + "description": "Dimensions [x, y, z] of the docking box", + "name": "box_size", + "type": "List[float]", + }, + ], + }, + { + "description": "Runs AutoSite on a PDB file to identify potential binding " + "sites and returns a research log with the results.", + "name": "run_autosite", + "optional_parameters": [ + { + "default": 1.0, + "description": "Grid spacing parameter for AutoSite calculation", + "name": "spacing", + "type": "float", + } + ], + "required_parameters": [ + { + "default": None, + "description": "Path to the input PDB file", + "name": "pdb_file", + "type": "str", + }, + { + "default": None, + "description": "Directory where AutoSite results will be saved", + "name": "output_dir", + "type": "str", + }, + ], + }, + { + "description": "Computes TxGNN model predictions for drug repurposing and " + "returns the top predicted drugs with their scores for a " + "given disease.", + "name": "retrieve_topk_repurposing_drugs_from_disease_txgnn", + "optional_parameters": [ + { + "default": 5, + "description": "The number of top drug predictions to return", + "name": "k", + "type": "int", + } + ], + "required_parameters": [ + { + "default": None, + "description": "The name of the disease for which to retrieve drug predictions", + "name": "disease_name", + "type": "str", + }, + { + "default": None, + "description": "Path to the data lake", + "name": "data_lake_path", + "type": "str", + }, + ], + }, + { + "description": "Predicts ADMET (Absorption, Distribution, Metabolism, " + "Excretion, Toxicity) properties for a list of compounds " + "using pretrained models.", + "name": "predict_admet_properties", + "optional_parameters": [ + { + "default": "MPNN", + "description": "Type of model to use for ADMET prediction (options: 'MPNN', 'CNN', 'Morgan')", + "name": "ADMET_model_type", + "type": "str", + } + ], + "required_parameters": [ + { + "default": None, + "description": "List of SMILES strings representing chemical compounds to analyze", + "name": "smiles_list", + "type": "List[str]", + } + ], + }, + { + "description": "Predicts binding affinity between small molecules and a " + "protein sequence using pre-trained deep learning models.", + "name": "predict_binding_affinity_protein_1d_sequence", + "optional_parameters": [ + { + "default": "MPNN-CNN", + "description": "Deep learning model architecture to " + "use for binding affinity prediction " + "(options: CNN-CNN, MPNN-CNN, " + "Morgan-CNN, Morgan-AAC, " + "Daylight-AAC)", + "name": "affinity_model_type", + "type": "str", + } + ], + "required_parameters": [ + { + "default": None, + "description": "List of SMILES strings representing chemical compounds", + "name": "smiles_list", + "type": "List[str]", + }, + { + "default": None, + "description": "Protein sequence in amino acid format", + "name": "amino_acid_sequence", + "type": "str", + }, + ], + }, + { + "description": "Analyzes the stability of pharmaceutical formulations under accelerated storage conditions.", + "name": "analyze_accelerated_stability_of_pharmaceutical_formulations", + "optional_parameters": [], + "required_parameters": [ + { + "default": None, + "description": "List of formulation dictionaries " + "containing name, active ingredient, " + "concentration, and excipients", + "name": "formulations", + "type": "List[dict]", + }, + { + "default": None, + "description": "List of storage condition " + "dictionaries containing " + "temperature, humidity (optional), " + "and description", + "name": "storage_conditions", + "type": "List[dict]", + }, + { + "default": None, + "description": "List of time points in days to evaluate stability", + "name": "time_points", + "type": "List[int]", + }, + ], + }, + { + "description": "Generates a detailed protocol for performing a 3D " + "chondrogenic aggregate culture assay to evaluate compounds' " + "effects on chondrogenesis.", + "name": "run_3d_chondrogenic_aggregate_assay", + "optional_parameters": [ + { + "default": 21, + "description": "Total duration of the culture period in days", + "name": "culture_duration_days", + "type": "int", + }, + { + "default": 7, + "description": "Interval in days between measurements", + "name": "measurement_intervals", + "type": "int", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Dictionary with cell information " + "including 'source', " + "'passage_number', and " + "'cell_density'", + "name": "chondrocyte_cells", + "type": "dict", + }, + { + "default": None, + "description": "List of compounds to test, each with 'name', 'concentration', and 'vehicle' keys", + "name": "test_compounds", + "type": "list of dict", + }, + ], + }, + { + "description": "Grade and monitor adverse events in animal studies using the VCOG-CTCAE standard.", + "name": "grade_adverse_events_using_vcog_ctcae", + "optional_parameters": [], + "required_parameters": [ + { + "default": None, + "description": "Path to a CSV file containing " + "clinical evaluation data with " + "columns: subject_id, time_point, " + "symptom, severity, measurement " + "(optional)", + "name": "clinical_data_file", + "type": "str", + } + ], + }, + { + "description": "Analyze biodistribution and pharmacokinetic profile of radiolabeled antibodies.", + "name": "analyze_radiolabeled_antibody_biodistribution", + "optional_parameters": [], + "required_parameters": [ + { + "default": None, + "description": "Time points (hours) at which measurements were taken", + "name": "time_points", + "type": "List[float] or numpy.ndarray", + }, + { + "default": None, + "description": "Dictionary where keys are tissue " + "names and values are lists/arrays " + "of %IA/g measurements corresponding " + "to time_points. Must include " + "'tumor' as one of the keys", + "name": "tissue_data", + "type": "dict", + }, + ], + }, + { + "description": "Estimate radiation absorbed doses to tumor and normal organs " + "for alpha-particle radiotherapeutics using the Medical " + "Internal Radiation Dose (MIRD) schema.", + "name": "estimate_alpha_particle_radiotherapy_dosimetry", + "optional_parameters": [ + { + "default": "dosimetry_results.csv", + "description": "Filename to save the dosimetry results", + "name": "output_file", + "type": "str", + } + ], + "required_parameters": [ + { + "default": None, + "description": "Dictionary containing organ/tissue " + "names as keys and a list of " + "time-activity measurements as " + "values. Each measurement should be " + "a tuple of (time_hours, " + "percent_injected_activity). Must " + "include entries for all relevant " + "organs including 'tumor'.", + "name": "biodistribution_data", + "type": "dict", + }, + { + "default": None, + "description": "Dictionary containing radiation " + "parameters for the alpha-emitting " + "radionuclide including " + "'radionuclide', 'half_life_hours', " + "'energy_per_decay_MeV', " + "'radiation_weighting_factor', and " + "'S_factors'.", + "name": "radiation_parameters", + "type": "dict", + }, + ], + }, + { + "description": "Perform a Methylome-wide Association Study (MWAS) to " + "identify CpG sites significantly associated with CYP2C19 " + "metabolizer status.", + "name": "perform_mwas_cyp2c19_metabolizer_status", + "optional_parameters": [ + { + "default": None, + "description": "Path to CSV or TSV file containing " + "covariates to adjust for in the " + "regression model (e.g., age, sex, " + "smoking status).", + "name": "covariates_path", + "type": "str", + }, + { + "default": 0.05, + "description": "P-value threshold for significance after multiple testing correction.", + "name": "pvalue_threshold", + "type": "float", + }, + { + "default": "significant_cpg_sites.csv", + "description": "Filename to save significant CpG sites.", + "name": "output_file", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to CSV or TSV file containing " + "DNA methylation beta values. Rows " + "should be samples, columns should " + "be CpG sites.", + "name": "methylation_data_path", + "type": "str", + }, + { + "default": None, + "description": "Path to CSV or TSV file containing " + "CYP2C19 metabolizer status for each " + "sample. Should have a sample ID " + "column and a status column.", + "name": "metabolizer_status_path", + "type": "str", + }, + ], + }, + { + "description": "Calculate key physicochemical properties of a drug candidate molecule.", + "name": "calculate_physicochemical_properties", + "optional_parameters": [], + "required_parameters": [ + { + "default": None, + "description": "The molecular structure in SMILES format", + "name": "smiles_string", + "type": "str", + } + ], + }, + { + "description": "Analyze tumor growth inhibition in xenograft models across different treatment groups.", + "name": "analyze_xenograft_tumor_growth_inhibition", + "optional_parameters": [ + { + "default": "./results", + "description": "Directory to save output files", + "name": "output_dir", + "type": "str", + } + ], + "required_parameters": [ + { + "default": None, + "description": "Path to CSV or TSV file containing tumor volume measurements", + "name": "data_path", + "type": "str", + }, + { + "default": None, + "description": "Name of the column containing time points", + "name": "time_column", + "type": "str", + }, + { + "default": None, + "description": "Name of the column containing tumor volume measurements", + "name": "volume_column", + "type": "str", + }, + { + "default": None, + "description": "Name of the column containing treatment group labels", + "name": "group_column", + "type": "str", + }, + { + "default": None, + "description": "Name of the column containing subject/mouse identifiers", + "name": "subject_column", + "type": "str", + }, + ], + }, + { + "description": "Analyze western blot or DNA electrophoresis images and return pixel distribution statistics including intensity statistics, percentiles, and brightness distribution. Use this to determine appropriate threshold values for find_roi_from_image.", + "name": "analyze_pixel_distribution", + "optional_parameters": [], + "required_parameters": [ + { + "default": None, + "description": "Path to the input grayscale image. Automatically appends .png if no suffix is provided.", + "name": "image_path", + "type": "str", + } + ], + }, + { + "description": "Find the ROIs (regions of interest) of protein bands from a Western blot or DNA electrophoresis image using threshold-based blob detection. Returns annotated image path and list of ROI coordinates. Use analyze_pixel_distribution first to determine appropriate threshold values. The returned ROI list can be converted to target_bands format for analyze_western_blot.", + "name": "find_roi_from_image", + "optional_parameters": [ + { + "default": True, + "description": "If True, draw green contours (hulls) and blue keypoint boxes for debugging.", + "name": "debug", + "type": "bool", + } + ], + "required_parameters": [ + { + "default": None, + "description": "Path to the input image.", + "name": "image_path", + "type": "str", + }, + { + "default": None, + "description": "Pixel intensities lower than this value are used to make the binary image. Use analyze_pixel_distribution to determine appropriate values.", + "name": "lower_threshold", + "type": "int", + }, + { + "default": None, + "description": "Pixel intensities greater than or equal to this value are used to make the binary image. Use analyze_pixel_distribution to determine appropriate values.", + "name": "upper_threshold", + "type": "int", + }, + { + "default": None, + "description": "The actual number of bands expected in the image.", + "name": "number_of_bands", + "type": "int", + }, + ], + }, + { + "description": "Performs densitometric analysis of Western blot images to " + "quantify relative protein expression.", + "name": "analyze_western_blot", + "optional_parameters": [ + { + "default": "./results", + "description": "Directory to save output files", + "name": "output_dir", + "type": "str", + } + ], + "required_parameters": [ + { + "default": None, + "description": "Path to the Western blot image file", + "name": "blot_image_path", + "type": "str", + }, + { + "default": None, + "description": "List of dictionaries containing " + "information about target protein " + "bands, each with 'name' and 'roi' " + "(region of interest as [x, y, " + "width, height])", + "name": "target_bands", + "type": "list of dict", + }, + { + "default": None, + "description": "Dictionary with 'name' and 'roi' " + "for the loading control protein " + "(e.g., β-actin, GAPDH)", + "name": "loading_control_band", + "type": "dict", + }, + { + "default": None, + "description": "Dictionary containing information " + "about antibodies used with " + "'primary' and 'secondary' keys", + "name": "antibody_info", + "type": "dict", + }, + ], + }, + { + "description": "Query drug-drug interactions from DDInter database to identify potential interactions, mechanisms, and severity levels between specified drugs.", + "name": "query_drug_interactions", + "required_parameters": [ + { + "default": None, + "description": "List of drug names to query for interactions", + "name": "drug_names", + "type": "List[str]", + } + ], + "optional_parameters": [ + { + "default": None, + "description": "Filter results by specific interaction types", + "name": "interaction_types", + "type": "List[str]", + }, + { + "default": None, + "description": "Filter results by severity levels (Major, Moderate, Minor)", + "name": "severity_levels", + "type": "List[str]", + }, + { + "default": None, + "description": "Path to data lake directory containing DDInter data", + "name": "data_lake_path", + "type": "str", + }, + ], + }, + { + "description": "Analyze safety of a drug combination for potential interactions using DDInter database with comprehensive risk assessment and clinical recommendations.", + "name": "check_drug_combination_safety", + "required_parameters": [ + { + "default": None, + "description": "List of drugs to analyze for combination safety", + "name": "drug_list", + "type": "List[str]", + } + ], + "optional_parameters": [ + { + "default": True, + "description": "Include interaction mechanism descriptions in results", + "name": "include_mechanisms", + "type": "bool", + }, + { + "default": True, + "description": "Include management recommendations in results", + "name": "include_management", + "type": "bool", + }, + { + "default": None, + "description": "Path to data lake directory containing DDInter data", + "name": "data_lake_path", + "type": "str", + }, + ], + }, + { + "description": "Analyze interaction mechanisms between two specific drugs providing detailed mechanistic insights and clinical significance assessment.", + "name": "analyze_interaction_mechanisms", + "required_parameters": [ + { + "default": None, + "description": "Pair of drug names to analyze (drug1, drug2)", + "name": "drug_pair", + "type": "Tuple[str, str]", + } + ], + "optional_parameters": [ + { + "default": True, + "description": "Include detailed mechanistic information in analysis", + "name": "detailed_analysis", + "type": "bool", + }, + { + "default": None, + "description": "Path to data lake directory containing DDInter data", + "name": "data_lake_path", + "type": "str", + }, + ], + }, + { + "description": "Find alternative drugs that don't interact with contraindicated drugs using DDInter database for safer therapeutic substitutions.", + "name": "find_alternative_drugs_ddinter", + "required_parameters": [ + { + "default": None, + "description": "Drug to find alternatives for", + "name": "target_drug", + "type": "str", + }, + { + "default": None, + "description": "List of drugs to avoid interactions with", + "name": "contraindicated_drugs", + "type": "List[str]", + }, + ], + "optional_parameters": [ + { + "default": None, + "description": "Limit search to specific therapeutic class", + "name": "therapeutic_class", + "type": "str", + }, + { + "default": None, + "description": "Path to data lake directory containing DDInter data", + "name": "data_lake_path", + "type": "str", + }, + ], + }, + { + "description": "Query FDA adverse event reports for specific drugs from the OpenFDA database to identify potential safety signals, reaction patterns, and regulatory intelligence.", + "name": "query_fda_adverse_events", + "required_parameters": [ + { + "default": None, + "description": "Name of the drug to query for adverse events", + "name": "drug_name", + "type": "str", + }, + ], + "optional_parameters": [ + { + "default": None, + "description": "Optional date range as (start_date, end_date) in YYYY-MM-DD format", + "name": "date_range", + "type": "Tuple[str, str]", + }, + { + "default": None, + "description": "Optional filter by severity levels ['serious', 'non_serious']", + "name": "severity_filter", + "type": "List[str]", + }, + { + "default": None, + "description": "Optional filter by outcomes ['life_threatening', 'hospitalization', 'death']", + "name": "outcome_filter", + "type": "List[str]", + }, + { + "default": 100, + "description": "Maximum number of results to return", + "name": "limit", + "type": "int", + }, + ], + }, + { + "description": "Retrieve FDA drug label information including indications, contraindications, warnings, and dosage information from the OpenFDA database.", + "name": "get_fda_drug_label_info", + "required_parameters": [ + { + "default": None, + "description": "Name of the drug to query for label information", + "name": "drug_name", + "type": "str", + }, + ], + "optional_parameters": [ + { + "default": None, + "description": "Optional list of specific sections to retrieve ['indications_and_usage', 'contraindications', 'warnings', 'dosage_and_administration']", + "name": "sections", + "type": "List[str]", + }, + ], + }, + { + "description": "Check for FDA drug recalls and enforcement actions from the OpenFDA database to identify safety concerns and regulatory actions.", + "name": "check_fda_drug_recalls", + "required_parameters": [ + { + "default": None, + "description": "Name of the drug to check for recalls", + "name": "drug_name", + "type": "str", + }, + ], + "optional_parameters": [ + { + "default": None, + "description": "Optional filter by recall class ['Class I', 'Class II', 'Class III']", + "name": "classification", + "type": "List[str]", + }, + { + "default": None, + "description": "Optional date range for recalls as (start_date, end_date)", + "name": "date_range", + "type": "Tuple[str, str]", + }, + ], + }, + { + "description": "Analyze safety signals across multiple drugs using OpenFDA adverse event data to identify patterns and comparative risk profiles.", + "name": "analyze_fda_safety_signals", + "required_parameters": [ + { + "default": None, + "description": "List of drug names to analyze for safety signals", + "name": "drug_list", + "type": "List[str]", + }, + ], + "optional_parameters": [ + { + "default": None, + "description": "Optional comparison time period as (start_date, end_date)", + "name": "comparison_period", + "type": "Tuple[str, str]", + }, + { + "default": 2.0, + "description": "Threshold for signal detection", + "name": "signal_threshold", + "type": "float", + }, + ], + }, +] diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/physiology.py b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/physiology.py new file mode 100644 index 0000000000000000000000000000000000000000..7583ec7d9799eec48c7181ce132db34340a1c14f --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/physiology.py @@ -0,0 +1,363 @@ +description = [ + { + "description": "Generate a 3D model of facial anatomy from MRI scans of the head and neck.", + "name": "reconstruct_3d_face_from_mri", + "optional_parameters": [ + { + "default": "./output", + "description": "Directory where output files will be saved", + "name": "output_dir", + "type": "str", + }, + { + "default": "subject", + "description": "Identifier for the subject, used in output filenames", + "name": "subject_id", + "type": "str", + }, + { + "default": 300, + "description": "Threshold value for initial segmentation of facial tissues", + "name": "threshold_value", + "type": "int", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to the MRI scan file (NIfTI format: .nii or .nii.gz)", + "name": "mri_file_path", + "type": "str", + } + ], + }, + { + "description": "Extracts P1 amplitude and latency from Auditory Brainstem Response (ABR) waveform data.", + "name": "analyze_abr_waveform_p1_metrics", + "optional_parameters": [], + "required_parameters": [ + { + "default": None, + "description": "Time points of the ABR recording in milliseconds", + "name": "time_ms", + "type": "array-like", + }, + { + "default": None, + "description": "Amplitude values of the ABR recording in microvolts", + "name": "amplitude_uv", + "type": "array-like", + }, + ], + }, + { + "description": "Analyze ciliary beat frequency from high-speed video microscopy data using FFT analysis.", + "name": "analyze_ciliary_beat_frequency", + "optional_parameters": [ + { + "default": 5, + "description": "Number of regions of interest to analyze", + "name": "roi_count", + "type": "int", + }, + { + "default": 0, + "description": "Minimum frequency to consider in Hz", + "name": "min_freq", + "type": "float", + }, + { + "default": 30, + "description": "Maximum frequency to consider in Hz", + "name": "max_freq", + "type": "float", + }, + { + "default": "./", + "description": "Directory to save output files", + "name": "output_dir", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to the high-speed video microscopy file of ciliary beating", + "name": "video_path", + "type": "str", + } + ], + }, + { + "description": "Analyze colocalization between two fluorescently labeled proteins in microscopy images.", + "name": "analyze_protein_colocalization", + "optional_parameters": [ + { + "default": "./output", + "description": "Directory to save output files", + "name": "output_dir", + "type": "str", + }, + { + "default": "otsu", + "description": "Method for thresholding images ('otsu', 'li', or 'yen')", + "name": "threshold_method", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to the first channel image file (fluorescent protein 1)", + "name": "channel1_path", + "type": "str", + }, + { + "default": None, + "description": "Path to the second channel image file (fluorescent protein 2)", + "name": "channel2_path", + "type": "str", + }, + ], + }, + { + "description": "Performs cosinor analysis on physiological time series data to characterize circadian rhythms.", + "name": "perform_cosinor_analysis", + "optional_parameters": [ + { + "default": 24.0, + "description": "Period of the rhythm in hours, default is 24 hours for circadian rhythms", + "name": "period", + "type": "float", + } + ], + "required_parameters": [ + { + "default": None, + "description": "Time points of the measurements in hours", + "name": "time_data", + "type": "array-like", + }, + { + "default": None, + "description": "Physiological measurements corresponding to each time point", + "name": "physiological_data", + "type": "array-like", + }, + ], + }, + { + "description": "Calculate Apparent Diffusion Coefficient (ADC) map from " + "diffusion-weighted MRI data using monoexponential diffusion " + "model.", + "name": "calculate_brain_adc_map", + "optional_parameters": [ + { + "default": "adc_map.nii.gz", + "description": "Path where the output ADC map will be saved", + "name": "output_path", + "type": "str", + }, + { + "default": None, + "description": "Path to a binary mask file to limit ADC calculation to brain regions", + "name": "mask_file_path", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to the 4D NIfTI file containing diffusion-weighted MRI data", + "name": "dwi_file_path", + "type": "str", + }, + { + "default": None, + "description": "List of b-values corresponding to each volume in the 4D DWI data", + "name": "b_values", + "type": "List[float]", + }, + ], + }, + { + "description": "Analyze calcium dynamics in endo-lysosomal compartments using ELGA/ELGA1 probe data.", + "name": "analyze_endolysosomal_calcium_dynamics", + "optional_parameters": [ + { + "default": None, + "description": "Time point (in seconds) when treatment/stimulus was applied", + "name": "treatment_time", + "type": "float", + }, + { + "default": "", + "description": "Type of cells used in the experiment", + "name": "cell_type", + "type": "str", + }, + { + "default": "", + "description": "Name of the treatment or stimulus applied", + "name": "treatment_name", + "type": "str", + }, + { + "default": "calcium_analysis_results.txt", + "description": "Name of the file to save detailed analysis results", + "name": "output_file", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Time points of the measurements in seconds", + "name": "time_points", + "type": "numpy.ndarray or list", + }, + { + "default": None, + "description": "Luminescence intensity values from ELGA/ELGA1 probes corresponding to Ca2+ levels", + "name": "luminescence_values", + "type": "numpy.ndarray or list", + }, + ], + }, + { + "description": "Analyzes fatty acid composition in tissue samples using gas chromatography data.", + "name": "analyze_fatty_acid_composition_by_gc", + "optional_parameters": [ + { + "default": "./results", + "description": "Directory where result files will be saved", + "name": "output_directory", + "type": "str", + } + ], + "required_parameters": [ + { + "default": None, + "description": "Path to the CSV file containing gas " + "chromatography data with columns " + "'retention_time' and 'peak_area'", + "name": "gc_data_file", + "type": "str", + }, + { + "default": None, + "description": "Type of tissue sample (e.g., liver, kidney, heart, muscle, adipose)", + "name": "tissue_type", + "type": "str", + }, + { + "default": None, + "description": "Identifier for the sample being analyzed", + "name": "sample_id", + "type": "str", + }, + ], + }, + { + "description": "Analyzes raw blood pressure data to calculate key hemodynamic parameters.", + "name": "analyze_hemodynamic_data", + "optional_parameters": [ + { + "default": "hemodynamic_results.csv", + "description": "Filename to save the calculated parameters", + "name": "output_file", + "type": "str", + } + ], + "required_parameters": [ + { + "default": None, + "description": "Raw blood pressure measurements in mmHg", + "name": "pressure_data", + "type": "numpy.ndarray", + }, + { + "default": None, + "description": "Data acquisition rate in Hz (samples per second)", + "name": "sampling_rate", + "type": "float", + }, + ], + }, + { + "description": "Simulates the transport and binding of thyroid hormones " + "across different tissue compartments using an ODE-based " + "pharmacokinetic model.", + "name": "simulate_thyroid_hormone_pharmacokinetics", + "optional_parameters": [ + { + "default": "(0, 24)", + "description": "Start and end time for simulation in hours", + "name": "time_span", + "type": "tuple", + }, + { + "default": 100, + "description": "Number of time points to output", + "name": "time_points", + "type": "int", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Dictionary containing model " + "parameters including " + "transport_rates, binding_constants, " + "metabolism_rates, and volumes", + "name": "parameters", + "type": "dict", + }, + { + "default": None, + "description": "Dictionary of initial concentrations for all molecular species in each compartment", + "name": "initial_conditions", + "type": "dict", + }, + ], + }, + { + "description": "Analyzes an image to detect and quantify amyloid-beta " + "plaques, returning a detailed analysis log.", + "name": "quantify_amyloid_beta_plaques", + "optional_parameters": [ + { + "default": "./results", + "description": "Directory where results will be saved", + "name": "output_dir", + "type": "str", + }, + { + "default": "otsu", + "description": "Method for image thresholding (otsu, adaptive, or manual)", + "name": "threshold_method", + "type": "str", + }, + { + "default": 50, + "description": "Minimum size in pixels² for a region to be considered a plaque", + "name": "min_plaque_size", + "type": "int", + }, + { + "default": 127, + "description": "Threshold value to use when threshold_method is manual", + "name": "manual_threshold", + "type": "int", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to the image file to be analyzed for amyloid-beta plaques", + "name": "image_path", + "type": "str", + } + ], + }, +] diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/protocols.py b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/protocols.py new file mode 100644 index 0000000000000000000000000000000000000000..4cef1633267980a7b2c703ddffd8714f0e26841a --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/protocols.py @@ -0,0 +1,68 @@ +description = [ + { + "description": "Search protocols.io for public protocols matching a keyword.", + "name": "search_protocols", + "optional_parameters": [], + "required_parameters": [ + { + "default": None, + "description": "Most important keyword or phrase to search (title, description, authors)", + "name": "query", + "type": "str", + } + ], + }, + { + "description": "Retrieve detailed metadata for a specific protocols.io protocol by ID.", + "name": "get_protocol_details", + "optional_parameters": [ + { + "default": 30, + "description": "Request timeout in seconds", + "name": "timeout", + "type": "int", + } + ], + "required_parameters": [ + { + "default": None, + "description": "Numeric protocol ID from protocols.io", + "name": "protocol_id", + "type": "int", + } + ], + }, + { + "description": "List available protocol files in the local biomni/tool/protocols/ directory. Includes protocols from Addgene and Thermo Fisher Scientific.", + "name": "list_local_protocols", + "optional_parameters": [ + { + "default": None, + "description": "Filter by source directory (e.g., 'addgene' or 'thermofisher'). If None, lists all protocols.", + "name": "source", + "type": "str", + } + ], + "required_parameters": [], + }, + { + "description": "Read the contents of a local protocol file from biomni/tool/protocols/. Use list_local_protocols() first to find available protocol filenames.", + "name": "read_local_protocol", + "optional_parameters": [ + { + "default": None, + "description": "Source directory (e.g., 'addgene' or 'thermofisher'). If None, searches all sources.", + "name": "source", + "type": "str", + } + ], + "required_parameters": [ + { + "default": None, + "description": "Name of the protocol file (e.g., 'Addgene_ Protocol - How to Run an Agarose Gel.txt')", + "name": "filename", + "type": "str", + } + ], + }, +] diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/support_tools.py b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/support_tools.py new file mode 100644 index 0000000000000000000000000000000000000000..981325f8bbc769c5cb6b9658e6ad6ff012f998de --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/support_tools.py @@ -0,0 +1,74 @@ +description = [ + { + "description": "Executes the provided Python command in the notebook environment and returns the output.", + "name": "run_python_repl", + "optional_parameters": [], + "required_parameters": [ + { + "default": None, + "description": "Python command to execute in the notebook environment", + "name": "command", + "type": "str", + } + ], + }, + { + "description": "Read the source code of a function from any module path.", + "name": "read_function_source_code", + "optional_parameters": [], + "required_parameters": [ + { + "default": None, + "description": "Fully qualified function name " + "(e.g., " + "'bioagentos.tool.support_tools.write_python_code')", + "name": "function_name", + "type": "str", + } + ], + }, + { + "description": "Download data from Synapse using entity IDs. Requires SYNAPSE_AUTH_TOKEN environment variable for authentication. CRITICAL: Always specify entity_type parameter based on what you're downloading (file, dataset, folder, project). Check user hints like 'files' or search results to determine correct type. Multiple IDs only work with entity_type='file'. Recursive only works with entity_type='folder'.", + "name": "download_synapse_data", + "optional_parameters": [ + { + "name": "download_location", + "type": "str", + "description": "Directory where files will be downloaded", + "default": ".", + }, + { + "name": "follow_link", + "type": "bool", + "description": "Whether to follow links to download the linked entity", + "default": False, + }, + { + "name": "recursive", + "type": "bool", + "description": "Whether to recursively download folders and their contents. ONLY valid with entity_type='folder'", + "default": False, + }, + { + "name": "timeout", + "type": "int", + "description": "Timeout in seconds for each download operation", + "default": 300, + }, + { + "name": "entity_type", + "type": "str", + "description": "Type of Synapse entity: 'file', 'dataset', 'folder', or 'project'. MUST match actual entity type! Check user hints (e.g., 'files' means entity_type='file') or search results ('node_type' field). Default 'dataset' should only be used for actual datasets.", + "default": "dataset", + }, + ], + "required_parameters": [ + { + "name": "entity_ids", + "type": "str|list[str]", + "description": "Synapse entity ID(s) to download. For files: single ID or list of IDs. For datasets/folders/projects: single ID only", + "default": None, + } + ], + }, +] diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/synthetic_biology.py b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/synthetic_biology.py new file mode 100644 index 0000000000000000000000000000000000000000..ec12fd4b02d0e2f07f17b3db4828ee8774a3eb9d --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/synthetic_biology.py @@ -0,0 +1,273 @@ +description = [ + { + "description": "Engineer a bacterial genome by integrating therapeutic genetic parts for therapeutic delivery.", + "name": "engineer_bacterial_genome_for_therapeutic_delivery", + "optional_parameters": [], + "required_parameters": [ + { + "default": None, + "description": "Path to the file containing the bacterial genome sequence in FASTA format", + "name": "bacterial_genome_file", + "type": "str", + }, + { + "default": None, + "description": "Dictionary containing genetic parts " + "to be integrated (promoters, genes, " + "terminators, cargo)", + "name": "genetic_parts", + "type": "dict", + }, + ], + }, + { + "description": "Analyze bacterial growth data and extract growth parameters from OD600 measurements.", + "name": "analyze_bacterial_growth_rate", + "optional_parameters": [ + { + "default": "Unknown strain", + "description": "Name of the bacterial strain being analyzed", + "name": "strain_name", + "type": "str", + }, + { + "default": "./", + "description": "Directory where to save the output files", + "name": "output_dir", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Time points at which OD600 measurements were taken (in hours)", + "name": "time_points", + "type": "List or numpy.ndarray", + }, + { + "default": None, + "description": "Optical density (OD600) measurements corresponding to each time point", + "name": "od_measurements", + "type": "List or numpy.ndarray", + }, + ], + }, + { + "description": "Analyze sequencing data to extract, quantify and determine lineage relationships of barcodes.", + "name": "analyze_barcode_sequencing_data", + "optional_parameters": [ + { + "default": None, + "description": "Regular expression pattern to identify barcodes. If None, will use flanking sequences", + "name": "barcode_pattern", + "type": "str", + }, + { + "default": None, + "description": "5' flanking sequence of the barcode region", + "name": "flanking_seq_5prime", + "type": "str", + }, + { + "default": None, + "description": "3' flanking sequence of the barcode region", + "name": "flanking_seq_3prime", + "type": "str", + }, + { + "default": 5, + "description": "Minimum count threshold for considering a barcode", + "name": "min_count", + "type": "int", + }, + { + "default": "./results", + "description": "Directory to save output files", + "name": "output_dir", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to the input sequencing file in FASTQ or FASTA format", + "name": "input_file", + "type": "str", + } + ], + }, + { + "description": "Performs bifurcation analysis on a dynamical system and generates a bifurcation diagram.", + "name": "analyze_bifurcation_diagram", + "optional_parameters": [ + { + "default": "Dynamical System", + "description": "Name of the dynamical system being analyzed, used for plot titles.", + "name": "system_name", + "type": "str", + }, + { + "default": "./", + "description": "Directory to save the output files.", + "name": "output_dir", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "A 2D array where each row " + "represents a time series for a " + "specific parameter value. Shape " + "should be (n_parameter_values, " + "n_time_points).", + "name": "time_series_data", + "type": "numpy.ndarray", + }, + { + "default": None, + "description": "1D array of parameter values " + "corresponding to each time series. " + "Shape should be " + "(n_parameter_values,).", + "name": "parameter_values", + "type": "numpy.ndarray", + }, + ], + }, + { + "description": "Generate a mathematical model of a biochemical network in SBML format.", + "name": "create_biochemical_network_sbml_model", + "optional_parameters": [ + { + "default": "biochemical_model.xml", + "description": "File path to save the SBML model", + "name": "output_file", + "type": "str", + } + ], + "required_parameters": [ + { + "default": None, + "description": "List of dictionaries representing " + "reactions with id, name, reactants, " + "products, and reversible properties", + "name": "reaction_network", + "type": "List[dict]", + }, + { + "default": None, + "description": "Dictionary mapping reaction IDs to kinetic law parameters with law_type and parameters", + "name": "kinetic_parameters", + "type": "dict", + }, + ], + }, + { + "description": "Analyzes and optimizes a DNA/RNA sequence for improved " + "expression in a heterologous host organism.", + "name": "optimize_codons_for_heterologous_expression", + "optional_parameters": [], + "required_parameters": [ + { + "default": None, + "description": "The DNA or RNA sequence of the " + "target gene to be optimized. Should " + "contain complete codons (length " + "divisible by 3).", + "name": "target_sequence", + "type": "str", + }, + { + "default": None, + "description": "Dictionary mapping codons to their " + "usage frequency in the host " + "organism. Format: {'AUG': 0.8, " + "'GCC': 0.6, ...} or {'ATG': 0.8, " + "'GCC': 0.6, ...}", + "name": "host_codon_usage", + "type": "dict", + }, + ], + }, + { + "description": "Simulate gene regulatory circuit dynamics with growth feedback.", + "name": "simulate_gene_circuit_with_growth_feedback", + "optional_parameters": [ + { + "default": 100, + "description": "Total simulation time", + "name": "simulation_time", + "type": "float", + }, + { + "default": 1000, + "description": "Number of time points to sample", + "name": "time_points", + "type": "int", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Adjacency matrix representing the " + "gene circuit topology. Positive " + "values indicate activation, " + "negative values indicate " + "repression. Shape should be " + "(n_genes, n_genes) where n_genes is " + "the number of genes in the circuit.", + "name": "circuit_topology", + "type": "numpy.ndarray", + }, + { + "default": None, + "description": "Dictionary containing kinetic " + "parameters: 'basal_rates', " + "'degradation_rates', " + "'hill_coefficients', and " + "'threshold_constants' for the gene " + "circuit.", + "name": "kinetic_params", + "type": "dict", + }, + { + "default": None, + "description": "Dictionary containing " + "growth-related parameters: " + "'max_growth_rate', " + "'growth_inhibition', and " + "'gene_growth_weights'.", + "name": "growth_params", + "type": "dict", + }, + ], + }, + { + "description": "Identifies functional domains within a Fatty Acid Synthase " + "(FAS) sequence and predicts their roles.", + "name": "identify_fas_functional_domains", + "optional_parameters": [ + { + "default": "protein", + "description": 'Type of sequence provided - "protein" or "nucleotide"', + "name": "sequence_type", + "type": "str", + }, + { + "default": "fas_domains_report.txt", + "description": "Name of the output file to save the detailed domain report", + "name": "output_file", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "The nucleotide or protein sequence of a FAS gene", + "name": "sequence", + "type": "str", + } + ], + }, +] diff --git a/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/systems_biology.py b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/systems_biology.py new file mode 100644 index 0000000000000000000000000000000000000000..5c235abfd1e42744f5c65e6bad9662947b6057cb --- /dev/null +++ b/BioScientist/agent_system/engines/v1_executor_backup/tool/tool_description/systems_biology.py @@ -0,0 +1,235 @@ +description = [ + { + "description": "Perform Flux Balance Analysis (FBA) on a genome-scale " + "metabolic network model and return a research log of the " + "process and results.", + "name": "perform_flux_balance_analysis", + "optional_parameters": [ + { + "default": None, + "description": "Dictionary of reaction constraints " + "where keys are reaction IDs and " + "values are tuples of (lower_bound, " + "upper_bound)", + "name": "constraints", + "type": "dict", + }, + { + "default": None, + "description": "Reaction ID to use as the objective function (e.g., biomass reaction)", + "name": "objective_reaction", + "type": "str", + }, + { + "default": "fba_results.csv", + "description": "File name to save the flux distribution results", + "name": "output_file", + "type": "str", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to the metabolic model file (SBML or JSON format)", + "name": "model_file", + "type": "str", + } + ], + }, + { + "description": "Model protein dimerization networks to find equilibrium concentrations of dimers.", + "name": "model_protein_dimerization_network", + "optional_parameters": [], + "required_parameters": [ + { + "default": None, + "description": "Dictionary mapping monomer names to their initial concentrations (in arbitrary units)", + "name": "monomer_concentrations", + "type": "dict", + }, + { + "default": None, + "description": "Dictionary mapping dimer names (as 'A-B' strings) to their association constants (Ka)", + "name": "dimerization_affinities", + "type": "dict", + }, + { + "default": None, + "description": "List of (monomer1, monomer2) pairs that can form dimers", + "name": "network_topology", + "type": "list", + }, + ], + }, + { + "description": "Construct and simulate kinetic models of metabolic networks " + "and analyze their responses to perturbations.", + "name": "simulate_metabolic_network_perturbation", + "optional_parameters": [ + {"default": 100, "description": "Total simulation time", "name": "simulation_time", "type": "float"}, + {"default": 1000, "description": "Number of time points to simulate", "name": "time_points", "type": "int"}, + ], + "required_parameters": [ + { + "default": None, + "description": "Path to the COBRA model file (SBML format)", + "name": "model_file", + "type": "str", + }, + { + "default": None, + "description": "Dictionary mapping metabolite IDs to their initial concentrations", + "name": "initial_concentrations", + "type": "dict", + }, + { + "default": None, + "description": "Dictionary with keys 'time' " + "(float), 'metabolite' (str), and " + "'factor' (float) for perturbation " + "details", + "name": "perturbation_params", + "type": "dict", + }, + ], + }, + { + "description": "Simulate protein signaling network dynamics using ODE-based " + "logic modeling with normalized Hill functions.", + "name": "simulate_protein_signaling_network", + "optional_parameters": [ + { + "default": 100, + "description": "Total simulation time in arbitrary time units.", + "name": "simulation_time", + "type": "float", + }, + { + "default": 1000, + "description": "Number of time points for the simulation.", + "name": "time_points", + "type": "int", + }, + ], + "required_parameters": [ + { + "default": None, + "description": "Dictionary defining the network " + "topology. Each key is a target " + "protein and its value is a list of " + "tuples (regulator, regulation_type) " + "where regulation_type is 1 for " + "activation and -1 for inhibition.", + "name": "network_structure", + "type": "dict", + }, + { + "default": None, + "description": "Dictionary of reaction parameters. " + "Keys are tuples (regulator, target) " + "and values are dictionaries with " + "keys 'W' (weight), 'n' (Hill " + "coefficient), and 'EC50' " + "(half-maximal effective " + "concentration).", + "name": "reaction_params", + "type": "dict", + }, + { + "default": None, + "description": "Dictionary of species parameters. " + "Keys are protein names and values " + "are dictionaries with keys 'tau' " + "(time constant), 'y0' (initial " + "concentration), and 'ymax' (maximum " + "concentration).", + "name": "species_params", + "type": "dict", + }, + ], + }, + { + "description": "Compares two protein structures to identify structural differences and conformational changes.", + "name": "compare_protein_structures", + "optional_parameters": [ + { + "default": "A", + "description": "Chain ID to analyze in the first structure", + "name": "chain_id1", + "type": "str", + }, + { + "default": "A", + "description": "Chain ID to analyze in the second structure", + "name": "chain_id2", + "type": "str", + }, + { + "default": "protein_comparison", + "description": "Prefix for output files", + "name": "output_prefix", + "type": "str", + }, + ], + "required_parameters": [ + {"default": None, "description": "Path to the first PDB file", "name": "pdb_file1", "type": "str"}, + {"default": None, "description": "Path to the second PDB file", "name": "pdb_file2", "type": "str"}, + ], + }, + { + "description": "Simulate the time-dependent concentrations of renin-angiotensin system (RAS) components.", + "name": "simulate_renin_angiotensin_system_dynamics", + "optional_parameters": [ + { + "default": 48, + "description": "Total simulation time in hours", + "name": "simulation_time", + "type": "float", + }, + {"default": 100, "description": "Number of time points to evaluate", "name": "time_points", "type": "int"}, + ], + "required_parameters": [ + { + "default": None, + "description": "Initial concentrations of RAS " + "components with keys: 'renin', " + "'angiotensinogen', 'angiotensin_I', " + "'angiotensin_II', " + "'ACE2_angiotensin_II', " + "'angiotensin_1_7'", + "name": "initial_concentrations", + "type": "dict", + }, + { + "default": None, + "description": "Kinetic rate constants with keys: " + "'k_ren', 'k_agt', 'k_ace', " + "'k_ace2', 'k_at1r', 'k_mas'", + "name": "rate_constants", + "type": "dict", + }, + { + "default": None, + "description": "Parameters controlling feedback mechanisms with keys: 'fb_ang_II', 'fb_ace2'", + "name": "feedback_params", + "type": "dict", + }, + ], + }, + { + "description": "Answer functions and properties questions for DNA sequences ", + "name": "query_chatnt", + "optional_parameters": [ + { + "default": -1, + "description": "Device to use for the ChatNT model. Default is -1 (CPU).", + "name": "device", + "type": "int", + } + ], + "required_parameters": [ + {"default": "A", "description": "Questions about the DNA sequence", "name": "question", "type": "str"}, + {"default": "A", "description": "DNA sequence with potential functions", "name": "sequence", "type": "str"}, + ], + }, +] diff --git a/BioScientist/agent_system/toolbase/README.md b/BioScientist/agent_system/toolbase/README.md new file mode 100644 index 0000000000000000000000000000000000000000..9996a3d3a8df2266d7f85ee912a54124db6461c2 --- /dev/null +++ b/BioScientist/agent_system/toolbase/README.md @@ -0,0 +1,95 @@ +# Bioconda Tool Crawler (Tiered) + +该目录提供一个分层抓取脚本:`bioconda_crawler.py`,用于从 Bioconda 抓取工具元数据并按 `T0 / T1 / T2` 输出。 + +## 输出字段 + +每条记录至少包含: + +- `software_name` +- `package_name` +- `latest_version` +- `dependencies` +- `maintainers` +- `description` +- `summary` +- `license` +- `home_url` +- `doc_url` +- `dev_url` + +## 分层策略 + +- `T0`(核心层):按下载量自动选取 + - 各领域(单细胞/空间转录组/蛋白组/代谢组)按下载量取 Top-K + - 全部包再按下载量取整体 Top-K + - 合并去重后作为 T0 结果,不再硬编码固定名单 +- `T1`(扩展层):按关键词覆盖单细胞、空间转录组、蛋白组、代谢组工具 +- `T2`(长尾层):按需输入工具名动态抓取 + +## 快速开始 + +在项目根目录运行: + +```bash +python agent_system/toolbase/bioconda_crawler.py \ + --tiers ALL T0 T1 T2 \ + --subdirs linux-64 noarch \ + --downloads-source channel_api \ + --t0-k-per-domain 5 \ + --t0-k-overall 20 \ + --t1-max-per-domain 200 \ + --t1-target-total 600 \ + --t2-tools cellranger scanpy \ + --output-dir agent_system/toolbase/output +``` + +说明: + +- `ALL`:导出全量包索引(依赖来自 repodata,维护者默认空) +- `T0`:按累计下载量自动排序和筛选(结果包含 `downloads` 字段) +- `T0/T1/T2`:会进一步访问 Anaconda 包 API 补充维护者和描述等字段 +- `--t1-max-per-domain`:控制 T1 每个领域抓取上限(默认 200) +- `--t1-target-total`:控制 T1 总目标数量(默认 600,不足会从全局高下载包回填) +- `--downloads-source`: + - `channel_api`:优先使用频道级包列表接口抓下载量(默认) + - `package_api`:逐包查询下载量(可配合 `--package-api-max` 限制数量) + +## 结果文件 + +- `bioconda_all_packages_index.json` +- `bioconda_t0_core_tools.json` +- `bioconda_t1_domain_tools.json` +- `bioconda_t2_on_demand_tools.json` + +## 转换为 Converter 输入 + +使用 `prepare_converter_inputs.py` 将 `T0/T1/T2` 三份 JSON 转成 `tool2mcp.py` 可直接处理的格式,并可选生成每个工具的 help 文档: + +```bash +python agent_system/toolbase/prepare_converter_inputs.py \ + --input-dir agent_system/toolbase/output \ + --output-dir agent_system/toolbase/output \ + --conda-env bioinfomcp-env +``` + +常用输出: + +- `converter_input_t0.json` / `converter_input_t1.json` / `converter_input_t2.json` +- `converter_input_all.json`(可用于 `tool2mcp.py --tools_json`) +- `converter_jobs.json`(每个工具含 `manual` 和 `run_help_command`,可用于 `tool2mcp.py --jobs_json`) +- `help_index.json` 与 `help_docs/*.help.txt` +- `help_docs/*.manual_bundle.txt`(多源文档聚合:CLI help + URL 文档 + conda search --info) + +如果只做格式转换,不执行安装: + +```bash +python agent_system/toolbase/prepare_converter_inputs.py --skip-install +``` + +多元回退策略(自动): + +1. ` --help` +2. `python -m --help` +3. 抓取 `doc_url/home_url/dev_url` 网页文本 +4. `conda search --info` 元信息 diff --git a/BioScientist/agent_system/toolbase/annotate_runtime_env.py b/BioScientist/agent_system/toolbase/annotate_runtime_env.py new file mode 100644 index 0000000000000000000000000000000000000000..c897f30e115ffb27d46e831c934c61c8f8b19f86 --- /dev/null +++ b/BioScientist/agent_system/toolbase/annotate_runtime_env.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python3 +""" +Annotate runtime environment for Bioconda tool JSON files. + +Default targets: +- output/bioconda_source_tool/bioconda_t0_core_tools.json +- output/bioconda_source_tool/bioconda_t1_domain_tools.json +- output/bioconda_source_tool/bioconda_t2_on_demand_tools.json +""" + +from __future__ import annotations + +import argparse +import json +from pathlib import Path +from typing import Dict, List, Tuple + + +def _lower_list(values: List[str]) -> List[str]: + return [str(v).strip().lower() for v in values if str(v).strip()] + + +def infer_runtime(package_name: str, dependencies: List[str], summary: str, description: str) -> Tuple[str, str]: + pkg = package_name.lower() + deps = _lower_list(dependencies) + text = f"{summary} {description}".lower() + + # Rule 1: R ecosystem + if pkg.startswith("r-") or pkg.startswith("bioconductor-"): + return "R", "package_name prefix indicates R/Bioconductor ecosystem" + if any(d.startswith("r-") or "r-base" in d for d in deps): + return "R", "dependencies include r-base or r-* packages" + + # Rule 2: Perl ecosystem + if pkg.startswith("perl-") or any(d.startswith("perl-") or d == "perl" for d in deps): + return "Perl", "package/dependencies indicate Perl runtime" + + # Rule 3: Java ecosystem + if any("openjdk" in d or "default-jre" in d or d == "java" for d in deps): + return "Java", "dependencies include Java runtime (openjdk/jre)" + + # Rule 4: Python ecosystem + if any("python" in d for d in deps): + return "Python", "dependencies include python" + py_keywords = ("python", "pypi", "scanpy", "scvelo", "scvi", "anndata") + if any(k in text for k in py_keywords): + return "Python", "summary/description contains Python ecosystem keywords" + + # Rule 5: Mostly compiled binary style + compiled_markers = ("libgcc", "libstdcxx", "htslib", "zlib", "gcc", "gxx") + if any(any(m in d for m in compiled_markers) for d in deps): + return "Compiled", "dependencies suggest compiled/native executable" + + return "Other", "no strong signal for Python/R/Perl/Java; marked as Other" + + +def annotate_file(json_path: Path, inplace: bool = True) -> Dict[str, int]: + if not json_path.exists(): + return {"total": 0, "updated": 0} + + with json_path.open("r", encoding="utf-8") as f: + rows = json.load(f) + if not isinstance(rows, list): + raise ValueError(f"JSON root must be list: {json_path}") + + updated = 0 + for row in rows: + if not isinstance(row, dict): + continue + runtime, reason = infer_runtime( + package_name=str(row.get("package_name", "")).strip(), + dependencies=list(row.get("dependencies", []) or []), + summary=str(row.get("summary", "")).strip(), + description=str(row.get("description", "")).strip(), + ) + row["execution_environment"] = runtime + row["execution_environment_reason"] = reason + updated += 1 + + if inplace: + with json_path.open("w", encoding="utf-8") as f: + json.dump(rows, f, ensure_ascii=False, indent=2) + + return {"total": len(rows), "updated": updated} + + +def main() -> None: + parser = argparse.ArgumentParser(description="Add execution environment annotations to tool JSON files.") + parser.add_argument( + "--files", + nargs="*", + default=[ + "/225040511/project/BioScientist/agent_system/toolbase/output/bioconda_source_tool/bioconda_t0_core_tools.json", + "/225040511/project/BioScientist/agent_system/toolbase/output/bioconda_source_tool/bioconda_t1_domain_tools.json", + "/225040511/project/BioScientist/agent_system/toolbase/output/bioconda_source_tool/bioconda_t2_on_demand_tools.json", + ], + help="Target JSON files.", + ) + args = parser.parse_args() + + results = {} + for p in args.files: + path = Path(p) + stats = annotate_file(path, inplace=True) + results[str(path)] = stats + print(f"{path}: updated {stats['updated']}/{stats['total']}") + + report_path = Path("/225040511/project/BioScientist/agent_system/toolbase/output/bioconda_source_tool/runtime_annotation_report.json") + report_path.parent.mkdir(parents=True, exist_ok=True) + with report_path.open("w", encoding="utf-8") as f: + json.dump(results, f, ensure_ascii=False, indent=2) + print(f"Saved report: {report_path}") + + +if __name__ == "__main__": + main() diff --git a/BioScientist/agent_system/toolbase/bioconda_crawler.py b/BioScientist/agent_system/toolbase/bioconda_crawler.py new file mode 100644 index 0000000000000000000000000000000000000000..6df20599fc6fef3d00875b418299fd4e6e895d2f --- /dev/null +++ b/BioScientist/agent_system/toolbase/bioconda_crawler.py @@ -0,0 +1,646 @@ +#!/usr/bin/env python3 +""" +Bioconda package crawler with tiered export (T0 / T1 / T2). + +Data sources: +- https://conda.anaconda.org/bioconda//repodata.json +- https://api.anaconda.org/package/bioconda/ +""" + +from __future__ import annotations + +import argparse +import json +import time +from dataclasses import dataclass +from pathlib import Path +from typing import Any, Dict, Iterable, List, Optional, Set, Tuple + +import requests +from packaging.version import InvalidVersion, Version + + +REPO_BASE = "https://conda.anaconda.org/bioconda" +ANACONDA_PACKAGE_API = "https://api.anaconda.org/package/bioconda/{package_name}" +ANACONDA_CHANNEL_PACKAGES_API = "https://api.anaconda.org/packages/bioconda" + + +T1_DOMAIN_KEYWORDS = { + "single_cell": [ + "single-cell", + "single cell", + "scrna", + "scanpy", + "seurat", + "cellranger", + "scvelo", + "scvi", + ], + "spatial_transcriptomics": [ + "spatial", + "visium", + "stereoseq", + "spaceranger", + "squidpy", + "spatialde", + ], + "proteomics": [ + "proteomics", + "proteome", + "peptide", + "mass spectrometry", + "metaproteomics", + ], + "metabolomics": [ + "metabolomics", + "metabolome", + "metabolic profiling", + "lipidomics", + "lc-ms", + ], +} + + +@dataclass +class PackageRecord: + package_name: str + latest_version: str + build_number: int + depends: List[str] + subdir: str + timestamp: int + repodata_summary: str = "" + downloads: int = -1 + + +def _safe_version(raw_version: str) -> Version: + try: + return Version(raw_version) + except InvalidVersion: + return Version("0") + + +def fetch_repodata(subdir: str, timeout: int = 60) -> Dict: + url = f"{REPO_BASE}/{subdir}/repodata.json" + response = requests.get(url, timeout=timeout) + response.raise_for_status() + return response.json() + + +def iter_repodata_packages(payload: Dict) -> Iterable[Tuple[str, Dict]]: + for section in ("packages", "packages.conda"): + for filename, meta in payload.get(section, {}).items(): + yield filename, meta + + +def build_latest_index(subdirs: List[str]) -> Dict[str, PackageRecord]: + latest: Dict[str, PackageRecord] = {} + + for subdir in subdirs: + payload = fetch_repodata(subdir=subdir) + for _filename, meta in iter_repodata_packages(payload): + pkg_name = meta.get("name") + version = meta.get("version", "") + build_number = int(meta.get("build_number", 0)) + depends = meta.get("depends", []) or [] + timestamp = int(meta.get("timestamp", 0)) + repodata_summary = meta.get("summary", "") or "" + if not pkg_name: + continue + + candidate = PackageRecord( + package_name=pkg_name, + latest_version=version, + build_number=build_number, + depends=depends, + subdir=subdir, + timestamp=timestamp, + repodata_summary=repodata_summary, + ) + + if pkg_name not in latest: + latest[pkg_name] = candidate + continue + + current = latest[pkg_name] + candidate_key = (_safe_version(candidate.latest_version), candidate.build_number, candidate.timestamp) + current_key = (_safe_version(current.latest_version), current.build_number, current.timestamp) + if candidate_key > current_key: + latest[pkg_name] = candidate + + return latest + + +def _normalize_owners(owners_field) -> List[str]: + if not owners_field: + return [] + owners: List[str] = [] + for item in owners_field: + if isinstance(item, str): + owners.append(item) + elif isinstance(item, dict): + login = item.get("login") or item.get("name") + if login: + owners.append(login) + return sorted(set(owners)) + + +def fetch_package_profile(package_name: str, timeout: int = 30) -> Dict: + url = ANACONDA_PACKAGE_API.format(package_name=package_name) + response = requests.get(url, timeout=timeout) + if response.status_code == 404: + return {} + response.raise_for_status() + return response.json() + + +def extract_download_count(profile: Dict[str, Any]) -> int: + for key in ("ndownloads", "downloads", "download_count"): + value = profile.get(key) + if isinstance(value, int): + return value + if isinstance(value, str) and value.isdigit(): + return int(value) + return -1 + + +def _match_any_keyword(text: str, keywords: List[str]) -> bool: + low = text.lower() + return any(keyword in low for keyword in keywords) + + +def _decode_channel_packages_payload(payload: Any) -> Dict[str, int]: + result: Dict[str, int] = {} + if isinstance(payload, list): + entries = payload + elif isinstance(payload, dict): + entries = payload.get("items") or payload.get("packages") or [] + else: + entries = [] + + for item in entries: + if not isinstance(item, dict): + continue + pkg_name = item.get("name") + if not pkg_name: + continue + result[pkg_name] = max(result.get(pkg_name, -1), extract_download_count(item)) + return result + + +def fetch_download_index_from_channel_api(timeout: int = 60, max_pages: int = 50) -> Dict[str, int]: + download_index: Dict[str, int] = {} + page = 1 + while True: + params = {"page": page} + response = requests.get(ANACONDA_CHANNEL_PACKAGES_API, params=params, timeout=timeout) + response.raise_for_status() + payload = response.json() + current_page = _decode_channel_packages_payload(payload) + + if not current_page: + if page == 1: + current_page = _decode_channel_packages_payload(payload) + if not current_page: + break + + for pkg_name, downloads in current_page.items(): + download_index[pkg_name] = max(download_index.get(pkg_name, -1), downloads) + + if isinstance(payload, list): + break + + total_pages = payload.get("total_pages") + next_page = payload.get("next_page") + if isinstance(total_pages, int) and page >= total_pages: + break + if next_page is None and not payload.get("items"): + break + page += 1 + if page > max_pages: + break + + return download_index + + +def build_download_index_from_package_api( + index: Dict[str, PackageRecord], + profile_cache: Dict[str, Dict], + timeout: int = 30, + sleep_seconds: float = 0.05, + max_packages: int = 0, +) -> Dict[str, int]: + download_index: Dict[str, int] = {} + package_names = sorted(index.keys()) + if max_packages > 0: + package_names = package_names[:max_packages] + + for package_name in package_names: + profile = profile_cache.get(package_name) + if profile is None: + profile = fetch_package_profile(package_name=package_name, timeout=timeout) + profile_cache[package_name] = profile + if sleep_seconds > 0: + time.sleep(sleep_seconds) + download_index[package_name] = extract_download_count(profile) + return download_index + + +def resolve_download_index( + index: Dict[str, PackageRecord], + download_source: str, + profile_cache: Dict[str, Dict], + package_api_max: int, +) -> Dict[str, int]: + print(f"max packages for package_api mode: {package_api_max}") + if download_source == "channel_api": + try: + print("Fetching download index from channel API...") + return fetch_download_index_from_channel_api() + + except Exception: + print("Failed to fetch download index from channel API, falling back to package API...") + return build_download_index_from_package_api( + index=index, + profile_cache=profile_cache, + max_packages=package_api_max, + ) + return build_download_index_from_package_api( + index=index, + profile_cache=profile_cache, + max_packages=package_api_max, + ) + + +def _sorted_by_download(items: List[Tuple[str, PackageRecord]]) -> List[Tuple[str, PackageRecord]]: + return sorted( + items, + key=lambda x: (x[1].downloads, _safe_version(x[1].latest_version), x[1].timestamp), + reverse=True, + ) + + +def select_t0_records( + index: Dict[str, PackageRecord], + k_per_domain: int, + k_overall: int, +) -> List[Tuple[str, PackageRecord, str]]: + selected: List[Tuple[str, PackageRecord, str]] = [] + selected_names: Set[str] = set() + + for domain, keywords in T1_DOMAIN_KEYWORDS.items(): + domain_candidates: List[Tuple[str, PackageRecord]] = [] + for package_name, record in index.items(): + searchable = f"{package_name} {record.repodata_summary}" + if _match_any_keyword(searchable, keywords): + domain_candidates.append((package_name, record)) + + ranked_domain = _sorted_by_download(domain_candidates) + for package_name, record in ranked_domain[:k_per_domain]: + if package_name in selected_names: + continue + selected.append((package_name, record, domain)) + selected_names.add(package_name) + + overall_candidates = _sorted_by_download(list(index.items())) + for package_name, record in overall_candidates[:k_overall]: + if package_name in selected_names: + continue + selected.append((package_name, record, "overall")) + selected_names.add(package_name) + + return selected + + +def select_t1_records(index: Dict[str, PackageRecord], max_per_domain: int) -> List[Tuple[str, PackageRecord, str]]: + selected: List[Tuple[str, PackageRecord, str]] = [] + used: Set[str] = set() + + for domain, keywords in T1_DOMAIN_KEYWORDS.items(): + counter = 0 + domain_candidates: List[Tuple[str, PackageRecord]] = [] + for package_name, record in index.items(): + if package_name in used: + continue + dep_text = " ".join(record.depends) + searchable = f"{package_name} {record.repodata_summary} {dep_text}" + if _match_any_keyword(searchable, keywords): + domain_candidates.append((package_name, record)) + + # Prefer higher-download tools first for better practical coverage. + ranked_domain = _sorted_by_download(domain_candidates) + for package_name, record in ranked_domain[:max_per_domain]: + if package_name in used: + continue + selected.append((package_name, record, domain)) + used.add(package_name) + counter += 1 + if counter >= max_per_domain: + break + return selected + + +def backfill_t1_records( + index: Dict[str, PackageRecord], + selected: List[Tuple[str, PackageRecord, str]], + target_total: int, +) -> List[Tuple[str, PackageRecord, str]]: + if target_total <= 0 or len(selected) >= target_total: + return selected + + used = {pkg for pkg, _record, _domain in selected} + ranked_overall = _sorted_by_download(list(index.items())) + for package_name, record in ranked_overall: + if package_name in used: + continue + selected.append((package_name, record, "t1_backfill_overall")) + used.add(package_name) + if len(selected) >= target_total: + break + return selected + + +def select_t2_records(index: Dict[str, PackageRecord], tools: List[str]) -> List[Tuple[str, PackageRecord]]: + selected: List[Tuple[str, PackageRecord]] = [] + for tool in tools: + normalized = tool.strip() + if not normalized: + continue + lower_map = {name.lower(): name for name in index.keys()} + hit = lower_map.get(normalized.lower()) + if hit: + selected.append((normalized, index[hit])) + return selected + + +def enrich_record( + software_name: str, + record: PackageRecord, + tier: str, + domain: Optional[str] = None, + sleep_seconds: float = 0.2, + profile_cache: Optional[Dict[str, Dict]] = None, +) -> Dict: + profile_cache = profile_cache or {} + profile = profile_cache.get(record.package_name) + if profile is None: + profile = fetch_package_profile(record.package_name) + profile_cache[record.package_name] = profile + if sleep_seconds > 0: + time.sleep(sleep_seconds) + + maintainers = _normalize_owners(profile.get("owners")) + summary = profile.get("summary") or record.repodata_summary or "" + description = profile.get("description") or summary + latest_version = profile.get("latest_version") or record.latest_version + downloads = record.downloads if record.downloads >= 0 else extract_download_count(profile) + + return { + "tier": tier, + "domain": domain or "", + "software_name": software_name, + "package_name": record.package_name, + "latest_version": latest_version, + "dependencies": record.depends, + "maintainers": maintainers, + "description": description, + "summary": summary, + "downloads": downloads, + "license": profile.get("license") or "", + "home_url": profile.get("home") or "", + "doc_url": profile.get("doc_url") or "", + "dev_url": profile.get("dev_url") or "", + "source_subdir": record.subdir, + "timestamp": record.timestamp, + } + + +def export_json(data: List[Dict], output_file: Path) -> None: + output_file.parent.mkdir(parents=True, exist_ok=True) + with output_file.open("w", encoding="utf-8") as f: + json.dump(data, f, ensure_ascii=False, indent=2) + + +def run_t0( + index: Dict[str, PackageRecord], + output_dir: Path, + k_per_domain: int, + k_overall: int, + profile_cache: Dict[str, Dict], +) -> List[Dict]: + result: List[Dict] = [] + for software_name, record, domain in select_t0_records(index, k_per_domain=k_per_domain, k_overall=k_overall): + result.append( + enrich_record( + software_name=software_name, + record=record, + tier="T0", + domain=domain, + profile_cache=profile_cache, + ) + ) + export_json(result, output_dir / "bioconda_t0_core_tools.json") + return result + + +def run_t1( + index: Dict[str, PackageRecord], + output_dir: Path, + max_per_domain: int, + profile_cache: Dict[str, Dict], + target_total: int, +) -> List[Dict]: + result: List[Dict] = [] + selected = select_t1_records(index=index, max_per_domain=max_per_domain) + selected = backfill_t1_records(index=index, selected=selected, target_total=target_total) + for software_name, record, domain in selected: + result.append( + enrich_record( + software_name=software_name, + record=record, + tier="T1", + domain=domain, + profile_cache=profile_cache, + ) + ) + export_json(result, output_dir / "bioconda_t1_domain_tools.json") + return result + + +def run_t2( + index: Dict[str, PackageRecord], + output_dir: Path, + t2_tools: List[str], + profile_cache: Dict[str, Dict], +) -> List[Dict]: + result: List[Dict] = [] + selected = select_t2_records(index=index, tools=t2_tools) + for software_name, record in selected: + result.append( + enrich_record( + software_name=software_name, + record=record, + tier="T2", + profile_cache=profile_cache, + ) + ) + export_json(result, output_dir / "bioconda_t2_on_demand_tools.json") + return result + + +def run_all_package_index(index: Dict[str, PackageRecord], output_dir: Path) -> None: + rows = [] + for package_name, record in sorted(index.items()): + rows.append( + { + "software_name": package_name, + "package_name": package_name, + "latest_version": record.latest_version, + "dependencies": record.depends, + "maintainers": [], + "description": record.repodata_summary, + "summary": record.repodata_summary, + "downloads": record.downloads, + "license": "", + "home_url": "", + "doc_url": "", + "dev_url": "", + "source_subdir": record.subdir, + "timestamp": record.timestamp, + } + ) + export_json(rows, output_dir / "bioconda_all_packages_index.json") + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser( + description="Crawl Bioconda package metadata in a tiered manner (T0/T1/T2)." + ) + parser.add_argument( + "--tiers", + nargs="+", + default=["T0", "T1", "T2"], + choices=["T0", "T1", "T2", "ALL"], + help="Which tiers to run. Use ALL to export whole package index from repodata.", + ) + parser.add_argument( + "--subdirs", + nargs="+", + default=["linux-64", "noarch"], + help="Bioconda subdirs to index, e.g. linux-64 noarch osx-64.", + ) + parser.add_argument( + "--output-dir", + default="./output", + help="Directory for output JSON files.", + ) + parser.add_argument( + "--t2-tools", + nargs="*", + default=[], + help="Tools for T2 on-demand crawling, e.g. --t2-tools cellranger scanpy", + ) + parser.add_argument( + "--t1-max-per-domain", + type=int, + default=200, + help="Max selected packages per T1 domain.", + ) + parser.add_argument( + "--t1-target-total", + type=int, + default=600, + help="Target total rows for T1. Uses overall backfill when domain matches are insufficient.", + ) + parser.add_argument( + "--downloads-source", + choices=["channel_api", "package_api"], + default="channel_api", + help="Download ranking source. channel_api first, package_api is fallback or explicit mode.", + ) + parser.add_argument( + "--t0-k-per-domain", + type=int, + default=5, + help="T0: top K packages per domain ranked by downloads.", + ) + parser.add_argument( + "--t0-k-overall", + type=int, + default=20, + help="T0: top K packages in overall ranking by downloads.", + ) + parser.add_argument( + "--package-api-max", + type=int, + default=0, + help="Max packages for package_api mode (0 means all indexed packages).", + ) + return parser.parse_args() + + +def main() -> None: + args = parse_args() + output_dir = Path(args.output_dir) + output_dir.mkdir(parents=True, exist_ok=True) + + print(f"[1/4] Building Bioconda latest-package index from subdirs: {args.subdirs}") + latest_index = build_latest_index(subdirs=args.subdirs) + print(f" Indexed packages: {len(latest_index)}") + profile_cache: Dict[str, Dict] = {} + + print("[2/4] Resolving package download counts...") + download_index = resolve_download_index( + index=latest_index, + download_source=args.downloads_source, + profile_cache=profile_cache, + package_api_max=args.package_api_max, + ) + for package_name, record in latest_index.items(): + record.downloads = download_index.get(package_name, -1) + known_downloads = sum(1 for r in latest_index.values() if r.downloads >= 0) + print(f" Packages with download count: {known_downloads}") + + run_all = "ALL" in args.tiers + if run_all: + print("[3/4] Exporting full package index...") + run_all_package_index(index=latest_index, output_dir=output_dir) + print(" -> bioconda_all_packages_index.json") + + if "T0" in args.tiers: + print("[4/4] Running T0 core tools (auto top-k by downloads)...") + t0_rows = run_t0( + index=latest_index, + output_dir=output_dir, + k_per_domain=args.t0_k_per_domain, + k_overall=args.t0_k_overall, + profile_cache=profile_cache, + ) + print(f" -> bioconda_t0_core_tools.json ({len(t0_rows)} rows)") + + if "T1" in args.tiers: + print("[4/4] Running T1 domain tools...") + t1_rows = run_t1( + index=latest_index, + output_dir=output_dir, + max_per_domain=args.t1_max_per_domain, + profile_cache=profile_cache, + target_total=args.t1_target_total, + ) + print(f" -> bioconda_t1_domain_tools.json ({len(t1_rows)} rows)") + + if "T2" in args.tiers: + print("[4/4] Running T2 on-demand tools...") + t2_rows = run_t2( + index=latest_index, + output_dir=output_dir, + t2_tools=args.t2_tools, + profile_cache=profile_cache, + ) + print(f" -> bioconda_t2_on_demand_tools.json ({len(t2_rows)} rows)") + + print("Done.") + + +if __name__ == "__main__": + main() diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/conversion_report.json b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/conversion_report.json new file mode 100644 index 0000000000000000000000000000000000000000..a63546d7dce4b8096ee0782c29f56f2e37222dd6 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/conversion_report.json @@ -0,0 +1,623 @@ +[ + { + "tool_name": "abyss", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/abyss.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_abyss/app/abyss_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "augustus", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/augustus.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_augustus/app/augustus_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "bamtools", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/bamtools.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bamtools/app/bamtools_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "bbmap", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/bbmap.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bbmap/app/bbmap_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "bcftools", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/bcftools.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bcftools/app/bcftools_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "bedtools", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/bedtools.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bedtools/app/bedtools_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "bioconductor-annotate", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/bioconductor-annotate.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotate/app/bioconductor-annotate_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "bioconductor-annotationdbi", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/bioconductor-annotationdbi.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotationdbi/app/bioconductor-annotationdbi_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "bioconductor-apeglm", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/bioconductor-apeglm.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-apeglm/app/bioconductor-apeglm_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "bioconductor-beachmat", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/bioconductor-beachmat.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-beachmat/app/bioconductor-beachmat_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "bioconductor-biobase", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/bioconductor-biobase.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biobase/app/bioconductor-biobase_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "bioconductor-biocgenerics", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/bioconductor-biocgenerics.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocgenerics/app/bioconductor-biocgenerics_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "bioconductor-biocneighbors", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/bioconductor-biocneighbors.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocneighbors/app/bioconductor-biocneighbors_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "bioconductor-biocparallel", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/bioconductor-biocparallel.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocparallel/app/bioconductor-biocparallel_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "bioconductor-biocsingular", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/bioconductor-biocsingular.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocsingular/app/bioconductor-biocsingular_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "bioconductor-biomart", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/bioconductor-biomart.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biomart/app/bioconductor-biomart_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "bioconductor-biostrings", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/bioconductor-biostrings.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biostrings/app/bioconductor-biostrings_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "bioconductor-clustifyr", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/bioconductor-clustifyr.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-clustifyr/app/bioconductor-clustifyr_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "bioconductor-cytomapper", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/bioconductor-cytomapper.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-cytomapper/app/bioconductor-cytomapper_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "bioconductor-gsva", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/bioconductor-gsva.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gsva/app/bioconductor-gsva_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "bioconductor-infercnv", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/bioconductor-infercnv.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-infercnv/app/bioconductor-infercnv_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "bioconductor-metabolomicsworkbenchr", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/bioconductor-metabolomicsworkbenchr.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-metabolomicsworkbenchr/app/bioconductor-metabolomicsworkbenchr_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "bioconductor-mosim", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/bioconductor-mosim.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-mosim/app/bioconductor-mosim_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "bioconductor-nebulosa", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/bioconductor-nebulosa.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-nebulosa/app/bioconductor-nebulosa_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "bioconductor-phemd", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/bioconductor-phemd.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-phemd/app/bioconductor-phemd_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "bioconductor-proteomicsannotationhubdata", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/bioconductor-proteomicsannotationhubdata.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-proteomicsannotationhubdata/app/bioconductor-proteomicsannotationhubdata_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "bioconductor-rforproteomics", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/bioconductor-rforproteomics.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rforproteomics/app/bioconductor-rforproteomics_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "bioconductor-scbfa", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/bioconductor-scbfa.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scbfa/app/bioconductor-scbfa_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "bioconductor-sccb2", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/bioconductor-sccb2.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-sccb2/app/bioconductor-sccb2_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "bioconductor-scdataviz", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/bioconductor-scdataviz.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scdataviz/app/bioconductor-scdataviz_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "bioconductor-scmageck", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/bioconductor-scmageck.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scmageck/app/bioconductor-scmageck_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "bioconductor-screpertoire", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/bioconductor-screpertoire.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-screpertoire/app/bioconductor-screpertoire_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "bioconductor-scrnaseq", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/bioconductor-scrnaseq.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scrnaseq/app/bioconductor-scrnaseq_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "bioconductor-singlecellmultimodal", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/bioconductor-singlecellmultimodal.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-singlecellmultimodal/app/bioconductor-singlecellmultimodal_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "bioconductor-spaniel", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/bioconductor-spaniel.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spaniel/app/bioconductor-spaniel_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "bioconductor-spatialcpie", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/bioconductor-spatialcpie.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spatialcpie/app/bioconductor-spatialcpie_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "bioconductor-spatialdecon", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/bioconductor-spatialdecon.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spatialdecon/app/bioconductor-spatialdecon_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "bioconductor-spatialexperiment", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/bioconductor-spatialexperiment.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spatialexperiment/app/bioconductor-spatialexperiment_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "bioconductor-spatialheatmap", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/bioconductor-spatialheatmap.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spatialheatmap/app/bioconductor-spatialheatmap_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "brooklyn_plot", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/brooklyn_plot.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_brooklyn_plot/app/brooklyn_plot_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "bwa", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/bwa.help.txt", + "run_help_command": false, + "status": "success", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bwa/app/bwa_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "cellrank", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/cellrank.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cellrank/app/cellrank_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "celltypist", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/celltypist.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_celltypist/app/celltypist_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "cnmf", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/cnmf.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cnmf/app/cnmf_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "cytotrace2-python", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/cytotrace2-python.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cytotrace2-python/app/cytotrace2-python_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "decoupler", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/decoupler.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_decoupler/app/decoupler_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "gsmap", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/gsmap.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_gsmap/app/gsmap_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "last", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/last.help.txt", + "run_help_command": false, + "status": "success", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_last/app/last_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "multivelo", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/multivelo.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_multivelo/app/multivelo_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "peptide-shaker", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/peptide-shaker.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_peptide-shaker/app/peptide-shaker_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "perl-metabolomics-fragment-annotation", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/perl-metabolomics-fragment-annotation.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_perl-metabolomics-fragment-annotation/app/perl-metabolomics-fragment-annotation_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "picard", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/picard.help.txt", + "run_help_command": false, + "status": "success", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_picard/app/picard_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "proteomiqon-peptidedb", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/proteomiqon-peptidedb.help.txt", + "run_help_command": false, + "status": "success", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_proteomiqon-peptidedb/app/proteomiqon-peptidedb_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "pycistopic", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/pycistopic.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_pycistopic/app/pycistopic_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "pyroe", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/pyroe.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_pyroe/app/pyroe_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "r-scpred", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/r-scpred.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-scpred/app/r-scpred_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "r-seurat", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/r-seurat.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-seurat/app/r-seurat_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "r-seurat-scripts", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/r-seurat-scripts.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-seurat-scripts/app/r-seurat-scripts_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "r-signac", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/r-signac.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-signac/app/r-signac_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "samtools", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/samtools.help.txt", + "run_help_command": false, + "status": "success", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_samtools/app/samtools_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "scanpy", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/scanpy.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scanpy/app/scanpy_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "scar", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/scar.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scar/app/scar_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "scarches", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/scarches.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scarches/app/scarches_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "sccaf", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/sccaf.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_sccaf/app/sccaf_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "scelvis", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/scelvis.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scelvis/app/scelvis_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "scpred-cli", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/scpred-cli.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scpred-cli/app/scpred-cli_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "scvelo", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/scvelo.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scvelo/app/scvelo_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "seurat-scripts", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/seurat-scripts.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_seurat-scripts/app/seurat-scripts_server.py", + "dockerfile_ready": true + }, + { + "tool_name": "snp2cell", + "manual": "/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt/snp2cell.help.txt", + "run_help_command": false, + "status": "skipped_existing", + "error": "", + "output_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_snp2cell/app/snp2cell_server.py", + "dockerfile_ready": true + } +] \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_abundancebin/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_abundancebin/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..bef882fc9d87ab2e0ff61be73df1c30027f57489 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_abundancebin/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install abundancebin via conda (e.g., from bioconda) +RUN conda install -c bioconda abundancebin -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY app/abundancebin_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/abundancebin_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/abundancebin_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_abundancebin/app/abundancebin_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_abundancebin/app/abundancebin_server.py new file mode 100644 index 0000000000000000000000000000000000000000..49605f4c464aa9f218612597833a995e25dc3c0d --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_abundancebin/app/abundancebin_server.py @@ -0,0 +1,128 @@ +import subprocess +import logging +from pathlib import Path +from typing import Optional, List + +# Assume @mcp.tool() is defined in the execution environment. +# No import is needed for the final code. + +# Set up logging +logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') +logger = logging.getLogger(__name__) + +@mcp.tool() +def abundancebin( + input_file: Path, + kmer_len: int = 20, + output: Optional[Path] = None, + exclude: Optional[int] = None, + exclude_max: Optional[int] = None, + output_fasta: bool = False, + bin_num: Optional[int] = None, + recursive_classification: bool = False, +): + """ + Performs abundance-based binning on a given input FASTA/FASTQ file. + + This tool uses k-mer frequency to classify sequences into bins. It can either + classify into a specified number of bins or use a recursive classification approach. + + Args: + input_file: Path to the input FASTA/FASTQ file. + kmer_len: The length of the k-mer to use for composition analysis (default: 20). + output: Path to the output log file. If not provided, defaults to '.log'. + exclude: Exclude contigs with coverage lower than this count. + exclude_max: Exclude contigs with coverage higher than this count. + output_fasta: If True, output binned sequences into separate FASTA files. + bin_num: The specific number of bins to classify sequences into. + recursive_classification: If True, undergo recursive classification instead of specifying a bin number. + This is mutually exclusive with 'bin_num'. + + Returns: + A dictionary containing the execution details and paths to output files. + """ + # 1. Input Validation + if not input_file.is_file(): + raise FileNotFoundError(f"Input file not found: {input_file}") + + if bin_num is not None and recursive_classification: + raise ValueError("Parameters 'bin_num' and 'recursive_classification' are mutually exclusive. Please provide only one.") + + if kmer_len <= 0: + raise ValueError("kmer_len must be a positive integer.") + + # 2. Command Construction + # Determine the output file path based on the tool's default behavior + if output: + output_path = output + else: + output_path = input_file.with_suffix(".log") + + # Ensure the output directory exists + output_path.parent.mkdir(parents=True, exist_ok=True) + + cmd = [ + "abundancebin", + "-input", str(input_file), + "-kmer_len", str(kmer_len), + "-output", str(output_path) + ] + + if exclude is not None: + cmd.extend(["-exclude", str(exclude)]) + + if exclude_max is not None: + cmd.extend(["-exclude_max", str(exclude_max)]) + + if output_fasta: + cmd.append("-OUTPUT_FASTA") + + if bin_num is not None: + cmd.extend(["-bin_num", str(bin_num)]) + + if recursive_classification: + cmd.append("-RECURSIVE_CLASSIFICATION") + + command_executed = " ".join(cmd) + logger.info(f"Executing command: {command_executed}") + + # 3. Subprocess Execution and Error Handling + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True + ) + + # The tool might generate more files if -OUTPUT_FASTA is used. + # For simplicity, we return the main log file. The user can infer others. + output_files = [str(output_path)] if output_path.exists() else [] + + # 4. Structured Result Return (Success) + return { + "command_executed": command_executed, + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": output_files + } + + except FileNotFoundError: + error_message = "abundancebin command not found. Please ensure the tool is installed and in your system's PATH." + logger.error(error_message) + # Re-raising is often better to signal a fatal environment error. + raise RuntimeError(error_message) from None + + except subprocess.CalledProcessError as e: + logger.error(f"abundancebin failed with exit code {e.returncode}") + logger.error(f"Stderr: {e.stderr}") + logger.error(f"Stdout: {e.stdout}") + + # 4. Structured Result Return (Failure) + return { + "command_executed": command_executed, + "stdout": e.stdout, + "stderr": e.stderr, + "return_code": e.returncode, + "output_files": [] + } \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_abundancebin/app/abundancebin_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_abundancebin/app/abundancebin_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..a1c20e1fc3ada48b9c58607cabf3ea25c4564c12 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_abundancebin/app/abundancebin_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_abundancebin/app/abundancebin_server.py') +SERVER_NAME = 'biosci_abundancebin' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_abundancebin/app/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_abundancebin/app/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_abundancebin/app/requirements.txt @@ -0,0 +1 @@ + diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_abundancebin/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_abundancebin/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..c3e728f0802fb0284f48f87c588f826b60f324c2 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_abundancebin/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-abundancebin: + build: . + image: mcp-abundancebin:latest + container_name: mcp-abundancebin + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=abundancebin + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_abundancebin/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_abundancebin/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..fb3f2d4c33b5cfc882a79148b0d58be0b05b89bc --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_abundancebin/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - abundancebin + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_abundancebin/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_abundancebin/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_abundancebin/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_augustus/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_augustus/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..c0a94be1323010919b7cb28347b5292c858b85d4 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_augustus/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install augustus via conda (e.g., from bioconda) +RUN conda install -c bioconda augustus -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY augustus_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/augustus_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/augustus_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_augustus/app/augustus_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_augustus/app/augustus_server.py new file mode 100644 index 0000000000000000000000000000000000000000..ada35adfe18bc95d0db30fe0ee9900a35bf1c03b --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_augustus/app/augustus_server.py @@ -0,0 +1,149 @@ +import subprocess +import logging +from pathlib import Path +from typing import Optional, List, Literal + +# Assume mcp.tool is available in the execution environment. +# Since we are not importing it, we can define a dummy decorator +# to make the code syntactically valid. +class mcp: + def tool(func): + return func + +@mcp.tool +def augustus( + query_file: Path, + species: str, + strand: Literal["both", "forward", "backward"] = "both", + genemodel: Literal["partial", "intronless", "complete", "atleastone", "exactlyone"] = "partial", + outfile: Optional[Path] = None, + hints_file: Optional[Path] = None, + gff3: bool = False, + utr: bool = False, + singlestrand: bool = False, + protein: bool = True, + introns: bool = True, + start: bool = True, + stop: bool = True, + cds: bool = True, + codingseq: bool = False, + no_in_frame_stop: bool = False, + alternatives_from_evidence: bool = True, + alternatives_from_sampling: bool = False, + sample: Optional[int] = None, + keep_viterbi: bool = False, + no_prediction: bool = False, + progress: bool = False, + unique_gene_id: bool = False, + softmasking: bool = False, + extrinsic_cfg_file: Optional[Path] = None, + augustus_config_path: Optional[Path] = None, +) -> dict: + """ + Runs AUGUSTUS, a tool for gene prediction in eukaryotes. + + This tool predicts genes in a given input FASTA file (query_file) based on a species-specific model. + It supports various prediction models, extrinsic evidence (hints), and output formats. + """ + # 1. Input validation + if not query_file.is_file(): + raise FileNotFoundError(f"Input query file not found: {query_file}") + if hints_file and not hints_file.is_file(): + raise FileNotFoundError(f"Hints file not found: {hints_file}") + if extrinsic_cfg_file and not extrinsic_cfg_file.is_file(): + raise FileNotFoundError(f"Extrinsic config file not found: {extrinsic_cfg_file}") + if augustus_config_path and not augustus_config_path.is_dir(): + raise NotADirectoryError(f"AUGUSTUS_CONFIG_PATH is not a valid directory: {augustus_config_path}") + + # 2. Command construction + cmd = ["augustus"] + + # Add parameters + cmd.append(f"--species={species}") + cmd.append(f"--strand={strand}") + cmd.append(f"--genemodel={genemodel}") + + # Boolean flags with true/false values + if singlestrand: + cmd.append("--singlestrand=true") + if no_in_frame_stop: + cmd.append("--noInFrameStop=true") + if alternatives_from_evidence: + cmd.append("--alternatives-from-evidence=true") + if alternatives_from_sampling: + cmd.append("--alternatives-from-sampling=true") + if keep_viterbi: + cmd.append("--keep_viterbi=true") + if no_prediction: + cmd.append("--noprediction=true") + if progress: + cmd.append("--progress=true") + if unique_gene_id: + cmd.append("--uniqueGeneId=true") + + # Boolean flags with on/off values + cmd.append(f"--gff3={'on' if gff3 else 'off'}") + cmd.append(f"--UTR={'on' if utr else 'off'}") + cmd.append(f"--protein={'on' if protein else 'off'}") + cmd.append(f"--introns={'on' if introns else 'off'}") + cmd.append(f"--start={'on' if start else 'off'}") + cmd.append(f"--stop={'on' if stop else 'off'}") + cmd.append(f"--cds={'on' if cds else 'off'}") + cmd.append(f"--codingseq={'on' if codingseq else 'off'}") + + # Boolean flag with 1/0 value + if softmasking: + cmd.append("--softmasking=1") + + # Optional file/directory paths and other values + if hints_file: + cmd.append(f"--hintsfile={hints_file}") + if extrinsic_cfg_file: + cmd.append(f"--extrinsicCfgFile={extrinsic_cfg_file}") + if augustus_config_path: + cmd.append(f"--AUGUSTUS_CONFIG_PATH={augustus_config_path}") + if sample is not None: + cmd.append(f"--sample={sample}") + if outfile: + # Ensure parent directory exists for the output file + outfile.parent.mkdir(parents=True, exist_ok=True) + cmd.append(f"--outfile={outfile}") + + # Positional argument (must be last for some versions) + cmd.append(str(query_file)) + + command_executed = " ".join(cmd) + logging.info(f"Executing command: {command_executed}") + + # 3. Subprocess execution + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + ) + except FileNotFoundError: + raise RuntimeError("augustus executable not found. Please ensure it is in your system's PATH.") + except subprocess.CalledProcessError as e: + logging.error(f"AUGUSTUS execution failed with exit code {e.returncode}") + logging.error(f"Stderr: {e.stderr}") + logging.error(f"Stdout: {e.stdout}") + return { + "command_executed": command_executed, + "stdout": e.stdout, + "stderr": e.stderr, + "error": "AUGUSTUS execution failed.", + "return_code": e.returncode, + "output_files": [] + } + + # 4. Structured result return + output_files = [str(outfile)] if outfile else [] + + return { + "command_executed": command_executed, + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": output_files + } \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_augustus/app/augustus_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_augustus/app/augustus_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..34190c4ccf7c4919c9d95ae883723a67ecab0f3f --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_augustus/app/augustus_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_augustus/app/augustus_server.py') +SERVER_NAME = 'biosci_augustus' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_augustus/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_augustus/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..96daa1843cc7203f8a7a8124eaf3c24a918f5aa7 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_augustus/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-augustus: + build: . + image: mcp-augustus:latest + container_name: mcp-augustus + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=augustus + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_augustus/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_augustus/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..bb14a584251a561e179beb4b9f7b966a7c3ea338 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_augustus/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - augustus + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_augustus/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_augustus/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_augustus/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bamtools/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bamtools/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..0c00395bd1b2d1ebcdee0a4e47e9bae314fa2abd --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bamtools/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install bamtools via conda (e.g., from bioconda) +RUN conda install -c bioconda bamtools -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY bamtools_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/bamtools_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/bamtools_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bamtools/app/bamtools_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bamtools/app/bamtools_server.py new file mode 100644 index 0000000000000000000000000000000000000000..7a11c0e409a6de9747affa2d43ad4c333a8ac44c --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bamtools/app/bamtools_server.py @@ -0,0 +1,704 @@ +import subprocess +import shlex +import os +from pathlib import Path +from typing import List, Optional + +# In a real MCP environment, the 'mcp' object with its decorators +# would be provided by the framework. This is a placeholder for standalone validation. +class _MCP: + def tool(self, *args, **kwargs): + def decorator(f): + return f + return decorator +mcp = _MCP() + +### Bamtools Tool Definitions ### + +@mcp.tool() +def convert( + in_bam: Path, + format: str, + out: Optional[Path] = None, + region: Optional[str] = None, +) -> dict: + """ + Converts a BAM file to various other formats. + + Args: + in_bam: The input BAM file. + format: The output format. Must be one of: bed, fasta, fastq, json, pileup, sam, yaml. + out: The output filename. If not provided, output is sent to stdout. + region: Only convert alignments that overlap this region (e.g., "ref:start-end"). + + Returns: + A dictionary containing the command executed, stdout, stderr, and output files. + """ + if not in_bam.is_file(): + raise FileNotFoundError(f"Input BAM file not found: {in_bam}") + + valid_formats = {"bed", "fasta", "fastq", "json", "pileup", "sam", "yaml"} + if format not in valid_formats: + raise ValueError(f"Invalid format '{format}'. Must be one of {valid_formats}") + + cmd = ["bamtools", "convert", "-in", str(in_bam), "-format", format] + output_files = [] + + if out: + cmd.extend(["-out", str(out)]) + output_files.append(str(out)) + if region: + cmd.extend(["-region", region]) + + command_executed = shlex.join(cmd) + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + ) + return { + "command_executed": command_executed, + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": output_files, + } + except subprocess.CalledProcessError as e: + return { + "command_executed": command_executed, + "stdout": e.stdout, + "stderr": e.stderr, + "error": f"bamtools convert failed with exit code {e.returncode}", + "output_files": [], + } + +@mcp.tool() +def count(in_bams: List[Path]) -> dict: + """ + Prints the number of alignments in one or more BAM files. + + Args: + in_bams: A list of input BAM files. + + Returns: + A dictionary containing the command executed, stdout (the count), and stderr. + """ + if not in_bams: + raise ValueError("At least one input BAM file must be provided.") + + cmd = ["bamtools", "count"] + for bam_file in in_bams: + if not bam_file.is_file(): + raise FileNotFoundError(f"Input BAM file not found: {bam_file}") + cmd.extend(["-in", str(bam_file)]) + + command_executed = shlex.join(cmd) + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + ) + return { + "command_executed": command_executed, + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": [], + } + except subprocess.CalledProcessError as e: + return { + "command_executed": command_executed, + "stdout": e.stdout, + "stderr": e.stderr, + "error": f"bamtools count failed with exit code {e.returncode}", + "output_files": [], + } + +@mcp.tool() +def coverage(in_bams: List[Path]) -> dict: + """ + Prints coverage statistics from one or more BAM files. + + Args: + in_bams: A list of input BAM files. + + Returns: + A dictionary containing the command executed, stdout (coverage stats), and stderr. + """ + if not in_bams: + raise ValueError("At least one input BAM file must be provided.") + + cmd = ["bamtools", "coverage"] + for bam_file in in_bams: + if not bam_file.is_file(): + raise FileNotFoundError(f"Input BAM file not found: {bam_file}") + cmd.extend(["-in", str(bam_file)]) + + command_executed = shlex.join(cmd) + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + ) + return { + "command_executed": command_executed, + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": [], + } + except subprocess.CalledProcessError as e: + return { + "command_executed": command_executed, + "stdout": e.stdout, + "stderr": e.stderr, + "error": f"bamtools coverage failed with exit code {e.returncode}", + "output_files": [], + } + +@mcp.tool() +def filter_bam( + in_bams: List[Path], + out_bam: Optional[Path] = None, + region: Optional[str] = None, + property_filters: Optional[List[str]] = None, + tag_filters: Optional[List[str]] = None, + script: Optional[Path] = None, + list_file: Optional[Path] = None, + force_compression: bool = False, +) -> dict: + """ + Filters BAM file(s) by user-specified criteria. + + Args: + in_bams: The input BAM file(s). + out_bam: The output BAM file. If not provided, output is sent to stdout. + region: Only keeps alignments that overlap this region. + property_filters: List of "TAG:VALUE" strings to filter by BamAlignment property. + tag_filters: List of "TAG:VALUE" strings to filter by BamAlignment tag. + script: A file containing a list of filter rules. + list_file: A file containing a list of read names to be kept. + force_compression: If True, the output BAM file will be compressed. + + Returns: + A dictionary containing the command executed, stdout, stderr, and output files. + """ + if not in_bams: + raise ValueError("At least one input BAM file must be provided.") + + cmd = ["bamtools", "filter"] + output_files = [] + + for bam_file in in_bams: + if not bam_file.is_file(): + raise FileNotFoundError(f"Input BAM file not found: {bam_file}") + cmd.extend(["-in", str(bam_file)]) + + if out_bam: + cmd.extend(["-out", str(out_bam)]) + output_files.append(str(out_bam)) + if region: + cmd.extend(["-region", region]) + if property_filters: + for p_filter in property_filters: + cmd.extend(["-property", p_filter]) + if tag_filters: + for t_filter in tag_filters: + cmd.extend(["-tag", t_filter]) + if script: + if not script.is_file(): + raise FileNotFoundError(f"Script file not found: {script}") + cmd.extend(["-script", str(script)]) + if list_file: + if not list_file.is_file(): + raise FileNotFoundError(f"List file not found: {list_file}") + cmd.extend(["-list", str(list_file)]) + if force_compression: + cmd.append("-forceCompression") + + command_executed = shlex.join(cmd) + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + ) + return { + "command_executed": command_executed, + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": output_files, + } + except subprocess.CalledProcessError as e: + return { + "command_executed": command_executed, + "stdout": e.stdout, + "stderr": e.stderr, + "error": f"bamtools filter failed with exit code {e.returncode}", + "output_files": [], + } + +@mcp.tool() +def header(in_bam: Path) -> dict: + """ + Prints the header from a BAM file. + + Args: + in_bam: The input BAM file. + + Returns: + A dictionary containing the command executed, stdout (the header), and stderr. + """ + if not in_bam.is_file(): + raise FileNotFoundError(f"Input BAM file not found: {in_bam}") + + cmd = ["bamtools", "header", "-in", str(in_bam)] + command_executed = shlex.join(cmd) + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + ) + return { + "command_executed": command_executed, + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": [], + } + except subprocess.CalledProcessError as e: + return { + "command_executed": command_executed, + "stdout": e.stdout, + "stderr": e.stderr, + "error": f"bamtools header failed with exit code {e.returncode}", + "output_files": [], + } + +@mcp.tool() +def index(in_bam: Path) -> dict: + """ + Generates an index for a BAM file. The index file (.bai) is created in the same directory. + + Args: + in_bam: The input BAM file to index. + + Returns: + A dictionary containing the command executed, stdout, stderr, and the path to the generated index file. + """ + if not in_bam.is_file(): + raise FileNotFoundError(f"Input BAM file not found: {in_bam}") + + cmd = ["bamtools", "index", "-in", str(in_bam)] + output_index_file = in_bam.with_suffix(in_bam.suffix + '.bai') + + command_executed = shlex.join(cmd) + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + ) + if not output_index_file.is_file(): + raise FileNotFoundError(f"Expected index file was not created: {output_index_file}") + return { + "command_executed": command_executed, + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": [str(output_index_file)], + } + except subprocess.CalledProcessError as e: + return { + "command_executed": command_executed, + "stdout": e.stdout, + "stderr": e.stderr, + "error": f"bamtools index failed with exit code {e.returncode}", + "output_files": [], + } + +@mcp.tool() +def merge( + in_bams: List[Path], + out_bam: Optional[Path] = None, + region: Optional[str] = None, + force: bool = False, +) -> dict: + """ + Merges multiple BAM files into a single file. + + Args: + in_bams: A list of input BAM files to merge. Must contain at least two files. + out_bam: The output BAM file. If not provided, output is sent to stdout. + region: Merges only alignments that overlap this region. + force: Forces merge, even if headers are not identical. Uses the first BAM file's header. + + Returns: + A dictionary containing the command executed, stdout, stderr, and output files. + """ + if len(in_bams) < 2: + raise ValueError("At least two input BAM files must be provided for merging.") + + cmd = ["bamtools", "merge"] + output_files = [] + + for bam_file in in_bams: + if not bam_file.is_file(): + raise FileNotFoundError(f"Input BAM file not found: {bam_file}") + cmd.extend(["-in", str(bam_file)]) + + if out_bam: + cmd.extend(["-out", str(out_bam)]) + output_files.append(str(out_bam)) + if region: + cmd.extend(["-region", region]) + if force: + cmd.append("-force") + + command_executed = shlex.join(cmd) + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + ) + return { + "command_executed": command_executed, + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": output_files, + } + except subprocess.CalledProcessError as e: + return { + "command_executed": command_executed, + "stdout": e.stdout, + "stderr": e.stderr, + "error": f"bamtools merge failed with exit code {e.returncode}", + "output_files": [], + } + +@mcp.tool() +def random( + in_bams: List[Path], + out_bam: Optional[Path] = None, + n: int = 100, + seed: int = 0, +) -> dict: + """ + Selects a random number of alignments from existing BAM file(s). + + Args: + in_bams: The input BAM file(s). + out_bam: The output BAM file. If not provided, output is sent to stdout. + n: Number of alignments to select. + seed: Random seed. + + Returns: + A dictionary containing the command executed, stdout, stderr, and output files. + """ + if not in_bams: + raise ValueError("At least one input BAM file must be provided.") + + cmd = ["bamtools", "random", "-n", str(n), "-seed", str(seed)] + output_files = [] + + for bam_file in in_bams: + if not bam_file.is_file(): + raise FileNotFoundError(f"Input BAM file not found: {bam_file}") + cmd.extend(["-in", str(bam_file)]) + + if out_bam: + cmd.extend(["-out", str(out_bam)]) + output_files.append(str(out_bam)) + + command_executed = shlex.join(cmd) + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + ) + return { + "command_executed": command_executed, + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": output_files, + } + except subprocess.CalledProcessError as e: + return { + "command_executed": command_executed, + "stdout": e.stdout, + "stderr": e.stderr, + "error": f"bamtools random failed with exit code {e.returncode}", + "output_files": [], + } + +@mcp.tool() +def resolve(in_bam: Path, out_bam: Path) -> dict: + """ + Resolves paired-end reads, marking the IsProperPair flag as needed. + + Args: + in_bam: The input BAM file. + out_bam: The output BAM file. + + Returns: + A dictionary containing the command executed, stdout, stderr, and the output file path. + """ + if not in_bam.is_file(): + raise FileNotFoundError(f"Input BAM file not found: {in_bam}") + + cmd = ["bamtools", "resolve", "-in", str(in_bam), "-out", str(out_bam)] + command_executed = shlex.join(cmd) + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + ) + return { + "command_executed": command_executed, + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": [str(out_bam)], + } + except subprocess.CalledProcessError as e: + return { + "command_executed": command_executed, + "stdout": e.stdout, + "stderr": e.stderr, + "error": f"bamtools resolve failed with exit code {e.returncode}", + "output_files": [], + } + +@mcp.tool() +def revert(in_bam: Path, out_bam: Path) -> dict: + """ + Removes duplicate marks and restores original base qualities from a BAM file. + + Args: + in_bam: The input BAM file. + out_bam: The output BAM file. + + Returns: + A dictionary containing the command executed, stdout, stderr, and the output file path. + """ + if not in_bam.is_file(): + raise FileNotFoundError(f"Input BAM file not found: {in_bam}") + + cmd = ["bamtools", "revert", "-in", str(in_bam), "-out", str(out_bam)] + command_executed = shlex.join(cmd) + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + ) + return { + "command_executed": command_executed, + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": [str(out_bam)], + } + except subprocess.CalledProcessError as e: + return { + "command_executed": command_executed, + "stdout": e.stdout, + "stderr": e.stderr, + "error": f"bamtools revert failed with exit code {e.returncode}", + "output_files": [], + } + +@mcp.tool() +def sort( + in_bam: Path, + out_bam: Optional[Path] = None, + by: str = "position", + order: str = "ascending", + n: int = 1000, + mem: int = 512, +) -> dict: + """ + Sorts a BAM file by position or name. + + Args: + in_bam: The input BAM file. + out_bam: The output BAM file. If not provided, output is sent to stdout. + by: Sort by 'position' or 'name'. + order: Sort in 'ascending' or 'descending' order. + n: Max number of alignments to buffer in memory. + mem: Max memory to use (in megabytes). + + Returns: + A dictionary containing the command executed, stdout, stderr, and output files. + """ + if not in_bam.is_file(): + raise FileNotFoundError(f"Input BAM file not found: {in_bam}") + if by not in ["position", "name"]: + raise ValueError("Sort 'by' must be 'position' or 'name'.") + if order not in ["ascending", "descending"]: + raise ValueError("Sort 'order' must be 'ascending' or 'descending'.") + + cmd = ["bamtools", "sort", "-in", str(in_bam), "-by", by, "-order", order, "-n", str(n), "-mem", str(mem)] + output_files = [] + + if out_bam: + cmd.extend(["-out", str(out_bam)]) + output_files.append(str(out_bam)) + + command_executed = shlex.join(cmd) + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + ) + return { + "command_executed": command_executed, + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": output_files, + } + except subprocess.CalledProcessError as e: + return { + "command_executed": command_executed, + "stdout": e.stdout, + "stderr": e.stderr, + "error": f"bamtools sort failed with exit code {e.returncode}", + "output_files": [], + } + +@mcp.tool() +def split( + in_bam: Path, + output_dir: Path, + stub: Optional[str] = None, + by: Optional[str] = None, + reference: bool = False, + mapped: bool = False, + paired: bool = False, + tag: Optional[str] = None, +) -> dict: + """ + Splits a BAM file based on a specified property, creating multiple output BAM files. + + Args: + in_bam: The input BAM file. + output_dir: The directory where output files will be created. + stub: The prefix for output file names. Defaults to the input file name. + by: Split file by a specific property. + reference: Split by reference sequence. + mapped: Split into mapped and unmapped files. + paired: Split into paired and single-end files. + tag: Split by the value of a specific tag. + + Returns: + A dictionary containing the command executed, stdout, stderr, and a list of created files. + """ + if not in_bam.is_file(): + raise FileNotFoundError(f"Input BAM file not found: {in_bam}") + + split_options = [by is not None, reference, mapped, paired, tag is not None] + if sum(split_options) != 1: + raise ValueError("Exactly one split criterion (by, reference, mapped, paired, or tag) must be specified.") + + output_dir.mkdir(parents=True, exist_ok=True) + + cmd = ["bamtools", "split", "-in", str(in_bam)] + + # Use the stub to direct output to the specified directory + output_stub = stub if stub else in_bam.stem + cmd.extend(["-stub", str(output_dir / output_stub)]) + + if by: + cmd.extend(["-by", by]) + if reference: + cmd.append("-reference") + if mapped: + cmd.append("-mapped") + if paired: + cmd.append("-paired") + if tag: + cmd.extend(["-tag", tag]) + + command_executed = shlex.join(cmd) + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + ) + # Find all files created in the output directory + created_files = [str(p) for p in output_dir.glob(f"{output_stub}*")] + return { + "command_executed": command_executed, + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": created_files, + } + except subprocess.CalledProcessError as e: + return { + "command_executed": command_executed, + "stdout": e.stdout, + "stderr": e.stderr, + "error": f"bamtools split failed with exit code {e.returncode}", + "output_files": [], + } + +@mcp.tool() +def stats(in_bams: List[Path], insert: bool = False) -> dict: + """ + Prints basic statistics from one or more BAM files. + + Args: + in_bams: A list of input BAM files. + insert: If True, print insert size summary. + + Returns: + A dictionary containing the command executed, stdout (the stats), and stderr. + """ + if not in_bams: + raise ValueError("At least one input BAM file must be provided.") + + cmd = ["bamtools", "stats"] + for bam_file in in_bams: + if not bam_file.is_file(): + raise FileNotFoundError(f"Input BAM file not found: {bam_file}") + cmd.extend(["-in", str(bam_file)]) + + if insert: + cmd.append("-insert") + + command_executed = shlex.join(cmd) + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + ) + return { + "command_executed": command_executed, + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": [], + } + except subprocess.CalledProcessError as e: + return { + "command_executed": command_executed, + "stdout": e.stdout, + "stderr": e.stderr, + "error": f"bamtools stats failed with exit code {e.returncode}", + "output_files": [], + } \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bamtools/app/bamtools_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bamtools/app/bamtools_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..cc10d80b29f2f8e85c2daf09b396825f68e1737b --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bamtools/app/bamtools_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bamtools/app/bamtools_server.py') +SERVER_NAME = 'biosci_bamtools' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bamtools/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bamtools/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..efe15438bf81dc42bdebaf6b8a684c7d8c8ae3f6 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bamtools/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-bamtools: + build: . + image: mcp-bamtools:latest + container_name: mcp-bamtools + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=bamtools + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bamtools/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bamtools/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..cd56f2319dab67d6b24a5b2974f63480e998a013 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bamtools/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - bamtools + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bamtools/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bamtools/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bamtools/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bbmap/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bbmap/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..7cc25d733f3d34ccf27ade9837916eb9d0540256 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bbmap/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install bbmap via conda (e.g., from bioconda) +RUN conda install -c bioconda bbmap -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY bbmap_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/bbmap_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/bbmap_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bbmap/app/bbmap_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bbmap/app/bbmap_server.py new file mode 100644 index 0000000000000000000000000000000000000000..2ba763017b182adc08a15551357fd097d127c7c9 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bbmap/app/bbmap_server.py @@ -0,0 +1,234 @@ +import subprocess +import tempfile +from pathlib import Path +from typing import Optional, List + +# This is a placeholder for the MCP decorator. +# In a real MCP environment, this would be provided by the MCP framework. +def tool(func): + def wrapper(*args, **kwargs): + return func(*args, **kwargs) + return wrapper + +mcp = type("mcp", (), {"tool": tool}) + + +@mcp.tool +def bbmap( + in_file: Path, + ref_file: Path, + out_file: Path, + in2_file: Optional[Path] = None, + out_unmapped: Optional[Path] = None, + java_memory: Optional[str] = None, + threads: Optional[int] = None, + overwrite: bool = False, + interleaved: str = "auto", + reads: int = -1, + samplerate: float = 1.0, + bamscript: Optional[Path] = None, + scafstats: Optional[Path] = None, + covstats: Optional[Path] = None, + fast: bool = False, + slow: bool = False, + vslow: bool = False, + max_indel: int = 16000, + min_identity: float = 0.76, + min_hits: int = 1, + local_alignment: bool = False, + perfect_mode: bool = False, + ambiguous_reads_mode: str = "best", + sam_version: str = "1.4", + secondary_alignments: bool = True, + max_sites: int = 5, + pairlen: int = 32000, + qtrim: str = "f", + untrim: bool = False, + trimq: int = 6, + min_avg_quality: int = 0, + nodisk: bool = False, +) -> dict: + """ + Maps sequencing reads to a reference genome using BBMap. + + BBMap is a fast and accurate splice-aware read mapper. This tool wraps the + bbmap.sh script, providing a comprehensive set of parameters for fine-tuning + the mapping process. + + Args: + in_file: Path to the primary input file (fasta, fastq, sam; compressed or uncompressed). + ref_file: Path to the reference genome file (fasta). + out_file: Path for the output SAM file. + in2_file: Path to the second input file for paired-end reads. + out_unmapped: Path to write unmapped reads to. + java_memory: Java heap size (e.g., '8g', '1000m'). Passed as -Xmx to the JVM. + threads: Number of threads to use. If not set, BBMap will auto-detect. + overwrite: If True, allows overwriting of existing output files. + interleaved: Set to 't' or 'f' if reads are interleaved; 'auto' detects. + reads: If positive, quit after processing this many reads. + samplerate: Subsample reads to this fraction (0.0 to 1.0). + bamscript: Write a shell script to this path for SAM to BAM conversion. + scafstats: Write statistics on coverage of each reference scaffold. + covstats: Write coverage statistics to a file. + fast: Use faster, less sensitive presets. + slow: Use slower, more sensitive presets. + vslow: Use very slow, very sensitive presets. + max_indel: Do not look for indels longer than this. + min_identity: Approximate minimum identity of reads to map (0.0 to 1.0). + min_hits: Minimum number of seed hits required for candidate sites. + local_alignment: Use local instead of global alignments. + perfect_mode: Allow only perfect mappings. + ambiguous_reads_mode: Behavior for ambiguously-mapped reads ('best', 'all', 'random', 'toss'). + sam_version: Set SAM version ('1.4' or '1.5'). + secondary_alignments: Allow secondary alignments for ambiguous reads. + max_sites: Maximum number of sites to record per read. + pairlen: Maximum insert size for paired-end reads. + qtrim: Quality trimming mode ('l', 'r', 'lr', 'f' for left, right, both, or none). + untrim: Untrim reads. + trimq: Quality threshold for trimming. + min_avg_quality: Reads with average quality below this will be discarded. + nodisk: If True, do not write temporary files to disk. + + Returns: + A dictionary containing the executed command, stdout, stderr, and a list of output files. + """ + # --- Input Validation --- + if not in_file.exists(): + raise FileNotFoundError(f"Input file not found: {in_file}") + if not ref_file.exists(): + raise FileNotFoundError(f"Reference file not found: {ref_file}") + if in2_file and not in2_file.exists(): + raise FileNotFoundError(f"Second input file not found: {in2_file}") + + if not (0.0 <= samplerate <= 1.0): + raise ValueError("samplerate must be between 0.0 and 1.0") + if not (0.0 <= min_identity <= 1.0): + raise ValueError("min_identity must be between 0.0 and 1.0") + + valid_ambiguous_modes = {"best", "all", "random", "toss"} + if ambiguous_reads_mode not in valid_ambiguous_modes: + raise ValueError(f"ambiguous_reads_mode must be one of {valid_ambiguous_modes}") + + valid_sam_versions = {"1.4", "1.5"} + if sam_version not in valid_sam_versions: + raise ValueError(f"sam_version must be one of {valid_sam_versions}") + + valid_qtrim_modes = {"l", "r", "lr", "f"} + if qtrim not in valid_qtrim_modes: + raise ValueError(f"qtrim must be one of {valid_qtrim_modes}") + + # --- Command Construction --- + cmd = ["bbmap.sh"] + + if java_memory: + cmd.append(f"-Xmx{java_memory}") + + # Required parameters + cmd.append(f"in={in_file}") + cmd.append(f"ref={ref_file}") + cmd.append(f"out={out_file}") + + # Optional file paths + if in2_file: + cmd.append(f"in2={in2_file}") + if out_unmapped: + cmd.append(f"outu={out_unmapped}") + if bamscript: + cmd.append(f"bamscript={bamscript}") + if scafstats: + cmd.append(f"scafstats={scafstats}") + if covstats: + cmd.append(f"covstats={covstats}") + + # Boolean flags (converted to 't'/'f') + if overwrite: + cmd.append("ow=t") + if fast: + cmd.append("fast=t") + if slow: + cmd.append("slow=t") + if vslow: + cmd.append("vslow=t") + if local_alignment: + cmd.append("local=t") + if perfect_mode: + cmd.append("perfectmode=t") + if secondary_alignments: + cmd.append("secondary=t") + if untrim: + cmd.append("untrim=t") + if nodisk: + cmd.append("nodisk=t") + + # String and numeric parameters + if threads is not None: + cmd.append(f"threads={threads}") + if interleaved != "auto": + cmd.append(f"interleaved={interleaved}") + if reads != -1: + cmd.append(f"reads={reads}") + if samplerate != 1.0: + cmd.append(f"samplerate={samplerate}") + if max_indel != 16000: + cmd.append(f"maxindel={max_indel}") + if min_identity != 0.76: + cmd.append(f"minid={min_identity}") + if min_hits != 1: + cmd.append(f"minhits={min_hits}") + if ambiguous_reads_mode != "best": + cmd.append(f"ambiguous={ambiguous_reads_mode}") + if sam_version != "1.4": + cmd.append(f"sam={sam_version}") + if max_sites != 5: + cmd.append(f"maxsites={max_sites}") + if pairlen != 32000: + cmd.append(f"pairlen={pairlen}") + if qtrim != "f": + cmd.append(f"qtrim={qtrim}") + if trimq != 6: + cmd.append(f"trimq={trimq}") + if min_avg_quality != 0: + cmd.append(f"maq={min_avg_quality}") + + # --- Subprocess Execution --- + command_str = " ".join(cmd) + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + ) + except FileNotFoundError: + return { + "error": "bbmap.sh not found. Please ensure BBMap is in your PATH.", + "command_executed": command_str, + "stdout": "", + "stderr": "Executable not found.", + } + except subprocess.CalledProcessError as e: + return { + "error": "BBMap execution failed.", + "command_executed": command_str, + "stdout": e.stdout, + "stderr": e.stderr, + "return_code": e.returncode, + } + + # --- Collect Output Files --- + output_files = [str(out_file)] + if out_unmapped: + output_files.append(str(out_unmapped)) + if bamscript: + output_files.append(str(bamscript)) + if scafstats: + output_files.append(str(scafstats)) + if covstats: + output_files.append(str(covstats)) + + return { + "command_executed": command_str, + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": output_files, + } \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bbmap/app/bbmap_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bbmap/app/bbmap_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..8ebb38cfa9b18ff3c0c65c66a49cee8661181ee9 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bbmap/app/bbmap_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bbmap/app/bbmap_server.py') +SERVER_NAME = 'biosci_bbmap' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bbmap/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bbmap/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..8bb1d6c1e02e727e07ab7705f2f875415e352426 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bbmap/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-bbmap: + build: . + image: mcp-bbmap:latest + container_name: mcp-bbmap + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=bbmap + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bbmap/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bbmap/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..4dd8a76883b5fb6460bb4414d93156ecc7e3149a --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bbmap/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - bbmap + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bbmap/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bbmap/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bbmap/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bcftools/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bcftools/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..075aef4a34315764c86518d4f68189f8f3484117 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bcftools/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install bcftools via conda (e.g., from bioconda) +RUN conda install -c bioconda bcftools -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY bcftools_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/bcftools_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/bcftools_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bcftools/app/bcftools_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bcftools/app/bcftools_server.py new file mode 100644 index 0000000000000000000000000000000000000000..90645ca623fb8d0cdb8515b71a7da4233efc7da7 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bcftools/app/bcftools_server.py @@ -0,0 +1,858 @@ +import subprocess +import tempfile +from pathlib import Path +from typing import List, Optional + +# Note: The @mcp.tool decorator is not defined here. +# It is assumed to be provided by the Model Context Protocol (MCP) framework. +# This code is designed to be used within that framework. + +# Helper function to handle subprocess execution and error reporting +def _run_bcftools_command(cmd: List[str], output_file: Optional[Path] = None): + """ + A helper function to execute a bcftools command, handle errors, + and return a structured dictionary. + """ + command_str = " ".join(cmd) + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + ) + output_files = [str(output_file)] if output_file and output_file.exists() else [] + + # For commands that create index files automatically + if output_file and str(output_file).endswith((".bcf", ".vcf.gz")): + index_extensions = [".csi", ".tbi"] + for ext in index_extensions: + index_file = Path(str(output_file) + ext) + if index_file.exists(): + output_files.append(str(index_file)) + + return { + "command_executed": command_str, + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": output_files, + "return_code": 0, + } + except FileNotFoundError: + return { + "command_executed": command_str, + "stdout": "", + "stderr": "Error: 'bcftools' command not found. Please ensure it is in your PATH.", + "output_files": [], + "return_code": 1, + "error": "FileNotFoundError" + } + except subprocess.CalledProcessError as e: + return { + "command_executed": command_str, + "stdout": e.stdout, + "stderr": e.stderr, + "output_files": [], + "return_code": e.returncode, + "error": "CalledProcessError" + } + +@mcp.tool() +def bcftools_annotate( + input_file: Path, + annotations: Optional[Path] = None, + columns: Optional[str] = None, + header_lines: Optional[Path] = None, + output: Optional[Path] = None, + output_type: str = "v", + remove: Optional[str] = None, + set_id: Optional[str] = None, + regions: Optional[str] = None, + regions_file: Optional[Path] = None, + targets: Optional[str] = None, + targets_file: Optional[Path] = None, + include: Optional[str] = None, + exclude: Optional[str] = None, + samples: Optional[str] = None, + samples_file: Optional[Path] = None, + threads: int = 1, + rename_chrs: Optional[Path] = None, + no_version: bool = False, + single_overlaps: bool = False, + mark_sites: Optional[str] = None, +): + """ + Annotate VCF/BCF files with information from other files. + """ + if not input_file.exists(): + raise FileNotFoundError(f"Input file not found: {input_file}") + if annotations and not annotations.exists(): + raise FileNotFoundError(f"Annotations file not found: {annotations}") + if header_lines and not header_lines.exists(): + raise FileNotFoundError(f"Header lines file not found: {header_lines}") + if output_type not in ["b", "u", "z", "v"]: + raise ValueError("output_type must be one of 'b', 'u', 'z', 'v'.") + + cmd = ["bcftools", "annotate", str(input_file)] + + if annotations: + cmd.extend(["-a", str(annotations)]) + if columns: + cmd.extend(["-c", columns]) + if header_lines: + cmd.extend(["-h", str(header_lines)]) + if output: + cmd.extend(["-o", str(output)]) + if output_type: + cmd.extend(["-O", output_type]) + if remove: + cmd.extend(["-x", remove]) + if set_id: + cmd.extend(["--set-id", set_id]) + if regions: + cmd.extend(["-r", regions]) + if regions_file: + cmd.extend(["-R", str(regions_file)]) + if targets: + cmd.extend(["-t", targets]) + if targets_file: + cmd.extend(["-T", str(targets_file)]) + if include: + cmd.extend(["-i", include]) + if exclude: + cmd.extend(["-e", exclude]) + if samples: + cmd.extend(["-s", samples]) + if samples_file: + cmd.extend(["-S", str(samples_file)]) + if threads > 1: + cmd.extend(["--threads", str(threads)]) + if rename_chrs: + cmd.extend(["--rename-chrs", str(rename_chrs)]) + if no_version: + cmd.append("--no-version") + if single_overlaps: + cmd.append("--single-overlaps") + if mark_sites: + cmd.extend(["--mark-sites", mark_sites]) + + return _run_bcftools_command(cmd, output) + +@mcp.tool() +def bcftools_call( + input_file: Path, + output: Optional[Path] = None, + output_type: str = "v", + ploidy: Optional[str] = None, + ploidy_file: Optional[Path] = None, + call_method: str = "multiallelic", + constrain_alleles: bool = False, + group_samples: Optional[str] = None, + samples: Optional[str] = None, + samples_file: Optional[Path] = None, + format_fields: Optional[str] = None, + keep_alts: bool = False, + keep_masked_ref: bool = False, + skip_variants: bool = False, + threads: int = 1, +): + """ + Call genotypes from likelihoods. + """ + if not input_file.exists(): + raise FileNotFoundError(f"Input file not found: {input_file}") + if output_type not in ["b", "u", "z", "v"]: + raise ValueError("output_type must be one of 'b', 'u', 'z', 'v'.") + if call_method not in ["consensus", "multiallelic"]: + raise ValueError("call_method must be 'consensus' or 'multiallelic'.") + + cmd = ["bcftools", "call", str(input_file)] + + if output: + cmd.extend(["-o", str(output)]) + if output_type: + cmd.extend(["-O", output_type]) + if ploidy: + cmd.extend(["-p", ploidy]) + if ploidy_file: + cmd.extend(["-P", str(ploidy_file)]) + if call_method == "consensus": + cmd.append("-c") + else: # multiallelic is default, but -m is explicit + cmd.append("-m") + if constrain_alleles: + cmd.append("-C alleles") + if group_samples: + cmd.extend(["-G", group_samples]) + if samples: + cmd.extend(["-s", samples]) + if samples_file: + cmd.extend(["-S", str(samples_file)]) + if format_fields: + cmd.extend(["-f", format_fields]) + if keep_alts: + cmd.append("-A") + if keep_masked_ref: + cmd.append("-M") + if skip_variants: + cmd.append("-V") + if threads > 1: + cmd.extend(["--threads", str(threads)]) + + return _run_bcftools_command(cmd, output) + +@mcp.tool() +def bcftools_concat( + input_files: List[Path], + output: Optional[Path] = None, + output_type: str = "v", + allow_overlaps: bool = False, + remove_duplicates: bool = False, + naive: bool = False, + threads: int = 1, +): + """ + Concatenate VCF/BCF files from non-overlapping regions. + """ + if not input_files: + raise ValueError("At least one input file must be provided.") + for f in input_files: + if not f.exists(): + raise FileNotFoundError(f"Input file not found: {f}") + if output_type not in ["b", "u", "z", "v"]: + raise ValueError("output_type must be one of 'b', 'u', 'z', 'v'.") + + cmd = ["bcftools", "concat"] + + if allow_overlaps: + cmd.append("-a") + if remove_duplicates: + cmd.append("-d") + if naive: + cmd.append("-n") + if output: + cmd.extend(["-o", str(output)]) + if output_type: + cmd.extend(["-O", output_type]) + if threads > 1: + cmd.extend(["--threads", str(threads)]) + + cmd.extend([str(f) for f in input_files]) + + return _run_bcftools_command(cmd, output) + +@mcp.tool() +def bcftools_consensus( + input_file: Path, + fasta_ref: Path, + output: Optional[Path] = None, + chain: Optional[Path] = None, + haplotype: Optional[str] = None, + iupac_codes: bool = False, + mark_del: Optional[str] = None, + mark_ins: Optional[str] = None, + mark_snv: Optional[str] = None, + missing: Optional[str] = None, + sample: Optional[str] = None, + include: Optional[str] = None, + exclude: Optional[str] = None, +): + """ + Create a consensus sequence by applying VCF variants to a reference FASTA file. + """ + if not input_file.exists(): + raise FileNotFoundError(f"Input VCF/BCF file not found: {input_file}") + if not fasta_ref.exists(): + raise FileNotFoundError(f"Reference FASTA file not found: {fasta_ref}") + if haplotype and haplotype not in ["1", "2", "R", "A", "IUPAC", "all"]: + raise ValueError("haplotype must be one of '1', '2', 'R', 'A', 'IUPAC', 'all'.") + + cmd = ["bcftools", "consensus", str(input_file)] + cmd.extend(["-f", str(fasta_ref)]) + + if output: + cmd.extend(["-o", str(output)]) + if chain: + cmd.extend(["-c", str(chain)]) + if haplotype: + cmd.extend(["-H", haplotype]) + if iupac_codes: + cmd.append("-i") + if mark_del: + cmd.extend(["--mark-del", mark_del]) + if mark_ins: + cmd.extend(["--mark-ins", mark_ins]) + if mark_snv: + cmd.extend(["--mark-snv", mark_snv]) + if missing: + cmd.extend(["-m", missing]) + if sample: + cmd.extend(["-s", sample]) + if include: + cmd.extend(["--include", include]) + if exclude: + cmd.extend(["--exclude", exclude]) + + return _run_bcftools_command(cmd, output) + +@mcp.tool() +def bcftools_filter( + input_file: Path, + output: Optional[Path] = None, + output_type: str = "v", + include: Optional[str] = None, + exclude: Optional[str] = None, + soft_filter: Optional[str] = None, + set_gt: Optional[str] = None, + mode: str = "+", + threads: int = 1, +): + """ + Apply filters to VCF/BCF files. + """ + if not input_file.exists(): + raise FileNotFoundError(f"Input file not found: {input_file}") + if output_type not in ["b", "u", "z", "v"]: + raise ValueError("output_type must be one of 'b', 'u', 'z', 'v'.") + if mode not in ["+", "x", "X"]: + raise ValueError("mode must be one of '+', 'x', 'X'.") + + cmd = ["bcftools", "filter", str(input_file)] + + if output: + cmd.extend(["-o", str(output)]) + if output_type: + cmd.extend(["-O", output_type]) + if include: + cmd.extend(["-i", include]) + if exclude: + cmd.extend(["-e", exclude]) + if soft_filter: + cmd.extend(["-s", soft_filter]) + if set_gt: + cmd.extend(["-S", set_gt]) + if mode != "+": + cmd.extend(["-m", mode]) + if threads > 1: + cmd.extend(["--threads", str(threads)]) + + return _run_bcftools_command(cmd, output) + +@mcp.tool() +def bcftools_index( + input_file: Path, + force: bool = False, + stats: bool = False, + threads: int = 1, + csi: bool = False, + tbi: bool = False, + min_csi_shift: int = 14, +): + """ + Index VCF/BCF files for fast random access. + """ + if not input_file.exists(): + raise FileNotFoundError(f"Input file not found: {input_file}") + if csi and tbi: + raise ValueError("Cannot specify both --csi (-c) and --tbi (-t).") + + cmd = ["bcftools", "index"] + + if force: + cmd.append("-f") + if stats: + cmd.append("-n") + if threads > 1: + cmd.extend(["--threads", str(threads)]) + if csi: + cmd.append("-c") + if tbi: + cmd.append("-t") + if csi and min_csi_shift != 14: + cmd.extend(["-m", str(min_csi_shift)]) + + cmd.append(str(input_file)) + + # The output file is the index file itself + output_idx_file = None + if csi: + output_idx_file = Path(str(input_file) + ".csi") + else: # default is tbi for vcf.gz, csi for bcf + if str(input_file).endswith(".bcf"): + output_idx_file = Path(str(input_file) + ".csi") + else: + output_idx_file = Path(str(input_file) + ".tbi") + + return _run_bcftools_command(cmd, output_idx_file) + +@mcp.tool() +def bcftools_isec( + input_files: List[Path], + output_dir: Path, + output_type: str = "v", + complement: bool = False, + collapse: Optional[str] = None, + exclude: Optional[str] = None, + include: Optional[str] = None, + n_sites: Optional[str] = None, + regions: Optional[str] = None, + regions_file: Optional[Path] = None, + targets: Optional[str] = None, + targets_file: Optional[Path] = None, + threads: int = 1, +): + """ + Create intersections, unions, and complements of VCF/BCF files. + """ + if len(input_files) < 2: + raise ValueError("At least two input files must be provided for isec.") + for f in input_files: + if not f.exists(): + raise FileNotFoundError(f"Input file not found: {f}") + if output_type not in ["b", "u", "z", "v"]: + raise ValueError("output_type must be one of 'b', 'u', 'z', 'v'.") + if collapse and collapse not in ["none", "all", "snps", "indels", "both", "any"]: + raise ValueError("Invalid value for collapse.") + + output_dir.mkdir(parents=True, exist_ok=True) + + cmd = ["bcftools", "isec"] + cmd.extend(["-p", str(output_dir)]) + cmd.extend(["-O", output_type]) + + if complement: + cmd.append("-c") + if collapse: + cmd.extend(["--collapse", collapse]) + if exclude: + cmd.extend(["-e", exclude]) + if include: + cmd.extend(["-i", include]) + if n_sites: + cmd.extend(["-n", n_sites]) + if regions: + cmd.extend(["-r", regions]) + if regions_file: + cmd.extend(["-R", str(regions_file)]) + if targets: + cmd.extend(["-t", targets]) + if targets_file: + cmd.extend(["-T", str(targets_file)]) + if threads > 1: + cmd.extend(["--threads", str(threads)]) + + cmd.extend([str(f) for f in input_files]) + + # isec doesn't have a single output file, it creates a directory + # We will return the directory path in a structured way if needed, + # but for now, we'll rely on the user knowing the output is a directory. + # The _run_bcftools_command helper won't find a single output file. + result = _run_bcftools_command(cmd) + + # Manually list created files + if result["return_code"] == 0: + created_files = [str(p) for p in output_dir.glob('*')] + result["output_files"] = created_files + + return result + +@mcp.tool() +def bcftools_merge( + input_files: List[Path], + output: Optional[Path] = None, + output_type: str = "v", + info_rules: Optional[str] = None, + merge_logic: Optional[str] = None, + threads: int = 1, +): + """ + Merge multiple VCF/BCF files from different samples into a single file. + """ + if not input_files: + raise ValueError("At least one input file must be provided.") + for f in input_files: + if not f.exists(): + raise FileNotFoundError(f"Input file not found: {f}") + if output_type not in ["b", "u", "z", "v"]: + raise ValueError("output_type must be one of 'b', 'u', 'z', 'v'.") + + cmd = ["bcftools", "merge"] + + if output: + cmd.extend(["-o", str(output)]) + if output_type: + cmd.extend(["-O", output_type]) + if info_rules: + cmd.extend(["--info-rules", info_rules]) + if merge_logic: + cmd.extend(["-m", merge_logic]) + if threads > 1: + cmd.extend(["--threads", str(threads)]) + + cmd.extend([str(f) for f in input_files]) + + return _run_bcftools_command(cmd, output) + +@mcp.tool() +def bcftools_mpileup( + input_bams: List[Path], + fasta_ref: Path, + output: Optional[Path] = None, + output_type: str = "v", + regions: Optional[str] = None, + regions_file: Optional[Path] = None, + annotate: Optional[str] = None, + max_depth: int = 250, + min_base_quality: int = 13, + min_mapping_quality: int = 0, + adjust_mq: int = 50, + no_baq: bool = False, + threads: int = 1, +): + """ + Generate VCF/BCF from alignment files (BAM/CRAM). + """ + if not input_bams: + raise ValueError("At least one input BAM/CRAM file must be provided.") + for f in input_bams: + if not f.exists(): + raise FileNotFoundError(f"Input alignment file not found: {f}") + if not fasta_ref.exists(): + raise FileNotFoundError(f"Reference FASTA file not found: {fasta_ref}") + if output_type not in ["b", "u", "z", "v"]: + raise ValueError("output_type must be one of 'b', 'u', 'z', 'v'.") + + cmd = ["bcftools", "mpileup"] + cmd.extend(["-f", str(fasta_ref)]) + + if output: + cmd.extend(["-o", str(output)]) + if output_type: + cmd.extend(["-O", output_type]) + if regions: + cmd.extend(["-r", regions]) + if regions_file: + cmd.extend(["-R", str(regions_file)]) + if annotate: + cmd.extend(["-a", annotate]) + if max_depth != 250: + cmd.extend(["-d", str(max_depth)]) + if min_base_quality != 13: + cmd.extend(["-q", str(min_base_quality)]) + if min_mapping_quality != 0: + cmd.extend(["-Q", str(min_mapping_quality)]) + if adjust_mq != 50: + cmd.extend(["-C", str(adjust_mq)]) + if no_baq: + cmd.append("-B") + if threads > 1: + cmd.extend(["--threads", str(threads)]) + + cmd.extend([str(f) for f in input_bams]) + + return _run_bcftools_command(cmd, output) + +@mcp.tool() +def bcftools_norm( + input_file: Path, + fasta_ref: Path, + output: Optional[Path] = None, + output_type: str = "v", + check_ref: str = "w", + multiallelics: Optional[str] = None, + atomize: bool = False, + rm_dup: Optional[str] = None, + threads: int = 1, +): + """ + Left-align and normalize indels, check REF, split multiallelic sites. + """ + if not input_file.exists(): + raise FileNotFoundError(f"Input file not found: {input_file}") + if not fasta_ref.exists(): + raise FileNotFoundError(f"Reference FASTA file not found: {fasta_ref}") + if output_type not in ["b", "u", "z", "v"]: + raise ValueError("output_type must be one of 'b', 'u', 'z', 'v'.") + if check_ref not in ["w", "e", "x", "s"]: + raise ValueError("check_ref must be one of 'w', 'e', 'x', 's'.") + + cmd = ["bcftools", "norm", str(input_file)] + cmd.extend(["-f", str(fasta_ref)]) + + if output: + cmd.extend(["-o", str(output)]) + if output_type: + cmd.extend(["-O", output_type]) + if check_ref != "w": + cmd.extend(["-c", check_ref]) + if multiallelics: + cmd.extend(["-m", multiallelics]) + if atomize: + cmd.append("-a") + if rm_dup: + cmd.extend(["-d", rm_dup]) + if threads > 1: + cmd.extend(["--threads", str(threads)]) + + return _run_bcftools_command(cmd, output) + +@mcp.tool() +def bcftools_query( + input_file: Path, + format_string: str, + output: Optional[Path] = None, + include: Optional[str] = None, + exclude: Optional[str] = None, + regions: Optional[str] = None, + regions_file: Optional[Path] = None, + samples: Optional[str] = None, + samples_file: Optional[Path] = None, + list_samples: bool = False, +): + """ + Extracts fields from VCF/BCF files and prints them in a user-defined format. + """ + if not input_file.exists(): + raise FileNotFoundError(f"Input file not found: {input_file}") + + cmd = ["bcftools", "query", str(input_file)] + + if list_samples: + cmd.append("-l") + else: + cmd.extend(["-f", format_string]) + + if output: + cmd.extend(["-o", str(output)]) + if include: + cmd.extend(["-i", include]) + if exclude: + cmd.extend(["-e", exclude]) + if regions: + cmd.extend(["-r", regions]) + if regions_file: + cmd.extend(["-R", str(regions_file)]) + if samples: + cmd.extend(["-s", samples]) + if samples_file: + cmd.extend(["-S", str(samples_file)]) + + return _run_bcftools_command(cmd, output) + +@mcp.tool() +def bcftools_reheader( + input_file: Path, + header: Optional[Path] = None, + samples: Optional[Path] = None, + output: Optional[Path] = None, + output_type: str = "v", +): + """ + Modify VCF/BCF header, e.g., rename samples. + """ + if not input_file.exists(): + raise FileNotFoundError(f"Input file not found: {input_file}") + if header and not header.exists(): + raise FileNotFoundError(f"Header file not found: {header}") + if samples and not samples.exists(): + raise FileNotFoundError(f"Samples file not found: {samples}") + if not header and not samples: + raise ValueError("Either 'header' or 'samples' file must be provided.") + if output_type not in ["b", "u", "z", "v"]: + raise ValueError("output_type must be one of 'b', 'u', 'z', 'v'.") + + cmd = ["bcftools", "reheader"] + + if header: + cmd.extend(["-h", str(header)]) + if samples: + cmd.extend(["-s", str(samples)]) + if output: + cmd.extend(["-o", str(output)]) + + cmd.append(str(input_file)) + + # Reheader does not support -O, output type is inferred from extension + return _run_bcftools_command(cmd, output) + +@mcp.tool() +def bcftools_sort( + input_file: Path, + output: Optional[Path] = None, + output_type: str = "v", + max_mem: str = "768M", + temp_dir: Optional[Path] = None, +): + """ + Sort VCF/BCF file by chromosome and position. + """ + if not input_file.exists(): + raise FileNotFoundError(f"Input file not found: {input_file}") + if output_type not in ["b", "u", "z", "v"]: + raise ValueError("output_type must be one of 'b', 'u', 'z', 'v'.") + + cmd = ["bcftools", "sort", str(input_file)] + + if output: + cmd.extend(["-o", str(output)]) + if output_type: + cmd.extend(["-O", output_type]) + if max_mem: + cmd.extend(["-m", max_mem]) + if temp_dir: + temp_dir.mkdir(exist_ok=True, parents=True) + cmd.extend(["-T", str(temp_dir)]) + + return _run_bcftools_command(cmd, output) + +@mcp.tool() +def bcftools_stats( + input_files: List[Path], + fasta_ref: Optional[Path] = None, + output_dir: Optional[Path] = None, + regions: Optional[str] = None, + regions_file: Optional[Path] = None, + samples: Optional[str] = None, + samples_file: Optional[Path] = None, + threads: int = 1, +): + """ + Produce VCF/BCF stats, create plots with plot-vcfstats. + """ + if not input_files: + raise ValueError("At least one input file must be provided.") + for f in input_files: + if not f.exists(): + raise FileNotFoundError(f"Input file not found: {f}") + if fasta_ref and not fasta_ref.exists(): + raise FileNotFoundError(f"Reference FASTA file not found: {fasta_ref}") + + cmd = ["bcftools", "stats"] + + if fasta_ref: + cmd.extend(["-f", str(fasta_ref)]) + if regions: + cmd.extend(["-r", regions]) + if regions_file: + cmd.extend(["-R", str(regions_file)]) + if samples: + cmd.extend(["-s", samples]) + if samples_file: + cmd.extend(["-S", str(samples_file)]) + if threads > 1: + cmd.extend(["--threads", str(threads)]) + + cmd.extend([str(f) for f in input_files]) + + # stats command outputs to stdout by default. + # If output_dir is provided, we redirect stdout to a file. + output_file = None + if output_dir: + output_dir.mkdir(exist_ok=True, parents=True) + output_file = output_dir / "stats.txt" + with open(output_file, "w") as f_out: + command_str = " ".join(cmd) + try: + result = subprocess.run( + cmd, + stdout=f_out, + stderr=subprocess.PIPE, + text=True, + check=True, + ) + return { + "command_executed": command_str, + "stdout": f"Stats written to {output_file}", + "stderr": result.stderr, + "output_files": [str(output_file)], + "return_code": 0, + } + except subprocess.CalledProcessError as e: + return { + "command_executed": command_str, + "stdout": e.stdout or "", + "stderr": e.stderr, + "output_files": [], + "return_code": e.returncode, + "error": "CalledProcessError" + } + else: + # No output file, capture stdout directly + return _run_bcftools_command(cmd) + +@mcp.tool() +def bcftools_view( + input_file: Path, + output: Optional[Path] = None, + output_type: str = "v", + header_only: bool = False, + no_header: bool = False, + drop_genotypes: bool = False, + trim_alt_alleles: bool = False, + min_alleles: Optional[int] = None, + max_alleles: Optional[int] = None, + min_ac: Optional[int] = None, + max_ac: Optional[int] = None, + min_af: Optional[float] = None, + max_af: Optional[float] = None, + types: Optional[str] = None, + include: Optional[str] = None, + exclude: Optional[str] = None, + regions: Optional[str] = None, + regions_file: Optional[Path] = None, + samples: Optional[str] = None, + samples_file: Optional[Path] = None, + threads: int = 1, +): + """ + Subset, filter, and convert VCF and BCF files. + """ + if not input_file.exists(): + raise FileNotFoundError(f"Input file not found: {input_file}") + if output_type not in ["b", "u", "z", "v"]: + raise ValueError("output_type must be one of 'b', 'u', 'z', 'v'.") + + cmd = ["bcftools", "view", str(input_file)] + + if output: + cmd.extend(["-o", str(output)]) + if output_type: + cmd.extend(["-O", output_type]) + if header_only: + cmd.append("-h") + if no_header: + cmd.append("-H") + if drop_genotypes: + cmd.append("-G") + if trim_alt_alleles: + cmd.append("-a") + if min_alleles is not None: + cmd.extend(["-m", str(min_alleles)]) + if max_alleles is not None: + cmd.extend(["-M", str(max_alleles)]) + if min_ac is not None: + cmd.extend(["-c", str(min_ac)]) + if max_ac is not None: + cmd.extend(["-C", str(max_ac)]) + if min_af is not None: + cmd.extend(["-q", str(min_af)]) + if max_af is not None: + cmd.extend(["-Q", str(max_af)]) + if types: + cmd.extend(["-v", types]) + if include: + cmd.extend(["-i", include]) + if exclude: + cmd.extend(["-e", exclude]) + if regions: + cmd.extend(["-r", regions]) + if regions_file: + cmd.extend(["-R", str(regions_file)]) + if samples: + cmd.extend(["-s", samples]) + if samples_file: + cmd.extend(["-S", str(samples_file)]) + if threads > 1: + cmd.extend(["--threads", str(threads)]) + + return _run_bcftools_command(cmd, output) \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bcftools/app/bcftools_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bcftools/app/bcftools_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..524cd0a2aaba344aa7af43bbf7efda3c34265972 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bcftools/app/bcftools_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bcftools/app/bcftools_server.py') +SERVER_NAME = 'biosci_bcftools' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bcftools/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bcftools/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..b6d4e0018c2bd5952a61daa862c93500125d3415 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bcftools/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-bcftools: + build: . + image: mcp-bcftools:latest + container_name: mcp-bcftools + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=bcftools + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bcftools/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bcftools/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..047c9fb057f47426cf0d379551d816ade5cd1fcd --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bcftools/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - bcftools + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bcftools/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bcftools/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bcftools/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bedops/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bedops/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..565ae50155b78f1d8b26241027d43a56a2b50f5a --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bedops/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install bedops via conda (e.g., from bioconda) +RUN conda install -c bioconda bedops -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY app/bedops_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/bedops_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/bedops_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bedops/app/bedops_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bedops/app/bedops_server.py new file mode 100644 index 0000000000000000000000000000000000000000..83f7d8dfa5ad2bb88469adccd27792cee19213de --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bedops/app/bedops_server.py @@ -0,0 +1,819 @@ +import subprocess +import tempfile +from pathlib import Path +from typing import List, Optional + +# MCP decorator is commented out as per instructions +# import mcp + +@mcp.tool() +def bedops_complement( + files: List[Path], + chop_to_limits: bool = False, + chrom: Optional[str] = None, + ec: bool = False, + header: bool = False, + range_str: Optional[str] = None, + output_file: Optional[Path] = None, +) -> dict: + """ + Computes the complement of one or more BED files. + + This corresponds to the `bedops -c` or `bedops --complement` operation. + It finds the regions within chromosome boundaries that are not covered by + any intervals in the input file(s). + + Args: + files: A list of one or more input BED/Starch files. Must be sorted. + chop_to_limits: If True, chop complementary regions to chromosome limits + defined by the first input file (-L flag). + chrom: Process data for the given chromosome only. + ec: Error check input files (slower). + header: Accept headers (VCF, GFF, SAM, BED, WIG) in any input file. + range_str: Pad coordinates. Use 'L:R' format (e.g., '-10:20') or a + single value 'S' for symmetric padding (e.g., '100'). + output_file: Optional path to save the output. If not provided, + output is returned as a string in the result dictionary. + + Returns: + A dictionary containing the command executed, stdout, stderr, and a + list of output files generated. + """ + if not files: + raise ValueError("At least one input file must be provided for the complement operation.") + for file_path in files: + if not file_path.exists(): + raise FileNotFoundError(f"Input file not found: {file_path}") + + cmd = ["bedops"] + + if chrom: + cmd.extend(["--chrom", chrom]) + if ec: + cmd.append("--ec") + if header: + cmd.append("--header") + if range_str: + cmd.extend(["--range", range_str]) + + cmd.append("--complement") + if chop_to_limits: + cmd.append("-L") + + cmd.extend([str(p) for p in files]) + + try: + if output_file: + with open(output_file, "w") as f: + result = subprocess.run( + cmd, check=True, text=True, stdout=f, stderr=subprocess.PIPE + ) + stdout_capture = "" + output_files_list = [str(output_file)] + else: + result = subprocess.run( + cmd, check=True, text=True, capture_output=True + ) + stdout_capture = result.stdout + output_files_list = [] + + return { + "command_executed": " ".join(cmd), + "stdout": stdout_capture, + "stderr": result.stderr, + "output_files": output_files_list, + } + except subprocess.CalledProcessError as e: + raise RuntimeError( + f"bedops complement failed with exit code {e.returncode}\n" + f"Stderr: {e.stderr}\n" + f"Stdout: {e.stdout}\n" + f"Command: {' '.join(cmd)}" + ) from e + +@mcp.tool() +def bedops_difference( + files: List[Path], + chrom: Optional[str] = None, + ec: bool = False, + header: bool = False, + range_str: Optional[str] = None, + output_file: Optional[Path] = None, +) -> dict: + """ + Computes the difference between a reference BED file and one or more other BED files. + + This corresponds to the `bedops -d` or `bedops --difference` operation. + It returns regions from the first (reference) file that do not overlap + with any regions in the subsequent files. + + Args: + files: A list of two or more input BED/Starch files. The first file is + the reference. All files must be sorted. + chrom: Process data for the given chromosome only. + ec: Error check input files (slower). + header: Accept headers (VCF, GFF, SAM, BED, WIG) in any input file. + range_str: Pad coordinates. Use 'L:R' format (e.g., '-10:20') or a + single value 'S' for symmetric padding (e.g., '100'). + output_file: Optional path to save the output. If not provided, + output is returned as a string in the result dictionary. + + Returns: + A dictionary containing the command executed, stdout, stderr, and a + list of output files generated. + """ + if len(files) < 2: + raise ValueError("At least two input files (a reference and one other) must be provided for the difference operation.") + for file_path in files: + if not file_path.exists(): + raise FileNotFoundError(f"Input file not found: {file_path}") + + cmd = ["bedops"] + + if chrom: + cmd.extend(["--chrom", chrom]) + if ec: + cmd.append("--ec") + if header: + cmd.append("--header") + if range_str: + cmd.extend(["--range", range_str]) + + cmd.append("--difference") + cmd.extend([str(p) for p in files]) + + try: + if output_file: + with open(output_file, "w") as f: + result = subprocess.run( + cmd, check=True, text=True, stdout=f, stderr=subprocess.PIPE + ) + stdout_capture = "" + output_files_list = [str(output_file)] + else: + result = subprocess.run( + cmd, check=True, text=True, capture_output=True + ) + stdout_capture = result.stdout + output_files_list = [] + + return { + "command_executed": " ".join(cmd), + "stdout": stdout_capture, + "stderr": result.stderr, + "output_files": output_files_list, + } + except subprocess.CalledProcessError as e: + raise RuntimeError( + f"bedops difference failed with exit code {e.returncode}\n" + f"Stderr: {e.stderr}\n" + f"Stdout: {e.stdout}\n" + f"Command: {' '.join(cmd)}" + ) from e + +@mcp.tool() +def bedops_element_of( + files: List[Path], + overlap_criterion: str = "100%", + chrom: Optional[str] = None, + ec: bool = False, + header: bool = False, + range_str: Optional[str] = None, + output_file: Optional[Path] = None, +) -> dict: + """ + Finds elements in the reference file that overlap other files by a specified amount. + + This corresponds to the `bedops -e` or `bedops --element-of` operation. + It returns elements from the first (reference) file that overlap elements + in any of the other files by at least the specified amount. + + Args: + files: A list of two or more input BED/Starch files. The first file is + the reference. All files must be sorted. + overlap_criterion: The required overlap, as base pairs (e.g., '1') or + percentage (e.g., '50%'). Defaults to '100%'. + chrom: Process data for the given chromosome only. + ec: Error check input files (slower). + header: Accept headers (VCF, GFF, SAM, BED, WIG) in any input file. + range_str: Pad coordinates. Use 'L:R' or 'S' format. The first (reference) + file is NOT padded with this operation. + output_file: Optional path to save the output. If not provided, + output is returned as a string in the result dictionary. + + Returns: + A dictionary containing the command executed, stdout, stderr, and a + list of output files generated. + """ + if len(files) < 2: + raise ValueError("At least two input files (a reference and one other) must be provided for the element-of operation.") + for file_path in files: + if not file_path.exists(): + raise FileNotFoundError(f"Input file not found: {file_path}") + + cmd = ["bedops"] + + if chrom: + cmd.extend(["--chrom", chrom]) + if ec: + cmd.append("--ec") + if header: + cmd.append("--header") + if range_str: + cmd.extend(["--range", range_str]) + + cmd.extend(["--element-of", overlap_criterion]) + cmd.extend([str(p) for p in files]) + + try: + if output_file: + with open(output_file, "w") as f: + result = subprocess.run( + cmd, check=True, text=True, stdout=f, stderr=subprocess.PIPE + ) + stdout_capture = "" + output_files_list = [str(output_file)] + else: + result = subprocess.run( + cmd, check=True, text=True, capture_output=True + ) + stdout_capture = result.stdout + output_files_list = [] + + return { + "command_executed": " ".join(cmd), + "stdout": stdout_capture, + "stderr": result.stderr, + "output_files": output_files_list, + } + except subprocess.CalledProcessError as e: + raise RuntimeError( + f"bedops element-of failed with exit code {e.returncode}\n" + f"Stderr: {e.stderr}\n" + f"Stdout: {e.stdout}\n" + f"Command: {' '.join(cmd)}" + ) from e + +@mcp.tool() +def bedops_intersect( + files: List[Path], + chrom: Optional[str] = None, + ec: bool = False, + header: bool = False, + range_str: Optional[str] = None, + output_file: Optional[Path] = None, +) -> dict: + """ + Computes the intersection of two or more BED files. + + This corresponds to the `bedops -i` or `bedops --intersect` operation. + It returns regions that are common to all input files. + + Args: + files: A list of two or more input BED/Starch files. All files must be sorted. + chrom: Process data for the given chromosome only. + ec: Error check input files (slower). + header: Accept headers (VCF, GFF, SAM, BED, WIG) in any input file. + range_str: Pad coordinates. Use 'L:R' format (e.g., '-10:20') or a + single value 'S' for symmetric padding (e.g., '100'). + output_file: Optional path to save the output. If not provided, + output is returned as a string in the result dictionary. + + Returns: + A dictionary containing the command executed, stdout, stderr, and a + list of output files generated. + """ + if len(files) < 2: + raise ValueError("At least two input files must be provided for the intersect operation.") + for file_path in files: + if not file_path.exists(): + raise FileNotFoundError(f"Input file not found: {file_path}") + + cmd = ["bedops"] + + if chrom: + cmd.extend(["--chrom", chrom]) + if ec: + cmd.append("--ec") + if header: + cmd.append("--header") + if range_str: + cmd.extend(["--range", range_str]) + + cmd.append("--intersect") + cmd.extend([str(p) for p in files]) + + try: + if output_file: + with open(output_file, "w") as f: + result = subprocess.run( + cmd, check=True, text=True, stdout=f, stderr=subprocess.PIPE + ) + stdout_capture = "" + output_files_list = [str(output_file)] + else: + result = subprocess.run( + cmd, check=True, text=True, capture_output=True + ) + stdout_capture = result.stdout + output_files_list = [] + + return { + "command_executed": " ".join(cmd), + "stdout": stdout_capture, + "stderr": result.stderr, + "output_files": output_files_list, + } + except subprocess.CalledProcessError as e: + raise RuntimeError( + f"bedops intersect failed with exit code {e.returncode}\n" + f"Stderr: {e.stderr}\n" + f"Stdout: {e.stdout}\n" + f"Command: {' '.join(cmd)}" + ) from e + +@mcp.tool() +def bedops_merge( + files: List[Path], + chrom: Optional[str] = None, + ec: bool = False, + header: bool = False, + range_str: Optional[str] = None, + output_file: Optional[Path] = None, +) -> dict: + """ + Merges overlapping regions from one or more BED files. + + This corresponds to the `bedops -m` or `bedops --merge` operation. + It combines overlapping or adjacent intervals into a single, larger interval. + + Args: + files: A list of one or more input BED/Starch files. Must be sorted. + chrom: Process data for the given chromosome only. + ec: Error check input files (slower). + header: Accept headers (VCF, GFF, SAM, BED, WIG) in any input file. + range_str: Pad coordinates. Use 'L:R' format (e.g., '-10:20') or a + single value 'S' for symmetric padding (e.g., '100'). + output_file: Optional path to save the output. If not provided, + output is returned as a string in the result dictionary. + + Returns: + A dictionary containing the command executed, stdout, stderr, and a + list of output files generated. + """ + if not files: + raise ValueError("At least one input file must be provided for the merge operation.") + for file_path in files: + if not file_path.exists(): + raise FileNotFoundError(f"Input file not found: {file_path}") + + cmd = ["bedops"] + + if chrom: + cmd.extend(["--chrom", chrom]) + if ec: + cmd.append("--ec") + if header: + cmd.append("--header") + if range_str: + cmd.extend(["--range", range_str]) + + cmd.append("--merge") + cmd.extend([str(p) for p in files]) + + try: + if output_file: + with open(output_file, "w") as f: + result = subprocess.run( + cmd, check=True, text=True, stdout=f, stderr=subprocess.PIPE + ) + stdout_capture = "" + output_files_list = [str(output_file)] + else: + result = subprocess.run( + cmd, check=True, text=True, capture_output=True + ) + stdout_capture = result.stdout + output_files_list = [] + + return { + "command_executed": " ".join(cmd), + "stdout": stdout_capture, + "stderr": result.stderr, + "output_files": output_files_list, + } + except subprocess.CalledProcessError as e: + raise RuntimeError( + f"bedops merge failed with exit code {e.returncode}\n" + f"Stderr: {e.stderr}\n" + f"Stdout: {e.stdout}\n" + f"Command: {' '.join(cmd)}" + ) from e + +@mcp.tool() +def bedops_not_element_of( + files: List[Path], + overlap_criterion: str = "100%", + chrom: Optional[str] = None, + ec: bool = False, + header: bool = False, + range_str: Optional[str] = None, + output_file: Optional[Path] = None, +) -> dict: + """ + Finds elements in the reference file that DO NOT overlap other files by a specified amount. + + This corresponds to the `bedops -n` or `bedops --not-element-of` operation. + It is the inverse of the `element-of` operation. + + Args: + files: A list of two or more input BED/Starch files. The first file is + the reference. All files must be sorted. + overlap_criterion: The required overlap, as base pairs (e.g., '1') or + percentage (e.g., '50%'). Defaults to '100%'. + chrom: Process data for the given chromosome only. + ec: Error check input files (slower). + header: Accept headers (VCF, GFF, SAM, BED, WIG) in any input file. + range_str: Pad coordinates. Use 'L:R' or 'S' format. The first (reference) + file is NOT padded with this operation. + output_file: Optional path to save the output. If not provided, + output is returned as a string in the result dictionary. + + Returns: + A dictionary containing the command executed, stdout, stderr, and a + list of output files generated. + """ + if len(files) < 2: + raise ValueError("At least two input files (a reference and one other) must be provided for the not-element-of operation.") + for file_path in files: + if not file_path.exists(): + raise FileNotFoundError(f"Input file not found: {file_path}") + + cmd = ["bedops"] + + if chrom: + cmd.extend(["--chrom", chrom]) + if ec: + cmd.append("--ec") + if header: + cmd.append("--header") + if range_str: + cmd.extend(["--range", range_str]) + + cmd.extend(["--not-element-of", overlap_criterion]) + cmd.extend([str(p) for p in files]) + + try: + if output_file: + with open(output_file, "w") as f: + result = subprocess.run( + cmd, check=True, text=True, stdout=f, stderr=subprocess.PIPE + ) + stdout_capture = "" + output_files_list = [str(output_file)] + else: + result = subprocess.run( + cmd, check=True, text=True, capture_output=True + ) + stdout_capture = result.stdout + output_files_list = [] + + return { + "command_executed": " ".join(cmd), + "stdout": stdout_capture, + "stderr": result.stderr, + "output_files": output_files_list, + } + except subprocess.CalledProcessError as e: + raise RuntimeError( + f"bedops not-element-of failed with exit code {e.returncode}\n" + f"Stderr: {e.stderr}\n" + f"Stdout: {e.stdout}\n" + f"Command: {' '.join(cmd)}" + ) from e + +@mcp.tool() +def bedops_partition( + files: List[Path], + chrom: Optional[str] = None, + ec: bool = False, + header: bool = False, + range_str: Optional[str] = None, + output_file: Optional[Path] = None, +) -> dict: + """ + Partitions the input BED file(s) into disjoint segments. + + This corresponds to the `bedops -p` or `bedops --partition` operation. + It breaks the input regions into non-overlapping segments, reporting each + new segment and which input files it came from. + + Args: + files: A list of one or more input BED/Starch files. Must be sorted. + chrom: Process data for the given chromosome only. + ec: Error check input files (slower). + header: Accept headers (VCF, GFF, SAM, BED, WIG) in any input file. + range_str: Pad coordinates. Use 'L:R' format (e.g., '-10:20') or a + single value 'S' for symmetric padding (e.g., '100'). + output_file: Optional path to save the output. If not provided, + output is returned as a string in the result dictionary. + + Returns: + A dictionary containing the command executed, stdout, stderr, and a + list of output files generated. + """ + if not files: + raise ValueError("At least one input file must be provided for the partition operation.") + for file_path in files: + if not file_path.exists(): + raise FileNotFoundError(f"Input file not found: {file_path}") + + cmd = ["bedops"] + + if chrom: + cmd.extend(["--chrom", chrom]) + if ec: + cmd.append("--ec") + if header: + cmd.append("--header") + if range_str: + cmd.extend(["--range", range_str]) + + cmd.append("--partition") + cmd.extend([str(p) for p in files]) + + try: + if output_file: + with open(output_file, "w") as f: + result = subprocess.run( + cmd, check=True, text=True, stdout=f, stderr=subprocess.PIPE + ) + stdout_capture = "" + output_files_list = [str(output_file)] + else: + result = subprocess.run( + cmd, check=True, text=True, capture_output=True + ) + stdout_capture = result.stdout + output_files_list = [] + + return { + "command_executed": " ".join(cmd), + "stdout": stdout_capture, + "stderr": result.stderr, + "output_files": output_files_list, + } + except subprocess.CalledProcessError as e: + raise RuntimeError( + f"bedops partition failed with exit code {e.returncode}\n" + f"Stderr: {e.stderr}\n" + f"Stdout: {e.stdout}\n" + f"Command: {' '.join(cmd)}" + ) from e + +@mcp.tool() +def bedops_symmdiff( + files: List[Path], + chrom: Optional[str] = None, + ec: bool = False, + header: bool = False, + range_str: Optional[str] = None, + output_file: Optional[Path] = None, +) -> dict: + """ + Computes the symmetric difference of two or more BED files. + + This corresponds to the `bedops -s` or `bedops --symmdiff` operation. + It returns regions that are unique to any of the input files (i.e., not + present in their intersection). + + Args: + files: A list of two or more input BED/Starch files. All files must be sorted. + chrom: Process data for the given chromosome only. + ec: Error check input files (slower). + header: Accept headers (VCF, GFF, SAM, BED, WIG) in any input file. + range_str: Pad coordinates. Use 'L:R' format (e.g., '-10:20') or a + single value 'S' for symmetric padding (e.g., '100'). + output_file: Optional path to save the output. If not provided, + output is returned as a string in the result dictionary. + + Returns: + A dictionary containing the command executed, stdout, stderr, and a + list of output files generated. + """ + if len(files) < 2: + raise ValueError("At least two input files must be provided for the symmetric difference operation.") + for file_path in files: + if not file_path.exists(): + raise FileNotFoundError(f"Input file not found: {file_path}") + + cmd = ["bedops"] + + if chrom: + cmd.extend(["--chrom", chrom]) + if ec: + cmd.append("--ec") + if header: + cmd.append("--header") + if range_str: + cmd.extend(["--range", range_str]) + + cmd.append("--symmdiff") + cmd.extend([str(p) for p in files]) + + try: + if output_file: + with open(output_file, "w") as f: + result = subprocess.run( + cmd, check=True, text=True, stdout=f, stderr=subprocess.PIPE + ) + stdout_capture = "" + output_files_list = [str(output_file)] + else: + result = subprocess.run( + cmd, check=True, text=True, capture_output=True + ) + stdout_capture = result.stdout + output_files_list = [] + + return { + "command_executed": " ".join(cmd), + "stdout": stdout_capture, + "stderr": result.stderr, + "output_files": output_files_list, + } + except subprocess.CalledProcessError as e: + raise RuntimeError( + f"bedops symmdiff failed with exit code {e.returncode}\n" + f"Stderr: {e.stderr}\n" + f"Stdout: {e.stdout}\n" + f"Command: {' '.join(cmd)}" + ) from e + +@mcp.tool() +def bedops_everything( + files: List[Path], + chrom: Optional[str] = None, + ec: bool = False, + header: bool = False, + range_str: Optional[str] = None, + output_file: Optional[Path] = None, +) -> dict: + """ + Returns the union of all elements from input files without merging. + + This corresponds to the `bedops -u` or `bedops --everything` operation. + It effectively concatenates the input files while maintaining sort order + and preserving all original columns. + + Args: + files: A list of one or more input BED/Starch files. Must be sorted. + chrom: Process data for the given chromosome only. + ec: Error check input files (slower). + header: Accept headers (VCF, GFF, SAM, BED, WIG) in any input file. + range_str: Pad coordinates. Use 'L:R' format (e.g., '-10:20') or a + single value 'S' for symmetric padding (e.g., '100'). + output_file: Optional path to save the output. If not provided, + output is returned as a string in the result dictionary. + + Returns: + A dictionary containing the command executed, stdout, stderr, and a + list of output files generated. + """ + if not files: + raise ValueError("At least one input file must be provided for the everything operation.") + for file_path in files: + if not file_path.exists(): + raise FileNotFoundError(f"Input file not found: {file_path}") + + cmd = ["bedops"] + + if chrom: + cmd.extend(["--chrom", chrom]) + if ec: + cmd.append("--ec") + if header: + cmd.append("--header") + if range_str: + cmd.extend(["--range", range_str]) + + cmd.append("--everything") + cmd.extend([str(p) for p in files]) + + try: + if output_file: + with open(output_file, "w") as f: + result = subprocess.run( + cmd, check=True, text=True, stdout=f, stderr=subprocess.PIPE + ) + stdout_capture = "" + output_files_list = [str(output_file)] + else: + result = subprocess.run( + cmd, check=True, text=True, capture_output=True + ) + stdout_capture = result.stdout + output_files_list = [] + + return { + "command_executed": " ".join(cmd), + "stdout": stdout_capture, + "stderr": result.stderr, + "output_files": output_files_list, + } + except subprocess.CalledProcessError as e: + raise RuntimeError( + f"bedops everything failed with exit code {e.returncode}\n" + f"Stderr: {e.stderr}\n" + f"Stdout: {e.stdout}\n" + f"Command: {' '.join(cmd)}" + ) from e + +@mcp.tool() +def bedops_chop( + files: List[Path], + bp: int = 1, + stagger: Optional[int] = None, + exclusive_chop: bool = False, + chrom: Optional[str] = None, + ec: bool = False, + header: bool = False, + range_str: Optional[str] = None, + output_file: Optional[Path] = None, +) -> dict: + """ + Chops elements into fixed-size, potentially staggered sub-elements. + + This corresponds to the `bedops -w` or `bedops --chop` operation. + + Args: + files: A list of one or more input BED/Starch files. Must be sorted. + bp: The size in base pairs of each chopped element. Defaults to 1. + stagger: The stagger distance in nucleotides. If not set, no staggering is done. + exclusive_chop: If True, removes single-base elements that can result + from chopping (-x flag). + chrom: Process data for the given chromosome only. + ec: Error check input files (slower). + header: Accept headers (VCF, GFF, SAM, BED, WIG) in any input file. + range_str: Pad coordinates. Use 'L:R' format (e.g., '-10:20') or a + single value 'S' for symmetric padding (e.g., '100'). + output_file: Optional path to save the output. If not provided, + output is returned as a string in the result dictionary. + + Returns: + A dictionary containing the command executed, stdout, stderr, and a + list of output files generated. + """ + if not files: + raise ValueError("At least one input file must be provided for the chop operation.") + for file_path in files: + if not file_path.exists(): + raise FileNotFoundError(f"Input file not found: {file_path}") + + cmd = ["bedops"] + + if chrom: + cmd.extend(["--chrom", chrom]) + if ec: + cmd.append("--ec") + if header: + cmd.append("--header") + if range_str: + cmd.extend(["--range", range_str]) + + cmd.extend(["--chop", str(bp)]) + if stagger is not None: + cmd.extend(["--stagger", str(stagger)]) + if exclusive_chop: + cmd.append("-x") + + cmd.extend([str(p) for p in files]) + + try: + if output_file: + with open(output_file, "w") as f: + result = subprocess.run( + cmd, check=True, text=True, stdout=f, stderr=subprocess.PIPE + ) + stdout_capture = "" + output_files_list = [str(output_file)] + else: + result = subprocess.run( + cmd, check=True, text=True, capture_output=True + ) + stdout_capture = result.stdout + output_files_list = [] + + return { + "command_executed": " ".join(cmd), + "stdout": stdout_capture, + "stderr": result.stderr, + "output_files": output_files_list, + } + except subprocess.CalledProcessError as e: + raise RuntimeError( + f"bedops chop failed with exit code {e.returncode}\n" + f"Stderr: {e.stderr}\n" + f"Stdout: {e.stdout}\n" + f"Command: {' '.join(cmd)}" + ) from e \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bedops/app/bedops_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bedops/app/bedops_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..4be003035fc3d2877db85a69e3f99d712e5e6a44 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bedops/app/bedops_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bedops/app/bedops_server.py') +SERVER_NAME = 'biosci_bedops' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bedops/app/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bedops/app/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bedops/app/requirements.txt @@ -0,0 +1 @@ + diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bedops/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bedops/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..91a34e4d62a9ab6c006b5be2741a5942d0c66a8b --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bedops/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-bedops: + build: . + image: mcp-bedops:latest + container_name: mcp-bedops + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=bedops + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bedops/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bedops/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..11a313e56d9e8c3b984f027df03882228599fd59 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bedops/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - bedops + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioawk/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioawk/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..26acb9706d6e3e8a943d4d9676b9eb014a983372 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioawk/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install bioawk via conda (e.g., from bioconda) +RUN conda install -c bioconda bioawk -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY app/bioawk_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/bioawk_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/bioawk_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioawk/app/bioawk_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioawk/app/bioawk_server.py new file mode 100644 index 0000000000000000000000000000000000000000..045640223e6d54a4636d76ad5fad59535ca67373 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioawk/app/bioawk_server.py @@ -0,0 +1,132 @@ +import subprocess +from pathlib import Path +from typing import List, Optional, Dict, Any + +# Assume 'mcp' is a globally available module in the execution environment. +# from some_mcp_library import mcp + +@mcp.tool +def bioawk( + program: Optional[str] = None, + program_file: Optional[Path] = None, + input_files: Optional[List[Path]] = None, + output_file: Optional[Path] = None, + format: Optional[str] = None, + tab_separator: bool = False, + include_header: bool = False, + variables: Optional[List[str]] = None, + field_separator: Optional[str] = None, +) -> Dict[str, Any]: + """ + Executes the bioawk command, a powerful stream editor for biological data formats. + + bioawk is an extension of awk that understands common biological data formats + like FASTA, FASTQ, SAM, VCF, BED, and GFF. At least one of 'program' or + 'program_file' must be provided. + + Args: + program: The AWK program string to execute. Mutually exclusive with 'program_file'. + program_file: Path to a file containing the AWK program. Mutually exclusive with 'program'. + input_files: A list of input files to process. If not provided, bioawk reads from standard input. + output_file: Path to a file where the output (stdout) will be saved. If not provided, stdout is captured and returned. + format: Input format (-c). Supported formats include 'fasta', 'fastq', 'sam', 'vcf', 'bed', 'gff'. + tab_separator: Use tab as the input and output field separator (-t flag). + include_header: Include header in the output for formats like VCF/SAM (-H flag). + variables: A list of 'var=value' strings to define AWK variables (-v flag). + field_separator: The input field separator string (-F flag). + + Returns: + A dictionary containing the executed command, stdout, stderr, and a list of output files. + """ + # --- Input Validation --- + if not program and not program_file: + raise ValueError("Either 'program' or 'program_file' must be provided.") + if program and program_file: + raise ValueError("'program' and 'program_file' are mutually exclusive and cannot be used together.") + + if program_file: + if not program_file.is_file(): + raise FileNotFoundError(f"Program file not found: {program_file}") + + if input_files: + for file_path in input_files: + if not file_path.is_file(): + raise FileNotFoundError(f"Input file not found: {file_path}") + + VALID_FORMATS = {"fasta", "fastq", "sam", "vcf", "bed", "gff"} + if format and format.lower() not in VALID_FORMATS: + raise ValueError(f"Invalid format '{format}'. Must be one of {VALID_FORMATS}.") + + if variables: + for var in variables: + if "=" not in var: + raise ValueError(f"Invalid variable assignment '{var}'. Must be in 'var=value' format.") + + # --- Command Construction --- + cmd = ["bioawk"] + + if format: + cmd.extend(["-c", format.lower()]) + if tab_separator: + cmd.append("-t") + if include_header: + cmd.append("-H") + if field_separator: + cmd.extend(["-F", field_separator]) + if variables: + for var in variables: + cmd.extend(["-v", var]) + + # The program or program_file argument must come after options but before input files. + if program_file: + cmd.extend(["-f", str(program_file)]) + elif program: + cmd.append(program) + + if input_files: + cmd.extend([str(p) for p in input_files]) + + command_executed = " ".join(cmd) + + # --- Subprocess Execution --- + try: + if output_file: + # Create parent directories if they don't exist + output_file.parent.mkdir(parents=True, exist_ok=True) + with open(output_file, "w") as f_out: + result = subprocess.run( + cmd, + check=True, + stdout=f_out, + stderr=subprocess.PIPE, + text=True, + ) + stdout_content = f"Output successfully written to {output_file}" + output_files_list = [str(output_file)] + else: + result = subprocess.run( + cmd, + check=True, + capture_output=True, + text=True, + ) + stdout_content = result.stdout + output_files_list = [] + + return { + "command_executed": command_executed, + "stdout": stdout_content, + "stderr": result.stderr, + "output_files": output_files_list, + } + except FileNotFoundError: + raise RuntimeError("bioawk command not found. Please ensure it is installed and in your system's PATH.") + except subprocess.CalledProcessError as e: + # Return a structured error response if the command fails + return { + "command_executed": command_executed, + "stdout": e.stdout or "", + "stderr": e.stderr or f"bioawk exited with error code {e.returncode}", + "output_files": [], + "error": f"Command failed with exit code {e.returncode}" + } \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioawk/app/bioawk_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioawk/app/bioawk_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..6b2bf10ed77446b94cc76a336eba7370590a14db --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioawk/app/bioawk_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioawk/app/bioawk_server.py') +SERVER_NAME = 'biosci_bioawk' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioawk/app/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioawk/app/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioawk/app/requirements.txt @@ -0,0 +1 @@ + diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioawk/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioawk/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..7225a96d51707881729bddfe8df7a8a8ad5a61bd --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioawk/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-bioawk: + build: . + image: mcp-bioawk:latest + container_name: mcp-bioawk + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=bioawk + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioawk/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioawk/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d850d38d19bdb05c11c590472bc88660b4d32fef --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioawk/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - bioawk + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioawk/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioawk/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioawk/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-affyio/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-affyio/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..6f2d33b2efd16bce295e2841bac519b1b3633d42 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-affyio/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install bioconductor-affyio via conda (e.g., from bioconda) +RUN conda install -c bioconda bioconductor-affyio -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY app/bioconductor-affyio_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/bioconductor-affyio_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/bioconductor-affyio_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-affyio/app/bioconductor-affyio_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-affyio/app/bioconductor-affyio_server.py new file mode 100644 index 0000000000000000000000000000000000000000..59885936782f559ab659966f24a285ba65cff383 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-affyio/app/bioconductor-affyio_server.py @@ -0,0 +1,208 @@ +import subprocess +import json +import os +from pathlib import Path +from typing import Optional, List, Dict, Any + +@mcp.tool() +def affyio_read_celfile_header( + filename: str, + info: str = "full" +) -> Dict[str, Any]: + """ + Read the header information from an Affymetrix CEL file. + + Args: + filename: Path to the CEL file. + info: Level of information to extract ('full' or 'minimal'). + """ + file_path = Path(filename) + if not file_path.exists(): + return {"error": f"File not found: {filename}"} + + if info not in ["full", "minimal"]: + info = "full" + + # R script to extract header and convert to JSON + r_command = f""" + library(affyio) + library(jsonlite) + header <- read.celfile.header("{str(file_path)}", info="{info}") + cat(toJSON(header, auto_unbox = TRUE)) + """ + + try: + result = subprocess.run( + ["Rscript", "-e", r_command], + capture_output=True, + text=True, + check=True + ) + return { + "command_executed": f"read.celfile.header('{filename}')", + "header_data": json.loads(result.stdout), + "stderr": result.stderr + } + except subprocess.CalledProcessError as e: + return { + "error": "R execution failed", + "stdout": e.stdout, + "stderr": e.stderr, + "command_executed": e.cmd + } + except json.JSONDecodeError: + return {"error": "Failed to parse R output", "raw_stdout": result.stdout} + +@mcp.tool() +def affyio_read_celfile( + filename: str, + output_csv: str, + intensity_only: bool = True +) -> Dict[str, Any]: + """ + Read an Affymetrix CEL file and export the intensity data to a CSV file. + + Args: + filename: Path to the CEL file. + output_csv: Path where the intensity data should be saved. + intensity_only: If True, only the intensity values are extracted. + """ + input_path = Path(filename) + output_path = Path(output_csv) + + if not input_path.exists(): + return {"error": f"Input file not found: {filename}"} + + intensity_val = "TRUE" if intensity_only else "FALSE" + + r_command = f""" + library(affyio) + data <- read.celfile("{str(input_path)}", intensity.only={intensity_val}) + # If intensity.only is TRUE, it returns a list with INTENSITY + # If FALSE, it returns a list with INTENSITY, MASKS, OUTLIERS + write.csv(data$INTENSITY, "{str(output_path)}") + """ + + try: + subprocess.run( + ["Rscript", "-e", r_command], + capture_output=True, + text=True, + check=True + ) + return { + "command_executed": f"read.celfile('{filename}')", + "status": "Success", + "output_file": str(output_path) + } + except subprocess.CalledProcessError as e: + return { + "error": "R execution failed", + "stderr": e.stderr, + "stdout": e.stdout + } + +@mcp.tool() +def affyio_check_cdf_type( + filename: str +) -> Dict[str, Any]: + """ + Identify the type of an Affymetrix CDF file (e.g., text, binary, gzipped). + + Args: + filename: Path to the CDF file. + """ + file_path = Path(filename) + if not file_path.exists(): + return {"error": f"File not found: {filename}"} + + r_command = f""" + library(affyio) + type <- check.cdf.type("{str(file_path)}") + cat(type) + """ + + try: + result = subprocess.run( + ["Rscript", "-e", r_command], + capture_output=True, + text=True, + check=True + ) + return { + "command_executed": f"check.cdf.type('{filename}')", + "cdf_type": result.stdout.strip(), + "stderr": result.stderr + } + except subprocess.CalledProcessError as e: + return {"error": "R execution failed", "stderr": e.stderr} + +@mcp.tool() +def affyio_read_cdffile_summary( + filename: str +) -> Dict[str, Any]: + """ + Read an Affymetrix CDF file and return a summary of its contents. + Note: Full CDF lists are extremely large; this tool returns structural metadata. + + Args: + filename: Path to the CDF file. + """ + file_path = Path(filename) + if not file_path.exists(): + return {"error": f"File not found: {filename}"} + + r_command = f""" + library(affyio) + library(jsonlite) + cdf_data <- read.cdffile.list("{str(file_path)}") + summary_info <- list( + filename = "{filename}", + num_probesets = length(cdf_data), + probeset_names = head(names(cdf_data), 10) + ) + cat(toJSON(summary_info, auto_unbox = TRUE)) + """ + + try: + result = subprocess.run( + ["Rscript", "-e", r_command], + capture_output=True, + text=True, + check=True + ) + return { + "command_executed": f"read.cdffile.list('{filename}')", + "summary": json.loads(result.stdout), + "stderr": result.stderr + } + except subprocess.CalledProcessError as e: + return {"error": "R execution failed", "stderr": e.stderr} + +@mcp.tool() +def affyio_get_package_version() -> Dict[str, Any]: + """ + Check the installed version of the affyio package and its dependencies. + """ + r_command = """ + library(affyio) + v <- as.character(packageVersion("affyio")) + cat(v) + """ + try: + result = subprocess.run( + ["Rscript", "-e", r_command], + capture_output=True, + text=True, + check=True + ) + return { + "package": "affyio", + "version": result.stdout.strip(), + "r_version": subprocess.run(["Rscript", "--version"], capture_output=True, text=True).stderr.strip() + } + except subprocess.CalledProcessError as e: + return { + "error": "Could not determine package version. Ensure bioconductor-affyio is installed.", + "stderr": e.stderr + } \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-affyio/app/bioconductor-affyio_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-affyio/app/bioconductor-affyio_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..e5070944db2376613a715d207ee0461b226c7a22 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-affyio/app/bioconductor-affyio_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-affyio/app/bioconductor-affyio_server.py') +SERVER_NAME = 'biosci_bioconductor_affyio' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-affyio/app/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-affyio/app/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-affyio/app/requirements.txt @@ -0,0 +1 @@ + diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-affyio/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-affyio/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..ac239ca3a52d2c9c05317d88ee726fcd08573a94 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-affyio/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-bioconductor-affyio: + build: . + image: mcp-bioconductor-affyio:latest + container_name: mcp-bioconductor-affyio + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=bioconductor-affyio + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-affyio/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-affyio/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..486380658759a501811fc16c5f5101304cb08b26 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-affyio/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - bioconductor-affyio + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-affyio/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-affyio/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-affyio/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotate/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotate/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..8df3183e644dd3c5947b4c5585e2c942f6d7c80c --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotate/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install bioconductor-annotate via conda (e.g., from bioconda) +RUN conda install -c bioconda bioconductor-annotate -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY bioconductor-annotate_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/bioconductor-annotate_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/bioconductor-annotate_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotate/app/bioconductor-annotate_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotate/app/bioconductor-annotate_server.py new file mode 100644 index 0000000000000000000000000000000000000000..e8aa22c0b818479e01d8ba4f0ce30f4cb61ba843 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotate/app/bioconductor-annotate_server.py @@ -0,0 +1,141 @@ +import subprocess +import logging +from pathlib import Path +from typing import Optional, List, Dict, Any + +# The mcp.tool decorator is supplied by the MCP framework. +# It is aliased here for clarity and to allow for standalone code analysis. +class mcp: + """A dummy class to represent the MCP decorator for static analysis.""" + @staticmethod + def tool(func): + """A dummy decorator that returns the function unchanged.""" + return func + +@mcp.tool +def rscript( + script_file: Optional[Path] = None, + expressions: Optional[List[str]] = None, + script_args: Optional[List[str]] = None, + verbose: bool = False, + default_packages: Optional[str] = None, + vanilla: bool = False, + save: bool = False, + no_environ: bool = False, + no_site_file: bool = False, + no_init_file: bool = False, + restore: bool = False, +) -> Dict[str, Any]: + """ + Executes an R script or R expressions using the Rscript command-line tool. + + This tool serves as a wrapper for the Rscript interpreter, which is commonly + used to run bioinformatics scripts that rely on R packages from repositories + like CRAN or Bioconductor (e.g., for using bioconductor-annotate). + You must provide either a path to an R script file or a list of R expressions + to execute. + + Args: + script_file: Path to the R script file to be executed. + expressions: A list of R expressions to execute directly. Use this instead of script_file. + script_args: A list of arguments to be passed to the R script itself. + verbose: If True, enables verbose output, printing information on progress. + default_packages: A comma-separated string of package names to be loaded by default. + vanilla: If True, combines --no-save, --no-restore, --no-site-file, + --no-init-file, and --no-environ. This provides a clean session. + If True, the individual flags (save, restore, etc.) are ignored. + save: If True, the workspace will be saved at the end of the session. Ignored if vanilla is True. + no_environ: If True, site and user environment files will not be read. Ignored if vanilla is True. + no_site_file: If True, the site-wide Rprofile will not be read. Ignored if vanilla is True. + no_init_file: If True, the user's R profile will not be read. Ignored if vanilla is True. + restore: If True, previously saved objects will be restored at startup. Ignored if vanilla is True. + + Returns: + A dictionary containing the executed command, stdout, stderr, and a list of output files. + """ + # 1. Input Validation + if not script_file and not expressions: + raise ValueError("Either 'script_file' or 'expressions' must be provided.") + if script_file and expressions: + raise ValueError("Cannot provide both 'script_file' and 'expressions' simultaneously.") + + if script_file: + if not script_file.is_file(): + raise FileNotFoundError(f"The specified script file does not exist: {script_file}") + + # 2. Command Construction + cmd = ["Rscript"] + + if verbose: + cmd.append("--verbose") + + if default_packages: + cmd.append(f"--default-packages={default_packages}") + + if vanilla: + cmd.append("--vanilla") + else: + # These options are processed only if --vanilla is not used + if save: + cmd.append("--save") + if no_environ: + cmd.append("--no-environ") + if no_site_file: + cmd.append("--no-site-file") + if no_init_file: + cmd.append("--no-init-file") + if restore: + cmd.append("--restore") + + # Add script file or expressions to execute + if script_file: + cmd.append(str(script_file)) + elif expressions: + for expr in expressions: + cmd.extend(["-e", expr]) + + # Add trailing arguments for the R script + if script_args: + cmd.extend(script_args) + + command_executed = " ".join(cmd) + logging.info(f"Executing command: {command_executed}") + + # 3. Subprocess Execution and Error Handling + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + ) + except FileNotFoundError: + # This error occurs if 'Rscript' is not in the system's PATH + logging.error("Rscript executable not found.") + return { + "error": "Rscript not found. Please ensure R is installed and in your PATH.", + "command_executed": command_executed, + "stdout": "", + "stderr": "Rscript executable not found.", + "output_files": [] + } + except subprocess.CalledProcessError as e: + # This error occurs if the R script exits with a non-zero status code + logging.error(f"Rscript execution failed with exit code {e.returncode}") + return { + "error": f"Rscript execution failed with exit code {e.returncode}.", + "command_executed": command_executed, + "stdout": e.stdout, + "stderr": e.stderr, + "output_files": [] + } + + # 4. Structured Result Return + # This wrapper cannot reliably determine output files generated by the user's script. + # The user is responsible for knowing and handling the script's output. + return { + "command_executed": command_executed, + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": [] + } \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotate/app/bioconductor-annotate_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotate/app/bioconductor-annotate_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..9e75ef215bafcb160485aeb4bb69c2b3257d2406 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotate/app/bioconductor-annotate_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotate/app/bioconductor-annotate_server.py') +SERVER_NAME = 'biosci_bioconductor_annotate' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotate/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotate/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..5020838deb35bbae2bcb064ef99231a9f153e504 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotate/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-bioconductor-annotate: + build: . + image: mcp-bioconductor-annotate:latest + container_name: mcp-bioconductor-annotate + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=bioconductor-annotate + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotate/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotate/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..ca6f7fedcb6d13738028109983815bb7e6c4b8fd --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotate/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - bioconductor-annotate + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotate/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotate/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotate/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotationdbi/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotationdbi/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..31bb65012357ab749e55a3d2e0a30bbf3fc1c6e2 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotationdbi/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install bioconductor-annotationdbi via conda (e.g., from bioconda) +RUN conda install -c bioconda bioconductor-annotationdbi -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY bioconductor-annotationdbi_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/bioconductor-annotationdbi_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/bioconductor-annotationdbi_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotationdbi/app/bioconductor-annotationdbi_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotationdbi/app/bioconductor-annotationdbi_server.py new file mode 100644 index 0000000000000000000000000000000000000000..6ae86efcdbf2219ae36a88dbaccb8032654aa3f2 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotationdbi/app/bioconductor-annotationdbi_server.py @@ -0,0 +1,456 @@ +import subprocess +import tempfile +from pathlib import Path +from typing import Optional, List + +# MCP decorator is assumed to be defined in the execution environment. +# No import is needed as per the instructions. + +@mcp.tool() +def annotationdbi_columns(db_package: str) -> dict: + """ + Lists all available columns for a given Bioconductor annotation package. + + This tool requires R, Rscript, and the Bioconductor packages 'AnnotationDbi' + and the specified 'db_package' to be installed in the R environment. + + Args: + db_package: The name of the Bioconductor annotation package (e.g., "org.Hs.eg.db"). + + Returns: + A dictionary containing the command executed and the standard output with the column names. + """ + if not db_package: + raise ValueError("db_package must be a non-empty string.") + + r_script_content = f""" + suppressPackageStartupMessages(library(AnnotationDbi)) + + db_package_name <- "{db_package}" + + if (!requireNamespace(db_package_name, quietly = TRUE)) {{ + stop(paste("Annotation package '", db_package_name, "' is not installed. Please install it from Bioconductor."), call. = FALSE) + }} + db <- get(db_package_name) + + tryCatch({{ + result_data <- AnnotationDbi::columns(db) + cat(result_data, sep = "\\n") + }}, error = function(e) {{ + stop(paste("AnnotationDbi::columns failed:", e$message), call. = FALSE) + }}) + """ + + with tempfile.NamedTemporaryFile(mode='w', suffix=".R", delete=False, encoding='utf-8') as tmp_script: + tmp_script.write(r_script_content) + script_path = tmp_script.name + + cmd = ["Rscript", script_path] + command_executed = f"Rscript {script_path}" + + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + encoding='utf-8' + ) + return { + "command_executed": command_executed, + "stdout": result.stdout, + "stderr": result.stderr, + } + except subprocess.CalledProcessError as e: + return { + "command_executed": command_executed, + "stdout": e.stdout, + "stderr": e.stderr, + "error": f"R script execution failed with exit code {e.returncode}" + } + except FileNotFoundError: + return { + "command_executed": command_executed, + "stdout": "", + "stderr": "Error: 'Rscript' command not found. Please ensure R is installed and 'Rscript' is in your system's PATH.", + "error": "Dependency not found" + } + finally: + Path(script_path).unlink() + +@mcp.tool() +def annotationdbi_keytypes(db_package: str) -> dict: + """ + Lists all available keytypes for a given Bioconductor annotation package. + + This tool requires R, Rscript, and the Bioconductor packages 'AnnotationDbi' + and the specified 'db_package' to be installed in the R environment. + + Args: + db_package: The name of the Bioconductor annotation package (e.g., "org.Hs.eg.db"). + + Returns: + A dictionary containing the command executed and the standard output with the keytype names. + """ + if not db_package: + raise ValueError("db_package must be a non-empty string.") + + r_script_content = f""" + suppressPackageStartupMessages(library(AnnotationDbi)) + + db_package_name <- "{db_package}" + + if (!requireNamespace(db_package_name, quietly = TRUE)) {{ + stop(paste("Annotation package '", db_package_name, "' is not installed. Please install it from Bioconductor."), call. = FALSE) + }} + db <- get(db_package_name) + + tryCatch({{ + result_data <- AnnotationDbi::keytypes(db) + cat(result_data, sep = "\\n") + }}, error = function(e) {{ + stop(paste("AnnotationDbi::keytypes failed:", e$message), call. = FALSE) + }}) + """ + + with tempfile.NamedTemporaryFile(mode='w', suffix=".R", delete=False, encoding='utf-8') as tmp_script: + tmp_script.write(r_script_content) + script_path = tmp_script.name + + cmd = ["Rscript", script_path] + command_executed = f"Rscript {script_path}" + + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + encoding='utf-8' + ) + return { + "command_executed": command_executed, + "stdout": result.stdout, + "stderr": result.stderr, + } + except subprocess.CalledProcessError as e: + return { + "command_executed": command_executed, + "stdout": e.stdout, + "stderr": e.stderr, + "error": f"R script execution failed with exit code {e.returncode}" + } + except FileNotFoundError: + return { + "command_executed": command_executed, + "stdout": "", + "stderr": "Error: 'Rscript' command not found. Please ensure R is installed and 'Rscript' is in your system's PATH.", + "error": "Dependency not found" + } + finally: + Path(script_path).unlink() + +@mcp.tool() +def annotationdbi_keys(db_package: str, keytype: str) -> dict: + """ + Lists all available keys for a given keytype in a Bioconductor annotation package. + + This tool requires R, Rscript, and the Bioconductor packages 'AnnotationDbi' + and the specified 'db_package' to be installed in the R environment. + + Args: + db_package: The name of the Bioconductor annotation package (e.g., "org.Hs.eg.db"). + keytype: The keytype for which to retrieve all available keys (e.g., "ENTREZID"). + + Returns: + A dictionary containing the command executed and the standard output with the keys. + """ + if not db_package: + raise ValueError("db_package must be a non-empty string.") + if not keytype: + raise ValueError("keytype must be a non-empty string.") + + r_script_content = f""" + suppressPackageStartupMessages(library(AnnotationDbi)) + + db_package_name <- "{db_package}" + keytype_str <- "{keytype}" + + if (!requireNamespace(db_package_name, quietly = TRUE)) {{ + stop(paste("Annotation package '", db_package_name, "' is not installed. Please install it from Bioconductor."), call. = FALSE) + }} + db <- get(db_package_name) + + tryCatch({{ + result_data <- AnnotationDbi::keys(db, keytype = keytype_str) + cat(result_data, sep = "\\n") + }}, error = function(e) {{ + stop(paste("AnnotationDbi::keys failed:", e$message), call. = FALSE) + }}) + """ + + with tempfile.NamedTemporaryFile(mode='w', suffix=".R", delete=False, encoding='utf-8') as tmp_script: + tmp_script.write(r_script_content) + script_path = tmp_script.name + + cmd = ["Rscript", script_path] + command_executed = f"Rscript {script_path}" + + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + encoding='utf-8' + ) + return { + "command_executed": command_executed, + "stdout": result.stdout, + "stderr": result.stderr, + } + except subprocess.CalledProcessError as e: + return { + "command_executed": command_executed, + "stdout": e.stdout, + "stderr": e.stderr, + "error": f"R script execution failed with exit code {e.returncode}" + } + except FileNotFoundError: + return { + "command_executed": command_executed, + "stdout": "", + "stderr": "Error: 'Rscript' command not found. Please ensure R is installed and 'Rscript' is in your system's PATH.", + "error": "Dependency not found" + } + finally: + Path(script_path).unlink() + +@mcp.tool() +def annotationdbi_select( + db_package: str, + keys: str, + columns: str, + keytype: str, + output_file: Path, +) -> dict: + """ + Retrieves data from a Bioconductor annotation package using AnnotationDbi::select. + + This tool requires R, Rscript, and the Bioconductor packages 'AnnotationDbi' + and the specified 'db_package' to be installed in the R environment. + + Args: + db_package: The name of the Bioconductor annotation package (e.g., "org.Hs.eg.db"). + keys: A comma-separated string of keys to query (e.g., "BRCA1,TP53"). + columns: A comma-separated string of columns to retrieve (e.g., "SYMBOL,GENENAME,ENTREZID"). + keytype: The type of the provided keys (e.g., "SYMBOL"). + output_file: The path to save the results as a TSV file. + + Returns: + A dictionary containing the command executed, logs, and the path to the output file. + """ + if not db_package: + raise ValueError("db_package must be a non-empty string.") + if not keys: + raise ValueError("keys must be a non-empty, comma-separated string.") + if not columns: + raise ValueError("columns must be a non-empty, comma-separated string.") + if not keytype: + raise ValueError("keytype must be a non-empty string.") + + output_file.parent.mkdir(parents=True, exist_ok=True) + + r_script_content = f""" + suppressPackageStartupMessages(library(AnnotationDbi)) + + db_package_name <- "{db_package}" + keys_vec <- unlist(strsplit("{keys}", ",")) + columns_vec <- unlist(strsplit("{columns}", ",")) + keytype_str <- "{keytype}" + output_file_path <- "{output_file.resolve()}" + + if (!requireNamespace(db_package_name, quietly = TRUE)) {{ + stop(paste("Annotation package '", db_package_name, "' is not installed. Please install it from Bioconductor."), call. = FALSE) + }} + db <- get(db_package_name) + + tryCatch({{ + results <- AnnotationDbi::select(db, + keys = keys_vec, + columns = columns_vec, + keytype = keytype_str) + + write.table(results, + file = output_file_path, + sep = "\\t", + row.names = FALSE, + col.names = TRUE, + quote = FALSE) + + cat(paste("Successfully wrote", nrow(results), "rows to", basename(output_file_path), "\\n")) + + }}, error = function(e) {{ + stop(paste("AnnotationDbi::select failed:", e$message), call. = FALSE) + }}) + """ + + with tempfile.NamedTemporaryFile(mode='w', suffix=".R", delete=False, encoding='utf-8') as tmp_script: + tmp_script.write(r_script_content) + script_path = tmp_script.name + + cmd = ["Rscript", script_path] + command_executed = f"Rscript {script_path}" + + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + encoding='utf-8' + ) + return { + "command_executed": command_executed, + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": [str(output_file.resolve())] + } + except subprocess.CalledProcessError as e: + return { + "command_executed": command_executed, + "stdout": e.stdout, + "stderr": e.stderr, + "error": f"R script execution failed with exit code {e.returncode}", + "output_files": [] + } + except FileNotFoundError: + return { + "command_executed": command_executed, + "stdout": "", + "stderr": "Error: 'Rscript' command not found. Please ensure R is installed and 'Rscript' is in your system's PATH.", + "error": "Dependency not found", + "output_files": [] + } + finally: + Path(script_path).unlink() + +@mcp.tool() +def annotationdbi_mapids( + db_package: str, + keys: str, + column: str, + keytype: str, + output_file: Path, + multi_vals: str = "first", +) -> dict: + """ + Maps identifiers from one type to another using AnnotationDbi::mapIds. + + This tool requires R, Rscript, and the Bioconductor packages 'AnnotationDbi' + and the specified 'db_package' to be installed in the R environment. + + Args: + db_package: The name of the Bioconductor annotation package (e.g., "org.Hs.eg.db"). + keys: A comma-separated string of keys to query (e.g., "BRCA1,TP53"). + column: The single column (identifier type) to map to (e.g., "ENTREZID"). + keytype: The type of the provided keys (e.g., "SYMBOL"). + output_file: The path to save the mapping results as a TSV file. + multi_vals: How to handle multiple matches. One of "first", "list", "filter", "asNA". + + Returns: + A dictionary containing the command executed, logs, and the path to the output file. + """ + if not db_package: + raise ValueError("db_package must be a non-empty string.") + if not keys: + raise ValueError("keys must be a non-empty, comma-separated string.") + if not column: + raise ValueError("column must be a non-empty string.") + if not keytype: + raise ValueError("keytype must be a non-empty string.") + + valid_multi_vals = ["first", "list", "filter", "asNA", "character"] + if multi_vals not in valid_multi_vals: + raise ValueError(f"multi_vals must be one of {valid_multi_vals}") + + output_file.parent.mkdir(parents=True, exist_ok=True) + + r_script_content = f""" + suppressPackageStartupMessages(library(AnnotationDbi)) + + db_package_name <- "{db_package}" + keys_vec <- unlist(strsplit("{keys}", ",")) + column_str <- "{column}" + keytype_str <- "{keytype}" + multi_vals_str <- "{multi_vals}" + output_file_path <- "{output_file.resolve()}" + + if (!requireNamespace(db_package_name, quietly = TRUE)) {{ + stop(paste("Annotation package '", db_package_name, "' is not installed. Please install it from Bioconductor."), call. = FALSE) + }} + db <- get(db_package_name) + + tryCatch({{ + results_vec <- AnnotationDbi::mapIds(db, + keys = keys_vec, + column = column_str, + keytype = keytype_str, + multiVals = multi_vals_str) + + # Convert named vector to a data frame for saving + results_df <- data.frame(FROM = names(results_vec), TO = I(results_vec), stringsAsFactors = FALSE) + + write.table(results_df, + file = output_file_path, + sep = "\\t", + row.names = FALSE, + col.names = TRUE, + quote = FALSE) + + cat(paste("Successfully wrote", nrow(results_df), "rows to", basename(output_file_path), "\\n")) + + }}, error = function(e) {{ + stop(paste("AnnotationDbi::mapIds failed:", e$message), call. = FALSE) + }}) + """ + + with tempfile.NamedTemporaryFile(mode='w', suffix=".R", delete=False, encoding='utf-8') as tmp_script: + tmp_script.write(r_script_content) + script_path = tmp_script.name + + cmd = ["Rscript", script_path] + command_executed = f"Rscript {script_path}" + + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + encoding='utf-8' + ) + return { + "command_executed": command_executed, + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": [str(output_file.resolve())] + } + except subprocess.CalledProcessError as e: + return { + "command_executed": command_executed, + "stdout": e.stdout, + "stderr": e.stderr, + "error": f"R script execution failed with exit code {e.returncode}", + "output_files": [] + } + except FileNotFoundError: + return { + "command_executed": command_executed, + "stdout": "", + "stderr": "Error: 'Rscript' command not found. Please ensure R is installed and 'Rscript' is in your system's PATH.", + "error": "Dependency not found", + "output_files": [] + } + finally: + Path(script_path).unlink() \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotationdbi/app/bioconductor-annotationdbi_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotationdbi/app/bioconductor-annotationdbi_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..ee8169da2029a5a5a0d643141e5f82570ef9c861 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotationdbi/app/bioconductor-annotationdbi_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotationdbi/app/bioconductor-annotationdbi_server.py') +SERVER_NAME = 'biosci_bioconductor_annotationdbi' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotationdbi/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotationdbi/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..5ffb2fbebfe206e4992e7f807130e3578bf3ea00 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotationdbi/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-bioconductor-annotationdbi: + build: . + image: mcp-bioconductor-annotationdbi:latest + container_name: mcp-bioconductor-annotationdbi + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=bioconductor-annotationdbi + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotationdbi/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotationdbi/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..219d52fcbc8c34ff46e974f7676c137182099e8a --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotationdbi/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - bioconductor-annotationdbi + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotationdbi/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotationdbi/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotationdbi/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocgenerics/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocgenerics/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..787c5a33b775733411e744e8efa96b3656b0a63c --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocgenerics/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - bioconductor-biocgenerics + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocneighbors/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocneighbors/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..4cdc8c7e26e0a235c8ccaaa029b1ea7b48426fe9 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocneighbors/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install bioconductor-biocneighbors via conda (e.g., from bioconda) +RUN conda install -c bioconda bioconductor-biocneighbors -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY bioconductor-biocneighbors_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/bioconductor-biocneighbors_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/bioconductor-biocneighbors_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocneighbors/app/bioconductor-biocneighbors_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocneighbors/app/bioconductor-biocneighbors_server.py new file mode 100644 index 0000000000000000000000000000000000000000..887469d262cf6d0f608fa3ffa80c1d1d16565296 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocneighbors/app/bioconductor-biocneighbors_server.py @@ -0,0 +1,155 @@ +import subprocess +from pathlib import Path +from typing import List, Optional, Union + +@mcp.tool() +def run_rscript( + r_script_file: Optional[Path] = None, + r_expressions: Optional[List[str]] = None, + additional_args: Optional[List[str]] = None, + verbose: bool = False, + default_packages: Optional[str] = None, + save_workspace: bool = False, + no_environ: bool = False, + no_site_file: bool = False, + no_init_file: bool = False, + restore_workspace: bool = False, + vanilla: bool = False, + print_help: bool = False, + print_version: bool = False, +) -> dict: + """ + Executes an R script file or R expressions using the Rscript command-line utility. + + This tool provides a comprehensive interface to the Rscript utility, enabling users + to run R code directly from the command line. It supports two primary modes of + operation: executing a specified R script file or running one or more R expressions + passed as strings. Additionally, it allows for the configuration of various R session + options, such as default package loading, workspace saving/restoring behavior, + and environment file handling. + + Args: + r_script_file: Path to an R script file (.R file) to be executed. This parameter + is mutually exclusive with `r_expressions`. If provided, the file + must exist. + r_expressions: A list of R code strings, where each string represents an + expression to be executed. Each expression will be passed to + Rscript using a separate '-e' flag. This parameter is mutually + exclusive with `r_script_file`. + additional_args: A list of strings representing extra arguments to be passed + to the R script or expressions being executed. These arguments + are typically accessible within the R script via `commandArgs()`. + verbose: If True, Rscript will print information on its progress during execution. + default_packages: A comma-separated string of R package names (e.g., "stats,utils") + that R should load by default. Alternatively, "NULL" can be + specified to prevent any default packages from loading. + save_workspace: If True, the R workspace will be saved at the end of the session. + no_environ: If True, R will not read the site-wide and user-specific environment + files (.Renviron). + no_site_file: If True, R will not read the site-wide R profile file (Rprofile.site). + no_init_file: If True, R will not read the user's R profile file (.Rprofile). + restore_workspace: If True, R will attempt to restore previously saved objects + from a workspace file (.RData) at startup. + vanilla: If True, Rscript will combine the effects of --no-save, --no-restore, + --no-site-file, --no-init-file, and --no-environ, providing a clean + R session. + print_help: If True, Rscript will print its usage information and exit. When this + is True, other execution options are typically ignored by Rscript. + print_version: If True, Rscript will print its version information and exit. When + this is True, other execution options are typically ignored by Rscript. + + Returns: + A dictionary containing the command executed, standard output, standard error, + and a list of any output files generated (typically empty for Rscript itself, + as output files are usually created by the R script being run). + Returns structured error information if the Rscript command fails or encounters + an execution error. + """ + command: List[str] = ["Rscript"] + output_files: List[Path] = [] + + # Handle --help and --version flags first, as they typically cause Rscript to exit immediately. + if print_help: + command.append("--help") + elif print_version: + command.append("--version") + else: + # Validate mutually exclusive input modes: r_script_file vs. r_expressions + if r_script_file and r_expressions: + raise ValueError("Cannot specify both 'r_script_file' and 'r_expressions'. Please choose one mode of execution.") + if not r_script_file and not r_expressions: + raise ValueError("Either 'r_script_file' or 'r_expressions' must be provided to execute R code.") + + # Add the R script file or expressions to the command + if r_script_file: + if not r_script_file.is_file(): + raise FileNotFoundError(f"R script file not found at the specified path: {r_script_file}") + command.append(str(r_script_file)) + elif r_expressions: + for expr in r_expressions: + command.extend(["-e", expr]) + + # Add general Rscript options + if verbose: + command.append("--verbose") + if default_packages is not None: + command.append(f"--default-packages={default_packages}") + + # Add R session options + if save_workspace: + command.append("--save") + if no_environ: + command.append("--no-environ") + if no_site_file: + command.append("--no-site-file") + if no_init_file: + command.append("--no-init-file") + if restore_workspace: + command.append("--restore") + if vanilla: + command.append("--vanilla") + + # Add any additional arguments to be passed to the R script + if additional_args: + command.extend(additional_args) + + try: + # Execute the Rscript command + process = subprocess.run( + command, + check=True, # Raise CalledProcessError for non-zero exit codes + capture_output=True, # Capture stdout and stderr + text=True, # Decode stdout and stderr as text + encoding='utf-8' # Specify encoding for consistent text handling + ) + + return { + "command_executed": " ".join(command), + "stdout": process.stdout, + "stderr": process.stderr, + "output_files": output_files, + } + except FileNotFoundError: + # Handle case where 'Rscript' command itself is not found in PATH + return { + "command_executed": " ".join(command), + "stdout": "", + "stderr": "Error: 'Rscript' command not found. Please ensure R is installed and accessible in your system's PATH.", + "output_files": [], + } + except subprocess.CalledProcessError as e: + # Handle errors reported by Rscript (non-zero exit code) + return { + "command_executed": " ".join(command), + "stdout": e.stdout, + "stderr": e.stderr, + "output_files": [], + } + except Exception as e: + # Catch any other unexpected errors during execution + return { + "command_executed": " ".join(command), + "stdout": "", + "stderr": f"An unexpected error occurred during Rscript execution: {str(e)}", + "output_files": [], + } \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocneighbors/app/bioconductor-biocneighbors_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocneighbors/app/bioconductor-biocneighbors_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..9d5352a5c422b42808c38fcc1f414dacc6784f3a --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocneighbors/app/bioconductor-biocneighbors_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocneighbors/app/bioconductor-biocneighbors_server.py') +SERVER_NAME = 'biosci_bioconductor_biocneighbors' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocneighbors/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocneighbors/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..2a76ad0e73e8868ef81968583d407d15c3dcf99c --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocneighbors/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-bioconductor-biocneighbors: + build: . + image: mcp-bioconductor-biocneighbors:latest + container_name: mcp-bioconductor-biocneighbors + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=bioconductor-biocneighbors + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocneighbors/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocneighbors/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..ca4a426d4d1955490a5931118107ef1e6defbf17 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocneighbors/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - bioconductor-biocneighbors + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocneighbors/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocneighbors/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocneighbors/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocparallel/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocparallel/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..3889c91481bf1407e096bbf1fe1a4c95a424ee92 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocparallel/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install bioconductor-biocparallel via conda (e.g., from bioconda) +RUN conda install -c bioconda bioconductor-biocparallel -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY bioconductor-biocparallel_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/bioconductor-biocparallel_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/bioconductor-biocparallel_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocparallel/app/bioconductor-biocparallel_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocparallel/app/bioconductor-biocparallel_server.py new file mode 100644 index 0000000000000000000000000000000000000000..cf8902bf007e8eb9d0e9f394c52e4f4df8a3abdb --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocparallel/app/bioconductor-biocparallel_server.py @@ -0,0 +1,265 @@ +import subprocess +import tempfile +import os +from pathlib import Path +from typing import Optional, List, Literal, Union + +@mcp.tool() +def bplapply( + x_expr: str, + fun_expr: str, + workers: int = 2, + backend_type: Literal["MulticoreParam", "SnowParam", "SerialParam"] = "MulticoreParam", + tasks: int = 0, + stop_on_error: bool = True, + input_rds: Optional[str] = None, + output_rds: Optional[str] = None, +): + """ + Parallel version of lapply using BiocParallel. + + Args: + x_expr: R expression representing the list or vector to iterate over (e.g., '1:100'). + fun_expr: R expression for the function to apply (e.g., 'function(i) { Sys.sleep(0.1); i^2 }'). + workers: Number of parallel workers. + backend_type: The BiocParallel backend to use. + tasks: Number of tasks (0 for default). + stop_on_error: Whether to stop execution if an error occurs in a worker. + input_rds: Optional path to an RDS file containing the input data. If provided, x_expr is ignored. + output_rds: Optional path to save the result as an RDS file. + """ + if workers < 1: + workers = 1 + + # Construct R script + r_script = [ + "library(BiocParallel)", + f"param <- {backend_type}(workers = {workers}, tasks = {tasks}, stop.on.error = {str(stop_on_error).upper()})" + ] + + if input_rds: + input_path = Path(input_rds) + if not input_path.exists(): + return {"error": f"Input RDS file not found: {input_rds}"} + r_script.append(f"X <- readRDS('{input_path.absolute()}')") + else: + r_script.append(f"X <- {x_expr}") + + r_script.append(f"FUN <- {fun_expr}") + r_script.append("res <- bplapply(X, FUN, BPPARAM = param)") + + if output_rds: + output_path = Path(output_rds) + r_script.append(f"saveRDS(res, '{output_path.absolute()}')") + else: + r_script.append("print(res)") + + return _run_r_command("\n".join(r_script)) + +@mcp.tool() +def bpmapply( + fun_expr: str, + dots_expr: str, + workers: int = 2, + backend_type: Literal["MulticoreParam", "SnowParam", "SerialParam"] = "MulticoreParam", + more_args_expr: str = "list()", + input_rds: Optional[str] = None, +): + """ + Parallel version of mapply (multivariate apply) using BiocParallel. + + Args: + fun_expr: R expression for the function to apply. + dots_expr: R expression for the arguments to pass to FUN (e.g., 'list(1:3, 4:6)'). + workers: Number of parallel workers. + backend_type: The BiocParallel backend to use. + more_args_expr: R expression for additional arguments to FUN. + input_rds: Optional path to an RDS file containing a list of arguments. + """ + r_script = [ + "library(BiocParallel)", + f"param <- {backend_type}(workers = {workers})" + ] + + if input_rds: + input_path = Path(input_rds) + if not input_path.exists(): + return {"error": f"Input RDS file not found: {input_rds}"} + r_script.append(f"args_list <- readRDS('{input_path.absolute()}')") + r_script.append(f"res <- do.call(bpmapply, c(list(FUN = {fun_expr}, MoreArgs = {more_args_expr}, BPPARAM = param), args_list))") + else: + r_script.append(f"res <- bpmapply({fun_expr}, {dots_expr}, MoreArgs = {more_args_expr}, BPPARAM = param)") + + r_script.append("print(res)") + return _run_r_command("\n".join(r_script)) + +@mcp.tool() +def bpvec( + x_expr: str, + fun_expr: str, + workers: int = 2, + backend_type: Literal["MulticoreParam", "SnowParam", "SerialParam"] = "MulticoreParam", + input_rds: Optional[str] = None, +): + """ + Parallel version of vec (vectorized apply) using BiocParallel. + Useful when the function can handle chunks of the vector at once. + """ + r_script = [ + "library(BiocParallel)", + f"param <- {backend_type}(workers = {workers})" + ] + + if input_rds: + input_path = Path(input_rds) + if not input_path.exists(): + return {"error": f"Input RDS file not found: {input_rds}"} + r_script.append(f"X <- readRDS('{input_path.absolute()}')") + else: + r_script.append(f"X <- {x_expr}") + + r_script.append(f"res <- bpvec(X, {fun_expr}, BPPARAM = param)") + r_script.append("print(res)") + return _run_r_command("\n".join(r_script)) + +@mcp.tool() +def bpaggregate( + x_expr: str, + by_expr: str, + fun_expr: str, + workers: int = 2, + backend_type: Literal["MulticoreParam", "SnowParam", "SerialParam"] = "MulticoreParam", +): + """ + Parallel version of aggregate using BiocParallel. + + Args: + x_expr: R expression for the data object. + by_expr: R expression for the grouping elements. + fun_expr: R expression for the function to apply. + workers: Number of workers. + backend_type: Parallel backend. + """ + r_script = [ + "library(BiocParallel)", + f"param <- {backend_type}(workers = {workers})", + f"res <- bpaggregate({x_expr}, {by_expr}, {fun_expr}, BPPARAM = param)", + "print(res)" + ] + return _run_r_command("\n".join(r_script)) + +@mcp.tool() +def bpiterate( + iter_expr: str, + fun_expr: str, + workers: int = 2, + backend_type: Literal["SnowParam", "MulticoreParam"] = "SnowParam", + reduce_expr: Optional[str] = None, + init_expr: Optional[str] = None, +): + """ + Parallel iteration over an indeterminate number of elements using an iterator. + + Args: + iter_expr: R expression for the iterator function (should return NULL when finished). + fun_expr: R expression for the function to apply to each element. + workers: Number of workers. + backend_type: Parallel backend. + reduce_expr: Optional R expression for a reduction function. + init_expr: Optional R expression for the initial value for reduction. + """ + r_script = [ + "library(BiocParallel)", + f"param <- {backend_type}(workers = {workers})", + f"ITER <- {iter_expr}", + f"FUN <- {fun_expr}" + ] + + cmd = "res <- bpiterate(ITER, FUN" + if reduce_expr: + cmd += f", REDUCE = {reduce_expr}" + if init_expr: + cmd += f", init = {init_expr}" + cmd += ", BPPARAM = param)" + + r_script.append(cmd) + r_script.append("print(res)") + + return _run_r_command("\n".join(r_script)) + +@mcp.tool() +def bpworkers( + backend_type: Literal["MulticoreParam", "SnowParam", "SerialParam"] = "MulticoreParam" +): + """ + Query the number of available workers for a specific BiocParallel backend. + """ + r_script = [ + "library(BiocParallel)", + f"param <- {backend_type}()", + "cat(bpworkers(param))" + ] + return _run_r_command("\n".join(r_script)) + +@mcp.tool() +def bpvalidate( + code_snippet: str +): + """ + Validates if a specific R code snippet can be parallelized without errors. + Checks for global variable availability and serialization issues. + """ + r_script = [ + "library(BiocParallel)", + "tryCatch({", + f" expr <- quote({{ {code_snippet} }})", + " bpvalidate(expr)", + " cat('Validation successful')", + "}, error = function(e) {", + " cat('Validation failed:', e$message)", + "})" + ] + return _run_r_command("\n".join(r_script)) + +def _run_r_command(r_code: str): + """ + Helper function to execute R code via Rscript. + """ + with tempfile.NamedTemporaryFile(mode='w', suffix='.R', delete=False) as tmp: + tmp.write(r_code) + tmp_path = tmp.name + + try: + # Check if Rscript is available + subprocess.run(["Rscript", "--version"], capture_output=True, check=True) + + # Execute the script + result = subprocess.run( + ["Rscript", tmp_path], + capture_output=True, + text=True, + check=True + ) + + return { + "command_executed": f"Rscript {tmp_path}", + "stdout": result.stdout, + "stderr": result.stderr, + "status": "success" + } + except subprocess.CalledProcessError as e: + return { + "command_executed": f"Rscript {tmp_path}", + "stdout": e.stdout, + "stderr": e.stderr, + "status": "error", + "error_message": str(e) + } + except FileNotFoundError: + return { + "status": "error", + "error_message": "Rscript not found. Please ensure R is installed and in your PATH." + } + finally: + if os.path.exists(tmp_path): + os.remove(tmp_path) \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocparallel/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocparallel/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..c703a49304f38194f6f715e8d6331b09c68f0efe --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocparallel/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-bioconductor-biocparallel: + build: . + image: mcp-bioconductor-biocparallel:latest + container_name: mcp-bioconductor-biocparallel + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=bioconductor-biocparallel + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocparallel/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocparallel/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..9eff9f9d36cb8cda31d024a072cd5d4682ce6c01 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocparallel/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - bioconductor-biocparallel + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocparallel/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocparallel/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocparallel/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocsingular/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocsingular/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..dc043c8fcb94e3e8d18677417f0b4e0922ffc3f6 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocsingular/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install bioconductor-biocsingular via conda (e.g., from bioconda) +RUN conda install -c bioconda bioconductor-biocsingular -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY bioconductor-biocsingular_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/bioconductor-biocsingular_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/bioconductor-biocsingular_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocsingular/app/bioconductor-biocsingular_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocsingular/app/bioconductor-biocsingular_server.py new file mode 100644 index 0000000000000000000000000000000000000000..90c67d690984693cf5c0042bff7c64d944b44ab3 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocsingular/app/bioconductor-biocsingular_server.py @@ -0,0 +1,216 @@ +import subprocess +import os +from pathlib import Path +from typing import Optional, List, Dict, Any + +@mcp.tool() +def biocsingular_run_svd( + input_path: str, + output_prefix: str, + k: int = 5, + nu: int = 5, + nv: int = 5, + algorithm: str = "Irlba", + center: bool = True, + scale: bool = False, + deferred: bool = False, +) -> Dict[str, Any]: + """ + Perform Singular Value Decomposition (SVD) on a matrix using BiocSingular. + Supports various algorithms including Exact, Irlba, and Random SVD. + + Args: + input_path: Path to the input matrix file (CSV, TSV, or RDS format). + output_prefix: Prefix for the output files (will create .rds and .csv files). + k: Number of singular values to compute. + nu: Number of left singular vectors to compute. + nv: Number of right singular vectors to compute. + algorithm: SVD algorithm to use ('Exact', 'Irlba', 'Random', 'FastDot'). + center: Whether to center the columns of the matrix. + scale: Whether to scale the columns of the matrix. + deferred: Whether to use deferred centering and scaling (memory efficient). + """ + input_file = Path(input_path) + if not input_file.exists(): + return {"error": f"Input file not found: {input_path}"} + + # Validate algorithm + valid_algos = ["Exact", "Irlba", "Random", "FastDot"] + if algorithm not in valid_algos: + return {"error": f"Invalid algorithm. Must be one of: {', '.join(valid_algos)}"} + + # Construct R script + r_script = f""" + library(BiocSingular) + + # Load data + ext <- tolower(tools::file_ext("{input_path}")) + if (ext == "rds") {{ + mat <- readRDS("{input_path}") + }} else if (ext == "csv") {{ + mat <- as.matrix(read.csv("{input_path}", row.names=1)) + }} else {{ + mat <- as.matrix(read.table("{input_path}", sep="\\t", header=TRUE, row.names=1)) + }} + + # Set parameter object + param <- {algorithm}Param(deferred = {"TRUE" if deferred else "FALSE"}) + + # Run SVD + res <- runSVD( + mat, + k = {k}, + nu = {nu}, + nv = {nv}, + BSPARAM = param, + center = {"TRUE" if center else "FALSE"}, + scale = {"TRUE" if scale else "FALSE"} + ) + + # Save results + saveRDS(res, "{output_prefix}_svd.rds") + write.csv(res$u, "{output_prefix}_u.csv") + write.csv(res$v, "{output_prefix}_v.csv") + write.csv(data.frame(d=res$d), "{output_prefix}_d.csv") + """ + + try: + result = subprocess.run( + ["Rscript", "-e", r_script], + capture_output=True, + text=True, + check=True + ) + + output_files = [ + f"{output_prefix}_svd.rds", + f"{output_prefix}_u.csv", + f"{output_prefix}_v.csv", + f"{output_prefix}_d.csv" + ] + + return { + "command_executed": f"BiocSingular::runSVD via Rscript", + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": [str(Path(f).absolute()) for f in output_files if Path(f).exists()] + } + except subprocess.CalledProcessError as e: + return { + "error": "R execution failed", + "stdout": e.stdout, + "stderr": e.stderr + } + +@mcp.tool() +def biocsingular_run_pca( + input_path: str, + output_prefix: str, + rank: int = 5, + algorithm: str = "Irlba", + center: bool = True, + scale: bool = False, + deferred: bool = False, +) -> Dict[str, Any]: + """ + Perform Principal Component Analysis (PCA) on a matrix using BiocSingular. + Optimized for large-scale genomic data. + + Args: + input_path: Path to the input matrix file (CSV, TSV, or RDS format). + output_prefix: Prefix for the output files. + rank: Number of principal components to compute. + algorithm: PCA algorithm to use ('Exact', 'Irlba', 'Random', 'FastDot'). + center: Whether to center the columns. + scale: Whether to scale the columns. + deferred: Whether to use deferred centering and scaling. + """ + input_file = Path(input_path) + if not input_file.exists(): + return {"error": f"Input file not found: {input_path}"} + + valid_algos = ["Exact", "Irlba", "Random", "FastDot"] + if algorithm not in valid_algos: + return {"error": f"Invalid algorithm. Must be one of: {', '.join(valid_algos)}"} + + r_script = f""" + library(BiocSingular) + + # Load data + ext <- tolower(tools::file_ext("{input_path}")) + if (ext == "rds") {{ + mat <- readRDS("{input_path}") + }} else if (ext == "csv") {{ + mat <- as.matrix(read.csv("{input_path}", row.names=1)) + }} else {{ + mat <- as.matrix(read.table("{input_path}", sep="\\t", header=TRUE, row.names=1)) + }} + + # Set parameter object + param <- {algorithm}Param(deferred = {"TRUE" if deferred else "FALSE"}) + + # Run PCA + res <- runPCA( + mat, + rank = {rank}, + BSPARAM = param, + center = {"TRUE" if center else "FALSE"}, + scale = {"TRUE" if scale else "FALSE"} + ) + + # Save results + saveRDS(res, "{output_prefix}_pca.rds") + write.csv(res$x, "{output_prefix}_pcs.csv") + write.csv(res$rotation, "{output_prefix}_loadings.csv") + """ + + try: + result = subprocess.run( + ["Rscript", "-e", r_script], + capture_output=True, + text=True, + check=True + ) + + output_files = [ + f"{output_prefix}_pca.rds", + f"{output_prefix}_pcs.csv", + f"{output_prefix}_loadings.csv" + ] + + return { + "command_executed": f"BiocSingular::runPCA via Rscript", + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": [str(Path(f).absolute()) for f in output_files if Path(f).exists()] + } + except subprocess.CalledProcessError as e: + return { + "error": "R execution failed", + "stdout": e.stdout, + "stderr": e.stderr + } + +@mcp.tool() +def biocsingular_get_info() -> Dict[str, Any]: + """ + Check if BiocSingular is installed and return version information. + """ + r_script = "library(BiocSingular); cat(as.character(packageVersion('BiocSingular')))" + + try: + result = subprocess.run( + ["Rscript", "-e", r_script], + capture_output=True, + text=True, + check=True + ) + return { + "biocsingular_version": result.stdout.strip(), + "status": "installed" + } + except subprocess.CalledProcessError: + return { + "status": "not_found", + "error": "BiocSingular is not installed in the R environment." + } \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocsingular/app/bioconductor-biocsingular_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocsingular/app/bioconductor-biocsingular_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..afb1aaaaf718c06e2b84de3a05ff539382b51c2d --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocsingular/app/bioconductor-biocsingular_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocsingular/app/bioconductor-biocsingular_server.py') +SERVER_NAME = 'biosci_bioconductor_biocsingular' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocsingular/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocsingular/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..291654c99584d5dc3b38c51c7ad55775aac18c3a --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocsingular/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-bioconductor-biocsingular: + build: . + image: mcp-bioconductor-biocsingular:latest + container_name: mcp-bioconductor-biocsingular + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=bioconductor-biocsingular + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocsingular/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocsingular/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..0df4768f7fb4bd8ff66c5c7dee9e78602b0872f0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocsingular/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - bioconductor-biocsingular + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocsingular/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocsingular/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocsingular/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biostrings/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biostrings/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..04502dc2af170c29e07379c364d485a2b0cea7b8 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biostrings/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install bioconductor-biostrings via conda (e.g., from bioconda) +RUN conda install -c bioconda bioconductor-biostrings -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY bioconductor-biostrings_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/bioconductor-biostrings_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/bioconductor-biostrings_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biostrings/app/bioconductor-biostrings_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biostrings/app/bioconductor-biostrings_server.py new file mode 100644 index 0000000000000000000000000000000000000000..244c611111dc935cf10e298964e791a667a42b30 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biostrings/app/bioconductor-biostrings_server.py @@ -0,0 +1,136 @@ +import subprocess +import logging +from pathlib import Path +from typing import Optional, List, Dict, Any + +# Mock the decorator for standalone execution +class mcp: + @staticmethod + def tool(): + def decorator(func): + return func + return decorator + +@mcp.tool() +def rscript( + script_file: Optional[Path] = None, + expressions: Optional[List[str]] = None, + script_args: Optional[List[str]] = None, + verbose: bool = False, + default_packages: Optional[str] = None, + vanilla: bool = False, + save: bool = False, + no_environ: bool = False, + no_site_file: bool = False, + no_init_file: bool = False, + restore: bool = False, +) -> Dict[str, Any]: + """ + Executes an R script or R expressions using the Rscript command-line tool. + + This tool serves as a wrapper for Rscript, allowing for the execution of R code + from a file or directly from string expressions. It mirrors the functionality + provided by `Rscript --help`. + + Args: + script_file: Path to the R script file to be executed. Mutually exclusive with 'expressions'. + expressions: A list of R expressions to be executed. Mutually exclusive with 'script_file'. + script_args: A list of arguments to be passed to the R script itself. + verbose: If True, enables verbose output, printing information on progress. + default_packages: A comma-separated string of package names to be loaded by default. + vanilla: If True, combines --no-save, --no-restore, --no-site-file, --no-init-file, and --no-environ. + If set, it overrides the individual flags (save, restore, etc.). + save: If True, the workspace is saved at the end of the session. Ignored if 'vanilla' is True. + no_environ: If True, site and user environment files are not read. Ignored if 'vanilla' is True. + no_site_file: If True, the site-wide Rprofile is not read. Ignored if 'vanilla' is True. + no_init_file: If True, the user's R profile is not read. Ignored if 'vanilla' is True. + restore: If True, previously saved objects are restored at startup. Ignored if 'vanilla' is True. + + Returns: + A dictionary containing the executed command, stdout, stderr, and a list of output files (always empty). + """ + # 1. Input Validation + if not script_file and not expressions: + raise ValueError("Either 'script_file' or 'expressions' must be provided.") + if script_file and expressions: + raise ValueError("'script_file' and 'expressions' are mutually exclusive and cannot be used together.") + if script_file and not script_file.is_file(): + raise FileNotFoundError(f"The specified script file does not exist: {script_file}") + if expressions and not expressions: + raise ValueError("'expressions' list cannot be empty if provided.") + + # 2. Command Construction + cmd = ["Rscript"] + + if verbose: + cmd.append("--verbose") + + if default_packages: + cmd.extend(["--default-packages", default_packages]) + + if vanilla: + cmd.append("--vanilla") + else: + # These options are combined and handled by the --vanilla flag in Rscript + if save: + cmd.append("--save") + if no_environ: + cmd.append("--no-environ") + if no_site_file: + cmd.append("--no-site-file") + if no_init_file: + cmd.append("--no-init-file") + if restore: + cmd.append("--restore") + + # Add expressions or script file to the command + if expressions: + for expr in expressions: + cmd.extend(["-e", expr]) + elif script_file: + cmd.append(str(script_file)) + + # Add arguments for the R script itself + if script_args: + cmd.extend(script_args) + + command_str = " ".join(cmd) + logging.info(f"Executing command: {command_str}") + + # 3. Subprocess Execution and Error Handling + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + ) + stdout = result.stdout + stderr = result.stderr + except FileNotFoundError: + # This error occurs if 'Rscript' is not in the system's PATH + return { + "command_executed": command_str, + "stdout": "", + "stderr": "Error: 'Rscript' command not found. Please ensure R is installed and accessible in your system's PATH.", + "output_files": [] + } + except subprocess.CalledProcessError as e: + # This error occurs if the R script itself fails (non-zero exit code) + logging.error(f"Rscript execution failed with return code {e.returncode}") + return { + "command_executed": command_str, + "stdout": e.stdout, + "stderr": e.stderr, + "output_files": [] + } + + # 4. Structured Result Return + # Rscript itself does not have a dedicated output file parameter. Any files + # created are determined by the R code within the script. + return { + "command_executed": command_str, + "stdout": stdout, + "stderr": stderr, + "output_files": [] + } \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biostrings/app/bioconductor-biostrings_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biostrings/app/bioconductor-biostrings_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..71d9091746b506f4a3e3901f281dfce4854f2430 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biostrings/app/bioconductor-biostrings_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biostrings/app/bioconductor-biostrings_server.py') +SERVER_NAME = 'biosci_bioconductor_biostrings' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biostrings/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biostrings/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..04cc0ec4df0b6b32962f9077038c73df1dbbfe47 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biostrings/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-bioconductor-biostrings: + build: . + image: mcp-bioconductor-biostrings:latest + container_name: mcp-bioconductor-biostrings + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=bioconductor-biostrings + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biostrings/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biostrings/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..45c3e252d78ba0fbedb6d8c87e58e82896f73d44 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biostrings/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - bioconductor-biostrings + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biostrings/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biostrings/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biostrings/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-bsgenome/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-bsgenome/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..e92d90bc32975c5c742f867f85094b60f17d393d --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-bsgenome/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install bioconductor-bsgenome via conda (e.g., from bioconda) +RUN conda install -c bioconda bioconductor-bsgenome -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY app/bioconductor-bsgenome_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/bioconductor-bsgenome_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/bioconductor-bsgenome_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-bsgenome/app/bioconductor-bsgenome_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-bsgenome/app/bioconductor-bsgenome_server.py new file mode 100644 index 0000000000000000000000000000000000000000..588b7a281f58ec1138351f0da97d519f7db6badf --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-bsgenome/app/bioconductor-bsgenome_server.py @@ -0,0 +1,204 @@ +import subprocess +import tempfile +import shutil +import re +from pathlib import Path +from typing import Optional, List + +# This is a placeholder for the actual decorator. +# In a real MCP environment, you would use `@mcp.tool()`. +def mcp_tool_placeholder(*args, **kwargs): + def decorator(func): + return func + return decorator + +@mcp_tool_placeholder() +def forge_bsgenome_data_pkg( + organism: str, + common_name: str, + organism_abbreviation: str, + provider: str, + provider_version: str, + release_date: str, + package_version: str, + author: str, + maintainer: str, + seqs_srcdir: Path, + output_pkg_path: Path, + circ_seqs: Optional[List[str]] = None, + seqfiles_prefix: Optional[str] = None, + seqfiles_suffix: Optional[str] = None, + license_str: str = "Artistic-2.0", + title: Optional[str] = None, + description: Optional[str] = None, + organism_biocview: Optional[str] = None, +) -> dict: + """ + Creates a Bioconductor BSgenome data package from a set of FASTA files. + + This tool wraps the `forgeBSgenomeDataPkg` function from the R/Bioconductor + BSgenome package. It automates the creation of the necessary seed file and + executes an R script to build the package source directory, which is then + returned as a gzipped tarball. + + Args: + organism: Full organism name (e.g., "Homo sapiens"). + common_name: Common name for the organism (e.g., "Human"). + organism_abbreviation: Abbreviation for the organism, used in package naming (e.g., "Hsapiens"). + provider: Source of the genome data (e.g., "UCSC"). + provider_version: Version or build of the genome from the provider (e.g., "hg38"). + release_date: Release date of the genome build (e.g., "Dec. 2013"). + package_version: Version for the new BSgenome package, in X.Y.Z format (e.g., "1.0.0"). + author: The author of this BSgenome package. + maintainer: The maintainer of the package, including email (e.g., "Your Name "). + seqs_srcdir: Input directory containing the genome sequence files (e.g., FASTA files). + output_pkg_path: Path to save the final gzipped tarball of the package source (e.g., 'MyPackage.tar.gz'). + circ_seqs: Optional list of sequence names that are circular (e.g., ["chrM"]). + seqfiles_prefix: Optional prefix for the sequence files within `seqs_srcdir`. + seqfiles_suffix: Optional suffix for the sequence files (e.g., ".fa", ".fasta"). + license_str: The license for the generated package. + title: Optional title for the package. A default will be generated if not provided. + description: Optional description for the package. A default will be generated if not provided. + organism_biocview: Optional Bioconductor view term for the organism (e.g., "Homo_sapiens"). + + Returns: + A dictionary containing the execution details and path to the output file. + """ + # 1. Input Validation + if not seqs_srcdir.is_dir(): + raise ValueError(f"Input directory '{seqs_srcdir}' does not exist or is not a directory.") + if not re.match(r"^\d+\.\d+\.\d+$", package_version): + raise ValueError(f"Package version '{package_version}' is not in X.Y.Z format.") + for name_part in [organism_abbreviation, provider]: + if not name_part.isalnum(): + raise ValueError(f"Package name component '{name_part}' contains invalid characters. Use only alphanumerics.") + if not output_pkg_path.parent.exists(): + output_pkg_path.parent.mkdir(parents=True, exist_ok=True) + + # 2. Generate derived values + sanitized_provider_version = re.sub(r'[^a-zA-Z0-9.]', '', provider_version) + package_name = f"BSgenome.{organism_abbreviation}.{provider}.{sanitized_provider_version}" + bsgenome_objname = organism_abbreviation + + if title is None: + title = f"Full genome sequences for {organism} ({provider} version {provider_version})" + if description is None: + description = ( + f"Full genome sequences for {organism} ({common_name}) as provided by " + f"{provider} ({provider_version}, {release_date}) and stored in Biostrings objects." + ) + + organism_biocview_val = organism_biocview if organism_biocview else organism.replace(" ", "_") + + # 3. Create seed file content + seed_content = [ + f"Package: {package_name}", + f"Title: {title}", + f"Description: {description}", + f"Version: {package_version}", + f"Author: {author}", + f"Maintainer: {maintainer}", + f"License: {license_str}", + f"organism: {organism}", + f"common_name: {common_name}", + f"provider: {provider}", + f"provider_version: {provider_version}", + f"release_date: {release_date}", + f"BSgenomeObjname: {bsgenome_objname}", + f"organism_biocview: {organism_biocview_val}", + f"seqs_srcdir: {seqs_srcdir.resolve()}", + ] + + if circ_seqs: + r_vector = ', '.join(f'"{seq}"' for seq in circ_seqs) + seed_content.append(f"circ_seqs: c({r_vector})") + if seqfiles_prefix: + seed_content.append(f"seqfiles_prefix: {seqfiles_prefix}") + if seqfiles_suffix: + seed_content.append(f"seqfiles_suffix: {seqfiles_suffix}") + + seed_file_text = "\n".join(seed_content) + + # 4. Create R script + r_script_text = f""" + # Ensure BiocManager and BSgenome are installed + if (!requireNamespace("BiocManager", quietly = TRUE)) {{ + install.packages("BiocManager", repos="http://cran.us.r-project.org") + }} + if (!requireNamespace("BSgenome", quietly = TRUE)) {{ + BiocManager::install("BSgenome", update=FALSE, ask=FALSE) + }} + + library(BSgenome) + + # Forge the package + tryCatch({{ + forgeBSgenomeDataPkg(seed_file="seed.txt", destdir=".") + cat("BSgenome package '{package_name}' successfully forged.\\n") + }}, error = function(e) {{ + cat("Error during package forging:\\n") + cat(conditionMessage(e), "\\n") + quit(status = 1) + }}) + """ + + # 5. Execute in a temporary directory + with tempfile.TemporaryDirectory() as tmpdir: + work_dir = Path(tmpdir) + seed_file_path = work_dir / "seed.txt" + r_script_path = work_dir / "run_forge.R" + + seed_file_path.write_text(seed_file_text) + r_script_path.write_text(r_script_text) + + cmd = ["Rscript", str(r_script_path)] + command_executed = " ".join(cmd) + + try: + process = subprocess.run( + cmd, + cwd=work_dir, + check=True, + capture_output=True, + text=True, + encoding='utf-8', + ) + + # 6. Package the result + created_pkg_dir = work_dir / package_name + if not created_pkg_dir.is_dir(): + raise FileNotFoundError( + f"BSgenome package directory '{package_name}' was not created. " + f"Check R script output for errors.\nStderr: {process.stderr}" + ) + + archive_base_name = str(output_pkg_path.with_suffix('')) + archive_path_str = shutil.make_archive( + base_name=archive_base_name, + format='gztar', + root_dir=work_dir, + base_dir=package_name + ) + + final_archive_path = Path(archive_path_str) + if final_archive_path != output_pkg_path: + final_archive_path.rename(output_pkg_path) + + return { + "command_executed": command_executed, + "stdout": process.stdout, + "stderr": process.stderr, + "output_files": {"bsgenome_package_archive": str(output_pkg_path)} + } + + except subprocess.CalledProcessError as e: + # Using .decode() in case the output is not valid utf-8 on error + stdout = e.stdout if isinstance(e.stdout, str) else e.stdout.decode('utf-8', errors='replace') + stderr = e.stderr if isinstance(e.stderr, str) else e.stderr.decode('utf-8', errors='replace') + return { + "command_executed": command_executed, + "stdout": stdout, + "stderr": stderr, + "error": "R script execution failed.", + "return_code": e.returncode, + } \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-bsgenome/app/bioconductor-bsgenome_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-bsgenome/app/bioconductor-bsgenome_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..d121d0271bb0d74837b8f03f16a2f8e47b553b0e --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-bsgenome/app/bioconductor-bsgenome_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-bsgenome/app/bioconductor-bsgenome_server.py') +SERVER_NAME = 'biosci_bioconductor_bsgenome' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-bsgenome/app/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-bsgenome/app/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-bsgenome/app/requirements.txt @@ -0,0 +1 @@ + diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-bsgenome/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-bsgenome/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..a16172fc9d353b1fa84f3f1c445702f0bc06751b --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-bsgenome/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-bioconductor-bsgenome: + build: . + image: mcp-bioconductor-bsgenome:latest + container_name: mcp-bioconductor-bsgenome + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=bioconductor-bsgenome + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-bsgenome/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-bsgenome/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..1d3824d6847258fcb5b0a063d4a0c1268b07dfd8 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-bsgenome/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - bioconductor-bsgenome + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-bsgenome/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-bsgenome/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-bsgenome/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-dnacopy/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-dnacopy/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..acfa6545a2f171d74ff198f82cd7aaba66db4989 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-dnacopy/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install bioconductor-dnacopy via conda (e.g., from bioconda) +RUN conda install -c bioconda bioconductor-dnacopy -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY app/bioconductor-dnacopy_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/bioconductor-dnacopy_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/bioconductor-dnacopy_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-dnacopy/app/bioconductor-dnacopy_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-dnacopy/app/bioconductor-dnacopy_server.py new file mode 100644 index 0000000000000000000000000000000000000000..0689beccafb1bc4991e8ebbb1daff93377fcf2ea --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-dnacopy/app/bioconductor-dnacopy_server.py @@ -0,0 +1,208 @@ +import subprocess +import tempfile +from pathlib import Path +from typing import Dict, List, Optional, Union + +# This is a placeholder for the MCP decorator. +# In a real MCP environment, this would be imported. +def tool(func): + """A dummy decorator to mimic @mcp.tool() for standalone execution.""" + return func + +@tool +def dnacopy_segment( + input_file: Path, + output_prefix: str, + sample_id_col: str, + chrom_col: str, + maploc_col: str, + data_col: str, + smooth_cna: bool = True, + make_plot: bool = True, + alpha: float = 0.01, + nperm: int = 10000, + p_method: str = "hybrid", + min_width: int = 2, + undo_splits: str = "sdundo", + undo_sd: float = 3.0, + trim: float = 0.025, + verbose: int = 1, +) -> Dict[str, Union[str, List[str]]]: + """ + Performs Circular Binary Segmentation (CBS) on copy number data using the R package DNAcopy. + + This tool takes a tab-delimited file containing genomic data (chromosome, position, log-ratio) + and segments it to identify regions of equal copy number. + + Args: + input_file: Path to the input tab-delimited data file. + output_prefix: Prefix for the output files (e.g., 'my_sample'). + sample_id_col: Name of the column containing sample identifiers. + chrom_col: Name of the column containing chromosome identifiers. + maploc_col: Name of the column containing genomic map locations (positions). + data_col: Name of the column containing the log2 ratio copy number data. + smooth_cna: If True, apply the `smooth.CNA` function before segmentation. Defaults to True. + make_plot: If True, generate a plot of the segmentation results as a PDF. Defaults to True. + alpha: Significance level to accept a change-point. Defaults to 0.01. + nperm: Number of permutations for `p.method='perm'`. Defaults to 10000. + p_method: Method to compute p-values. Must be 'hybrid' or 'perm'. Defaults to 'hybrid'. + min_width: The minimum number of markers for a segment. Defaults to 2. + undo_splits: Method for undoing splits. Must be 'none', 'prune', or 'sdundo'. Defaults to 'sdundo'. + undo_sd: The number of standard deviations for the undoing rule. Defaults to 3.0. + trim: Proportion of data to be trimmed for variance calculation. Defaults to 0.025. + verbose: Verbosity level (0, 1, or 2). Defaults to 1. + + Returns: + A dictionary containing the executed command, stdout, stderr, and a list of output file paths. + """ + # --- 1. Input Validation --- + if not input_file.is_file(): + raise FileNotFoundError(f"Input file not found: {input_file}") + + p_method_choices = ["hybrid", "perm"] + if p_method not in p_method_choices: + raise ValueError(f"p_method must be one of {p_method_choices}, not '{p_method}'") + + undo_splits_choices = ["none", "prune", "sdundo"] + if undo_splits not in undo_splits_choices: + raise ValueError(f"undo_splits must be one of {undo_splits_choices}, not '{undo_splits}'") + + if not (0 < alpha < 1): + raise ValueError("alpha must be between 0 and 1.") + + if not (0 <= trim < 0.5): + raise ValueError("trim must be between 0 and 0.5.") + + if nperm <= 0: + raise ValueError("nperm must be a positive integer.") + + if min_width < 2: + raise ValueError("min_width must be an integer >= 2.") + + if verbose not in [0, 1, 2]: + raise ValueError("verbose must be 0, 1, or 2.") + + # --- 2. Define Output Paths --- + output_seg_file = Path(f"{output_prefix}.seg") + output_plot_file = Path(f"{output_prefix}.pdf") + output_files = [str(output_seg_file)] + if make_plot: + output_files.append(str(output_plot_file)) + + # --- 3. Generate R Script --- + # This script reads the data, creates a CNA object, optionally smooths it, + # runs segmentation, and writes the output. It also handles non-numeric + # chromosome names like 'X' and 'Y'. + r_script = f""" + # Load the library + library(DNAcopy) + + # Read the input data + cat("Reading input file: {input_file}\\n") + raw_data <- read.table("{input_file}", header=TRUE, sep="\\t", stringsAsFactors=FALSE, check.names=FALSE) + + # Ensure required columns exist + required_cols <- c("{sample_id_col}", "{chrom_col}", "{maploc_col}", "{data_col}") + if (!all(required_cols %in% colnames(raw_data))) {{ + stop("One or more required columns not found in the input file.") + }} + + # Pre-process chromosome column to handle non-numeric values (e.g., X, Y) + cat("Processing chromosome identifiers...\\n") + raw_data[["{chrom_col}"]] <- as.character(raw_data[["{chrom_col}"]]) + raw_data[["{chrom_col}"]][toupper(raw_data[["{chrom_col}"]]) == 'X'] <- 23 + raw_data[["{chrom_col}"]][toupper(raw_data[["{chrom_col}"]]) == 'Y'] <- 24 + raw_data[["{chrom_col}"]][toupper(raw_data[["{chrom_col}"]]) == 'MT'] <- 25 + raw_data[["{chrom_col}"]] <- suppressWarnings(as.numeric(raw_data[["{chrom_col}"]])) + + # Filter out rows with NA values in key columns after conversion + raw_data <- raw_data[ + !is.na(raw_data[["{chrom_col}"]]) & + !is.na(raw_data[["{maploc_col}"]]) & + !is.na(raw_data[["{data_col}"]]), + ] + + # Create CNA object + cat("Creating CNA object...\\n") + CNA.object <- CNA( + genomdat = raw_data[["{data_col}"]], + chrom = raw_data[["{chrom_col}"]], + maploc = raw_data[["{maploc_col}"]], + data.type = 'logratio', + sampleid = raw_data[["{sample_id_col}"]] + ) + + # Smooth the data if requested + target_object <- CNA.object + if ({str(smooth_cna).upper()}) {{ + cat("Smoothing CNA object...\\n") + target_object <- smooth.CNA(CNA.object) + }} + + # Perform segmentation + cat("Performing segmentation...\\n") + segmentation <- segment( + target_object, + alpha = {alpha}, + nperm = {nperm}, + p.method = "{p_method}", + min.width = {min_width}, + undo.splits = "{undo_splits}", + undo.SD = {undo_sd}, + trim = {trim}, + verbose = {verbose} + ) + + # Write segmentation output + cat("Writing segmentation output to {output_seg_file}\\n") + write.table(segmentation$output, file="{output_seg_file}", sep="\\t", quote=FALSE, row.names=FALSE) + + # Generate plot if requested + if ({str(make_plot).upper()}) {{ + cat("Generating plot at {output_plot_file}\\n") + pdf("{output_plot_file}") + plot(segmentation, plot.type="w") + dev.off() + }} + + cat("DNAcopy analysis complete.\\n") + """ + + # --- 4. Execute R Script --- + command = [] + try: + with tempfile.NamedTemporaryFile(mode='w', suffix=".R", delete=False) as tmp_script: + tmp_script.write(r_script) + script_path = tmp_script.name + + command = ["Rscript", script_path] + process = subprocess.run( + command, + check=True, + capture_output=True, + text=True, + ) + + except FileNotFoundError: + raise RuntimeError("Rscript not found. Please ensure R is installed and in your PATH.") + except subprocess.CalledProcessError as e: + # Provide a more informative error message + error_message = ( + f"DNAcopy R script failed with exit code {e.returncode}.\n" + f"Command: {' '.join(command)}\n" + f"Stdout: {e.stdout}\n" + f"Stderr: {e.stderr}" + ) + raise RuntimeError(error_message) from e + finally: + # Clean up the temporary script file + if 'script_path' in locals() and Path(script_path).exists(): + Path(script_path).unlink() + + # --- 5. Return Structured Output --- + return { + "command_executed": " ".join(command), + "stdout": process.stdout, + "stderr": process.stderr, + "output_files": output_files, + } \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-dnacopy/app/bioconductor-dnacopy_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-dnacopy/app/bioconductor-dnacopy_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..4e35c63c11f28ceaa1593b1d5726dff44d482f70 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-dnacopy/app/bioconductor-dnacopy_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-dnacopy/app/bioconductor-dnacopy_server.py') +SERVER_NAME = 'biosci_bioconductor_dnacopy' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-dnacopy/app/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-dnacopy/app/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-dnacopy/app/requirements.txt @@ -0,0 +1 @@ + diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-dnacopy/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-dnacopy/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..2a3bc04cf7735b56b19adb7824aab027ad1edc38 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-dnacopy/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-bioconductor-dnacopy: + build: . + image: mcp-bioconductor-dnacopy:latest + container_name: mcp-bioconductor-dnacopy + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=bioconductor-dnacopy + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-dnacopy/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-dnacopy/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a899be3d3c4b68ef4f21429190feaaf5b44d4dbf --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-dnacopy/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - bioconductor-dnacopy + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-dnacopy/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-dnacopy/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-dnacopy/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-geneplotter/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-geneplotter/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..9d0c94a2a986994b11bf5544d2ed47deb4078e57 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-geneplotter/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install bioconductor-geneplotter via conda (e.g., from bioconda) +RUN conda install -c bioconda bioconductor-geneplotter -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY app/bioconductor-geneplotter_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/bioconductor-geneplotter_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/bioconductor-geneplotter_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-geneplotter/app/bioconductor-geneplotter_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-geneplotter/app/bioconductor-geneplotter_server.py new file mode 100644 index 0000000000000000000000000000000000000000..ef6dfcc0ec4c0900ae2ecde3121d5f1e6f66341a --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-geneplotter/app/bioconductor-geneplotter_server.py @@ -0,0 +1,442 @@ +import subprocess +import tempfile +import os +from pathlib import Path +from typing import Optional, Dict, Any, List + +# Mock decorator for standalone execution +class mcp: + @staticmethod + def tool(func): + return func + +@mcp.tool +def geneplotter_plot_ma( + expression_file: Path, + output_file: Path, + main_title: str = "MA Plot", + xlab: str = "A (Average Log Intensity)", + ylab: str = "M (Log Ratio)", + point_color: str = "blue", + point_size: float = 0.5, + add_abline: bool = True, + file_separator: str = "tab", +) -> Dict[str, Any]: + """ + Generates an M-A plot from a two-column expression file. + + This tool takes a file with two columns of expression data (e.g., two + samples or conditions), calculates M (log-ratio) and A (average log-intensity), + and generates a scatter plot. It is a common visualization for differential + expression analysis. + + Args: + expression_file: Path to the input data file. Must contain at least two + numeric columns representing two conditions. A header is expected. + output_file: Path to save the output PNG image. + main_title: The main title for the plot. + xlab: Label for the x-axis (A-values). + ylab: Label for the y-axis (M-values). + point_color: Color of the points in the plot. + point_size: Size of the points (cex in R). + add_abline: If True, adds a horizontal red line at y=0. + file_separator: The separator used in the input file ('tab' or 'comma'). + + Returns: + A dictionary containing the execution command, stdout, stderr, and a + list with the path to the output plot file. + """ + # --- Input Validation --- + if not expression_file.is_file(): + raise FileNotFoundError(f"Input file not found: {expression_file}") + if output_file.suffix.lower() != ".png": + raise ValueError("output_file must have a .png extension.") + if point_size <= 0: + raise ValueError("point_size must be a positive number.") + if file_separator not in ["tab", "comma"]: + raise ValueError("file_separator must be 'tab' or 'comma'.") + + output_file.parent.mkdir(parents=True, exist_ok=True) + sep_char = "\t" if file_separator == "tab" else "," + + # --- R Script --- + r_script_content = f""" + library(geneplotter) + library(methods) + + args <- commandArgs(trailingOnly = TRUE) + inputFile <- args[1] + outputFile <- args[2] + mainTitle <- args[3] + xLab <- args[4] + yLab <- args[5] + pointColor <- args[6] + pointSize <- as.numeric(args[7]) + addAbline <- as.logical(args[8]) + + data <- read.csv(inputFile, header = TRUE, sep = "{sep_char}") + + if (ncol(data) < 2) {{ + stop("Input file must have at least two numeric columns.") + }} + + offset <- 1e-6 + col1 <- as.numeric(data[,1]) + col2 <- as.numeric(data[,2]) + + M <- log2(col1 + offset) - log2(col2 + offset) + A <- 0.5 * (log2(col1 + offset) + log2(col2 + offset)) + ma_data <- data.frame(A = A, M = M) + + png(outputFile, width = 800, height = 600) + + plot(ma_data, + main = mainTitle, + xlab = xLab, + ylab = yLab, + col = pointColor, + cex = pointSize, + pch = 16) + + if (addAbline) {{ + abline(h = 0, col = "red", lwd = 2) + }} + + dev.off() + """ + + with tempfile.NamedTemporaryFile(mode='w', suffix=".R", delete=False) as r_script_file: + r_script_file.write(r_script_content) + script_path = r_script_file.name + + # --- Subprocess Execution --- + command: List[str] = [ + "Rscript", + script_path, + str(expression_file), + str(output_file), + main_title, + xlab, + ylab, + point_color, + str(point_size), + str(add_abline).upper(), + ] + + command_str = " ".join(command) + try: + result = subprocess.run( + command, + capture_output=True, + text=True, + check=True, + ) + return { + "command_executed": command_str, + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": [str(output_file)], + } + except FileNotFoundError: + raise RuntimeError("Rscript not found. Please ensure R is installed and in your PATH.") + except subprocess.CalledProcessError as e: + error_message = ( + f"R script execution failed with return code {e.returncode}.\n" + f"Command: {command_str}\n" + f"Stdout: {e.stdout}\n" + f"Stderr: {e.stderr}" + ) + raise RuntimeError(error_message) + finally: + os.remove(script_path) + + +@mcp.tool +def geneplotter_plot_densities( + expression_file: Path, + output_file: Path, + main_title: str = "Density of log2(intensities)", + xlab: str = "log2(intensity)", + log_transform: bool = True, + legend_position: str = "topright", + line_width: int = 2, + file_separator: str = "tab", +) -> Dict[str, Any]: + """ + Plots density estimates of expression values for each sample. + + This tool is useful for quality control, allowing visual inspection of the + distribution of expression values across multiple samples to check for + batch effects or normalization issues. + + Args: + expression_file: Path to the input data file. Columns should be samples + and rows should be features (e.g., genes). A header row + with sample names and a first column with feature names + are expected. + output_file: Path to save the output PNG image. + main_title: The main title for the plot. + xlab: Label for the x-axis. + log_transform: If True, log2-transforms the data before plotting. + legend_position: Position of the legend (e.g., "topright", "bottomleft"). + line_width: Width of the density lines. + file_separator: The separator used in the input file ('tab' or 'comma'). + + Returns: + A dictionary containing the execution command, stdout, stderr, and a + list with the path to the output plot file. + """ + # --- Input Validation --- + if not expression_file.is_file(): + raise FileNotFoundError(f"Input file not found: {expression_file}") + if output_file.suffix.lower() != ".png": + raise ValueError("output_file must have a .png extension.") + if line_width <= 0: + raise ValueError("line_width must be a positive integer.") + if file_separator not in ["tab", "comma"]: + raise ValueError("file_separator must be 'tab' or 'comma'.") + + output_file.parent.mkdir(parents=True, exist_ok=True) + sep_char = "\t" if file_separator == "tab" else "," + + # --- R Script --- + r_script_content = f""" + library(geneplotter) + library(methods) + + args <- commandArgs(trailingOnly = TRUE) + inputFile <- args[1] + outputFile <- args[2] + mainTitle <- args[3] + xLab <- args[4] + logTransform <- as.logical(args[5]) + legendPos <- args[6] + lineWidth <- as.numeric(args[7]) + + data <- read.csv(inputFile, header = TRUE, sep = "{sep_char}", row.names = 1) + + data_matrix <- as.matrix(data) + if(!is.numeric(data_matrix)) {{ + stop("Input data must be numeric after the first column.") + }} + + if (logTransform) {{ + offset <- 1e-6 + data_matrix[data_matrix <= 0] <- offset + data_matrix <- log2(data_matrix) + }} + + png(outputFile, width = 800, height = 600) + + plotDensities(data_matrix, + main = mainTitle, + xlab = xLab, + legend = legendPos, + lwd = lineWidth) + + dev.off() + """ + + with tempfile.NamedTemporaryFile(mode='w', suffix=".R", delete=False) as r_script_file: + r_script_file.write(r_script_content) + script_path = r_script_file.name + + # --- Subprocess Execution --- + command: List[str] = [ + "Rscript", + script_path, + str(expression_file), + str(output_file), + main_title, + xlab, + str(log_transform).upper(), + legend_position, + str(line_width), + ] + + command_str = " ".join(command) + try: + result = subprocess.run( + command, + capture_output=True, + text=True, + check=True, + ) + return { + "command_executed": command_str, + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": [str(output_file)], + } + except FileNotFoundError: + raise RuntimeError("Rscript not found. Please ensure R is installed and in your PATH.") + except subprocess.CalledProcessError as e: + error_message = ( + f"R script execution failed with return code {e.returncode}.\n" + f"Command: {command_str}\n" + f"Stdout: {e.stdout}\n" + f"Stderr: {e.stderr}" + ) + raise RuntimeError(error_message) + finally: + os.remove(script_path) + + +@mcp.tool +def geneplotter_plot_pca( + expression_file: Path, + output_file: Path, + metadata_file: Optional[Path] = None, + grouping_column: Optional[str] = None, + pc_x: int = 1, + pc_y: int = 2, + main_title: str = "PCA Plot", + scale_data: bool = True, + center_data: bool = True, + point_size: float = 3.0, + file_separator: str = "tab", +) -> Dict[str, Any]: + """ + Performs PCA on expression data and generates a 2D scatter plot. + + This tool is used for exploratory data analysis to visualize sample + relationships. Points can be colored by providing a metadata file. + Requires R packages 'ggplot2' and 'RColorBrewer'. + + Args: + expression_file: Path to the expression data. Columns should be samples, + rows should be features. A header with sample names and + a first column with feature names are expected. + output_file: Path to save the output PNG image. + metadata_file: Optional. Path to a metadata file. The first column must + contain sample names matching the expression file's header. + grouping_column: The column name in metadata_file to use for coloring points. + Required if metadata_file is provided. + pc_x: The principal component to plot on the x-axis. + pc_y: The principal component to plot on the y-axis. + main_title: The main title for the plot. + scale_data: If True, scale variables to have unit variance before PCA. + center_data: If True, center variables to have mean zero before PCA. + point_size: Size of the points in the plot. + file_separator: The separator used in the input and metadata files ('tab' or 'comma'). + + Returns: + A dictionary containing the execution command, stdout, stderr, and a + list with the path to the output plot file. + """ + # --- Input Validation --- + if not expression_file.is_file(): + raise FileNotFoundError(f"Input file not found: {expression_file}") + if metadata_file and not metadata_file.is_file(): + raise FileNotFoundError(f"Metadata file not found: {metadata_file}") + if metadata_file and not grouping_column: + raise ValueError("grouping_column is required when metadata_file is provided.") + if not metadata_file and grouping_column: + raise ValueError("metadata_file is required when grouping_column is provided.") + if pc_x <= 0 or pc_y <= 0 or pc_x == pc_y: + raise ValueError("pc_x and pc_y must be different positive integers.") + if output_file.suffix.lower() != ".png": + raise ValueError("output_file must have a .png extension.") + if file_separator not in ["tab", "comma"]: + raise ValueError("file_separator must be 'tab' or 'comma'.") + + output_file.parent.mkdir(parents=True, exist_ok=True) + sep_char = "\t" if file_separator == "tab" else "," + + # --- R Script --- + r_script_content = f""" + library(ggplot2) + library(RColorBrewer) + + args <- commandArgs(trailingOnly = TRUE) + inputFile <- args[1] + outputFile <- args[2] + metadataFile <- args[3] + groupingColumn <- args[4] + pcX <- as.integer(args[5]) + pcY <- as.integer(args[6]) + mainTitle <- args[7] + scaleData <- as.logical(args[8]) + centerData <- as.logical(args[9]) + pointSize <- as.numeric(args[10]) + + expr_data <- read.csv(inputFile, header = TRUE, sep = "{sep_char}", row.names = 1) + data_for_pca <- t(expr_data) + + pca_result <- prcomp(data_for_pca, center = centerData, scale. = scaleData) + pca_summary <- summary(pca_result) + variance_explained <- pca_summary$importance[2, ] * 100 + xlab_text <- sprintf("PC%d (%.2f%% variance)", pcX, variance_explained[pcX]) + ylab_text <- sprintf("PC%d (%.2f%% variance)", pcY, variance_explained[pcY]) + + plot_data <- as.data.frame(pca_result$x) + + p <- ggplot(plot_data, aes_string(x = paste0("PC", pcX), y = paste0("PC", pcY))) + + if (metadataFile != "NULL") {{ + metadata <- read.csv(metadataFile, header = TRUE, sep = "{sep_char}", row.names = 1) + + if(!all(rownames(data_for_pca) %in% rownames(metadata))) {{ + stop("Not all samples in expression data are present in metadata file.") + }} + metadata_sorted <- metadata[rownames(data_for_pca), , drop = FALSE] + + if (!(groupingColumn %in% colnames(metadata_sorted))) {{ + stop(paste("Grouping column '", groupingColumn, "' not found in metadata file.", sep="")) + }} + plot_data$Group <- factor(metadata_sorted[[groupingColumn]]) + p <- p + geom_point(aes(color = Group), size = pointSize) + scale_color_brewer(palette = "Set1") + }} else {{ + p <- p + geom_point(size = pointSize) + }} + + p <- p + labs(title = mainTitle, x = xlab_text, y = ylab_text) + theme_bw() + ggsave(outputFile, plot = p, width = 8, height = 6, units = "in", dpi = 300) + """ + + with tempfile.NamedTemporaryFile(mode='w', suffix=".R", delete=False) as r_script_file: + r_script_file.write(r_script_content) + script_path = r_script_file.name + + # --- Subprocess Execution --- + command: List[str] = [ + "Rscript", + script_path, + str(expression_file), + str(output_file), + str(metadata_file) if metadata_file else "NULL", + str(grouping_column) if grouping_column else "NULL", + str(pc_x), + str(pc_y), + main_title, + str(scale_data).upper(), + str(center_data).upper(), + str(point_size), + ] + + command_str = " ".join(command) + try: + result = subprocess.run( + command, + capture_output=True, + text=True, + check=True, + ) + return { + "command_executed": command_str, + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": [str(output_file)], + } + except FileNotFoundError: + raise RuntimeError("Rscript not found. Please ensure R is installed and in your PATH.") + except subprocess.CalledProcessError as e: + error_message = ( + f"R script execution failed with return code {e.returncode}.\n" + f"Command: {command_str}\n" + f"Stdout: {e.stdout}\n" + f"Stderr: {e.stderr}" + ) + raise RuntimeError(error_message) + finally: + os.remove(script_path) \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-geneplotter/app/bioconductor-geneplotter_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-geneplotter/app/bioconductor-geneplotter_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..54951763fdcb4e86383e60e373262226eb1ba525 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-geneplotter/app/bioconductor-geneplotter_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-geneplotter/app/bioconductor-geneplotter_server.py') +SERVER_NAME = 'biosci_bioconductor_geneplotter' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-geneplotter/app/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-geneplotter/app/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-geneplotter/app/requirements.txt @@ -0,0 +1 @@ + diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-geneplotter/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-geneplotter/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..026bcda856f99b635b1b6d84ba99f4b936d948d7 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-geneplotter/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-bioconductor-geneplotter: + build: . + image: mcp-bioconductor-geneplotter:latest + container_name: mcp-bioconductor-geneplotter + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=bioconductor-geneplotter + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-geneplotter/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-geneplotter/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..140b2e80539603f5b9039b3b6fdfde9efa0c3d43 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-geneplotter/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - bioconductor-geneplotter + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-geneplotter/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-geneplotter/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-geneplotter/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomeinfodbdata/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomeinfodbdata/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..dc26f6e5aed612e1d00f134418a4dfb7f9cfe0cb --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomeinfodbdata/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install bioconductor-genomeinfodbdata via conda (e.g., from bioconda) +RUN conda install -c bioconda bioconductor-genomeinfodbdata -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY app/bioconductor-genomeinfodbdata_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/bioconductor-genomeinfodbdata_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/bioconductor-genomeinfodbdata_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomeinfodbdata/app/bioconductor-genomeinfodbdata_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomeinfodbdata/app/bioconductor-genomeinfodbdata_server.py new file mode 100644 index 0000000000000000000000000000000000000000..01172e946bbc296476712c464e9a98a8dd117e2b --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomeinfodbdata/app/bioconductor-genomeinfodbdata_server.py @@ -0,0 +1,180 @@ +import subprocess +import logging +from pathlib import Path +from typing import Optional, List, Dict, Any + +# Set up a logger for better debugging and information +logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') + +# This is a placeholder for the actual MCP decorator. +# The final code will be compatible with the MCP framework. +class mcp: + @staticmethod + def tool(func): + def wrapper(*args, **kwargs): + return func(*args, **kwargs) + # In a real MCP environment, this would register the function. + # For this standalone script, it just acts as a pass-through. + wrapper.__doc__ = func.__doc__ + wrapper.__annotations__ = func.__annotations__ + return wrapper + +@mcp.tool +def rscript_runner( + script_file: Optional[Path] = None, + expressions: Optional[List[str]] = None, + script_args: Optional[List[str]] = None, + verbose: bool = False, + default_packages: Optional[str] = None, + vanilla: bool = False, + save: bool = False, + no_environ: bool = False, + no_site_file: bool = False, + no_init_file: bool = False, + restore: bool = False, +) -> Dict[str, Any]: + """ + Executes an R script or R expressions using the Rscript command-line tool. + + This tool serves as a general-purpose wrapper for Rscript, allowing for the execution + of either a specified R script file or a list of R expressions. + + Args: + script_file: Path to the R script file to execute. Mutually exclusive with 'expressions'. + expressions: A list of R expressions to execute. Mutually exclusive with 'script_file'. + script_args: A list of arguments to be passed to the R script. + verbose: If True, enables verbose output from Rscript. + default_packages: A comma-separated list of package names to be loaded by default. + vanilla: If True, combines --no-save, --no-restore, --no-site-file, --no-init-file, and --no-environ. + This provides a "clean" R session. + save: If True, the workspace is saved at the end of the session. Ignored if 'vanilla' is True. + no_environ: If True, site and user environment files are not read. Ignored if 'vanilla' is True. + no_site_file: If True, the site-wide Rprofile is not read. Ignored if 'vanilla' is True. + no_init_file: If True, the user's R profile is not read. Ignored if 'vanilla' is True. + restore: If True, previously saved objects are restored at startup. Ignored if 'vanilla' is True. + + Returns: + A dictionary containing the executed command, stdout, stderr, and a list of potential output files. + """ + # --- Input Validation --- + if not script_file and not expressions: + raise ValueError("You must provide either 'script_file' or 'expressions'.") + if script_file and expressions: + raise ValueError("'script_file' and 'expressions' are mutually exclusive.") + if script_file and not script_file.is_file(): + raise FileNotFoundError(f"The specified script file does not exist: {script_file}") + + # --- Command Construction --- + command = ["Rscript"] + + if vanilla: + command.append("--vanilla") + else: + if save: + command.append("--save") + if no_environ: + command.append("--no-environ") + if no_site_file: + command.append("--no-site-file") + if no_init_file: + command.append("--no-init-file") + if restore: + command.append("--restore") + + if verbose: + command.append("--verbose") + + if default_packages: + command.extend(["--default-packages", default_packages]) + + if expressions: + for expr in expressions: + command.extend(["-e", expr]) + + if script_file: + command.append(str(script_file)) + + if script_args: + command.extend(script_args) + + command_str = " ".join(command) + logging.info(f"Executing command: {command_str}") + + # --- Subprocess Execution --- + try: + result = subprocess.run( + command, + capture_output=True, + text=True, + check=True, + ) + stdout = result.stdout + stderr = result.stderr + logging.info("Rscript executed successfully.") + + except FileNotFoundError: + logging.error("Rscript not found. Please ensure R is installed and in your system's PATH.") + raise + except subprocess.CalledProcessError as e: + logging.error(f"Rscript execution failed with return code {e.returncode}") + logging.error(f"Stderr: {e.stderr}") + logging.error(f"Stdout: {e.stdout}") + return { + "command_executed": command_str, + "stdout": e.stdout, + "stderr": e.stderr, + "output_files": [] + } + + # --- Structured Result Return --- + # Note: Predicting output files from a generic script runner is not feasible. + # The user of this tool is responsible for knowing what files their script creates. + return { + "command_executed": command_str, + "stdout": stdout, + "stderr": stderr, + "output_files": [] + } + +@mcp.tool +def rscript_version() -> Dict[str, Any]: + """ + Retrieves the version of the Rscript interpreter and the R language. + + This is equivalent to running 'Rscript --version' on the command line. + + Returns: + A dictionary containing the executed command and the version information + captured from stderr (as Rscript prints version info to stderr). + """ + command = ["Rscript", "--version"] + command_str = " ".join(command) + logging.info(f"Executing command: {command_str}") + + try: + # Rscript prints version information to stderr, so we capture it. + result = subprocess.run( + command, + capture_output=True, + text=True, + check=True, + ) + # The primary output is in stderr for the --version flag + version_info = result.stderr + + except FileNotFoundError: + logging.error("Rscript not found. Please ensure R is installed and in your system's PATH.") + raise + except subprocess.CalledProcessError as e: + logging.error(f"Rscript --version failed with return code {e.returncode}") + return { + "command_executed": command_str, + "stdout": e.stdout, + "stderr": e.stderr, + } + + return { + "command_executed": command_str, + "stdout": result.stdout, + "stderr": version_info, + } \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomeinfodbdata/app/bioconductor-genomeinfodbdata_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomeinfodbdata/app/bioconductor-genomeinfodbdata_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..08d533246b60c98b5a276012a57b31f2229d4d32 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomeinfodbdata/app/bioconductor-genomeinfodbdata_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomeinfodbdata/app/bioconductor-genomeinfodbdata_server.py') +SERVER_NAME = 'biosci_bioconductor_genomeinfodbdata' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomeinfodbdata/app/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomeinfodbdata/app/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomeinfodbdata/app/requirements.txt @@ -0,0 +1 @@ + diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomeinfodbdata/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomeinfodbdata/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..417a651e07b0490b797620fdf758562f52d5a1cb --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomeinfodbdata/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-bioconductor-genomeinfodbdata: + build: . + image: mcp-bioconductor-genomeinfodbdata:latest + container_name: mcp-bioconductor-genomeinfodbdata + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=bioconductor-genomeinfodbdata + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomeinfodbdata/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomeinfodbdata/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..e178851c0df5db898851d3336adcacfea12f5cad --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomeinfodbdata/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - bioconductor-genomeinfodbdata + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomeinfodbdata/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomeinfodbdata/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomeinfodbdata/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomicfeatures/app/bioconductor-genomicfeatures_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomicfeatures/app/bioconductor-genomicfeatures_server.py new file mode 100644 index 0000000000000000000000000000000000000000..c08cb1984359657020a5c6b1e1ca7e63d745eac3 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomicfeatures/app/bioconductor-genomicfeatures_server.py @@ -0,0 +1,170 @@ +import subprocess +import tempfile +import shlex +from pathlib import Path +from typing import Optional, Dict, List + +# @mcp.tool() is a placeholder for the actual decorator. +# The code is written to be compatible with the MCP framework. + +@mcp.tool() +def make_txdb_from_gff( + gff_file: Path, + output_db_path: Path, + format: Optional[str] = None, + data_source: Optional[str] = None, + organism: Optional[str] = None, + taxonomy_id: Optional[int] = None, + chrominfo_file: Optional[Path] = None, + metadata_file: Optional[Path] = None, + pruning_mode: str = "coarse", + on_foreign_chrom: str = "abort", + infer_cds: bool = False, + infer_utr: bool = True, +) -> Dict: + """ + Creates a TranscriptDb (TxDb) SQLite database from a GFF or GTF file. + + This tool serves as a wrapper for the `makeTxDbFromGFF` function from the + R/Bioconductor GenomicFeatures package. It parses a gene annotation file + (GFF3 or GTF) and stores the transcript metadata in a structured SQLite + database, which is highly efficient for downstream analysis. + + Args: + gff_file: Path to the input GFF3 or GTF file. + output_db_path: Path where the output SQLite TxDb file will be saved. + format: The format of the input file. Can be 'gff3' or 'gtf'. + If not provided, the tool attempts to infer it from the file extension. + data_source: A string describing the source of the data (e.g., "Ensembl v104"). + organism: The scientific name of the organism (e.g., "Homo sapiens"). + taxonomy_id: The NCBI Taxonomy ID for the organism. + chrominfo_file: Optional path to a two-column, tab-separated file containing + chromosome names and their lengths. + metadata_file: Optional path to a two-column, tab-separated file containing + metadata as name-value pairs to be stored in the database. + pruning_mode: Sets the strictness for handling problematic transcripts. + Must be one of 'coarse', 'fine', or 'strict'. + on_foreign_chrom: Action to take for features on chromosomes not listed in + `chrominfo_file`. Must be one of 'abort', 'drop', or 'as.is'. + infer_cds: If TRUE, infer CDS features from annotated stop codons. + infer_utr: If TRUE, infer UTR features (5' and 3') when not explicitly provided. + + Returns: + A dictionary containing the executed command, stdout, stderr, and a + mapping to the generated output database file. + """ + # 1. Input Validation + if not gff_file.is_file(): + raise FileNotFoundError(f"Input GFF/GTF file not found: {gff_file}") + + if chrominfo_file and not chrominfo_file.is_file(): + raise FileNotFoundError(f"Chrominfo file not found: {chrominfo_file}") + + if metadata_file and not metadata_file.is_file(): + raise FileNotFoundError(f"Metadata file not found: {metadata_file}") + + if format and format.lower() not in ["gff3", "gtf"]: + raise ValueError("Parameter 'format' must be either 'gff3' or 'gtf'.") + + allowed_pruning = ["coarse", "fine", "strict"] + if pruning_mode not in allowed_pruning: + raise ValueError(f"Parameter 'pruning_mode' must be one of {allowed_pruning}.") + + allowed_foreign_chrom = ["abort", "drop", "as.is"] + if on_foreign_chrom not in allowed_foreign_chrom: + raise ValueError(f"Parameter 'on_foreign_chrom' must be one of {allowed_foreign_chrom}.") + + output_db_path.parent.mkdir(parents=True, exist_ok=True) + + # 2. R Script Generation + # Use R-friendly paths (forward slashes) for cross-platform compatibility + gff_file_r = str(gff_file).replace('\\', '/') + output_db_path_r = str(output_db_path).replace('\\', '/') + + r_script_lines = [ + "suppressPackageStartupMessages(library(GenomicFeatures))", + "", + "# Build the argument list for makeTxDbFromGFF", + f'txdb_args <- list(file = "{gff_file_r}")', + ] + + # Add optional arguments to the list + if format: + r_script_lines.append(f'txdb_args$format <- "{format.lower()}"') + if data_source: + r_script_lines.append(f'txdb_args$dataSource <- "{data_source}"') + if organism: + r_script_lines.append(f'txdb_args$organism <- "{organism}"') + if taxonomy_id is not None: + r_script_lines.append(f'txdb_args$taxonomyId <- {taxonomy_id}') + + r_script_lines.append(f'txdb_args$pruning.mode <- "{pruning_mode}"') + r_script_lines.append(f'txdb_args$on.foreign.chrom <- "{on_foreign_chrom}"') + r_script_lines.append(f'txdb_args$infer_cds <- {"TRUE" if infer_cds else "FALSE"}') + r_script_lines.append(f'txdb_args$infer_utr <- {"TRUE" if infer_utr else "FALSE"}') + + if chrominfo_file: + chrominfo_file_r = str(chrominfo_file).replace('\\', '/') + r_script_lines.extend([ + f'chrominfo_df <- read.table("{chrominfo_file_r}", sep="\\t", header=FALSE, col.names=c("chrom", "length"), stringsAsFactors=FALSE)', + 'txdb_args$chrominfo <- chrominfo_df' + ]) + + if metadata_file: + metadata_file_r = str(metadata_file).replace('\\', '/') + r_script_lines.extend([ + f'metadata_df <- read.table("{metadata_file_r}", sep="\\t", header=FALSE, col.names=c("name", "value"), stringsAsFactors=FALSE)', + 'txdb_args$metadata <- metadata_df' + ]) + + r_script_lines.extend([ + "", + "# Execute the function with the constructed arguments", + "txdb <- do.call(makeTxDbFromGFF, txdb_args)", + "", + "# Save the resulting database", + f'saveDb(txdb, file="{output_db_path_r}")', + 'message("TxDb database created successfully.")' + ]) + + r_script_content = "\n".join(r_script_lines) + + script_path = None + try: + with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix=".R", encoding='utf-8') as r_script_file: + r_script_file.write(r_script_content) + script_path = r_script_file.name + + # 3. Subprocess Execution + cmd = ["Rscript", script_path] + command_executed = shlex.join(cmd) + + result = subprocess.run( + cmd, + check=True, + capture_output=True, + text=True, + encoding='utf-8' + ) + + # 4. Structured Result Return + return { + "command_executed": command_executed, + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": {"txdb_database": str(output_db_path)} + } + + except subprocess.CalledProcessError as e: + # R often prints errors to stdout, so combine them for a comprehensive message + error_message = ( + f"R script execution failed with exit code {e.returncode}.\n" + f"STDOUT:\n{e.stdout}\n" + f"STDERR:\n{e.stderr}\n" + ) + raise RuntimeError(error_message) from e + + finally: + # Clean up the temporary script file + if script_path and Path(script_path).exists(): + Path(script_path).unlink() diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomicfeatures/app/bioconductor-genomicfeatures_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomicfeatures/app/bioconductor-genomicfeatures_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..74beea75c4dc00d1eca821fc4bdd3c69b4163675 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomicfeatures/app/bioconductor-genomicfeatures_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomicfeatures/app/bioconductor-genomicfeatures_server.py') +SERVER_NAME = 'biosci_bioconductor_genomicfeatures' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomicfeatures/app/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomicfeatures/app/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomicfeatures/app/requirements.txt @@ -0,0 +1 @@ + diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomicfeatures/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomicfeatures/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomicfeatures/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-go.db/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-go.db/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..2069a4e8592c1da90c7837bb6d4c45e57bd872d8 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-go.db/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install bioconductor-go.db via conda (e.g., from bioconda) +RUN conda install -c bioconda bioconductor-go.db -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY app/bioconductor-go.db_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/bioconductor-go.db_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/bioconductor-go.db_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-go.db/app/bioconductor-go.db_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-go.db/app/bioconductor-go.db_server.py new file mode 100644 index 0000000000000000000000000000000000000000..4a09956198630ec0735b212eb2a3f512798d6621 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-go.db/app/bioconductor-go.db_server.py @@ -0,0 +1,188 @@ +import subprocess +import tempfile +from pathlib import Path +from typing import List, Optional, Dict, Any + +# MCP decorator is not imported as per instructions. +# It is assumed to be available in the execution environment. + +# @mcp.tool() +def list_go_db_columns() -> Dict[str, Any]: + """ + Lists all available columns for querying in the Bioconductor GO.db. + + This function executes an R script to load the GO.db package and + extract the names of all queryable columns. It is useful for discovering + what data can be retrieved using the `query_go_db` function. + + Requirements: + - R must be installed and in the system's PATH. + - The R packages 'BiocManager', 'AnnotationDbi', and 'GO.db' must be installed. + (e.g., in R: BiocManager::install(c("AnnotationDbi", "GO.db"))) + """ + r_script = "library(GO.db); cat(columns(GO.db), sep='\\n')" + command = ["Rscript", "-e", r_script] + command_executed = " ".join(command) + + try: + result = subprocess.run( + command, + capture_output=True, + text=True, + check=True, + ) + # The columns are returned as a newline-separated string + columns_list = result.stdout.strip().split('\n') + return { + "command_executed": command_executed, + "stdout": f"Available columns: {', '.join(columns_list)}", + "stderr": result.stderr, + "columns": columns_list, + } + except FileNotFoundError: + return { + "command_executed": command_executed, + "stdout": "", + "stderr": "Error: 'Rscript' not found. Please ensure R is installed and in your PATH.", + "error": "Dependency not found" + } + except subprocess.CalledProcessError as e: + stderr = e.stderr + if "there is no package called" in stderr: + stderr += "\n\nHint: Please ensure the 'GO.db' and 'AnnotationDbi' R packages are installed." + return { + "command_executed": command_executed, + "stdout": e.stdout, + "stderr": stderr, + "error": "R script execution failed" + } + +# @mcp.tool() +def query_go_db( + go_ids: List[str], + columns: Optional[List[str]] = None, + output_file: Optional[Path] = None, +) -> Dict[str, Any]: + """ + Query the Bioconductor GO.db to retrieve information about Gene Ontology terms. + + This tool uses R/Bioconductor's GO.db annotation package to fetch details + for a given list of GO IDs. You can specify which columns of data to retrieve. + + Requirements: + - R must be installed and in the system's PATH. + - The R packages 'BiocManager', 'AnnotationDbi', and 'GO.db' must be installed. + (e.g., in R: BiocManager::install(c("AnnotationDbi", "GO.db"))) + + Args: + go_ids: A list of Gene Ontology (GO) IDs to query (e.g., ['GO:0005575', 'GO:0008150']). + columns: A list of columns to retrieve. Defaults to ['GOID', 'TERM', 'DEFINITION', 'ONTOLOGY']. + Use the `list_go_db_columns` tool to see all available columns. + output_file: Optional path to save the output as a tab-separated (TSV) file. + If not provided, the output is returned in stdout. + """ + # --- Input Validation --- + if not go_ids: + raise ValueError("The 'go_ids' list cannot be empty.") + + for go_id in go_ids: + if not isinstance(go_id, str) or not go_id.startswith("GO:"): + raise ValueError(f"Invalid GO ID format: '{go_id}'. Expected format is 'GO:#######'.") + + if columns is None: + # Default columns provide the most common information + columns_to_query = ["GOID", "TERM", "DEFINITION", "ONTOLOGY"] + else: + if not isinstance(columns, list) or not all(isinstance(c, str) for c in columns): + raise TypeError("The 'columns' parameter must be a list of strings.") + columns_to_query = columns + + # --- R Script Construction --- + # Convert Python lists to R vector syntax: c("item1", "item2") + r_go_ids = 'c({})'.format(','.join(f'"{gid}"' for gid in go_ids)) + r_columns = 'c({})'.format(','.join(f'"{col}"' for col in columns_to_query)) + + # Using a temporary file for the output if no output_file is specified by the user + # This avoids complex stdout redirection and ensures clean capture + temp_dir = tempfile.TemporaryDirectory() + final_output_path = Path(output_file) if output_file else Path(temp_dir.name) / "go_query_results.tsv" + + r_script = f""" + # Suppress package startup messages for cleaner output + suppressPackageStartupMessages(library(AnnotationDbi)) + suppressPackageStartupMessages(library(GO.db)) + + go_keys <- {r_go_ids} + cols_to_get <- {r_columns} + output_path <- "{str(final_output_path)}" + + # Perform the query + results <- tryCatch( + AnnotationDbi::select(GO.db, keys=go_keys, columns=cols_to_get, keytype="GOID"), + error = function(e) {{ + write(paste("Error during AnnotationDbi::select:", e$message), stderr()) + return(NULL) + }} + ) + + # Write results to the specified output file + if (!is.null(results)) {{ + write.table( + results, + file=output_path, + sep="\\t", + row.names=FALSE, + quote=FALSE + ) + }} + """ + + command = ["Rscript", "-e", r_script] + command_executed = " ".join(command) + output_files_list = [] + + try: + # --- Subprocess Execution --- + result = subprocess.run( + command, + capture_output=True, + text=True, + check=True, + ) + + stdout_content = "" + if final_output_path.exists() and final_output_path.stat().st_size > 0: + output_files_list.append(str(final_output_path)) + # If no output file was requested by the user, read the temp file content for stdout + if not output_file: + stdout_content = final_output_path.read_text() + else: + # Handle cases where the R script runs but produces no output (e.g., no matches) + stdout_content = "Query executed successfully, but no results were found for the given GO IDs." + + return { + "command_executed": command_executed, + "stdout": stdout_content, + "stderr": result.stderr, + "output_files": output_files_list, + } + except FileNotFoundError: + return { + "command_executed": command_executed, + "stdout": "", + "stderr": "Error: 'Rscript' not found. Please ensure R is installed and in your PATH.", + "error": "Dependency not found" + } + except subprocess.CalledProcessError as e: + stderr = e.stderr + if "there is no package called" in stderr: + stderr += "\n\nHint: Please ensure the 'GO.db' and 'AnnotationDbi' R packages are installed." + return { + "command_executed": command_executed, + "stdout": e.stdout, + "stderr": stderr, + "error": "R script execution failed" + } + finally: + # Clean up the temporary directory + temp_dir.cleanup() diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-go.db/app/bioconductor-go.db_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-go.db/app/bioconductor-go.db_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..bfcac25303616fc3345c9ddbc3e5a66e85099288 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-go.db/app/bioconductor-go.db_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-go.db/app/bioconductor-go.db_server.py') +SERVER_NAME = 'biosci_bioconductor_go_db' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-go.db/app/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-go.db/app/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-go.db/app/requirements.txt @@ -0,0 +1 @@ + diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-go.db/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-go.db/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..bcb222a73c2f27a64f265287d9ff4aa040928e68 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-go.db/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-bioconductor-go.db: + build: . + image: mcp-bioconductor-go.db:latest + container_name: mcp-bioconductor-go.db + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=bioconductor-go.db + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-go.db/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-go.db/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..0607214ee0c410fe2635325e9264b0cba5fd89bb --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-go.db/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - bioconductor-go.db + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-go.db/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-go.db/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-go.db/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gosemsim/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gosemsim/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..79759355a85d632d7922ea3c56930957dd4d59fa --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gosemsim/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install bioconductor-gosemsim via conda (e.g., from bioconda) +RUN conda install -c bioconda bioconductor-gosemsim -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY app/bioconductor-gosemsim_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/bioconductor-gosemsim_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/bioconductor-gosemsim_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gosemsim/app/bioconductor-gosemsim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gosemsim/app/bioconductor-gosemsim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..ebbc0235d7f4f0bbde1d9573e8b5c8e69843c7f9 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gosemsim/app/bioconductor-gosemsim_server.py @@ -0,0 +1,273 @@ +import subprocess +import json +import tempfile +from pathlib import Path +from typing import List, Optional, Literal, Union + +@mcp.tool() +def go_similarity( + term1: str, + term2: str, + org_db: str = "org.Hs.eg.db", + ont: Literal["BP", "MF", "CC"] = "BP", + measure: Literal["Resnik", "Lin", "Rel", "Jiang", "Wang"] = "Wang", + keytype: str = "ENTREZID" +): + """ + Calculate semantic similarity between two GO terms using GOSemSim. + + Args: + term1: First GO term ID (e.g., 'GO:0004022'). + term2: Second GO term ID (e.g., 'GO:0005515'). + org_db: The annotation OrgDb package (e.g., 'org.Hs.eg.db' for human). + ont: One of "BP", "MF", or "CC" ontologies. + measure: Semantic similarity method ("Resnik", "Lin", "Rel", "Jiang", or "Wang"). + keytype: Key type of the gene identifiers in the OrgDb. + """ + if not term1.startswith("GO:") or not term2.startswith("GO:"): + return {"error": "GO terms must start with 'GO:' prefix."} + + r_script = f""" + suppressPackageStartupMessages(library(GOSemSim)) + suppressPackageStartupMessages(library({org_db})) + + hsGO <- godata('{org_db}', ont='{ont}', computeIC=TRUE, keytype='{keytype}') + sim <- goSim('{term1}', '{term2}', semData=hsGO, measure='{measure}') + cat(sim) + """ + + return _execute_r_script(r_script) + +@mcp.tool() +def mgo_similarity( + terms: List[str], + org_db: str = "org.Hs.eg.db", + ont: Literal["BP", "MF", "CC"] = "BP", + measure: Literal["Resnik", "Lin", "Rel", "Jiang", "Wang"] = "Wang", + keytype: str = "ENTREZID" +): + """ + Calculate semantic similarity matrix for a list of GO terms. + + Args: + terms: List of GO term IDs. + org_db: The annotation OrgDb package. + ont: One of "BP", "MF", or "CC" ontologies. + measure: Semantic similarity method. + keytype: Key type of the gene identifiers. + """ + terms_r = 'c("' + '","'.join(terms) + '")' + r_script = f""" + suppressPackageStartupMessages(library(GOSemSim)) + suppressPackageStartupMessages(library({org_db})) + + hsGO <- godata('{org_db}', ont='{ont}', computeIC=TRUE, keytype='{keytype}') + sim_matrix <- mgoSim({terms_r}, semData=hsGO, measure='{measure}', combine=NULL) + write.csv(sim_matrix, row.names=TRUE) + """ + + return _execute_r_script(r_script) + +@mcp.tool() +def gene_similarity( + gene1: str, + gene2: str, + org_db: str = "org.Hs.eg.db", + ont: Literal["BP", "MF", "CC"] = "BP", + measure: Literal["Resnik", "Lin", "Rel", "Jiang", "Wang"] = "Wang", + combine: Literal["max", "avg", "rcmax", "BMA"] = "BMA", + keytype: str = "ENTREZID" +): + """ + Calculate semantic similarity between two genes based on their GO annotations. + + Args: + gene1: First gene ID. + gene2: Second gene ID. + org_db: The annotation OrgDb package. + ont: One of "BP", "MF", or "CC" ontologies. + measure: Semantic similarity method. + combine: Strategy to combine similarities of multiple GO terms ("max", "avg", "rcmax", "BMA"). + keytype: Key type of the gene identifiers (e.g., 'ENTREZID', 'SYMBOL'). + """ + r_script = f""" + suppressPackageStartupMessages(library(GOSemSim)) + suppressPackageStartupMessages(library({org_db})) + + hsGO <- godata('{org_db}', ont='{ont}', computeIC=TRUE, keytype='{keytype}') + sim <- geneSim('{gene1}', '{gene2}', semData=hsGO, measure='{measure}', combine='{combine}') + print(sim) + """ + + return _execute_r_script(r_script) + +@mcp.tool() +def mgene_similarity( + genes: List[str], + org_db: str = "org.Hs.eg.db", + ont: Literal["BP", "MF", "CC"] = "BP", + measure: Literal["Resnik", "Lin", "Rel", "Jiang", "Wang"] = "Wang", + combine: Literal["max", "avg", "rcmax", "BMA"] = "BMA", + keytype: str = "ENTREZID" +): + """ + Calculate semantic similarity matrix for a list of genes. + + Args: + genes: List of gene IDs. + org_db: The annotation OrgDb package. + ont: One of "BP", "MF", or "CC" ontologies. + measure: Semantic similarity method. + combine: Strategy to combine similarities. + keytype: Key type of the gene identifiers. + """ + genes_r = 'c("' + '","'.join(genes) + '")' + r_script = f""" + suppressPackageStartupMessages(library(GOSemSim)) + suppressPackageStartupMessages(library({org_db})) + + hsGO <- godata('{org_db}', ont='{ont}', computeIC=TRUE, keytype='{keytype}') + sim_matrix <- mgeneSim({genes_r}, semData=hsGO, measure='{measure}', combine='{combine}') + write.csv(sim_matrix, row.names=TRUE) + """ + + return _execute_r_script(r_script) + +@mcp.tool() +def cluster_similarity( + cluster1: List[str], + cluster2: List[str], + org_db: str = "org.Hs.eg.db", + ont: Literal["BP", "MF", "CC"] = "BP", + measure: Literal["Resnik", "Lin", "Rel", "Jiang", "Wang"] = "Wang", + combine: Literal["max", "avg", "rcmax", "BMA"] = "BMA", + keytype: str = "ENTREZID" +): + """ + Calculate semantic similarity between two clusters (sets) of genes. + + Args: + cluster1: List of gene IDs in the first cluster. + cluster2: List of gene IDs in the second cluster. + org_db: The annotation OrgDb package. + ont: One of "BP", "MF", or "CC" ontologies. + measure: Semantic similarity method. + combine: Strategy to combine similarities. + keytype: Key type of the gene identifiers. + """ + c1_r = 'c("' + '","'.join(cluster1) + '")' + c2_r = 'c("' + '","'.join(cluster2) + '")' + + r_script = f""" + suppressPackageStartupMessages(library(GOSemSim)) + suppressPackageStartupMessages(library({org_db})) + + hsGO <- godata('{org_db}', ont='{ont}', computeIC=TRUE, keytype='{keytype}') + sim <- clusterSim({c1_r}, {c2_r}, semData=hsGO, measure='{measure}', combine='{combine}') + cat(sim) + """ + + return _execute_r_script(r_script) + +@mcp.tool() +def mcluster_similarity( + clusters_json: str, + org_db: str = "org.Hs.eg.db", + ont: Literal["BP", "MF", "CC"] = "BP", + measure: Literal["Resnik", "Lin", "Rel", "Jiang", "Wang"] = "Wang", + combine: Literal["max", "avg", "rcmax", "BMA"] = "BMA", + keytype: str = "ENTREZID" +): + """ + Calculate semantic similarity matrix between multiple clusters of genes. + + Args: + clusters_json: A JSON string representing a dictionary where keys are cluster names + and values are lists of gene IDs. + org_db: The annotation OrgDb package. + ont: One of "BP", "MF", or "CC" ontologies. + measure: Semantic similarity method. + combine: Strategy to combine similarities. + keytype: Key type of the gene identifiers. + """ + try: + clusters_dict = json.loads(clusters_json) + except json.JSONDecodeError: + return {"error": "Invalid JSON format for clusters_json."} + + # Construct R list of character vectors + r_list_elements = [] + for name, genes in clusters_dict.items(): + genes_str = 'c("' + '","'.join(genes) + '")' + r_list_elements.append(f'"{name}" = {genes_str}') + + clusters_r = "list(" + ", ".join(r_list_elements) + ")" + + r_script = f""" + suppressPackageStartupMessages(library(GOSemSim)) + suppressPackageStartupMessages(library({org_db})) + + hsGO <- godata('{org_db}', ont='{ont}', computeIC=TRUE, keytype='{keytype}') + clusters <- {clusters_r} + sim_matrix <- mclusterSim(clusters, semData=hsGO, measure='{measure}', combine='{combine}') + write.csv(sim_matrix, row.names=TRUE) + """ + + return _execute_r_script(r_script) + +def _execute_r_script(script_content: str): + """ + Internal helper to execute R code via Rscript. + """ + with tempfile.NamedTemporaryFile(mode='w', suffix='.R', delete=False) as tmp: + tmp.write(script_content) + tmp_path = tmp.name + + try: + # Note: We assume Rscript is in the PATH and GOSemSim is installed. + # If using a specific conda environment, the user should run the MCP server within it. + result = subprocess.run( + ["Rscript", tmp_path], + capture_output=True, + text=True, + check=True + ) + + return { + "command_executed": f"Rscript {tmp_path}", + "stdout": result.stdout.strip(), + "stderr": result.stderr.strip(), + "status": "success" + } + except subprocess.CalledProcessError as e: + return { + "command_executed": f"Rscript {tmp_path}", + "stdout": e.stdout, + "stderr": e.stderr, + "error": "R execution failed. Ensure R and GOSemSim are installed and the OrgDb package is available.", + "status": "error" + } + finally: + if Path(tmp_path).exists(): + Path(tmp_path).unlink() + +@mcp.tool() +def list_supported_orgdbs(): + """ + Returns a list of commonly used Bioconductor OrgDb packages for GOSemSim. + """ + org_dbs = { + "human": "org.Hs.eg.db", + "mouse": "org.Mm.eg.db", + "rat": "org.Rn.eg.db", + "fly": "org.Dm.eg.db", + "zebrafish": "org.Dr.eg.db", + "yeast": "org.Sc.sgd.db", + "arabidopsis": "org.At.tair.db", + "chicken": "org.Gg.eg.db", + "bovine": "org.Bt.eg.db", + "worm": "org.Ce.eg.db", + "pig": "org.Ss.eg.db", + "rhesus": "org.Mmu.eg.db" + } + return {"supported_org_dbs": org_dbs} \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gosemsim/app/bioconductor-gosemsim_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gosemsim/app/bioconductor-gosemsim_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..6fe69ca16f4eb0f0c51ade0c53de6bdc8df84fff --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gosemsim/app/bioconductor-gosemsim_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gosemsim/app/bioconductor-gosemsim_server.py') +SERVER_NAME = 'biosci_bioconductor_gosemsim' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gosemsim/app/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gosemsim/app/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gosemsim/app/requirements.txt @@ -0,0 +1 @@ + diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gosemsim/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gosemsim/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..e0264312aed56c58603128d118ddb6f05d42616d --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gosemsim/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-bioconductor-gosemsim: + build: . + image: mcp-bioconductor-gosemsim:latest + container_name: mcp-bioconductor-gosemsim + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=bioconductor-gosemsim + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gosemsim/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gosemsim/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..8f13aa43e05a5c4edac218b82b7b0981931e9030 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gosemsim/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - bioconductor-gosemsim + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gosemsim/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gosemsim/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gosemsim/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gsva/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gsva/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..8ebd79da057998281de6f71ad1cfb659acc1f297 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gsva/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install bioconductor-gsva via conda (e.g., from bioconda) +RUN conda install -c bioconda bioconductor-gsva -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY bioconductor-gsva_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/bioconductor-gsva_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/bioconductor-gsva_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gsva/app/bioconductor-gsva_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gsva/app/bioconductor-gsva_server.py new file mode 100644 index 0000000000000000000000000000000000000000..58fb676f7ac21eb2dc924b9e2f5894575e0aedf5 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gsva/app/bioconductor-gsva_server.py @@ -0,0 +1,207 @@ +import subprocess +import tempfile +from pathlib import Path +from typing import Optional, Literal, List +import sys + +# MCP decorator placeholder, as per the instructions. +class mcp: + @staticmethod + def tool(): + def decorator(func): + return func + return decorator + +@mcp.tool() +def gsva( + expr_file: Path, + gene_sets_file: Path, + output_file: Optional[Path] = None, + method: Literal["gsva", "ssgsea", "zscore", "plage"] = "gsva", + kcdf: Literal["Gaussian", "Poisson", "none"] = "Gaussian", + abs_ranking: bool = False, + min_sz: int = 1, + max_sz: Optional[int] = None, + parallel_sz: int = 1, + mx_diff: bool = True, + tau: float = 1.0, + ssgsea_norm: bool = True, + verbose: bool = True, +) -> dict: + """ + Performs Gene Set Variation Analysis (GSVA) on gene expression data. + + This tool is a wrapper around the `gsva` function from the Bioconductor GSVA package. + It calculates sample-wise gene set enrichment scores as a function of genes inside and + outside the gene set, respectively. The tool requires R and the 'Rscript' + executable to be in the system's PATH. + + Args: + expr_file: Path to the gene expression data file (e.g., TSV, CSV). + The file should have genes as rows and samples as columns. + The first column must contain unique gene identifiers. + gene_sets_file: Path to the gene sets file in GMT format. + output_file: Optional path for the output TSV file. If not provided, a file + named 'gsva_results.tsv' will be created in a temporary directory + and its path will be returned. + method: The GSVA method to use. + kcdf: Character string denoting the kernel to use during the non-parametric + estimation of the cumulative distribution function of expression + levels across samples. 'Gaussian' is recommended for continuous data, + 'Poisson' for integer counts. + abs_ranking: For 'gsva' method, whether to use absolute values of rankings. + min_sz: Minimum size of the gene sets to be considered. + max_sz: Maximum size of the gene sets to be considered. If None, no maximum size is enforced. + parallel_sz: Number of parallel processes to use (cores). + mx_diff: For 'gsva' and 'ssgsea' methods, whether to calculate enrichment scores + as the difference between the largest positive and negative deviations + from the random walk. + tau: Exponent defining the weight of the tail in the random walk score. + Only used for the 'gsva' method. + ssgsea_norm: For 'ssgsea' method, whether to normalize enrichment scores. + verbose: If True, the R script will print progress messages to stdout. + + Returns: + A dictionary containing the command executed, stdout, stderr, and a list of output files. + """ + # --- Input Validation --- + if not expr_file.exists(): + raise FileNotFoundError(f"Expression file not found: {expr_file}") + if not gene_sets_file.exists(): + raise FileNotFoundError(f"Gene sets file not found: {gene_sets_file}") + if min_sz < 0: + raise ValueError("min_sz must be a non-negative integer.") + if max_sz is not None and max_sz < min_sz: + raise ValueError("max_sz must be greater than or equal to min_sz.") + if parallel_sz < 1: + raise ValueError("parallel_sz must be at least 1.") + if tau <= 0 and method == "gsva": + raise ValueError("tau must be a positive number for the 'gsva' method.") + + with tempfile.TemporaryDirectory() as temp_dir: + temp_path = Path(temp_dir) + + # Define output file path + if output_file: + # Ensure output directory exists + output_file.parent.mkdir(parents=True, exist_ok=True) + final_output_path = output_file + else: + final_output_path = temp_path / "gsva_results.tsv" + + r_script_path = temp_path / "run_gsva.R" + + # Convert Python types to R-compatible strings + r_abs_ranking = "TRUE" if abs_ranking else "FALSE" + r_mx_diff = "TRUE" if mx_diff else "FALSE" + r_ssgsea_norm = "TRUE" if ssgsea_norm else "FALSE" + r_verbose = "TRUE" if verbose else "FALSE" + r_max_sz = "Inf" if max_sz is None else str(max_sz) + + # --- R Script Generation --- + r_script_content = f""" + # This script automatically installs required Bioconductor packages. + if (!requireNamespace("BiocManager", quietly = TRUE)) + install.packages("BiocManager", repos="http://cran.us.r-project.org") + + packages <- c("GSVA", "GSEABase") + for (pkg in packages) {{ + if (!require(pkg, character.only = TRUE)) {{ + cat(paste("Installing", pkg, "...\\n")) + BiocManager::install(pkg, update=FALSE, ask=FALSE) + library(pkg, character.only = TRUE) + }} + }} + + # --- Arguments --- + expr_file <- "{expr_file.resolve()}" + gene_sets_file <- "{gene_sets_file.resolve()}" + output_file <- "{final_output_path.resolve()}" + method <- "{method}" + kcdf <- "{kcdf}" + abs_ranking <- {r_abs_ranking} + min_sz <- {min_sz} + max_sz <- {r_max_sz} + parallel_sz <- {parallel_sz} + mx_diff <- {r_mx_diff} + tau <- {tau} + ssgsea_norm <- {r_ssgsea_norm} + verbose <- {r_verbose} + + # --- Data Loading --- + if (verbose) cat("Loading expression data from:", expr_file, "\\n") + # Assuming a standard tab-separated file with a header and row names (gene IDs) + expr_data <- tryCatch({{ + as.matrix(read.table(expr_file, header=TRUE, row.names=1, sep='\\t', check.names=FALSE, quote="")) + }}, error = function(e) {{ + # Try with comma separator if tab fails + if (verbose) cat("Failed to read as TSV, trying CSV...\\n") + as.matrix(read.table(expr_file, header=TRUE, row.names=1, sep=',', check.names=FALSE, quote="")) + }}) + + if (verbose) cat("Loading gene sets from:", gene_sets_file, "\\n") + gene_sets <- getGmt(gene_sets_file) + + # --- Run GSVA --- + if (verbose) cat("Running GSVA with method:", method, "\\n") + gsva_results <- gsva( + expr = expr_data, + gset.idx.list = gene_sets, + method = method, + kcdf = kcdf, + abs.ranking = abs_ranking, + min.sz = min_sz, + max.sz = max_sz, + parallel.sz = parallel_sz, + mx.diff = mx_diff, + tau = tau, + ssgsea.norm = ssgsea_norm, + verbose = verbose + ) + + # --- Save Results --- + if (verbose) cat("Saving results to:", output_file, "\\n") + write.table(gsva_results, file=output_file, sep='\\t', quote=FALSE, col.names=NA) + + if (verbose) cat("GSVA analysis completed successfully.\\n") + """ + + with open(r_script_path, "w") as f: + f.write(r_script_content) + + # --- Subprocess Execution --- + command = ["Rscript", str(r_script_path)] + command_str = " ".join(map(str, command)) + + try: + process = subprocess.run( + command, + capture_output=True, + text=True, + check=True, + cwd=temp_path, + ) + + output_files_list = [str(final_output_path)] if final_output_path.exists() else [] + + return { + "command_executed": command_str, + "stdout": process.stdout, + "stderr": process.stderr, + "output_files": output_files_list, + } + except FileNotFoundError: + # This happens if 'Rscript' is not in the system's PATH + return { + "command_executed": command_str, + "stdout": "", + "stderr": "Error: 'Rscript' command not found. Please ensure R is installed and in your system's PATH.", + "output_files": [], + } + except subprocess.CalledProcessError as e: + return { + "command_executed": command_str, + "stdout": e.stdout, + "stderr": e.stderr, + "output_files": [], + } diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gsva/app/bioconductor-gsva_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gsva/app/bioconductor-gsva_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..8dafc62d85ac13e71d61dc3c4f3314ba10270b03 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gsva/app/bioconductor-gsva_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gsva/app/bioconductor-gsva_server.py') +SERVER_NAME = 'biosci_bioconductor_gsva' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gsva/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gsva/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..b4964f9f87d7439fea449eca0d8b3eb185825066 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gsva/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-bioconductor-gsva: + build: . + image: mcp-bioconductor-gsva:latest + container_name: mcp-bioconductor-gsva + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=bioconductor-gsva + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gsva/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gsva/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..198d9d117bd9b55b6abc459e12bbedf2ab5a8b35 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gsva/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - bioconductor-gsva + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gsva/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gsva/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gsva/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-infercnv/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-infercnv/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..2a7999e32fcac07aa795437e3ed33b833e69b59f --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-infercnv/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install bioconductor-infercnv via conda (e.g., from bioconda) +RUN conda install -c bioconda bioconductor-infercnv -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY bioconductor-infercnv_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/bioconductor-infercnv_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/bioconductor-infercnv_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-infercnv/app/bioconductor-infercnv_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-infercnv/app/bioconductor-infercnv_server.py new file mode 100644 index 0000000000000000000000000000000000000000..8683bd1fa8381f10ed74f5e0bee078ca4e8b0a0d --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-infercnv/app/bioconductor-infercnv_server.py @@ -0,0 +1,290 @@ +import subprocess +import os +from pathlib import Path +from typing import Optional, List +import tempfile +import shlex + +@mcp.tool() +def infercnv_run( + raw_counts_matrix: str, + annotations_file: str, + gene_order_file: str, + out_dir: str, + ref_group_names: Optional[List[str]] = None, + cutoff: float = 1.0, + min_cells_per_gene: int = 3, + cluster_by_groups: bool = True, + denoise: bool = False, + hmm: bool = False, + hmm_type: str = "i6", + analysis_mode: str = "samples", + num_threads: int = 1, + plot_steps: bool = False, + no_plot: bool = False, + window_length: int = 101, + max_centered_threshold: float = 3.0, + leiden_resolution: float = 0.05, +): + """ + Run the full InferCNV pipeline to identify somatic copy number alterations in single-cell RNA-seq data. + + Args: + raw_counts_matrix: Path to the matrix of gene expression counts (genes as rows, cells as columns). + annotations_file: Path to the cell annotations file (cell name and group). + gene_order_file: Path to the gene positions file (gene, chromosome, start, stop). + out_dir: Directory to save the output files. + ref_group_names: List of group names to use as reference (normal) cells. If None, all cells are used. + cutoff: Threshold for gene expression. Use 1.0 for Smart-seq2 and 0.1 for 10x Genomics. + min_cells_per_gene: Minimum number of cells a gene must be expressed in to be kept. + cluster_by_groups: Whether to cluster cells by their annotation groups. + denoise: Whether to apply denoising filters. + hmm: Whether to run the Hidden Markov Model (HMM) to predict CNV states. + hmm_type: Type of HMM to use ('i6' for 6-state model, 'i3' for 3-state model). + analysis_mode: Analysis mode ('samples' or 'subclusters'). + num_threads: Number of CPU threads to use for parallel processing. + plot_steps: Whether to generate plots for every intermediate step. + no_plot: If True, skips the final heatmap generation. + window_length: Length of the moving average window for smoothing. + max_centered_threshold: Maximum value for centering the expression data. + leiden_resolution: Resolution for Leiden clustering if analysis_mode is 'subclusters'. + """ + # Input validation + raw_path = Path(raw_counts_matrix) + ann_path = Path(annotations_file) + gene_path = Path(gene_order_file) + out_path = Path(out_dir) + + if not raw_path.exists(): + return {"error": f"Raw counts matrix not found: {raw_counts_matrix}"} + if not ann_path.exists(): + return {"error": f"Annotations file not found: {annotations_file}"} + if not gene_path.exists(): + return {"error": f"Gene order file not found: {gene_order_file}"} + + if hmm_type not in ["i6", "i3"]: + return {"error": "hmm_type must be either 'i6' or 'i3'"} + + if analysis_mode not in ["samples", "subclusters"]: + return {"error": "analysis_mode must be either 'samples' or 'subclusters'"} + + os.makedirs(out_path, exist_ok=True) + + # Prepare R vector for reference groups + if ref_group_names: + ref_groups_r = "c(" + ", ".join([f"'{g}'" for g in ref_group_names]) + ")" + else: + ref_groups_r = "NULL" + + # Construct R script + r_script_content = f""" +library(infercnv) + +# Create InferCNV Object +infercnv_obj = CreateInfercnvObject( + raw_counts_matrix = "{raw_path.absolute()}", + gene_order_file = "{gene_path.absolute()}", + annotations_file = "{ann_path.absolute()}", + ref_group_names = {ref_groups_r} +) + +# Run InferCNV Pipeline +infercnv_obj = infercnv::run( + infercnv_obj, + cutoff = {cutoff}, + min_cells_per_gene = {min_cells_per_gene}, + out_dir = "{out_path.absolute()}", + cluster_by_groups = {str(cluster_by_groups).upper()}, + denoise = {str(denoise).upper()}, + HMM = {str(hmm).upper()}, + HMM_type = "{hmm_type}", + analysis_mode = "{analysis_mode}", + num_threads = {num_threads}, + plot_steps = {str(plot_steps).upper()}, + no_plot = {str(no_plot).upper()}, + window_length = {window_length}, + max_centered_threshold = {max_centered_threshold}, + leiden_resolution = {leiden_resolution} +) +""" + + try: + with tempfile.NamedTemporaryFile(suffix=".R", mode="w", delete=False) as tmp: + tmp.write(r_script_content) + tmp_path = tmp.name + + cmd = ["Rscript", tmp_path] + result = subprocess.run(cmd, capture_output=True, text=True, check=True) + + # Cleanup temp file + os.unlink(tmp_path) + + # Identify output files + output_files = [str(f) for f in out_path.glob("*") if f.is_file()] + + return { + "command_executed": " ".join(cmd), + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": output_files, + "status": "success" + } + + except subprocess.CalledProcessError as e: + if os.path.exists(tmp_path): + os.unlink(tmp_path) + return { + "command_executed": " ".join(e.cmd), + "stdout": e.stdout, + "stderr": e.stderr, + "error": "InferCNV execution failed." + } + except Exception as e: + return {"error": str(e)} + +@mcp.tool() +def infercnv_plot( + infercnv_obj_path: str, + out_dir: str, + output_filename: str = "infercnv_plot", + color_safe_pal: bool = False, + title: str = "InferCNV Heatmap", + cluster_by_groups: bool = True, + x_center: float = 1.0, + x_range: Optional[float] = None, + custom_color_pal: Optional[List[str]] = None, +): + """ + Generate or regenerate plots from a saved InferCNV object. + + Args: + infercnv_obj_path: Path to the saved .rds or .obj InferCNV object. + out_dir: Directory to save the plot. + output_filename: Name of the output plot file (without extension). + color_safe_pal: Use a color-blind safe palette. + title: Title of the plot. + cluster_by_groups: Whether to cluster by groups in the plot. + x_center: Value to center the color scale on (usually 1.0). + x_range: Range of values to display (e.g., 0.1 means 0.9 to 1.1). + custom_color_pal: Optional list of colors for the heatmap palette. + """ + obj_path = Path(infercnv_obj_path) + out_path = Path(out_dir) + + if not obj_path.exists(): + return {"error": f"InferCNV object not found: {infercnv_obj_path}"} + + os.makedirs(out_path, exist_ok=True) + + x_range_r = f"{x_range}" if x_range is not None else "NULL" + color_pal_r = "NULL" + if custom_color_pal: + color_pal_r = "c(" + ", ".join([f"'{c}'" for c in custom_color_pal]) + ")" + + r_script_content = f""" +library(infercnv) +infercnv_obj = readRDS("{obj_path.absolute()}") + +plot_cnv( + infercnv_obj, + out_dir = "{out_path.absolute()}", + output_filename = "{output_filename}", + color_safe_pal = {str(color_safe_pal).upper()}, + title = "{title}", + cluster_by_groups = {str(cluster_by_groups).upper()}, + x_center = {x_center}, + x_range = {x_range_r}, + custom_color_pal = {color_pal_r} +) +""" + + try: + with tempfile.NamedTemporaryFile(suffix=".R", mode="w", delete=False) as tmp: + tmp.write(r_script_content) + tmp_path = tmp.name + + cmd = ["Rscript", tmp_path] + result = subprocess.run(cmd, capture_output=True, text=True, check=True) + os.unlink(tmp_path) + + return { + "command_executed": " ".join(cmd), + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": [str(f) for f in out_path.glob(f"{output_filename}*")], + "status": "success" + } + + except subprocess.CalledProcessError as e: + if os.path.exists(tmp_path): + os.unlink(tmp_path) + return { + "command_executed": " ".join(e.cmd), + "stdout": e.stdout, + "stderr": e.stderr, + "error": "InferCNV plotting failed." + } + except Exception as e: + return {"error": str(e)} + +@mcp.tool() +def infercnv_filter_genes( + raw_counts_matrix: str, + gene_order_file: str, + output_matrix_path: str, + min_cells_per_gene: int = 3, +): + """ + Pre-filter a counts matrix to remove genes expressed in fewer than a threshold number of cells. + + Args: + raw_counts_matrix: Path to the input counts matrix. + gene_order_file: Path to the gene order file. + output_matrix_path: Path to save the filtered matrix. + min_cells_per_gene: Minimum number of cells a gene must be expressed in. + """ + raw_path = Path(raw_counts_matrix) + gene_path = Path(gene_order_file) + out_path = Path(output_matrix_path) + + if not raw_path.exists(): + return {"error": f"Input matrix not found: {raw_counts_matrix}"} + + r_script_content = f""" +library(infercnv) +# Load data +counts = read.table("{raw_path.absolute()}", header=TRUE, row.names=1, check.names=FALSE) +# Filter +gene_counts = rowSums(counts > 0) +filtered_counts = counts[gene_counts >= {min_cells_per_gene}, ] +# Save +write.table(filtered_counts, file="{out_path.absolute()}", quote=FALSE, sep='\\t') +""" + + try: + with tempfile.NamedTemporaryFile(suffix=".R", mode="w", delete=False) as tmp: + tmp.write(r_script_content) + tmp_path = tmp.name + + cmd = ["Rscript", tmp_path] + result = subprocess.run(cmd, capture_output=True, text=True, check=True) + os.unlink(tmp_path) + + return { + "command_executed": " ".join(cmd), + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": [str(out_path)], + "status": "success" + } + except subprocess.CalledProcessError as e: + if os.path.exists(tmp_path): + os.unlink(tmp_path) + return { + "command_executed": " ".join(e.cmd), + "stdout": e.stdout, + "stderr": e.stderr, + "error": "Filtering failed." + } + except Exception as e: + return {"error": str(e)} \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-infercnv/app/bioconductor-infercnv_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-infercnv/app/bioconductor-infercnv_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..4cca777fad0e4810e65f5dfbf87c581110c5192e --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-infercnv/app/bioconductor-infercnv_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-infercnv/app/bioconductor-infercnv_server.py') +SERVER_NAME = 'biosci_bioconductor_infercnv' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-infercnv/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-infercnv/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..f701e922db8fed281ae7e21356ec9c7d1a54f5e2 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-infercnv/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-bioconductor-infercnv: + build: . + image: mcp-bioconductor-infercnv:latest + container_name: mcp-bioconductor-infercnv + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=bioconductor-infercnv + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-infercnv/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-infercnv/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..3f15fb47aebdab67c6414b91b31d218a96f2e752 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-infercnv/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - bioconductor-infercnv + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-infercnv/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-infercnv/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-infercnv/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-iranges/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-iranges/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..78c8aad093ce7b8c16bd39ced21755f4ca8bea80 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-iranges/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install bioconductor-iranges via conda (e.g., from bioconda) +RUN conda install -c bioconda bioconductor-iranges -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY app/bioconductor-iranges_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/bioconductor-iranges_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/bioconductor-iranges_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-iranges/app/bioconductor-iranges_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-iranges/app/bioconductor-iranges_server.py new file mode 100644 index 0000000000000000000000000000000000000000..c3338fa966c83d7a2aa4f39137514d6cdd3ec6dd --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-iranges/app/bioconductor-iranges_server.py @@ -0,0 +1,284 @@ +import subprocess +import os +from pathlib import Path +from typing import Optional, List, Union + +@mcp.tool() +def iranges_transform( + input_csv: str, + output_csv: str, + operation: str = "shift", + shift_amount: int = 0, + width_amount: int = -1, + side: str = "both", + fix: str = "start" +): + """ + Perform transformations on integer ranges such as shifting, resizing, or flanking. + + Args: + input_csv: Path to input CSV file containing 'start' and 'end' (or 'width') columns. + output_csv: Path where the transformed ranges will be saved. + operation: Transformation to perform: 'shift', 'resize', 'flank', or 'narrow'. + shift_amount: Amount to shift ranges (used if operation is 'shift'). + width_amount: New width or flanking width (used if operation is 'resize' or 'flank'). + side: For 'flank', which side to generate: 'start', 'end', or 'both'. + fix: For 'resize', which part of the range to fix: 'start', 'end', or 'center'. + """ + if not Path(input_csv).exists(): + return {"error": f"Input file {input_csv} not found."} + + valid_ops = ["shift", "resize", "flank", "narrow"] + if operation not in valid_ops: + return {"error": f"Invalid operation. Must be one of {valid_ops}"} + + # Construct R script + r_cmd = f""" + library(IRanges) + df <- read.csv('{input_csv}') + ir <- IRanges(start=df$start, end=df$end) + + if ('{operation}' == 'shift') {{ + res <- shift(ir, shift={shift_amount}) + }} else if ('{operation}' == 'resize') {{ + res <- resize(ir, width={width_amount}, fix='{fix}') + }} else if ('{operation}' == 'flank') {{ + is_both <- if('{side}' == 'both') TRUE else FALSE + res <- flank(ir, width={width_amount}, start=('{side}' == 'start'), both=is_both) + }} else if ('{operation}' == 'narrow') {{ + res <- narrow(ir, start=NA, end=NA, width={width_amount}) + }} + + write.csv(as.data.frame(res), '{output_csv}', row.names=FALSE) + """ + + try: + result = subprocess.run( + ["Rscript", "-e", r_cmd], + check=True, + capture_output=True, + text=True + ) + return { + "command_executed": f"Rscript -e \"{operation} on {input_csv}\"", + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": [output_csv] + } + except subprocess.CalledProcessError as e: + return { + "error": "R execution failed", + "stdout": e.stdout, + "stderr": e.stderr + } + +@mcp.tool() +def iranges_set_operations( + input_csv: str, + output_csv: str, + operation: str = "reduce", + min_gapwidth: int = 1 +): + """ + Perform set-like operations on ranges such as merging overlapping intervals or finding gaps. + + Args: + input_csv: Path to input CSV file containing 'start' and 'end' columns. + output_csv: Path where the resulting ranges will be saved. + operation: Operation to perform: 'reduce' (merge overlapping), 'disjoin' (find elementary ranges), or 'gaps'. + min_gapwidth: Minimum gap width for the 'reduce' operation. + """ + if not Path(input_csv).exists(): + return {"error": f"Input file {input_csv} not found."} + + r_cmd = f""" + library(IRanges) + df <- read.csv('{input_csv}') + ir <- IRanges(start=df$start, end=df$end) + + if ('{operation}' == 'reduce') {{ + res <- reduce(ir, min.gapwidth={min_gapwidth}) + }} else if ('{operation}' == 'disjoin') {{ + res <- disjoin(ir) + }} else if ('{operation}' == 'gaps') {{ + res <- gaps(ir) + }} + + write.csv(as.data.frame(res), '{output_csv}', row.names=FALSE) + """ + + try: + result = subprocess.run( + ["Rscript", "-e", r_cmd], + check=True, + capture_output=True, + text=True + ) + return { + "command_executed": f"Rscript -e \"{operation} on {input_csv}\"", + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": [output_csv] + } + except subprocess.CalledProcessError as e: + return {"error": "R execution failed", "stderr": e.stderr} + +@mcp.tool() +def iranges_overlap_analysis( + query_csv: str, + subject_csv: str, + output_csv: str, + find_overlaps: bool = True, + maxgap: int = -1, + minoverlap: int = 0, + overlap_type: str = "any" +): + """ + Find overlaps or count overlaps between two sets of ranges (Query and Subject). + + Args: + query_csv: CSV file for query ranges. + subject_csv: CSV file for subject ranges. + output_csv: Path to save the overlap mapping (query hits and subject hits). + find_overlaps: If True, returns mapping of hits. If False, returns counts per query. + maxgap: Maximum gap allowed between ranges to be considered overlapping. + minoverlap: Minimum number of overlapping positions. + overlap_type: Type of overlap: 'any', 'start', 'end', 'within', or 'equal'. + """ + if not Path(query_csv).exists() or not Path(subject_csv).exists(): + return {"error": "One or both input files not found."} + + r_cmd = f""" + library(IRanges) + q_df <- read.csv('{query_csv}') + s_df <- read.csv('{subject_csv}') + query <- IRanges(start=q_df$start, end=q_df$end) + subject <- IRanges(start=s_df$start, end=s_df$end) + + if ({str(find_overlaps).upper()}) {{ + hits <- findOverlaps(query, subject, maxgap={maxgap}, minoverlap={minoverlap}, type='{overlap_type}') + res <- as.data.frame(hits) + }} else {{ + counts <- countOverlaps(query, subject, maxgap={maxgap}, minoverlap={minoverlap}, type='{overlap_type}') + res <- data.frame(query_index=1:length(query), overlap_count=counts) + }} + + write.csv(res, '{output_csv}', row.names=FALSE) + """ + + try: + result = subprocess.run( + ["Rscript", "-e", r_cmd], + check=True, + capture_output=True, + text=True + ) + return { + "command_executed": "IRanges::findOverlaps/countOverlaps", + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": [output_csv] + } + except subprocess.CalledProcessError as e: + return {"error": "R execution failed", "stderr": e.stderr} + +@mcp.tool() +def iranges_nearest_methods( + query_csv: str, + subject_csv: str, + output_csv: str, + method: str = "nearest" +): + """ + Find nearest, preceding, or following ranges between query and subject. + + Args: + query_csv: CSV file for query ranges. + subject_csv: CSV file for subject ranges. + output_csv: Path to save the results (mapping of query index to subject index). + method: Method to use: 'nearest', 'precede', or 'follow'. + """ + if not Path(query_csv).exists() or not Path(subject_csv).exists(): + return {"error": "Input files not found."} + + r_cmd = f""" + library(IRanges) + q_df <- read.csv('{query_csv}') + s_df <- read.csv('{subject_csv}') + query <- IRanges(start=q_df$start, end=q_df$end) + subject <- IRanges(start=s_df$start, end=s_df$end) + + if ('{method}' == 'nearest') {{ + idx <- nearest(query, subject) + }} else if ('{method}' == 'precede') {{ + idx <- precede(query, subject) + }} else if ('{method}' == 'follow') {{ + idx <- follow(query, subject) + }} + + res <- data.frame(query_index=1:length(query), subject_index=idx) + write.csv(res, '{output_csv}', row.names=FALSE) + """ + + try: + result = subprocess.run( + ["Rscript", "-e", r_cmd], + check=True, + capture_output=True, + text=True + ) + return { + "command_executed": f"IRanges::{method}", + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": [output_csv] + } + except subprocess.CalledProcessError as e: + return {"error": "R execution failed", "stderr": e.stderr} + +@mcp.tool() +def iranges_coverage( + input_csv: str, + output_csv: str +): + """ + Calculate the coverage (number of ranges covering each integer position). + + Args: + input_csv: Path to input CSV file containing 'start' and 'end' columns. + output_csv: Path to save the coverage data (position and value). + """ + if not Path(input_csv).exists(): + return {"error": f"Input file {input_csv} not found."} + + r_cmd = f""" + library(IRanges) + df <- read.csv('{input_csv}') + ir <- IRanges(start=df$start, end=df$end) + cov <- coverage(ir) + + # Convert Rle to data frame for export + res <- data.frame( + value = as.vector(cov), + width = runLength(cov) + ) + # Expand or keep as run-length encoded? Let's provide a summary-like table + # To keep it simple and usable, we export the Rle components + write.csv(res, '{output_csv}', row.names=FALSE) + """ + + try: + result = subprocess.run( + ["Rscript", "-e", r_cmd], + check=True, + capture_output=True, + text=True + ) + return { + "command_executed": "IRanges::coverage", + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": [output_csv] + } + except subprocess.CalledProcessError as e: + return {"error": "R execution failed", "stderr": e.stderr} \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-iranges/app/bioconductor-iranges_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-iranges/app/bioconductor-iranges_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..75e878ed77b94194fd9f3598675b098ec3f24eec --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-iranges/app/bioconductor-iranges_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-iranges/app/bioconductor-iranges_server.py') +SERVER_NAME = 'biosci_bioconductor_iranges' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-iranges/app/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-iranges/app/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-iranges/app/requirements.txt @@ -0,0 +1 @@ + diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-iranges/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-iranges/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..7a44a8a7f67111158d1ce5c6143cbe40c2b20625 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-iranges/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-bioconductor-iranges: + build: . + image: mcp-bioconductor-iranges:latest + container_name: mcp-bioconductor-iranges + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=bioconductor-iranges + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-iranges/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-iranges/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..e7776983b41417b9ccff7c889b7607cae4724926 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-iranges/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - bioconductor-iranges + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-iranges/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-iranges/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-iranges/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-keggrest/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-keggrest/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..61124c030833e7bfe2a16651cd9cf937150cfeb6 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-keggrest/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install bioconductor-keggrest via conda (e.g., from bioconda) +RUN conda install -c bioconda bioconductor-keggrest -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY app/bioconductor-keggrest_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/bioconductor-keggrest_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/bioconductor-keggrest_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-keggrest/app/bioconductor-keggrest_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-keggrest/app/bioconductor-keggrest_server.py new file mode 100644 index 0000000000000000000000000000000000000000..933724b47d84cd424c63d76e5742b16ebb929caa --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-keggrest/app/bioconductor-keggrest_server.py @@ -0,0 +1,446 @@ +import subprocess +import tempfile +import logging +from pathlib import Path +from typing import List, Optional, Dict, Union + +# Mock decorator for standalone validation. In a real MCP environment, this would be `from mcp import mcp`. +class mcp: + @staticmethod + def tool(func): + # This decorator is a placeholder and doesn't modify the function. + return func + +# Configure logging +logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') +logger = logging.getLogger(__name__) + +def _run_r_script(r_script_content: str, command_name: str) -> Dict[str, Union[str, List[str]]]: + """ + Executes an R script using Rscript and captures its output. + + Args: + r_script_content: A string containing the R code to execute. + command_name: The name of the calling function for logging purposes. + + Returns: + A dictionary containing the executed command, stdout, and stderr. + + Raises: + subprocess.CalledProcessError: If the Rscript command returns a non-zero exit code. + """ + command_str = "" + try: + with tempfile.NamedTemporaryFile(mode='w', suffix=".R", delete=False, encoding='utf-8') as tmp_script: + script_path = Path(tmp_script.name) + tmp_script.write(r_script_content) + + command = ["Rscript", str(script_path)] + command_str = " ".join(command) + logger.info(f"Executing command for {command_name}: {command_str}") + + process = subprocess.run( + command, + capture_output=True, + text=True, + check=True, + encoding='utf-8' + ) + return { + "command_executed": command_str, + "stdout": process.stdout, + "stderr": process.stderr, + } + except FileNotFoundError: + logger.error("Rscript not found. Please ensure R is installed and in the system's PATH.") + raise + finally: + if 'script_path' in locals() and script_path.exists(): + script_path.unlink() + +@mcp.tool +def kegg_info(database: str) -> Dict[str, Union[str, List]]: + """ + Retrieves information about a KEGG database. + + This tool corresponds to the KEGGREST::keggInfo function. It requires an + environment with R and the bioconductor-keggrest package installed. + + Args: + database: The name of the KEGG database (e.g., 'pathway', 'genes', 'compound'). + + Returns: + A dictionary containing the command executed, stdout (database info), and stderr. + """ + if not database: + raise ValueError("The 'database' parameter cannot be empty.") + + r_script = f""" + library(KEGGREST) + tryCatch({{ + info <- keggInfo("{database}") + cat(info) + }}, error = function(e) {{ + stop(e) + }}) + """ + + try: + result = _run_r_script(r_script, "kegg_info") + return { + "command_executed": result["command_executed"], + "stdout": result["stdout"], + "stderr": result["stderr"], + "output_files": [] + } + except subprocess.CalledProcessError as e: + logger.error(f"R script execution failed for kegg_info: {e.stderr}") + return { + "command_executed": e.cmd, + "stdout": e.stdout, + "stderr": e.stderr, + "error": "R script execution failed. Check if the database name is correct and KEGGREST is installed." + } + +@mcp.tool +def kegg_list(database: str, organism: Optional[str] = None) -> Dict[str, Union[str, List]]: + """ + Lists all entries in a KEGG database, optionally for a specific organism. + + This tool corresponds to the KEGGREST::keggList function. It outputs a + two-column TSV (id, description) to stdout. It requires an environment + with R and the bioconductor-keggrest package installed. + + Args: + database: The name of the KEGG database (e.g., 'pathway', 'organism'). + organism: Optional KEGG organism code (e.g., 'hsa' for Homo sapiens). + + Returns: + A dictionary containing the command executed, stdout (TSV list), and stderr. + """ + if not database: + raise ValueError("The 'database' parameter cannot be empty.") + + if organism: + kegg_call = f'keggList("{database}", "{organism}")' + else: + kegg_call = f'keggList("{database}")' + + r_script = f""" + library(KEGGREST) + tryCatch({{ + result_list <- {kegg_call} + if (length(result_list) > 0) {{ + df <- data.frame(id=names(result_list), description=result_list, stringsAsFactors=FALSE) + write.table(df, file=stdout(), sep="\\t", row.names=FALSE, col.names=TRUE, quote=FALSE) + }} else {{ + cat("No entries found.\\n") + }} + }}, error = function(e) {{ + stop(e) + }}) + """ + + try: + result = _run_r_script(r_script, "kegg_list") + return { + "command_executed": result["command_executed"], + "stdout": result["stdout"], + "stderr": result["stderr"], + "output_files": [] + } + except subprocess.CalledProcessError as e: + logger.error(f"R script execution failed for kegg_list: {e.stderr}") + return { + "command_executed": e.cmd, + "stdout": e.stdout, + "stderr": e.stderr, + "error": "R script execution failed. Check parameters and KEGGREST installation." + } + +@mcp.tool +def kegg_find( + database: str, + query: List[str], + option: str = "all" +) -> Dict[str, Union[str, List]]: + """ + Finds entries in a KEGG database by keyword, formula, etc. + + This tool corresponds to the KEGGREST::keggFind function. It outputs a + two-column TSV (id, description) to stdout. It requires an environment + with R and the bioconductor-keggrest package installed. + + Args: + database: The name of the KEGG database to search. + query: A list of keywords to search for. + option: The search option. Must be one of 'all', 'mol_weight', + 'exact_mass', or 'formula'. Defaults to 'all'. + + Returns: + A dictionary containing the command executed, stdout (TSV results), and stderr. + """ + if not database: + raise ValueError("The 'database' parameter cannot be empty.") + if not query: + raise ValueError("The 'query' list cannot be empty.") + + valid_options = {"all", "mol_weight", "exact_mass", "formula"} + if option not in valid_options: + raise ValueError(f"Invalid 'option'. Must be one of {valid_options}.") + + r_query_vector = "c(" + ", ".join(f'"{q}"' for q in query) + ")" + + r_script = f""" + library(KEGGREST) + tryCatch({{ + query_vec <- {r_query_vector} + result_list <- keggFind("{database}", query_vec, option="{option}") + if (length(result_list) > 0) {{ + df <- data.frame(id=names(result_list), description=result_list, stringsAsFactors=FALSE) + write.table(df, file=stdout(), sep="\\t", row.names=FALSE, col.names=TRUE, quote=FALSE) + }} else {{ + cat("No entries found for the given query.\\n") + }} + }}, error = function(e) {{ + stop(e) + }}) + """ + + try: + result = _run_r_script(r_script, "kegg_find") + return { + "command_executed": result["command_executed"], + "stdout": result["stdout"], + "stderr": result["stderr"], + "output_files": [] + } + except subprocess.CalledProcessError as e: + logger.error(f"R script execution failed for kegg_find: {e.stderr}") + return { + "command_executed": e.cmd, + "stdout": e.stdout, + "stderr": e.stderr, + "error": "R script execution failed. Check parameters and KEGGREST installation." + } + +@mcp.tool +def kegg_get( + dbentries: List[str], + option: str = "aaseq", + output_file: Optional[Path] = None +) -> Dict[str, Union[str, List]]: + """ + Retrieves KEGG database entries for a given set of KEGG identifiers. + + This tool corresponds to the KEGGREST::keggGet function. It requires an + environment with R and bioconductor-keggrest. For the 'image' option, + the 'png' R package is also required. + + Args: + dbentries: A list of KEGG identifiers to retrieve. + option: The type of data to retrieve. Must be one of 'aaseq', 'ntseq', + 'mol', 'kcf', 'image', 'kgml'. Defaults to 'aaseq'. + output_file: Optional path to save the output. Required for 'image' option. + If not provided for text options, output is returned in stdout. + + Returns: + A dictionary containing the command executed, stdout, stderr, and output_files. + """ + if not dbentries: + raise ValueError("The 'dbentries' list cannot be empty.") + + valid_options = {"aaseq", "ntseq", "mol", "kcf", "image", "kgml"} + if option not in valid_options: + raise ValueError(f"Invalid 'option'. Must be one of {valid_options}.") + + r_dbentries_vector = "c(" + ", ".join(f'"{d}"' for d in dbentries) + ")" + output_files = [] + + if option == "image": + if len(dbentries) > 1: + raise ValueError("Only one entry can be retrieved at a time for the 'image' option.") + if not output_file: + raise ValueError("The 'output_file' parameter is required for the 'image' option.") + + output_file.parent.mkdir(parents=True, exist_ok=True) + output_files.append(str(output_file)) + + r_script = f""" + if (!requireNamespace("png", quietly = TRUE)) {{ + stop("The 'png' R package is required for the 'image' option. Please install it.") + }} + library(KEGGREST) + library(png) + tryCatch({{ + png_data <- keggGet("{dbentries[0]}", "image") + writePNG(png_data, target="{str(output_file)}") + cat("Image successfully saved to {str(output_file)}\\n") + }}, error = function(e) {{ + stop(e) + }}) + """ + else: + r_script = f""" + library(KEGGREST) + tryCatch({{ + dbentries_vec <- {r_dbentries_vector} + results_list <- keggGet(dbentries_vec, option="{option}") + + if (is.list(results_list)) {{ + for (entry_name in names(results_list)) {{ + cat(paste0(">", entry_name, "\\n")) + content <- paste(results_list[[entry_name]], collapse="\\n") + cat(content) + cat("\\n") + }} + }} else {{ + cat(paste0(">", dbentries_vec[1], "\\n")) + content <- paste(results_list, collapse="\\n") + cat(content) + cat("\\n") + }} + }}, error = function(e) {{ + stop(e) + }}) + """ + + try: + result = _run_r_script(r_script, "kegg_get") + stdout_content = result["stdout"] + + if output_file and option != "image": + output_file.parent.mkdir(parents=True, exist_ok=True) + with open(output_file, "w", encoding='utf-8') as f: + f.write(stdout_content) + output_files.append(str(output_file)) + stdout_content = f"Output successfully saved to {str(output_file)}" + + return { + "command_executed": result["command_executed"], + "stdout": stdout_content, + "stderr": result["stderr"], + "output_files": output_files + } + except subprocess.CalledProcessError as e: + logger.error(f"R script execution failed for kegg_get: {e.stderr}") + return { + "command_executed": e.cmd, + "stdout": e.stdout, + "stderr": e.stderr, + "error": "R script execution failed. Check parameters and KEGGREST installation." + } + +@mcp.tool +def kegg_conv(target_db: str, source_ids: List[str]) -> Dict[str, Union[str, List]]: + """ + Converts KEGG identifiers to/from outside database identifiers. + + This tool corresponds to the KEGGREST::keggConv function. It outputs a + two-column TSV (source_id, target_id) to stdout. It requires an environment + with R and the bioconductor-keggrest package installed. + + Args: + target_db: The target database or organism code (e.g., 'eco', 'ncbi-geneid'). + source_ids: A list of source database identifiers (e.g., ['hsa:10458', 'ece:Z5100']). + + Returns: + A dictionary containing the command executed, stdout (TSV results), and stderr. + """ + if not target_db: + raise ValueError("The 'target_db' parameter cannot be empty.") + if not source_ids: + raise ValueError("The 'source_ids' list cannot be empty.") + + r_source_vector = "c(" + ", ".join(f'"{s}"' for s in source_ids) + ")" + + r_script = f""" + library(KEGGREST) + tryCatch({{ + source_vec <- {r_source_vector} + result_list <- keggConv("{target_db}", source_vec) + if (length(result_list) > 0) {{ + df <- data.frame(source_id=names(result_list), target_id=result_list, stringsAsFactors=FALSE) + write.table(df, file=stdout(), sep="\\t", row.names=FALSE, col.names=TRUE, quote=FALSE) + }} else {{ + cat("No conversion results found.\\n") + }} + }}, error = function(e) {{ + stop(e) + }}) + """ + + try: + result = _run_r_script(r_script, "kegg_conv") + return { + "command_executed": result["command_executed"], + "stdout": result["stdout"], + "stderr": result["stderr"], + "output_files": [] + } + except subprocess.CalledProcessError as e: + logger.error(f"R script execution failed for kegg_conv: {e.stderr}") + return { + "command_executed": e.cmd, + "stdout": e.stdout, + "stderr": e.stderr, + "error": "R script execution failed. Check parameters and KEGGREST installation." + } + +@mcp.tool +def kegg_link(target_db: str, source_db_or_ids: List[str]) -> Dict[str, Union[str, List]]: + """ + Finds related entries by linking two KEGG databases or a set of entries to a database. + + This tool corresponds to the KEGGREST::keggLink function. It outputs a + two-column TSV (source_id, target_id) to stdout. It requires an environment + with R and the bioconductor-keggrest package installed. + + Args: + target_db: The target database (e.g., 'pathway'). + source_db_or_ids: A list containing either a single source database name + (e.g., ['hsa']) or multiple source entry IDs + (e.g., ['hsa:1234', 'hsa:5678']). + + Returns: + A dictionary containing the command executed, stdout (TSV results), and stderr. + """ + if not target_db: + raise ValueError("The 'target_db' parameter cannot be empty.") + if not source_db_or_ids: + raise ValueError("The 'source_db_or_ids' list cannot be empty.") + + r_source_vector = "c(" + ", ".join(f'"{s}"' for s in source_db_or_ids) + ")" + + r_script = f""" + library(KEGGREST) + tryCatch({{ + source_vec <- {r_source_vector} + result_list <- keggLink("{target_db}", source_vec) + if (length(result_list) > 0) {{ + df <- data.frame(source_id=names(result_list), target_id=result_list, stringsAsFactors=FALSE) + write.table(df, file=stdout(), sep="\\t", row.names=FALSE, col.names=TRUE, quote=FALSE) + }} else {{ + cat("No linked entries found.\\n") + }} + }}, error = function(e) {{ + stop(e) + }}) + """ + + try: + result = _run_r_script(r_script, "kegg_link") + return { + "command_executed": result["command_executed"], + "stdout": result["stdout"], + "stderr": result["stderr"], + "output_files": [] + } + except subprocess.CalledProcessError as e: + logger.error(f"R script execution failed for kegg_link: {e.stderr}") + return { + "command_executed": e.cmd, + "stdout": e.stdout, + "stderr": e.stderr, + "error": "R script execution failed. Check parameters and KEGGREST installation." + } \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-keggrest/app/bioconductor-keggrest_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-keggrest/app/bioconductor-keggrest_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..9cbd8c890161c5a58c7c0bb6ab3daac4d9e229b1 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-keggrest/app/bioconductor-keggrest_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-keggrest/app/bioconductor-keggrest_server.py') +SERVER_NAME = 'biosci_bioconductor_keggrest' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-keggrest/app/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-keggrest/app/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-keggrest/app/requirements.txt @@ -0,0 +1 @@ + diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-keggrest/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-keggrest/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..b59215b718958fa8391ccf923a5c42292d83fc55 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-keggrest/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-bioconductor-keggrest: + build: . + image: mcp-bioconductor-keggrest:latest + container_name: mcp-bioconductor-keggrest + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=bioconductor-keggrest + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-keggrest/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-keggrest/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..463bf05c34256a44f7cfa3a9b883412278c134bc --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-keggrest/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - bioconductor-keggrest + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-keggrest/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-keggrest/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-keggrest/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-limma/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-limma/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..525795313103fb6713b9d1f764668bfc4b01ffd9 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-limma/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install bioconductor-limma via conda (e.g., from bioconda) +RUN conda install -c bioconda bioconductor-limma -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY app/bioconductor-limma_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/bioconductor-limma_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/bioconductor-limma_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-limma/app/bioconductor-limma_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-limma/app/bioconductor-limma_server.py new file mode 100644 index 0000000000000000000000000000000000000000..2931e806194ac1e4e7a96f0cbec34f87131c77bb --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-limma/app/bioconductor-limma_server.py @@ -0,0 +1,172 @@ +import subprocess +import tempfile +from pathlib import Path +from typing import Dict + +# The mcp.tool decorator is supplied by the MCP framework. +# It is commented out here to allow for standalone code analysis. +# @mcp.tool() + +def limma_voom_differential_expression( + expression_matrix: Path, + design_matrix: Path, + contrast_matrix: Path, + output_prefix: str = "limma_results", + gene_id_column: str = "GeneID", + normalize_method: str = "quantile", + p_adjust_method: str = "BH", + lfc_threshold: float = 0.0, +) -> Dict: + """ + Performs differential expression analysis using the limma-voom pipeline. + + This tool wraps the common limma workflow for RNA-Seq data. It takes a raw count + matrix, a design matrix specifying the experimental groups, and a contrast + matrix defining the comparisons of interest. It uses voom for mean-variance + modeling, fits linear models, and uses empirical Bayes moderation to find + differentially expressed genes. + + Args: + expression_matrix: Path to the input file with gene expression counts. + Rows should be genes and columns should be samples. + design_matrix: Path to the design matrix file, describing the experimental + design. Rows correspond to samples and columns to coefficients. + contrast_matrix: Path to the contrast matrix file, specifying the comparisons + to be made between the coefficients of the linear model. + output_prefix: Prefix for the output file(s). + gene_id_column: Name of the column in the expression matrix that contains + gene identifiers. + normalize_method: Normalization method to be applied by voom. + Options: "none", "scale", "quantile", "cyclicloess". + p_adjust_method: Method for multiple testing correction. + Options: "holm", "hochberg", "hommel", "bonferroni", + "BH", "BY", "fdr", "none". + lfc_threshold: Log-fold change threshold to test against. A value of 0 tests + for any change. + + Returns: + A dictionary containing the command executed, stdout, stderr, and a + dictionary of output files. + """ + # 1. Input Validation + if not expression_matrix.exists(): + raise FileNotFoundError(f"Expression matrix not found: {expression_matrix}") + if not design_matrix.exists(): + raise FileNotFoundError(f"Design matrix not found: {design_matrix}") + if not contrast_matrix.exists(): + raise FileNotFoundError(f"Contrast matrix not found: {contrast_matrix}") + + allowed_norm_methods = ["none", "scale", "quantile", "cyclicloess"] + if normalize_method not in allowed_norm_methods: + raise ValueError( + f"Invalid normalize_method '{normalize_method}'. " + f"Must be one of {allowed_norm_methods}" + ) + + allowed_padjust_methods = [ + "holm", "hochberg", "hommel", "bonferroni", "BH", "BY", "fdr", "none" + ] + if p_adjust_method not in allowed_padjust_methods: + raise ValueError( + f"Invalid p_adjust_method '{p_adjust_method}'. " + f"Must be one of {allowed_padjust_methods}" + ) + + # 2. Define output file path + output_file = Path(f"{output_prefix}_differential_expression.tsv") + + # 3. Generate R script content + # This script loads data, runs the voom-limma pipeline, and writes results. + r_script_content = f""" + # Ensure limma is installed and loaded + if (!requireNamespace("limma", quietly = TRUE)) {{ + if (!requireNamespace("BiocManager", quietly = TRUE)) + install.packages("BiocManager") + BiocManager::install("limma", update=FALSE, ask=FALSE) + }} + library(limma) + + # --- 1. Load Data --- + # Expression data (counts) + counts <- read.csv("{expression_matrix.resolve()}", row.names="{gene_id_column}", check.names=FALSE) + # Design matrix + design <- as.matrix(read.csv("{design_matrix.resolve()}", row.names=1, check.names=FALSE)) + # Contrast matrix + contrast.matrix <- as.matrix(read.csv("{contrast_matrix.resolve()}", row.names=1, check.names=FALSE)) + + # --- 2. Pre-processing and Voom Transformation --- + # Create DGEList object + dge <- DGEList(counts=counts) + # Filter out lowly expressed genes + keep <- filterByExpr(dge, design) + dge <- dge[keep,,keep.lib.sizes=FALSE] + # Calculate normalization factors + dge <- calcNormFactors(dge) + # Apply voom transformation + v <- voom(dge, design, plot=FALSE, normalize.method="{normalize_method}") + + # --- 3. Linear Model Fitting --- + # Fit the linear model for each gene + fit <- lmFit(v, design) + # Apply the contrast matrix to get the desired comparisons + fit2 <- contrasts.fit(fit, contrast.matrix) + # Apply empirical Bayes moderation + fit2 <- eBayes(fit2) + + # --- 4. Extract and Save Results --- + # Get the top differentially expressed genes for all contrasts + results <- topTable(fit2, adjust.method="{p_adjust_method}", number=Inf, lfc={lfc_threshold}, sort.by="P") + + # Write the results to a file + write.table(results, file="{output_file.resolve()}", sep="\\t", quote=FALSE, row.names=TRUE, col.names=NA) + + cat("Limma-voom analysis complete. Results saved to {output_file.resolve()}\\n") + """ + + # 4. Execute the R script using a temporary file + script_path = None + try: + with tempfile.NamedTemporaryFile( + mode='w', suffix=".R", delete=False + ) as tmp_script: + tmp_script.write(r_script_content) + script_path = tmp_script.name + + cmd = ["Rscript", script_path] + command_executed = " ".join(cmd) + + process = subprocess.run( + cmd, + text=True, + capture_output=True, + check=True + ) + stdout = process.stdout + stderr = process.stderr + + except FileNotFoundError: + raise RuntimeError( + "Rscript not found. Please ensure R is installed and in your system's PATH." + ) + except subprocess.CalledProcessError as e: + error_message = ( + f"R script execution failed with return code {e.returncode}.\n" + f"Command: {e.cmd}\n" + f"Stdout:\n{e.stdout}\n" + f"Stderr:\n{e.stderr}" + ) + raise RuntimeError(error_message) from e + finally: + # Clean up the temporary script file + if script_path and Path(script_path).exists(): + Path(script_path).unlink() + + # 5. Return structured output + return { + "command_executed": command_executed, + "stdout": stdout, + "stderr": stderr, + "output_files": { + "differential_expression_results": str(output_file) + } + } \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-limma/app/bioconductor-limma_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-limma/app/bioconductor-limma_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..f5fc76757aafa6e203112ee4c60fe34fc92c8452 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-limma/app/bioconductor-limma_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-limma/app/bioconductor-limma_server.py') +SERVER_NAME = 'biosci_bioconductor_limma' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-limma/app/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-limma/app/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-limma/app/requirements.txt @@ -0,0 +1 @@ + diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-limma/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-limma/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..29e9a31d1a7db8397f8930371cdcc4af13dd8878 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-limma/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-bioconductor-limma: + build: . + image: mcp-bioconductor-limma:latest + container_name: mcp-bioconductor-limma + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=bioconductor-limma + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-limma/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-limma/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..4dc498b72bbe5cd0bbee0f558f371c3866f3c61d --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-limma/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - bioconductor-limma + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-limma/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-limma/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-limma/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-mosim/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-mosim/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..4e5ae9b6e22413ed1bf33d860c1e348d015a1f58 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-mosim/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install bioconductor-mosim via conda (e.g., from bioconda) +RUN conda install -c bioconda bioconductor-mosim -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY bioconductor-mosim_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/bioconductor-mosim_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/bioconductor-mosim_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-mosim/app/bioconductor-mosim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-mosim/app/bioconductor-mosim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..178f761efc45e22f5d69b71caaef2bd532e7a98f --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-mosim/app/bioconductor-mosim_server.py @@ -0,0 +1,207 @@ +import subprocess +import tempfile +from pathlib import Path +from typing import List, Dict, Any +import logging + +# Set up logging +logging.basicConfig(level=logging.INFO) +log = logging.getLogger(__name__) + +# Per the instructions, the mcp decorator is assumed to be available in the execution environment. +# We define a placeholder here for standalone validation. +class mcp: + @staticmethod + def tool(): + def decorator(f): + return f + return decorator + +@mcp.tool() +def start_simulation( + sim_name: str, + omics_list: List[str], + omics_distributions: List[str], + n_samples: int, + n_features: List[int], + omics_network_file: Path, + prop_causal: float, + prop_shared_causal: float, + output_path: Path, + seed: int = 123, + save_results: bool = True, + verbose: bool = True, +) -> Dict[str, Any]: + """ + Runs a multi-omics simulation using the bioconductor-mosim R package. + + This tool acts as a wrapper around the `mosim::startSimulation` R function. + It requires R, the Rscript executable in the system's PATH, and the + Bioconductor 'mosim' package to be installed in the R environment. + + Args: + sim_name: Name for the simulation. A directory with this name will be created in the output_path. + omics_list: A list of omics types to be simulated (e.g., ["RNA", "protein"]). + omics_distributions: A list of distributions for each omic (e.g., ["NB", "normal"]). Must be the same length as omics_list. + n_samples: The number of samples to simulate. Must be a positive integer. + n_features: A list of the number of features for each omic. Must be the same length as omics_list. + omics_network_file: Path to a CSV file representing the adjacency matrix of the omics network. The first column should contain feature names (row names). + prop_causal: The proportion of causal features. Must be between 0.0 and 1.0. + prop_shared_causal: The proportion of causal features that are shared among omics. Must be between 0.0 and 1.0. + output_path: The directory where the simulation results will be saved. + seed: An integer to be used as the random seed. + save_results: If True, the simulation results will be saved to files. + verbose: If True, the simulation progress will be printed to standard output. + + Returns: + A dictionary containing the executed command, stdout, stderr, and a list of output files. + """ + # --- Input Validation --- + if not sim_name: + raise ValueError("sim_name cannot be empty.") + if not omics_list: + raise ValueError("omics_list cannot be empty.") + if len(omics_list) != len(omics_distributions): + raise ValueError("omics_list and omics_distributions must have the same length.") + if len(omics_list) != len(n_features): + raise ValueError("omics_list and n_features must have the same length.") + if n_samples <= 0: + raise ValueError("n_samples must be a positive integer.") + for n in n_features: + if n <= 0: + raise ValueError("All values in n_features must be positive integers.") + if not (0.0 <= prop_causal <= 1.0): + raise ValueError("prop_causal must be between 0.0 and 1.0.") + if not (0.0 <= prop_shared_causal <= 1.0): + raise ValueError("prop_shared_causal must be between 0.0 and 1.0.") + + if not omics_network_file.is_file(): + raise FileNotFoundError(f"Omics network file not found at: {omics_network_file}") + + # --- File Path Handling --- + try: + output_path.mkdir(parents=True, exist_ok=True) + except OSError as e: + raise OSError(f"Could not create output directory {output_path}: {e}") + + # --- R Script Generation --- + # Convert Python lists to R vector strings, e.g., ["a", "b"] -> 'c("a", "b")' + r_omics_list = 'c(' + ', '.join(f'"{o}"' for o in omics_list) + ')' + r_omics_distributions = 'c(' + ', '.join(f'"{d}"' for d in omics_distributions) + ')' + r_n_features = 'c(' + ', '.join(map(str, n_features)) + ')' + + # Convert Python bool to R TRUE/FALSE + r_save_results = "TRUE" if save_results else "FALSE" + r_verbose = "TRUE" if verbose else "FALSE" + + r_script_content = f""" + # Check if mosim is installed, if not, stop with an error + if (!requireNamespace("mosim", quietly = TRUE)) {{ + stop("The 'mosim' package is not installed. Please install it from Bioconductor.", call. = FALSE) + }} + library(mosim) + + # --- Parameters --- + sim_name_val <- "{sim_name}" + omics_list_val <- {r_omics_list} + omics_distributions_val <- {r_omics_distributions} + n_samples_val <- {n_samples} + n_features_val <- {r_n_features} + omics_network_path <- "{omics_network_file.resolve()}" + prop_causal_val <- {prop_causal} + prop_shared_causal_val <- {prop_shared_causal} + output_path_val <- "{output_path.resolve()}" + seed_val <- {seed} + save_results_val <- {r_save_results} + verbose_val <- {r_verbose} + + # --- Data Loading --- + # Assuming the network file is a CSV with a header and row names in the first column + tryCatch({{ + omics_network_df <- read.csv(omics_network_path, header=TRUE, row.names=1, check.names=FALSE) + }}, error = function(e) {{ + stop(paste("Failed to read omics network file:", e$message), call. = FALSE) + }}) + + # --- Simulation --- + set.seed(seed_val) + + cat("Starting mosim simulation...\\n") + + tryCatch({{ + simulation_results <- mosim::startSimulation( + sim_name = sim_name_val, + omics_list = omics_list_val, + omics_distributions = omics_distributions_val, + n_samples = n_samples_val, + n_features = n_features_val, + omics_network = omics_network_df, + prop_causal = prop_causal_val, + prop_shared_causal = prop_shared_causal_val, + output_path = output_path_val, + seed = seed_val, + save_results = save_results_val, + verbose = verbose_val + ) + }}, error = function(e) {{ + stop(paste("Error during mosim::startSimulation:", e$message), call. = FALSE) + }}) + + cat("Simulation completed successfully.\\n") + """ + + # --- Subprocess Execution --- + command = [] + r_script_path = None + try: + with tempfile.NamedTemporaryFile(mode='w', suffix=".R", delete=False, dir=".") as r_script_file: + r_script_file.write(r_script_content) + r_script_path = Path(r_script_file.name) + + command = ["Rscript", str(r_script_path)] + log.info(f"Executing command: {' '.join(command)}") + + process = subprocess.run( + command, + capture_output=True, + text=True, + check=True + ) + stdout_str = process.stdout + stderr_str = process.stderr + + # --- Collect Output Files --- + output_files = [] + if save_results: + simulation_output_dir = output_path / sim_name + if simulation_output_dir.is_dir(): + output_files = [str(f.resolve()) for f in simulation_output_dir.glob('**/*') if f.is_file()] + else: + log.warning(f"Expected output directory '{simulation_output_dir}' was not created by mosim.") + stderr_str += f"\n[MCP WARNING] Expected output directory '{simulation_output_dir}' was not created by mosim." + + return { + "command_executed": " ".join(command), + "stdout": stdout_str, + "stderr": stderr_str, + "output_files": output_files + } + + except FileNotFoundError: + raise RuntimeError("Rscript not found. Please ensure R is installed and 'Rscript' is in your system's PATH.") + except subprocess.CalledProcessError as e: + log.error(f"R script execution failed with return code {e.returncode}") + log.error(f"STDOUT: {e.stdout}") + log.error(f"STDERR: {e.stderr}") + # Return a structured error response + return { + "command_executed": " ".join(command), + "stdout": e.stdout, + "stderr": e.stderr, + "output_files": [], + "error": f"R script execution failed with return code {e.returncode}. Check stderr for details from R." + } + finally: + # Clean up the temporary R script + if r_script_path and r_script_path.exists(): + r_script_path.unlink() diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-mosim/app/bioconductor-mosim_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-mosim/app/bioconductor-mosim_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..33bbe92d4808d58b90f4d410adaf04b0f73ca958 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-mosim/app/bioconductor-mosim_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-mosim/app/bioconductor-mosim_server.py') +SERVER_NAME = 'biosci_bioconductor_mosim' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-mosim/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-mosim/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..a63563333da7f44cdd4997ed3050fff8fb05f7a7 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-mosim/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-bioconductor-mosim: + build: . + image: mcp-bioconductor-mosim:latest + container_name: mcp-bioconductor-mosim + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=bioconductor-mosim + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-mosim/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-mosim/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..1d19ee09029b7f73facf98be195e04fba8c25a83 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-mosim/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - bioconductor-mosim + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-mosim/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-mosim/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-mosim/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-nebulosa/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-nebulosa/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..791e3c6938d43d81317b2e40924857ae6bb3b39c --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-nebulosa/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-bioconductor-nebulosa: + build: . + image: mcp-bioconductor-nebulosa:latest + container_name: mcp-bioconductor-nebulosa + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=bioconductor-nebulosa + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-nebulosa/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-nebulosa/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-nebulosa/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-org.hs.eg.db/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-org.hs.eg.db/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..4063797cda67f7442fa6031a699b1ed32b5b26f8 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-org.hs.eg.db/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install bioconductor-org.hs.eg.db via conda (e.g., from bioconda) +RUN conda install -c bioconda bioconductor-org.hs.eg.db -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY app/bioconductor-org.hs.eg.db_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/bioconductor-org.hs.eg.db_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/bioconductor-org.hs.eg.db_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-org.hs.eg.db/app/bioconductor-org.hs.eg.db_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-org.hs.eg.db/app/bioconductor-org.hs.eg.db_server.py new file mode 100644 index 0000000000000000000000000000000000000000..98e9cd9bcb0b3cc04ad6fe8b9e8ab574b9d54407 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-org.hs.eg.db/app/bioconductor-org.hs.eg.db_server.py @@ -0,0 +1,187 @@ +import subprocess +import json +import tempfile +from pathlib import Path +from typing import List, Optional, Dict, Any + +def run_r_command(script: str) -> Dict[str, Any]: + """ + Helper function to execute R code and capture output. + Uses jsonlite in R to return structured data. + """ + # Wrap the script to load the library and output JSON + full_script = f""" + suppressPackageStartupMessages(library(org.hs.eg.db)) + suppressPackageStartupMessages(library(jsonlite)) + + tryCatch({{ + {script} + }}, error = function(e) {{ + write(paste("ERROR:", e$message), stderr()) + q(status = 1) + }}) + """ + + with tempfile.NamedTemporaryFile(mode='w', suffix='.R', delete=False) as tmp: + tmp.write(full_script) + tmp_path = tmp.name + + try: + process = subprocess.run( + ["Rscript", tmp_path], + capture_output=True, + text=True, + check=True + ) + return { + "stdout": process.stdout, + "stderr": process.stderr, + "command_executed": f"Rscript {tmp_path}" + } + except subprocess.CalledProcessError as e: + return { + "error": e.stderr or e.stdout, + "command_executed": f"Rscript {tmp_path}", + "stdout": e.stdout, + "stderr": e.stderr + } + finally: + if Path(tmp_path).exists(): + Path(tmp_path).unlink() + +@mcp.tool() +def org_hs_eg_db_select( + keys: List[str], + columns: List[str], + keytype: str = "ENTREZID", +) -> Dict[str, Any]: + """ + Retrieve annotations for the specified keys from the Human (org.hs.eg.db) database. + + Args: + keys: A list of identifiers to look up (e.g., ["7157", "4312"] or ["TP53", "BRCA1"]). + columns: The types of data to retrieve (e.g., ["SYMBOL", "GENENAME", "ENSEMBL"]). + keytype: The type of the input keys (e.g., "ENTREZID", "SYMBOL", "ENSEMBL"). + """ + # Validation + if not keys: + return {"error": "At least one key must be provided."} + if not columns: + return {"error": "At least one column must be provided."} + + # Format R vectors + r_keys = 'c("' + '","'.join(keys) + '")' + r_cols = 'c("' + '","'.join(columns) + '")' + + script = f""" + res <- select(org.hs.eg.db, keys = {r_keys}, columns = {r_cols}, keytype = "{keytype}") + cat(toJSON(res, pretty = TRUE)) + """ + + result = run_r_command(script) + return result + +@mcp.tool() +def org_hs_eg_db_keytypes() -> Dict[str, Any]: + """ + List all available types of identifiers (keytypes) that can be used as input for queries. + Common types include ENTREZID, SYMBOL, ENSEMBL, and UNIPROT. + """ + script = """ + res <- keytypes(org.hs.eg.db) + cat(toJSON(res)) + """ + return run_r_command(script) + +@mcp.tool() +def org_hs_eg_db_columns() -> Dict[str, Any]: + """ + List all available annotation columns that can be retrieved from the database. + """ + script = """ + res <- columns(org.hs.eg.db) + cat(toJSON(res)) + """ + return run_r_command(script) + +@mcp.tool() +def org_hs_eg_db_map_symbol_to_entrez( + symbols: List[str] +) -> Dict[str, Any]: + """ + A convenience tool to quickly map Human Gene Symbols to Entrez IDs. + + Args: + symbols: List of gene symbols (e.g., ["TP53", "APOE"]). + """ + if not symbols: + return {"error": "No symbols provided."} + + r_keys = 'c("' + '","'.join(symbols) + '")' + script = f""" + res <- select(org.hs.eg.db, keys = {r_keys}, columns = c("ENTREZID"), keytype = "SYMBOL") + cat(toJSON(res, pretty = TRUE)) + """ + return run_r_command(script) + +@mcp.tool() +def org_hs_eg_db_get_keys( + keytype: str = "SYMBOL", + pattern: str = "", + limit: int = 100 +) -> Dict[str, Any]: + """ + Retrieve a list of all valid keys of a specific type, optionally filtered by a pattern. + + Args: + keytype: The type of keys to retrieve (e.g., "SYMBOL", "ENSEMBL"). + pattern: A string pattern to filter keys (uses grep-style matching). + limit: Maximum number of keys to return to prevent overwhelming output. + """ + if limit <= 0: + limit = 100 + + script = f""" + all_keys <- keys(org.hs.eg.db, keytype = "{keytype}") + if ("{pattern}" != "") {{ + all_keys <- all_keys[grep("{pattern}", all_keys)] + }} + res <- head(all_keys, {limit}) + cat(toJSON(res)) + """ + return run_r_command(script) + +@mcp.tool() +def org_hs_eg_db_metadata() -> Dict[str, Any]: + """ + Get metadata about the org.hs.eg.db package, including version, organism, and data sources. + """ + script = """ + res <- metadata(org.hs.eg.db) + cat(toJSON(res, pretty = TRUE)) + """ + return run_r_command(script) + +@mcp.tool() +def org_hs_eg_db_map_ids( + ids: List[str], + from_type: str, + to_type: str +) -> Dict[str, Any]: + """ + Generic tool to map identifiers from one type to another. + + Args: + ids: List of input identifiers. + from_type: The source identifier type (e.g., "ENSEMBL"). + to_type: The target identifier type (e.g., "SYMBOL"). + """ + if not ids: + return {"error": "No IDs provided."} + + r_keys = 'c("' + '","'.join(ids) + '")' + script = f""" + res <- select(org.hs.eg.db, keys = {r_keys}, columns = c("{to_type}"), keytype = "{from_type}") + cat(toJSON(res, pretty = TRUE)) + """ + return run_r_command(script) \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-org.hs.eg.db/app/bioconductor-org.hs.eg.db_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-org.hs.eg.db/app/bioconductor-org.hs.eg.db_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..266df6adc735d13db8bcc4915c3392a18657213e --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-org.hs.eg.db/app/bioconductor-org.hs.eg.db_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-org.hs.eg.db/app/bioconductor-org.hs.eg.db_server.py') +SERVER_NAME = 'biosci_bioconductor_org_hs_eg_db' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-org.hs.eg.db/app/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-org.hs.eg.db/app/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-org.hs.eg.db/app/requirements.txt @@ -0,0 +1 @@ + diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-org.hs.eg.db/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-org.hs.eg.db/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..4eb289ab819090371a3aacbde6c3d48a7e26bd78 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-org.hs.eg.db/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-bioconductor-org.hs.eg.db: + build: . + image: mcp-bioconductor-org.hs.eg.db:latest + container_name: mcp-bioconductor-org.hs.eg.db + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=bioconductor-org.hs.eg.db + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-org.hs.eg.db/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-org.hs.eg.db/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..2ddb7785c9c4ce5c193d1ada773c1d53f4a86a89 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-org.hs.eg.db/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - bioconductor-org.hs.eg.db + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-org.hs.eg.db/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-org.hs.eg.db/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-org.hs.eg.db/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-preprocesscore/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-preprocesscore/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..a575fb7871cf3df2022dfe794a043ce28ce6f649 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-preprocesscore/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install bioconductor-preprocesscore via conda (e.g., from bioconda) +RUN conda install -c bioconda bioconductor-preprocesscore -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY app/bioconductor-preprocesscore_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/bioconductor-preprocesscore_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/bioconductor-preprocesscore_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-preprocesscore/app/bioconductor-preprocesscore_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-preprocesscore/app/bioconductor-preprocesscore_server.py new file mode 100644 index 0000000000000000000000000000000000000000..56e0b0e457cc95d644072ef6e2c55b8b53ecab5c --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-preprocesscore/app/bioconductor-preprocesscore_server.py @@ -0,0 +1,332 @@ +import subprocess +import os +from pathlib import Path +from typing import Optional, List +import tempfile + +def run_r_command(script_content: str): + """Helper to execute R code and handle errors.""" + with tempfile.NamedTemporaryFile(mode='w', suffix='.R', delete=False) as tmp: + tmp.write("library(preprocessCore)\n") + tmp.write(script_content) + tmp_path = tmp.name + + try: + result = subprocess.run( + ["Rscript", tmp_path], + capture_output=True, + text=True, + check=True + ) + return result.stdout, result.stderr + except subprocess.CalledProcessError as e: + raise RuntimeError(f"R execution failed: {e.stderr}\nStdout: {e.stdout}") + finally: + if os.path.exists(tmp_path): + os.remove(tmp_path) + +@mcp.tool() +def preprocesscore_normalize_quantiles( + input_file: str, + output_file: str, + keep_names: bool = True, + sep: str = ",", + header: bool = True +): + """ + Perform Quantile Normalization on a numeric matrix. + + Args: + input_file: Path to the input CSV/TSV file containing the matrix. + output_file: Path where the normalized matrix will be saved. + keep_names: Whether to preserve row and column names in the output. + sep: Delimiter used in the input file (e.g., ',' or '\t'). + header: Whether the input file has a header row. + """ + input_path = Path(input_file) + output_path = Path(output_file) + + if not input_path.exists(): + return {"error": f"Input file {input_file} not found."} + + r_script = f""" + data <- as.matrix(read.table("{input_path}", header={str(header).upper()}, sep="{sep}")) + normalized_data <- normalize.quantiles(data, keep.names={str(keep_names).upper()}) + write.table(normalized_data, "{output_path}", sep="{sep}", col.names={str(header).upper()}, row.names=TRUE, quote=FALSE) + """ + + try: + stdout, stderr = run_r_command(r_script) + return { + "command_executed": "normalize.quantiles", + "stdout": stdout, + "stderr": stderr, + "output_files": [str(output_path)] + } + except Exception as e: + return {"error": str(e)} + +@mcp.tool() +def preprocesscore_normalize_quantiles_robust( + input_file: str, + output_file: str, + remove_extreme: str = "both", + n_remove: int = 1, + use_log2: bool = False, + sep: str = ",", + header: bool = True +): + """ + Perform Robust Quantile Normalization. + + Args: + input_file: Path to the input CSV/TSV file. + output_file: Path for the output file. + remove_extreme: How to remove outliers: 'none', 'left', 'right', or 'both'. + n_remove: Number of extreme values to remove. + use_log2: Whether to apply log2 transformation before normalization. + sep: Delimiter used in the input file. + header: Whether the input file has a header row. + """ + input_path = Path(input_file) + output_path = Path(output_file) + + if not input_path.exists(): + return {"error": f"Input file {input_file} not found."} + + if remove_extreme not in ["none", "left", "right", "both"]: + return {"error": "remove_extreme must be one of: none, left, right, both"} + + r_script = f""" + data <- as.matrix(read.table("{input_path}", header={str(header).upper()}, sep="{sep}")) + normalized_data <- normalize.quantiles.robust( + data, + remove.extreme="{remove_extreme}", + n.remove={n_remove}, + use.log2={str(use_log2).upper()} + ) + write.table(normalized_data, "{output_path}", sep="{sep}", col.names={str(header).upper()}, row.names=TRUE, quote=FALSE) + """ + + try: + stdout, stderr = run_r_command(r_script) + return { + "command_executed": "normalize.quantiles.robust", + "stdout": stdout, + "stderr": stderr, + "output_files": [str(output_path)] + } + except Exception as e: + return {"error": str(e)} + +@mcp.tool() +def preprocesscore_background_correct( + input_file: str, + output_file: str, + method: str = "rma", + sep: str = ",", + header: bool = True +): + """ + Perform background correction on a matrix of intensities. + + Args: + input_file: Path to the input CSV/TSV file. + output_file: Path for the output file. + method: Correction method (typically 'rma'). + sep: Delimiter used in the input file. + header: Whether the input file has a header row. + """ + input_path = Path(input_file) + output_path = Path(output_file) + + if not input_path.exists(): + return {"error": f"Input file {input_file} not found."} + + r_script = f""" + data <- as.matrix(read.table("{input_path}", header={str(header).upper()}, sep="{sep}")) + corrected_data <- background.correct(data, method="{method}") + write.table(corrected_data, "{output_path}", sep="{sep}", col.names={str(header).upper()}, row.names=TRUE, quote=FALSE) + """ + + try: + stdout, stderr = run_r_command(r_script) + return { + "command_executed": f"background.correct(method='{method}')", + "stdout": stdout, + "stderr": stderr, + "output_files": [str(output_path)] + } + except Exception as e: + return {"error": str(e)} + +@mcp.tool() +def preprocesscore_sub_col_summarize_median_polish( + input_file: str, + output_file: str, + group_labels: List[int], + sep: str = ",", + header: bool = True +): + """ + Summarize columns of a matrix using Median Polish based on group labels. + + Args: + input_file: Path to the input CSV/TSV file. + output_file: Path for the output file. + group_labels: A list of integers representing the group for each column (e.g., [1, 1, 2, 2]). + sep: Delimiter used in the input file. + header: Whether the input file has a header row. + """ + input_path = Path(input_file) + output_path = Path(output_file) + + if not input_path.exists(): + return {"error": f"Input file {input_file} not found."} + + # Convert Python list to R vector string + r_groups = f"c({','.join(map(str, group_labels))})" + + r_script = f""" + data <- as.matrix(read.table("{input_path}", header={str(header).upper()}, sep="{sep}")) + groups <- as.integer({r_groups}) + summarized <- subColSummarizeMedianPolish(data, groups) + write.table(summarized, "{output_path}", sep="{sep}", col.names=NA, quote=FALSE) + """ + + try: + stdout, stderr = run_r_command(r_script) + return { + "command_executed": "subColSummarizeMedianPolish", + "stdout": stdout, + "stderr": stderr, + "output_files": [str(output_path)] + } + except Exception as e: + return {"error": str(e)} + +@mcp.tool() +def preprocesscore_sub_col_summarize_log_avg( + input_file: str, + output_file: str, + group_labels: List[int], + sep: str = ",", + header: bool = True +): + """ + Summarize columns of a matrix using Log-Average based on group labels. + + Args: + input_file: Path to the input CSV/TSV file. + output_file: Path for the output file. + group_labels: A list of integers representing the group for each column. + """ + input_path = Path(input_file) + output_path = Path(output_file) + + if not input_path.exists(): + return {"error": f"Input file {input_file} not found."} + + r_groups = f"c({','.join(map(str, group_labels))})" + + r_script = f""" + data <- as.matrix(read.table("{input_path}", header={str(header).upper()}, sep="{sep}")) + groups <- as.integer({r_groups}) + summarized <- subColSummarizeLogAvg(data, groups) + write.table(summarized, "{output_path}", sep="{sep}", col.names=NA, quote=FALSE) + """ + + try: + stdout, stderr = run_r_command(r_script) + return { + "command_executed": "subColSummarizeLogAvg", + "stdout": stdout, + "stderr": stderr, + "output_files": [str(output_path)] + } + except Exception as e: + return {"error": str(e)} + +@mcp.tool() +def preprocesscore_sub_col_summarize_log_median( + input_file: str, + output_file: str, + group_labels: List[int], + sep: str = ",", + header: bool = True +): + """ + Summarize columns of a matrix using Log-Median based on group labels. + + Args: + input_file: Path to the input CSV/TSV file. + output_file: Path for the output file. + group_labels: A list of integers representing the group for each column. + """ + input_path = Path(input_file) + output_path = Path(output_file) + + if not input_path.exists(): + return {"error": f"Input file {input_file} not found."} + + r_groups = f"c({','.join(map(str, group_labels))})" + + r_script = f""" + data <- as.matrix(read.table("{input_path}", header={str(header).upper()}, sep="{sep}")) + groups <- as.integer({r_groups}) + summarized <- subColSummarizeLogMedian(data, groups) + write.table(summarized, "{output_path}", sep="{sep}", col.names=NA, quote=FALSE) + """ + + try: + stdout, stderr = run_r_command(r_script) + return { + "command_executed": "subColSummarizeLogMedian", + "stdout": stdout, + "stderr": stderr, + "output_files": [str(output_path)] + } + except Exception as e: + return {"error": str(e)} + +@mcp.tool() +def preprocesscore_sub_col_summarize_biweight_midavg( + input_file: str, + output_file: str, + group_labels: List[int], + sep: str = ",", + header: bool = True +): + """ + Summarize columns of a matrix using Biweight Mid-average based on group labels. + + Args: + input_file: Path to the input CSV/TSV file. + output_file: Path for the output file. + group_labels: A list of integers representing the group for each column. + """ + input_path = Path(input_file) + output_path = Path(output_file) + + if not input_path.exists(): + return {"error": f"Input file {input_file} not found."} + + r_groups = f"c({','.join(map(str, group_labels))})" + + r_script = f""" + data <- as.matrix(read.table("{input_path}", header={str(header).upper()}, sep="{sep}")) + groups <- as.integer({r_groups}) + summarized <- subColSummarizeBiweightMidavg(data, groups) + write.table(summarized, "{output_path}", sep="{sep}", col.names=NA, quote=FALSE) + """ + + try: + stdout, stderr = run_r_command(r_script) + return { + "command_executed": "subColSummarizeBiweightMidavg", + "stdout": stdout, + "stderr": stderr, + "output_files": [str(output_path)] + } + except Exception as e: + return {"error": str(e)} \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-preprocesscore/app/bioconductor-preprocesscore_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-preprocesscore/app/bioconductor-preprocesscore_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..207ac82a8dd22712c0b714d90a5b3a08bfbed251 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-preprocesscore/app/bioconductor-preprocesscore_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-preprocesscore/app/bioconductor-preprocesscore_server.py') +SERVER_NAME = 'biosci_bioconductor_preprocesscore' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-preprocesscore/app/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-preprocesscore/app/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-preprocesscore/app/requirements.txt @@ -0,0 +1 @@ + diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-preprocesscore/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-preprocesscore/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..e344031a5676f11d324f8a07e7dbcf4341d74455 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-preprocesscore/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-bioconductor-preprocesscore: + build: . + image: mcp-bioconductor-preprocesscore:latest + container_name: mcp-bioconductor-preprocesscore + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=bioconductor-preprocesscore + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-preprocesscore/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-preprocesscore/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..9a3892f6e80633f97fad970e2fc73523e6b13dc8 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-preprocesscore/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - bioconductor-preprocesscore + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-preprocesscore/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-preprocesscore/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-preprocesscore/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-proteomicsannotationhubdata/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-proteomicsannotationhubdata/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..adbf3ebc54fccef2f2bf508538755a4d5a89b24e --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-proteomicsannotationhubdata/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install bioconductor-proteomicsannotationhubdata via conda (e.g., from bioconda) +RUN conda install -c bioconda bioconductor-proteomicsannotationhubdata -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY bioconductor-proteomicsannotationhubdata_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/bioconductor-proteomicsannotationhubdata_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/bioconductor-proteomicsannotationhubdata_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-proteomicsannotationhubdata/app/bioconductor-proteomicsannotationhubdata_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-proteomicsannotationhubdata/app/bioconductor-proteomicsannotationhubdata_server.py new file mode 100644 index 0000000000000000000000000000000000000000..90b31cb06cbc02c8ee3218b223749aa9db7f4913 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-proteomicsannotationhubdata/app/bioconductor-proteomicsannotationhubdata_server.py @@ -0,0 +1,120 @@ +import subprocess +from pathlib import Path +from typing import Optional, List, Dict, Any + +# MCP decorator placeholder +def tool(func): + """A dummy decorator to stand in for the real mcp.tool decorator.""" + return func + +mcp = type('mcp', (), {'tool': tool}) + +@mcp.tool +def proteomicsannotationhubdata_rscript( + script_file: Optional[Path] = None, + expressions: Optional[List[str]] = None, + verbose: bool = False, + default_packages: Optional[str] = None, + save: bool = False, + no_environ: bool = False, + no_site_file: bool = False, + no_init_file: bool = False, + restore: bool = False, + vanilla: bool = False, + script_args: Optional[List[str]] = None, +) -> Dict[str, Any]: + """ + Executes an R script using the Rscript command-line interface. + + This tool serves as a generic wrapper for Rscript, enabling the execution of R code + that can leverage Bioconductor packages like proteomicsannotationhubdata. + It allows running R code from a file or directly from string expressions. + + Args: + script_file: Path to the R script file to be executed. Mutually exclusive with 'expressions'. + expressions: A list of R expressions to execute. Mutually exclusive with 'script_file'. + verbose: If True, enables verbose output, printing information on progress (--verbose). + default_packages: A comma-separated list of packages to load by default (e.g., "utils,graphics"). + save: If True, the workspace will be saved at the end of the session (--save). + no_environ: If True, site and user environment files will not be read (--no-environ). + no_site_file: If True, the site-wide Rprofile will not be read (--no-site-file). + no_init_file: If True, the user's R profile will not be read (--no-init-file). + restore: If True, previously saved objects will be restored at startup (--restore). + vanilla: If True, combines --no-save, --no-restore, --no-site-file, --no-init-file, and --no-environ. + script_args: A list of arguments to be passed to the R script itself. + + Returns: + A dictionary containing the executed command, stdout, stderr, and a list of output files. + Note: This wrapper cannot automatically detect output files generated by the R script. + """ + # 1. Input Validation + if script_file and expressions: + raise ValueError("Cannot specify both 'script_file' and 'expressions'. They are mutually exclusive.") + if not script_file and not expressions: + raise ValueError("Must specify either 'script_file' or 'expressions' to execute.") + + if script_file: + if not script_file.is_file(): + raise FileNotFoundError(f"The specified script file does not exist: {script_file}") + + # 2. Command Construction + command = ["Rscript"] + + if verbose: + command.append("--verbose") + if default_packages: + command.extend(["--default-packages", default_packages]) + if save: + command.append("--save") + if no_environ: + command.append("--no-environ") + if no_site_file: + command.append("--no-site-file") + if no_init_file: + command.append("--no-init-file") + if restore: + command.append("--restore") + if vanilla: + command.append("--vanilla") + + if expressions: + for expr in expressions: + command.extend(["-e", expr]) + elif script_file: + command.append(str(script_file)) + + if script_args: + command.extend(script_args) + + command_str = " ".join(command) + + # 3. Subprocess Execution and Error Handling + try: + result = subprocess.run( + command, + check=True, + capture_output=True, + text=True, + ) + return { + "command_executed": command_str, + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": [] + } + except FileNotFoundError: + # This error occurs if 'Rscript' is not in the system's PATH + return { + "command_executed": command_str, + "stdout": "", + "stderr": "Error: 'Rscript' command not found. Make sure R is installed and in your system's PATH.", + "output_files": [] + } + except subprocess.CalledProcessError as e: + # This error occurs if the R script returns a non-zero exit code + return { + "command_executed": command_str, + "stdout": e.stdout or "", + "stderr": e.stderr or "", + "output_files": [] + } \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-proteomicsannotationhubdata/app/bioconductor-proteomicsannotationhubdata_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-proteomicsannotationhubdata/app/bioconductor-proteomicsannotationhubdata_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..dae826bd202cfc587302172994341cb964750257 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-proteomicsannotationhubdata/app/bioconductor-proteomicsannotationhubdata_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-proteomicsannotationhubdata/app/bioconductor-proteomicsannotationhubdata_server.py') +SERVER_NAME = 'biosci_bioconductor_proteomicsannotationhubdata' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-proteomicsannotationhubdata/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-proteomicsannotationhubdata/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..b8ac5970dd6840a7998007627da87e4f60be9c51 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-proteomicsannotationhubdata/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-bioconductor-proteomicsannotationhubdata: + build: . + image: mcp-bioconductor-proteomicsannotationhubdata:latest + container_name: mcp-bioconductor-proteomicsannotationhubdata + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=bioconductor-proteomicsannotationhubdata + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-proteomicsannotationhubdata/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-proteomicsannotationhubdata/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..ac7f8e4fe821d39719f5a0a64a7123c5d0691d97 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-proteomicsannotationhubdata/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - bioconductor-proteomicsannotationhubdata + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-proteomicsannotationhubdata/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-proteomicsannotationhubdata/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-proteomicsannotationhubdata/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-protgenerics/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-protgenerics/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..3f2bf309ffe7ffbc844c764b6d238665b9b9f7d6 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-protgenerics/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install bioconductor-protgenerics via conda (e.g., from bioconda) +RUN conda install -c bioconda bioconductor-protgenerics -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY app/bioconductor-protgenerics_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/bioconductor-protgenerics_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/bioconductor-protgenerics_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-protgenerics/app/bioconductor-protgenerics_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-protgenerics/app/bioconductor-protgenerics_server.py new file mode 100644 index 0000000000000000000000000000000000000000..66bf7a1b0ec4d3de2a87d88e5dd02a170b925a2a --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-protgenerics/app/bioconductor-protgenerics_server.py @@ -0,0 +1,85 @@ +import subprocess +from pathlib import Path +from typing import List, Optional +import mcp + +@mcp.tool( + name="protgenerics_run_r_script", + description="Executes a user-provided R script in an environment with bioconductor-protgenerics." +) +def run_r_script( + script_path: Path, + args: Optional[List[str]] = None, +) -> dict: + """ + Executes a given R script using the 'Rscript' command. + + This tool serves as a generic executor for R scripts within an environment + where the 'bioconductor-protgenerics' package is expected to be available. + The 'bioconductor-protgenerics' package itself does not provide a direct + command-line interface; it is a library of S4 generic functions for + proteomics analysis, intended to be used within R scripts by other packages. + + Therefore, instead of wrapping non-existent subcommands, this tool allows + you to run your own R script that utilizes the functionality provided by + 'bioconductor-protgenerics' or packages that depend on it. + + Args: + script_path: Path to the R script to be executed. + args: A list of optional command-line arguments to pass to the R script. + + Returns: + A dictionary containing the execution details, including the command, + stdout, stderr, and return code. + """ + # 1. Input validation + if not script_path.is_file(): + raise FileNotFoundError(f"The specified R script was not found: {script_path}") + + if args is None: + args = [] + + # 2. Command construction + command = ["Rscript", str(script_path)] + args + command_str = " ".join(command) + + # 3. Subprocess execution and error handling + try: + process = subprocess.run( + command, + capture_output=True, + text=True, + check=True, + encoding='utf-8' + ) + stdout = process.stdout + stderr = process.stderr + return_code = process.returncode + + except FileNotFoundError: + # This error occurs if 'Rscript' is not in the system's PATH + return { + "command_executed": command_str, + "stdout": "", + "stderr": "Error: 'Rscript' command not found. Please ensure R is installed and in your system's PATH.", + "return_code": -1, + "output_files": [] + } + except subprocess.CalledProcessError as e: + # This error occurs if the R script itself fails (returns a non-zero exit code) + return { + "command_executed": command_str, + "stdout": e.stdout, + "stderr": e.stderr, + "return_code": e.returncode, + "output_files": [] + } + + # 4. Structured result return + return { + "command_executed": command_str, + "stdout": stdout, + "stderr": stderr, + "return_code": return_code, + "output_files": [] # Output files must be managed by the R script itself and their paths known beforehand. + } \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-protgenerics/app/bioconductor-protgenerics_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-protgenerics/app/bioconductor-protgenerics_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..11e0736926fce52850e0a15bd7828269749d3d45 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-protgenerics/app/bioconductor-protgenerics_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-protgenerics/app/bioconductor-protgenerics_server.py') +SERVER_NAME = 'biosci_bioconductor_protgenerics' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-protgenerics/app/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-protgenerics/app/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..47e13413587e0d6524543a5a4c25700d07c47e08 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-protgenerics/app/requirements.txt @@ -0,0 +1 @@ +mcp==1.27.0 diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-protgenerics/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-protgenerics/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..8e1d8d8096c32ba24e5823365e99b8573189e31a --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-protgenerics/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-bioconductor-protgenerics: + build: . + image: mcp-bioconductor-protgenerics:latest + container_name: mcp-bioconductor-protgenerics + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=bioconductor-protgenerics + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-protgenerics/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-protgenerics/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d17c7b69d3b821e749569b909c88ec485482063c --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-protgenerics/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - bioconductor-protgenerics + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-protgenerics/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-protgenerics/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..062b47df16d08f6173721af25952519f73dfcafa --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-protgenerics/requirements.txt @@ -0,0 +1,3 @@ +mcp==1.27.0 +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rforproteomics/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rforproteomics/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..0490536356ac972684113e03f94ef6e5a5ed5edb --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rforproteomics/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install bioconductor-rforproteomics via conda (e.g., from bioconda) +RUN conda install -c bioconda bioconductor-rforproteomics -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY bioconductor-rforproteomics_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/bioconductor-rforproteomics_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/bioconductor-rforproteomics_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rforproteomics/app/bioconductor-rforproteomics_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rforproteomics/app/bioconductor-rforproteomics_server.py new file mode 100644 index 0000000000000000000000000000000000000000..11851eb51bc71813affd06c1385fe37f7a179070 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rforproteomics/app/bioconductor-rforproteomics_server.py @@ -0,0 +1,140 @@ +import subprocess +import logging +from pathlib import Path +from typing import Optional, List, Dict, Any + +# MCP decorator is assumed to be available in the execution environment. +# +# @mcp.tool +# def rscript(...): +# ... + +def _mcp_tool_dummy_decorator(func): + """A dummy decorator to allow the code to be syntactically valid.""" + return func + +# In a real MCP environment, the @mcp.tool decorator would be provided. +# For this example, we use a dummy decorator. +mcp = type('mcp', (), {'tool': staticmethod(_mcp_tool_dummy_decorator)}) + + +@mcp.tool +def rscript( + file: Optional[Path] = None, + expressions: Optional[List[str]] = None, + script_args: Optional[List[str]] = None, + verbose: bool = False, + default_packages: Optional[str] = None, + save: bool = False, + no_environ: bool = False, + no_site_file: bool = False, + no_init_file: bool = False, + restore: bool = False, + vanilla: bool = False, +) -> Dict[str, Any]: + """ + Executes an R script or R expressions using the Rscript command-line tool. + + This tool serves as a wrapper for the Rscript utility, allowing for the execution + of R code from a file or directly from string expressions. It supports various + options to control the R session's environment and behavior. Note that either + 'file' or 'expressions' must be provided, but not both. + + Args: + file: Path to the R script file to be executed. Mutually exclusive with 'expressions'. + expressions: A list of R expressions to be executed. Mutually exclusive with 'file'. + script_args: A list of arguments to be passed to the R script itself. + verbose: If True, enables verbose output, printing information on progress. Corresponds to --verbose. + default_packages: A comma-separated list of package names to be loaded by default (e.g., "utils,graphics"). + Corresponds to --default-packages. + save: If True, saves the workspace at the end of the session. Corresponds to --save. + no_environ: If True, prevents reading of site and user environment files. Corresponds to --no-environ. + no_site_file: If True, prevents reading of the site-wide Rprofile. Corresponds to --no-site-file. + no_init_file: If True, prevents reading of the user R profile. Corresponds to --no-init-file. + restore: If True, restores previously saved objects at startup. Corresponds to --restore. + vanilla: If True, combines --no-save, --no-restore, --no-site-file, --no-init-file, and --no-environ. + Corresponds to --vanilla. + + Returns: + A dictionary containing the executed command, stdout, stderr, and a list of output files. + Since Rscript does not have a dedicated output file parameter, 'output_files' will be empty. + """ + # 1. Input Validation + if not file and not expressions: + raise ValueError("Either 'file' or 'expressions' must be provided.") + if file and expressions: + raise ValueError("'file' and 'expressions' are mutually exclusive and cannot be used together.") + if file: + if not file.is_file(): + raise FileNotFoundError(f"The specified script file does not exist: {file}") + + # 2. Command Construction + cmd = ["Rscript"] + + if verbose: + cmd.append("--verbose") + if default_packages: + cmd.extend(["--default-packages", default_packages]) + if save: + cmd.append("--save") + if no_environ: + cmd.append("--no-environ") + if no_site_file: + cmd.append("--no-site-file") + if no_init_file: + cmd.append("--no-init-file") + if restore: + cmd.append("--restore") + if vanilla: + cmd.append("--vanilla") + + if expressions: + for expr in expressions: + cmd.extend(["-e", expr]) + elif file: + cmd.append(str(file)) + + if script_args: + cmd.extend(script_args) + + command_executed = " ".join(cmd) + logging.info(f"Executing command: {command_executed}") + + # 3. Subprocess Execution + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + ) + stdout = result.stdout + stderr = result.stderr + except FileNotFoundError: + error_message = "Error: 'Rscript' command not found. Please ensure R is installed and accessible in the system's PATH." + logging.error(error_message) + # This is a critical configuration error, so we return a structured error + return { + "command_executed": command_executed, + "stdout": "", + "stderr": error_message, + "output_files": [] + } + except subprocess.CalledProcessError as e: + logging.error(f"Rscript execution failed with exit code {e.returncode}") + return { + "command_executed": command_executed, + "stdout": e.stdout, + "stderr": e.stderr, + "output_files": [] + } + + # 4. Structured Result Return + # Rscript does not have a defined output file parameter. Any files created + # are determined by the script's own logic. + return { + "command_executed": command_executed, + "stdout": stdout, + "stderr": stderr, + "output_files": [] + } \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rforproteomics/app/bioconductor-rforproteomics_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rforproteomics/app/bioconductor-rforproteomics_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..6983bd35269d523f5a5199a49f1afe547f96af05 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rforproteomics/app/bioconductor-rforproteomics_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rforproteomics/app/bioconductor-rforproteomics_server.py') +SERVER_NAME = 'biosci_bioconductor_rforproteomics' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rforproteomics/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rforproteomics/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..8777e2825f2c61ac247216ca6df83d0b77132802 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rforproteomics/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-bioconductor-rforproteomics: + build: . + image: mcp-bioconductor-rforproteomics:latest + container_name: mcp-bioconductor-rforproteomics + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=bioconductor-rforproteomics + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rforproteomics/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rforproteomics/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..add6d6abe9185029b539778ee50f8561cb2dbfcc --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rforproteomics/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - bioconductor-rforproteomics + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rforproteomics/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rforproteomics/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rforproteomics/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhdf5/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhdf5/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..23b2b83e0e1daf22cc0c286cbebf06a5f2214728 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhdf5/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install bioconductor-rhdf5 via conda (e.g., from bioconda) +RUN conda install -c bioconda bioconductor-rhdf5 -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY app/bioconductor-rhdf5_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/bioconductor-rhdf5_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/bioconductor-rhdf5_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhdf5/app/bioconductor-rhdf5_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhdf5/app/bioconductor-rhdf5_server.py new file mode 100644 index 0000000000000000000000000000000000000000..cc30a312df2d214c7c9088bf9411aa990f01c819 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhdf5/app/bioconductor-rhdf5_server.py @@ -0,0 +1,184 @@ +import subprocess +import tempfile +from pathlib import Path +from typing import Optional, List, Dict, Any + +# Note: The 'mcp' import is omitted as per instructions, but @mcp.tool() is used. + +def _check_rscript_available() -> None: + """Checks if Rscript is available in the system's PATH.""" + try: + subprocess.run(["Rscript", "--version"], check=True, capture_output=True, text=True) + except FileNotFoundError: + raise RuntimeError( + "Rscript command not found. Please ensure R is installed and Rscript is in your system's PATH." + ) + except subprocess.CalledProcessError as e: + raise RuntimeError( + f"Rscript command found but returned an error: {e.stderr.strip()}" + ) + except Exception as e: + raise RuntimeError(f"An unexpected error occurred while checking Rscript: {e}") + +@mcp.tool() +def run_rhdf5_r_script( + r_script_content: str, + input_files: Optional[List[Path]] = None, + output_dir: Optional[Path] = None, + r_args: Optional[List[str]] = None, + verbose: bool = False, +) -> Dict[str, Any]: + """ + Executes an R script that can utilize the bioconductor-rhdf5 package. + + Note: bioconductor-rhdf5 is an R package, not a standalone command-line tool. + This MCP tool provides a mechanism to run arbitrary R scripts that use rhdf5 + by executing them via the 'Rscript' command-line utility. + Users are expected to provide the R script content directly, ensuring it + includes `library(rhdf5)` and performs the desired HDF5 operations. + + Args: + r_script_content: A string containing the R script to be executed. + This script should include `library(rhdf5)` and + perform the desired HDF5 operations. + input_files: An optional list of Path objects pointing to input files + that the R script might need. These files will be symlinked + into the working directory where the R script is executed, + making them accessible by their base names. + output_dir: An optional Path object specifying the directory where + the R script should write its output files. If not provided, + a temporary directory will be created for outputs. + r_args: Optional list of additional arguments to pass to Rscript. + These arguments will be available in the R script via `commandArgs(trailingOnly=TRUE)`. + verbose: If True, Rscript will print verbose output during execution. + + Returns: + A dictionary containing execution details: + - command_executed: The full command string executed. + - stdout: Standard output from the Rscript execution. + - stderr: Standard error from the Rscript execution. + - output_files: A list of Path objects for any files found in the output directory. + - error: Optional error message if the Rscript execution fails. + """ + _check_rscript_available() + + if not r_script_content or not r_script_content.strip(): + raise ValueError("R script content cannot be empty.") + + # Validate input files + if input_files: + for f in input_files: + if not isinstance(f, Path): + raise TypeError(f"Input file path must be a Path object, got {type(f)}") + if not f.is_file(): + raise FileNotFoundError(f"Input file not found: {f}") + + # Prepare output directory + temp_output_dir_obj: Optional[tempfile.TemporaryDirectory] = None + if output_dir: + if not isinstance(output_dir, Path): + raise TypeError(f"Output directory path must be a Path object, got {type(output_dir)}") + output_dir.mkdir(parents=True, exist_ok=True) + else: + temp_output_dir_obj = tempfile.TemporaryDirectory() + output_dir = Path(temp_output_dir_obj.name) + + temp_r_script_path: Optional[Path] = None + stdout_data = "" + stderr_data = "" + output_files_list: List[Path] = [] + error_message: Optional[str] = None + command_executed_str = "" + + try: + # Write the R script content to a temporary file + with tempfile.NamedTemporaryFile(mode="w", delete=False, suffix=".R", encoding="utf-8") as temp_r_script_file: + temp_r_script_file.write(r_script_content) + temp_r_script_path = Path(temp_r_script_file.name) + + command = ["Rscript"] + if verbose: + command.append("--verbose") + command.append(str(temp_r_script_path)) + + if r_args: + if not isinstance(r_args, list) or not all(isinstance(arg, str) for arg in r_args): + raise TypeError("r_args must be a list of strings.") + command.extend(r_args) + + command_executed_str = " ".join(command) + + # Create symlinks for input files in the output directory + # This makes them easily accessible by their base name from the R script + for f in (input_files or []): + target_path = output_dir / f.name + if not target_path.exists(): # Avoid overwriting existing files or symlinks + try: + target_path.symlink_to(f.resolve()) # Use resolve() for absolute path + except OSError as e: + # Handle cases where symlinking might not be supported or fails + # Fallback to copying if symlink fails, or just log a warning + print(f"Warning: Could not symlink {f} to {target_path}. Error: {e}") + # Optionally, copy the file instead: + # import shutil + # shutil.copy(f, target_path) + + process = subprocess.run( + command, + cwd=output_dir, # Execute Rscript in the output directory + check=True, + capture_output=True, + text=True, + encoding="utf-8", + ) + stdout_data = process.stdout + stderr_data = process.stderr + + # Collect output files from the output directory + # Exclude the temporary R script and any symlinked input files + for f in output_dir.iterdir(): + if f.is_file() and f != temp_r_script_path and (input_files is None or f not in [output_dir / i.name for i in input_files]): + output_files_list.append(f) + + except FileNotFoundError: + error_message = "Rscript command not found. Please ensure R is installed and Rscript is in your system's PATH." + stderr_data = error_message + except subprocess.CalledProcessError as e: + error_message = f"Rscript execution failed with exit code {e.returncode}." + stdout_data = e.stdout + stderr_data = e.stderr + except ValueError as e: + error_message = f"Input validation error: {e}" + stderr_data = str(e) + except TypeError as e: + error_message = f"Type error: {e}" + stderr_data = str(e) + except Exception as e: + error_message = f"An unexpected error occurred: {e}" + stderr_data = str(e) + finally: + # Clean up the temporary R script file + if temp_r_script_path and temp_r_script_path.exists(): + try: + temp_r_script_path.unlink() + except OSError as e: + print(f"Warning: Failed to delete temporary R script {temp_r_script_path}: {e}") + + # Clean up temporary output directory if it was created by the tool + if temp_output_dir_obj: + try: + temp_output_dir_obj.cleanup() + except Exception as e: + # Log cleanup error if necessary, but don't fail the tool + print(f"Warning: Failed to clean up temporary directory {temp_output_dir_obj.name}: {e}") + + result = { + "command_executed": command_executed_str, + "stdout": stdout_data, + "stderr": stderr_data, + "output_files": [str(f) for f in output_files_list], + } + if error_message: + result["error"] = error_message + + return result \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhdf5/app/bioconductor-rhdf5_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhdf5/app/bioconductor-rhdf5_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..fcc45627e94f1a5956122356fc518493a9dce1d2 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhdf5/app/bioconductor-rhdf5_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhdf5/app/bioconductor-rhdf5_server.py') +SERVER_NAME = 'biosci_bioconductor_rhdf5' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhdf5/app/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhdf5/app/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhdf5/app/requirements.txt @@ -0,0 +1 @@ + diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhdf5/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhdf5/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..371502a90b6b0e642754aebfdcfbed6956a61c7d --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhdf5/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-bioconductor-rhdf5: + build: . + image: mcp-bioconductor-rhdf5:latest + container_name: mcp-bioconductor-rhdf5 + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=bioconductor-rhdf5 + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhdf5/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhdf5/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..5cee49d16e0b5556057e50c59af4bc0cf5ee744b --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhdf5/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - bioconductor-rhdf5 + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhdf5/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhdf5/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhdf5/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhtslib/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhtslib/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..06606fbc87c7cc914c960f63ba38650caa95bbc6 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhtslib/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install bioconductor-rhtslib via conda (e.g., from bioconda) +RUN conda install -c bioconda bioconductor-rhtslib -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY app/bioconductor-rhtslib_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/bioconductor-rhtslib_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/bioconductor-rhtslib_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhtslib/app/bioconductor-rhtslib_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhtslib/app/bioconductor-rhtslib_server.py new file mode 100644 index 0000000000000000000000000000000000000000..0b5bb28c98191937f3201d841970f7d861d91a51 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhtslib/app/bioconductor-rhtslib_server.py @@ -0,0 +1,120 @@ +import subprocess +import logging +from pathlib import Path +from typing import Optional, List, Dict, Any + +# Configure logging +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + +@mcp.tool() +def rscript_run( + script_file: Optional[Path] = None, + expression: Optional[str] = None, + script_args: Optional[List[str]] = None, + verbose: bool = False, + default_packages: Optional[str] = None, + vanilla: bool = False, + no_save: bool = False, + no_restore_data: bool = False, + no_restore_history: bool = False, + no_restore: bool = False, + no_environ: bool = False, + no_site_file: bool = False, + no_init_file: bool = False, + slave: bool = False, + arch: Optional[str] = None, +) -> Dict[str, Any]: + """ + Executes an R script or expression using the Rscript command-line tool. + + This tool serves as a wrapper for Rscript, the non-interactive R interpreter. + It is suitable for running scripts that utilize Bioconductor packages like + bioconductor-rhtslib, which is a library and does not have its own + direct command-line interface. You must provide either a script file or an + R expression to execute. + """ + # --- Input Validation --- + if not (script_file is None) ^ (expression is None): + raise ValueError("Exactly one of 'script_file' or 'expression' must be provided.") + + if script_file: + if not script_file.is_file(): + raise FileNotFoundError(f"The specified script file does not exist: {script_file}") + + # --- Command Construction --- + command = ["Rscript"] + + if verbose: + command.append("--verbose") + if default_packages: + command.extend(["--default-packages", default_packages]) + if vanilla: + command.append("--vanilla") + if no_save: + command.append("--no-save") + if no_restore_data: + command.append("--no-restore-data") + if no_restore_history: + command.append("--no-restore-history") + if no_restore: + command.append("--no-restore") + if no_environ: + command.append("--no-environ") + if no_site_file: + command.append("--no-site-file") + if no_init_file: + command.append("--no-init-file") + if slave: + command.append("--slave") + if arch: + command.extend(["--arch", arch]) + + if expression: + command.extend(["-e", expression]) + elif script_file: + command.append(str(script_file)) + + if script_args: + command.extend(script_args) + + command_str = " ".join(command) + logger.info(f"Executing command: {command_str}") + + # --- Subprocess Execution --- + try: + result = subprocess.run( + command, + capture_output=True, + text=True, + check=True, + ) + stdout = result.stdout + stderr = result.stderr + except FileNotFoundError: + error_msg = "Error: Rscript command not found. Please ensure R is installed and in your system's PATH." + logger.error(error_msg) + return { + "command_executed": command_str, + "stdout": "", + "stderr": error_msg, + "output_files": [] + } + except subprocess.CalledProcessError as e: + logger.error(f"Rscript execution failed with return code {e.returncode}") + return { + "command_executed": command_str, + "stdout": e.stdout, + "stderr": e.stderr, + "output_files": [] + } + + # --- Structured Result Return --- + # Rscript itself doesn't manage output files; the executed script does. + # We return an empty list as this wrapper cannot know what files the script might create. + return { + "command_executed": command_str, + "stdout": stdout, + "stderr": stderr, + "output_files": [] + } \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhtslib/app/bioconductor-rhtslib_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhtslib/app/bioconductor-rhtslib_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..5133663518de585f8b51b2d412ccd94e182459d0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhtslib/app/bioconductor-rhtslib_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhtslib/app/bioconductor-rhtslib_server.py') +SERVER_NAME = 'biosci_bioconductor_rhtslib' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhtslib/app/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhtslib/app/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhtslib/app/requirements.txt @@ -0,0 +1 @@ + diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhtslib/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhtslib/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..e3490324c687de6f1d638054610292218df8d093 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhtslib/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-bioconductor-rhtslib: + build: . + image: mcp-bioconductor-rhtslib:latest + container_name: mcp-bioconductor-rhtslib + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=bioconductor-rhtslib + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhtslib/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhtslib/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..8d9fd1f10209694d0af1705cd86798274dadc35c --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhtslib/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - bioconductor-rhtslib + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhtslib/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhtslib/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhtslib/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rsubread/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rsubread/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..e4dec6ab2174115a3f1326b6fd37bc802e9c6b00 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rsubread/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install bioconductor-rsubread via conda (e.g., from bioconda) +RUN conda install -c bioconda bioconductor-rsubread -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY app/bioconductor-rsubread_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/bioconductor-rsubread_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/bioconductor-rsubread_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rsubread/app/bioconductor-rsubread_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rsubread/app/bioconductor-rsubread_server.py new file mode 100644 index 0000000000000000000000000000000000000000..ba1b38286725ea5b9101ff371ee79579eb2c7d72 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rsubread/app/bioconductor-rsubread_server.py @@ -0,0 +1,314 @@ +import subprocess +import os +from pathlib import Path +from typing import Optional, List, Union +import tempfile + +def run_r_command(command: str): + """Helper to execute R commands via Rscript""" + try: + # We use -e to execute the expression directly + full_cmd = ["Rscript", "-e", f"library(Rsubread); {command}"] + result = subprocess.run(full_cmd, capture_output=True, text=True, check=True) + return result.stdout, result.stderr + except subprocess.CalledProcessError as e: + raise RuntimeError(f"Rsubread execution failed: {e.stderr}") + +@mcp.tool() +def rsubread_buildindex( + basename: str, + reference: str, + gapped_index: bool = False, + index_memory: int = 8000, + colorspace: bool = False, + split_index: bool = False +): + """ + Builds an index for a reference genome. + + Args: + basename: Base name of the index files to be generated. + reference: Path to the reference genome file (FASTA format). + gapped_index: If True, a gapped index will be built (saves memory). + index_memory: Memory usage in MB. + colorspace: If True, index is built for color-space reads (SOLiD). + split_index: If True, the index will be split into multiple blocks. + """ + ref_path = Path(reference) + if not ref_path.exists(): + return {"error": f"Reference file {reference} not found."} + + # Construct R command + r_cmd = ( + f"buildindex(basename='{basename}', reference='{reference}', " + f"gappedIndex={'TRUE' if gapped_index else 'FALSE'}, " + f"indexMemory={index_memory}, colorspace={'TRUE' if colorspace else 'FALSE'}, " + f"splitIndex={'TRUE' if split_index else 'FALSE'})" + ) + + try: + stdout, stderr = run_r_command(r_cmd) + return { + "command_executed": f"Rsubread::buildindex({basename})", + "stdout": stdout, + "stderr": stderr, + "output_files": [str(Path(f"{basename}.{ext}")) for ext in ["files"]] # Rsubread creates multiple files + } + except Exception as e: + return {"error": str(e)} + +@mcp.tool() +def rsubread_align( + index: str, + readfile1: str, + readfile2: Optional[str] = None, + output_file: str = "output.bam", + input_format: str = "gzFASTQ", + output_format: str = "BAM", + nthreads: int = 1, + type: str = "dna", + phred_offset: int = 33, + unique: bool = False, + n_best_locations: int = 1, + max_mismatches: int = 3 +): + """ + Aligns reads to a reference genome using the Subread aligner. + + Args: + index: Base name of the index. + readfile1: Path to the first read file. + readfile2: Path to the second read file (for paired-end). + output_file: Name of the output file. + input_format: Format of input reads ('FASTQ', 'gzFASTQ', 'SAM', 'BAM'). + output_format: Format of output ('BAM', 'SAM'). + nthreads: Number of threads to use. + type: Type of sequencing ('dna' or 'rna'). + phred_offset: Phred score offset (33 or 64). + unique: If True, only uniquely mapped reads are reported. + n_best_locations: Number of best mapping locations to report. + max_mismatches: Maximum number of mismatches allowed. + """ + if not Path(readfile1).exists(): + return {"error": f"Read file {readfile1} not found."} + + read2_param = f"'{readfile2}'" if readfile2 else "NULL" + + r_cmd = ( + f"align(index='{index}', readfile1='{readfile1}', readfile2={read2_param}, " + f"output_file='{output_file}', input_format='{input_format}', output_format='{output_format}', " + f"nthreads={nthreads}, type='{type}', phredOffset={phred_offset}, " + f"unique={'TRUE' if unique else 'FALSE'}, nBestLocations={n_best_locations}, " + f"maxMismatches={max_mismatches})" + ) + + try: + stdout, stderr = run_r_command(r_cmd) + return { + "command_executed": "Rsubread::align", + "stdout": stdout, + "stderr": stderr, + "output_files": [output_file] + } + except Exception as e: + return {"error": str(e)} + +@mcp.tool() +def rsubread_subjunc( + index: str, + readfile1: str, + readfile2: Optional[str] = None, + output_file: str = "output_subjunc.bam", + input_format: str = "gzFASTQ", + output_format: str = "BAM", + nthreads: int = 1, + phred_offset: int = 33, + unique: bool = False +): + """ + Aligns RNA-seq reads and detects exon-exon junctions using the Subjunc aligner. + + Args: + index: Base name of the index. + readfile1: Path to the first read file. + readfile2: Path to the second read file (for paired-end). + output_file: Name of the output file. + input_format: Format of input reads. + output_format: Format of output. + nthreads: Number of threads. + phred_offset: Phred score offset. + unique: If True, only uniquely mapped reads are reported. + """ + read2_param = f"'{readfile2}'" if readfile2 else "NULL" + + r_cmd = ( + f"subjunc(index='{index}', readfile1='{readfile1}', readfile2={read2_param}, " + f"output_file='{output_file}', input_format='{input_format}', output_format='{output_format}', " + f"nthreads={nthreads}, phredOffset={phred_offset}, unique={'TRUE' if unique else 'FALSE'})" + ) + + try: + stdout, stderr = run_r_command(r_cmd) + return { + "command_executed": "Rsubread::subjunc", + "stdout": stdout, + "stderr": stderr, + "output_files": [output_file] + } + except Exception as e: + return {"error": str(e)} + +@mcp.tool() +def rsubread_featurecounts( + files: List[str], + annot_ext: str, + is_gtf_annotation_file: bool = True, + gtf_feature_type: str = "exon", + gtf_attr_type: str = "gene_id", + use_meta_features: bool = True, + allow_multi_overlap: bool = False, + is_paired_end: bool = False, + nthreads: int = 1, + strand_specific: int = 0, + count_multi_mapping_reads: bool = False +): + """ + Assigns mapped reads to genomic features (e.g. genes, exons). + + Args: + files: List of paths to alignment files (BAM/SAM). + annot_ext: Path to the annotation file (GTF/GFF/SAF). + is_gtf_annotation_file: Whether the annotation file is in GTF format. + gtf_feature_type: Feature type in GTF to be used (e.g. 'exon'). + gtf_attr_type: Attribute type in GTF to be used (e.g. 'gene_id'). + use_meta_features: If True, reads are counted for meta-features (e.g. genes). + allow_multi_overlap: If True, a read is allowed to be assigned to multiple features. + is_paired_end: If True, reads are treated as paired-end. + nthreads: Number of threads. + strand_specific: Strand specificity (0: unstranded, 1: stranded, 2: reversely stranded). + count_multi_mapping_reads: If True, multi-mapping reads will be counted. + """ + # Convert Python list to R vector + files_r = "c(" + ",".join([f"'{f}'" for f in files]) + ")" + + r_cmd = ( + f"fc <- featureCounts(files={files_r}, annot.ext='{annot_ext}', " + f"isGTFAnnotationFile={'TRUE' if is_gtf_annotation_file else 'FALSE'}, " + f"GTF.featureType='{gtf_feature_type}', GTF.attrType='{gtf_attr_type}', " + f"useMetaFeatures={'TRUE' if use_meta_features else 'FALSE'}, " + f"allowMultiOverlap={'TRUE' if allow_multi_overlap else 'FALSE'}, " + f"isPairedEnd={'TRUE' if is_paired_end else 'FALSE'}, " + f"nthreads={nthreads}, strandSpecific={strand_specific}, " + f"countMultiMappingReads={'TRUE' if count_multi_mapping_reads else 'FALSE'}); " + f"write.table(fc$counts, file='counts.txt', sep='\\t', quote=FALSE); " + f"write.table(fc$stat, file='stats.txt', sep='\\t', quote=FALSE)" + ) + + try: + stdout, stderr = run_r_command(r_cmd) + return { + "command_executed": "Rsubread::featureCounts", + "stdout": stdout, + "stderr": stderr, + "output_files": ["counts.txt", "stats.txt"] + } + except Exception as e: + return {"error": str(e)} + +@mcp.tool() +def rsubread_qualityscores( + filename: str, + input_format: str = "gzFASTQ", + offset: int = 33, + nreads: int = 10000 +): + """ + Extracts quality scores from a read file. + + Args: + filename: Path to the read file. + input_format: Format of the input file. + offset: Phred score offset. + nreads: Number of reads to extract quality scores from. + """ + if not Path(filename).exists(): + return {"error": f"File {filename} not found."} + + r_cmd = ( + f"qs <- qualityScores(filename='{filename}', input_format='{input_format}', " + f"offset={offset}, nreads={nreads}); " + f"write.table(qs, file='quality_scores.txt', sep='\\t', quote=FALSE)" + ) + + try: + stdout, stderr = run_r_command(r_cmd) + return { + "command_executed": "Rsubread::qualityScores", + "stdout": stdout, + "stderr": stderr, + "output_files": ["quality_scores.txt"] + } + except Exception as e: + return {"error": str(e)} + +@mcp.tool() +def rsubread_atgccontent( + filename: str, + input_format: str = "gzFASTQ", + basewise: bool = True +): + """ + Calculates ATGC content of reads. + + Args: + filename: Path to the read file. + input_format: Format of the input file. + basewise: If True, calculate content for each base position. + """ + r_cmd = ( + f"atgc <- atgcContent(filename='{filename}', input_format='{input_format}', " + f"basewise={'TRUE' if basewise else 'FALSE'}); " + f"write.table(atgc, file='atgc_content.txt', sep='\\t', quote=FALSE)" + ) + + try: + stdout, stderr = run_r_command(r_cmd) + return { + "command_executed": "Rsubread::atgcContent", + "stdout": stdout, + "stderr": stderr, + "output_files": ["atgc_content.txt"] + } + except Exception as e: + return {"error": str(e)} + +@mcp.tool() +def rsubread_propmapped( + files: List[str], + count_multi_mapping_reads: bool = False +): + """ + Calculates the proportion of mapped reads in BAM/SAM files. + + Args: + files: List of paths to alignment files. + count_multi_mapping_reads: Whether to include multi-mapping reads. + """ + files_r = "c(" + ",".join([f"'{f}'" for f in files]) + ")" + + r_cmd = ( + f"pm <- propMapped(files={files_r}, " + f"countMultiMappingReads={'TRUE' if count_multi_mapping_reads else 'FALSE'}); " + f"write.table(pm, file='prop_mapped.txt', sep='\\t', quote=FALSE, row.names=FALSE)" + ) + + try: + stdout, stderr = run_r_command(r_cmd) + return { + "command_executed": "Rsubread::propMapped", + "stdout": stdout, + "stderr": stderr, + "output_files": ["prop_mapped.txt"] + } + except Exception as e: + return {"error": str(e)} \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rsubread/app/bioconductor-rsubread_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rsubread/app/bioconductor-rsubread_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..7bda888c6bb1f569b842195b1c9b9dbc56172ae8 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rsubread/app/bioconductor-rsubread_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rsubread/app/bioconductor-rsubread_server.py') +SERVER_NAME = 'biosci_bioconductor_rsubread' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rsubread/app/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rsubread/app/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rsubread/app/requirements.txt @@ -0,0 +1 @@ + diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rsubread/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rsubread/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..e2725ed890f216390d4ca45f72fe80e813511c82 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rsubread/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-bioconductor-rsubread: + build: . + image: mcp-bioconductor-rsubread:latest + container_name: mcp-bioconductor-rsubread + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=bioconductor-rsubread + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rsubread/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rsubread/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..fdd1061efad1bac463df38b14d847bf8a1798168 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rsubread/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - bioconductor-rsubread + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rsubread/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rsubread/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rsubread/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rtracklayer/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rtracklayer/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..cc4c0991514cc01e8dac3cd11c123168bf61c81a --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rtracklayer/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install bioconductor-rtracklayer via conda (e.g., from bioconda) +RUN conda install -c bioconda bioconductor-rtracklayer -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY app/bioconductor-rtracklayer_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/bioconductor-rtracklayer_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/bioconductor-rtracklayer_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rtracklayer/app/bioconductor-rtracklayer_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rtracklayer/app/bioconductor-rtracklayer_server.py new file mode 100644 index 0000000000000000000000000000000000000000..d68fa4f35a1715e991d5843bb988c2cb66583da9 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rtracklayer/app/bioconductor-rtracklayer_server.py @@ -0,0 +1,340 @@ +import subprocess +import tempfile +import re +from pathlib import Path +from typing import Optional, List + +# @mcp.tool() is a placeholder for the actual decorator. +# The code is written to be compatible with the MCP framework. + +def mcp_tool_placeholder(): + def decorator(func): + return func + return decorator + +@mcp_tool_placeholder() +def rtracklayer_convert( + input_file: Path, + output_file: Path, + input_format: Optional[str] = None, + output_format: Optional[str] = None, + which: Optional[str] = None, + genome: Optional[str] = None, + gff_feature_type_filter: Optional[str] = None, + gff_version: Optional[str] = None, + export_source: Optional[str] = None, + index_output: bool = False, +): + """ + Converts genomic data files from one format to another using rtracklayer. + + This tool wraps the core import() and export() functionality of the rtracklayer + R package, allowing for conversion between formats like BED, GFF, GTF, WIG, + and BigWig. It also supports filtering by genomic region. + + Args: + input_file: Path to the input genomic data file. + output_file: Path to write the converted output file. + input_format: The format of the input file (e.g., 'bed', 'gff', 'bigWig'). + If not provided, rtracklayer will guess from the file extension. + output_format: The format for the output file. If not provided, rtracklayer + will guess from the file extension. + which: A specific genomic region to process, in the format 'chr:start-end' + (e.g., 'chr1:1000-2000'). This is highly effective for indexed files. + genome: The genome assembly name (e.g., 'hg19', 'mm10'). + gff_feature_type_filter: For GFF/GTF import, a comma-separated list of + feature types to keep (e.g., 'exon,gene'). + gff_version: Specify the GFF version ('1', '2', or '3') for import/export. + export_source: The 'source' field to use for GFF/GTF export. + index_output: If True, create a tabix index (.tbi) for the output file. + Applicable to formats like BED and GFF. + """ + # 1. Input Validation + if not input_file.exists(): + raise FileNotFoundError(f"Input file not found: {input_file}") + + ALLOWED_FORMATS = ["bed", "gff", "gff1", "gff2", "gff3", "gtf", "wig", "bigWig", "bedGraph", "2bit", "fasta"] + if input_format and input_format not in ALLOWED_FORMATS: + raise ValueError(f"Invalid input_format '{input_format}'. Allowed formats: {ALLOWED_FORMATS}") + if output_format and output_format not in ALLOWED_FORMATS: + raise ValueError(f"Invalid output_format '{output_format}'. Allowed formats: {ALLOWED_FORMATS}") + + if gff_version and gff_version not in ["1", "2", "3"]: + raise ValueError("gff_version must be one of '1', '2', or '3'.") + + if which and not re.match(r"^\w+:\d+-\d+$", which): + raise ValueError("Invalid 'which' format. Expected 'chr:start-end' (e.g., 'chr1:1000-5000').") + + # 2. Build R Script + r_script_lines = [ + "suppressPackageStartupMessages(library(rtracklayer))", + "suppressPackageStartupMessages(library(GenomicRanges))", + "", + "# --- Import Arguments ---", + f"import_args <- list(con = '{input_file.resolve()}')", + ] + if input_format: + r_script_lines.append(f"import_args$format <- '{input_format}'") + if which: + r_script_lines.append(f"import_args$which <- GRanges('{which}')") + if genome: + r_script_lines.append(f"import_args$genome <- '{genome}'") + if gff_feature_type_filter: + r_vector = 'c(' + ', '.join([f'"{f.strip()}"' for f in gff_feature_type_filter.split(',')]) + ')' + r_script_lines.append(f"import_args$feature.type <- {r_vector}") + if gff_version: + r_script_lines.append(f"import_args$version <- '{gff_version}'") + + r_script_lines.extend([ + "", + "# --- Import Data ---", + "gr_object <- do.call(rtracklayer::import, import_args)", + "", + "# --- Export Arguments ---", + f"export_args <- list(object = gr_object, con = '{output_file.resolve()}')", + ]) + + if output_format: + r_script_lines.append(f"export_args$format <- '{output_format}'") + if export_source: + r_script_lines.append(f"export_args$source <- '{export_source}'") + if gff_version: + r_script_lines.append(f"export_args$version <- '{gff_version}'") + if index_output: + r_script_lines.append("export_args$index <- TRUE") + + r_script_lines.extend([ + "", + "# --- Export Data ---", + "do.call(rtracklayer::export, export_args)", + "cat('Conversion successful.\\n')" + ]) + + r_script = "\n".join(r_script_lines) + + # 3. Execute R Script + with tempfile.NamedTemporaryFile(mode='w', suffix=".R", delete=False, dir=".") as tmp_script: + script_path = Path(tmp_script.name) + tmp_script.write(r_script) + + command = ["Rscript", str(script_path.name)] + command_str = " ".join(command) + + try: + result = subprocess.run( + command, + capture_output=True, + text=True, + check=True, + cwd=Path.cwd() + ) + + output_files = [str(output_file)] + index_file = Path(f"{output_file}.tbi") + if index_output and index_file.exists(): + output_files.append(str(index_file)) + + return { + "command_executed": command_str, + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": output_files + } + except subprocess.CalledProcessError as e: + raise RuntimeError( + f"Rscript execution failed with return code {e.returncode}.\n" + f"Command: {command_str}\n" + f"Stderr: {e.stderr}\n" + f"Stdout: {e.stdout}" + ) from e + finally: + script_path.unlink() + + +@mcp_tool_placeholder() +def rtracklayer_liftover( + input_file: Path, + output_file: Path, + chain_file: Path, + input_format: Optional[str] = None, + unmapped_output_file: Optional[Path] = None, +): + """ + Lifts over genomic coordinates from one assembly to another using a chain file. + + This tool wraps the liftOver() function from rtracklayer, which is essential + for translating genomic features between different reference genome versions + (e.g., hg18 to hg19). + + Args: + input_file: Path to the input genomic data file (e.g., BED, GFF) with + coordinates to be lifted over. + output_file: Path to write the output file with lifted coordinates. + chain_file: Path to the liftOver chain file (.chain or .chain.gz). + input_format: The format of the input file (e.g., 'bed', 'gff'). If not + provided, rtracklayer will guess from the file extension. + unmapped_output_file: Optional path to write features that could not be + mapped to the new assembly. + """ + # 1. Input Validation + if not input_file.exists(): + raise FileNotFoundError(f"Input file not found: {input_file}") + if not chain_file.exists(): + raise FileNotFoundError(f"Chain file not found: {chain_file}") + + # 2. Build R Script + r_script_lines = [ + "suppressPackageStartupMessages(library(rtracklayer))", + "", + "# --- Import Data ---", + f"ch <- rtracklayer::import.chain('{chain_file.resolve()}')", + f"gr <- rtracklayer::import('{input_file.resolve()}'" + (f", format = '{input_format}'" if input_format else "") + ")", + "", + "# --- Perform LiftOver ---", + "lifted_grl <- rtracklayer::liftOver(gr, ch)", + "lifted_gr <- unlist(lifted_grl)", + "", + "# --- Export Lifted Data ---", + f"rtracklayer::export(lifted_gr, '{output_file.resolve()}')", + ] + + if unmapped_output_file: + r_script_lines.extend([ + "", + "# --- Handle Unmapped Regions ---", + "unmapped_indices <- elementNROWS(lifted_grl) == 0", + "unmapped_gr <- gr[unmapped_indices]", + f"if (length(unmapped_gr) > 0) {{", + f" rtracklayer::export(unmapped_gr, '{unmapped_output_file.resolve()}')", + f"}}", + ]) + + r_script_lines.append("cat('LiftOver successful.\\n')") + r_script = "\n".join(r_script_lines) + + # 3. Execute R Script + with tempfile.NamedTemporaryFile(mode='w', suffix=".R", delete=False, dir=".") as tmp_script: + script_path = Path(tmp_script.name) + tmp_script.write(r_script) + + command = ["Rscript", str(script_path.name)] + command_str = " ".join(command) + + try: + result = subprocess.run( + command, + capture_output=True, + text=True, + check=True, + cwd=Path.cwd() + ) + + output_files = [str(output_file)] + if unmapped_output_file and unmapped_output_file.exists(): + output_files.append(str(unmapped_output_file)) + + return { + "command_executed": command_str, + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": output_files + } + except subprocess.CalledProcessError as e: + raise RuntimeError( + f"Rscript execution failed with return code {e.returncode}.\n" + f"Command: {command_str}\n" + f"Stderr: {e.stderr}\n" + f"Stdout: {e.stdout}" + ) from e + finally: + script_path.unlink() + + +@mcp_tool_placeholder() +def rtracklayer_ucsc_query( + output_file: Path, + genome: str, + track: str, + which: Optional[str] = None, + output_format: Optional[str] = None, +): + """ + Downloads data directly from the UCSC Table Browser. + + This tool provides an interface to query and download genomic tracks from the + UCSC database, saving them to a local file in a specified format. + + Args: + output_file: Path to write the downloaded data. + genome: The UCSC genome assembly to query (e.g., 'hg19', 'mm10'). + track: The name of the track/table to download (e.g., 'knownGene', 'cpgIslandExt'). + which: A specific genomic region to query, in the format 'chr:start-end' + (e.g., 'chr1:1000-2000'). If not provided, the whole genome is queried. + output_format: The format for the output file (e.g., 'bed', 'gff'). If not + provided, rtracklayer will guess from the file extension. + """ + # 1. Input Validation + if which and not re.match(r"^\w+:\d+-\d+$", which): + raise ValueError("Invalid 'which' format. Expected 'chr:start-end' (e.g., 'chr1:1000-5000').") + + # 2. Build R Script + r_script_lines = [ + "suppressPackageStartupMessages(library(rtracklayer))", + "suppressPackageStartupMessages(library(GenomicRanges))", + "", + "# --- Build UCSC Data Source ---", + f"ucsc_args <- list(genome = '{genome}', tablename = '{track}')", + ] + if which: + r_script_lines.append(f"ucsc_args$range <- GRanges('{which}')") + + r_script_lines.extend([ + "ucsc_data_source <- do.call(UCSCData, ucsc_args)", + "", + "# --- Import Data from UCSC ---", + "gr_object <- rtracklayer::import(ucsc_data_source)", + "", + "# --- Export Data to File ---", + f"export_args <- list(object = gr_object, con = '{output_file.resolve()}')", + ]) + if output_format: + r_script_lines.append(f"export_args$format <- '{output_format}'") + + r_script_lines.extend([ + "do.call(rtracklayer::export, export_args)", + "cat('UCSC data downloaded successfully.\\n')" + ]) + r_script = "\n".join(r_script_lines) + + # 3. Execute R Script + with tempfile.NamedTemporaryFile(mode='w', suffix=".R", delete=False, dir=".") as tmp_script: + script_path = Path(tmp_script.name) + tmp_script.write(r_script) + + command = ["Rscript", str(script_path.name)] + command_str = " ".join(command) + + try: + result = subprocess.run( + command, + capture_output=True, + text=True, + check=True, + cwd=Path.cwd() + ) + + return { + "command_executed": command_str, + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": [str(output_file)] + } + except subprocess.CalledProcessError as e: + raise RuntimeError( + f"Rscript execution failed with return code {e.returncode}.\n" + f"Command: {command_str}\n" + f"Stderr: {e.stderr}\n" + f"Stdout: {e.stdout}" + ) from e + finally: + script_path.unlink() \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rtracklayer/app/bioconductor-rtracklayer_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rtracklayer/app/bioconductor-rtracklayer_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..f221860110800b53e421855fc9c7fa929a826c9c --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rtracklayer/app/bioconductor-rtracklayer_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rtracklayer/app/bioconductor-rtracklayer_server.py') +SERVER_NAME = 'biosci_bioconductor_rtracklayer' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rtracklayer/app/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rtracklayer/app/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rtracklayer/app/requirements.txt @@ -0,0 +1 @@ + diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rtracklayer/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rtracklayer/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..157e572f2f12f56aa788b6b9d1f6cae0a70d2ee0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rtracklayer/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-bioconductor-rtracklayer: + build: . + image: mcp-bioconductor-rtracklayer:latest + container_name: mcp-bioconductor-rtracklayer + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=bioconductor-rtracklayer + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rtracklayer/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rtracklayer/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a856295b3e4e95df8ebc94bdd0203c76011ff269 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rtracklayer/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - bioconductor-rtracklayer + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rtracklayer/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rtracklayer/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rtracklayer/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scbfa/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scbfa/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..94ff6db8337a62074ee000d9331841b428126b2e --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scbfa/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install bioconductor-scbfa via conda (e.g., from bioconda) +RUN conda install -c bioconda bioconductor-scbfa -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY bioconductor-scbfa_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/bioconductor-scbfa_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/bioconductor-scbfa_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scbfa/app/bioconductor-scbfa_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scbfa/app/bioconductor-scbfa_server.py new file mode 100644 index 0000000000000000000000000000000000000000..5b179a68910946e7b326ce16ef4b74822ce00516 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scbfa/app/bioconductor-scbfa_server.py @@ -0,0 +1,183 @@ +import subprocess +import tempfile +from pathlib import Path +from typing import Optional, List + +# @mcp.tool() is a placeholder for the actual decorator. +# The final code should be used in an environment where mcp is available. + +def mcp_tool(): + """A dummy decorator for standalone execution.""" + def decorator(f): + return f + return decorator + +@mcp_tool() +def run_scbfa( + input_data: Path, + output_prefix: str, + num_factors: int, + max_iter: int = 1000, + min_rel_err: float = 1e-08, + abs_err: float = 1e-06, + a: float = 0.1, + b: float = 0.1, + alpha: float = 0.1, + beta: float = 0.1, + verbose: bool = False, + rscript_executable: str = "Rscript", + rscript_options: Optional[List[str]] = None, +): + """ + Runs Single-Cell Bayesian Factor Analysis (scBFA) on a given count matrix. + + This tool generates and executes an R script to perform scBFA, saving the + resulting factor loadings and scores to specified output files. It requires + the 'scBFA' Bioconductor package and the 'data.table' CRAN package to be + installed in the R environment. + + Args: + input_data: Path to the input data file (e.g., CSV format). + The data should be a numeric matrix of counts (genes x cells). + output_prefix: Prefix for the output files. Two files will be generated: + _loadings.csv and _scores.csv. + num_factors: The number of latent factors to compute. + max_iter: Maximum number of iterations for the algorithm. + min_rel_err: Minimum relative error for convergence. + abs_err: Absolute error for convergence. + a: Hyperparameter for the gamma prior on factor loadings. + b: Hyperparameter for the gamma prior on factor loadings. + alpha: Hyperparameter for the gamma prior on factor scores. + beta: Hyperparameter for the gamma prior on factor scores. + verbose: If True, enables verbose output from the R script. + rscript_executable: The path to the Rscript executable. + rscript_options: A list of additional options to pass to Rscript + (e.g., ["--vanilla", "--verbose"]). + """ + # 1. Input Validation + if not input_data.is_file(): + raise FileNotFoundError(f"Input data file not found: {input_data}") + if num_factors <= 0: + raise ValueError("num_factors must be a positive integer.") + if max_iter <= 0: + raise ValueError("max_iter must be a positive integer.") + if not output_prefix: + raise ValueError("output_prefix cannot be empty.") + + # 2. R Script Generation + verbose_r = "TRUE" if verbose else "FALSE" + + r_script_content = f""" + # Ensure required packages are installed and loaded + if (!requireNamespace("scBFA", quietly = TRUE)) {{ + stop("The 'scBFA' package is not installed. Please install it from Bioconductor.") + }} + if (!requireNamespace("data.table", quietly = TRUE)) {{ + stop("The 'data.table' package is not installed. Please install it from CRAN.") + }} + library(scBFA) + library(data.table) + + # --- Parameters --- + input_file <- "{str(input_data.resolve())}" + output_prefix <- "{output_prefix}" + num_factors <- {num_factors} + max_iter <- {max_iter} + min_rel_err <- {min_rel_err} + abs_err <- {abs_err} + a <- {a} + b <- {b} + alpha <- {alpha} + beta <- {beta} + verbose_r <- {verbose_r} + + # --- Main Logic --- + tryCatch({{ + message("Reading input data from: ", input_file) + counts_matrix <- as.matrix(fread(input_file)) + message("Input data dimensions: ", paste(dim(counts_matrix), collapse = " x ")) + + message("Running scBFA with ", num_factors, " factors...") + bfa_result <- scBFA( + x = counts_matrix, + num_factors = num_factors, + max_iter = max_iter, + min_rel_err = min_rel_err, + abs_err = abs_err, + a = a, + b = b, + alpha = alpha, + beta = beta, + verbose = verbose_r + ) + message("scBFA completed.") + + # --- Save Results --- + loadings_file <- paste0(output_prefix, "_loadings.csv") + scores_file <- paste0(output_prefix, "_scores.csv") + + message("Saving factor loadings to: ", loadings_file) + write.csv(bfa_result$L, file = loadings_file, row.names = FALSE) + + message("Saving factor scores to: ", scores_file) + write.csv(bfa_result$F, file = scores_file, row.names = FALSE) + + message("Analysis finished successfully.") + }}, error = function(e) {{ + message("An error occurred during scBFA execution: ") + message(conditionMessage(e)) + quit(status = 1, save = "no") + }}) + """ + + # 3. Subprocess Execution + output_files_map = { + "factor_loadings": Path(f"{output_prefix}_loadings.csv").resolve(), + "factor_scores": Path(f"{output_prefix}_scores.csv").resolve() + } + + r_script_path = "" + try: + with tempfile.NamedTemporaryFile(mode='w', suffix=".R", delete=False) as tmp_r_script: + tmp_r_script.write(r_script_content) + r_script_path = tmp_r_script.name + + cmd = [rscript_executable] + if rscript_options: + cmd.extend(rscript_options) + cmd.append(r_script_path) + + command_executed = " ".join(cmd) + + result = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + ) + + # 4. Structured Result Return + return { + "command_executed": command_executed, + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": {k: str(v) for k, v in output_files_map.items()} + } + + except FileNotFoundError: + return { + "command_executed": f"{rscript_executable} ...", + "stdout": "", + "stderr": f"Error: '{rscript_executable}' not found. Is R installed and in your system's PATH?", + "output_files": {} + } + except subprocess.CalledProcessError as e: + return { + "command_executed": command_executed, + "stdout": e.stdout, + "stderr": e.stderr, + "output_files": {} + } + finally: + if r_script_path and Path(r_script_path).exists(): + Path(r_script_path).unlink() diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scbfa/app/bioconductor-scbfa_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scbfa/app/bioconductor-scbfa_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..8d1ca759ea8ce8f87ceb2402cd98b0aef99d3bc7 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scbfa/app/bioconductor-scbfa_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scbfa/app/bioconductor-scbfa_server.py') +SERVER_NAME = 'biosci_bioconductor_scbfa' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scbfa/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scbfa/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..8ddfddb024ad9c91d3fc9d4cd013f1cb9d9e00b1 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scbfa/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-bioconductor-scbfa: + build: . + image: mcp-bioconductor-scbfa:latest + container_name: mcp-bioconductor-scbfa + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=bioconductor-scbfa + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scbfa/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scbfa/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..0e5aaa29f0c7f136ee493fe61a322bcf41a2787f --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scbfa/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - bioconductor-scbfa + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scbfa/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scbfa/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scbfa/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-sccb2/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-sccb2/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..ef9f5c761e496cb49c647c4b468c551764238a6f --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-sccb2/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install bioconductor-sccb2 via conda (e.g., from bioconda) +RUN conda install -c bioconda bioconductor-sccb2 -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY bioconductor-sccb2_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/bioconductor-sccb2_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/bioconductor-sccb2_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-sccb2/app/bioconductor-sccb2_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-sccb2/app/bioconductor-sccb2_server.py new file mode 100644 index 0000000000000000000000000000000000000000..e78a3694e1e3d73a316b75c7c69dd53bc200b264 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-sccb2/app/bioconductor-sccb2_server.py @@ -0,0 +1,135 @@ +import subprocess +from pathlib import Path +from typing import Optional, List + +# In a real MCP environment, the 'mcp' object with the 'tool' decorator +# would be provided by the MCP framework. +# from mcp import tool +# +# For demonstration purposes, a placeholder is defined. +class _MCP: + def tool(self, *args, **kwargs): + def decorator(f): + return f + return decorator +mcp = _MCP() + + +@mcp.tool() +def run_rscript( + script_file: Optional[Path] = None, + expressions: Optional[List[str]] = None, + script_args: Optional[List[str]] = None, + verbose: bool = False, + default_packages: Optional[str] = None, + save: bool = False, + no_environ: bool = False, + no_site_file: bool = False, + no_init_file: bool = False, + restore: bool = False, + vanilla: bool = False, +): + """ + Executes an R script using the Rscript command-line interface. + + This tool is a generic wrapper for the 'Rscript' command, designed to run scripts + from Bioconductor packages like 'sccb2' or any other R script. You can either + provide a path to an R script file or a list of R expressions to be executed directly. + + Args: + script_file: Path to the R script file to be executed. Mutually exclusive with 'expressions'. + expressions: A list of R expressions to execute using the '-e' flag. Mutually exclusive with 'script_file'. + script_args: A list of arguments to be passed to the R script itself. + verbose: If True, prints information on progress. Corresponds to the --verbose flag. + default_packages: A comma-separated string of package names to be loaded. Corresponds to --default-packages. + save: If True, saves the workspace at the end of the session. Corresponds to --save. + no_environ: If True, does not read the site and user environment files. Corresponds to --no-environ. + no_site_file: If True, does not read the site-wide Rprofile. Corresponds to --no-site-file. + no_init_file: If True, does not read the user R profile. Corresponds to --no-init-file. + restore: If True, restores previously saved objects at startup. Corresponds to --restore. + vanilla: If True, combines --no-save, --no-restore, --no-site-file, --no-init-file, and --no-environ. + This option overrides the individual flags if set. + + Returns: + A dictionary containing the executed command, stdout, stderr, and a list of output files. + Note: 'output_files' will be empty as the script's outputs are not known beforehand. + """ + # --- Input Validation --- + if script_file and expressions: + raise ValueError("Parameters 'script_file' and 'expressions' are mutually exclusive. Please provide only one.") + if not script_file and not expressions: + raise ValueError("Either 'script_file' or 'expressions' must be provided.") + + if script_file: + if not script_file.is_file(): + raise FileNotFoundError(f"Input script file not found at: {script_file}") + + # --- Command Construction --- + base_command = "Rscript" + command = [base_command] + + # Handle R session options + if vanilla: + command.append("--vanilla") + else: + if save: + command.append("--save") + if no_environ: + command.append("--no-environ") + if no_site_file: + command.append("--no-site-file") + if no_init_file: + command.append("--no-init-file") + if restore: + command.append("--restore") + + # Handle Rscript-specific options + if verbose: + command.append("--verbose") + if default_packages: + command.extend(["--default-packages", default_packages]) + + # Add expressions or script file to the command + if expressions: + for expr in expressions: + command.extend(["-e", expr]) + elif script_file: + command.append(str(script_file)) + + # Add arguments for the R script + if script_args: + command.extend(script_args) + + command_str = " ".join(command) + + # --- Subprocess Execution --- + try: + result = subprocess.run( + command, + capture_output=True, + text=True, + check=True + ) + stdout = result.stdout + stderr = result.stderr + + except FileNotFoundError: + raise RuntimeError(f"Error: '{base_command}' not found. Is R installed and in your system's PATH?") + except subprocess.CalledProcessError as e: + # The process failed. Return a structured error with captured output. + return { + "command_executed": command_str, + "stdout": e.stdout, + "stderr": e.stderr, + "output_files": [] + } + + # --- Structured Result Return --- + # Since the output files are determined by the R script itself, + # we cannot predict them here. We return an empty list. + return { + "command_executed": command_str, + "stdout": stdout, + "stderr": stderr, + "output_files": [] + } \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-sccb2/app/bioconductor-sccb2_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-sccb2/app/bioconductor-sccb2_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..1f51eb626202f43eaa390ea8639dd0f2dbb0098f --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-sccb2/app/bioconductor-sccb2_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-sccb2/app/bioconductor-sccb2_server.py') +SERVER_NAME = 'biosci_bioconductor_sccb2' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-sccb2/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-sccb2/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..64f80f2c0b9fee1954c7a433abd544684a676332 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-sccb2/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-bioconductor-sccb2: + build: . + image: mcp-bioconductor-sccb2:latest + container_name: mcp-bioconductor-sccb2 + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=bioconductor-sccb2 + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-sccb2/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-sccb2/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..f49b35fc0692ce48114a48bf1bbad3003d57ff13 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-sccb2/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - bioconductor-sccb2 + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-sccb2/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-sccb2/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-sccb2/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scdataviz/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scdataviz/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..c926501a4fd661158e18096512c4e1f1481c6b4a --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scdataviz/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install bioconductor-scdataviz via conda (e.g., from bioconda) +RUN conda install -c bioconda bioconductor-scdataviz -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY bioconductor-scdataviz_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/bioconductor-scdataviz_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/bioconductor-scdataviz_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scdataviz/app/bioconductor-scdataviz_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scdataviz/app/bioconductor-scdataviz_server.py new file mode 100644 index 0000000000000000000000000000000000000000..6262e5ea82010f6d2290e68c395b98fca31465c2 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scdataviz/app/bioconductor-scdataviz_server.py @@ -0,0 +1,173 @@ +import subprocess +import shlex +from pathlib import Path +from typing import Optional, List + +# This is a placeholder for the MCP decorator. +# In a real MCP environment, this would be provided by the MCP framework. +def tool(func): + def wrapper(*args, **kwargs): + return func(*args, **kwargs) + return wrapper + +mcp = type("mcp", (), {"tool": tool}) + + +@mcp.tool +def rscript( + file: Optional[Path] = None, + expressions: Optional[List[str]] = None, + script_args: Optional[List[str]] = None, + verbose: bool = False, + default_packages: Optional[List[str]] = None, + save: bool = False, + no_environ: bool = False, + no_site_file: bool = False, + no_init_file: bool = False, + restore: bool = False, + vanilla: bool = False, +) -> dict: + """ + Executes an R script or R expressions using the Rscript command-line interface. + + This tool serves as a wrapper for Rscript, allowing you to run R code from a file + or directly as command-line expressions. It provides control over the R session's + environment and startup behavior. You must provide either a script file or a list + of expressions to execute, but not both. + + Args: + file: Path to the R script file to be executed. + expressions: A list of R expressions to execute. Use instead of 'file'. + script_args: A list of arguments to be passed to the R script. + verbose: If True, print information on progress. + default_packages: A list of package names to be loaded by default. + save: If True, save the workspace at the end of the session. + no_environ: If True, do not read the site and user environment files. + no_site_file: If True, do not read the site-wide Rprofile. + no_init_file: If True, do not read the user R profile. + restore: If True, restore previously saved objects at startup. + vanilla: If True, combine --no-save, --no-restore, --no-site-file, + --no-init-file, and --no-environ for a clean session. + + Returns: + A dictionary containing the executed command, stdout, and stderr. + """ + # 1. Input Validation + if (file is None and not expressions) or (file is not None and expressions): + raise ValueError("You must provide either 'file' or 'expressions', but not both.") + + if file and not file.is_file(): + raise FileNotFoundError(f"The specified R script file does not exist: {file}") + + # 2. Command Construction + cmd = ["Rscript"] + + # Add session control options + if vanilla: + cmd.append("--vanilla") + if save: + cmd.append("--save") + if no_environ: + cmd.append("--no-environ") + if no_site_file: + cmd.append("--no-site-file") + if no_init_file: + cmd.append("--no-init-file") + if restore: + cmd.append("--restore") + if verbose: + cmd.append("--verbose") + if default_packages: + packages_str = ",".join(default_packages) + cmd.append(f"--default-packages={packages_str}") + + # Add the script file or expressions to execute + if file: + cmd.append(str(file)) + elif expressions: + for expr in expressions: + cmd.extend(["-e", expr]) + + # Add arguments for the script itself + if script_args: + cmd.extend(script_args) + + command_executed = shlex.join(cmd) + + # 3. Subprocess Execution and Error Handling + try: + result = subprocess.run( + cmd, + check=True, + capture_output=True, + text=True, + ) + stdout = result.stdout + stderr = result.stderr + except FileNotFoundError: + return { + "command_executed": command_executed, + "stdout": "", + "stderr": "Error: 'Rscript' command not found. Please ensure R is installed and in your system's PATH.", + "output_files": [] + } + except subprocess.CalledProcessError as e: + return { + "command_executed": command_executed, + "stdout": e.stdout, + "stderr": e.stderr, + "error": f"Rscript execution failed with return code {e.returncode}", + "output_files": [] + } + + # 4. Structured Result Return + return { + "command_executed": command_executed, + "stdout": stdout, + "stderr": stderr, + "output_files": [] # Rscript itself doesn't guarantee output files; the script's content does. + } + +@mcp.tool +def rscript_version() -> dict: + """ + Retrieves the version of the Rscript interpreter. + + This function executes `Rscript --version` to get the version information of the + installed R environment. + + Returns: + A dictionary containing the executed command, stdout (version info), and stderr. + """ + cmd = ["Rscript", "--version"] + command_executed = shlex.join(cmd) + + try: + # Note: Rscript --version prints to stderr, so we capture both. + result = subprocess.run( + cmd, + check=True, + capture_output=True, + text=True, + ) + # Combine stdout and stderr as version info can be in either + output = result.stdout + result.stderr + except FileNotFoundError: + return { + "command_executed": command_executed, + "stdout": "", + "stderr": "Error: 'Rscript' command not found. Please ensure R is installed and in your system's PATH.", + } + except subprocess.CalledProcessError as e: + return { + "command_executed": command_executed, + "stdout": e.stdout, + "stderr": e.stderr, + "error": f"Rscript version check failed with return code {e.returncode}", + } + + return { + "command_executed": command_executed, + "stdout": output, + "stderr": "", # Stderr content is moved to stdout for consistency + } \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scdataviz/app/bioconductor-scdataviz_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scdataviz/app/bioconductor-scdataviz_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..a04b11fde322fb9d8af18ad9cfe1626b50e4749a --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scdataviz/app/bioconductor-scdataviz_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scdataviz/app/bioconductor-scdataviz_server.py') +SERVER_NAME = 'biosci_bioconductor_scdataviz' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scdataviz/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scdataviz/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..c505a0ca6bc8f3d61067bbe38ad54952de78ce99 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scdataviz/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-bioconductor-scdataviz: + build: . + image: mcp-bioconductor-scdataviz:latest + container_name: mcp-bioconductor-scdataviz + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=bioconductor-scdataviz + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scdataviz/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scdataviz/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..6dcce732cd877fc501a28cde5132e3bd3d44d826 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scdataviz/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - bioconductor-scdataviz + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scdataviz/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scdataviz/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scdataviz/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scmageck/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scmageck/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..5f8e016875df53696a5db64cc303a6d7da461a8e --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scmageck/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install bioconductor-scmageck via conda (e.g., from bioconda) +RUN conda install -c bioconda bioconductor-scmageck -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY bioconductor-scmageck_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/bioconductor-scmageck_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/bioconductor-scmageck_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scmageck/app/bioconductor-scmageck_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scmageck/app/bioconductor-scmageck_server.py new file mode 100644 index 0000000000000000000000000000000000000000..8cc802ab8284f45637e3da88be938501f5436c59 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scmageck/app/bioconductor-scmageck_server.py @@ -0,0 +1,269 @@ +import subprocess +from pathlib import Path +from typing import Optional, List, Dict, Any +import tempfile + +@mcp.tool() +def scmageck_eff_estimate( + count_matrix_path: str, + barcode_file_path: str, + output_rds_path: str, + neg_control: str = "non-target", + perturb_gene: Optional[str] = None, + cell_column: str = "cell", + barcode_column: str = "barcode", + gene_column: str = "gene" +): + """ + Estimate the efficiency of guides using the scmageck_eff_estimate function. + + Args: + count_matrix_path: Path to the gene expression count matrix (CSV/TSV or RDS). + barcode_file_path: Path to the barcode-to-cell mapping file (CSV/TSV). + output_rds_path: Path where the resulting RDS object will be saved. + neg_control: Name of the negative control gene/guide. + perturb_gene: Specific gene to estimate efficiency for. If None, estimates for all. + cell_column: Column name for cell identifiers in barcode file. + barcode_column: Column name for barcode identifiers in barcode file. + gene_column: Column name for gene identifiers in barcode file. + """ + # Validate inputs + count_path = Path(count_matrix_path) + bc_path = Path(barcode_file_path) + out_path = Path(output_rds_path) + + if not count_path.exists(): + return {"error": f"Count matrix not found: {count_matrix_path}"} + if not bc_path.exists(): + return {"error": f"Barcode file not found: {barcode_file_path}"} + + # Ensure output directory exists + out_path.parent.mkdir(parents=True, exist_ok=True) + + # Construct R script + perturb_gene_cmd = f'"{perturb_gene}"' if perturb_gene else "NULL" + + r_script = f""" + library(scmageck) + + # Load data + if (grepl(".rds$", "{count_path}", ignore.case = TRUE)) {{ + counts <- readRDS("{count_path}") + }} else {{ + counts <- read.table("{count_path}", header = TRUE, sep = ",", row.names = 1) + }} + + barcodes <- read.table("{bc_path}", header = TRUE, sep = ",") + + # Run efficiency estimation + eff_result <- scmageck_eff_estimate( + count_mat = counts, + barcode_df = barcodes, + negctrl = "{neg_control}", + perturb_gene = {perturb_gene_cmd}, + cell_col = "{cell_column}", + bc_col = "{barcode_column}", + gene_col = "{gene_column}" + ) + + saveRDS(eff_result, file = "{out_path}") + """ + + try: + process = subprocess.run( + ["Rscript", "-e", r_script], + capture_output=True, + text=True, + check=True + ) + return { + "command_executed": f"scmageck_eff_estimate on {count_matrix_path}", + "stdout": process.stdout, + "stderr": process.stderr, + "output_files": [str(out_path)] + } + except subprocess.CalledProcessError as e: + return { + "error": "R execution failed", + "stdout": e.stdout, + "stderr": e.stderr, + "command_executed": e.cmd + } + +@mcp.tool() +def scmageck_lr( + expression_matrix_path: str, + perturbation_matrix_path: str, + output_csv_path: str, + lambda_val: float = 0.01, + n_cores: int = 1 +): + """ + Perform Linear Regression analysis to identify gene targets using scmageck_lr. + + Args: + expression_matrix_path: Path to the expression matrix (RDS or CSV). + perturbation_matrix_path: Path to the perturbation matrix (RDS or CSV). + output_csv_path: Path to save the regression results (CSV). + lambda_val: Penalty parameter for regression. + n_cores: Number of CPU cores to use. + """ + expr_path = Path(expression_matrix_path) + pert_path = Path(perturbation_matrix_path) + out_path = Path(output_csv_path) + + if not expr_path.exists() or not pert_path.exists(): + return {"error": "Input expression or perturbation matrix not found."} + + r_script = f""" + library(scmageck) + + # Load matrices + load_mat <- function(p) {{ + if (grepl(".rds$", p, ignore.case = TRUE)) return(readRDS(p)) + return(as.matrix(read.table(p, header = TRUE, row.names = 1, sep = ","))) + }} + + expr_mat <- load_mat("{expr_path}") + pert_mat <- load_mat("{pert_path}") + + # Run LR + lr_result <- scmageck_lr( + m_matrix = expr_mat, + g_matrix = pert_mat, + lambda = {lambda_val} + ) + + # Handle result (scmageck_lr returns a list or matrix depending on version) + write.csv(lr_result, file = "{out_path}") + """ + + try: + process = subprocess.run( + ["Rscript", "-e", r_script], + capture_output=True, + text=True, + check=True + ) + return { + "command_executed": "scmageck_lr", + "stdout": process.stdout, + "stderr": process.stderr, + "output_files": [str(out_path)] + } + except subprocess.CalledProcessError as e: + return { + "error": "R execution failed", + "stdout": e.stdout, + "stderr": e.stderr + } + +@mcp.tool() +def scmageck_optim_perturb( + rds_input_path: str, + output_rds_path: str, + max_iter: int = 100, + threshold: float = 1e-4 +): + """ + Optimize the perturbation matrix using the scmageck_optim_perturb function. + + Args: + rds_input_path: Path to an RDS file containing the scmageck object/list. + output_rds_path: Path to save the optimized RDS object. + max_iter: Maximum number of iterations for optimization. + threshold: Convergence threshold. + """ + in_path = Path(rds_input_path) + out_path = Path(output_rds_path) + + if not in_path.exists(): + return {"error": f"Input RDS file not found: {rds_input_path}"} + + r_script = f""" + library(scmageck) + + obj <- readRDS("{in_path}") + + # Run optimization + # Note: scmageck_optim_perturb parameters may vary by version; + # usually takes the result of eff_estimate + optim_result <- scmageck_optim_perturb( + eff_obj = obj, + max_iter = {max_iter}, + tol = {threshold} + ) + + saveRDS(optim_result, file = "{out_path}") + """ + + try: + process = subprocess.run( + ["Rscript", "-e", r_script], + capture_output=True, + text=True, + check=True + ) + return { + "command_executed": "scmageck_optim_perturb", + "stdout": process.stdout, + "stderr": process.stderr, + "output_files": [str(out_path)] + } + except subprocess.CalledProcessError as e: + return { + "error": "R execution failed", + "stdout": e.stdout, + "stderr": e.stderr + } + +@mcp.tool() +def scmageck_get_score( + rds_input_path: str, + output_csv_path: str +): + """ + Extract scores/p-values from a processed scmageck RDS object. + + Args: + rds_input_path: Path to the RDS file generated by scmageck_lr or eff_estimate. + output_csv_path: Path to save the extracted scores as CSV. + """ + in_path = Path(rds_input_path) + out_path = Path(output_csv_path) + + if not in_path.exists(): + return {"error": "Input RDS file not found."} + + r_script = f""" + library(scmageck) + obj <- readRDS("{in_path}") + + # Extracting score logic depends on the object structure + if (is.list(obj) && "score" %in% names(obj)) {{ + write.csv(obj$score, file = "{out_path}") + }} else {{ + # Fallback for matrix results + write.csv(as.data.frame(obj), file = "{out_path}") + }} + """ + + try: + process = subprocess.run( + ["Rscript", "-e", r_script], + capture_output=True, + text=True, + check=True + ) + return { + "command_executed": "scmageck_get_score", + "stdout": process.stdout, + "stderr": process.stderr, + "output_files": [str(out_path)] + } + except subprocess.CalledProcessError as e: + return { + "error": "R execution failed", + "stdout": e.stdout, + "stderr": e.stderr + } \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scmageck/app/bioconductor-scmageck_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scmageck/app/bioconductor-scmageck_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..9b1834557f6cba6b9bd2e98af60ca143dffaa12d --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scmageck/app/bioconductor-scmageck_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scmageck/app/bioconductor-scmageck_server.py') +SERVER_NAME = 'biosci_bioconductor_scmageck' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scmageck/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scmageck/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..d8b52be87679997a875f56ca4fd7e866ffb2037e --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scmageck/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-bioconductor-scmageck: + build: . + image: mcp-bioconductor-scmageck:latest + container_name: mcp-bioconductor-scmageck + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=bioconductor-scmageck + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scmageck/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scmageck/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..ce0115c2ac316e90558b3f5a4f73c8a8d45677b2 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scmageck/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - bioconductor-scmageck + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scmageck/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scmageck/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scmageck/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scrnaseq/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scrnaseq/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..6935960696a97733edffdcdabac83c9f0cfb8ff3 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scrnaseq/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install bioconductor-scrnaseq via conda (e.g., from bioconda) +RUN conda install -c bioconda bioconductor-scrnaseq -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY bioconductor-scrnaseq_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/bioconductor-scrnaseq_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/bioconductor-scrnaseq_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scrnaseq/app/bioconductor-scrnaseq_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scrnaseq/app/bioconductor-scrnaseq_server.py new file mode 100644 index 0000000000000000000000000000000000000000..d408b5ebdd5929347dec7d8b059d5640bcb2ba14 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scrnaseq/app/bioconductor-scrnaseq_server.py @@ -0,0 +1,116 @@ +import subprocess +from pathlib import Path +from typing import Optional, List, Dict, Any + +# @mcp.tool is a placeholder for the actual decorator in the MCP environment. +# No need to import it in the final code. + +@mcp.tool() +def run_rscript( + script_file: Optional[Path] = None, + expressions: Optional[List[str]] = None, + script_args: Optional[List[str]] = None, + verbose: bool = False, + default_packages: Optional[str] = None, + save: bool = False, + no_environ: bool = False, + no_site_file: bool = False, + no_init_file: bool = False, + restore: bool = False, + vanilla: bool = False, +) -> Dict[str, Any]: + """ + Executes an R script or R expressions using the Rscript command-line tool. + + This tool serves as a wrapper for Rscript, allowing execution of R code from + the command line. It is commonly used to run scripts that utilize libraries + from repositories like Bioconductor (e.g., for scRNA-seq analysis). You must + provide either a script file to run or a list of expressions to evaluate. + + Args: + script_file: Path to the R script file to be executed. Mutually exclusive with 'expressions'. + expressions: A list of R expressions to be executed. Mutually exclusive with 'script_file'. + script_args: A list of arguments to be passed to the R script itself. + verbose: If True, prints information on progress. Corresponds to --verbose. + default_packages: A comma-separated list of package names to be loaded by default, or 'NULL'. Corresponds to --default-packages. + save: If True, saves the workspace at the end of the session. Corresponds to --save. + no_environ: If True, does not read the site and user environment files. Corresponds to --no-environ. + no_site_file: If True, does not read the site-wide Rprofile. Corresponds to --no-site-file. + no_init_file: If True, does not read the user R profile. Corresponds to --no-init-file. + restore: If True, restores previously saved objects at startup. Corresponds to --restore. + vanilla: If True, combines --no-save, --no-restore, --no-site-file, --no-init-file, and --no-environ. + + Returns: + A dictionary containing the executed command, stdout, stderr, and a list of output files. + The 'output_files' list will be empty as Rscript itself does not define output files; + any files created are determined by the R code being executed. + """ + # 1. Input Validation + if script_file is None and (expressions is None or not expressions): + raise ValueError("Either 'script_file' or a non-empty 'expressions' list must be provided.") + if script_file is not None and expressions is not None: + raise ValueError("'script_file' and 'expressions' are mutually exclusive and cannot be used together.") + if script_file and not script_file.is_file(): + raise FileNotFoundError(f"Input script file not found or is not a file: {script_file}") + + # 2. Command Construction + cmd = ["Rscript"] + + if verbose: + cmd.append("--verbose") + if default_packages: + cmd.append(f"--default-packages={default_packages}") + if save: + cmd.append("--save") + if no_environ: + cmd.append("--no-environ") + if no_site_file: + cmd.append("--no-site-file") + if no_init_file: + cmd.append("--no-init-file") + if restore: + cmd.append("--restore") + if vanilla: + cmd.append("--vanilla") + + if expressions: + for expr in expressions: + cmd.extend(["-e", expr]) + elif script_file: + cmd.append(str(script_file)) + + if script_args: + cmd.extend(script_args) + + command_executed = " ".join(cmd) + + # 3. Subprocess Execution and Error Handling + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + ) + stdout = result.stdout + stderr = result.stderr + except FileNotFoundError: + # This error is caught if 'Rscript' is not in the system's PATH + raise RuntimeError("Rscript not found. Please ensure R is installed and in your system's PATH.") + except subprocess.CalledProcessError as e: + # This error is caught if Rscript returns a non-zero exit code + return { + "error": "Rscript execution failed with a non-zero exit code.", + "command_executed": command_executed, + "stdout": e.stdout, + "stderr": e.stderr, + "return_code": e.returncode, + } + + # 4. Structured Result Return + return { + "command_executed": command_executed, + "stdout": stdout, + "stderr": stderr, + "output_files": [] + } \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scrnaseq/app/bioconductor-scrnaseq_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scrnaseq/app/bioconductor-scrnaseq_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..ee9e0583947519b824a95a220c76b8aa9bfd7082 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scrnaseq/app/bioconductor-scrnaseq_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scrnaseq/app/bioconductor-scrnaseq_server.py') +SERVER_NAME = 'biosci_bioconductor_scrnaseq' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scrnaseq/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scrnaseq/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..8549e865843268bd4f159a5c4a3a0ebc0224e44b --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scrnaseq/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-bioconductor-scrnaseq: + build: . + image: mcp-bioconductor-scrnaseq:latest + container_name: mcp-bioconductor-scrnaseq + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=bioconductor-scrnaseq + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scrnaseq/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scrnaseq/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..bb6a1f695b37cabd5682568ab5e2361a96feab94 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scrnaseq/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - bioconductor-scrnaseq + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scrnaseq/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scrnaseq/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scrnaseq/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-singlecellmultimodal/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-singlecellmultimodal/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..87c58c18dc99720b13df8531fe3ec735a53a472d --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-singlecellmultimodal/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install bioconductor-singlecellmultimodal via conda (e.g., from bioconda) +RUN conda install -c bioconda bioconductor-singlecellmultimodal -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY bioconductor-singlecellmultimodal_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/bioconductor-singlecellmultimodal_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/bioconductor-singlecellmultimodal_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-singlecellmultimodal/app/bioconductor-singlecellmultimodal_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-singlecellmultimodal/app/bioconductor-singlecellmultimodal_server.py new file mode 100644 index 0000000000000000000000000000000000000000..8d9f88e48b26b28ffaf85bf24967f5017bd10ae4 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-singlecellmultimodal/app/bioconductor-singlecellmultimodal_server.py @@ -0,0 +1,143 @@ +import subprocess +import logging +from pathlib import Path +from typing import Optional, List, Dict, Any + +# Configure logging +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + +# MCP decorator is not defined here, but the function is written +# to be compatible with it, as per the instructions. +# from mcp import tool as mcp_tool +# For demonstration, we'll use a placeholder decorator. +class mcp: + @staticmethod + def tool(func): + return func + +@mcp.tool +def rscript( + script_file: Optional[Path] = None, + expressions: Optional[List[str]] = None, + script_args: Optional[List[str]] = None, + verbose: bool = False, + default_packages: Optional[str] = None, + save: bool = False, + no_environ: bool = False, + no_site_file: bool = False, + no_init_file: bool = False, + restore: bool = False, + vanilla: bool = False, +) -> Dict[str, Any]: + """ + Executes an R script or R expressions using the Rscript command-line tool. + + This tool serves as a wrapper around Rscript, allowing for the execution of R code + either from a file or directly from command-line expressions. It supports various + options to control the R session's environment and behavior. + + Args: + script_file: Path to the R script file to be executed. Mutually exclusive with 'expressions'. + expressions: A list of R expressions to execute. Mutually exclusive with 'script_file'. + script_args: A list of arguments to be passed to the R script specified by 'script_file'. + verbose: If True, prints information on progress. + default_packages: A comma-separated list of package names to be loaded by default. + save: If True, the workspace will be saved at the end of the session. Ignored if 'vanilla' is True. + no_environ: If True, site and user environment files will not be read. Ignored if 'vanilla' is True. + no_site_file: If True, the site-wide Rprofile will not be read. Ignored if 'vanilla' is True. + no_init_file: If True, the user's R profile will not be read. Ignored if 'vanilla' is True. + restore: If True, previously saved objects will be restored at startup. Ignored if 'vanilla' is True. + vanilla: If True, combines --no-save, --no-restore, --no-site-file, --no-init-file, and --no-environ. + This provides a "clean" R session. + + Returns: + A dictionary containing the executed command, stdout, stderr, and a list of potential output files. + """ + # 1. Input Validation + if not script_file and not expressions: + raise ValueError("Either 'script_file' or 'expressions' must be provided.") + if script_file and expressions: + raise ValueError("'script_file' and 'expressions' are mutually exclusive.") + if script_args and not script_file: + raise ValueError("'script_args' can only be used when a 'script_file' is specified.") + + if script_file: + if not script_file.is_file(): + raise FileNotFoundError(f"The specified script file does not exist: {script_file}") + + # 2. Command Construction + command = ["Rscript"] + + # The --vanilla flag is a combination of other flags. + if vanilla: + command.append("--vanilla") + else: + if save: + command.append("--save") + if no_environ: + command.append("--no-environ") + if no_site_file: + command.append("--no-site-file") + if no_init_file: + command.append("--no-init-file") + if restore: + command.append("--restore") + + if verbose: + command.append("--verbose") + + if default_packages: + command.append(f"--default-packages={default_packages}") + + # Add the script file or expressions to the command + if expressions: + for expr in expressions: + command.extend(["-e", expr]) + elif script_file: + command.append(str(script_file)) + if script_args: + command.extend(script_args) + + command_str = " ".join(command) + logger.info(f"Executing command: {command_str}") + + # 3. Subprocess Execution + try: + result = subprocess.run( + command, + capture_output=True, + text=True, + check=True, + ) + stdout = result.stdout + stderr = result.stderr + logger.info("Rscript executed successfully.") + + except FileNotFoundError: + logger.error("Rscript not found. Please ensure R is installed and in your PATH.") + return { + "command_executed": command_str, + "stdout": "", + "stderr": "Error: Rscript command not found. Please ensure R is installed and in your system's PATH.", + "output_files": [] + } + except subprocess.CalledProcessError as e: + logger.error(f"Rscript execution failed with return code {e.returncode}.") + logger.error(f"Stderr: {e.stderr}") + return { + "command_executed": command_str, + "stdout": e.stdout, + "stderr": e.stderr, + "output_files": [] + } + + # 4. Structured Result Return + # Rscript itself does not define output files; the script being run does. + # The list of output_files is therefore empty unless explicitly handled. + return { + "command_executed": command_str, + "stdout": stdout, + "stderr": stderr, + "output_files": [] + } \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-singlecellmultimodal/app/bioconductor-singlecellmultimodal_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-singlecellmultimodal/app/bioconductor-singlecellmultimodal_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..9a7ea8fd3004575447ded422234ed514577e5890 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-singlecellmultimodal/app/bioconductor-singlecellmultimodal_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-singlecellmultimodal/app/bioconductor-singlecellmultimodal_server.py') +SERVER_NAME = 'biosci_bioconductor_singlecellmultimodal' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-singlecellmultimodal/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-singlecellmultimodal/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..a6f42b0a459288cb5086ca83ad44e9ad694c6bdb --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-singlecellmultimodal/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-bioconductor-singlecellmultimodal: + build: . + image: mcp-bioconductor-singlecellmultimodal:latest + container_name: mcp-bioconductor-singlecellmultimodal + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=bioconductor-singlecellmultimodal + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-singlecellmultimodal/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-singlecellmultimodal/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..30cfd95ed178d3a724fdc76a21229d88702c0edc --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-singlecellmultimodal/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - bioconductor-singlecellmultimodal + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-singlecellmultimodal/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-singlecellmultimodal/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-singlecellmultimodal/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spaniel/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spaniel/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..9dbd68e1fb55260579019aed1a41043a433e47dd --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spaniel/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install bioconductor-spaniel via conda (e.g., from bioconda) +RUN conda install -c bioconda bioconductor-spaniel -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY bioconductor-spaniel_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/bioconductor-spaniel_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/bioconductor-spaniel_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spaniel/app/bioconductor-spaniel_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spaniel/app/bioconductor-spaniel_server.py new file mode 100644 index 0000000000000000000000000000000000000000..660588ac66e4448135d06a03765c02ef0ad96d81 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spaniel/app/bioconductor-spaniel_server.py @@ -0,0 +1,144 @@ +import subprocess +import logging +from pathlib import Path +from typing import Optional, List + +# Set up logging +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + +# Mock mcp.tool decorator for standalone execution +def mcp_tool_mock(): + def decorator(func): + def wrapper(*args, **kwargs): + return func(*args, **kwargs) + return wrapper + return decorator + +mcp = type('mcp', (), {'tool': mcp_tool_mock}) + +@mcp.tool() +def rscript( + script_file: Optional[Path] = None, + expressions: Optional[List[str]] = None, + script_args: Optional[List[str]] = None, + version: bool = False, + verbose: bool = False, + default_packages: Optional[str] = None, + vanilla: bool = False, + save: bool = False, + no_environ: bool = False, + no_site_file: bool = False, + no_init_file: bool = False, + restore: bool = False +): + """ + Executes an R script or R expressions using the Rscript command-line tool. + + This tool serves as a wrapper for Rscript, the non-interactive R interpreter. + It can be used to run bioinformatics scripts, such as those utilizing + Bioconductor packages. You must provide either a script file to execute or + a list of R expressions. + + Args: + script_file: Path to the R script file to be executed. + expressions: A list of R expressions to execute. Use instead of script_file. + script_args: A list of arguments to be passed to the R script itself. + version: If True, print the R version and exit. + verbose: If True, enable verbose output, printing progress information. + default_packages: A comma-separated list of package names to be loaded by default. + vanilla: If True, combines --no-save, --no-restore, --no-site-file, + --no-init-file, and --no-environ. Overrides individual flags. + save: If True, save the workspace at the end of the session. Ignored if vanilla is True. + no_environ: If True, do not read site and user environment files. Ignored if vanilla is True. + no_site_file: If True, do not read the site-wide Rprofile. Ignored if vanilla is True. + no_init_file: If True, do not read the user R profile. Ignored if vanilla is True. + restore: If True, restore previously saved objects at startup. Ignored if vanilla is True. + + Returns: + A dictionary containing the executed command, stdout, stderr, and a list of output files. + Note: Rscript itself does not define output files; any files created are determined by the + script being executed. This tool does not track those files. + """ + # --- Input Validation --- + if version: + if script_file or expressions: + logger.warning("--version is set; other execution arguments like script_file and expressions will be ignored.") + elif not script_file and not expressions: + raise ValueError("You must provide either 'script_file' or 'expressions' to execute.") + elif script_file and expressions: + raise ValueError("You cannot provide both 'script_file' and 'expressions'. Please choose one.") + + if script_file and not script_file.is_file(): + raise FileNotFoundError(f"The specified script file does not exist: {script_file}") + + # --- Command Construction --- + cmd = ["Rscript"] + + if version: + cmd.append("--version") + else: + # Add R environment options + if vanilla: + cmd.append("--vanilla") + else: + if save: + cmd.append("--save") + if no_environ: + cmd.append("--no-environ") + if no_site_file: + cmd.append("--no-site-file") + if no_init_file: + cmd.append("--no-init-file") + if restore: + cmd.append("--restore") + + # Add other options + if verbose: + cmd.append("--verbose") + if default_packages: + cmd.append(f"--default-packages={default_packages}") + + # Add the script file or expressions to execute + if script_file: + cmd.append(str(script_file)) + elif expressions: + for expr in expressions: + cmd.extend(["-e", expr]) + + # Add arguments for the script itself + if script_args: + cmd.extend(script_args) + + # --- Subprocess Execution --- + command_executed = " ".join(cmd) + logger.info(f"Executing command: {command_executed}") + + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True + ) + stdout = result.stdout + stderr = result.stderr + logger.info("Rscript executed successfully.") + + except FileNotFoundError: + logger.error("Rscript not found. Is R installed and in your system's PATH?") + raise + except subprocess.CalledProcessError as e: + logger.error(f"Rscript execution failed with return code {e.returncode}.") + logger.error(f"STDOUT: {e.stdout}") + logger.error(f"STDERR: {e.stderr}") + # Re-raise to signal failure to the MCP controller + raise e + + # --- Structured Result Return --- + return { + "command_executed": command_executed, + "stdout": stdout, + "stderr": stderr, + "output_files": [] # Rscript itself doesn't manage output files + } \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spaniel/app/bioconductor-spaniel_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spaniel/app/bioconductor-spaniel_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..a830ff6f694f46f4b7e32054c5cb88c4b3ec1a4f --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spaniel/app/bioconductor-spaniel_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spaniel/app/bioconductor-spaniel_server.py') +SERVER_NAME = 'biosci_bioconductor_spaniel' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spaniel/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spaniel/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..e8bdb553b274706a2c79f0789f4397e161629dc9 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spaniel/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-bioconductor-spaniel: + build: . + image: mcp-bioconductor-spaniel:latest + container_name: mcp-bioconductor-spaniel + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=bioconductor-spaniel + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spaniel/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spaniel/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..e0ae5308d6c56dea2d8bb0f7777b29c3031a0218 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spaniel/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - bioconductor-spaniel + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spaniel/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spaniel/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spaniel/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spatialcpie/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spatialcpie/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..d010d9f12ec2cad4b0c4b144e3c43bcfc1cdcf43 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spatialcpie/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install bioconductor-spatialcpie via conda (e.g., from bioconda) +RUN conda install -c bioconda bioconductor-spatialcpie -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY bioconductor-spatialcpie_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/bioconductor-spatialcpie_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/bioconductor-spatialcpie_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spatialcpie/app/bioconductor-spatialcpie_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spatialcpie/app/bioconductor-spatialcpie_server.py new file mode 100644 index 0000000000000000000000000000000000000000..449d10759f0416a7fd500c474ffafaccdd7a7ab0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spatialcpie/app/bioconductor-spatialcpie_server.py @@ -0,0 +1,150 @@ +import subprocess +from pathlib import Path +from typing import List, Optional, Dict, Any + +# Assume @mcp.tool is defined elsewhere or imported. + +@mcp.tool() +def run_rscript( + script_file: Optional[Path] = None, + expressions: Optional[List[str]] = None, + script_args: Optional[List[str]] = None, + help_flag: bool = False, + version_flag: bool = False, + verbose: bool = False, + default_packages: Optional[str] = None, + save_workspace: bool = False, + no_environ: bool = False, + no_site_file: bool = False, + no_init_file: bool = False, + restore_workspace: bool = False, + vanilla: bool = False, +) -> Dict[str, Any]: + """ + Executes an R script or R expressions using the Rscript command-line tool. + + This tool provides an interface to the Rscript command, allowing users to run + R code from the command line. It supports running either a specified R script + file or direct R expressions. Various options are available to control the + R session environment, such as package loading, workspace saving/restoring, + and environment file handling. + + Args: + script_file: Path to an R script file to be executed. Mutually exclusive with 'expressions'. + expressions: A list of R expressions (strings) to be executed. Mutually exclusive with 'script_file'. + script_args: A list of arguments (strings) to be passed to the R script itself. + help_flag: If True, print usage information and exit. + version_flag: If True, print Rscript version information and exit. + verbose: If True, print information on progress during execution. + default_packages: A comma-separated list of package names to load by default, or 'NULL'. + save_workspace: If True, save the workspace at the end of the session. + no_environ: If True, do not read the site and user environment files. + no_site_file: If True, do not read the site-wide Rprofile. + no_init_file: If True, do not read the user R profile. + restore_workspace: If True, restore previously saved objects at startup. + vanilla: If True, combine --no-save, --no-restore, --no-site-file, + --no-init-file, and --no-environ. + + Returns: + A dictionary containing the command executed, stdout, stderr, and any + output files (though Rscript itself doesn't typically produce named + output files directly from the command line). + """ + # Input validation + if script_file and expressions: + raise ValueError("Cannot specify both 'script_file' and 'expressions'. Please choose one.") + if not script_file and not expressions and not help_flag and not version_flag: + raise ValueError( + "Either 'script_file' or 'expressions' must be provided, " + "unless '--help' or '--version' is requested." + ) + + if script_file: + if not script_file.exists(): + raise FileNotFoundError(f"R script file not found: {script_file}") + if not script_file.is_file(): + raise ValueError(f"Provided path is not a file: {script_file}") + + command = ["Rscript"] + + # Add Rscript options + if help_flag: + command.append("--help") + if version_flag: + command.append("--version") + if verbose: + command.append("--verbose") + if default_packages is not None: + command.append(f"--default-packages={default_packages}") + if save_workspace: + command.append("--save") + if no_environ: + command.append("--no-environ") + if no_site_file: + command.append("--no-site-file") + if no_init_file: + command.append("--no-init-file") + if restore_workspace: + command.append("--restore") + if vanilla: + command.append("--vanilla") + + # Add expressions or script file + if expressions: + for expr in expressions: + command.extend(["-e", expr]) + elif script_file: + command.append(str(script_file)) + + # Add arguments to the R script itself + if script_args: + command.extend(script_args) + + command_executed = " ".join(command) + stdout = "" + stderr = "" + output_files: List[Path] = [] + + try: + process = subprocess.run( + command, + capture_output=True, + text=True, + check=True + ) + stdout = process.stdout + stderr = process.stderr + except subprocess.CalledProcessError as e: + return { + "command_executed": command_executed, + "stdout": e.stdout, + "stderr": e.stderr, + "error": f"Rscript execution failed with exit code {e.returncode}: {e}", + "returncode": e.returncode, + "output_files": output_files, + } + except FileNotFoundError: + return { + "command_executed": command_executed, + "stdout": "", + "stderr": "Rscript command not found. Please ensure R is installed and in your system's PATH.", + "error": "Rscript executable not found.", + "returncode": 127, + "output_files": output_files, + } + except Exception as e: + return { + "command_executed": command_executed, + "stdout": stdout, + "stderr": stderr, + "error": f"An unexpected error occurred: {e}", + "returncode": 1, # Generic error code + "output_files": output_files, + } + + return { + "command_executed": command_executed, + "stdout": stdout, + "stderr": stderr, + "output_files": output_files, + } \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spatialcpie/app/bioconductor-spatialcpie_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spatialcpie/app/bioconductor-spatialcpie_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..a49013b626f0fc05621c296bd9f2db649428010b --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spatialcpie/app/bioconductor-spatialcpie_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spatialcpie/app/bioconductor-spatialcpie_server.py') +SERVER_NAME = 'biosci_bioconductor_spatialcpie' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spatialcpie/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spatialcpie/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..af22e63eb3cf1dfabb2a5af22b6e7f0461e24b2e --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spatialcpie/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-bioconductor-spatialcpie: + build: . + image: mcp-bioconductor-spatialcpie:latest + container_name: mcp-bioconductor-spatialcpie + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=bioconductor-spatialcpie + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spatialcpie/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spatialcpie/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..7def5d0efb796363bb7babf86d4339b4525e0ee9 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spatialcpie/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - bioconductor-spatialcpie + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spatialcpie/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spatialcpie/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spatialcpie/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-xvector/app/bioconductor-xvector_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-xvector/app/bioconductor-xvector_server.py new file mode 100644 index 0000000000000000000000000000000000000000..b53f4542fca2d6e83dff9ff3930eebc0201aa345 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-xvector/app/bioconductor-xvector_server.py @@ -0,0 +1,342 @@ +import subprocess +import os +from pathlib import Path +from typing import Optional, List, Union, Dict, Any +import json +import tempfile + +def _run_r_command(script: str) -> dict: + """ + Helper function to execute R code via Rscript. + """ + if not subprocess.run(["which", "Rscript"], capture_output=True).returncode == 0: + raise RuntimeError("Rscript not found. Please ensure R and Bioconductor-XVector are installed.") + + # Check if XVector is installed in R + check_pkg = "if (!requireNamespace('XVector', quietly = TRUE)) quit(status = 1)" + if subprocess.run(["Rscript", "-e", check_pkg]).returncode != 0: + raise RuntimeError("R package 'XVector' is not installed.") + + try: + result = subprocess.run( + ["Rscript", "-e", script], + capture_output=True, + text=True, + check=True + ) + return { + "stdout": result.stdout, + "stderr": result.stderr, + "status": "success" + } + except subprocess.CalledProcessError as e: + return { + "stdout": e.stdout, + "stderr": e.stderr, + "status": "error", + "error_msg": str(e) + } + +@mcp.tool() +def xvector_get_info( + rds_path: str +) -> Dict[str, Any]: + """ + Retrieve metadata about an XVector object stored in an RDS file. + + Args: + rds_path: Path to the .rds file containing the XVector object. + """ + path = Path(rds_path) + if not path.exists(): + return {"error": f"File {rds_path} not found."} + + script = f""" + library(XVector) + obj <- readRDS('{rds_path}') + cat(paste0('class:', class(obj), '\\n')) + cat(paste0('length:', length(obj), '\\n')) + cat(paste0('typeof:', typeof(obj), '\\n')) + if (is(obj, 'XVectorList')) {{ + cat(paste0('element_lengths:', paste(elementNROWS(obj), collapse=','), '\\n')) + }} + """ + + res = _run_r_command(script) + return { + "command_executed": f"Rscript -e \"{script.strip()}\"", + "stdout": res.get("stdout"), + "stderr": res.get("stderr"), + "status": res.get("status") + } + +@mcp.tool() +def xvector_subseq( + input_rds: str, + output_rds: str, + start: Optional[int] = None, + end: Optional[int] = None, + width: Optional[int] = None +) -> Dict[str, Any]: + """ + Extract a subsequence from an XVector object using subseq(). + + Args: + input_rds: Path to input .rds file. + output_rds: Path to save the resulting .rds file. + start: The start index of the subsequence. + end: The end index of the subsequence. + width: The width of the subsequence. + """ + input_path = Path(input_rds) + if not input_path.exists(): + return {"error": f"Input file {input_rds} not found."} + + # Build R arguments + args = [] + if start is not None: args.append(f"start={start}") + if end is not None: args.append(f"end={end}") + if width is not None: args.append(f"width={width}") + + arg_str = ", ".join(args) + if arg_str: + arg_str = ", " + arg_str + + script = f""" + library(XVector) + x <- readRDS('{input_rds}') + res <- subseq(x{arg_str}) + saveRDS(res, '{output_rds}') + """ + + res = _run_r_command(script) + return { + "command_executed": f"subseq(x{arg_str})", + "stdout": res.get("stdout"), + "stderr": res.get("stderr"), + "output_files": [output_rds] if res.get("status") == "success" else [] + } + +@mcp.tool() +def xvector_narrow( + input_rds: str, + output_rds: str, + start: int = 1, + end: Optional[int] = None, + width: Optional[int] = None +) -> Dict[str, Any]: + """ + Narrow an XVector object. Unlike subseq, narrow creates a view without copying data. + + Args: + input_rds: Path to input .rds file. + output_rds: Path to save the resulting .rds file. + start: Relative start offset. + end: Relative end offset. + width: Desired width. + """ + input_path = Path(input_rds) + if not input_path.exists(): + return {"error": f"Input file {input_rds} not found."} + + args = [f"start={start}"] + if end is not None: args.append(f"end={end}") + if width is not None: args.append(f"width={width}") + + arg_str = ", ".join(args) + + script = f""" + library(XVector) + x <- readRDS('{input_rds}') + res <- narrow(x, {arg_str}) + saveRDS(res, '{output_rds}') + """ + + res = _run_r_command(script) + return { + "command_executed": f"narrow(x, {arg_str})", + "stdout": res.get("stdout"), + "stderr": res.get("stderr"), + "output_files": [output_rds] + } + +@mcp.tool() +def xvector_compact( + input_rds: str, + output_rds: str +) -> Dict[str, Any]: + """ + Compact an XVector object to force memory deallocation of unused parts of the external vector. + + Args: + input_rds: Path to input .rds file. + output_rds: Path to save the compacted .rds file. + """ + input_path = Path(input_rds) + if not input_path.exists(): + return {"error": f"Input file {input_rds} not found."} + + script = f""" + library(XVector) + x <- readRDS('{input_rds}') + res <- compact(x) + saveRDS(res, '{output_rds}') + """ + + res = _run_r_command(script) + return { + "command_executed": "compact(x)", + "stdout": res.get("stdout"), + "stderr": res.get("stderr"), + "output_files": [output_rds] + } + +@mcp.tool() +def xvector_slice( + input_rds: str, + lower: float = -float('inf'), + upper: float = float('inf') +) -> Dict[str, Any]: + """ + Slice an XInteger or XDouble vector to find ranges where values are within [lower, upper]. + Returns a summary of the ranges. + + Args: + input_rds: Path to input .rds file. + lower: Lower bound for slicing. + upper: Upper bound for slicing. + """ + input_path = Path(input_rds) + if not input_path.exists(): + return {"error": f"Input file {input_rds} not found."} + + # Handle infinity for R + r_lower = "-Inf" if lower == -float('inf') else lower + r_upper = "Inf" if upper == float('inf') else upper + + script = f""" + library(XVector) + x <- readRDS('{input_rds}') + sl <- slice(x, lower={r_lower}, upper={r_upper}) + print(sl) + """ + + res = _run_r_command(script) + return { + "command_executed": f"slice(x, lower={r_lower}, upper={r_upper})", + "stdout": res.get("stdout"), + "stderr": res.get("stderr") + } + +@mcp.tool() +def xvector_to_raw( + input_rds: str, + output_bin: str +) -> Dict[str, Any]: + """ + Export the raw content of an XVector to a binary file. + + Args: + input_rds: Path to input .rds file. + output_bin: Path to the output binary file. + """ + input_path = Path(input_rds) + if not input_path.exists(): + return {"error": f"Input file {input_rds} not found."} + + script = f""" + library(XVector) + x <- readRDS('{input_rds}') + # Ensure it is an XRaw or similar + writeBin(as.raw(x), '{output_bin}') + """ + + res = _run_r_command(script) + return { + "command_executed": "writeBin(as.raw(x), ...)", + "stdout": res.get("stdout"), + "stderr": res.get("stderr"), + "output_files": [output_bin] + } + +@mcp.tool() +def xvector_aggregate( + input_rds: str, + method: str = "sum" +) -> Dict[str, Any]: + """ + Perform aggregation on an XVector (sum, mean, min, max). + + Args: + input_rds: Path to input .rds file. + method: Aggregation method ('sum', 'mean', 'min', 'max'). + """ + if method not in ["sum", "mean", "min", "max"]: + return {"error": "Method must be one of: sum, mean, min, max"} + + input_path = Path(input_rds) + if not input_path.exists(): + return {"error": f"Input file {input_rds} not found."} + + script = f""" + library(XVector) + x <- readRDS('{input_rds}') + val <- {method}(x, na.rm=TRUE) + cat(val) + """ + + res = _run_r_command(script) + return { + "command_executed": f"{method}(x)", + "stdout": res.get("stdout"), + "stderr": res.get("stderr"), + "result": res.get("stdout").strip() if res.get("status") == "success" else None + } + +@mcp.tool() +def xvector_create_from_list( + data: List[float], + type: str = "double", + output_rds: str = "vector.rds" +) -> Dict[str, Any]: + """ + Create an XVector object from a Python list and save as RDS. + + Args: + data: List of numeric values. + type: Type of XVector to create ('integer', 'double', 'raw'). + output_rds: Filename for the output RDS. + """ + if type not in ["integer", "double", "raw"]: + return {"error": "Type must be 'integer', 'double', or 'raw'"} + + # Create a temporary file for the data to pass to R + with tempfile.NamedTemporaryFile(mode='w', suffix='.json', delete=False) as tmp: + json.dump(data, tmp) + tmp_path = tmp.name + + r_class = { + "integer": "XInteger", + "double": "XDouble", + "raw": "XRaw" + }[type] + + script = f""" + library(XVector) + library(jsonlite) + raw_data <- fromJSON('{tmp_path}') + vec <- as(raw_data, '{r_class}') + saveRDS(vec, '{output_rds}') + """ + + try: + res = _run_r_command(script) + return { + "command_executed": f"as(data, '{r_class}')", + "stdout": res.get("stdout"), + "stderr": res.get("stderr"), + "output_files": [output_rds] + } + finally: + if os.path.exists(tmp_path): + os.remove(tmp_path) \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-xvector/app/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-xvector/app/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-xvector/app/requirements.txt @@ -0,0 +1 @@ + diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-zlibbioc/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-zlibbioc/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..48bafb10c18bb5ffc2209a4f57ce2b58af3f38a3 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-zlibbioc/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install bioconductor-zlibbioc via conda (e.g., from bioconda) +RUN conda install -c bioconda bioconductor-zlibbioc -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY app/bioconductor-zlibbioc_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/bioconductor-zlibbioc_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/bioconductor-zlibbioc_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-zlibbioc/app/bioconductor-zlibbioc_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-zlibbioc/app/bioconductor-zlibbioc_server.py new file mode 100644 index 0000000000000000000000000000000000000000..4a770418dda4a68dded2fed1465752b979c1d46d --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-zlibbioc/app/bioconductor-zlibbioc_server.py @@ -0,0 +1,172 @@ +import subprocess +from pathlib import Path +from typing import List, Optional, Dict, Any + +# Assume @mcp.tool is imported from the mcp library +# from mcp import tool + +@mcp.tool() +def run_rscript( + r_script_file: Optional[Path] = None, + expressions: Optional[List[str]] = None, + r_script_args: Optional[List[str]] = None, + help_flag: bool = False, + version_flag: bool = False, + verbose: bool = False, + default_packages: Optional[str] = None, + save: bool = False, + no_environ: bool = False, + no_site_file: bool = False, + no_init_file: bool = False, + restore: bool = False, + vanilla: bool = False, +) -> Dict[str, Any]: + """ + Executes an R script file or R expressions using the Rscript command. + + This tool provides an interface to the Rscript command, allowing users to run R code + from the command line, either by specifying a script file or by providing R expressions + directly. It supports various Rscript options for controlling the R session behavior. + + Args: + r_script_file: Path to an R script file to execute. Mutually exclusive with 'expressions'. + The file must exist. + expressions: A list of R expressions to execute. Each string in the list will be + passed with a separate '-e' flag. Mutually exclusive with 'r_script_file'. + r_script_args: A list of arguments to be passed to the R script itself. These are + appended after the script file or expressions. + help_flag: If True, print usage information and exit. When True, all other parameters + related to script execution are ignored. + version_flag: If True, print version information and exit. When True, all other parameters + related to script execution are ignored. + verbose: If True, print information on progress during Rscript execution. + default_packages: A comma-separated list of package names, or 'NULL', to load by default. + If None, this option is not included. + save: If True, save the workspace at the end of the session. Cannot be used with 'vanilla'. + no_environ: If True, don't read the site and user environment files. + This is implied by 'vanilla'. + no_site_file: If True, don't read the site-wide Rprofile. + This is implied by 'vanilla'. + no_init_file: If True, don't read the user R profile. + This is implied by 'vanilla'. + restore: If True, restore previously saved objects at startup. Cannot be used with 'vanilla'. + vanilla: If True, combine --no-save, --no-restore, --no-site-file, --no-init-file, + and --no-environ. Cannot be used with 'save' or 'restore'. + + Returns: + A dictionary containing the command executed, stdout, stderr, and any output files. + 'output_files' will typically be empty unless the R script itself creates files + in a known location. + """ + cmd = ["Rscript"] + output_files: List[Path] = [] + + # Handle --help and --version first, as they are standalone and override other options + if help_flag: + cmd.append("--help") + elif version_flag: + cmd.append("--version") + else: + # Input validation for script/expressions + if r_script_file and expressions: + raise ValueError("Cannot specify both 'r_script_file' and 'expressions'. Choose one.") + if not r_script_file and not expressions: + raise ValueError("Either 'r_script_file' or 'expressions' must be provided.") + + # Validate --vanilla conflicts + if vanilla: + conflicting_options = [] + if save: + conflicting_options.append("--save") + if restore: + conflicting_options.append("--restore") + if conflicting_options: + raise ValueError( + f"Cannot use --vanilla with conflicting options: {', '.join(conflicting_options)}. " + "--vanilla implies --no-save and --no-restore." + ) + + # Add general options + if verbose: + cmd.append("--verbose") + if default_packages is not None: + cmd.append(f"--default-packages={default_packages}") + + # Add R session options + if vanilla: + cmd.append("--vanilla") + else: + # Only add these if vanilla is not set, to avoid redundancy and potential conflicts + if save: + cmd.append("--save") + if no_environ: + cmd.append("--no-environ") + if no_site_file: + cmd.append("--no-site-file") + if no_init_file: + cmd.append("--no-init-file") + if restore: + cmd.append("--restore") + + # Handle script file vs expressions + if r_script_file: + if not r_script_file.is_file(): + raise FileNotFoundError(f"R script file not found: {r_script_file}") + cmd.append(str(r_script_file)) + elif expressions: + for expr in expressions: + cmd.extend(["-e", expr]) + + # Add arguments to the R script + if r_script_args: + cmd.extend(r_script_args) + + try: + process = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True + ) + stdout = process.stdout + stderr = process.stderr + command_executed = " ".join(cmd) + + return { + "command_executed": command_executed, + "stdout": stdout, + "stderr": stderr, + "output_files": output_files, + } + except FileNotFoundError: + # This specific error means the 'Rscript' executable itself was not found + return { + "command_executed": " ".join(cmd), + "stdout": "", + "stderr": "Error: Rscript command not found. Please ensure R is installed and 'Rscript' is in your system's PATH.", + "output_files": [], + } + except subprocess.CalledProcessError as e: + # This means Rscript ran, but exited with a non-zero status + return { + "command_executed": " ".join(cmd), + "stdout": e.stdout, + "stderr": e.stderr, + "output_files": [], + } + except ValueError as e: + # Catch validation errors before subprocess call + return { + "command_executed": " ".join(cmd), + "stdout": "", + "stderr": f"Input validation error: {e}", + "output_files": [], + } + except Exception as e: + # Catch any other unexpected errors + return { + "command_executed": " ".join(cmd), + "stdout": "", + "stderr": f"An unexpected error occurred: {e}", + "output_files": [], + } \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-zlibbioc/app/bioconductor-zlibbioc_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-zlibbioc/app/bioconductor-zlibbioc_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..f70f867cd8e6e8f42b9b42afe798ece33628d3db --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-zlibbioc/app/bioconductor-zlibbioc_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-zlibbioc/app/bioconductor-zlibbioc_server.py') +SERVER_NAME = 'biosci_bioconductor_zlibbioc' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-zlibbioc/app/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-zlibbioc/app/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-zlibbioc/app/requirements.txt @@ -0,0 +1 @@ + diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-zlibbioc/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-zlibbioc/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..0725bb33611e65ca6c39a977c9733243aa80647c --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-zlibbioc/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-bioconductor-zlibbioc: + build: . + image: mcp-bioconductor-zlibbioc:latest + container_name: mcp-bioconductor-zlibbioc + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=bioconductor-zlibbioc + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-zlibbioc/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-zlibbioc/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..4d1768c84dd8493e0a4816be7680761fd5fb9a40 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-zlibbioc/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - bioconductor-zlibbioc + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-zlibbioc/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-zlibbioc/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-zlibbioc/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..e92733ea1e0f47e2a97581359f7a5c599ccda71a --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install bowtie via conda (e.g., from bioconda) +RUN conda install -c bioconda bowtie -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY app/bowtie_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/bowtie_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/bowtie_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie/app/bowtie_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie/app/bowtie_server.py new file mode 100644 index 0000000000000000000000000000000000000000..5c6f37b0f719388ff8c8c473751cc46c645805b2 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie/app/bowtie_server.py @@ -0,0 +1,206 @@ +import subprocess +import tempfile +from pathlib import Path +from typing import List, Optional + +# This is a placeholder for the MCP decorator. +# In a real MCP environment, this would be provided by the MCP framework. +def tool(func): + def wrapper(*args, **kwargs): + return func(*args, **kwargs) + return wrapper + +mcp = type("mcp", (), {"tool": tool}) + + +@mcp.tool +def perl( + programfile: Optional[Path] = None, + arguments: Optional[List[str]] = None, + execute_program: Optional[List[str]] = None, + execute_program_extended: Optional[List[str]] = None, + check_syntax_only: bool = False, + loop_around_program: bool = False, + loop_and_print: bool = False, + autosplit: bool = False, + split_pattern: Optional[str] = None, + in_place_edit_extension: Optional[str] = None, + include_directories: Optional[List[Path]] = None, + use_modules: Optional[List[str]] = None, + no_modules: Optional[List[str]] = None, + use_modules_no_import: Optional[List[str]] = None, + no_modules_no_import: Optional[List[str]] = None, + enable_warnings: bool = False, + enable_all_warnings: bool = False, + disable_all_warnings: bool = False, + enable_tainting_checks: bool = False, + enable_tainting_warnings: bool = False, + search_path_for_program: bool = False, + record_separator: Optional[str] = None, + enable_line_ending_processing: Optional[str] = None, + enable_switch_parsing: bool = False, + dump_core: bool = False, + allow_unsafe_operations: bool = False, + extract_program: bool = False, + extract_directory: Optional[Path] = None, + run_under_debugger: Optional[str] = None, + debugging_flags: Optional[str] = None, + unicode_features: Optional[str] = None, + disable_sitecustomize: bool = False, + print_version: bool = False, + print_config: Optional[str] = None, +) -> dict: + """ + Executes the Perl interpreter with a wide range of options. + + This tool can run a Perl script from a file, execute one-liners, check syntax, + and modify Perl's behavior with various switches for warnings, modules, + input processing, and more. + """ + # --- Input Validation --- + actionable_input = any([ + programfile, + execute_program, + execute_program_extended, + print_version, + print_config is not None, + check_syntax_only + ]) + if not actionable_input: + raise ValueError( + "Either a programfile, an executable string (-e/-E), or an action " + "like --print_version, --print_config, or --check_syntax_only must be provided." + ) + + if programfile and (execute_program or execute_program_extended): + raise ValueError("Cannot specify both a 'programfile' and an inline program via '-e' or '-E'.") + + if programfile and not programfile.exists(): + raise FileNotFoundError(f"The specified program file does not exist: {programfile}") + + if loop_around_program and loop_and_print: + raise ValueError("The flags '-n' (loop_around_program) and '-p' (loop_and_print) are mutually exclusive.") + + if enable_all_warnings and disable_all_warnings: + raise ValueError("The flags '-W' (enable_all_warnings) and '-X' (disable_all_warnings) are mutually exclusive.") + + if split_pattern and not autosplit: + raise ValueError("A 'split_pattern' (-F) can only be used with 'autosplit' mode (-a).") + + if extract_directory and not extract_program: + raise ValueError("Specifying 'extract_directory' requires 'extract_program' (-x) to be enabled.") + + # --- Command Construction --- + cmd = ["perl"] + + if record_separator is not None: + cmd.append(f"-0{record_separator}") + if autosplit: + cmd.append("-a") + if unicode_features is not None: + cmd.append(f"-C{unicode_features}") + if check_syntax_only: + cmd.append("-c") + if run_under_debugger is not None: + cmd.append(f"-d{run_under_debugger}") + if debugging_flags is not None: + cmd.append(f"-D{debugging_flags}") + if execute_program: + for prog_line in execute_program: + cmd.extend(["-e", prog_line]) + if execute_program_extended: + for prog_line in execute_program_extended: + cmd.extend(["-E", prog_line]) + if disable_sitecustomize: + cmd.append("-f") + if split_pattern: + cmd.extend(["-F", split_pattern]) + if in_place_edit_extension is not None: + cmd.append(f"-i{in_place_edit_extension}") + if include_directories: + for directory in include_directories: + cmd.extend(["-I", str(directory)]) + if enable_line_ending_processing is not None: + cmd.append(f"-l{enable_line_ending_processing}") + if use_modules: + for module in use_modules: + cmd.append(f"-M{module}") + if no_modules: + for module in no_modules: + cmd.append(f"-M-{module}") + if use_modules_no_import: + for module in use_modules_no_import: + cmd.append(f"-m{module}") + if no_modules_no_import: + for module in no_modules_no_import: + cmd.append(f"-m-{module}") + if loop_around_program: + cmd.append("-n") + if loop_and_print: + cmd.append("-p") + if enable_switch_parsing: + cmd.append("-s") + if search_path_for_program: + cmd.append("-S") + if enable_tainting_warnings: + cmd.append("-t") + if enable_tainting_checks: + cmd.append("-T") + if dump_core: + cmd.append("-u") + if allow_unsafe_operations: + cmd.append("-U") + if print_version: + cmd.append("-v") + if print_config is not None: + cmd.append(f"-V{print_config}") + if enable_warnings: + cmd.append("-w") + if enable_all_warnings: + cmd.append("-W") + if extract_program: + cmd.append("-x") + if extract_directory: + cmd.extend([str(extract_directory)]) + if disable_all_warnings: + cmd.append("-X") + + # Add program file and arguments + if programfile: + cmd.append(str(programfile)) + + if arguments: + # The '--' switch is good practice to separate perl options from script arguments + if programfile or execute_program or execute_program_extended: + cmd.append("--") + cmd.extend(arguments) + + # --- Subprocess Execution --- + command_executed = " ".join(cmd) + try: + result = subprocess.run( + cmd, + check=True, + capture_output=True, + text=True, + ) + return { + "command_executed": command_executed, + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": [] # Perl execution doesn't have a defined output file + } + except FileNotFoundError: + return { + "command_executed": command_executed, + "stdout": "", + "stderr": "Error: 'perl' command not found. Please ensure Perl is installed and in your system's PATH.", + "output_files": [] + } + except subprocess.CalledProcessError as e: + return { + "command_executed": command_executed, + "stdout": e.stdout, + "stderr": e.stderr, + "output_files": [] + } diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie/app/bowtie_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie/app/bowtie_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..d54cb40e6eafcf34f6402a2a45dbea5fdf58ca97 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie/app/bowtie_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie/app/bowtie_server.py') +SERVER_NAME = 'biosci_bowtie' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie/app/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie/app/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie/app/requirements.txt @@ -0,0 +1 @@ + diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..b590c5d861b6fcc1f695edf5c47bf23f69e96dbc --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-bowtie: + build: . + image: mcp-bowtie:latest + container_name: mcp-bowtie + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=bowtie + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a94f45ccfd6430e8677fdd9d183a45bb30cda4a9 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - bowtie + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie2/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie2/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..484df324fc962e67f03afc5f4a0efc621fb6b948 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie2/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install bowtie2 via conda (e.g., from bioconda) +RUN conda install -c bioconda bowtie2 -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY app/bowtie2_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/bowtie2_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/bowtie2_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie2/app/bowtie2_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie2/app/bowtie2_server.py new file mode 100644 index 0000000000000000000000000000000000000000..4d5d6dcff7bd10985dcfd158490b540fc04e122b --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie2/app/bowtie2_server.py @@ -0,0 +1,227 @@ +import subprocess +from pathlib import Path +from typing import List, Optional, Union + +@mcp.tool() +def run_perl_script( + script_file: Optional[Path] = None, + program_strings: Optional[List[str]] = None, + program_strings_extended: Optional[List[str]] = None, + script_arguments: Optional[List[str]] = None, + record_separator_octal: Optional[str] = None, + autosplit_mode: bool = False, + unicode_features: Optional[str] = None, + check_syntax_only: bool = False, + debugger: Optional[str] = None, + debugging_flags: Optional[str] = None, + no_sitecustomize: bool = False, + split_pattern: Optional[str] = None, + edit_in_place_extension: Optional[str] = None, + include_directories: Optional[List[Path]] = None, + line_ending_processing: Optional[str] = None, + use_modules: Optional[List[str]] = None, + no_use_modules: Optional[List[str]] = None, + loop_around_program: bool = False, + loop_and_print: bool = False, + rudimentary_switch_parsing: bool = False, + search_programfile_in_path: bool = False, + tainting_warnings: bool = False, + tainting_checks: bool = False, + dump_core_on_parse_error: bool = False, + allow_unsafe_operations: bool = False, + print_version: bool = False, + print_config_summary_variable: Optional[str] = None, + enable_warnings: bool = False, + enable_all_warnings: bool = False, + ignore_text_before_shebang_dir: Optional[Path] = None, + disable_all_warnings: bool = False, +) -> dict: + """ + Executes a Perl script or one-liner with specified switches and arguments. + + This function provides comprehensive control over the Perl interpreter, + allowing users to run Perl programs from a file or directly from a string, + and configure various aspects of its execution environment. + + Args: + script_file: Path to the Perl program file to execute. Mutually exclusive with `program_strings` and `program_strings_extended`. + program_strings: A list of Perl program lines to execute directly from the command line using the -e switch. + Multiple -e switches are allowed. Mutually exclusive with `script_file`. + program_strings_extended: A list of Perl program lines to execute directly from the command line using the -E switch. + Like -e, but enables all optional features. Multiple -E switches are allowed. + Mutually exclusive with `script_file`. + script_arguments: Arguments to be passed to the Perl script itself. These are appended after the script source. + record_separator_octal: Specifies the input record separator (-0 switch). Can be an octal number (e.g., "0777") or empty string for '\0'. + autosplit_mode: Enables autosplit mode with -n or -p (splits $_ into @F) (-a switch). Requires `loop_around_program` or `loop_and_print`. + unicode_features: Enables listed Unicode features (-C switch). Argument is a number or list (e.g., "all", "0x10"). + check_syntax_only: Check syntax only (runs BEGIN and CHECK blocks) (-c switch). + debugger: Run program under debugger (-d switch). If an empty string, uses default debugger; otherwise, specifies debugger (e.g., "MyDebugger"). + debugging_flags: Set debugging flags (argument is a bit mask or alphabets) (-D switch, e.g., "t", "1024"). + no_sitecustomize: Don't do $sitelib/sitecustomize.pl at startup (-f switch). + split_pattern: split() pattern for -a switch (//'s are optional) (-F switch, e.g., "/\s+/"). Requires `autosplit_mode`. + edit_in_place_extension: Edit <> files in place (-i switch). If an empty string, no backup is made; otherwise, specifies backup extension (e.g., ".bak"). + include_directories: Specify @INC/#include directory (several -I's allowed) (-I switch). Paths must exist. + line_ending_processing: Enable line ending processing, specifies line terminator (-l switch). Can be an octal number (e.g., "012") or empty string for newline. + use_modules: List of modules to execute "use module..." before executing program (-m or -M switch, e.g., "strict", "warnings"). + no_use_modules: List of modules to execute "no module..." before executing program (-m- or -M- switch, e.g., "strict"). + loop_around_program: Assume "while (<>) { ... }" loop around program (-n switch). + loop_and_print: Assume loop like -n but print line also, like sed (-p switch). + rudimentary_switch_parsing: Enable rudimentary parsing for switches after programfile (-s switch). + search_programfile_in_path: Look for programfile using PATH environment variable (-S switch). + tainting_warnings: Enable tainting warnings (-t switch). + tainting_checks: Enable tainting checks (-T switch). + dump_core_on_parse_error: Dump core after parsing program (-u switch). + allow_unsafe_operations: Allow unsafe operations (-U switch). + print_version: Print version, patchlevel and license (-v switch). + print_config_summary_variable: Print configuration summary (-V switch). If an empty string, prints full summary; otherwise, prints a single Config.pm variable (e.g., "osname"). + enable_warnings: Enable many useful warnings (-w switch). + enable_all_warnings: Enable all warnings (-W switch). + ignore_text_before_shebang_dir: Ignore text before #!perl line (-x switch). If an empty path, ignores text without changing directory; otherwise, changes to the specified directory. + disable_all_warnings: Disable all warnings (-X switch). + + Returns: + A dictionary containing the command executed, stdout, stderr, and any output files. + """ + command: List[Union[str, Path]] = ["perl"] + output_files: List[Path] = [] + + # --- Input Validation --- + script_source_provided = script_file is not None or program_strings is not None or program_strings_extended is not None + + if script_file and (program_strings or program_strings_extended): + raise ValueError("Cannot specify both a script file and program strings (-e/-E). Choose one.") + if not script_source_provided and not (print_version or print_config_summary_variable is not None or check_syntax_only): + # If no script source is provided, it must be a utility command like -v, -V, -c + raise ValueError("Either a script file, program strings (-e/-E), or a utility switch (-v, -V, -c) must be provided.") + + if script_file and not script_file.is_file(): + raise FileNotFoundError(f"Script file not found: {script_file}") + + if ignore_text_before_shebang_dir is not None and ignore_text_before_shebang_dir != Path("") and not ignore_text_before_shebang_dir.is_dir(): + raise NotADirectoryError(f"Directory for -x switch not found: {ignore_text_before_shebang_dir}") + + if autosplit_mode and not (loop_around_program or loop_and_print): + raise ValueError("Autosplit mode (-a) requires either loop_around_program (-n) or loop_and_print (-p).") + + if split_pattern is not None and not autosplit_mode: + raise ValueError("Split pattern (-F) requires autosplit mode (-a).") + + # --- Build Command --- + + if record_separator_octal is not None: + command.append(f"-0{record_separator_octal}") + if autosplit_mode: + command.append("-a") + if unicode_features is not None: + command.append(f"-C{unicode_features}") + if check_syntax_only: + command.append("-c") + if debugger is not None: + command.append(f"-d:{debugger}" if debugger else "-d") + if debugging_flags is not None: + command.append(f"-D{debugging_flags}") + if no_sitecustomize: + command.append("-f") + if split_pattern is not None: + command.append(f"-F{split_pattern}") + if edit_in_place_extension is not None: + command.append(f"-i{edit_in_place_extension}") + if include_directories: + for inc_dir in include_directories: + if not inc_dir.is_dir(): + raise NotADirectoryError(f"Include directory not found: {inc_dir}") + command.append(f"-I{inc_dir}") + if line_ending_processing is not None: + command.append(f"-l{line_ending_processing}") + if use_modules: + for module in use_modules: + command.append(f"-M{module}") # Using -M for 'use module' as it's common. + if no_use_modules: + for module in no_use_modules: + command.append(f"-M-{module}") # Using -M- for 'no module'. + if loop_around_program: + command.append("-n") + if loop_and_print: + command.append("-p") + if rudimentary_switch_parsing: + command.append("-s") + if search_programfile_in_path: + command.append("-S") + if tainting_warnings: + command.append("-t") + if tainting_checks: + command.append("-T") + if dump_core_on_parse_error: + command.append("-u") + if allow_unsafe_operations: + command.append("-U") + if print_version: + command.append("-v") + if print_config_summary_variable is not None: + command.append(f"-V:{print_config_summary_variable}" if print_config_summary_variable else "-V") + if enable_warnings: + command.append("-w") + if enable_all_warnings: + command.append("-W") + if ignore_text_before_shebang_dir is not None: + command.append(f"-x{ignore_text_before_shebang_dir}") + if disable_all_warnings: + command.append("-X") + + # Add program strings (-e/-E) + if program_strings: + for prog_str in program_strings: + command.extend(["-e", prog_str]) + if program_strings_extended: + for prog_str in program_strings_extended: + command.extend(["-E", prog_str]) + + # Add script file and its arguments + if script_file: + command.append(str(script_file)) + + if script_arguments: + # The `--` is typically used to separate Perl switches from script arguments + # if there's ambiguity. If the user needs `--`, they can include it as + # the first element of script_arguments. + command.extend(script_arguments) + + # Convert Path objects to strings for subprocess.run + final_command = [str(arg) for arg in command] + command_str = " ".join(final_command) + + # --- Execute Command --- + try: + process = subprocess.run( + final_command, + capture_output=True, + text=True, + check=True + ) + stdout = process.stdout + stderr = process.stderr + except subprocess.CalledProcessError as e: + return { + "command_executed": command_str, + "stdout": e.stdout, + "stderr": e.stderr, + "error": str(e), + "returncode": e.returncode, + "output_files": output_files, + } + except FileNotFoundError: + return { + "command_executed": command_str, + "stdout": "", + "stderr": "Error: 'perl' command not found. Please ensure Perl is installed and in your PATH.", + "error": "Perl executable not found.", + "returncode": 127, + "output_files": output_files, + } + + return { + "command_executed": command_str, + "stdout": stdout, + "stderr": stderr, + "output_files": output_files, + } \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie2/app/bowtie2_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie2/app/bowtie2_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..75a3a1ce190e795514985ba0e2bfd9a912d30403 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie2/app/bowtie2_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie2/app/bowtie2_server.py') +SERVER_NAME = 'biosci_bowtie2' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie2/app/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie2/app/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie2/app/requirements.txt @@ -0,0 +1 @@ + diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie2/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie2/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..add4d2c95250fdada71909666fb03ab9baf80c82 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie2/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-bowtie2: + build: . + image: mcp-bowtie2:latest + container_name: mcp-bowtie2 + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=bowtie2 + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie2/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie2/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..56712b35c54c869a0d14e760ba6372aa027278b9 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie2/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - bowtie2 + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie2/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie2/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie2/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_brooklyn_plot/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_brooklyn_plot/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..821fcc1f62c40c20276c1b35c3a537c8912da6ac --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_brooklyn_plot/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-brooklyn_plot: + build: . + image: mcp-brooklyn_plot:latest + container_name: mcp-brooklyn_plot + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=brooklyn_plot + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_brooklyn_plot/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_brooklyn_plot/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_brooklyn_plot/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bwa/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bwa/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..1c540403613c57c4f7059830d34ca4cd57ef217e --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bwa/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install bwa via conda (e.g., from bioconda) +RUN conda install -c bioconda bwa -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY app/bwa_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/bwa_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/bwa_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bwa/app/bwa_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bwa/app/bwa_server.py new file mode 100644 index 0000000000000000000000000000000000000000..e17632ce5ce5d6426dd66b5f43cee9a8e7ed533c --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bwa/app/bwa_server.py @@ -0,0 +1,774 @@ +import subprocess +from pathlib import Path +from typing import Optional, List + +# In a real MCP environment, you would import mcp. +# This is a placeholder to allow the code to be syntactically valid. +class mcp: + @staticmethod + def tool(): + def decorator(func): + return func + return decorator + +@mcp.tool() +def bwa_index( + in_fa: Path, + prefix: Optional[Path] = None, + algorithm: str = "is", + color_space: bool = False, + block_size_bwtsw: int = 10000000, + index_for_64bit_genome: bool = False, +): + """ + Constructs the BWA index for a reference genome. + + This command builds the FM-index for a reference genome in FASTA format. + The index is composed of several files, all of which are required for alignment. + + Args: + in_fa: Path to the input reference genome file in FASTA format. + prefix: Prefix for the output index files. If not provided, it defaults to the input FASTA filename. + algorithm: Algorithm for index construction. Can be 'is' (default) or 'bwtsw'. + color_space: Build a color-space index. + block_size_bwtsw: Block size for the 'bwtsw' algorithm. + index_for_64bit_genome: Index files for 64-bit genome. + + Returns: + A dictionary containing the execution details and paths to the output index files. + """ + if not in_fa.is_file(): + raise FileNotFoundError(f"Input FASTA file not found: {in_fa}") + if algorithm not in ["is", "bwtsw"]: + raise ValueError(f"Invalid algorithm '{algorithm}'. Must be 'is' or 'bwtsw'.") + + output_prefix = prefix if prefix else in_fa.with_suffix('') + + cmd = ["bwa", "index"] + if algorithm != "is": + cmd.extend(["-a", algorithm]) + if color_space: + cmd.append("-c") + if block_size_bwtsw != 10000000 and algorithm == "bwtsw": + cmd.extend(["-b", str(block_size_bwtsw)]) + if index_for_64bit_genome: + cmd.append("-6") + + cmd.extend(["-p", str(output_prefix)]) + cmd.append(str(in_fa)) + + try: + process = subprocess.run( + cmd, check=True, capture_output=True, text=True, + ) + + output_files_str = [ + f"{output_prefix}.amb", + f"{output_prefix}.ann", + f"{output_prefix}.bwt", + f"{output_prefix}.pac", + f"{output_prefix}.sa", + ] + if index_for_64bit_genome: + output_files_str[2] = f"{output_prefix}.bwt.64" + + for f in output_files_str: + if not Path(f).is_file(): + raise FileNotFoundError(f"Expected output file was not created: {f}") + + return { + "command_executed": " ".join(cmd), + "stdout": process.stdout, + "stderr": process.stderr, + "output_files": output_files_str, + } + except FileNotFoundError: + raise RuntimeError("bwa command not found. Please ensure BWA is installed and in your PATH.") + except subprocess.CalledProcessError as e: + raise RuntimeError( + f"BWA index command failed with exit code {e.returncode}.\n" + f"Stderr: {e.stderr}\n" + f"Stdout: {e.stdout}" + ) + +@mcp.tool() +def bwa_mem( + idx_prefix: Path, + in1_fq: Path, + in2_fq: Optional[Path] = None, + output_file: Optional[Path] = None, + threads: int = 1, + min_seed_len: int = 19, + band_width: int = 100, + off_diagonal_x_dropoff: int = 100, + reseeding_factor: float = 1.5, + max_mem_occurrences: int = 500, + drop_chain_threshold: float = 0.50, + mark_shorter_splits_sec: bool = False, + perform_sw_rescue: bool = False, + match_score: int = 1, + mismatch_penalty: int = 4, + gap_open_penalty: str = "6,6", + gap_extension_penalty: str = "1,1", + clipping_penalty: str = "5,5", + unpaired_read_penalty: int = 17, + interleaved_input: bool = False, + read_group_header: Optional[str] = None, + min_score_to_output: int = 30, + header: Optional[str] = None, + treat_alt_as_primary: bool = False, + verbosity_level: int = 3, + soft_clip_supplementary: bool = False, + mark_shorter_splits_picard: bool = False, + read_length_params: Optional[str] = None, + read_type: Optional[str] = None, + output_all_alignments: bool = False, + append_fastq_comment: bool = False, + output_ref_header_in_xr: bool = False, + skip_mate_rescue: bool = False, + batch_size: int = 10000000, +): + """ + Aligns 70bp-1Mbp query sequences with the BWA-MEM algorithm. + + Args: + idx_prefix: Path to the BWA index prefix. + in1_fq: Path to the FASTQ file of reads (or first reads for PE). + in2_fq: Path to the FASTQ file of second reads for paired-end data. + output_file: Path to the output SAM file. If None, output is sent to stdout. + threads: Number of threads. + min_seed_len: Minimum seed length. + band_width: Band width for chaining. + off_diagonal_x_dropoff: Off-diagonal X-dropoff. + reseeding_factor: Trigger re-seeding for a MEM longer than min_seed_len * r. + max_mem_occurrences: Discard a MEM if it has more than this many occurrences. + drop_chain_threshold: Drop chains shorter than this fraction of the longest extension. + mark_shorter_splits_sec: Mark shorter split hits as secondary. + perform_sw_rescue: Perform Smith-Waterman to rescue missing hits. + match_score: Score for a sequence match. + mismatch_penalty: Penalty for a mismatch. + gap_open_penalty: Gap open penalty as a string "INT" or "INT,INT". + gap_extension_penalty: Gap extension penalty as a string "INT" or "INT,INT". + clipping_penalty: Penalty for a clipped read as a string "INT" or "INT,INT". + unpaired_read_penalty: Penalty for an unpaired read pair. + interleaved_input: Input file is an interleaved paired-end FASTQ. + read_group_header: Read group header line (e.g., '@RG\\tID:foo\\tSM:bar'). + min_score_to_output: Don't output alignment with score lower than this. + header: Insert this string to header, or read from file if it's a path. + treat_alt_as_primary: Treat ALT contigs as part of the primary assembly. + verbosity_level: Verbosity level. + soft_clip_supplementary: Use soft-clipping for supplementary alignments. + mark_shorter_splits_picard: Mark shorter split hits as secondary (for Picard compatibility). + read_length_params: Comma-separated string of "avg,std,max_is,min_is". + read_type: Read type. Can be 'pacbio', 'ont2d', or 'intractg'. + output_all_alignments: Output all found alignments for single-end or unpaired paired-end reads. + append_fastq_comment: Append FASTA/Q comment to SAM output. + output_ref_header_in_xr: Output the reference FASTA header in the XR tag. + skip_mate_rescue: Skip mate rescue. + batch_size: Process INT reads in a batch. + + Returns: + A dictionary containing the execution details and path to the output SAM file. + """ + if not idx_prefix.with_suffix(".bwt").is_file(): + raise FileNotFoundError(f"BWA index file not found: {idx_prefix}.bwt") + if not in1_fq.is_file(): + raise FileNotFoundError(f"Input FASTQ file not found: {in1_fq}") + if in2_fq and not in2_fq.is_file(): + raise FileNotFoundError(f"Input FASTQ file 2 not found: {in2_fq}") + if read_type and read_type not in ['pacbio', 'ont2d', 'intractg']: + raise ValueError(f"Invalid read_type '{read_type}'.") + + cmd = ["bwa", "mem"] + + # Add options + if threads != 1: cmd.extend(["-t", str(threads)]) + if min_seed_len != 19: cmd.extend(["-k", str(min_seed_len)]) + if band_width != 100: cmd.extend(["-w", str(band_width)]) + if off_diagonal_x_dropoff != 100: cmd.extend(["-d", str(off_diagonal_x_dropoff)]) + if reseeding_factor != 1.5: cmd.extend(["-r", str(reseeding_factor)]) + if max_mem_occurrences != 500: cmd.extend(["-c", str(max_mem_occurrences)]) + if drop_chain_threshold != 0.50: cmd.extend(["-D", str(drop_chain_threshold)]) + if mark_shorter_splits_sec: cmd.append("-m") + if perform_sw_rescue: cmd.append("-P") + if match_score != 1: cmd.extend(["-A", str(match_score)]) + if mismatch_penalty != 4: cmd.extend(["-B", str(mismatch_penalty)]) + if gap_open_penalty != "6,6": cmd.extend(["-O", gap_open_penalty]) + if gap_extension_penalty != "1,1": cmd.extend(["-E", gap_extension_penalty]) + if clipping_penalty != "5,5": cmd.extend(["-L", clipping_penalty]) + if unpaired_read_penalty != 17: cmd.extend(["-U", str(unpaired_read_penalty)]) + if interleaved_input: cmd.append("-p") + if read_group_header: cmd.extend(["-R", read_group_header]) + if min_score_to_output != 30: cmd.extend(["-T", str(min_score_to_output)]) + if header: cmd.extend(["-H", header]) + if treat_alt_as_primary: cmd.append("-j") + if verbosity_level != 3: cmd.extend(["-v", str(verbosity_level)]) + if soft_clip_supplementary: cmd.append("-Y") + if mark_shorter_splits_picard: cmd.append("-M") + if read_length_params: cmd.extend(["-I", read_length_params]) + if read_type: cmd.extend(["-x", read_type]) + if output_all_alignments: cmd.append("-a") + if append_fastq_comment: cmd.append("-C") + if output_ref_header_in_xr: cmd.append("-V") + if skip_mate_rescue: cmd.append("-S") + if batch_size != 10000000: cmd.extend(["-K", str(batch_size)]) + if output_file: cmd.extend(["-o", str(output_file)]) + + # Add positional arguments + cmd.append(str(idx_prefix)) + cmd.append(str(in1_fq)) + if in2_fq: + cmd.append(str(in2_fq)) + + try: + process = subprocess.run( + cmd, check=True, capture_output=True, text=True, + ) + + output_files_list = [str(output_file)] if output_file else [] + + return { + "command_executed": " ".join(cmd), + "stdout": process.stdout, + "stderr": process.stderr, + "output_files": output_files_list, + } + except FileNotFoundError: + raise RuntimeError("bwa command not found. Please ensure BWA is installed and in your PATH.") + except subprocess.CalledProcessError as e: + raise RuntimeError( + f"BWA mem command failed with exit code {e.returncode}.\n" + f"Stderr: {e.stderr}\n" + f"Stdout: {e.stdout}" + ) + +@mcp.tool() +def bwa_aln( + idx_prefix: Path, + in_fq: Path, + output_sai: Optional[Path] = None, + max_diff: float = 0.04, + max_gap_opens: int = 1, + max_gap_extensions: int = -1, + disallow_long_del_at_3_end: int = 16, + disallow_indel_at_ends: int = 5, + seed_length: int = 32, + max_diff_in_seed: int = 2, + threads: int = 1, + mismatch_penalty: int = 3, + gap_open_penalty: int = 11, + gap_extension_penalty: int = 4, + stop_search_threshold: int = 30, + trimming_quality: int = 0, + barcode_length: int = 0, + reverse_query_no_complement: bool = False, + disable_iterative_search: bool = False, + illumina_1_3_plus_fastq: bool = False, + input_is_bam: bool = False, +): + """ + Finds the SA coordinates of the input reads using the BWA-backtrack algorithm. + + Args: + idx_prefix: Path to the BWA index prefix. + in_fq: Path to the input FASTQ file. + output_sai: Path to the output SAI file. If None, output is sent to stdout. + max_diff: Max #diff (int) or missing prob under 0.02 err rate (float). + max_gap_opens: Maximum number of gap opens. + max_gap_extensions: Maximum number of gap extensions. -1 to disable. + disallow_long_del_at_3_end: Disallow a long deletion within INT bp towards the 3'-end. + disallow_indel_at_ends: Disallow an indel within INT bp towards the ends. + seed_length: Take the first INT subsequence as seed. If INT is larger than the query sequence, seeding will be disabled. + max_diff_in_seed: Maximum edit distance in the seed. + threads: Number of threads. + mismatch_penalty: Mismatch penalty. + gap_open_penalty: Gap open penalty. + gap_extension_penalty: Gap extension penalty. + stop_search_threshold: Stop searching when there are > INT equally best hits. + trimming_quality: Quality threshold for read trimming down to 35bp. + barcode_length: Length of barcode starting from the 5'-end. + reverse_query_no_complement: Reverse query but not complement it. + disable_iterative_search: Disable iterative search. + illumina_1_3_plus_fastq: Input is in Illumina 1.3+ FASTQ format. + input_is_bam: Input is BAM. + + Returns: + A dictionary containing the execution details and path to the output SAI file. + """ + if not idx_prefix.with_suffix(".bwt").is_file(): + raise FileNotFoundError(f"BWA index file not found: {idx_prefix}.bwt") + if not in_fq.is_file(): + raise FileNotFoundError(f"Input FASTQ/BAM file not found: {in_fq}") + + cmd = ["bwa", "aln"] + + if max_diff != 0.04: cmd.extend(["-n", str(max_diff)]) + if max_gap_opens != 1: cmd.extend(["-o", str(max_gap_opens)]) + if max_gap_extensions != -1: cmd.extend(["-e", str(max_gap_extensions)]) + if disallow_long_del_at_3_end != 16: cmd.extend(["-d", str(disallow_long_del_at_3_end)]) + if disallow_indel_at_ends != 5: cmd.extend(["-i", str(disallow_indel_at_ends)]) + if seed_length != 32: cmd.extend(["-l", str(seed_length)]) + if max_diff_in_seed != 2: cmd.extend(["-k", str(max_diff_in_seed)]) + if threads != 1: cmd.extend(["-t", str(threads)]) + if mismatch_penalty != 3: cmd.extend(["-M", str(mismatch_penalty)]) + if gap_open_penalty != 11: cmd.extend(["-O", str(gap_open_penalty)]) + if gap_extension_penalty != 4: cmd.extend(["-E", str(gap_extension_penalty)]) + if stop_search_threshold != 30: cmd.extend(["-R", str(stop_search_threshold)]) + if trimming_quality != 0: cmd.extend(["-q", str(trimming_quality)]) + if barcode_length != 0: cmd.extend(["-B", str(barcode_length)]) + if reverse_query_no_complement: cmd.append("-c") + if disable_iterative_search: cmd.append("-N") + if illumina_1_3_plus_fastq: cmd.append("-I") + if input_is_bam: cmd.append("-b") + if output_sai: cmd.extend(["-f", str(output_sai)]) + + cmd.extend([str(idx_prefix), str(in_fq)]) + + try: + process = subprocess.run( + cmd, check=True, capture_output=True, text=True, + ) + + output_files_list = [str(output_sai)] if output_sai else [] + + return { + "command_executed": " ".join(cmd), + "stdout": process.stdout, + "stderr": process.stderr, + "output_files": output_files_list, + } + except FileNotFoundError: + raise RuntimeError("bwa command not found. Please ensure BWA is installed and in your PATH.") + except subprocess.CalledProcessError as e: + raise RuntimeError( + f"BWA aln command failed with exit code {e.returncode}.\n" + f"Stderr: {e.stderr}\n" + f"Stdout: {e.stdout}" + ) + +@mcp.tool() +def bwa_samse( + idx_prefix: Path, + in_sai: Path, + in_fq: Path, + output_sam: Optional[Path] = None, + read_group_header: Optional[str] = None, + max_alignments_in_xa: int = 3, +): + """ + Generates alignments in the SAM format given single-end reads. + + Args: + idx_prefix: Path to the BWA index prefix. + in_sai: Path to the input SAI file from `bwa aln`. + in_fq: Path to the input FASTQ file. + output_sam: Path to the output SAM file. If None, output is sent to stdout. + read_group_header: Read group header line. + max_alignments_in_xa: Maximum number of alignments to output in the XA tag. + + Returns: + A dictionary containing the execution details and path to the output SAM file. + """ + if not idx_prefix.with_suffix(".bwt").is_file(): + raise FileNotFoundError(f"BWA index file not found: {idx_prefix}.bwt") + if not in_sai.is_file(): + raise FileNotFoundError(f"Input SAI file not found: {in_sai}") + if not in_fq.is_file(): + raise FileNotFoundError(f"Input FASTQ file not found: {in_fq}") + + cmd = ["bwa", "samse"] + + if output_sam: cmd.extend(["-f", str(output_sam)]) + if read_group_header: cmd.extend(["-r", read_group_header]) + if max_alignments_in_xa != 3: cmd.extend(["-n", str(max_alignments_in_xa)]) + + cmd.extend([str(idx_prefix), str(in_sai), str(in_fq)]) + + try: + process = subprocess.run( + cmd, check=True, capture_output=True, text=True, + ) + + output_files_list = [str(output_sam)] if output_sam else [] + + return { + "command_executed": " ".join(cmd), + "stdout": process.stdout, + "stderr": process.stderr, + "output_files": output_files_list, + } + except FileNotFoundError: + raise RuntimeError("bwa command not found. Please ensure BWA is installed and in your PATH.") + except subprocess.CalledProcessError as e: + raise RuntimeError( + f"BWA samse command failed with exit code {e.returncode}.\n" + f"Stderr: {e.stderr}\n" + f"Stdout: {e.stdout}" + ) + +@mcp.tool() +def bwa_sampe( + idx_prefix: Path, + in1_sai: Path, + in2_sai: Path, + in1_fq: Path, + in2_fq: Path, + output_sam: Optional[Path] = None, + read_group_header: Optional[str] = None, + max_insert_size: int = 500, + max_occurrences: int = 100000, + max_abnormal_xa: int = 3, + max_discordant_xa: int = 10, + load_entire_fm_index: bool = False, +): + """ + Generates alignments in the SAM format given paired-end reads. + + Args: + idx_prefix: Path to the BWA index prefix. + in1_sai: Path to the SAI file for the first reads. + in2_sai: Path to the SAI file for the second reads. + in1_fq: Path to the FASTQ file for the first reads. + in2_fq: Path to the FASTQ file for the second reads. + output_sam: Path to the output SAM file. If None, output is sent to stdout. + read_group_header: Read group header line. + max_insert_size: Maximum insert size for a read pair to be considered being mapped properly. + max_occurrences: Maximum occurrences for one end before mate-SW is used. + max_abnormal_xa: Maximum number of alignments to output in the XA tag for reads paired abnormally. + max_discordant_xa: Maximum number of alignments to output in the XA tag for disconcordant read pairs. + load_entire_fm_index: Load the entire FM-index into memory to reduce disk operations. + + Returns: + A dictionary containing the execution details and path to the output SAM file. + """ + if not idx_prefix.with_suffix(".bwt").is_file(): + raise FileNotFoundError(f"BWA index file not found: {idx_prefix}.bwt") + if not in1_sai.is_file(): raise FileNotFoundError(f"Input SAI file not found: {in1_sai}") + if not in2_sai.is_file(): raise FileNotFoundError(f"Input SAI file not found: {in2_sai}") + if not in1_fq.is_file(): raise FileNotFoundError(f"Input FASTQ file not found: {in1_fq}") + if not in2_fq.is_file(): raise FileNotFoundError(f"Input FASTQ file not found: {in2_fq}") + + cmd = ["bwa", "sampe"] + + if output_sam: cmd.extend(["-f", str(output_sam)]) + if read_group_header: cmd.extend(["-r", read_group_header]) + if max_insert_size != 500: cmd.extend(["-a", str(max_insert_size)]) + if max_occurrences != 100000: cmd.extend(["-o", str(max_occurrences)]) + if max_abnormal_xa != 3: cmd.extend(["-n", str(max_abnormal_xa)]) + if max_discordant_xa != 10: cmd.extend(["-N", str(max_discordant_xa)]) + if load_entire_fm_index: cmd.append("-P") + + cmd.extend([str(idx_prefix), str(in1_sai), str(in2_sai), str(in1_fq), str(in2_fq)]) + + try: + process = subprocess.run( + cmd, check=True, capture_output=True, text=True, + ) + + output_files_list = [str(output_sam)] if output_sam else [] + + return { + "command_executed": " ".join(cmd), + "stdout": process.stdout, + "stderr": process.stderr, + "output_files": output_files_list, + } + except FileNotFoundError: + raise RuntimeError("bwa command not found. Please ensure BWA is installed and in your PATH.") + except subprocess.CalledProcessError as e: + raise RuntimeError( + f"BWA sampe command failed with exit code {e.returncode}.\n" + f"Stderr: {e.stderr}\n" + f"Stdout: {e.stdout}" + ) + +@mcp.tool() +def bwa_fastmap( + idx_prefix: Path, + in_fq: Path, + output_file: Optional[Path] = None, + min_smem_length: int = 17, + max_interval_size: int = 20, + threads: int = 1, +): + """ + Identify super-maximal exact matches (SMEMs). + + Args: + idx_prefix: Path to the BWA index prefix. + in_fq: Path to the input FASTQ file. + output_file: Path to the output file. If None, output is sent to stdout. + min_smem_length: Minimum length for a SMEM. + max_interval_size: Maximum interval size to find SMEMs. + threads: Number of threads. + + Returns: + A dictionary containing the execution details and path to the output file. + """ + if not idx_prefix.with_suffix(".bwt").is_file(): + raise FileNotFoundError(f"BWA index file not found: {idx_prefix}.bwt") + if not in_fq.is_file(): + raise FileNotFoundError(f"Input FASTQ file not found: {in_fq}") + + cmd = ["bwa", "fastmap"] + + if min_smem_length != 17: cmd.extend(["-l", str(min_smem_length)]) + if max_interval_size != 20: cmd.extend(["-w", str(max_interval_size)]) + if threads != 1: cmd.extend(["-t", str(threads)]) + if output_file: cmd.extend(["-o", str(output_file)]) + + cmd.extend([str(idx_prefix), str(in_fq)]) + + try: + process = subprocess.run( + cmd, check=True, capture_output=True, text=True, + ) + + output_files_list = [str(output_file)] if output_file else [] + + return { + "command_executed": " ".join(cmd), + "stdout": process.stdout, + "stderr": process.stderr, + "output_files": output_files_list, + } + except FileNotFoundError: + raise RuntimeError("bwa command not found. Please ensure BWA is installed and in your PATH.") + except subprocess.CalledProcessError as e: + raise RuntimeError( + f"BWA fastmap command failed with exit code {e.returncode}.\n" + f"Stderr: {e.stderr}\n" + f"Stdout: {e.stdout}" + ) + +@mcp.tool() +def bwa_shm( + command: str, + idx_prefix: Path, +): + """ + Manage BWA index in shared memory. + + Args: + command: The command to execute: 'load', 'get', or 'rm'. + idx_prefix: Path to the BWA index prefix. + + Returns: + A dictionary containing the execution details. + """ + if command not in ["load", "get", "rm"]: + raise ValueError("Command must be one of 'load', 'get', or 'rm'.") + if not idx_prefix.with_suffix(".bwt").is_file(): + raise FileNotFoundError(f"BWA index file not found: {idx_prefix}.bwt") + + cmd = ["bwa", "shm", command, str(idx_prefix)] + + try: + process = subprocess.run( + cmd, check=True, capture_output=True, text=True, + ) + return { + "command_executed": " ".join(cmd), + "stdout": process.stdout, + "stderr": process.stderr, + "output_files": [], + } + except FileNotFoundError: + raise RuntimeError("bwa command not found. Please ensure BWA is installed and in your PATH.") + except subprocess.CalledProcessError as e: + raise RuntimeError( + f"BWA shm command failed with exit code {e.returncode}.\n" + f"Stderr: {e.stderr}\n" + f"Stdout: {e.stdout}" + ) + +@mcp.tool() +def bwa_fa2pac( + in_fa: Path, + out_pac: Path, + force_overwrite: bool = False, +): + """ + Convert FASTA to PAC format (binary sequence). + + Args: + in_fa: Path to the input FASTA file. + out_pac: Path for the output PAC file. + force_overwrite: Force overwrite of the output file if it exists. + + Returns: + A dictionary containing the execution details and path to the output PAC file. + """ + if not in_fa.is_file(): + raise FileNotFoundError(f"Input FASTA file not found: {in_fa}") + + cmd = ["bwa", "fa2pac"] + if force_overwrite: + cmd.append("-f") + cmd.extend([str(in_fa), str(out_pac)]) + + try: + process = subprocess.run( + cmd, check=True, capture_output=True, text=True, + ) + if not out_pac.is_file(): + raise FileNotFoundError(f"Expected output file was not created: {out_pac}") + return { + "command_executed": " ".join(cmd), + "stdout": process.stdout, + "stderr": process.stderr, + "output_files": [str(out_pac)], + } + except FileNotFoundError: + raise RuntimeError("bwa command not found. Please ensure BWA is installed and in your PATH.") + except subprocess.CalledProcessError as e: + raise RuntimeError( + f"BWA fa2pac command failed with exit code {e.returncode}.\n" + f"Stderr: {e.stderr}\n" + f"Stdout: {e.stdout}" + ) + +@mcp.tool() +def bwa_pac2bwt( + in_pac: Path, + out_bwt: Path, + use_manber_myers: bool = False, + use_z_algorithm: bool = False, + force_overwrite: bool = False, +): + """ + Generate BWT from PAC format. + + Args: + in_pac: Path to the input PAC file. + out_bwt: Path for the output BWT file. + use_manber_myers: Use the Manber-Myers algorithm for D-critical characters. + use_z_algorithm: Use the Z-algorithm for D-critical characters. + force_overwrite: Force overwrite of the output file if it exists. + + Returns: + A dictionary containing the execution details and path to the output BWT file. + """ + if not in_pac.is_file(): + raise FileNotFoundError(f"Input PAC file not found: {in_pac}") + + cmd = ["bwa", "pac2bwt"] + if use_manber_myers: + cmd.append("-d") + if use_z_algorithm: + cmd.append("-z") + if force_overwrite: + cmd.append("-f") + cmd.extend([str(in_pac), str(out_bwt)]) + + try: + process = subprocess.run( + cmd, check=True, capture_output=True, text=True, + ) + if not out_bwt.is_file(): + raise FileNotFoundError(f"Expected output file was not created: {out_bwt}") + return { + "command_executed": " ".join(cmd), + "stdout": process.stdout, + "stderr": process.stderr, + "output_files": [str(out_bwt)], + } + except FileNotFoundError: + raise RuntimeError("bwa command not found. Please ensure BWA is installed and in your PATH.") + except subprocess.CalledProcessError as e: + raise RuntimeError( + f"BWA pac2bwt command failed with exit code {e.returncode}.\n" + f"Stderr: {e.stderr}\n" + f"Stdout: {e.stdout}" + ) + +@mcp.tool() +def bwa_bwtupdate( + in_bwt: Path, + out_bwt: Path, +): + """ + Update BWT for the new reference sequence. + + Args: + in_bwt: Path to the input BWT file. + out_bwt: Path for the output BWT file. + + Returns: + A dictionary containing the execution details and path to the output BWT file. + """ + if not in_bwt.is_file(): + raise FileNotFoundError(f"Input BWT file not found: {in_bwt}") + + cmd = ["bwa", "bwtupdate", str(in_bwt), str(out_bwt)] + + try: + process = subprocess.run( + cmd, check=True, capture_output=True, text=True, + ) + if not out_bwt.is_file(): + raise FileNotFoundError(f"Expected output file was not created: {out_bwt}") + return { + "command_executed": " ".join(cmd), + "stdout": process.stdout, + "stderr": process.stderr, + "output_files": [str(out_bwt)], + } + except FileNotFoundError: + raise RuntimeError("bwa command not found. Please ensure BWA is installed and in your PATH.") + except subprocess.CalledProcessError as e: + raise RuntimeError( + f"BWA bwtupdate command failed with exit code {e.returncode}.\n" + f"Stderr: {e.stderr}\n" + f"Stdout: {e.stdout}" + ) + +@mcp.tool() +def bwa_bwt2sa( + in_bwt: Path, + out_sa: Path, + force_overwrite: bool = False, + sa_interval: int = 16, +): + """ + Generate SA from BWT and Occ. + + Args: + in_bwt: Path to the input BWT file. + out_sa: Path for the output SA file. + force_overwrite: Force overwrite of the output file if it exists. + sa_interval: SA interval. + + Returns: + A dictionary containing the execution details and path to the output SA file. + """ + if not in_bwt.is_file(): + raise FileNotFoundError(f"Input BWT file not found: {in_bwt}") + + cmd = ["bwa", "bwt2sa"] + if force_overwrite: + cmd.append("-f") + if sa_interval != 16: + cmd.extend(["-i", str(sa_interval)]) + cmd.extend([str(in_bwt), str(out_sa)]) + + try: + process = subprocess.run( + cmd, check=True, capture_output=True, text=True, + ) + if not out_sa.is_file(): + raise FileNotFoundError(f"Expected output file was not created: {out_sa}") + return { + "command_executed": " ".join(cmd), + "stdout": process.stdout, + "stderr": process.stderr, + "output_files": [str(out_sa)], + } + except FileNotFoundError: + raise RuntimeError("bwa command not found. Please ensure BWA is installed and in your PATH.") + except subprocess.CalledProcessError as e: + raise RuntimeError( + f"BWA bwt2sa command failed with exit code {e.returncode}.\n" + f"Stderr: {e.stderr}\n" + f"Stdout: {e.stdout}" + ) \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bwa/app/bwa_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bwa/app/bwa_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..e274c624dbed66baf68bafa11bee644f98c002f6 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bwa/app/bwa_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bwa/app/bwa_server.py') +SERVER_NAME = 'biosci_bwa' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bwa/app/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bwa/app/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bwa/app/requirements.txt @@ -0,0 +1 @@ + diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bwa/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bwa/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..6c34807f2062027c5a22e819759fe77c42ff13b8 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bwa/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-bwa: + build: . + image: mcp-bwa:latest + container_name: mcp-bwa + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=bwa + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bwa/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bwa/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..f74db625e040cbe9746d3807eb4a3e3672bf5953 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bwa/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - bwa + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bwa/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bwa/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bwa/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cd-hit/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cd-hit/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..ff7a9d5afb15ee9ed48b941671202aa2435b509b --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cd-hit/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install cd-hit via conda (e.g., from bioconda) +RUN conda install -c bioconda cd-hit -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY app/cd-hit_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/cd-hit_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/cd-hit_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cd-hit/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cd-hit/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..5c51c300967d68d853e465b1ab25c478c681991d --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cd-hit/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-cd-hit: + build: . + image: mcp-cd-hit:latest + container_name: mcp-cd-hit + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=cd-hit + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cd-hit/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cd-hit/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cd-hit/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_circos/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_circos/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..45c89e56842a0ba01a9945a2c6d554a3e8e2998e --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_circos/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install circos via conda (e.g., from bioconda) +RUN conda install -c bioconda circos -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY app/circos_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/circos_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/circos_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_circos/app/circos_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_circos/app/circos_server.py new file mode 100644 index 0000000000000000000000000000000000000000..831f111c9abfaf119dee6b61d193a7e5d216bbb2 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_circos/app/circos_server.py @@ -0,0 +1,252 @@ +import subprocess +import tempfile +import re +from pathlib import Path +from typing import Optional, List, Dict, Any + +# This is a mock decorator. In a real MCP environment, this would be provided by the mcp package. +class mcp: + @staticmethod + def tool(func): + return func + +@mcp.tool +def circos_run( + conf: Path, + outputfile: Optional[str] = None, + outputdir: Optional[Path] = None, + debug: bool = False, + debug_group: Optional[str] = None, + cdump: bool = False, + mdump: bool = False, + userconf: Optional[Path] = None, + params: Optional[List[str]] = None, + nosvg: bool = False, + nopng: bool = False, +) -> Dict[str, Any]: + """ + Generates a Circos plot from a configuration file. + + This is the main tool for creating visualizations. It takes a configuration + file and various command-line overrides to produce PNG and/or SVG images. + It can also be used to dump configuration for debugging purposes. + + Args: + conf: The main Circos configuration file. + outputfile: The name of the output image file. + outputdir: The directory where the output files will be saved. + debug: Enable debugging output for all groups. + debug_group: Debug a specific group (e.g., 'summary', 'ideogram'). + cdump: Dump the parsed configuration and exit. + mdump: Dump the module configuration and exit. + userconf: Provide an additional user configuration file. + params: A list of 'key=value' strings to override configuration parameters. + nosvg: Disable SVG output. + nopng: Disable PNG output. + + Returns: + A dictionary containing the command executed, stdout, stderr, and a list of output files. + """ + # Input validation + if not conf.is_file(): + raise FileNotFoundError(f"Configuration file not found: {conf}") + if userconf and not userconf.is_file(): + raise FileNotFoundError(f"User configuration file not found: {userconf}") + if params: + for p in params: + if not re.match(r"^\S+=\S+$", p): + raise ValueError(f"Invalid parameter format: '{p}'. Expected 'key=value'.") + + cmd = ["circos"] + cmd.extend(["-conf", str(conf)]) + + if outputfile: + cmd.extend(["-outputfile", outputfile]) + if outputdir: + outputdir.mkdir(parents=True, exist_ok=True) + cmd.extend(["-outputdir", str(outputdir)]) + if debug: + cmd.append("-debug") + if debug_group: + cmd.extend(["-debug_group", debug_group]) + if cdump: + cmd.append("-cdump") + if mdump: + cmd.append("-mdump") + if userconf: + cmd.extend(["-userconf", str(userconf)]) + if params: + for p in params: + cmd.extend(["-param", p]) + if nosvg: + cmd.append("-nosvg") + if nopng: + cmd.append("-nopng") + + command_executed = " ".join(cmd) + + try: + if outputdir: + work_dir = outputdir + result = subprocess.run( + cmd, capture_output=True, text=True, check=True, cwd=work_dir + ) + # Scan the specified output directory for generated files + output_files = [str(p) for p in work_dir.glob("*.*")] + else: + with tempfile.TemporaryDirectory() as temp_dir: + work_dir = Path(temp_dir) + result = subprocess.run( + cmd, capture_output=True, text=True, check=True, cwd=work_dir + ) + # Scan the temporary directory for generated files + output_files = [str(p) for p in work_dir.glob("*.*")] + + return { + "command_executed": command_executed, + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": sorted(list(set(output_files))) + } + except FileNotFoundError: + raise RuntimeError("circos command not found. Please ensure it is in your system's PATH.") + except subprocess.CalledProcessError as e: + return { + "command_executed": command_executed, + "stdout": e.stdout, + "stderr": e.stderr, + "error": f"Circos failed with exit code {e.returncode}", + "output_files": [] + } + +@mcp.tool +def circos_list_colors() -> Dict[str, Any]: + """Lists all available colors in Circos.""" + cmd = ["circos", "-colorlist"] + command_executed = " ".join(cmd) + try: + result = subprocess.run(cmd, capture_output=True, text=True, check=True) + return { + "command_executed": command_executed, + "stdout": result.stdout, + "stderr": result.stderr, + } + except FileNotFoundError: + raise RuntimeError("circos command not found. Please ensure it is in your system's PATH.") + except subprocess.CalledProcessError as e: + return { + "command_executed": command_executed, + "stdout": e.stdout, + "stderr": e.stderr, + "error": f"Circos failed with exit code {e.returncode}", + } + +@mcp.tool +def circos_list_fonts() -> Dict[str, Any]: + """Lists all available fonts in Circos.""" + cmd = ["circos", "-fontlist"] + command_executed = " ".join(cmd) + try: + result = subprocess.run(cmd, capture_output=True, text=True, check=True) + return { + "command_executed": command_executed, + "stdout": result.stdout, + "stderr": result.stderr, + } + except FileNotFoundError: + raise RuntimeError("circos command not found. Please ensure it is in your system's PATH.") + except subprocess.CalledProcessError as e: + return { + "command_executed": command_executed, + "stdout": e.stdout, + "stderr": e.stderr, + "error": f"Circos failed with exit code {e.returncode}", + } + +@mcp.tool +def circos_list_items(item_type: str) -> Dict[str, Any]: + """ + Lists available items of a given type (e.g., 'ideogram', 'highlight'). + + Args: + item_type: The type of item to list (e.g., ideogram, highlight, plot, link, rule). + + Returns: + A dictionary containing the command executed, stdout, and stderr. + """ + if not item_type: + raise ValueError("item_type cannot be empty.") + + cmd = ["circos", "-list", item_type] + command_executed = " ".join(cmd) + try: + result = subprocess.run(cmd, capture_output=True, text=True, check=True) + return { + "command_executed": command_executed, + "stdout": result.stdout, + "stderr": result.stderr, + } + except FileNotFoundError: + raise RuntimeError("circos command not found. Please ensure it is in your system's PATH.") + except subprocess.CalledProcessError as e: + return { + "command_executed": command_executed, + "stdout": e.stdout, + "stderr": e.stderr, + "error": f"Circos failed with exit code {e.returncode}", + } + +@mcp.tool +def circos_show_rules(conf: Path) -> Dict[str, Any]: + """ + Shows the evaluation of rules for a given configuration. + + Args: + conf: The Circos configuration file to evaluate rules against. + + Returns: + A dictionary containing the command executed, stdout, and stderr. + """ + if not conf.is_file(): + raise FileNotFoundError(f"Configuration file not found: {conf}") + + cmd = ["circos", "-rules", "-conf", str(conf)] + command_executed = " ".join(cmd) + try: + result = subprocess.run(cmd, capture_output=True, text=True, check=True) + return { + "command_executed": command_executed, + "stdout": result.stdout, + "stderr": result.stderr, + } + except FileNotFoundError: + raise RuntimeError("circos command not found. Please ensure it is in your system's PATH.") + except subprocess.CalledProcessError as e: + return { + "command_executed": command_executed, + "stdout": e.stdout, + "stderr": e.stderr, + "error": f"Circos failed with exit code {e.returncode}", + } + +@mcp.tool +def circos_version() -> Dict[str, Any]: + """Shows the Circos version number.""" + cmd = ["circos", "-version"] + command_executed = " ".join(cmd) + try: + result = subprocess.run(cmd, capture_output=True, text=True, check=True) + return { + "command_executed": command_executed, + "stdout": result.stdout, + "stderr": result.stderr, + } + except FileNotFoundError: + raise RuntimeError("circos command not found. Please ensure it is in your system's PATH.") + except subprocess.CalledProcessError as e: + return { + "command_executed": command_executed, + "stdout": e.stdout, + "stderr": e.stderr, + "error": f"Circos failed with exit code {e.returncode}", + } \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_circos/app/circos_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_circos/app/circos_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..fd8646e0de45a72fbb7f3a5193f462191f56a6f6 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_circos/app/circos_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_circos/app/circos_server.py') +SERVER_NAME = 'biosci_circos' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_circos/app/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_circos/app/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_circos/app/requirements.txt @@ -0,0 +1 @@ + diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_circos/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_circos/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..e0915b2a07ecf606bcc406087ff447720f8b025a --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_circos/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-circos: + build: . + image: mcp-circos:latest + container_name: mcp-circos + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=circos + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_circos/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_circos/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..e8a3b56643b3d7d712ea5502944fe3da58e4763a --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_circos/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - circos + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_circos/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_circos/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_circos/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_clustalo/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_clustalo/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..eb716cc02b3ed82157b190e6ce990aac387b416d --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_clustalo/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install clustalo via conda (e.g., from bioconda) +RUN conda install -c bioconda clustalo -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY app/clustalo_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/clustalo_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/clustalo_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_clustalo/app/clustalo_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_clustalo/app/clustalo_server.py new file mode 100644 index 0000000000000000000000000000000000000000..d5d795b1d238f3423c77135f6187db740833b499 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_clustalo/app/clustalo_server.py @@ -0,0 +1,248 @@ +import subprocess +from pathlib import Path +from typing import List, Optional, Literal + +# @mcp.tool() decorator would be here in a real MCP environment +def clustalo( + infile: Path, + outfile: Optional[Path] = None, + hmm_in: Optional[List[Path]] = None, + hmm_batch: Optional[Path] = None, + dealign: bool = False, + profile1: Optional[Path] = None, + profile2: Optional[Path] = None, + is_profile: bool = False, + seqtype: Optional[Literal["Protein", "RNA", "DNA"]] = None, + infmt: Optional[Literal["a2m", "fasta", "fa", "sta", "clustal", "clu", "msf", "phylip", "phy", "selex", "stockholm", "st", "vienna", "vie"]] = None, + distmat_in: Optional[Path] = None, + distmat_out: Optional[Path] = None, + guidetree_in: Optional[Path] = None, + guidetree_out: Optional[Path] = None, + pileup: bool = False, + full: bool = False, + full_iter: bool = False, + cluster_size: Optional[int] = None, + clustering_out: Optional[Path] = None, + trans: int = 0, + posterior_out: Optional[Path] = None, + use_kimura: bool = False, + percent_id: bool = False, + outfmt: Literal["a2m", "fasta", "fa", "sta", "clustal", "clu", "msf", "phylip", "phy", "selex", "stockholm", "st", "vienna", "vie"] = "fasta", + residuenumber: bool = False, + wrap: Optional[int] = None, + output_order: Optional[Literal["input-order", "tree-order"]] = None, + iterations: Optional[int] = None, + max_guidetree_iterations: Optional[int] = None, + max_hmm_iterations: Optional[int] = None, + maxnumseq: Optional[int] = None, + maxseqlen: Optional[int] = None, + auto: bool = False, + threads: Optional[int] = None, + pseudo: Optional[Path] = None, + log: Optional[Path] = None, + verbose: int = 0, + force: bool = False, + mac_ram: Optional[int] = None, +): + """ + Run Clustal Omega for multiple sequence alignment. + + Clustal Omega is a fast, scalable tool for generating high-quality protein + and nucleic acid multiple sequence alignments. + + Args: + infile: Multiple sequence input file. + outfile: Multiple sequence alignment output file (default: stdout). + hmm_in: HMM input files. + hmm_batch: Specify HMMs for individual sequences. + dealign: Dealign input sequences. + profile1: Pre-aligned multiple sequence file (aligned columns will be kept fixed). + profile2: Pre-aligned multiple sequence file (aligned columns will be kept fixed). + is_profile: Disable check if profile, force profile (default: False). + seqtype: Force a sequence type (default: auto). + infmt: Forced sequence input file format (default: auto). + distmat_in: Pairwise distance matrix input file (skips distance computation). + distmat_out: Pairwise distance matrix output file. + guidetree_in: Guide tree input file (skips guide-tree clustering step). + guidetree_out: Guide tree output file. + pileup: Sequentially align sequences. + full: Use full distance matrix for guide-tree calculation (default: mBed). + full_iter: Use full distance matrix for guide-tree calculation during iteration (default: mBed). + cluster_size: Soft maximum of sequences in sub-clusters. + clustering_out: Clustering output file. + trans: Use transitivity (default: 0). + posterior_out: Posterior probability output file. + use_kimura: Use Kimura distance correction for aligned sequences (default: False). + percent_id: Convert distances into percent identities (default: False). + outfmt: MSA output file format (default: fasta). + residuenumber: In Clustal format, print residue numbers (default: False). + wrap: Number of residues before line-wrap in output. + output_order: MSA output order like in input/guide-tree. + iterations: Number of (combined guide-tree/HMM) iterations. + max_guidetree_iterations: Maximum number of guidetree iterations. + max_hmm_iterations: Maximum number of HMM iterations. + maxnumseq: Maximum allowed number of sequences. + maxseqlen: Maximum allowed sequence length. + auto: Set options automatically (might overwrite some of your options). + threads: Number of processors to use. + pseudo: Input file for pseudo-count parameters. + log: Log all non-essential output to this file. + verbose: Verbose output level (e.g., 1 for -v, 2 for -vv). + force: Force file overwriting. + mac_ram: Set a memory limit (undocumented, platform-specific). + + Returns: + A dictionary containing the command executed, stdout, stderr, and a list of output files. + """ + # --- Input Validation --- + if not infile.is_file(): + raise FileNotFoundError(f"Input file not found: {infile}") + + input_files_to_check = { + "hmm_batch": hmm_batch, + "profile1": profile1, + "profile2": profile2, + "distmat_in": distmat_in, + "guidetree_in": guidetree_in, + "pseudo": pseudo, + } + for name, path in input_files_to_check.items(): + if path and not path.is_file(): + raise FileNotFoundError(f"Input file for --{name.replace('_', '-')} not found: {path}") + + if hmm_in: + for hmm_file in hmm_in: + if not hmm_file.is_file(): + raise FileNotFoundError(f"HMM input file not found: {hmm_file}") + + if threads is not None and threads <= 0: + raise ValueError("threads must be a positive integer.") + + if verbose < 0: + raise ValueError("verbose level cannot be negative.") + + # --- Command Construction --- + cmd = ["clustalo"] + output_files = [] + + # Sequence Input + cmd.extend(["--infile", str(infile)]) + if hmm_in: + for hmm_file in hmm_in: + cmd.extend(["--hmm-in", str(hmm_file)]) + if hmm_batch: + cmd.extend(["--hmm-batch", str(hmm_batch)]) + if dealign: + cmd.append("--dealign") + if profile1: + cmd.extend(["--profile1", str(profile1)]) + if profile2: + cmd.extend(["--profile2", str(profile2)]) + if is_profile: + cmd.append("--is-profile") + if seqtype: + cmd.extend(["--seqtype", seqtype]) + if infmt: + cmd.extend(["--infmt", infmt]) + + # Clustering + if distmat_in: + cmd.extend(["--distmat-in", str(distmat_in)]) + if distmat_out: + cmd.extend(["--distmat-out", str(distmat_out)]) + output_files.append(str(distmat_out)) + if guidetree_in: + cmd.extend(["--guidetree-in", str(guidetree_in)]) + if guidetree_out: + cmd.extend(["--guidetree-out", str(guidetree_out)]) + output_files.append(str(guidetree_out)) + if pileup: + cmd.append("--pileup") + if full: + cmd.append("--full") + if full_iter: + cmd.append("--full-iter") + if cluster_size is not None: + cmd.extend(["--cluster-size", str(cluster_size)]) + if clustering_out: + cmd.extend(["--clustering-out", str(clustering_out)]) + output_files.append(str(clustering_out)) + if trans != 0: + cmd.extend(["--trans", str(trans)]) + if posterior_out: + cmd.extend(["--posterior-out", str(posterior_out)]) + output_files.append(str(posterior_out)) + if use_kimura: + cmd.append("--use-kimura") + if percent_id: + cmd.append("--percent-id") + + # Alignment Output + if outfile: + cmd.extend(["--outfile", str(outfile)]) + output_files.append(str(outfile)) + cmd.extend(["--outfmt", outfmt]) + if residuenumber: + cmd.append("--residuenumber") + if wrap is not None: + cmd.extend(["--wrap", str(wrap)]) + if output_order: + cmd.extend(["--output-order", output_order]) + + # Iteration + if iterations is not None: + cmd.extend(["--iterations", str(iterations)]) + if max_guidetree_iterations is not None: + cmd.extend(["--max-guidetree-iterations", str(max_guidetree_iterations)]) + if max_hmm_iterations is not None: + cmd.extend(["--max-hmm-iterations", str(max_hmm_iterations)]) + + # Limits + if maxnumseq is not None: + cmd.extend(["--maxnumseq", str(maxnumseq)]) + if maxseqlen is not None: + cmd.extend(["--maxseqlen", str(maxseqlen)]) + + # Miscellaneous + if auto: + cmd.append("--auto") + if threads is not None: + cmd.extend(["--threads", str(threads)]) + if pseudo: + cmd.extend(["--pseudo", str(pseudo)]) + if log: + cmd.extend(["--log", str(log)]) + output_files.append(str(log)) + if verbose > 0: + cmd.append("-" + "v" * verbose) + if force: + cmd.append("--force") + if mac_ram is not None: + cmd.extend(["--MAC-RAM", str(mac_ram)]) + + # --- Subprocess Execution --- + try: + command_str = " ".join(cmd) + result = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True + ) + return { + "command_executed": command_str, + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": output_files + } + except FileNotFoundError: + raise RuntimeError("clustalo command not found. Please ensure it is installed and in your system's PATH.") + except subprocess.CalledProcessError as e: + # Return structured error information + return { + "command_executed": " ".join(e.cmd), + "stdout": e.stdout, + "stderr": e.stderr, + "error": f"ClustalO failed with exit code {e.returncode}", + "output_files": [] + } diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_clustalo/app/clustalo_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_clustalo/app/clustalo_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..4b8930f05aea48c16524633ffce3c0df08adf589 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_clustalo/app/clustalo_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_clustalo/app/clustalo_server.py') +SERVER_NAME = 'biosci_clustalo' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_clustalo/app/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_clustalo/app/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_clustalo/app/requirements.txt @@ -0,0 +1 @@ + diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_clustalo/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_clustalo/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..50ecbc94d4624b00f0fe687ff464198dc02e71e7 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_clustalo/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-clustalo: + build: . + image: mcp-clustalo:latest + container_name: mcp-clustalo + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=clustalo + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_clustalo/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_clustalo/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..ca423df37f9d284dce831fcf7f072fd41a6a4d5d --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_clustalo/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - clustalo + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_clustalo/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_clustalo/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_clustalo/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cnmf/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cnmf/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..7dcdcdc1f551d13aa67f84f292057bb9dabe9211 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cnmf/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install cnmf via conda (e.g., from bioconda) +RUN conda install -c bioconda cnmf -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY cnmf_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/cnmf_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/cnmf_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cnmf/app/cnmf_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cnmf/app/cnmf_server.py new file mode 100644 index 0000000000000000000000000000000000000000..376c5cefc7a0bee58619fabc27dca60ded259ffe --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cnmf/app/cnmf_server.py @@ -0,0 +1,348 @@ +import subprocess +import shlex +from pathlib import Path +from typing import List, Optional + +# MCP decorator is commented out as per instructions +# @mcp.tool() +def cnmf_prepare( + counts: Path, + components: List[int], + n_iter: int, + name: str, + output_dir: Path, + total_workers: Optional[int] = None, + seed: Optional[int] = None, + genes_file: Optional[Path] = None, + numgenes: Optional[int] = None, + tpm: Optional[Path] = None, + max_nmf_iter: int = 1000, + beta_loss: str = "frobenius", + init: str = "random", + densify: bool = False, +) -> dict: + """ + Prepares the data and directory structure for a cNMF analysis. + + This step filters the count matrix, selects high-variance genes, + and sets up the output directory for subsequent factorization runs. + """ + # --- Input Validation --- + if not counts.is_file(): + raise FileNotFoundError(f"Input counts file not found: {counts}") + if genes_file and not genes_file.is_file(): + raise FileNotFoundError(f"Genes file not found: {genes_file}") + if tpm and not tpm.is_file(): + raise FileNotFoundError(f"TPM file not found: {tpm}") + + if not components: + raise ValueError("At least one component value (-k/--components) must be provided.") + if n_iter <= 0: + raise ValueError("--n-iter must be a positive integer.") + if max_nmf_iter <= 0: + raise ValueError("--max-nmf-iter must be a positive integer.") + if numgenes is not None and numgenes <= 0: + raise ValueError("--numgenes must be a positive integer.") + + beta_loss_choices = ["frobenius", "kullback-leibler", "itakura-saito"] + if beta_loss not in beta_loss_choices: + raise ValueError(f"--beta-loss must be one of {beta_loss_choices}, not '{beta_loss}'") + + init_choices = ["random", "nndsvd"] + if init not in init_choices: + raise ValueError(f"--init must be one of {init_choices}, not '{init}'") + + # --- Command Construction --- + cmd = ["cnmf", "prepare"] + cmd.extend(["--output-dir", str(output_dir)]) + cmd.extend(["--name", name]) + cmd.extend(["--counts", str(counts)]) + cmd.extend(["--components", *[str(k) for k in components]]) + cmd.extend(["--n-iter", str(n_iter)]) + + if total_workers is not None: + cmd.extend(["--total-workers", str(total_workers)]) + if seed is not None: + cmd.extend(["--seed", str(seed)]) + if genes_file: + cmd.extend(["--genes-file", str(genes_file)]) + if numgenes is not None: + cmd.extend(["--numgenes", str(numgenes)]) + if tpm: + cmd.extend(["--tpm", str(tpm)]) + if max_nmf_iter != 1000: + cmd.extend(["--max-nmf-iter", str(max_nmf_iter)]) + if beta_loss != "frobenius": + cmd.extend(["--beta-loss", beta_loss]) + if init != "random": + cmd.extend(["--init", init]) + if densify: + cmd.append("--densify") + + # --- Subprocess Execution --- + try: + # Ensure output directory exists + output_dir.mkdir(parents=True, exist_ok=True) + + process = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + ) + except FileNotFoundError: + return { + "command_executed": shlex.join(cmd), + "stdout": "", + "stderr": "Error: 'cnmf' command not found. Please ensure it is in your PATH.", + "output_files": [] + } + except subprocess.CalledProcessError as e: + return { + "command_executed": shlex.join(cmd), + "stdout": e.stdout, + "stderr": e.stderr, + "output_files": [] + } + + # --- Structured Result Return --- + # The prepare step creates the main output directory for the analysis. + output_path = output_dir / name + return { + "command_executed": shlex.join(cmd), + "stdout": process.stdout, + "stderr": process.stderr, + "output_files": [str(output_path)] + } + + +# @mcp.tool() +def cnmf_factorize( + name: str, + output_dir: Path, + worker_index: Optional[int] = None, + total_workers: Optional[int] = None, + skip_completed_runs: bool = False, +) -> dict: + """ + Runs the NMF factorizations for a cNMF analysis. + + This step can be parallelized across multiple workers. + """ + # --- Input Validation --- + if worker_index is not None and worker_index < 0: + raise ValueError("--worker-index must be a non-negative integer.") + if total_workers is not None and total_workers <= 0: + raise ValueError("--total-workers must be a positive integer.") + + # --- Command Construction --- + cmd = ["cnmf", "factorize"] + cmd.extend(["--output-dir", str(output_dir)]) + cmd.extend(["--name", name]) + + if worker_index is not None: + cmd.extend(["--worker-index", str(worker_index)]) + if total_workers is not None: + cmd.extend(["--total-workers", str(total_workers)]) + if skip_completed_runs: + cmd.append("--skip-completed-runs") + + # --- Subprocess Execution --- + try: + process = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + ) + except FileNotFoundError: + return { + "command_executed": shlex.join(cmd), + "stdout": "", + "stderr": "Error: 'cnmf' command not found. Please ensure it is in your PATH.", + "output_files": [] + } + except subprocess.CalledProcessError as e: + return { + "command_executed": shlex.join(cmd), + "stdout": e.stdout, + "stderr": e.stderr, + "output_files": [] + } + + # --- Structured Result Return --- + # Factorize populates the directory created by 'prepare'. + output_path = output_dir / name + return { + "command_executed": shlex.join(cmd), + "stdout": process.stdout, + "stderr": process.stderr, + "output_files": [str(output_path)] + } + + +# @mcp.tool() +def cnmf_combine( + name: str, + output_dir: Path, +) -> dict: + """ + Combines the factorization results from multiple workers into a single file. + """ + # --- Command Construction --- + cmd = ["cnmf", "combine"] + cmd.extend(["--output-dir", str(output_dir)]) + cmd.extend(["--name", name]) + + # --- Subprocess Execution --- + try: + process = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + ) + except FileNotFoundError: + return { + "command_executed": shlex.join(cmd), + "stdout": "", + "stderr": "Error: 'cnmf' command not found. Please ensure it is in your PATH.", + "output_files": [] + } + except subprocess.CalledProcessError as e: + return { + "command_executed": shlex.join(cmd), + "stdout": e.stdout, + "stderr": e.stderr, + "output_files": [] + } + + # --- Structured Result Return --- + # Combine creates merged files within the main output directory. + output_path = output_dir / name + return { + "command_executed": shlex.join(cmd), + "stdout": process.stdout, + "stderr": process.stderr, + "output_files": [str(output_path)] + } + + +# @mcp.tool() +def cnmf_consensus( + name: str, + output_dir: Path, + local_density_threshold: Optional[float] = None, + local_neighborhood_size: Optional[float] = None, + show_clustering: bool = False, + build_reference: bool = False, +) -> dict: + """ + Performs consensus clustering and filtering on the factorization results. + """ + # --- Input Validation --- + if local_density_threshold is not None: + if not (0 < local_density_threshold <= 2): + raise ValueError("--local-density-threshold must be a float > 0 and <= 2.") + if local_neighborhood_size is not None and not (0 < local_neighborhood_size <= 1): + raise ValueError("--local-neighborhood-size must be a float > 0 and <= 1.") + + # --- Command Construction --- + cmd = ["cnmf", "consensus"] + cmd.extend(["--output-dir", str(output_dir)]) + cmd.extend(["--name", name]) + + if local_density_threshold is not None: + cmd.extend(["--local-density-threshold", str(local_density_threshold)]) + if local_neighborhood_size is not None: + cmd.extend(["--local-neighborhood-size", str(local_neighborhood_size)]) + if show_clustering: + cmd.append("--show-clustering") + if build_reference: + cmd.append("--build-reference") + + # --- Subprocess Execution --- + try: + process = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + ) + except FileNotFoundError: + return { + "command_executed": shlex.join(cmd), + "stdout": "", + "stderr": "Error: 'cnmf' command not found. Please ensure it is in your PATH.", + "output_files": [] + } + except subprocess.CalledProcessError as e: + return { + "command_executed": shlex.join(cmd), + "stdout": e.stdout, + "stderr": e.stderr, + "output_files": [] + } + + # --- Structured Result Return --- + output_path = output_dir / name + outputs = [str(output_path)] + # Assuming standard output file names for optional plots + if show_clustering: + outputs.append(str(output_path / f"{name}.clustering.pdf")) + + return { + "command_executed": shlex.join(cmd), + "stdout": process.stdout, + "stderr": process.stderr, + "output_files": outputs + } + + +# @mcp.tool() +def cnmf_k_selection_plot( + name: str, + output_dir: Path, +) -> dict: + """ + Generates plots to help select the number of components (K). + """ + # --- Command Construction --- + cmd = ["cnmf", "k_selection_plot"] + cmd.extend(["--output-dir", str(output_dir)]) + cmd.extend(["--name", name]) + + # --- Subprocess Execution --- + try: + process = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + ) + except FileNotFoundError: + return { + "command_executed": shlex.join(cmd), + "stdout": "", + "stderr": "Error: 'cnmf' command not found. Please ensure it is in your PATH.", + "output_files": [] + } + except subprocess.CalledProcessError as e: + return { + "command_executed": shlex.join(cmd), + "stdout": e.stdout, + "stderr": e.stderr, + "output_files": [] + } + + # --- Structured Result Return --- + output_path = output_dir / name + # Assuming a standard output file name for the plot + plot_file = output_path / f"{name}.k_selection.pdf" + + return { + "command_executed": shlex.join(cmd), + "stdout": process.stdout, + "stderr": process.stderr, + "output_files": [str(plot_file)] + } \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cnmf/app/cnmf_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cnmf/app/cnmf_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..033b4303c923ca3de76726b0ba98c65f7b30f0e5 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cnmf/app/cnmf_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cnmf/app/cnmf_server.py') +SERVER_NAME = 'biosci_cnmf' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cnmf/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cnmf/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..635e5916557072f02007e3ba1681195e4dc5f7ba --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cnmf/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-cnmf: + build: . + image: mcp-cnmf:latest + container_name: mcp-cnmf + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=cnmf + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cnmf/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cnmf/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..013ba86cf1efcb8a1a6aa0a45222e3626eec9499 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cnmf/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - cnmf + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cnmf/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cnmf/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cnmf/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_decoupler/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_decoupler/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..9377ee41676018cd45120e518daf4324c4695657 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_decoupler/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install decoupler via conda (e.g., from bioconda) +RUN conda install -c bioconda decoupler -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY decoupler_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/decoupler_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/decoupler_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_decoupler/app/decoupler_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_decoupler/app/decoupler_server.py new file mode 100644 index 0000000000000000000000000000000000000000..73d38c3641d110b4dee7f96316fb2c0e49a3f683 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_decoupler/app/decoupler_server.py @@ -0,0 +1,692 @@ +import subprocess +import tempfile +from pathlib import Path +from typing import List, Literal, Optional + +# Mock mcp decorator for standalone execution +class mcp: + @staticmethod + def tool(func): + return func + +@mcp.tool +def decoupler_mlm( + mat: Path, + net: Path, + output: Path, + mat_source_col: str = 'genes', + mat_target_col: str = 'cells', + mat_value_col: str = 'expression', + net_source_col: str = 'tf', + net_target_col: str = 'target', + net_weight_col: str = 'weight', + min_n: int = 5, + batch_size: int = 10000, + verbose: bool = False, +): + """ + Runs transcription factor/pathway activities using the Multivariate Linear Model (mlm) method from decoupler. + + This method is equivalent to the `run_mlm` function in the decoupler library. + It models the relationship between a set of regulators and their target features using a linear model. + + Args: + mat: Path to the input matrix file (e.g., gene expression). Should be a long-format CSV/TSV. + net: Path to the input network file (e.g., TF-target interactions). Should be a long-format CSV/TSV. + output: Path to the output file where the inferred activities will be saved. + mat_source_col: Column name in the matrix file for the features (e.g., 'genes'). + mat_target_col: Column name in the matrix file for the samples (e.g., 'cells'). + mat_value_col: Column name in the matrix file for the values (e.g., 'expression'). + net_source_col: Column name in the network file for the regulators (e.g., 'tf'). + net_target_col: Column name in the network file for the targets (e.g., 'target'). + net_weight_col: Column name in the network file for the interaction weights (e.g., 'weight'). + min_n: Minimum number of targets per regulator in the network to be considered. + batch_size: Number of samples to process in each batch to manage memory usage. + verbose: If True, increases verbosity of the tool's output. + """ + # Input validation + if not mat.is_file(): + raise FileNotFoundError(f"Input matrix file not found: {mat}") + if not net.is_file(): + raise FileNotFoundError(f"Input network file not found: {net}") + if min_n < 1: + raise ValueError("min_n must be a positive integer.") + if batch_size < 1: + raise ValueError("batch_size must be a positive integer.") + + output.parent.mkdir(parents=True, exist_ok=True) + + cmd = [ + "python", "-m", "decoupler", "mlm", + "--mat", str(mat), + "--net", str(net), + "--output", str(output), + "--mat-source-col", mat_source_col, + "--mat-target-col", mat_target_col, + "--mat-value-col", mat_value_col, + "--net-source-col", net_source_col, + "--net-target-col", net_target_col, + "--net-weight-col", net_weight_col, + "--min-n", str(min_n), + "--batch-size", str(batch_size), + ] + if verbose: + cmd.append("--verbose") + + try: + process = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + ) + except subprocess.CalledProcessError as e: + return { + "command_executed": " ".join(e.cmd), + "stdout": e.stdout, + "stderr": e.stderr, + "return_code": e.returncode, + "output_files": [] + } + + return { + "command_executed": " ".join(cmd), + "stdout": process.stdout, + "stderr": process.stderr, + "output_files": [str(output)] + } + +@mcp.tool +def decoupler_ulm( + mat: Path, + net: Path, + output: Path, + mat_source_col: str = 'genes', + mat_target_col: str = 'cells', + mat_value_col: str = 'expression', + net_source_col: str = 'tf', + net_target_col: str = 'target', + net_weight_col: str = 'weight', + min_n: int = 5, + batch_size: int = 10000, + verbose: bool = False, +): + """ + Runs transcription factor/pathway activities using the Univariate Linear Model (ulm) method from decoupler. + + This method is equivalent to the `run_ulm` function in the decoupler library. + It models the relationship between each regulator and its target features independently. + + Args: + mat: Path to the input matrix file (e.g., gene expression). Should be a long-format CSV/TSV. + net: Path to the input network file (e.g., TF-target interactions). Should be a long-format CSV/TSV. + output: Path to the output file where the inferred activities will be saved. + mat_source_col: Column name in the matrix file for the features (e.g., 'genes'). + mat_target_col: Column name in the matrix file for the samples (e.g., 'cells'). + mat_value_col: Column name in the matrix file for the values (e.g., 'expression'). + net_source_col: Column name in the network file for the regulators (e.g., 'tf'). + net_target_col: Column name in the network file for the targets (e.g., 'target'). + net_weight_col: Column name in the network file for the interaction weights (e.g., 'weight'). + min_n: Minimum number of targets per regulator in the network to be considered. + batch_size: Number of samples to process in each batch to manage memory usage. + verbose: If True, increases verbosity of the tool's output. + """ + # Input validation + if not mat.is_file(): + raise FileNotFoundError(f"Input matrix file not found: {mat}") + if not net.is_file(): + raise FileNotFoundError(f"Input network file not found: {net}") + if min_n < 1: + raise ValueError("min_n must be a positive integer.") + if batch_size < 1: + raise ValueError("batch_size must be a positive integer.") + + output.parent.mkdir(parents=True, exist_ok=True) + + cmd = [ + "python", "-m", "decoupler", "ulm", + "--mat", str(mat), + "--net", str(net), + "--output", str(output), + "--mat-source-col", mat_source_col, + "--mat-target-col", mat_target_col, + "--mat-value-col", mat_value_col, + "--net-source-col", net_source_col, + "--net-target-col", net_target_col, + "--net-weight-col", net_weight_col, + "--min-n", str(min_n), + "--batch-size", str(batch_size), + ] + if verbose: + cmd.append("--verbose") + + try: + process = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + ) + except subprocess.CalledProcessError as e: + return { + "command_executed": " ".join(e.cmd), + "stdout": e.stdout, + "stderr": e.stderr, + "return_code": e.returncode, + "output_files": [] + } + + return { + "command_executed": " ".join(cmd), + "stdout": process.stdout, + "stderr": process.stderr, + "output_files": [str(output)] + } + +@mcp.tool +def decoupler_wsum( + mat: Path, + net: Path, + output: Path, + mat_source_col: str = 'genes', + mat_target_col: str = 'cells', + mat_value_col: str = 'expression', + net_source_col: str = 'tf', + net_target_col: str = 'target', + net_weight_col: str = 'weight', + min_n: int = 5, + batch_size: int = 10000, + nes: bool = False, + times: int = 100, + seed: int = 42, + verbose: bool = False, +): + """ + Runs transcription factor/pathway activities using the Weighted Sum (wsum) method from decoupler. + + This method calculates scores by multiplying the feature matrix by the network matrix. + It can optionally compute a normalized enrichment score (NES) through permutations. + + Args: + mat: Path to the input matrix file. + net: Path to the input network file. + output: Path to the output file. + mat_source_col: Column name for features in the matrix file. + mat_target_col: Column name for samples in the matrix file. + mat_value_col: Column name for values in the matrix file. + net_source_col: Column name for regulators in the network file. + net_target_col: Column name for targets in the network file. + net_weight_col: Column name for interaction weights in the network file. + min_n: Minimum number of targets per regulator. + batch_size: Number of samples to process per batch. + nes: If True, compute Normalized Enrichment Scores (NES) by permutation. + times: Number of permutations to perform if `nes` is True. + seed: Random seed for permutations. + verbose: If True, increases verbosity. + """ + # Input validation + if not mat.is_file(): + raise FileNotFoundError(f"Input matrix file not found: {mat}") + if not net.is_file(): + raise FileNotFoundError(f"Input network file not found: {net}") + if min_n < 1: + raise ValueError("min_n must be a positive integer.") + if batch_size < 1: + raise ValueError("batch_size must be a positive integer.") + if times < 1: + raise ValueError("times must be a positive integer.") + + output.parent.mkdir(parents=True, exist_ok=True) + + cmd = [ + "python", "-m", "decoupler", "wsum", + "--mat", str(mat), + "--net", str(net), + "--output", str(output), + "--mat-source-col", mat_source_col, + "--mat-target-col", mat_target_col, + "--mat-value-col", mat_value_col, + "--net-source-col", net_source_col, + "--net-target-col", net_target_col, + "--net-weight-col", net_weight_col, + "--min-n", str(min_n), + "--batch-size", str(batch_size), + "--times", str(times), + "--seed", str(seed), + ] + if nes: + cmd.append("--nes") + if verbose: + cmd.append("--verbose") + + try: + process = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + ) + except subprocess.CalledProcessError as e: + return { + "command_executed": " ".join(e.cmd), + "stdout": e.stdout, + "stderr": e.stderr, + "return_code": e.returncode, + "output_files": [] + } + + return { + "command_executed": " ".join(cmd), + "stdout": process.stdout, + "stderr": process.stderr, + "output_files": [str(output)] + } + +@mcp.tool +def decoupler_ora( + mat: Path, + net: Path, + output: Path, + mat_source_col: str = 'genes', + mat_target_col: str = 'cells', + mat_value_col: str = 'expression', + net_source_col: str = 'tf', + net_target_col: str = 'target', + net_weight_col: str = 'weight', + min_n: int = 5, + batch_size: int = 10000, + top: int = 100, + verbose: bool = False, +): + """ + Runs Over-Representation Analysis (ORA) using decoupler. + + This method performs a statistical test (Fisher's exact test) to determine if a set of features + (e.g., differentially expressed genes) is enriched in a given pathway/regulon. + + Args: + mat: Path to the input matrix file. + net: Path to the input network file. + output: Path to the output file. + mat_source_col: Column name for features in the matrix file. + mat_target_col: Column name for samples in the matrix file. + mat_value_col: Column name for values in the matrix file. + net_source_col: Column name for regulators in the network file. + net_target_col: Column name for targets in the network file. + net_weight_col: Column name for interaction weights in the network file. + min_n: Minimum number of targets per regulator. + batch_size: Number of samples to process per batch. + top: Number of top features from the matrix to use for the enrichment analysis. + verbose: If True, increases verbosity. + """ + # Input validation + if not mat.is_file(): + raise FileNotFoundError(f"Input matrix file not found: {mat}") + if not net.is_file(): + raise FileNotFoundError(f"Input network file not found: {net}") + if min_n < 1: + raise ValueError("min_n must be a positive integer.") + if batch_size < 1: + raise ValueError("batch_size must be a positive integer.") + if top < 1: + raise ValueError("top must be a positive integer.") + + output.parent.mkdir(parents=True, exist_ok=True) + + cmd = [ + "python", "-m", "decoupler", "ora", + "--mat", str(mat), + "--net", str(net), + "--output", str(output), + "--mat-source-col", mat_source_col, + "--mat-target-col", mat_target_col, + "--mat-value-col", mat_value_col, + "--net-source-col", net_source_col, + "--net-target-col", net_target_col, + "--net-weight-col", net_weight_col, + "--min-n", str(min_n), + "--batch-size", str(batch_size), + "--top", str(top), + ] + if verbose: + cmd.append("--verbose") + + try: + process = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + ) + except subprocess.CalledProcessError as e: + return { + "command_executed": " ".join(e.cmd), + "stdout": e.stdout, + "stderr": e.stderr, + "return_code": e.returncode, + "output_files": [] + } + + return { + "command_executed": " ".join(cmd), + "stdout": process.stdout, + "stderr": process.stderr, + "output_files": [str(output)] + } + +@mcp.tool +def decoupler_gsva( + mat: Path, + net: Path, + output: Path, + mat_source_col: str = 'genes', + mat_target_col: str = 'cells', + mat_value_col: str = 'expression', + net_source_col: str = 'tf', + net_target_col: str = 'target', + net_weight_col: str = 'weight', + min_n: int = 5, + batch_size: int = 10000, + mx_diff: bool = True, + abs_ranking: bool = False, + min_sz: int = 5, + max_sz: int = 500, + kcdf: Literal['Gaussian', 'Poisson'] = 'Gaussian', + seed: int = 42, + verbose: bool = False, +): + """ + Runs Gene Set Variation Analysis (GSVA) using decoupler. + + GSVA estimates variation of pathway activity over a sample population in an unsupervised manner. + + Args: + mat: Path to the input matrix file. + net: Path to the input network file. + output: Path to the output file. + mat_source_col: Column name for features in the matrix file. + mat_target_col: Column name for samples in the matrix file. + mat_value_col: Column name for values in the matrix file. + net_source_col: Column name for regulators in the network file. + net_target_col: Column name for targets in the network file. + net_weight_col: Column name for interaction weights in the network file. + min_n: Minimum number of targets per regulator. + batch_size: Number of samples to process per batch. + mx_diff: The maximum absolute difference between the minimum and maximum. + abs_ranking: If True, gene expression values are ranked by their absolute values. + min_sz: Minimum size of a gene set to be considered. + max_sz: Maximum size of a gene set to be considered. + kcdf: Kernel cumulative distribution function to use. + seed: Random seed. + verbose: If True, increases verbosity. + """ + # Input validation + if not mat.is_file(): + raise FileNotFoundError(f"Input matrix file not found: {mat}") + if not net.is_file(): + raise FileNotFoundError(f"Input network file not found: {net}") + if min_n < 1: + raise ValueError("min_n must be a positive integer.") + if batch_size < 1: + raise ValueError("batch_size must be a positive integer.") + if min_sz < 1: + raise ValueError("min_sz must be a positive integer.") + if max_sz < min_sz: + raise ValueError("max_sz must be greater than or equal to min_sz.") + + output.parent.mkdir(parents=True, exist_ok=True) + + cmd = [ + "python", "-m", "decoupler", "gsva", + "--mat", str(mat), + "--net", str(net), + "--output", str(output), + "--mat-source-col", mat_source_col, + "--mat-target-col", mat_target_col, + "--mat-value-col", mat_value_col, + "--net-source-col", net_source_col, + "--net-target-col", net_target_col, + "--net-weight-col", net_weight_col, + "--min-n", str(min_n), + "--batch-size", str(batch_size), + "--min-sz", str(min_sz), + "--max-sz", str(max_sz), + "--kcdf", kcdf, + "--seed", str(seed), + ] + if mx_diff: + cmd.append("--mx-diff") + if abs_ranking: + cmd.append("--abs-ranking") + if verbose: + cmd.append("--verbose") + + try: + process = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + ) + except subprocess.CalledProcessError as e: + return { + "command_executed": " ".join(e.cmd), + "stdout": e.stdout, + "stderr": e.stderr, + "return_code": e.returncode, + "output_files": [] + } + + return { + "command_executed": " ".join(cmd), + "stdout": process.stdout, + "stderr": process.stderr, + "output_files": [str(output)] + } + +@mcp.tool +def decoupler_viper( + mat: Path, + net: Path, + output: Path, + mat_source_col: str = 'genes', + mat_target_col: str = 'cells', + mat_value_col: str = 'expression', + net_source_col: str = 'tf', + net_target_col: str = 'target', + net_weight_col: str = 'weight', + min_n: int = 5, + batch_size: int = 10000, + nes: bool = True, + pleiotropy: bool = True, + eset_filter: bool = False, + seed: int = 42, + verbose: bool = False, +): + """ + Runs Virtual Inference of Protein-activity by Enriched Regulon analysis (VIPER). + + VIPER is a method to infer protein activity from gene expression data based on the enrichment + of its transcriptional targets (regulon). + + Args: + mat: Path to the input matrix file. + net: Path to the input network file. + output: Path to the output file. + mat_source_col: Column name for features in the matrix file. + mat_target_col: Column name for samples in the matrix file. + mat_value_col: Column name for values in the matrix file. + net_source_col: Column name for regulators in the network file. + net_target_col: Column name for targets in the network file. + net_weight_col: Column name for interaction weights in the network file. + min_n: Minimum number of targets per regulator. + batch_size: Number of samples to process per batch. + nes: If True, compute Normalized Enrichment Scores (NES). + pleiotropy: If True, correct for pleiotropy (regulators sharing targets). + eset_filter: If True, filter by eset size. + seed: Random seed. + verbose: If True, increases verbosity. + """ + # Input validation + if not mat.is_file(): + raise FileNotFoundError(f"Input matrix file not found: {mat}") + if not net.is_file(): + raise FileNotFoundError(f"Input network file not found: {net}") + if min_n < 1: + raise ValueError("min_n must be a positive integer.") + if batch_size < 1: + raise ValueError("batch_size must be a positive integer.") + + output.parent.mkdir(parents=True, exist_ok=True) + + cmd = [ + "python", "-m", "decoupler", "viper", + "--mat", str(mat), + "--net", str(net), + "--output", str(output), + "--mat-source-col", mat_source_col, + "--mat-target-col", mat_target_col, + "--mat-value-col", mat_value_col, + "--net-source-col", net_source_col, + "--net-target-col", net_target_col, + "--net-weight-col", net_weight_col, + "--min-n", str(min_n), + "--batch-size", str(batch_size), + "--seed", str(seed), + ] + if nes: + cmd.append("--nes") + if pleiotropy: + cmd.append("--pleiotropy") + if eset_filter: + cmd.append("--eset-filter") + if verbose: + cmd.append("--verbose") + + try: + process = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + ) + except subprocess.CalledProcessError as e: + return { + "command_executed": " ".join(e.cmd), + "stdout": e.stdout, + "stderr": e.stderr, + "return_code": e.returncode, + "output_files": [] + } + + return { + "command_executed": " ".join(cmd), + "stdout": process.stdout, + "stderr": process.stderr, + "output_files": [str(output)] + } + +@mcp.tool +def decoupler_gsea( + mat: Path, + net: Path, + output: Path, + mat_source_col: str = 'genes', + mat_target_col: str = 'cells', + mat_value_col: str = 'expression', + net_source_col: str = 'tf', + net_target_col: str = 'target', + net_weight_col: str = 'weight', + min_n: int = 5, + batch_size: int = 10000, + times: int = 100, + min_sz: int = 5, + max_sz: int = 500, + seed: int = 42, + verbose: bool = False, +): + """ + Runs Gene Set Enrichment Analysis (GSEA) using decoupler. + + GSEA determines whether a defined set of genes shows statistically significant, concordant + differences between two biological states. + + Args: + mat: Path to the input matrix file. + net: Path to the input network file. + output: Path to the output file. + mat_source_col: Column name for features in the matrix file. + mat_target_col: Column name for samples in the matrix file. + mat_value_col: Column name for values in the matrix file. + net_source_col: Column name for regulators in the network file. + net_target_col: Column name for targets in the network file. + net_weight_col: Column name for interaction weights in the network file. + min_n: Minimum number of targets per regulator. + batch_size: Number of samples to process per batch. + times: Number of permutations to perform. + min_sz: Minimum size of a gene set to be considered. + max_sz: Maximum size of a gene set to be considered. + seed: Random seed for permutations. + verbose: If True, increases verbosity. + """ + # Input validation + if not mat.is_file(): + raise FileNotFoundError(f"Input matrix file not found: {mat}") + if not net.is_file(): + raise FileNotFoundError(f"Input network file not found: {net}") + if min_n < 1: + raise ValueError("min_n must be a positive integer.") + if batch_size < 1: + raise ValueError("batch_size must be a positive integer.") + if times < 1: + raise ValueError("times must be a positive integer.") + if min_sz < 1: + raise ValueError("min_sz must be a positive integer.") + if max_sz < min_sz: + raise ValueError("max_sz must be greater than or equal to min_sz.") + + output.parent.mkdir(parents=True, exist_ok=True) + + cmd = [ + "python", "-m", "decoupler", "gsea", + "--mat", str(mat), + "--net", str(net), + "--output", str(output), + "--mat-source-col", mat_source_col, + "--mat-target-col", mat_target_col, + "--mat-value-col", mat_value_col, + "--net-source-col", net_source_col, + "--net-target-col", net_target_col, + "--net-weight-col", net_weight_col, + "--min-n", str(min_n), + "--batch-size", str(batch_size), + "--times", str(times), + "--min-sz", str(min_sz), + "--max-sz", str(max_sz), + "--seed", str(seed), + ] + if verbose: + cmd.append("--verbose") + + try: + process = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + ) + except subprocess.CalledProcessError as e: + return { + "command_executed": " ".join(e.cmd), + "stdout": e.stdout, + "stderr": e.stderr, + "return_code": e.returncode, + "output_files": [] + } + + return { + "command_executed": " ".join(cmd), + "stdout": process.stdout, + "stderr": process.stderr, + "output_files": [str(output)] + } \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_decoupler/app/decoupler_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_decoupler/app/decoupler_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..aea17c8ba6fdb5e501100ca59977ddac4ee16262 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_decoupler/app/decoupler_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_decoupler/app/decoupler_server.py') +SERVER_NAME = 'biosci_decoupler' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_decoupler/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_decoupler/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..22f3efd81dab73f998d976fd326fd2e380848eeb --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_decoupler/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-decoupler: + build: . + image: mcp-decoupler:latest + container_name: mcp-decoupler + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=decoupler + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_decoupler/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_decoupler/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..6a5b7a5c89f50dc67d9a15ca2e32f2b1b7d5d2dc --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_decoupler/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - decoupler + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_decoupler/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_decoupler/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_decoupler/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_delly/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_delly/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..b366d486cfa17d61cf0e4df2c8805f0e78f166a6 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_delly/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install delly via conda (e.g., from bioconda) +RUN conda install -c bioconda delly -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY app/delly_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/delly_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/delly_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_delly/app/delly_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_delly/app/delly_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..f3f746a74deec40591041b0c1a613f45af9679fd --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_delly/app/delly_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_delly/app/delly_server.py') +SERVER_NAME = 'biosci_delly' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_delly/app/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_delly/app/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_delly/app/requirements.txt @@ -0,0 +1 @@ + diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_delly/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_delly/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..3d263a79b1b4afc953f99195066dd01c5e1e94e3 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_delly/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-delly: + build: . + image: mcp-delly:latest + container_name: mcp-delly + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=delly + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_delly/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_delly/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..0807f33b5ba4db9b38fd918a18310c4fffecfed7 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_delly/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - delly + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_delly/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_delly/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_delly/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_dendropy/app/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_dendropy/app/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_dendropy/app/requirements.txt @@ -0,0 +1 @@ + diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_dendropy/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_dendropy/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..4ab49e61a4ca54072f87f5c362e6acca9a8b32f9 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_dendropy/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - dendropy + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_f5c/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_f5c/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..eaef5740a5c642df6299aa092a081142acb54aee --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_f5c/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install f5c via conda (e.g., from bioconda) +RUN conda install -c bioconda f5c -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY app/f5c_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/f5c_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/f5c_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_f5c/app/f5c_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_f5c/app/f5c_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..5dcec23ee13078667ea74679527dcaac106084e5 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_f5c/app/f5c_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_f5c/app/f5c_server.py') +SERVER_NAME = 'biosci_f5c' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_f5c/app/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_f5c/app/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_f5c/app/requirements.txt @@ -0,0 +1 @@ + diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_f5c/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_f5c/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..27e8b4b3b5a91d89ffed73d50a016ff54733c436 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_f5c/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-f5c: + build: . + image: mcp-f5c:latest + container_name: mcp-f5c + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=f5c + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_f5c/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_f5c/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..1bf1537b730c60252e18ce645322db7804f478b2 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_f5c/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - f5c + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_f5c/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_f5c/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_f5c/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_fastqc/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_fastqc/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..4a46b609ae07f90c3549799577d88835ea8fa245 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_fastqc/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install fastqc via conda (e.g., from bioconda) +RUN conda install -c bioconda fastqc -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY app/fastqc_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/fastqc_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/fastqc_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_fastqc/app/fastqc_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_fastqc/app/fastqc_server.py new file mode 100644 index 0000000000000000000000000000000000000000..f36091d83309d23a007c5bd9df589c96c1fc2874 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_fastqc/app/fastqc_server.py @@ -0,0 +1,193 @@ +import subprocess +import logging +from pathlib import Path +from typing import List, Optional, Literal + +# Setup logging +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + +# This is a placeholder for the MCP decorator. +# In a real MCP environment, this would be: +# from mcp import tool as mcp_tool +class mcp: + @staticmethod + def tool(func): + return func + +@mcp.tool +def fastqc( + seqfiles: List[Path], + outdir: Optional[Path] = None, + threads: int = 1, + contaminants: Optional[Path] = None, + adapters: Optional[Path] = None, + kmers: int = 7, + format: Optional[Literal["bam", "sam", "bam_mapped", "sam_mapped", "fastq"]] = None, + quiet: bool = False, + casava: bool = False, + nano: bool = False, + nofilter: bool = False, + extract: bool = False, + nogroup: bool = False, + min_length: Optional[int] = None, + fast5_dir: Optional[Path] = None, + no_summary: bool = False, +) -> dict: + """ + Runs FastQC, a quality control tool for high throughput sequence data. + + FastQC reads a set of sequence files and produces a quality control report + in HTML format, along with a zip archive containing the raw data. + + Args: + seqfiles: A list of sequence files to be processed (e.g., FASTQ, BAM, SAM). + outdir: Directory to store all output files. Must exist beforehand. + If not set, output is saved in the same directory as each input file. + threads: Number of files to process simultaneously. Defaults to 1. + contaminants: Path to a non-default file listing contaminants. + adapters: Path to a non-default file listing adapter sequences. + kmers: The length of k-mer to look for in the K-mer content module. Must be between 2 and 10. Defaults to 7. + format: Bypasses format detection. Forces FastQC to use the specified format. + quiet: Suppress all progress messages on stdout and only report errors. + casava: Indicates that files come from raw Casava output. + nano: Indicates that files are Nanopore fast5 files. + nofilter: Disables read filtering for reads failing QC. + extract: Uncompresses the output zip file after creation. + nogroup: Disables base grouping for reads >50bp. WARNING: Can be memory-intensive. + min_length: Sets an artificial lower limit on the sequence length for reporting. + fast5_dir: For Nanopore data, specifies the directory containing raw fast5 files. + no_summary: Prevents the generation of summary.txt and images.zip files. + + Returns: + A dictionary containing the executed command, stdout, stderr, and a list of output files. + """ + # --- Input Validation --- + if not seqfiles: + raise ValueError("At least one sequence file must be provided.") + for seqfile in seqfiles: + if not seqfile.is_file(): + raise FileNotFoundError(f"Input sequence file not found: {seqfile}") + + if outdir: + if not outdir.is_dir(): + raise NotADirectoryError(f"Output directory does not exist: {outdir}") + + if not 1 <= threads: + raise ValueError("Number of threads must be at least 1.") + + if contaminants and not contaminants.is_file(): + raise FileNotFoundError(f"Contaminants file not found: {contaminants}") + + if adapters and not adapters.is_file(): + raise FileNotFoundError(f"Adapters file not found: {adapters}") + + if not 2 <= kmers <= 10: + raise ValueError("K-mer size must be between 2 and 10.") + + if min_length is not None and min_length < 1: + raise ValueError("min_length must be a positive integer.") + + if fast5_dir and not fast5_dir.is_dir(): + raise NotADirectoryError(f"Fast5 directory not found: {fast5_dir}") + + # --- Command Construction --- + cmd = ["fastqc"] + + if outdir: + cmd.extend(["--outdir", str(outdir)]) + + cmd.extend(["--threads", str(threads)]) + + if contaminants: + cmd.extend(["--contaminants", str(contaminants)]) + + if adapters: + cmd.extend(["--adapters", str(adapters)]) + + cmd.extend(["--kmers", str(kmers)]) + + if format: + cmd.extend(["--format", format]) + + if quiet: + cmd.append("--quiet") + if casava: + cmd.append("--casava") + if nano: + cmd.append("--nano") + if nofilter: + cmd.append("--nofilter") + if extract: + cmd.append("--extract") + if nogroup: + cmd.append("--nogroup") + if no_summary: + cmd.append("--no-summary") + + if min_length is not None: + cmd.extend(["--min_length", str(min_length)]) + + if fast5_dir: + cmd.extend(["--fast5-dir", str(fast5_dir)]) + + cmd.extend([str(sf) for sf in seqfiles]) + command_executed = " ".join(cmd) + logger.info(f"Executing command: {command_executed}") + + # --- Subprocess Execution --- + try: + result = subprocess.run( + cmd, + check=True, + capture_output=True, + text=True, + ) + except FileNotFoundError: + raise RuntimeError("fastqc not found. Please ensure it is installed and in your PATH.") + except subprocess.CalledProcessError as e: + logger.error(f"FastQC failed with exit code {e.returncode}") + logger.error(f"Stdout: {e.stdout}") + logger.error(f"Stderr: {e.stderr}") + raise e + + # --- Output File Discovery --- + output_files = [] + for seqfile in seqfiles: + # FastQC uses the file stem for output names. + # e.g., 'my_reads.fastq.gz' -> stem 'my_reads.fastq' -> output 'my_reads.fastq_fastqc.html' + # e.g., 'my_reads.fastq' -> stem 'my_reads' -> output 'my_reads_fastqc.html' + stem = seqfile.stem + + # Output is placed in outdir if specified, otherwise next to the input file. + current_output_dir = outdir if outdir else seqfile.parent + + html_output = current_output_dir / f"{stem}_fastqc.html" + zip_output = current_output_dir / f"{stem}_fastqc.zip" + + if html_output.exists(): + output_files.append(str(html_output)) + if zip_output.exists(): + output_files.append(str(zip_output)) + + if extract: + extracted_dir = current_output_dir / f"{stem}_fastqc" + if extracted_dir.is_dir(): + output_files.append(str(extracted_dir)) + + # Discover summary files, which are generated in the main output directory + if not no_summary: + summary_dir = outdir if outdir else seqfiles[0].parent + summary_txt = summary_dir / "summary.txt" + images_zip = summary_dir / "images.zip" + if summary_txt.exists(): + output_files.append(str(summary_txt)) + if images_zip.exists(): + output_files.append(str(images_zip)) + + return { + "command_executed": command_executed, + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": sorted(list(set(output_files))), # Ensure unique paths + } \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_fastqc/app/fastqc_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_fastqc/app/fastqc_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..0ca8d91748a3aef39a91a2c87c70726eac39b728 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_fastqc/app/fastqc_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_fastqc/app/fastqc_server.py') +SERVER_NAME = 'biosci_fastqc' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_fastqc/app/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_fastqc/app/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_fastqc/app/requirements.txt @@ -0,0 +1 @@ + diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_fastqc/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_fastqc/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..b485c7107b50c9c6a9edf5ee3c6a0f48ba7f7d0f --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_fastqc/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-fastqc: + build: . + image: mcp-fastqc:latest + container_name: mcp-fastqc + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=fastqc + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_fastqc/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_fastqc/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..e27c18d74da1786962c7e7a84138540b00eb640a --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_fastqc/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - fastqc + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_fastqc/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_fastqc/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_fastqc/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_last/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_last/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..59483952effb91e93d6fe94ff3a4e05472227116 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_last/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install last via conda (e.g., from bioconda) +RUN conda install -c bioconda last -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY app/last_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/last_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/last_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_last/app/last_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_last/app/last_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..0eba9eaaea90e4d3869fb3ab64e8914c94a1c5c9 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_last/app/last_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_last/app/last_server.py') +SERVER_NAME = 'biosci_last' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_last/app/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_last/app/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_last/app/requirements.txt @@ -0,0 +1 @@ + diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_last/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_last/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..f11374230c29c61fa7cbe392bccd719c5bbd170f --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_last/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-last: + build: . + image: mcp-last:latest + container_name: mcp-last + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=last + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_last/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_last/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..3ca4459a1b5cfccdfb8ecc122b0d497c0670d4ff --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_last/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - last + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_last/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_last/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_last/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_multivelo/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_multivelo/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..089a5ac8ddef0130e2b63289fea1808fb4f8fa9b --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_multivelo/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install multivelo via conda (e.g., from bioconda) +RUN conda install -c bioconda multivelo -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY multivelo_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/multivelo_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/multivelo_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_multivelo/app/multivelo_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_multivelo/app/multivelo_server.py new file mode 100644 index 0000000000000000000000000000000000000000..71ff07ea56659c1b263921f5cf6db40854fb92f6 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_multivelo/app/multivelo_server.py @@ -0,0 +1,153 @@ +import subprocess +from pathlib import Path +from typing import Optional, List +import logging + +# Set up logging +logging.basicConfig(level=logging.INFO) +log = logging.getLogger(__name__) + +# This is a placeholder for the actual MCP decorator. +# In a real MCP environment, this would be imported. +class mcp: + def tool(func): + return func + +@mcp.tool +def run_multivelo( + data_path: Path, + output_path: Path, + gene_list_path: Optional[Path] = None, + sample: Optional[str] = None, + modality: str = "rna", + cell_anno_key: str = "cell_type", + embed_key: str = "X_umap", + n_genes: int = 2000, + fig_path: Optional[Path] = None, + no_preproc: bool = False, + no_plot: bool = False, +) -> dict: + """ + Infers cell dynamics from multi-omics data using the multivelo command-line tool. + + This tool is a wrapper for the `multivelo` Python package, which performs + velocity estimation on multi-modal single-cell data. It requires an AnnData + object as input and produces a new AnnData object with velocity information. + + Args: + data_path: Path to the input anndata file (.h5ad). + output_path: Path to save the output anndata file (.h5ad). + gene_list_path: Optional path to a gene list file. + sample: Optional sample name to be processed from the anndata object. + modality: Modality to be used for velocity estimation (e.g., 'rna'). + cell_anno_key: Key in .obs for cell type annotations. + embed_key: Key in .obsm for the cell embedding (e.g., 'X_umap'). + n_genes: Number of highly variable genes to use for velocity estimation. + fig_path: Optional path to a directory to save figures. + no_preproc: If True, skips the preprocessing steps. + no_plot: If True, skips the plotting steps. + + Returns: + A dictionary containing the executed command, stdout, stderr, and a list of output files. + """ + # 1. Input Validation + if not data_path.is_file(): + raise FileNotFoundError(f"Input data file not found: {data_path}") + if gene_list_path and not gene_list_path.is_file(): + raise FileNotFoundError(f"Gene list file not found: {gene_list_path}") + if n_genes <= 0: + raise ValueError("n_genes must be a positive integer.") + + # 2. Ensure output directories exist + try: + output_path.parent.mkdir(parents=True, exist_ok=True) + if fig_path: + fig_path.mkdir(parents=True, exist_ok=True) + except OSError as e: + log.error(f"Failed to create output directories: {e}") + raise + + # 3. Command Construction + # The command is executed as a Python module. + cmd = [ + "python", + "-m", + "multivelo", + "--data_path", str(data_path), + "--output_path", str(output_path), + "--modality", modality, + "--cell_anno_key", cell_anno_key, + "--embed_key", embed_key, + "--n_genes", str(n_genes), + ] + + if gene_list_path: + cmd.extend(["--gene_list_path", str(gene_list_path)]) + if sample: + cmd.extend(["--sample", sample]) + if fig_path: + cmd.extend(["--fig_path", str(fig_path)]) + if no_preproc: + cmd.append("--no_preproc") + if no_plot: + cmd.append("--no_plot") + + command_executed = " ".join(cmd) + log.info(f"Executing command: {command_executed}") + + # 4. Subprocess Execution + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + encoding='utf-8' + ) + except FileNotFoundError: + error_msg = "Error: 'python' executable not found. Please ensure Python and multivelo are installed and in your system's PATH." + log.error(error_msg) + # In a real MCP environment, you might raise a specific exception + # For this structure, we return an error dictionary. + return { + "error": error_msg, + "command_executed": command_executed, + "stdout": "", + "stderr": "", + } + except subprocess.CalledProcessError as e: + log.error(f"multivelo execution failed with return code {e.returncode}") + log.error(f"STDOUT: {e.stdout}") + log.error(f"STDERR: {e.stderr}") + return { + "error": "multivelo execution failed.", + "command_executed": command_executed, + "stdout": e.stdout, + "stderr": e.stderr, + "return_code": e.returncode, + } + + # 5. Structured Result Return + output_files = [] + if output_path.exists(): + output_files.append(str(output_path)) + else: + log.warning(f"Expected output file was not created: {output_path}") + + # If a figure path was provided, we can list the generated files. + # This assumes figures are PNGs, a common default. + if fig_path and fig_path.is_dir(): + generated_figs = [str(f) for f in fig_path.glob('*.png')] + if generated_figs: + output_files.extend(generated_figs) + else: + # Add the directory itself if no specific files are found + output_files.append(str(fig_path)) + + + return { + "command_executed": command_executed, + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": output_files, + } \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_multivelo/app/multivelo_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_multivelo/app/multivelo_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..fe3dce043f820d5a19d8dd2ca3d0c0be31d9ee93 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_multivelo/app/multivelo_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_multivelo/app/multivelo_server.py') +SERVER_NAME = 'biosci_multivelo' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_multivelo/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_multivelo/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..35bded64b155a199bf8d6c7650340b4ee9d41609 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_multivelo/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-multivelo: + build: . + image: mcp-multivelo:latest + container_name: mcp-multivelo + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=multivelo + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_multivelo/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_multivelo/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..9b2ed23315f6e900fd97d9dafc04758b6f6f29ae --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_multivelo/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - multivelo + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_multivelo/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_multivelo/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_multivelo/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_perl-metabolomics-fragment-annotation/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_perl-metabolomics-fragment-annotation/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..ffb5eaac759ff0959075bb715683824bbc7e7dde --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_perl-metabolomics-fragment-annotation/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install perl-metabolomics-fragment-annotation via conda (e.g., from bioconda) +RUN conda install -c bioconda perl-metabolomics-fragment-annotation -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY perl-metabolomics-fragment-annotation_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/perl-metabolomics-fragment-annotation_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/perl-metabolomics-fragment-annotation_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_perl-metabolomics-fragment-annotation/app/perl-metabolomics-fragment-annotation_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_perl-metabolomics-fragment-annotation/app/perl-metabolomics-fragment-annotation_server.py new file mode 100644 index 0000000000000000000000000000000000000000..50a609b52de8d4e0a49849a2df54d1a7018cd213 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_perl-metabolomics-fragment-annotation/app/perl-metabolomics-fragment-annotation_server.py @@ -0,0 +1,140 @@ +import subprocess +import tempfile +from pathlib import Path +from typing import Optional, List + +# The mcp.tool decorator is not defined here, as per the problem description. +# It is assumed to be provided by the MCP framework. +# +# @mcp.tool() +# def placeholder(): +# pass + + +@mcp.tool() +def fragment_annotation( + in_file: Path, + out_file: Path, + db_file: Optional[Path] = None, + mode: str = "positive", + precursor_mz: Optional[float] = None, + precursor_adduct: Optional[str] = None, + fragment_tol: float = 0.01, + fragment_tol_unit: str = "Da", + min_intensity: float = 1.0, + max_depth: int = 2, + verbose: bool = False, +) -> dict: + """ + Annotates MS/MS fragment ions from metabolomics data using fragment-annotation.pl. + + This tool takes a peak list file (e.g., MGF, MSP) and annotates the fragments + against a compound database. + + Args: + in_file: Input file containing peak list data (e.g., MGF, MSP). + out_file: Output file for annotated results (e.g., CSV, TSV). + db_file: Database file of known compounds (e.g., SDF, MOL). Highly recommended for annotation. + mode: Ionization mode. Must be 'positive' or 'negative'. + precursor_mz: Precursor m/z value. If not provided, it will be read from the input file. + precursor_adduct: Precursor adduct type (e.g., '[M+H]+', '[M-H]-'). + fragment_tol: Fragment tolerance value. Must be a positive number. + fragment_tol_unit: Fragment tolerance unit. Must be 'Da' or 'ppm'. + min_intensity: Minimum relative intensity for fragments to be considered (0-100). + max_depth: Maximum fragmentation depth to consider. Must be a positive integer. + verbose: Enable verbose logging. + + Returns: + A dictionary containing the command executed, stdout, stderr, and a list of output files. + """ + # 1. Input Validation + if not in_file.is_file(): + raise FileNotFoundError(f"Input file not found: {in_file}") + + if db_file and not db_file.is_file(): + raise FileNotFoundError(f"Database file not found: {db_file}") + + if out_file.parent and not out_file.parent.exists(): + out_file.parent.mkdir(parents=True, exist_ok=True) + + if mode not in ["positive", "negative"]: + raise ValueError(f"Invalid mode '{mode}'. Must be 'positive' or 'negative'.") + + if fragment_tol <= 0: + raise ValueError(f"Fragment tolerance must be positive, but got {fragment_tol}.") + + if fragment_tol_unit not in ["Da", "ppm"]: + raise ValueError(f"Invalid fragment tolerance unit '{fragment_tol_unit}'. Must be 'Da' or 'ppm'.") + + if not (0.0 <= min_intensity <= 100.0): + raise ValueError(f"Minimum intensity must be between 0 and 100, but got {min_intensity}.") + + if max_depth <= 0: + raise ValueError(f"Maximum depth must be a positive integer, but got {max_depth}.") + + # 2. Command Construction + # Assuming the tool is available in the system's PATH as 'fragment-annotation.pl' + cmd = [ + "fragment-annotation.pl", + "--in", str(in_file), + "--out", str(out_file), + "--mode", mode, + "--fragment_tol", str(fragment_tol), + "--fragment_tol_unit", fragment_tol_unit, + "--min_intensity", str(min_intensity), + "--max_depth", str(max_depth), + ] + + if db_file: + cmd.extend(["--db", str(db_file)]) + if precursor_mz is not None: + cmd.extend(["--precursor_mz", str(precursor_mz)]) + if precursor_adduct: + cmd.extend(["--precursor_adduct", precursor_adduct]) + if verbose: + cmd.append("--verbose") + + # 3. Subprocess Execution and Error Handling + command_executed = " ".join(cmd) + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + encoding='utf-8' + ) + + # 4. Structured Result Return (Success) + return { + "command_executed": command_executed, + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": [str(out_file)] + } + except FileNotFoundError: + # This error occurs if 'fragment-annotation.pl' is not in the PATH + raise RuntimeError("The command 'fragment-annotation.pl' was not found. Please ensure the tool is installed and in your system's PATH.") + except subprocess.CalledProcessError as e: + # This error occurs if the tool returns a non-zero exit code + # The MCP framework will typically handle this exception, but returning a + # structured error provides more context to the user. + error_message = ( + f"Tool execution failed with return code {e.returncode}.\n" + f"Command: {command_executed}\n" + f"Stdout: {e.stdout}\n" + f"Stderr: {e.stderr}" + ) + # Re-raising is often better for MCP to handle, but if we must return: + # For this problem, we will re-raise to let the MCP framework handle it, + # as this is a more robust pattern. If a dictionary must be returned, + # the following code could be used instead of raising the exception. + # + # return { + # "command_executed": command_executed, + # "stdout": e.stdout, + # "stderr": e.stderr, + # "error": f"Tool execution failed with return code {e.returncode}.", + # "output_files": [] + # } + raise RuntimeError(error_message) from e \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_perl-metabolomics-fragment-annotation/app/perl-metabolomics-fragment-annotation_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_perl-metabolomics-fragment-annotation/app/perl-metabolomics-fragment-annotation_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..2b1dae85b27cd09b8ec536c3a14de7e61ab261af --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_perl-metabolomics-fragment-annotation/app/perl-metabolomics-fragment-annotation_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_perl-metabolomics-fragment-annotation/app/perl-metabolomics-fragment-annotation_server.py') +SERVER_NAME = 'biosci_perl_metabolomics_fragment_annotation' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_perl-metabolomics-fragment-annotation/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_perl-metabolomics-fragment-annotation/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..b523ed6b72467dcd5874c2cefd94dcd3ef457613 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_perl-metabolomics-fragment-annotation/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-perl-metabolomics-fragment-annotation: + build: . + image: mcp-perl-metabolomics-fragment-annotation:latest + container_name: mcp-perl-metabolomics-fragment-annotation + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=perl-metabolomics-fragment-annotation + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_perl-metabolomics-fragment-annotation/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_perl-metabolomics-fragment-annotation/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..ded292d05dc8663928c1e34800953b626c95932f --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_perl-metabolomics-fragment-annotation/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - perl-metabolomics-fragment-annotation + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_perl-metabolomics-fragment-annotation/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_perl-metabolomics-fragment-annotation/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_perl-metabolomics-fragment-annotation/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_picard/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_picard/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..f601a803ec38d238369efa7d6e980988d48b19ed --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_picard/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install picard via conda (e.g., from bioconda) +RUN conda install -c bioconda picard -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY app/picard_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/picard_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/picard_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_picard/app/picard_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_picard/app/picard_server.py new file mode 100644 index 0000000000000000000000000000000000000000..793a52bab6d0dbdc26df6bfef493cb16edc23ed0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_picard/app/picard_server.py @@ -0,0 +1,509 @@ +import subprocess +import logging +from pathlib import Path +from typing import Optional, List, Union + +# --- MCP Tool Definition for Picard --- + +# Configure logging +logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') + +# Assume 'picard' is an executable in the system's PATH. +# This is a common setup when installed via Conda or as a standalone wrapper script. +PICARD_COMMAND = "picard" + +# Helper function to handle the return logic, not exposed as an MCP tool. +def _run_picard_command(cmd: List[Union[str, Path]], output_file_key: str, output_path: Path, create_md5: bool = False): + """ + Internal helper to execute a Picard command and return a structured response. + """ + # Convert all command parts to strings for execution + cmd_str_list = [str(c) for c in cmd] + command_to_execute = " ".join(cmd_str_list) + logging.info(f"Executing command: {command_to_execute}") + + try: + result = subprocess.run( + cmd_str_list, + capture_output=True, + text=True, + check=True, + ) + except FileNotFoundError: + error_msg = f"'{PICARD_COMMAND}' command not found. Is Picard installed and in your system's PATH?" + logging.error(error_msg) + raise RuntimeError(error_msg) from None + except subprocess.CalledProcessError as e: + logging.error(f"Picard command failed with exit code {e.returncode}") + logging.error(f"Stderr: {e.stderr}") + logging.error(f"Stdout: {e.stdout}") + # Re-raise to be handled by the MCP framework + raise e + + output_files = {output_file_key: str(output_path)} + if create_md5: + md5_file = output_path.with_suffix(output_path.suffix + ".md5") + if md5_file.exists(): + output_files["md5"] = str(md5_file) + + return { + "command_executed": command_to_execute, + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": output_files, + } + + +@mcp.tool() +def add_or_replace_read_groups( + input_bam: Path, + output_bam: Path, + read_group_id: str, + read_group_library: str, + read_group_platform: str, + read_group_platform_unit: str, + read_group_sample_name: str, + sort_order: Optional[str] = None, + validation_stringency: str = "STRICT", + create_index: bool = True, + create_md5_file: bool = False, + tmp_dir: Optional[Path] = None, +) -> dict: + """ + Replaces all read groups in the input BAM file with a single new read group. + """ + if not input_bam.is_file(): + raise FileNotFoundError(f"Input BAM file not found: {input_bam}") + + valid_stringencies = ["STRICT", "LENIENT", "SILENT"] + if validation_stringency not in valid_stringencies: + raise ValueError(f"VALIDATION_STRINGENCY must be one of {valid_stringencies}") + + output_bam.parent.mkdir(parents=True, exist_ok=True) + + cmd = [ + PICARD_COMMAND, "AddOrReplaceReadGroups", + f"INPUT={input_bam}", + f"OUTPUT={output_bam}", + f"RGID={read_group_id}", + f"RGLB={read_group_library}", + f"RGPL={read_group_platform}", + f"RGPU={read_group_platform_unit}", + f"RGSM={read_group_sample_name}", + f"VALIDATION_STRINGENCY={validation_stringency}", + f"CREATE_INDEX={str(create_index).lower()}", + f"CREATE_MD5_FILE={str(create_md5_file).lower()}", + ] + + if sort_order: + valid_sort_orders = ["unsorted", "queryname", "coordinate", "duplicate", "unknown"] + if sort_order not in valid_sort_orders: + raise ValueError(f"SORT_ORDER must be one of {valid_sort_orders}") + cmd.append(f"SORT_ORDER={sort_order}") + + if tmp_dir: + tmp_dir.mkdir(parents=True, exist_ok=True) + cmd.append(f"TMP_DIR={tmp_dir}") + + return _run_picard_command(cmd, "output_bam", output_bam, create_md5_file) + + +@mcp.tool() +def build_bam_index( + input_bam: Path, + output_bai: Optional[Path] = None, + validation_stringency: str = "STRICT", +) -> dict: + """ + Generates a BAM index (.bai) file for a coordinate-sorted BAM file. + """ + if not input_bam.is_file(): + raise FileNotFoundError(f"Input BAM file not found: {input_bam}") + + if output_bai is None: + # Picard defaults to creating a .bai file next to the input + output_bai = input_bam.with_suffix(input_bam.suffix + ".bai") + + output_bai.parent.mkdir(parents=True, exist_ok=True) + + cmd = [ + PICARD_COMMAND, "BuildBamIndex", + f"INPUT={input_bam}", + f"OUTPUT={output_bai}", + f"VALIDATION_STRINGENCY={validation_stringency}", + ] + + return _run_picard_command(cmd, "bai_file", output_bai) + + +@mcp.tool() +def collect_alignment_summary_metrics( + input_bam: Path, + output_metrics: Path, + reference_fasta: Path, + assume_sorted: bool = True, + adapter_sequence: Optional[List[str]] = None, + max_insert_size: int = 100000, + validation_stringency: str = "STRICT", + tmp_dir: Optional[Path] = None, +) -> dict: + """ + Collects alignment metrics from a BAM file. + """ + if not input_bam.is_file(): + raise FileNotFoundError(f"Input BAM file not found: {input_bam}") + if not reference_fasta.is_file(): + raise FileNotFoundError(f"Reference FASTA file not found: {reference_fasta}") + + output_metrics.parent.mkdir(parents=True, exist_ok=True) + + cmd = [ + PICARD_COMMAND, "CollectAlignmentSummaryMetrics", + f"INPUT={input_bam}", + f"OUTPUT={output_metrics}", + f"REFERENCE_SEQUENCE={reference_fasta}", + f"ASSUME_SORTED={str(assume_sorted).lower()}", + f"MAX_INSERT_SIZE={max_insert_size}", + f"VALIDATION_STRINGENCY={validation_stringency}", + ] + + if adapter_sequence: + for seq in adapter_sequence: + cmd.append(f"ADAPTER_SEQUENCE={seq}") + + if tmp_dir: + tmp_dir.mkdir(parents=True, exist_ok=True) + cmd.append(f"TMP_DIR={tmp_dir}") + + return _run_picard_command(cmd, "metrics_file", output_metrics) + + +@mcp.tool() +def collect_insert_size_metrics( + input_bam: Path, + output_metrics: Path, + output_histogram: Path, + minimum_pct: float = 0.05, + validation_stringency: str = "STRICT", + tmp_dir: Optional[Path] = None, +) -> dict: + """ + Collects insert size metrics from a BAM file. + """ + if not input_bam.is_file(): + raise FileNotFoundError(f"Input BAM file not found: {input_bam}") + + output_metrics.parent.mkdir(parents=True, exist_ok=True) + output_histogram.parent.mkdir(parents=True, exist_ok=True) + + cmd = [ + PICARD_COMMAND, "CollectInsertSizeMetrics", + f"INPUT={input_bam}", + f"OUTPUT={output_metrics}", + f"HISTOGRAM_FILE={output_histogram}", + f"MINIMUM_PCT={minimum_pct}", + f"VALIDATION_STRINGENCY={validation_stringency}", + ] + + if tmp_dir: + tmp_dir.mkdir(parents=True, exist_ok=True) + cmd.append(f"TMP_DIR={tmp_dir}") + + # This tool produces two primary outputs + result = _run_picard_command(cmd, "metrics_file", output_metrics) + result["output_files"]["histogram_file"] = str(output_histogram) + return result + + +@mcp.tool() +def create_sequence_dictionary( + reference_fasta: Path, + output_dict: Path, + genome_assembly: Optional[str] = None, + uri: Optional[str] = None, + species: Optional[str] = None, + truncate_names_at_whitespace: bool = True, + validation_stringency: str = "STRICT", +) -> dict: + """ + Creates a sequence dictionary file (.dict) from a reference FASTA file. + """ + if not reference_fasta.is_file(): + raise FileNotFoundError(f"Reference FASTA file not found: {reference_fasta}") + + output_dict.parent.mkdir(parents=True, exist_ok=True) + + cmd = [ + PICARD_COMMAND, "CreateSequenceDictionary", + f"REFERENCE={reference_fasta}", + f"OUTPUT={output_dict}", + f"TRUNCATE_NAMES_AT_WHITESPACE={str(truncate_names_at_whitespace).lower()}", + f"VALIDATION_STRINGENCY={validation_stringency}", + ] + + if genome_assembly: + cmd.append(f"GENOME_ASSEMBLY={genome_assembly}") + if uri: + cmd.append(f"URI={uri}") + if species: + cmd.append(f"SPECIES={species}") + + return _run_picard_command(cmd, "dictionary_file", output_dict) + + +@mcp.tool() +def fastq_to_sam( + fastq1: Path, + output_bam: Path, + sample_name: str, + read_group_name: str, + library_name: str, + platform: str, + platform_unit: str, + fastq2: Optional[Path] = None, + sort_order: str = "queryname", + validation_stringency: str = "STRICT", + tmp_dir: Optional[Path] = None, +) -> dict: + """ + Converts FASTQ files to an unaligned BAM file. + """ + if not fastq1.is_file(): + raise FileNotFoundError(f"Input FASTQ1 file not found: {fastq1}") + if fastq2 and not fastq2.is_file(): + raise FileNotFoundError(f"Input FASTQ2 file not found: {fastq2}") + + valid_sort_orders = ["unsorted", "queryname", "coordinate", "duplicate", "unknown"] + if sort_order not in valid_sort_orders: + raise ValueError(f"SORT_ORDER must be one of {valid_sort_orders}") + + output_bam.parent.mkdir(parents=True, exist_ok=True) + + cmd = [ + PICARD_COMMAND, "FastqToSam", + f"FASTQ={fastq1}", + f"OUTPUT={output_bam}", + f"SAMPLE_NAME={sample_name}", + f"READ_GROUP_NAME={read_group_name}", + f"LIBRARY_NAME={library_name}", + f"PLATFORM={platform}", + f"PLATFORM_UNIT={platform_unit}", + f"SORT_ORDER={sort_order}", + f"VALIDATION_STRINGENCY={validation_stringency}", + ] + + if fastq2: + cmd.append(f"FASTQ2={fastq2}") + + if tmp_dir: + tmp_dir.mkdir(parents=True, exist_ok=True) + cmd.append(f"TMP_DIR={tmp_dir}") + + return _run_picard_command(cmd, "output_bam", output_bam) + + +@mcp.tool() +def mark_duplicates( + input_bam: Path, + output_bam: Path, + metrics_file: Path, + remove_duplicates: bool = False, + assume_sorted: bool = True, + optical_duplicate_pixel_distance: int = 100, + validation_stringency: str = "STRICT", + create_index: bool = True, + create_md5_file: bool = False, + tmp_dir: Optional[Path] = None, +) -> dict: + """ + Identifies and flags duplicate reads in a BAM file. + """ + if not input_bam.is_file(): + raise FileNotFoundError(f"Input BAM file not found: {input_bam}") + + output_bam.parent.mkdir(parents=True, exist_ok=True) + metrics_file.parent.mkdir(parents=True, exist_ok=True) + + cmd = [ + PICARD_COMMAND, "MarkDuplicates", + f"INPUT={input_bam}", + f"OUTPUT={output_bam}", + f"METRICS_FILE={metrics_file}", + f"REMOVE_DUPLICATES={str(remove_duplicates).lower()}", + f"ASSUME_SORTED={str(assume_sorted).lower()}", + f"OPTICAL_DUPLICATE_PIXEL_DISTANCE={optical_duplicate_pixel_distance}", + f"VALIDATION_STRINGENCY={validation_stringency}", + f"CREATE_INDEX={str(create_index).lower()}", + f"CREATE_MD5_FILE={str(create_md5_file).lower()}", + ] + + if tmp_dir: + tmp_dir.mkdir(parents=True, exist_ok=True) + cmd.append(f"TMP_DIR={tmp_dir}") + + result = _run_picard_command(cmd, "output_bam", output_bam, create_md5_file) + result["output_files"]["metrics_file"] = str(metrics_file) + return result + + +@mcp.tool() +def merge_sam_files( + input_bams: List[Path], + output_bam: Path, + sort_order: str = "coordinate", + assume_sorted: bool = False, + merge_sequence_dictionaries: bool = False, + validation_stringency: str = "STRICT", + create_index: bool = True, + create_md5_file: bool = False, + tmp_dir: Optional[Path] = None, +) -> dict: + """ + Merges multiple BAM files into a single BAM file. + """ + for bam in input_bams: + if not bam.is_file(): + raise FileNotFoundError(f"Input BAM file not found: {bam}") + if not input_bams: + raise ValueError("At least one input BAM file is required.") + + valid_sort_orders = ["unsorted", "queryname", "coordinate", "duplicate", "unknown"] + if sort_order not in valid_sort_orders: + raise ValueError(f"SORT_ORDER must be one of {valid_sort_orders}") + + output_bam.parent.mkdir(parents=True, exist_ok=True) + + cmd = [ + PICARD_COMMAND, "MergeSamFiles", + f"OUTPUT={output_bam}", + f"SORT_ORDER={sort_order}", + f"ASSUME_SORTED={str(assume_sorted).lower()}", + f"MERGE_SEQUENCE_DICTIONARIES={str(merge_sequence_dictionaries).lower()}", + f"VALIDATION_STRINGENCY={validation_stringency}", + f"CREATE_INDEX={str(create_index).lower()}", + f"CREATE_MD5_FILE={str(create_md5_file).lower()}", + ] + + for bam in input_bams: + cmd.append(f"INPUT={bam}") + + if tmp_dir: + tmp_dir.mkdir(parents=True, exist_ok=True) + cmd.append(f"TMP_DIR={tmp_dir}") + + return _run_picard_command(cmd, "output_bam", output_bam, create_md5_file) + + +@mcp.tool() +def sort_sam( + input_bam: Path, + output_bam: Path, + sort_order: str, + validation_stringency: str = "STRICT", + create_index: bool = True, + create_md5_file: bool = False, + tmp_dir: Optional[Path] = None, +) -> dict: + """ + Sorts a BAM file by coordinate, queryname, etc. + """ + if not input_bam.is_file(): + raise FileNotFoundError(f"Input BAM file not found: {input_bam}") + + valid_sort_orders = ["unsorted", "queryname", "coordinate", "duplicate", "unknown"] + if sort_order not in valid_sort_orders: + raise ValueError(f"SORT_ORDER must be one of {valid_sort_orders}") + + output_bam.parent.mkdir(parents=True, exist_ok=True) + + cmd = [ + PICARD_COMMAND, "SortSam", + f"INPUT={input_bam}", + f"OUTPUT={output_bam}", + f"SORT_ORDER={sort_order}", + f"VALIDATION_STRINGENCY={validation_stringency}", + f"CREATE_INDEX={str(create_index).lower()}", + f"CREATE_MD5_FILE={str(create_md5_file).lower()}", + ] + + if tmp_dir: + tmp_dir.mkdir(parents=True, exist_ok=True) + cmd.append(f"TMP_DIR={tmp_dir}") + + return _run_picard_command(cmd, "output_bam", output_bam, create_md5_file) + + +@mcp.tool() +def validate_sam_file( + input_sam: Path, + output_report: Optional[Path] = None, + reference_fasta: Optional[Path] = None, + mode: str = "SUMMARY", + ignore_warnings: bool = False, + max_output: int = 100, + validation_stringency: str = "STRICT", + tmp_dir: Optional[Path] = None, +) -> dict: + """ + Validates a SAM or BAM file. + """ + if not input_sam.is_file(): + raise FileNotFoundError(f"Input SAM/BAM file not found: {input_sam}") + if reference_fasta and not reference_fasta.is_file(): + raise FileNotFoundError(f"Reference FASTA file not found: {reference_fasta}") + + valid_modes = ["SUMMARY", "VERBOSE"] + if mode not in valid_modes: + raise ValueError(f"MODE must be one of {valid_modes}") + + cmd = [ + PICARD_COMMAND, "ValidateSamFile", + f"INPUT={input_sam}", + f"MODE={mode}", + f"IGNORE_WARNINGS={str(ignore_warnings).lower()}", + f"MAX_OUTPUT={max_output}", + f"VALIDATION_STRINGENCY={validation_stringency}", + ] + + if output_report: + output_report.parent.mkdir(parents=True, exist_ok=True) + cmd.append(f"OUTPUT={output_report}") + if reference_fasta: + cmd.append(f"REFERENCE_SEQUENCE={reference_fasta}") + if tmp_dir: + tmp_dir.mkdir(parents=True, exist_ok=True) + cmd.append(f"TMP_DIR={tmp_dir}") + + # The primary output of this tool is its stdout/stderr report. + # The file output is optional. + command_to_execute = " ".join(map(str, cmd)) + logging.info(f"Executing command: {command_to_execute}") + + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + ) + except FileNotFoundError: + raise RuntimeError(f"'{PICARD_COMMAND}' command not found. Is Picard installed and in your PATH?") + except subprocess.CalledProcessError as e: + # For ValidateSamFile, a non-zero exit code IS the result if errors are found. + # We capture this as a successful run that found validation errors. + logging.warning(f"ValidateSamFile finished with a non-zero exit code, indicating validation errors.") + return { + "command_executed": command_to_execute, + "stdout": e.stdout, + "stderr": e.stderr, + "output_files": {"report": str(output_report)} if output_report else {}, + "validation_passed": False + } + + return { + "command_executed": command_to_execute, + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": {"report": str(output_report)} if output_report else {}, + "validation_passed": True + } diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_picard/app/picard_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_picard/app/picard_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..045bea8f0ce2b17ec59624e2c64b52fde2741c79 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_picard/app/picard_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_picard/app/picard_server.py') +SERVER_NAME = 'biosci_picard' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_picard/app/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_picard/app/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_picard/app/requirements.txt @@ -0,0 +1 @@ + diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_picard/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_picard/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..f562a180baf655ff1d15161868a30fd34cfd9aca --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_picard/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-picard: + build: . + image: mcp-picard:latest + container_name: mcp-picard + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=picard + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_picard/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_picard/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..194f3da9c887dfb19492e9b511ce5533157315b5 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_picard/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - picard + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_picard/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_picard/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_picard/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_pycistopic/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_pycistopic/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..78a3227eb4d434212bf5fdf8a94dad3c3e06635f --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_pycistopic/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install pycistopic via conda (e.g., from bioconda) +RUN conda install -c bioconda pycistopic -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY pycistopic_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/pycistopic_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/pycistopic_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_pycistopic/app/pycistopic_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_pycistopic/app/pycistopic_server.py new file mode 100644 index 0000000000000000000000000000000000000000..c96f14c008adcb888ada912e1dc369368b1ac46f --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_pycistopic/app/pycistopic_server.py @@ -0,0 +1,310 @@ +import subprocess +from pathlib import Path +from typing import Optional, List, Union +import os + +@mcp.tool() +def pycistopic_run_models( + input_path: str, + output_path: str, + n_topics: str, + n_iter: int = 150, + burn_in: int = 100, + n_cores: int = 1, + seed: int = 123, + alpha: float = 50.0, + eta: float = 0.1, +): + """ + Run Latent Dirichlet Allocation (LDA) models for a range of topics. + + Args: + input_path: Path to the input cisTopic object (.pkl). + output_path: Path to save the cisTopic object with models (.pkl). + n_topics: Comma-separated list of topic numbers to run (e.g., "2,5,10,20,30,40,50"). + n_iter: Number of iterations for LDA (default: 150). + burn_in: Number of burn-in iterations (default: 100). + n_cores: Number of cores to use for parallel processing (default: 1). + seed: Random seed for reproducibility (default: 123). + alpha: Alpha parameter for LDA (default: 50.0). + eta: Eta parameter for LDA (default: 0.1). + """ + # Input validation + in_p = Path(input_path) + if not in_p.exists(): + return {"error": f"Input file not found: {input_path}"} + + out_p = Path(output_path) + out_p.parent.mkdir(parents=True, exist_ok=True) + + # Validate n_topics format + try: + [int(x.strip()) for x in n_topics.split(",")] + except ValueError: + return {"error": "n_topics must be a comma-separated list of integers."} + + cmd = [ + "pycistopic", "run_models", + "-i", str(in_p), + "-o", str(out_p), + "-nt", n_topics, + "-it", str(n_iter), + "-bi", str(burn_in), + "-c", str(n_cores), + "-s", str(seed), + "-a", str(alpha), + "-e", str(eta) + ] + + try: + result = subprocess.run(cmd, capture_output=True, text=True, check=True) + return { + "command_executed": " ".join(cmd), + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": [str(out_p)] + } + except subprocess.CalledProcessError as e: + return { + "command_executed": " ".join(cmd), + "error": str(e), + "stdout": e.stdout, + "stderr": e.stderr + } + +@mcp.tool() +def pycistopic_analyze_models( + input_path: str, + output_path: str, + select_model: Optional[int] = None, +): + """ + Analyze LDA models to select the optimal number of topics. + + Args: + input_path: Path to the cisTopic object containing models (.pkl). + output_path: Path to save the cisTopic object with the selected model (.pkl). + select_model: Manually select a specific topic number. If None, the tool uses metrics to suggest one. + """ + in_p = Path(input_path) + if not in_p.exists(): + return {"error": f"Input file not found: {input_path}"} + + out_p = Path(output_path) + out_p.parent.mkdir(parents=True, exist_ok=True) + + cmd = [ + "pycistopic", "analyze_models", + "-i", str(in_p), + "-o", str(out_p) + ] + + if select_model is not None: + cmd.extend(["-sm", str(select_model)]) + + try: + result = subprocess.run(cmd, capture_output=True, text=True, check=True) + return { + "command_executed": " ".join(cmd), + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": [str(out_p)] + } + except subprocess.CalledProcessError as e: + return { + "command_executed": " ".join(cmd), + "error": str(e), + "stdout": e.stdout, + "stderr": e.stderr + } + +@mcp.tool() +def pycistopic_get_dar( + input_path: str, + output_path: str, + group_by: str, + contrast_type: str = "one_vs_rest", + adj_pval_threshold: float = 0.05, + log2fc_threshold: float = 1.0, +): + """ + Find Differentially Accessible Regions (DARs) between cell groups. + + Args: + input_path: Path to the cisTopic object (.pkl). + output_path: Path to save the DAR results (.pkl or .csv). + group_by: Metadata column to group cells by (e.g., 'cell_type'). + contrast_type: Type of contrast to perform ('one_vs_rest' or 'pairwise'). + adj_pval_threshold: Adjusted p-value threshold for significance (default: 0.05). + log2fc_threshold: Log2 Fold Change threshold (default: 1.0). + """ + in_p = Path(input_path) + if not in_p.exists(): + return {"error": f"Input file not found: {input_path}"} + + out_p = Path(output_path) + out_p.parent.mkdir(parents=True, exist_ok=True) + + cmd = [ + "pycistopic", "get_dar", + "-i", str(in_p), + "-o", str(out_p), + "-g", group_by, + "-ct", contrast_type, + "-p", str(adj_pval_threshold), + "-l", str(log2fc_threshold) + ] + + try: + result = subprocess.run(cmd, capture_output=True, text=True, check=True) + return { + "command_executed": " ".join(cmd), + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": [str(out_p)] + } + except subprocess.CalledProcessError as e: + return { + "command_executed": " ".join(cmd), + "error": str(e), + "stdout": e.stdout, + "stderr": e.stderr + } + +@mcp.tool() +def pycistopic_binarize_topics( + input_path: str, + output_path: str, + method: str = "otsu", + threshold: float = 0.0, +): + """ + Binarize the topic-region matrix. + + Args: + input_path: Path to the cisTopic object (.pkl). + output_path: Path to save the binarized results (.pkl). + method: Binarization method ('otsu', 'std', or 'threshold'). + threshold: Threshold value if method is 'threshold' (default: 0.0). + """ + in_p = Path(input_path) + if not in_p.exists(): + return {"error": f"Input file not found: {input_path}"} + + out_p = Path(output_path) + out_p.parent.mkdir(parents=True, exist_ok=True) + + cmd = [ + "pycistopic", "binarize_topics", + "-i", str(in_p), + "-o", str(out_p), + "-m", method, + "-t", str(threshold) + ] + + try: + result = subprocess.run(cmd, capture_output=True, text=True, check=True) + return { + "command_executed": " ".join(cmd), + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": [str(out_p)] + } + except subprocess.CalledProcessError as e: + return { + "command_executed": " ".join(cmd), + "error": str(e), + "stdout": e.stdout, + "stderr": e.stderr + } + +@mcp.tool() +def pycistopic_impute_accessibility( + input_path: str, + output_path: str, + scale_factor: int = 10000, +): + """ + Compute imputed accessibility from the LDA model. + + Args: + input_path: Path to the cisTopic object (.pkl). + output_path: Path to save the imputed accessibility matrix (.pkl). + scale_factor: Scaling factor for imputation (default: 10000). + """ + in_p = Path(input_path) + if not in_p.exists(): + return {"error": f"Input file not found: {input_path}"} + + out_p = Path(output_path) + out_p.parent.mkdir(parents=True, exist_ok=True) + + cmd = [ + "pycistopic", "impute_accessibility", + "-i", str(in_p), + "-o", str(out_p), + "-s", str(scale_factor) + ] + + try: + result = subprocess.run(cmd, capture_output=True, text=True, check=True) + return { + "command_executed": " ".join(cmd), + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": [str(out_p)] + } + except subprocess.CalledProcessError as e: + return { + "command_executed": " ".join(cmd), + "error": str(e), + "stdout": e.stdout, + "stderr": e.stderr + } + +@mcp.tool() +def pycistopic_get_markers( + input_path: str, + output_path: str, + group_by: str, + method: str = "wilcoxon", +): + """ + Identify marker regions for specific cell groups. + + Args: + input_path: Path to the cisTopic object (.pkl). + output_path: Path to save the marker results (.pkl or .csv). + group_by: Metadata column to group cells by. + method: Statistical test to use ('wilcoxon' or 't-test'). + """ + in_p = Path(input_path) + if not in_p.exists(): + return {"error": f"Input file not found: {input_path}"} + + out_p = Path(output_path) + out_p.parent.mkdir(parents=True, exist_ok=True) + + cmd = [ + "pycistopic", "get_markers", + "-i", str(in_p), + "-o", str(out_p), + "-g", group_by, + "-m", method + ] + + try: + result = subprocess.run(cmd, capture_output=True, text=True, check=True) + return { + "command_executed": " ".join(cmd), + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": [str(out_p)] + } + except subprocess.CalledProcessError as e: + return { + "command_executed": " ".join(cmd), + "error": str(e), + "stdout": e.stdout, + "stderr": e.stderr + } \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_pycistopic/app/pycistopic_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_pycistopic/app/pycistopic_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..6a9514503d941e3f8208dc1ee272eab75a386c81 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_pycistopic/app/pycistopic_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_pycistopic/app/pycistopic_server.py') +SERVER_NAME = 'biosci_pycistopic' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_pycistopic/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_pycistopic/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..6644b0ff37e9b251f7157e45c43150644fe8a6ba --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_pycistopic/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-pycistopic: + build: . + image: mcp-pycistopic:latest + container_name: mcp-pycistopic + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=pycistopic + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_pycistopic/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_pycistopic/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..6285d45abce74c8790fdb0ce3ed8e979a3989ec6 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_pycistopic/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - pycistopic + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_pycistopic/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_pycistopic/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_pycistopic/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-scpred/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-scpred/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..130cc046b9b4ba419e8625b3dbab709542e2bd0a --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-scpred/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install r-scpred via conda (e.g., from bioconda) +RUN conda install -c bioconda r-scpred -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY r-scpred_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/r-scpred_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/r-scpred_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-scpred/app/r-scpred_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-scpred/app/r-scpred_server.py new file mode 100644 index 0000000000000000000000000000000000000000..e649a395e80a30ce8d66778dd5f03971d38e18ad --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-scpred/app/r-scpred_server.py @@ -0,0 +1,290 @@ +import subprocess +import logging +from pathlib import Path +from typing import Optional, List + +# MCP decorator stub. In a real environment, this would be imported. +class mcp: + @staticmethod + def tool(): + def decorator(f): + return f + return decorator + +# Set up logging +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + +@mcp.tool() +def scpred_train( + train_data: Path, + cell_type_col: str, + output_model: Path, + n_features: int = 30, + model: str = "svmRadial", + allow_parallel: bool = False, + seed: Optional[int] = None, +) -> dict: + """ + Trains an scpred cell type classification model. + + This function wraps the training process of scpred, which involves feature selection + from principal components and training a specified classification model. + + Args: + train_data: Path to the training data (e.g., a Seurat object in .rds format). + cell_type_col: The name of the metadata column containing the cell type labels. + output_model: Path to save the trained scpred model object (.rds format). + n_features: The number of principal components to use for feature selection. + model: The classification model to use (e.g., 'svmRadial', 'glmnet', 'ranger'). + allow_parallel: If True, enables parallel processing for model training. + seed: An optional integer for setting the random seed for reproducibility. + + Returns: + A dictionary containing the execution command, stdout, stderr, and output file path. + """ + # --- Input Validation --- + if not train_data.exists(): + raise FileNotFoundError(f"Training data not found at: {train_data}") + if n_features <= 0: + raise ValueError("n_features must be a positive integer.") + if not cell_type_col: + raise ValueError("cell_type_col must be a non-empty string.") + + # Ensure output directory exists + output_model.parent.mkdir(parents=True, exist_ok=True) + + # --- Command Construction --- + # Based on a hypothetical scpred-cli.R script that wraps the R package functions. + cmd = [ + "Rscript", "scpred-cli.R", "train", + "--train-data", str(train_data), + "--cell-type-col", cell_type_col, + "--output-model", str(output_model), + "--n-features", str(n_features), + "--model", model, + ] + + if allow_parallel: + cmd.append("--allow-parallel") + if seed is not None: + cmd.extend(["--seed", str(seed)]) + + command_executed = " ".join(cmd) + logger.info(f"Executing command: {command_executed}") + + # --- Subprocess Execution --- + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + encoding='utf-8' + ) + stdout = result.stdout + stderr = result.stderr + output_files = [str(output_model)] if output_model.exists() else [] + + except FileNotFoundError: + logger.error("Rscript or scpred-cli.R not found. Ensure R and the scpred wrapper script are in your PATH.") + raise + except subprocess.CalledProcessError as e: + logger.error(f"scpred training failed with exit code {e.returncode}") + logger.error(f"STDOUT: {e.stdout}") + logger.error(f"STDERR: {e.stderr}") + raise e + + # --- Structured Result Return --- + return { + "command_executed": command_executed, + "stdout": stdout, + "stderr": stderr, + "output_files": output_files, + } + +@mcp.tool() +def scpred_predict( + model_file: Path, + test_data: Path, + output_rds: Path, + threshold: float = 0.9, + output_csv: Optional[Path] = None, +) -> dict: + """ + Predicts cell types in a new dataset using a trained scpred model. + + This function applies a pre-trained scpred model to a new single-cell dataset + to classify each cell. + + Args: + model_file: Path to the trained scpred model object (.rds format). + test_data: Path to the test data to be classified (e.g., a Seurat object in .rds format). + output_rds: Path to save the test data object with prediction results added (.rds format). + threshold: The minimum probability score required to assign a cell to a class. + output_csv: Optional path to save a CSV file with cell predictions. + + Returns: + A dictionary containing the execution command, stdout, stderr, and output file paths. + """ + # --- Input Validation --- + if not model_file.exists(): + raise FileNotFoundError(f"Model file not found at: {model_file}") + if not test_data.exists(): + raise FileNotFoundError(f"Test data not found at: {test_data}") + if not (0.0 <= threshold <= 1.0): + raise ValueError("threshold must be between 0.0 and 1.0.") + + # Ensure output directories exist + output_rds.parent.mkdir(parents=True, exist_ok=True) + if output_csv: + output_csv.parent.mkdir(parents=True, exist_ok=True) + + # --- Command Construction --- + cmd = [ + "Rscript", "scpred-cli.R", "predict", + "--model-file", str(model_file), + "--test-data", str(test_data), + "--output-rds", str(output_rds), + "--threshold", str(threshold), + ] + + if output_csv: + cmd.extend(["--output-csv", str(output_csv)]) + + command_executed = " ".join(cmd) + logger.info(f"Executing command: {command_executed}") + + # --- Subprocess Execution --- + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + encoding='utf-8' + ) + stdout = result.stdout + stderr = result.stderr + + output_files = [] + if output_rds.exists(): + output_files.append(str(output_rds)) + if output_csv and output_csv.exists(): + output_files.append(str(output_csv)) + + except FileNotFoundError: + logger.error("Rscript or scpred-cli.R not found. Ensure R and the scpred wrapper script are in your PATH.") + raise + except subprocess.CalledProcessError as e: + logger.error(f"scpred prediction failed with exit code {e.returncode}") + logger.error(f"STDOUT: {e.stdout}") + logger.error(f"STDERR: {e.stderr}") + raise e + + # --- Structured Result Return --- + return { + "command_executed": command_executed, + "stdout": stdout, + "stderr": stderr, + "output_files": output_files, + } + +@mcp.tool() +def scpred_cv( + train_data: Path, + cell_type_col: str, + output_prefix: str, + n_folds: int = 10, + n_repeats: int = 10, + n_features: int = 30, + model: str = "svmRadial", + allow_parallel: bool = False, + seed: Optional[int] = None, +) -> dict: + """ + Performs cross-validation for an scpred model on a training dataset. + + This function evaluates model performance using k-fold cross-validation, which can help + in tuning parameters like the number of features. + + Args: + train_data: Path to the training data (e.g., a Seurat object in .rds format). + cell_type_col: The name of the metadata column containing the cell type labels. + output_prefix: A prefix for output files (e.g., plots, summary tables). + n_folds: The number of folds for cross-validation. + n_repeats: The number of times to repeat the cross-validation. + n_features: The number of principal components to use for feature selection. + model: The classification model to use (e.g., 'svmRadial', 'glmnet', 'ranger'). + allow_parallel: If True, enables parallel processing. + seed: An optional integer for setting the random seed for reproducibility. + + Returns: + A dictionary containing the execution command, stdout, and stderr. + Output files are not explicitly listed as they depend on the script's implementation. + """ + # --- Input Validation --- + if not train_data.exists(): + raise FileNotFoundError(f"Training data not found at: {train_data}") + if n_folds <= 1: + raise ValueError("n_folds must be greater than 1.") + if n_repeats <= 0: + raise ValueError("n_repeats must be a positive integer.") + if n_features <= 0: + raise ValueError("n_features must be a positive integer.") + if not cell_type_col: + raise ValueError("cell_type_col must be a non-empty string.") + if not output_prefix: + raise ValueError("output_prefix must be a non-empty string.") + + # --- Command Construction --- + cmd = [ + "Rscript", "scpred-cli.R", "cv", + "--train-data", str(train_data), + "--cell-type-col", cell_type_col, + "--output-prefix", output_prefix, + "--n-folds", str(n_folds), + "--n-repeats", str(n_repeats), + "--n-features", str(n_features), + "--model", model, + ] + + if allow_parallel: + cmd.append("--allow-parallel") + if seed is not None: + cmd.extend(["--seed", str(seed)]) + + command_executed = " ".join(cmd) + logger.info(f"Executing command: {command_executed}") + + # --- Subprocess Execution --- + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + encoding='utf-8' + ) + stdout = result.stdout + stderr = result.stderr + # Note: The exact output files are unknown and depend on the R script. + # The user should know what files are generated based on the output_prefix. + output_files = [] + + except FileNotFoundError: + logger.error("Rscript or scpred-cli.R not found. Ensure R and the scpred wrapper script are in your PATH.") + raise + except subprocess.CalledProcessError as e: + logger.error(f"scpred cross-validation failed with exit code {e.returncode}") + logger.error(f"STDOUT: {e.stdout}") + logger.error(f"STDERR: {e.stderr}") + raise e + + # --- Structured Result Return --- + return { + "command_executed": command_executed, + "stdout": stdout, + "stderr": stderr, + "output_files": output_files, + } \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-scpred/app/r-scpred_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-scpred/app/r-scpred_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..3faf96e236a54360aa027dcf4617f465bdbdfb6d --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-scpred/app/r-scpred_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-scpred/app/r-scpred_server.py') +SERVER_NAME = 'biosci_r_scpred' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-scpred/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-scpred/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..ddf0527d367f6c800597d2fb4e6dde82c668d966 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-scpred/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-r-scpred: + build: . + image: mcp-r-scpred:latest + container_name: mcp-r-scpred + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=r-scpred + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-scpred/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-scpred/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..b6eb1b829c2a4959b7abb8f5cf0548248ffcfc6c --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-scpred/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - r-scpred + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-scpred/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-scpred/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-scpred/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-seurat-scripts/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-seurat-scripts/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..0eb7efcf3eb48163d4122751f572f3c1cd91b8d7 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-seurat-scripts/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install r-seurat-scripts via conda (e.g., from bioconda) +RUN conda install -c bioconda r-seurat-scripts -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY r-seurat-scripts_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/r-seurat-scripts_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/r-seurat-scripts_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-seurat-scripts/app/r-seurat-scripts_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-seurat-scripts/app/r-seurat-scripts_server.py new file mode 100644 index 0000000000000000000000000000000000000000..0760c43cc11c37e64fbdd1f714658759bd857673 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-seurat-scripts/app/r-seurat-scripts_server.py @@ -0,0 +1,131 @@ +import subprocess +import logging +from pathlib import Path +from typing import Optional, List, Dict + +# Configure logging +logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') + +@mcp.tool() +def rscript_run( + script_file: Optional[Path] = None, + expressions: Optional[List[str]] = None, + script_args: Optional[List[str]] = None, + verbose: bool = False, + default_packages: Optional[str] = None, + save: bool = False, + no_environ: bool = False, + no_site_file: bool = False, + no_init_file: bool = False, + restore: bool = False, + vanilla: bool = False, +) -> Dict: + """ + Executes an R script or R expressions using the Rscript command-line tool. + + This tool serves as a wrapper for Rscript, commonly used for running bioinformatics + scripts, such as those using the Seurat package. You must provide either a script + file to execute or a list of R expressions. + + Args: + script_file (Optional[Path]): Path to the R script file to be executed. Mutually exclusive with 'expressions'. + expressions (Optional[List[str]]): A list of R expressions to execute using the '-e' flag. Mutually exclusive with 'script_file'. + script_args (Optional[List[str]]): A list of arguments to be passed to the R script itself. + verbose (bool): If True, print information on progress (--verbose). Defaults to False. + default_packages (Optional[str]): A comma-separated list of package names to be loaded by default (--default-packages). + save (bool): If True, save the workspace at the end of the session (--save). Ignored if 'vanilla' is True. Defaults to False. + no_environ (bool): If True, do not read the site and user environment files (--no-environ). Ignored if 'vanilla' is True. Defaults to False. + no_site_file (bool): If True, do not read the site-wide Rprofile (--no-site-file). Ignored if 'vanilla' is True. Defaults to False. + no_init_file (bool): If True, do not read the user R profile (--no-init-file). Ignored if 'vanilla' is True. Defaults to False. + restore (bool): If True, restore previously saved objects at startup (--restore). Ignored if 'vanilla' is True. Defaults to False. + vanilla (bool): If True, combines --no-save, --no-restore, --no-site-file, --no-init-file, and --no-environ. Defaults to False. + + Returns: + Dict: A dictionary containing the executed command, stdout, stderr, and a list of potential output files. + """ + # 1. Input Validation + if script_file and expressions: + raise ValueError("Cannot provide both 'script_file' and 'expressions'. They are mutually exclusive.") + if not script_file and not expressions: + raise ValueError("Must provide either 'script_file' or 'expressions' to execute.") + + if script_file: + if not script_file.is_file(): + raise FileNotFoundError(f"The specified script file does not exist: {script_file}") + + # 2. Command Construction + command = ["Rscript"] + + if vanilla: + command.append("--vanilla") + else: + # These options are combined in --vanilla, so we only process them if vanilla is false. + if save: + command.append("--save") + if no_environ: + command.append("--no-environ") + if no_site_file: + command.append("--no-site-file") + if no_init_file: + command.append("--no-init-file") + if restore: + command.append("--restore") + + if verbose: + command.append("--verbose") + + if default_packages: + command.append(f"--default-packages={default_packages}") + + if expressions: + for expr in expressions: + command.extend(["-e", expr]) + elif script_file: + command.append(str(script_file)) + + if script_args: + command.extend(script_args) + + # 3. Subprocess Execution + command_str = " ".join(command) + logging.info(f"Executing command: {command_str}") + + try: + result = subprocess.run( + command, + capture_output=True, + text=True, + check=True + ) + stdout = result.stdout + stderr = result.stderr + logging.info("Rscript execution completed successfully.") + + except FileNotFoundError: + error_msg = "Rscript command not found. Please ensure R is installed and in your system's PATH." + logging.error(error_msg) + return { + "command_executed": command_str, + "stdout": "", + "stderr": error_msg, + "output_files": [] + } + except subprocess.CalledProcessError as e: + logging.error(f"Rscript execution failed with exit code {e.returncode}.") + logging.error(f"Stderr: {e.stderr}") + return { + "command_executed": command_str, + "stdout": e.stdout, + "stderr": e.stderr, + "output_files": [] + } + + # 4. Structured Result Return + # Rscript itself doesn't define output files; the script it runs does. + # We return an empty list, as we can't reliably determine what files the script might create. + return { + "command_executed": command_str, + "stdout": stdout, + "stderr": stderr, + "output_files": [] + } \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-seurat-scripts/app/r-seurat-scripts_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-seurat-scripts/app/r-seurat-scripts_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..55686706f3b1389e8dfc40b0ef6da0419f3f0078 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-seurat-scripts/app/r-seurat-scripts_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-seurat-scripts/app/r-seurat-scripts_server.py') +SERVER_NAME = 'biosci_r_seurat_scripts' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-seurat-scripts/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-seurat-scripts/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..c7e41432b1df433fcc2bdb0aa9cff82423355741 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-seurat-scripts/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-r-seurat-scripts: + build: . + image: mcp-r-seurat-scripts:latest + container_name: mcp-r-seurat-scripts + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=r-seurat-scripts + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-seurat-scripts/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-seurat-scripts/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..074b0cc004c9bd5ed9623010a5ba0315729c1e90 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-seurat-scripts/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - r-seurat-scripts + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-seurat-scripts/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-seurat-scripts/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-seurat-scripts/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_samtools/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_samtools/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..c3466c3e1924a54976d282de13c5f020d8406c5b --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_samtools/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install samtools via conda (e.g., from bioconda) +RUN conda install -c bioconda samtools -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY app/samtools_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/samtools_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/samtools_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_samtools/app/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_samtools/app/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_samtools/app/requirements.txt @@ -0,0 +1 @@ + diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_samtools/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_samtools/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_samtools/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scarches/app/scarches_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scarches/app/scarches_server.py new file mode 100644 index 0000000000000000000000000000000000000000..9432554de05dc27efb94d65dd298a412917dd6b7 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scarches/app/scarches_server.py @@ -0,0 +1,353 @@ +import subprocess +import logging +from pathlib import Path +from typing import List, Dict, Any, Optional + +# Configure logging +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + +# MCP decorator is not defined here, but the functions are structured +# as if it were present (e.g., @mcp.tool()). + +def _run_scarches_command(cmd: List[str], output_path: Path) -> Dict[str, Any]: + """ + A helper function to execute scarches commands, handle errors, and + return a structured output. + """ + command_str = " ".join(cmd) + logger.info(f"Executing command: {command_str}") + try: + result = subprocess.run( + cmd, + check=True, + capture_output=True, + text=True, + ) + return { + "command_executed": command_str, + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": [str(output_path)] if output_path.exists() else [], + } + except FileNotFoundError: + logger.error("Error: 'python' executable not found. Make sure Python is in your PATH.") + raise + except subprocess.CalledProcessError as e: + logger.error(f"Command failed with exit code {e.returncode}") + logger.error(f"Stdout: {e.stdout}") + logger.error(f"Stderr: {e.stderr}") + raise e + +# @mcp.tool() +def train_scvi( + adata_path: Path, + model_path: Path, + gpus: str = "0", + n_epochs: int = 400, + learning_rate: float = 1e-3, + batch_size: int = 128, + early_stopping: bool = False, +) -> Dict[str, Any]: + """ + Trains a scVI model using the scarches command-line interface. + + Args: + adata_path: Path to anndata object with raw counts. + model_path: Path where the trained model will be saved. + gpus: String specifying which GPUs to use (e.g., '0,1'). + n_epochs: Number of epochs for training. + learning_rate: Learning rate for training. + batch_size: Batch size for training. + early_stopping: If True, enables early stopping. + + Returns: + A dictionary containing the command executed, stdout, stderr, and output file path. + """ + if not adata_path.is_file(): + raise FileNotFoundError(f"Input anndata file not found: {adata_path}") + if not model_path.parent.exists(): + model_path.parent.mkdir(parents=True, exist_ok=True) + logger.info(f"Created output directory: {model_path.parent}") + if n_epochs <= 0: + raise ValueError("n_epochs must be a positive integer.") + if batch_size <= 0: + raise ValueError("batch_size must be a positive integer.") + + cmd = [ + "python", "-m", "scarches", "train-scvi", + str(adata_path), + str(model_path), + "--gpus", gpus, + "--n_epochs", str(n_epochs), + "--learning_rate", str(learning_rate), + "--batch_size", str(batch_size), + ] + if early_stopping: + cmd.append("--early_stopping") + + return _run_scarches_command(cmd, model_path) + +# @mcp.tool() +def train_scanvi( + adata_path: Path, + model_path: Path, + labels_key: str, + unlabeled_category: str, + gpus: str = "0", + n_epochs_unsupervised: int = 400, + n_epochs_semisupervised: int = 400, + lr_unsupervised: float = 1e-3, + lr_semisupervised: float = 1e-3, + batch_size: int = 128, + early_stopping: bool = False, +) -> Dict[str, Any]: + """ + Trains a scANVI model using the scarches command-line interface. + + Args: + adata_path: Path to anndata object with raw counts. + model_path: Path where the trained model will be saved. + labels_key: Key in adata.obs for cell type labels. + unlabeled_category: Value in adata.obs[labels_key] for unlabeled cells. + gpus: String specifying which GPUs to use (e.g., '0,1'). + n_epochs_unsupervised: Number of epochs for unsupervised training. + n_epochs_semisupervised: Number of epochs for semi-supervised training. + lr_unsupervised: Learning rate for unsupervised training. + lr_semisupervised: Learning rate for semi-supervised training. + batch_size: Batch size for training. + early_stopping: If True, enables early stopping. + + Returns: + A dictionary containing the command executed, stdout, stderr, and output file path. + """ + if not adata_path.is_file(): + raise FileNotFoundError(f"Input anndata file not found: {adata_path}") + if not model_path.parent.exists(): + model_path.parent.mkdir(parents=True, exist_ok=True) + logger.info(f"Created output directory: {model_path.parent}") + + cmd = [ + "python", "-m", "scarches", "train-scanvi", + str(adata_path), + str(model_path), + "--labels_key", labels_key, + "--unlabeled_category", unlabeled_category, + "--gpus", gpus, + "--n_epochs_unsupervised", str(n_epochs_unsupervised), + "--n_epochs_semisupervised", str(n_epochs_semisupervised), + "--lr_unsupervised", str(lr_unsupervised), + "--lr_semisupervised", str(lr_semisupervised), + "--batch_size", str(batch_size), + ] + if early_stopping: + cmd.append("--early_stopping") + + return _run_scarches_command(cmd, model_path) + +# @mcp.tool() +def train_trvae( + adata_path: Path, + model_path: Path, + condition_key: str, + gpus: str = "0", + n_epochs: int = 400, + learning_rate: float = 1e-3, + batch_size: int = 128, + early_stopping: bool = False, +) -> Dict[str, Any]: + """ + Trains a trVAE model using the scarches command-line interface. + + Args: + adata_path: Path to anndata object with raw counts. + model_path: Path where the trained model will be saved. + condition_key: Key in adata.obs for batch information. + gpus: String specifying which GPUs to use (e.g., '0,1'). + n_epochs: Number of epochs for training. + learning_rate: Learning rate for training. + batch_size: Batch size for training. + early_stopping: If True, enables early stopping. + + Returns: + A dictionary containing the command executed, stdout, stderr, and output file path. + """ + if not adata_path.is_file(): + raise FileNotFoundError(f"Input anndata file not found: {adata_path}") + if not model_path.parent.exists(): + model_path.parent.mkdir(parents=True, exist_ok=True) + logger.info(f"Created output directory: {model_path.parent}") + + cmd = [ + "python", "-m", "scarches", "train-trvae", + str(adata_path), + str(model_path), + "--condition_key", condition_key, + "--gpus", gpus, + "--n_epochs", str(n_epochs), + "--learning_rate", str(learning_rate), + "--batch_size", str(batch_size), + ] + if early_stopping: + cmd.append("--early_stopping") + + return _run_scarches_command(cmd, model_path) + +# @mcp.tool() +def query_scvi( + adata_path: Path, + ref_model_path: Path, + new_model_path: Path, + gpus: str = "0", + n_epochs: int = 200, + learning_rate: float = 1e-3, + batch_size: int = 128, + early_stopping: bool = False, +) -> Dict[str, Any]: + """ + Maps a query dataset to a reference scVI model. + + Args: + adata_path: Path to query anndata object with raw counts. + ref_model_path: Path to the reference model. + new_model_path: Path where the updated query model will be saved. + gpus: String specifying which GPUs to use (e.g., '0,1'). + n_epochs: Number of epochs for training. + learning_rate: Learning rate for training. + batch_size: Batch size for training. + early_stopping: If True, enables early stopping. + + Returns: + A dictionary containing the command executed, stdout, stderr, and output file path. + """ + if not adata_path.is_file(): + raise FileNotFoundError(f"Input query anndata file not found: {adata_path}") + if not ref_model_path.is_dir(): + raise FileNotFoundError(f"Reference model directory not found: {ref_model_path}") + if not new_model_path.parent.exists(): + new_model_path.parent.mkdir(parents=True, exist_ok=True) + logger.info(f"Created output directory: {new_model_path.parent}") + + cmd = [ + "python", "-m", "scarches", "query-scvi", + str(adata_path), + str(ref_model_path), + str(new_model_path), + "--gpus", gpus, + "--n_epochs", str(n_epochs), + "--learning_rate", str(learning_rate), + "--batch_size", str(batch_size), + ] + if early_stopping: + cmd.append("--early_stopping") + + return _run_scarches_command(cmd, new_model_path) + +# @mcp.tool() +def query_scanvi( + adata_path: Path, + ref_model_path: Path, + new_model_path: Path, + gpus: str = "0", + n_epochs_unsupervised: int = 200, + n_epochs_semisupervised: int = 100, + lr_unsupervised: float = 1e-3, + lr_semisupervised: float = 1e-3, + batch_size: int = 128, + early_stopping: bool = False, +) -> Dict[str, Any]: + """ + Maps a query dataset to a reference scANVI model. + + Args: + adata_path: Path to query anndata object with raw counts. + ref_model_path: Path to the reference model. + new_model_path: Path where the updated query model will be saved. + gpus: String specifying which GPUs to use (e.g., '0,1'). + n_epochs_unsupervised: Number of epochs for unsupervised training. + n_epochs_semisupervised: Number of epochs for semi-supervised training. + lr_unsupervised: Learning rate for unsupervised training. + lr_semisupervised: Learning rate for semi-supervised training. + batch_size: Batch size for training. + early_stopping: If True, enables early stopping. + + Returns: + A dictionary containing the command executed, stdout, stderr, and output file path. + """ + if not adata_path.is_file(): + raise FileNotFoundError(f"Input query anndata file not found: {adata_path}") + if not ref_model_path.is_dir(): + raise FileNotFoundError(f"Reference model directory not found: {ref_model_path}") + if not new_model_path.parent.exists(): + new_model_path.parent.mkdir(parents=True, exist_ok=True) + logger.info(f"Created output directory: {new_model_path.parent}") + + cmd = [ + "python", "-m", "scarches", "query-scanvi", + str(adata_path), + str(ref_model_path), + str(new_model_path), + "--gpus", gpus, + "--n_epochs_unsupervised", str(n_epochs_unsupervised), + "--n_epochs_semisupervised", str(n_epochs_semisupervised), + "--lr_unsupervised", str(lr_unsupervised), + "--lr_semisupervised", str(lr_semisupervised), + "--batch_size", str(batch_size), + ] + if early_stopping: + cmd.append("--early_stopping") + + return _run_scarches_command(cmd, new_model_path) + +# @mcp.tool() +def query_trvae( + adata_path: Path, + ref_model_path: Path, + new_model_path: Path, + condition_key: str, + gpus: str = "0", + n_epochs: int = 200, + learning_rate: float = 1e-3, + batch_size: int = 128, + early_stopping: bool = False, +) -> Dict[str, Any]: + """ + Maps a query dataset to a reference trVAE model. + + Args: + adata_path: Path to query anndata object with raw counts. + ref_model_path: Path to the reference model. + new_model_path: Path where the updated query model will be saved. + condition_key: Key in adata.obs for batch information. + gpus: String specifying which GPUs to use (e.g., '0,1'). + n_epochs: Number of epochs for training. + learning_rate: Learning rate for training. + batch_size: Batch size for training. + early_stopping: If True, enables early stopping. + + Returns: + A dictionary containing the command executed, stdout, stderr, and output file path. + """ + if not adata_path.is_file(): + raise FileNotFoundError(f"Input query anndata file not found: {adata_path}") + if not ref_model_path.is_dir(): + raise FileNotFoundError(f"Reference model directory not found: {ref_model_path}") + if not new_model_path.parent.exists(): + new_model_path.parent.mkdir(parents=True, exist_ok=True) + logger.info(f"Created output directory: {new_model_path.parent}") + + cmd = [ + "python", "-m", "scarches", "query-trvae", + str(adata_path), + str(ref_model_path), + str(new_model_path), + "--condition_key", condition_key, + "--gpus", gpus, + "--n_epochs", str(n_epochs), + "--learning_rate", str(learning_rate), + "--batch_size", str(batch_size), + ] + if early_stopping: + cmd.append("--early_stopping") + + return _run_scarches_command(cmd, new_model_path) \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scarches/app/scarches_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scarches/app/scarches_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..15c24506b610f5f7a23c7e5cbef9cad99cc59586 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scarches/app/scarches_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scarches/app/scarches_server.py') +SERVER_NAME = 'biosci_scarches' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scarches/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scarches/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..36515829bd5c93102752c1a043532a508bcab763 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scarches/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-scarches: + build: . + image: mcp-scarches:latest + container_name: mcp-scarches + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=scarches + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scarches/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scarches/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..7ae141f0d6db963f6b50ae1249b206c468ca6d98 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scarches/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - scarches + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scarches/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scarches/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scarches/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_sccaf/app/sccaf_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_sccaf/app/sccaf_server.py new file mode 100644 index 0000000000000000000000000000000000000000..2f94928d2f15dd4fd616951b38021a43b761ab0d --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_sccaf/app/sccaf_server.py @@ -0,0 +1,180 @@ +import subprocess +from pathlib import Path +from typing import Optional, List, Dict, Any + +# MCP decorator placeholder. In a real MCP environment, this would be imported. +class mcp: + @staticmethod + def tool(func): + return func + +@mcp.tool +def sccaf( + input_adata: Path, + output_adata: Path, + self_project: bool = False, + min_acc: float = 0.9, + prefix: str = 'sccaf', + n_jobs: int = 1, + use_rep: str = 'X_pca', + n_features: int = 2000, + n_components: int = 50, + resolution: float = 0.2, + k: int = 15, + reference: Optional[Path] = None, + reference_leiden: str = 'leiden', + reference_cell_type: str = 'cell_type', + reference_embedding: str = 'X_umap', + reference_n_jobs: int = 1, + reference_n_features: int = 2000, + reference_n_components: int = 50, + reference_resolution: float = 0.2, + reference_k: int = 15, + log_file: Optional[Path] = None, + verbose: int = 1, +) -> Dict[str, Any]: + """ + Runs SCCAF (Single-Cell Clustering Assessment Framework) for clustering and cell type identification. + + SCCAF is a tool for automated cell type identification and clustering refinement based on the + self-projection of a dataset. It can also project a query dataset onto a reference. + + Args: + input_adata: Path to the input AnnData object (.h5ad). + output_adata: Path where the output AnnData object (.h5ad) will be saved. + self_project: If True, run in self-projection mode. + min_acc: Minimum accuracy for self-projection. + prefix: Prefix for the column names for the results in the output AnnData. + n_jobs: Number of jobs to run in parallel. + use_rep: The key in `.obsm` for the embedding to use (e.g., 'X_pca'). + n_features: Number of features to use. + n_components: Number of components to use. + resolution: Resolution for Louvain clustering. + k: Number of nearest neighbors. + reference: Path to the reference AnnData object for projection. + reference_leiden: The key in `.obs` for the reference leiden clusters. + reference_cell_type: The key in `.obs` for the reference cell type annotations. + reference_embedding: The key in `.obsm` for the reference embedding. + reference_n_jobs: Number of jobs to run in parallel for the reference analysis. + reference_n_features: Number of features to use for the reference. + reference_n_components: Number of components to use for the reference. + reference_resolution: Resolution for Louvain for the reference. + reference_k: Number of nearest neighbors for the reference. + log_file: Optional path to a file for logging output. + verbose: Verbosity level (e.g., 0 for silent, 1 for info). + + Returns: + A dictionary containing the executed command, stdout, stderr, and a list of output files. + """ + # --- Input Validation --- + if not input_adata.is_file(): + raise FileNotFoundError(f"Input file not found: {input_adata}") + if reference and not reference.is_file(): + raise FileNotFoundError(f"Reference file not found: {reference}") + + # --- Output Directory Handling --- + output_adata.parent.mkdir(parents=True, exist_ok=True) + if log_file: + log_file.parent.mkdir(parents=True, exist_ok=True) + + # --- Parameter Value Validation --- + if not (0.0 <= min_acc <= 1.0): + raise ValueError("min_acc must be between 0.0 and 1.0") + if n_jobs <= 0: + raise ValueError("n_jobs must be a positive integer") + if n_features <= 0: + raise ValueError("n_features must be a positive integer") + if n_components <= 0: + raise ValueError("n_components must be a positive integer") + if resolution <= 0: + raise ValueError("resolution must be a positive float") + if k <= 0: + raise ValueError("k must be a positive integer") + if verbose < 0: + raise ValueError("verbose must be a non-negative integer") + + # --- Command Construction --- + cmd = [ + "sccaf", + "-i", str(input_adata), + "-o", str(output_adata), + "--min-acc", str(min_acc), + "--prefix", prefix, + "--n-jobs", str(n_jobs), + "--use-rep", use_rep, + "--n-features", str(n_features), + "--n-components", str(n_components), + "--resolution", str(resolution), + "--k", str(k), + "--verbose", str(verbose), + ] + + if self_project: + cmd.append("--self-project") + + if reference: + if reference_n_jobs <= 0: + raise ValueError("reference_n_jobs must be a positive integer") + if reference_n_features <= 0: + raise ValueError("reference_n_features must be a positive integer") + if reference_n_components <= 0: + raise ValueError("reference_n_components must be a positive integer") + if reference_resolution <= 0: + raise ValueError("reference_resolution must be a positive float") + if reference_k <= 0: + raise ValueError("reference_k must be a positive integer") + + cmd.extend([ + "--reference", str(reference), + "--reference-leiden", reference_leiden, + "--reference-cell-type", reference_cell_type, + "--reference-embedding", reference_embedding, + "--reference-n-jobs", str(reference_n_jobs), + "--reference-n-features", str(reference_n_features), + "--reference-n-components", str(reference_n_components), + "--reference-resolution", str(reference_resolution), + "--reference-k", str(reference_k), + ]) + + if log_file: + cmd.extend(["--log-file", str(log_file)]) + + command_executed = " ".join(cmd) + + # --- Subprocess Execution --- + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + encoding='utf-8' + ) + stdout = result.stdout + stderr = result.stderr + except FileNotFoundError: + return { + "command_executed": command_executed, + "stdout": "", + "stderr": "Error: 'sccaf' command not found. Make sure the tool is installed and in your system's PATH.", + "output_files": [] + } + except subprocess.CalledProcessError as e: + return { + "command_executed": command_executed, + "stdout": e.stdout, + "stderr": e.stderr, + "output_files": [] + } + + # --- Structured Result Return --- + output_files: List[str] = [str(output_adata)] + if log_file and log_file.exists(): + output_files.append(str(log_file)) + + return { + "command_executed": command_executed, + "stdout": stdout, + "stderr": stderr, + "output_files": output_files + } \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_sccaf/app/sccaf_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_sccaf/app/sccaf_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..e4ac6aa9a1b5e2877318bfbb31bdd605850682e9 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_sccaf/app/sccaf_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_sccaf/app/sccaf_server.py') +SERVER_NAME = 'biosci_sccaf' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_sccaf/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_sccaf/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..6068a48b1fd1b217fd92ff7a691d6ed4a3c02d61 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_sccaf/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-sccaf: + build: . + image: mcp-sccaf:latest + container_name: mcp-sccaf + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=sccaf + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scpred-cli/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scpred-cli/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..3ed31694e2abff593981c9e57f7bebf381e84db6 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scpred-cli/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install scpred-cli via conda (e.g., from bioconda) +RUN conda install -c bioconda scpred-cli -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY scpred-cli_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/scpred-cli_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/scpred-cli_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scpred-cli/app/scpred-cli_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scpred-cli/app/scpred-cli_server.py new file mode 100644 index 0000000000000000000000000000000000000000..357a0603d4e320a7b7abaed9e39a953d2bbfa4dc --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scpred-cli/app/scpred-cli_server.py @@ -0,0 +1,221 @@ +import subprocess +import logging +from pathlib import Path +from typing import Optional, List, Dict, Any + +# Configure logging +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + +# Mock mcp.tool decorator for standalone execution +class mcp: + def tool(func): + return func + +@mcp.tool +def train( + training_data: Path, + metadata: Path, + cell_type_column: str, + output_dir: Path, + model_name: str = "scPred_model", + seed: int = 66, +) -> Dict[str, Any]: + """ + Trains a scPred cell type prediction model. + + This tool corresponds to the --train functionality of scpred-cli.R. + It takes a training dataset and corresponding metadata to build and save + a scPred model. + + Args: + training_data: Path to the input training data file in .rds format. + metadata: Path to the metadata file in .tsv format. + cell_type_column: Name of the cell type column in the metadata file. + output_dir: Path to the directory where the trained model will be saved. + model_name: Name for the trained model file (without extension). + seed: An integer seed for reproducibility. + + Returns: + A dictionary containing the execution details and output file path. + """ + # --- Input Validation --- + if not training_data.is_file(): + raise FileNotFoundError(f"Training data file not found: {training_data}") + if not metadata.is_file(): + raise FileNotFoundError(f"Metadata file not found: {metadata}") + if not cell_type_column: + raise ValueError("The 'cell_type_column' parameter cannot be empty.") + if not model_name: + raise ValueError("The 'model_name' parameter cannot be empty.") + + # --- File Path Handling --- + try: + output_dir.mkdir(parents=True, exist_ok=True) + except OSError as e: + logger.error(f"Failed to create output directory {output_dir}: {e}") + raise + + # --- Command Construction --- + # Assumes scpred-cli.R is accessible in the environment. + # The command is executed via Rscript. + cmd = [ + "Rscript", "scpred-cli.R", + "--train", + "--input", str(training_data), + "--metadata", str(metadata), + "--celltype", cell_type_column, + "--output", str(output_dir), + "--name", model_name, + "--seed", str(seed), + ] + + command_executed = " ".join(cmd) + logger.info(f"Executing command: {command_executed}") + + # --- Subprocess Execution --- + try: + process = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + ) + stdout = process.stdout + stderr = process.stderr + logger.info("scPred training completed successfully.") + + except FileNotFoundError: + error_message = "Error: 'Rscript' or 'scpred-cli.R' not found. Please ensure R and scpred are installed and in your system's PATH." + logger.error(error_message) + return { + "command_executed": command_executed, + "stdout": "", + "stderr": error_message, + "output_files": [], + } + except subprocess.CalledProcessError as e: + logger.error(f"scPred training failed with exit code {e.returncode}.") + logger.error(f"Stderr: {e.stderr}") + return { + "command_executed": command_executed, + "stdout": e.stdout, + "stderr": e.stderr, + "output_files": [], + } + + # --- Structured Result Return --- + output_model_path = output_dir / f"{model_name}.rds" + output_files = [str(output_model_path)] if output_model_path.exists() else [] + + return { + "command_executed": command_executed, + "stdout": stdout, + "stderr": stderr, + "output_files": output_files, + } + + +@mcp.tool +def predict( + model: Path, + query_data: Path, + output_dir: Path, + reference_data: Optional[Path] = None, + seed: int = 66, +) -> Dict[str, Any]: + """ + Predicts cell types for a query dataset using a pre-trained scPred model. + + This tool corresponds to the --predict functionality of scpred-cli.R. + It uses a trained model to classify cells in a new query dataset. + + Args: + model: Path to a pre-trained scPred model file (.rds format). + query_data: Path to the query dataset file (.rds format). + output_dir: Path to the directory where prediction results will be saved. + reference_data: Optional path to a reference dataset (.rds format) for alignment. + seed: An integer seed for reproducibility. + + Returns: + A dictionary containing the execution details and output file paths. + """ + # --- Input Validation --- + if not model.is_file(): + raise FileNotFoundError(f"Model file not found: {model}") + if not query_data.is_file(): + raise FileNotFoundError(f"Query data file not found: {query_data}") + if reference_data and not reference_data.is_file(): + raise FileNotFoundError(f"Reference data file not found: {reference_data}") + + # --- File Path Handling --- + try: + output_dir.mkdir(parents=True, exist_ok=True) + except OSError as e: + logger.error(f"Failed to create output directory {output_dir}: {e}") + raise + + # --- Command Construction --- + cmd = [ + "Rscript", "scpred-cli.R", + "--predict", + "--model", str(model), + "--query", str(query_data), + "--output", str(output_dir), + "--seed", str(seed), + ] + + if reference_data: + cmd.extend(["--reference", str(reference_data)]) + + command_executed = " ".join(cmd) + logger.info(f"Executing command: {command_executed}") + + # --- Subprocess Execution --- + try: + process = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + ) + stdout = process.stdout + stderr = process.stderr + logger.info("scPred prediction completed successfully.") + + except FileNotFoundError: + error_message = "Error: 'Rscript' or 'scpred-cli.R' not found. Please ensure R and scpred are installed and in your system's PATH." + logger.error(error_message) + return { + "command_executed": command_executed, + "stdout": "", + "stderr": error_message, + "output_files": [], + } + except subprocess.CalledProcessError as e: + logger.error(f"scPred prediction failed with exit code {e.returncode}.") + logger.error(f"Stderr: {e.stderr}") + return { + "command_executed": command_executed, + "stdout": e.stdout, + "stderr": e.stderr, + "output_files": [], + } + + # --- Structured Result Return --- + # Based on the scpred-cli.R script, it produces these two output files. + output_rds = output_dir / "scpred_prediction.rds" + output_tsv = output_dir / "scpred_prediction_metadata.tsv" + + output_files = [] + if output_rds.exists(): + output_files.append(str(output_rds)) + if output_tsv.exists(): + output_files.append(str(output_tsv)) + + return { + "command_executed": command_executed, + "stdout": stdout, + "stderr": stderr, + "output_files": output_files, + } \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scpred-cli/app/scpred-cli_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scpred-cli/app/scpred-cli_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..c1e242a2a5fc99deb18e1f4cd54e36cced7fd4e7 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scpred-cli/app/scpred-cli_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scpred-cli/app/scpred-cli_server.py') +SERVER_NAME = 'biosci_scpred_cli' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scpred-cli/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scpred-cli/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..524bd3adbfe65916ad50ae4b52aa7afa514bc519 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scpred-cli/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-scpred-cli: + build: . + image: mcp-scpred-cli:latest + container_name: mcp-scpred-cli + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=scpred-cli + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scpred-cli/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scpred-cli/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..da5eda79832d108307282c7c4a676e663f84a821 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scpred-cli/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - scpred-cli + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scpred-cli/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scpred-cli/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scpred-cli/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_snp2cell/Dockerfile b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_snp2cell/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..c5594778177713c011b411fa0e4f36f33556cafb --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_snp2cell/Dockerfile @@ -0,0 +1,40 @@ + +FROM python:3.10-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Miniconda +RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda && rm /tmp/miniconda.sh + +# Add conda to PATH +ENV PATH="/opt/conda/bin:$PATH" + +# Install snp2cell via conda (e.g., from bioconda) +RUN conda install -c bioconda snp2cell -y && conda clean -a + +# Install Python dependencies +RUN pip install uv +RUN uv pip install --system fastmcp + +# Create app directory +WORKDIR /app + +# Copy your MCP server +COPY snp2cell_server.py /app/ + +# Create workspace and output directories +RUN mkdir -p /app/workspace /app/output + +# Make sure the server script is executable +RUN chmod +x /app/snp2cell_server.py + +# Expose port for MCP over HTTP (optional) +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)" + +# Default command runs the MCP server via stdio +CMD ["python", "/app/snp2cell_server.py"] + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_snp2cell/app/snp2cell_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_snp2cell/app/snp2cell_server.py new file mode 100644 index 0000000000000000000000000000000000000000..0c6603d50cf87050d929e771176120cf33246fec --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_snp2cell/app/snp2cell_server.py @@ -0,0 +1,534 @@ +import subprocess +import tempfile +from pathlib import Path +from typing import Optional, List + +# Mock decorator for standalone execution +class mcp: + @staticmethod + def tool(func): + return func + +@mcp.tool +def create_object( + network_file: Path, + s2c_object_file: Path, + network_format: str = "sif", +) -> dict: + """ + Create an initial SNP2CELL object holding a network. + + This can be used as an input for other sub-commands. + + Args: + network_file: Path to the network file. + s2c_object_file: Path to save the SNP2CELL object. + network_format: Format of the network file. + """ + # Input validation + if not network_file.is_file(): + raise FileNotFoundError(f"Network file not found: {network_file}") + + if network_format not in ["sif", "edgelist"]: + raise ValueError(f"Invalid network format: {network_format}. Must be 'sif' or 'edgelist'.") + + # Command construction + cmd = [ + "snp2cell", + "create-object", + "--network-format", + network_format, + str(network_file), + str(s2c_object_file), + ] + + # Subprocess execution + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + ) + return { + "command_executed": " ".join(cmd), + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": [str(s2c_object_file)], + } + except subprocess.CalledProcessError as e: + return { + "command_executed": " ".join(cmd), + "stdout": e.stdout, + "stderr": e.stderr, + "error": f"snp2cell create-object failed with exit code {e.returncode}", + "output_files": [], + } + +@mcp.tool +def create_gene2pos_mapping( + s2c_object_file: Path, + gene2pos_mapping_file: Path, + mart: str = "human", +) -> dict: + """ + Query pybiomart to obtain genomic locations for genes in the network + in the s2c object and save them to a csv file. + + Args: + s2c_object_file: Path to the SNP2CELL object file. + gene2pos_mapping_file: Path to save the gene to position mapping. + mart: Which mart to use. + """ + # Input validation + if not s2c_object_file.is_file(): + raise FileNotFoundError(f"SNP2CELL object file not found: {s2c_object_file}") + + if mart not in ["human", "mouse"]: + raise ValueError(f"Invalid mart: {mart}. Must be 'human' or 'mouse'.") + + # Command construction + cmd = [ + "snp2cell", + "create-gene2pos-mapping", + "--mart", + mart, + str(s2c_object_file), + str(gene2pos_mapping_file), + ] + + # Subprocess execution + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + ) + return { + "command_executed": " ".join(cmd), + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": [str(gene2pos_mapping_file)], + } + except subprocess.CalledProcessError as e: + return { + "command_executed": " ".join(cmd), + "stdout": e.stdout, + "stderr": e.stderr, + "error": f"snp2cell create-gene2pos-mapping failed with exit code {e.returncode}", + "output_files": [], + } + +@mcp.tool +def export_locations( + s2c_object_file: Path, + locations_file: Path, +) -> dict: + """ + Save the genomic locations of network nodes in the s2c object to a tsv file. + + Args: + s2c_object_file: Path to the SNP2CELL object file. + locations_file: Path to save the locations file. + """ + # Input validation + if not s2c_object_file.is_file(): + raise FileNotFoundError(f"SNP2CELL object file not found: {s2c_object_file}") + + # Command construction + cmd = [ + "snp2cell", + "export-locations", + str(s2c_object_file), + str(locations_file), + ] + + # Subprocess execution + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + ) + return { + "command_executed": " ".join(cmd), + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": [str(locations_file)], + } + except subprocess.CalledProcessError as e: + return { + "command_executed": " ".join(cmd), + "stdout": e.stdout, + "stderr": e.stderr, + "error": f"snp2cell export-locations failed with exit code {e.returncode}", + "output_files": [], + } + +@mcp.tool +def score_snp( + s2c_object_file: Path, + gwas_summary_stats_file: Path, + gene2pos_mapping_file: Path, + score_name: str = "snp_score", + chrom_col: str = "CHR", + pos_col: str = "POS", + snp_col: str = "SNP", + pval_col: str = "P", + z_col: Optional[str] = None, + or_col: Optional[str] = None, + beta_col: Optional[str] = None, + a1_col: Optional[str] = None, + a2_col: Optional[str] = None, + window_size: int = 250000, + n_permutations: int = 1000, + random_seed: int = 42, + n_jobs: int = 1, +) -> dict: + """ + Add fGWAS scores for network nodes based on GWAS summary statistics. + Then propagate the scores across the network and calculate statistics + based on random permutations. All calculated information will be saved + in the s2c object. + + Args: + s2c_object_file: Path to the SNP2CELL object file. + gwas_summary_stats_file: Path to the GWAS summary statistics file. + gene2pos_mapping_file: Path to the gene to position mapping file. + score_name: Name of the score. + chrom_col: Name of the chromosome column. + pos_col: Name of the position column. + snp_col: Name of the SNP ID column. + pval_col: Name of the p-value column. + z_col: Name of the z-score column. + or_col: Name of the odds ratio column. + beta_col: Name of the beta column. + a1_col: Name of the A1 allele column. + a2_col: Name of the A2 allele column. + window_size: Window size for fGWAS. + n_permutations: Number of permutations for statistics. + random_seed: Random seed for permutations. + n_jobs: Number of jobs to use for parallel processing. + """ + # Input validation + if not s2c_object_file.is_file(): + raise FileNotFoundError(f"SNP2CELL object file not found: {s2c_object_file}") + if not gwas_summary_stats_file.is_file(): + raise FileNotFoundError(f"GWAS summary stats file not found: {gwas_summary_stats_file}") + if not gene2pos_mapping_file.is_file(): + raise FileNotFoundError(f"Gene to position mapping file not found: {gene2pos_mapping_file}") + + # Command construction + cmd = [ + "snp2cell", "score-snp", + "--score-name", score_name, + "--chrom-col", chrom_col, + "--pos-col", pos_col, + "--snp-col", snp_col, + "--pval-col", pval_col, + "--window-size", str(window_size), + "--n-permutations", str(n_permutations), + "--random-seed", str(random_seed), + "--n-jobs", str(n_jobs), + ] + if z_col: + cmd.extend(["--z-col", z_col]) + if or_col: + cmd.extend(["--or-col", or_col]) + if beta_col: + cmd.extend(["--beta-col", beta_col]) + if a1_col: + cmd.extend(["--a1-col", a1_col]) + if a2_col: + cmd.extend(["--a2-col", a2_col]) + + cmd.extend([ + str(s2c_object_file), + str(gwas_summary_stats_file), + str(gene2pos_mapping_file), + ]) + + # Subprocess execution + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + ) + return { + "command_executed": " ".join(cmd), + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": [str(s2c_object_file)], + } + except subprocess.CalledProcessError as e: + return { + "command_executed": " ".join(cmd), + "stdout": e.stdout, + "stderr": e.stderr, + "error": f"snp2cell score-snp failed with exit code {e.returncode}", + "output_files": [], + } + +@mcp.tool +def add_score( + s2c_object_file: Path, + scores_file: Path, + score_name: str = "score", + n_permutations: int = 1000, + random_seed: int = 42, + n_jobs: int = 1, +) -> dict: + """ + Add scores for network nodes to the s2c object and propagate the scores + across the network. + + Args: + s2c_object_file: Path to the SNP2CELL object file. + scores_file: Path to the scores file. + score_name: Name of the score. + n_permutations: Number of permutations for statistics. + random_seed: Random seed for permutations. + n_jobs: Number of jobs to use for parallel processing. + """ + # Input validation + if not s2c_object_file.is_file(): + raise FileNotFoundError(f"SNP2CELL object file not found: {s2c_object_file}") + if not scores_file.is_file(): + raise FileNotFoundError(f"Scores file not found: {scores_file}") + + # Command construction + cmd = [ + "snp2cell", "add-score", + "--score-name", score_name, + "--n-permutations", str(n_permutations), + "--random-seed", str(random_seed), + "--n-jobs", str(n_jobs), + str(s2c_object_file), + str(scores_file), + ] + + # Subprocess execution + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + ) + return { + "command_executed": " ".join(cmd), + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": [str(s2c_object_file)], + } + except subprocess.CalledProcessError as e: + return { + "command_executed": " ".join(cmd), + "stdout": e.stdout, + "stderr": e.stderr, + "error": f"snp2cell add-score failed with exit code {e.returncode}", + "output_files": [], + } + +@mcp.tool +def contrast_scores( + s2c_object_file: Path, + score_name1: str, + score_name2: str, + new_score_name: str = "contrast_score", + n_permutations: int = 1000, + random_seed: int = 42, + n_jobs: int = 1, +) -> dict: + """ + Add a new score that is a contrast of two scores, propagate it across + the network and calculate statistics based on random permutations. + + Args: + s2c_object_file: Path to the SNP2CELL object file. + score_name1: Name of the first score. + score_name2: Name of the second score. + new_score_name: Name of the new score. + n_permutations: Number of permutations for statistics. + random_seed: Random seed for permutations. + n_jobs: Number of jobs to use for parallel processing. + """ + # Input validation + if not s2c_object_file.is_file(): + raise FileNotFoundError(f"SNP2CELL object file not found: {s2c_object_file}") + + # Command construction + cmd = [ + "snp2cell", "contrast-scores", + "--score-name1", score_name1, + "--score-name2", score_name2, + "--new-score-name", new_score_name, + "--n-permutations", str(n_permutations), + "--random-seed", str(random_seed), + "--n-jobs", str(n_jobs), + str(s2c_object_file), + ] + + # Subprocess execution + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + ) + return { + "command_executed": " ".join(cmd), + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": [str(s2c_object_file)], + } + except subprocess.CalledProcessError as e: + return { + "command_executed": " ".join(cmd), + "stdout": e.stdout, + "stderr": e.stderr, + "error": f"snp2cell contrast-scores failed with exit code {e.returncode}", + "output_files": [], + } + +@mcp.tool +def score_de( + s2c_object_file: Path, + anndata_file: Path, + obs_column: str, + group1: str, + group2: str, + de_score_name: str = "de_score", + snp_score_name: str = "snp_score", + combined_score_name: str = "combined_score", + n_permutations: int = 1000, + random_seed: int = 42, + n_jobs: int = 1, +) -> dict: + """ + Add an anndata object, find differentially expressed genes, propagate + scores, combine with SNP scores, and compute statistics. + + Args: + s2c_object_file: Path to the SNP2CELL object file. + anndata_file: Path to the anndata object file. + obs_column: Name of the column in obs to group by. + group1: Name of the first group. + group2: Name of the second group. + de_score_name: Name of the DE score. + snp_score_name: Name of the SNP score. + combined_score_name: Name of the combined score. + n_permutations: Number of permutations for statistics. + random_seed: Random seed for permutations. + n_jobs: Number of jobs to use for parallel processing. + """ + # Input validation + if not s2c_object_file.is_file(): + raise FileNotFoundError(f"SNP2CELL object file not found: {s2c_object_file}") + if not anndata_file.is_file(): + raise FileNotFoundError(f"AnnData file not found: {anndata_file}") + + # Command construction + cmd = [ + "snp2cell", "score-de", + "--obs-column", obs_column, + "--group1", group1, + "--group2", group2, + "--de-score-name", de_score_name, + "--snp-score-name", snp_score_name, + "--combined-score-name", combined_score_name, + "--n-permutations", str(n_permutations), + "--random-seed", str(random_seed), + "--n-jobs", str(n_jobs), + str(s2c_object_file), + str(anndata_file), + ] + + # Subprocess execution + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + ) + return { + "command_executed": " ".join(cmd), + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": [str(s2c_object_file)], + } + except subprocess.CalledProcessError as e: + return { + "command_executed": " ".join(cmd), + "stdout": e.stdout, + "stderr": e.stderr, + "error": f"snp2cell score-de failed with exit code {e.returncode}", + "output_files": [], + } + +@mcp.tool +def combine_scores( + s2c_object_file: Path, + snp_score_name: str = "snp_score", + de_score_name: str = "de_score", + combined_score_name: str = "combined_score", + n_permutations: int = 1000, + random_seed: int = 42, + n_jobs: int = 1, +) -> dict: + """ + Combine existing SNP and DE scores in the s2c object and compute statistics. + + Args: + s2c_object_file: Path to the SNP2CELL object file. + snp_score_name: Name of the SNP score. + de_score_name: Name of the DE score. + combined_score_name: Name of the combined score. + n_permutations: Number of permutations for statistics. + random_seed: Random seed for permutations. + n_jobs: Number of jobs to use for parallel processing. + """ + # Input validation + if not s2c_object_file.is_file(): + raise FileNotFoundError(f"SNP2CELL object file not found: {s2c_object_file}") + + # Command construction + cmd = [ + "snp2cell", "combine-scores", + "--snp-score-name", snp_score_name, + "--de-score-name", de_score_name, + "--combined-score-name", combined_score_name, + "--n-permutations", str(n_permutations), + "--random-seed", str(random_seed), + "--n-jobs", str(n_jobs), + str(s2c_object_file), + ] + + # Subprocess execution + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + check=True, + ) + return { + "command_executed": " ".join(cmd), + "stdout": result.stdout, + "stderr": result.stderr, + "output_files": [str(s2c_object_file)], + } + except subprocess.CalledProcessError as e: + return { + "command_executed": " ".join(cmd), + "stdout": e.stdout, + "stderr": e.stderr, + "error": f"snp2cell combine-scores failed with exit code {e.returncode}", + "output_files": [], + } \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_snp2cell/app/snp2cell_shim_server.py b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_snp2cell/app/snp2cell_shim_server.py new file mode 100644 index 0000000000000000000000000000000000000000..efbbd066991c98f72b3af10515cf1e9b8e2674fe --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_snp2cell/app/snp2cell_shim_server.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_snp2cell/app/snp2cell_server.py') +SERVER_NAME = 'biosci_snp2cell' + + +class _ShimMCP: + @staticmethod + def tool(): + def _decorator(fn): + return fn + return _decorator + + +def _load_functions(): + code = SOURCE_SERVER.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(SOURCE_SERVER)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = { + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + } + exec(compile(code, str(SOURCE_SERVER), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_snp2cell/docker-compose.yml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_snp2cell/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..1936c8bd0f809510927c8cf2341fb0bf93faf468 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_snp2cell/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + mcp-snp2cell: + build: . + image: mcp-snp2cell:latest + container_name: mcp-snp2cell + ports: + - "8000:8000" + environment: + - MCP_SERVER_NAME=snp2cell + volumes: + - ./workspace:/app/workspace + - ./output:/app/output + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_snp2cell/environment.yaml b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_snp2cell/environment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..6555b3e60bede732ccb6a586e83bca8068584bbd --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_snp2cell/environment.yaml @@ -0,0 +1,10 @@ + +name: mcp-tool +channels: + - bioconda + - conda-forge + - defaults +dependencies: + - snp2cell + - python=3.10 + \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_snp2cell/requirements.txt b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_snp2cell/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4702c254694b94825ae9800a56d8f68b1bcda0 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_snp2cell/requirements.txt @@ -0,0 +1,2 @@ +fastmcp +mcp diff --git a/BioScientist/agent_system/toolbase/mcp_registration_report.json b/BioScientist/agent_system/toolbase/mcp_registration_report.json new file mode 100644 index 0000000000000000000000000000000000000000..fe041aec6adb034f58e424863827dc7466722f52 --- /dev/null +++ b/BioScientist/agent_system/toolbase/mcp_registration_report.json @@ -0,0 +1,20270 @@ +{ + "summary": { + "scanned_dirs": 1066, + "registered": 970, + "skipped_no_server_file": 96, + "skipped_non_runnable_without_shim": 0, + "using_shim": 970, + "requirements_touched": 0, + "dry_run": false + }, + "biomni_root": "/225040511/project/BioScientist/agent_system/engines/v1_executor_backup", + "config_out": "/225040511/project/BioScientist/agent_system/engines/v1_executor_backup/mcp_config_bioscientist_generated.yaml", + "report_out": "/225040511/project/BioScientist/agent_system/toolbase/mcp_registration_report.json", + "records": [ + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_abricate", + "server_name": "biosci_abricate", + "tool_name": "abricate", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_abricate/app/abricate_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_abricate/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_abricate/app/abricate_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_abundancebin", + "server_name": "biosci_abundancebin", + "tool_name": "abundancebin", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_abundancebin/app/abundancebin_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_abundancebin/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_abundancebin/app/abundancebin_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_abyss", + "server_name": "biosci_abyss", + "tool_name": "abyss", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_abyss/app/abyss_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_abyss/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_abyss/app/abyss_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_aragorn", + "server_name": "biosci_aragorn", + "tool_name": "aragorn", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_aragorn/app/aragorn_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_aragorn/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_aragorn/app/aragorn_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_augustus", + "server_name": "biosci_augustus", + "tool_name": "augustus", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_augustus/app/augustus_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_augustus/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_augustus/app/augustus_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bamtools", + "server_name": "biosci_bamtools", + "tool_name": "bamtools", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bamtools/app/bamtools_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bamtools/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bamtools/app/bamtools_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_barrnap", + "server_name": "biosci_barrnap", + "tool_name": "barrnap", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_barrnap/app/barrnap_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_barrnap/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_barrnap/app/barrnap_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bbmap", + "server_name": "biosci_bbmap", + "tool_name": "bbmap", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bbmap/app/bbmap_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bbmap/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bbmap/app/bbmap_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bcftools", + "server_name": "biosci_bcftools", + "tool_name": "bcftools", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bcftools/app/bcftools_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bcftools/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bcftools/app/bcftools_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bedops", + "server_name": "biosci_bedops", + "tool_name": "bedops", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bedops/app/bedops_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bedops/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bedops/app/bedops_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bedtools", + "server_name": "biosci_bedtools", + "tool_name": "bedtools", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bedtools/app/bedtools_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bedtools/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bedtools/app/bedtools_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioawk", + "server_name": "biosci_bioawk", + "tool_name": "bioawk", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioawk/app/bioawk_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioawk/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioawk/app/bioawk_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-affyio", + "server_name": "biosci_bioconductor_affyio", + "tool_name": "bioconductor-affyio", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-affyio/app/bioconductor-affyio_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-affyio/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-affyio/app/bioconductor-affyio_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotate", + "server_name": "biosci_bioconductor_annotate", + "tool_name": "bioconductor-annotate", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotate/app/bioconductor-annotate_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotate/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotate/app/bioconductor-annotate_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotationdbi", + "server_name": "biosci_bioconductor_annotationdbi", + "tool_name": "bioconductor-annotationdbi", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotationdbi/app/bioconductor-annotationdbi_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotationdbi/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-annotationdbi/app/bioconductor-annotationdbi_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-apeglm", + "server_name": "biosci_bioconductor_apeglm", + "tool_name": "bioconductor-apeglm", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-apeglm/app/bioconductor-apeglm_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-apeglm/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-apeglm/app/bioconductor-apeglm_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-beachmat", + "server_name": "biosci_bioconductor_beachmat", + "tool_name": "bioconductor-beachmat", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-beachmat/app/bioconductor-beachmat_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-beachmat/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-beachmat/app/bioconductor-beachmat_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biobase", + "server_name": "biosci_bioconductor_biobase", + "tool_name": "bioconductor-biobase", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biobase/app/bioconductor-biobase_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biobase/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biobase/app/bioconductor-biobase_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocgenerics", + "server_name": "biosci_bioconductor_biocgenerics", + "tool_name": "bioconductor-biocgenerics", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocgenerics/app/bioconductor-biocgenerics_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocgenerics/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocgenerics/app/bioconductor-biocgenerics_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocneighbors", + "server_name": "biosci_bioconductor_biocneighbors", + "tool_name": "bioconductor-biocneighbors", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocneighbors/app/bioconductor-biocneighbors_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocneighbors/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocneighbors/app/bioconductor-biocneighbors_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocparallel", + "server_name": "biosci_bioconductor_biocparallel", + "tool_name": "bioconductor-biocparallel", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocparallel/app/bioconductor-biocparallel_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocparallel/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocparallel/app/bioconductor-biocparallel_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocsingular", + "server_name": "biosci_bioconductor_biocsingular", + "tool_name": "bioconductor-biocsingular", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocsingular/app/bioconductor-biocsingular_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocsingular/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocsingular/app/bioconductor-biocsingular_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biomart", + "server_name": "biosci_bioconductor_biomart", + "tool_name": "bioconductor-biomart", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biomart/app/bioconductor-biomart_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biomart/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biomart/app/bioconductor-biomart_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biomformat", + "server_name": "biosci_bioconductor_biomformat", + "tool_name": "bioconductor-biomformat", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biomformat/app/bioconductor-biomformat_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biomformat/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biomformat/app/bioconductor-biomformat_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biostrings", + "server_name": "biosci_bioconductor_biostrings", + "tool_name": "bioconductor-biostrings", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biostrings/app/bioconductor-biostrings_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biostrings/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biostrings/app/bioconductor-biostrings_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-bsgenome", + "server_name": "biosci_bioconductor_bsgenome", + "tool_name": "bioconductor-bsgenome", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-bsgenome/app/bioconductor-bsgenome_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-bsgenome/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-bsgenome/app/bioconductor-bsgenome_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-clustifyr", + "server_name": "biosci_bioconductor_clustifyr", + "tool_name": "bioconductor-clustifyr", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-clustifyr/app/bioconductor-clustifyr_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-clustifyr/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-clustifyr/app/bioconductor-clustifyr_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-cytomapper", + "server_name": "biosci_bioconductor_cytomapper", + "tool_name": "bioconductor-cytomapper", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-cytomapper/app/bioconductor-cytomapper_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-cytomapper/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-cytomapper/app/bioconductor-cytomapper_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-dirichletmultinomial", + "server_name": "biosci_bioconductor_dirichletmultinomial", + "tool_name": "bioconductor-dirichletmultinomial", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-dirichletmultinomial/app/bioconductor-dirichletmultinomial_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-dirichletmultinomial/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-dirichletmultinomial/app/bioconductor-dirichletmultinomial_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-dnacopy", + "server_name": "biosci_bioconductor_dnacopy", + "tool_name": "bioconductor-dnacopy", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-dnacopy/app/bioconductor-dnacopy_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-dnacopy/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-dnacopy/app/bioconductor-dnacopy_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-edger", + "server_name": "biosci_bioconductor_edger", + "tool_name": "bioconductor-edger", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-edger/app/bioconductor-edger_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-edger/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-edger/app/bioconductor-edger_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genefilter", + "server_name": "biosci_bioconductor_genefilter", + "tool_name": "bioconductor-genefilter", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genefilter/app/bioconductor-genefilter_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genefilter/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genefilter/app/bioconductor-genefilter_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-geneplotter", + "server_name": "biosci_bioconductor_geneplotter", + "tool_name": "bioconductor-geneplotter", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-geneplotter/app/bioconductor-geneplotter_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-geneplotter/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-geneplotter/app/bioconductor-geneplotter_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomeinfodbdata", + "server_name": "biosci_bioconductor_genomeinfodbdata", + "tool_name": "bioconductor-genomeinfodbdata", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomeinfodbdata/app/bioconductor-genomeinfodbdata_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomeinfodbdata/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomeinfodbdata/app/bioconductor-genomeinfodbdata_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomicalignments", + "server_name": "biosci_bioconductor_genomicalignments", + "tool_name": "bioconductor-genomicalignments", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomicalignments/app/bioconductor-genomicalignments_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomicalignments/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomicalignments/app/bioconductor-genomicalignments_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomicfeatures", + "server_name": "biosci_bioconductor_genomicfeatures", + "tool_name": "bioconductor-genomicfeatures", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomicfeatures/app/bioconductor-genomicfeatures_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomicfeatures/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-genomicfeatures/app/bioconductor-genomicfeatures_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-go.db", + "server_name": "biosci_bioconductor_go_db", + "tool_name": "bioconductor-go.db", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-go.db/app/bioconductor-go.db_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-go.db/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-go.db/app/bioconductor-go.db_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gosemsim", + "server_name": "biosci_bioconductor_gosemsim", + "tool_name": "bioconductor-gosemsim", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gosemsim/app/bioconductor-gosemsim_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gosemsim/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gosemsim/app/bioconductor-gosemsim_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-graph", + "server_name": "biosci_bioconductor_graph", + "tool_name": "bioconductor-graph", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-graph/app/bioconductor-graph_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-graph/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-graph/app/bioconductor-graph_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gsva", + "server_name": "biosci_bioconductor_gsva", + "tool_name": "bioconductor-gsva", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gsva/app/bioconductor-gsva_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gsva/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-gsva/app/bioconductor-gsva_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-infercnv", + "server_name": "biosci_bioconductor_infercnv", + "tool_name": "bioconductor-infercnv", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-infercnv/app/bioconductor-infercnv_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-infercnv/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-infercnv/app/bioconductor-infercnv_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-iranges", + "server_name": "biosci_bioconductor_iranges", + "tool_name": "bioconductor-iranges", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-iranges/app/bioconductor-iranges_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-iranges/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-iranges/app/bioconductor-iranges_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-keggrest", + "server_name": "biosci_bioconductor_keggrest", + "tool_name": "bioconductor-keggrest", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-keggrest/app/bioconductor-keggrest_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-keggrest/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-keggrest/app/bioconductor-keggrest_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-limma", + "server_name": "biosci_bioconductor_limma", + "tool_name": "bioconductor-limma", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-limma/app/bioconductor-limma_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-limma/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-limma/app/bioconductor-limma_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-metabolomicsworkbenchr", + "server_name": "biosci_bioconductor_metabolomicsworkbenchr", + "tool_name": "bioconductor-metabolomicsworkbenchr", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-metabolomicsworkbenchr/app/bioconductor-metabolomicsworkbenchr_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-metabolomicsworkbenchr/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-metabolomicsworkbenchr/app/bioconductor-metabolomicsworkbenchr_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-mosim", + "server_name": "biosci_bioconductor_mosim", + "tool_name": "bioconductor-mosim", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-mosim/app/bioconductor-mosim_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-mosim/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-mosim/app/bioconductor-mosim_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-multtest", + "server_name": "biosci_bioconductor_multtest", + "tool_name": "bioconductor-multtest", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-multtest/app/bioconductor-multtest_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-multtest/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-multtest/app/bioconductor-multtest_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-nebulosa", + "server_name": "biosci_bioconductor_nebulosa", + "tool_name": "bioconductor-nebulosa", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-nebulosa/app/bioconductor-nebulosa_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-nebulosa/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-nebulosa/app/bioconductor-nebulosa_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-noiseq", + "server_name": "biosci_bioconductor_noiseq", + "tool_name": "bioconductor-noiseq", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-noiseq/app/bioconductor-noiseq_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-noiseq/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-noiseq/app/bioconductor-noiseq_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-org.hs.eg.db", + "server_name": "biosci_bioconductor_org_hs_eg_db", + "tool_name": "bioconductor-org.hs.eg.db", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-org.hs.eg.db/app/bioconductor-org.hs.eg.db_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-org.hs.eg.db/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-org.hs.eg.db/app/bioconductor-org.hs.eg.db_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-phemd", + "server_name": "biosci_bioconductor_phemd", + "tool_name": "bioconductor-phemd", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-phemd/app/bioconductor-phemd_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-phemd/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-phemd/app/bioconductor-phemd_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-preprocesscore", + "server_name": "biosci_bioconductor_preprocesscore", + "tool_name": "bioconductor-preprocesscore", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-preprocesscore/app/bioconductor-preprocesscore_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-preprocesscore/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-preprocesscore/app/bioconductor-preprocesscore_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-proteomicsannotationhubdata", + "server_name": "biosci_bioconductor_proteomicsannotationhubdata", + "tool_name": "bioconductor-proteomicsannotationhubdata", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-proteomicsannotationhubdata/app/bioconductor-proteomicsannotationhubdata_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-proteomicsannotationhubdata/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-proteomicsannotationhubdata/app/bioconductor-proteomicsannotationhubdata_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-protgenerics", + "server_name": "biosci_bioconductor_protgenerics", + "tool_name": "bioconductor-protgenerics", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-protgenerics/app/bioconductor-protgenerics_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-protgenerics/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-protgenerics/app/bioconductor-protgenerics_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rforproteomics", + "server_name": "biosci_bioconductor_rforproteomics", + "tool_name": "bioconductor-rforproteomics", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rforproteomics/app/bioconductor-rforproteomics_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rforproteomics/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rforproteomics/app/bioconductor-rforproteomics_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhdf5", + "server_name": "biosci_bioconductor_rhdf5", + "tool_name": "bioconductor-rhdf5", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhdf5/app/bioconductor-rhdf5_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhdf5/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhdf5/app/bioconductor-rhdf5_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhtslib", + "server_name": "biosci_bioconductor_rhtslib", + "tool_name": "bioconductor-rhtslib", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhtslib/app/bioconductor-rhtslib_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhtslib/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rhtslib/app/bioconductor-rhtslib_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rsamtools", + "server_name": "biosci_bioconductor_rsamtools", + "tool_name": "bioconductor-rsamtools", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rsamtools/app/bioconductor-rsamtools_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rsamtools/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rsamtools/app/bioconductor-rsamtools_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rsubread", + "server_name": "biosci_bioconductor_rsubread", + "tool_name": "bioconductor-rsubread", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rsubread/app/bioconductor-rsubread_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rsubread/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rsubread/app/bioconductor-rsubread_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rtracklayer", + "server_name": "biosci_bioconductor_rtracklayer", + "tool_name": "bioconductor-rtracklayer", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rtracklayer/app/bioconductor-rtracklayer_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rtracklayer/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-rtracklayer/app/bioconductor-rtracklayer_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-s4vectors", + "server_name": "biosci_bioconductor_s4vectors", + "tool_name": "bioconductor-s4vectors", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-s4vectors/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scbfa", + "server_name": "biosci_bioconductor_scbfa", + "tool_name": "bioconductor-scbfa", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scbfa/app/bioconductor-scbfa_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scbfa/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scbfa/app/bioconductor-scbfa_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-sccb2", + "server_name": "biosci_bioconductor_sccb2", + "tool_name": "bioconductor-sccb2", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-sccb2/app/bioconductor-sccb2_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-sccb2/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-sccb2/app/bioconductor-sccb2_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scdataviz", + "server_name": "biosci_bioconductor_scdataviz", + "tool_name": "bioconductor-scdataviz", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scdataviz/app/bioconductor-scdataviz_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scdataviz/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scdataviz/app/bioconductor-scdataviz_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scmageck", + "server_name": "biosci_bioconductor_scmageck", + "tool_name": "bioconductor-scmageck", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scmageck/app/bioconductor-scmageck_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scmageck/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scmageck/app/bioconductor-scmageck_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-screpertoire", + "server_name": "biosci_bioconductor_screpertoire", + "tool_name": "bioconductor-screpertoire", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-screpertoire/app/bioconductor-screpertoire_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-screpertoire/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-screpertoire/app/bioconductor-screpertoire_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scrnaseq", + "server_name": "biosci_bioconductor_scrnaseq", + "tool_name": "bioconductor-scrnaseq", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scrnaseq/app/bioconductor-scrnaseq_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scrnaseq/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-scrnaseq/app/bioconductor-scrnaseq_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-shortread", + "server_name": "biosci_bioconductor_shortread", + "tool_name": "bioconductor-shortread", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-shortread/app/bioconductor-shortread_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-shortread/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-shortread/app/bioconductor-shortread_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-singlecellmultimodal", + "server_name": "biosci_bioconductor_singlecellmultimodal", + "tool_name": "bioconductor-singlecellmultimodal", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-singlecellmultimodal/app/bioconductor-singlecellmultimodal_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-singlecellmultimodal/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-singlecellmultimodal/app/bioconductor-singlecellmultimodal_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spaniel", + "server_name": "biosci_bioconductor_spaniel", + "tool_name": "bioconductor-spaniel", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spaniel/app/bioconductor-spaniel_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spaniel/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spaniel/app/bioconductor-spaniel_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spatialcpie", + "server_name": "biosci_bioconductor_spatialcpie", + "tool_name": "bioconductor-spatialcpie", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spatialcpie/app/bioconductor-spatialcpie_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spatialcpie/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spatialcpie/app/bioconductor-spatialcpie_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spatialdecon", + "server_name": "biosci_bioconductor_spatialdecon", + "tool_name": "bioconductor-spatialdecon", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spatialdecon/app/bioconductor-spatialdecon_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spatialdecon/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spatialdecon/app/bioconductor-spatialdecon_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spatialexperiment", + "server_name": "biosci_bioconductor_spatialexperiment", + "tool_name": "bioconductor-spatialexperiment", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spatialexperiment/app/bioconductor-spatialexperiment_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spatialexperiment/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spatialexperiment/app/bioconductor-spatialexperiment_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spatialheatmap", + "server_name": "biosci_bioconductor_spatialheatmap", + "tool_name": "bioconductor-spatialheatmap", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spatialheatmap/app/bioconductor-spatialheatmap_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spatialheatmap/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-spatialheatmap/app/bioconductor-spatialheatmap_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-tximport", + "server_name": "biosci_bioconductor_tximport", + "tool_name": "bioconductor-tximport", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-tximport/app/bioconductor-tximport_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-tximport/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-tximport/app/bioconductor-tximport_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-variantannotation", + "server_name": "biosci_bioconductor_variantannotation", + "tool_name": "bioconductor-variantannotation", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-variantannotation/app/bioconductor-variantannotation_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-variantannotation/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-variantannotation/app/bioconductor-variantannotation_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-xvector", + "server_name": "biosci_bioconductor_xvector", + "tool_name": "bioconductor-xvector", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-xvector/app/bioconductor-xvector_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-xvector/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-xvector/app/bioconductor-xvector_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-zlibbioc", + "server_name": "biosci_bioconductor_zlibbioc", + "tool_name": "bioconductor-zlibbioc", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-zlibbioc/app/bioconductor-zlibbioc_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-zlibbioc/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-zlibbioc/app/bioconductor-zlibbioc_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_blast", + "server_name": "biosci_blast", + "tool_name": "blast", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_blast/app/blast_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_blast/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_blast/app/blast_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie", + "server_name": "biosci_bowtie", + "tool_name": "bowtie", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie/app/bowtie_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie/app/bowtie_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie2", + "server_name": "biosci_bowtie2", + "tool_name": "bowtie2", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie2/app/bowtie2_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie2/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bowtie2/app/bowtie2_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_brooklyn_plot", + "server_name": "biosci_brooklyn_plot", + "tool_name": "brooklyn_plot", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_brooklyn_plot/app/brooklyn_plot_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_brooklyn_plot/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_brooklyn_plot/app/brooklyn_plot_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bwa", + "server_name": "biosci_bwa", + "tool_name": "bwa", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bwa/app/bwa_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bwa/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bwa/app/bwa_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cd-hit", + "server_name": "biosci_cd_hit", + "tool_name": "cd-hit", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cd-hit/app/cd-hit_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cd-hit/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cd-hit/app/cd-hit_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cellrank", + "server_name": "biosci_cellrank", + "tool_name": "cellrank", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cellrank/app/cellrank_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cellrank/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cellrank/app/cellrank_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_celltypist", + "server_name": "biosci_celltypist", + "tool_name": "celltypist", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_celltypist/app/celltypist_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_celltypist/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_celltypist/app/celltypist_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_circos", + "server_name": "biosci_circos", + "tool_name": "circos", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_circos/app/circos_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_circos/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_circos/app/circos_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_clustalo", + "server_name": "biosci_clustalo", + "tool_name": "clustalo", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_clustalo/app/clustalo_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_clustalo/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_clustalo/app/clustalo_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_clustalw", + "server_name": "biosci_clustalw", + "tool_name": "clustalw", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_clustalw/app/clustalw_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_clustalw/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_clustalw/app/clustalw_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cnmf", + "server_name": "biosci_cnmf", + "tool_name": "cnmf", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cnmf/app/cnmf_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cnmf/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cnmf/app/cnmf_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_csvtk", + "server_name": "biosci_csvtk", + "tool_name": "csvtk", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_csvtk/app/csvtk_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_csvtk/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_csvtk/app/csvtk_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cytotrace2-python", + "server_name": "biosci_cytotrace2_python", + "tool_name": "cytotrace2-python", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cytotrace2-python/app/cytotrace2-python_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cytotrace2-python/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_cytotrace2-python/app/cytotrace2-python_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_decoupler", + "server_name": "biosci_decoupler", + "tool_name": "decoupler", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_decoupler/app/decoupler_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_decoupler/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_decoupler/app/decoupler_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_delly", + "server_name": "biosci_delly", + "tool_name": "delly", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_delly/app/delly_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_delly/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_delly/app/delly_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_dendropy", + "server_name": "biosci_dendropy", + "tool_name": "dendropy", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_dendropy/app/dendropy_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_dendropy/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_dendropy/app/dendropy_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_diamond", + "server_name": "biosci_diamond", + "tool_name": "diamond", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_diamond/app/diamond_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_diamond/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_diamond/app/diamond_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_dsh-bio", + "server_name": "biosci_dsh_bio", + "tool_name": "dsh-bio", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_dsh-bio/app/dsh-bio_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_dsh-bio/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_dsh-bio/app/dsh-bio_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_ena-webin-cli", + "server_name": "biosci_ena_webin_cli", + "tool_name": "ena-webin-cli", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_ena-webin-cli/app/ena-webin-cli_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_ena-webin-cli/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_ena-webin-cli/app/ena-webin-cli_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_f5c", + "server_name": "biosci_f5c", + "tool_name": "f5c", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_f5c/app/f5c_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_f5c/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_f5c/app/f5c_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_fastdtw", + "server_name": "biosci_fastdtw", + "tool_name": "fastdtw", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_fastdtw/app/fastdtw_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_fastdtw/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_fastdtw/app/fastdtw_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_fastp", + "server_name": "biosci_fastp", + "tool_name": "fastp", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_fastp/app/fastp_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_fastp/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_fastp/app/fastp_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_fastqc", + "server_name": "biosci_fastqc", + "tool_name": "fastqc", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_fastqc/app/fastqc_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_fastqc/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_fastqc/app/fastqc_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_fasttree", + "server_name": "biosci_fasttree", + "tool_name": "fasttree", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_fasttree/app/fasttree_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_fasttree/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_fasttree/app/fasttree_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_fgbio", + "server_name": "biosci_fgbio", + "tool_name": "fgbio", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_fgbio/app/fgbio_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_fgbio/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_fgbio/app/fgbio_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_flye", + "server_name": "biosci_flye", + "tool_name": "flye", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_flye/app/flye_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_flye/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_flye/app/flye_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_foldseek", + "server_name": "biosci_foldseek", + "tool_name": "foldseek", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_foldseek/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_gsmap", + "server_name": "biosci_gsmap", + "tool_name": "gsmap", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_gsmap/app/gsmap_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_gsmap/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_gsmap/app/gsmap_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_last", + "server_name": "biosci_last", + "tool_name": "last", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_last/app/last_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_last/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_last/app/last_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_multivelo", + "server_name": "biosci_multivelo", + "tool_name": "multivelo", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_multivelo/app/multivelo_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_multivelo/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_multivelo/app/multivelo_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_peptide-shaker", + "server_name": "biosci_peptide_shaker", + "tool_name": "peptide-shaker", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_peptide-shaker/app/peptide-shaker_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_peptide-shaker/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_peptide-shaker/app/peptide-shaker_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_perl-metabolomics-fragment-annotation", + "server_name": "biosci_perl_metabolomics_fragment_annotation", + "tool_name": "perl-metabolomics-fragment-annotation", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_perl-metabolomics-fragment-annotation/app/perl-metabolomics-fragment-annotation_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_perl-metabolomics-fragment-annotation/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_perl-metabolomics-fragment-annotation/app/perl-metabolomics-fragment-annotation_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_picard", + "server_name": "biosci_picard", + "tool_name": "picard", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_picard/app/picard_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_picard/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_picard/app/picard_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_proteomiqon-peptidedb", + "server_name": "biosci_proteomiqon_peptidedb", + "tool_name": "proteomiqon-peptidedb", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_proteomiqon-peptidedb/app/proteomiqon-peptidedb_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_proteomiqon-peptidedb/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_proteomiqon-peptidedb/app/proteomiqon-peptidedb_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_pycistopic", + "server_name": "biosci_pycistopic", + "tool_name": "pycistopic", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_pycistopic/app/pycistopic_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_pycistopic/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_pycistopic/app/pycistopic_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_pyroe", + "server_name": "biosci_pyroe", + "tool_name": "pyroe", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_pyroe/app/pyroe_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_pyroe/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_pyroe/app/pyroe_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-scpred", + "server_name": "biosci_r_scpred", + "tool_name": "r-scpred", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-scpred/app/r-scpred_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-scpred/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-scpred/app/r-scpred_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-seurat", + "server_name": "biosci_r_seurat", + "tool_name": "r-seurat", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-seurat/app/r-seurat_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-seurat/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-seurat/app/r-seurat_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-seurat-scripts", + "server_name": "biosci_r_seurat_scripts", + "tool_name": "r-seurat-scripts", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-seurat-scripts/app/r-seurat-scripts_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-seurat-scripts/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-seurat-scripts/app/r-seurat-scripts_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-signac", + "server_name": "biosci_r_signac", + "tool_name": "r-signac", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-signac/app/r-signac_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-signac/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_r-signac/app/r-signac_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_samtools", + "server_name": "biosci_samtools", + "tool_name": "samtools", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_samtools/app/samtools_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_samtools/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_samtools/app/samtools_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scanpy", + "server_name": "biosci_scanpy", + "tool_name": "scanpy", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scanpy/app/scanpy_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scanpy/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scanpy/app/scanpy_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scar", + "server_name": "biosci_scar", + "tool_name": "scar", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scar/app/scar_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scar/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scar/app/scar_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scarches", + "server_name": "biosci_scarches", + "tool_name": "scarches", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scarches/app/scarches_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scarches/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scarches/app/scarches_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_sccaf", + "server_name": "biosci_sccaf", + "tool_name": "sccaf", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_sccaf/app/sccaf_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_sccaf/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_sccaf/app/sccaf_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scelvis", + "server_name": "biosci_scelvis", + "tool_name": "scelvis", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scelvis/app/scelvis_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scelvis/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scelvis/app/scelvis_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scpred-cli", + "server_name": "biosci_scpred_cli", + "tool_name": "scpred-cli", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scpred-cli/app/scpred-cli_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scpred-cli/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scpred-cli/app/scpred-cli_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scvelo", + "server_name": "biosci_scvelo", + "tool_name": "scvelo", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scvelo/app/scvelo_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scvelo/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_scvelo/app/scvelo_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_seurat-scripts", + "server_name": "biosci_seurat_scripts", + "tool_name": "seurat-scripts", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_seurat-scripts/app/seurat-scripts_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_seurat-scripts/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_seurat-scripts/app/seurat-scripts_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_snp2cell", + "server_name": "biosci_snp2cell", + "tool_name": "snp2cell", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_snp2cell/app/snp2cell_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_snp2cell/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_snp2cell/app/snp2cell_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_abnumber", + "server_name": "biosci_abnumber", + "tool_name": "abnumber", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_abnumber/app/abnumber_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_abnumber/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_abnumber/app/abnumber_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_abricate", + "server_name": "biosci_abricate", + "tool_name": "abricate", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_abricate/app/abricate_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_abricate/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_abricate/app/abricate_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_abundancebin", + "server_name": "biosci_abundancebin", + "tool_name": "abundancebin", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_abundancebin/app/abundancebin_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_abundancebin/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_abundancebin/app/abundancebin_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_abyss", + "server_name": "biosci_abyss", + "tool_name": "abyss", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_abyss/app/abyss_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_abyss/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_abyss/app/abyss_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_adapterremoval", + "server_name": "biosci_adapterremoval", + "tool_name": "adapterremoval", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_adapterremoval/app/adapterremoval_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_adapterremoval/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_adapterremoval/app/adapterremoval_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_alfred", + "server_name": "biosci_alfred", + "tool_name": "alfred", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_alfred/app/alfred_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_alfred/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_alfred/app/alfred_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_anansescanpy", + "server_name": "biosci_anansescanpy", + "tool_name": "anansescanpy", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_anansescanpy/app/anansescanpy_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_anansescanpy/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_anansescanpy/app/anansescanpy_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_anarci", + "server_name": "biosci_anarci", + "tool_name": "anarci", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_anarci/app/anarci_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_anarci/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_anarci/app/anarci_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_aragorn", + "server_name": "biosci_aragorn", + "tool_name": "aragorn", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_aragorn/app/aragorn_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_aragorn/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_aragorn/app/aragorn_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_aria2", + "server_name": "biosci_aria2", + "tool_name": "aria2", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_aria2/app/aria2_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_aria2/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_aria2/app/aria2_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ariba", + "server_name": "biosci_ariba", + "tool_name": "ariba", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ariba/app/ariba_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ariba/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ariba/app/ariba_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_arriba", + "server_name": "biosci_arriba", + "tool_name": "arriba", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_arriba/app/arriba_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_arriba/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_arriba/app/arriba_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_art", + "server_name": "biosci_art", + "tool_name": "art", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_art/app/art_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_art/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_art/app/art_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_arvados-cwl-runner", + "server_name": "biosci_arvados_cwl_runner", + "tool_name": "arvados-cwl-runner", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_arvados-cwl-runner/app/arvados-cwl-runner_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_arvados-cwl-runner/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_arvados-cwl-runner/app/arvados-cwl-runner_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_arvados-python-client", + "server_name": "biosci_arvados_python_client", + "tool_name": "arvados-python-client", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_arvados-python-client/app/arvados-python-client_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_arvados-python-client/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_arvados-python-client/app/arvados-python-client_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_atropos", + "server_name": "biosci_atropos", + "tool_name": "atropos", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_atropos/app/atropos_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_atropos/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_atropos/app/atropos_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_augur", + "server_name": "biosci_augur", + "tool_name": "augur", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_augur/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_auspice", + "server_name": "biosci_auspice", + "tool_name": "auspice", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_auspice/app/auspice_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_auspice/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_auspice/app/auspice_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bactopia", + "server_name": "biosci_bactopia", + "tool_name": "bactopia", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bactopia/app/bactopia_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bactopia/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bactopia/app/bactopia_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_barrnap", + "server_name": "biosci_barrnap", + "tool_name": "barrnap", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_barrnap/app/barrnap_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_barrnap/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_barrnap/app/barrnap_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bcbio-gff", + "server_name": "biosci_bcbio_gff", + "tool_name": "bcbio-gff", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bcbio-gff/app/bcbio-gff_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bcbio-gff/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bcbio-gff/app/bcbio-gff_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bcbio-nextgen", + "server_name": "biosci_bcbio_nextgen", + "tool_name": "bcbio-nextgen", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bcbio-nextgen/app/bcbio-nextgen_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bcbio-nextgen/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bcbio-nextgen/app/bcbio-nextgen_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bedops", + "server_name": "biosci_bedops", + "tool_name": "bedops", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bedops/app/bedops_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bedops/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bedops/app/bedops_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bin2cell", + "server_name": "biosci_bin2cell", + "tool_name": "bin2cell", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bin2cell/app/bin2cell_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bin2cell/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bin2cell/app/bin2cell_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioawk", + "server_name": "biosci_bioawk", + "tool_name": "bioawk", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioawk/app/bioawk_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioawk/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioawk/app/bioawk_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_biobambam", + "server_name": "biosci_biobambam", + "tool_name": "biobambam", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_biobambam/app/biobambam_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_biobambam/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_biobambam/app/biobambam_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioblend", + "server_name": "biosci_bioblend", + "tool_name": "bioblend", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioblend/app/bioblend_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioblend/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioblend/app/bioblend_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconda-repodata-patches", + "server_name": "biosci_bioconda_repodata_patches", + "tool_name": "bioconda-repodata-patches", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconda-repodata-patches/app/bioconda-repodata-patches_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconda-repodata-patches/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconda-repodata-patches/app/bioconda-repodata-patches_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconda-utils", + "server_name": "biosci_bioconda_utils", + "tool_name": "bioconda-utils", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconda-utils/app/bioconda-utils_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconda-utils/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconda-utils/app/bioconda-utils_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-affy", + "server_name": "biosci_bioconductor_affy", + "tool_name": "bioconductor-affy", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-affy/app/bioconductor-affy_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-affy/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-affy/app/bioconductor-affy_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-affyio", + "server_name": "biosci_bioconductor_affyio", + "tool_name": "bioconductor-affyio", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-affyio/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-alabaster", + "server_name": "biosci_bioconductor_alabaster", + "tool_name": "bioconductor-alabaster", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-alabaster/app/bioconductor-alabaster_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-alabaster/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-alabaster/app/bioconductor-alabaster_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-alabaster.sfe", + "server_name": "biosci_bioconductor_alabaster_sfe", + "tool_name": "bioconductor-alabaster.sfe", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-alabaster.sfe/app/bioconductor-alabaster.sfe_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-alabaster.sfe/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-alabaster.sfe/app/bioconductor-alabaster.sfe_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-alabaster.spatial", + "server_name": "biosci_bioconductor_alabaster_spatial", + "tool_name": "bioconductor-alabaster.spatial", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-alabaster.spatial/app/bioconductor-alabaster.spatial_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-alabaster.spatial/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-alabaster.spatial/app/bioconductor-alabaster.spatial_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-ancombc", + "server_name": "biosci_bioconductor_ancombc", + "tool_name": "bioconductor-ancombc", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-ancombc/app/bioconductor-ancombc_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-ancombc/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-ancombc/app/bioconductor-ancombc_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-annotationfilter", + "server_name": "biosci_bioconductor_annotationfilter", + "tool_name": "bioconductor-annotationfilter", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-annotationfilter/app/bioconductor-annotationfilter_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-annotationfilter/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-annotationfilter/app/bioconductor-annotationfilter_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-annotationhub", + "server_name": "biosci_bioconductor_annotationhub", + "tool_name": "bioconductor-annotationhub", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-annotationhub/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-apl", + "server_name": "biosci_bioconductor_apl", + "tool_name": "bioconductor-apl", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-apl/app/bioconductor-apl_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-apl/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-apl/app/bioconductor-apl_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-awaggregator", + "server_name": "biosci_bioconductor_awaggregator", + "tool_name": "bioconductor-awaggregator", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-awaggregator/app/bioconductor-awaggregator_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-awaggregator/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-awaggregator/app/bioconductor-awaggregator_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-banksy", + "server_name": "biosci_bioconductor_banksy", + "tool_name": "bioconductor-banksy", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-banksy/app/bioconductor-banksy_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-banksy/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-banksy/app/bioconductor-banksy_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-benchdamic", + "server_name": "biosci_bioconductor_benchdamic", + "tool_name": "bioconductor-benchdamic", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-benchdamic/app/bioconductor-benchdamic_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-benchdamic/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-benchdamic/app/bioconductor-benchdamic_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-biocbaseutils", + "server_name": "biosci_bioconductor_biocbaseutils", + "tool_name": "bioconductor-biocbaseutils", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-biocbaseutils/app/bioconductor-biocbaseutils_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-biocbaseutils/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-biocbaseutils/app/bioconductor-biocbaseutils_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-biocfilecache", + "server_name": "biosci_bioconductor_biocfilecache", + "tool_name": "bioconductor-biocfilecache", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-biocfilecache/app/bioconductor-biocfilecache_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-biocfilecache/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-biocfilecache/app/bioconductor-biocfilecache_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-biocio", + "server_name": "biosci_bioconductor_biocio", + "tool_name": "bioconductor-biocio", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-biocio/app/bioconductor-biocio_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-biocio/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-biocio/app/bioconductor-biocio_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-biomformat", + "server_name": "biosci_bioconductor_biomformat", + "tool_name": "bioconductor-biomformat", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-biomformat/app/bioconductor-biomformat_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-biomformat/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-biomformat/app/bioconductor-biomformat_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-biovizbase", + "server_name": "biosci_bioconductor_biovizbase", + "tool_name": "bioconductor-biovizbase", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-biovizbase/app/bioconductor-biovizbase_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-biovizbase/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-biovizbase/app/bioconductor-biovizbase_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-blase", + "server_name": "biosci_bioconductor_blase", + "tool_name": "bioconductor-blase", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-blase/app/bioconductor-blase_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-blase/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-blase/app/bioconductor-blase_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-bluster", + "server_name": "biosci_bioconductor_bluster", + "tool_name": "bioconductor-bluster", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-bluster/app/bioconductor-bluster_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-bluster/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-bluster/app/bioconductor-bluster_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-bsgenome", + "server_name": "biosci_bioconductor_bsgenome", + "tool_name": "bioconductor-bsgenome", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-bsgenome/app/bioconductor-bsgenome_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-bsgenome/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-bsgenome/app/bioconductor-bsgenome_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-bulksignalr", + "server_name": "biosci_bioconductor_bulksignalr", + "tool_name": "bioconductor-bulksignalr", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-bulksignalr/app/bioconductor-bulksignalr_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-bulksignalr/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-bulksignalr/app/bioconductor-bulksignalr_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-cardspa", + "server_name": "biosci_bioconductor_cardspa", + "tool_name": "bioconductor-cardspa", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-cardspa/app/bioconductor-cardspa_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-cardspa/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-cardspa/app/bioconductor-cardspa_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-catscradle", + "server_name": "biosci_bioconductor_catscradle", + "tool_name": "bioconductor-catscradle", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-catscradle/app/bioconductor-catscradle_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-catscradle/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-catscradle/app/bioconductor-catscradle_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-cdi", + "server_name": "biosci_bioconductor_cdi", + "tool_name": "bioconductor-cdi", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-cdi/app/bioconductor-cdi_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-cdi/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-cdi/app/bioconductor-cdi_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-cellhashr", + "server_name": "biosci_bioconductor_cellhashr", + "tool_name": "bioconductor-cellhashr", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-cellhashr/app/bioconductor-cellhashr_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-cellhashr/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-cellhashr/app/bioconductor-cellhashr_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-cellid", + "server_name": "biosci_bioconductor_cellid", + "tool_name": "bioconductor-cellid", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-cellid/app/bioconductor-cellid_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-cellid/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-cellid/app/bioconductor-cellid_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-cellmigration", + "server_name": "biosci_bioconductor_cellmigration", + "tool_name": "bioconductor-cellmigration", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-cellmigration/app/bioconductor-cellmigration_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-cellmigration/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-cellmigration/app/bioconductor-cellmigration_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-clusterfoldsimilarity", + "server_name": "biosci_bioconductor_clusterfoldsimilarity", + "tool_name": "bioconductor-clusterfoldsimilarity", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-clusterfoldsimilarity/app/bioconductor-clusterfoldsimilarity_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-clusterfoldsimilarity/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-clusterfoldsimilarity/app/bioconductor-clusterfoldsimilarity_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-clusterprofiler", + "server_name": "biosci_bioconductor_clusterprofiler", + "tool_name": "bioconductor-clusterprofiler", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-clusterprofiler/app/bioconductor-clusterprofiler_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-clusterprofiler/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-clusterprofiler/app/bioconductor-clusterprofiler_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-clustsignal", + "server_name": "biosci_bioconductor_clustsignal", + "tool_name": "bioconductor-clustsignal", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-clustsignal/app/bioconductor-clustsignal_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-clustsignal/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-clustsignal/app/bioconductor-clustsignal_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-complexheatmap", + "server_name": "biosci_bioconductor_complexheatmap", + "tool_name": "bioconductor-complexheatmap", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-complexheatmap/app/bioconductor-complexheatmap_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-complexheatmap/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-complexheatmap/app/bioconductor-complexheatmap_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-concordexr", + "server_name": "biosci_bioconductor_concordexr", + "tool_name": "bioconductor-concordexr", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-concordexr/app/bioconductor-concordexr_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-concordexr/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-concordexr/app/bioconductor-concordexr_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-cotan", + "server_name": "biosci_bioconductor_cotan", + "tool_name": "bioconductor-cotan", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-cotan/app/bioconductor-cotan_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-cotan/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-cotan/app/bioconductor-cotan_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-csoa", + "server_name": "biosci_bioconductor_csoa", + "tool_name": "bioconductor-csoa", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-csoa/app/bioconductor-csoa_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-csoa/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-csoa/app/bioconductor-csoa_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-ctsv", + "server_name": "biosci_bioconductor_ctsv", + "tool_name": "bioconductor-ctsv", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-ctsv/app/bioconductor-ctsv_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-ctsv/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-ctsv/app/bioconductor-ctsv_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-curatedatlasqueryr", + "server_name": "biosci_bioconductor_curatedatlasqueryr", + "tool_name": "bioconductor-curatedatlasqueryr", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-curatedatlasqueryr/app/bioconductor-curatedatlasqueryr_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-curatedatlasqueryr/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-curatedatlasqueryr/app/bioconductor-curatedatlasqueryr_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-dada2", + "server_name": "biosci_bioconductor_dada2", + "tool_name": "bioconductor-dada2", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-dada2/app/bioconductor-dada2_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-dada2/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-dada2/app/bioconductor-dada2_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-data-packages", + "server_name": "biosci_bioconductor_data_packages", + "tool_name": "bioconductor-data-packages", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-data-packages/app/bioconductor-data-packages_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-data-packages/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-data-packages/app/bioconductor-data-packages_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-decipher", + "server_name": "biosci_bioconductor_decipher", + "tool_name": "bioconductor-decipher", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-decipher/app/bioconductor-decipher_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-decipher/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-decipher/app/bioconductor-decipher_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-decontam", + "server_name": "biosci_bioconductor_decontam", + "tool_name": "bioconductor-decontam", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-decontam/app/bioconductor-decontam_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-decontam/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-decontam/app/bioconductor-decontam_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-decontx", + "server_name": "biosci_bioconductor_decontx", + "tool_name": "bioconductor-decontx", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-decontx/app/bioconductor-decontx_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-decontx/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-decontx/app/bioconductor-decontx_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-deconvobuddies", + "server_name": "biosci_bioconductor_deconvobuddies", + "tool_name": "bioconductor-deconvobuddies", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-deconvobuddies/app/bioconductor-deconvobuddies_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-deconvobuddies/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-deconvobuddies/app/bioconductor-deconvobuddies_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-delayedarray", + "server_name": "biosci_bioconductor_delayedarray", + "tool_name": "bioconductor-delayedarray", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-delayedarray/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-delayedmatrixstats", + "server_name": "biosci_bioconductor_delayedmatrixstats", + "tool_name": "bioconductor-delayedmatrixstats", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-delayedmatrixstats/app/bioconductor-delayedmatrixstats_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-delayedmatrixstats/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-delayedmatrixstats/app/bioconductor-delayedmatrixstats_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-deseq2", + "server_name": "biosci_bioconductor_deseq2", + "tool_name": "bioconductor-deseq2", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-deseq2/app/bioconductor-deseq2_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-deseq2/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-deseq2/app/bioconductor-deseq2_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-despace", + "server_name": "biosci_bioconductor_despace", + "tool_name": "bioconductor-despace", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-despace/app/bioconductor-despace_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-despace/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-despace/app/bioconductor-despace_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-diffbind", + "server_name": "biosci_bioconductor_diffbind", + "tool_name": "bioconductor-diffbind", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-diffbind/app/bioconductor-diffbind_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-diffbind/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-diffbind/app/bioconductor-diffbind_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-dino", + "server_name": "biosci_bioconductor_dino", + "tool_name": "bioconductor-dino", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-dino/app/bioconductor-dino_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-dino/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-dino/app/bioconductor-dino_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-dirichletmultinomial", + "server_name": "biosci_bioconductor_dirichletmultinomial", + "tool_name": "bioconductor-dirichletmultinomial", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-dirichletmultinomial/app/bioconductor-dirichletmultinomial_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-dirichletmultinomial/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-dirichletmultinomial/app/bioconductor-dirichletmultinomial_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-dnacopy", + "server_name": "biosci_bioconductor_dnacopy", + "tool_name": "bioconductor-dnacopy", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-dnacopy/app/bioconductor-dnacopy_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-dnacopy/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-dnacopy/app/bioconductor-dnacopy_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-dose", + "server_name": "biosci_bioconductor_dose", + "tool_name": "bioconductor-dose", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-dose/app/bioconductor-dose_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-dose/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-dose/app/bioconductor-dose_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-ebseq", + "server_name": "biosci_bioconductor_ebseq", + "tool_name": "bioconductor-ebseq", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-ebseq/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-edger", + "server_name": "biosci_bioconductor_edger", + "tool_name": "bioconductor-edger", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-edger/app/bioconductor-edger_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-edger/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-edger/app/bioconductor-edger_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-ensembldb", + "server_name": "biosci_bioconductor_ensembldb", + "tool_name": "bioconductor-ensembldb", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-ensembldb/app/bioconductor-ensembldb_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-ensembldb/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-ensembldb/app/bioconductor-ensembldb_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-erma", + "server_name": "biosci_bioconductor_erma", + "tool_name": "bioconductor-erma", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-erma/app/bioconductor-erma_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-erma/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-erma/app/bioconductor-erma_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-escher", + "server_name": "biosci_bioconductor_escher", + "tool_name": "bioconductor-escher", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-escher/app/bioconductor-escher_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-escher/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-escher/app/bioconductor-escher_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-experimentsubset", + "server_name": "biosci_bioconductor_experimentsubset", + "tool_name": "bioconductor-experimentsubset", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-experimentsubset/app/bioconductor-experimentsubset_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-experimentsubset/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-experimentsubset/app/bioconductor-experimentsubset_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-fgsea", + "server_name": "biosci_bioconductor_fgsea", + "tool_name": "bioconductor-fgsea", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-fgsea/app/bioconductor-fgsea_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-fgsea/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-fgsea/app/bioconductor-fgsea_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-genefilter", + "server_name": "biosci_bioconductor_genefilter", + "tool_name": "bioconductor-genefilter", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-genefilter/app/bioconductor-genefilter_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-genefilter/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-genefilter/app/bioconductor-genefilter_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-geneplotter", + "server_name": "biosci_bioconductor_geneplotter", + "tool_name": "bioconductor-geneplotter", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-geneplotter/app/bioconductor-geneplotter_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-geneplotter/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-geneplotter/app/bioconductor-geneplotter_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-genomeinfodb", + "server_name": "biosci_bioconductor_genomeinfodb", + "tool_name": "bioconductor-genomeinfodb", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-genomeinfodb/app/bioconductor-genomeinfodb_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-genomeinfodb/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-genomeinfodb/app/bioconductor-genomeinfodb_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-genomeinfodbdata", + "server_name": "biosci_bioconductor_genomeinfodbdata", + "tool_name": "bioconductor-genomeinfodbdata", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-genomeinfodbdata/app/bioconductor-genomeinfodbdata_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-genomeinfodbdata/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-genomeinfodbdata/app/bioconductor-genomeinfodbdata_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-genomicalignments", + "server_name": "biosci_bioconductor_genomicalignments", + "tool_name": "bioconductor-genomicalignments", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-genomicalignments/app/bioconductor-genomicalignments_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-genomicalignments/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-genomicalignments/app/bioconductor-genomicalignments_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-genomicfeatures", + "server_name": "biosci_bioconductor_genomicfeatures", + "tool_name": "bioconductor-genomicfeatures", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-genomicfeatures/app/bioconductor-genomicfeatures_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-genomicfeatures/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-genomicfeatures/app/bioconductor-genomicfeatures_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-genomicranges", + "server_name": "biosci_bioconductor_genomicranges", + "tool_name": "bioconductor-genomicranges", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-genomicranges/app/bioconductor-genomicranges_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-genomicranges/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-genomicranges/app/bioconductor-genomicranges_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-geomxtools", + "server_name": "biosci_bioconductor_geomxtools", + "tool_name": "bioconductor-geomxtools", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-geomxtools/app/bioconductor-geomxtools_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-geomxtools/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-geomxtools/app/bioconductor-geomxtools_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-ggsc", + "server_name": "biosci_bioconductor_ggsc", + "tool_name": "bioconductor-ggsc", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-ggsc/app/bioconductor-ggsc_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-ggsc/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-ggsc/app/bioconductor-ggsc_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-ggspavis", + "server_name": "biosci_bioconductor_ggspavis", + "tool_name": "bioconductor-ggspavis", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-ggspavis/app/bioconductor-ggspavis_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-ggspavis/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-ggspavis/app/bioconductor-ggspavis_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-ggtree", + "server_name": "biosci_bioconductor_ggtree", + "tool_name": "bioconductor-ggtree", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-ggtree/app/bioconductor-ggtree_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-ggtree/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-ggtree/app/bioconductor-ggtree_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-glmgampoi", + "server_name": "biosci_bioconductor_glmgampoi", + "tool_name": "bioconductor-glmgampoi", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-glmgampoi/app/bioconductor-glmgampoi_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-glmgampoi/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-glmgampoi/app/bioconductor-glmgampoi_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-go.db", + "server_name": "biosci_bioconductor_go_db", + "tool_name": "bioconductor-go.db", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-go.db/app/bioconductor-go.db_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-go.db/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-go.db/app/bioconductor-go.db_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-gosemsim", + "server_name": "biosci_bioconductor_gosemsim", + "tool_name": "bioconductor-gosemsim", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-gosemsim/app/bioconductor-gosemsim_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-gosemsim/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-gosemsim/app/bioconductor-gosemsim_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-graph", + "server_name": "biosci_bioconductor_graph", + "tool_name": "bioconductor-graph", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-graph/app/bioconductor-graph_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-graph/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-graph/app/bioconductor-graph_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-hcatonsildata", + "server_name": "biosci_bioconductor_hcatonsildata", + "tool_name": "bioconductor-hcatonsildata", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-hcatonsildata/app/bioconductor-hcatonsildata_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-hcatonsildata/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-hcatonsildata/app/bioconductor-hcatonsildata_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-hdf5array", + "server_name": "biosci_bioconductor_hdf5array", + "tool_name": "bioconductor-hdf5array", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-hdf5array/app/bioconductor-hdf5array_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-hdf5array/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-hdf5array/app/bioconductor-hdf5array_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-hoodscanr", + "server_name": "biosci_bioconductor_hoodscanr", + "tool_name": "bioconductor-hoodscanr", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-hoodscanr/app/bioconductor-hoodscanr_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-hoodscanr/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-hoodscanr/app/bioconductor-hoodscanr_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-humanhippocampus2024", + "server_name": "biosci_bioconductor_humanhippocampus2024", + "tool_name": "bioconductor-humanhippocampus2024", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-humanhippocampus2024/app/bioconductor-humanhippocampus2024_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-humanhippocampus2024/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-humanhippocampus2024/app/bioconductor-humanhippocampus2024_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-imcdatasets", + "server_name": "biosci_bioconductor_imcdatasets", + "tool_name": "bioconductor-imcdatasets", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-imcdatasets/app/bioconductor-imcdatasets_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-imcdatasets/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-imcdatasets/app/bioconductor-imcdatasets_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-imcrtools", + "server_name": "biosci_bioconductor_imcrtools", + "tool_name": "bioconductor-imcrtools", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-imcrtools/app/bioconductor-imcrtools_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-imcrtools/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-imcrtools/app/bioconductor-imcrtools_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-impute", + "server_name": "biosci_bioconductor_impute", + "tool_name": "bioconductor-impute", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-impute/app/bioconductor-impute_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-impute/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-impute/app/bioconductor-impute_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-interactivedisplaybase", + "server_name": "biosci_bioconductor_interactivedisplaybase", + "tool_name": "bioconductor-interactivedisplaybase", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-interactivedisplaybase/app/bioconductor-interactivedisplaybase_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-interactivedisplaybase/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-interactivedisplaybase/app/bioconductor-interactivedisplaybase_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-iranges", + "server_name": "biosci_bioconductor_iranges", + "tool_name": "bioconductor-iranges", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-iranges/app/bioconductor-iranges_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-iranges/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-iranges/app/bioconductor-iranges_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-irisfgm", + "server_name": "biosci_bioconductor_irisfgm", + "tool_name": "bioconductor-irisfgm", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-irisfgm/app/bioconductor-irisfgm_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-irisfgm/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-irisfgm/app/bioconductor-irisfgm_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-jazzpanda", + "server_name": "biosci_bioconductor_jazzpanda", + "tool_name": "bioconductor-jazzpanda", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-jazzpanda/app/bioconductor-jazzpanda_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-jazzpanda/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-jazzpanda/app/bioconductor-jazzpanda_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-keggrest", + "server_name": "biosci_bioconductor_keggrest", + "tool_name": "bioconductor-keggrest", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-keggrest/app/bioconductor-keggrest_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-keggrest/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-keggrest/app/bioconductor-keggrest_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-limma", + "server_name": "biosci_bioconductor_limma", + "tool_name": "bioconductor-limma", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-limma/app/bioconductor-limma_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-limma/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-limma/app/bioconductor-limma_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-lisaclust", + "server_name": "biosci_bioconductor_lisaclust", + "tool_name": "bioconductor-lisaclust", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-lisaclust/app/bioconductor-lisaclust_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-lisaclust/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-lisaclust/app/bioconductor-lisaclust_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-mastr", + "server_name": "biosci_bioconductor_mastr", + "tool_name": "bioconductor-mastr", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-mastr/app/bioconductor-mastr_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-mastr/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-mastr/app/bioconductor-mastr_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-matrixgenerics", + "server_name": "biosci_bioconductor_matrixgenerics", + "tool_name": "bioconductor-matrixgenerics", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-matrixgenerics/app/bioconductor-matrixgenerics_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-matrixgenerics/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-matrixgenerics/app/bioconductor-matrixgenerics_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-merfishdata", + "server_name": "biosci_bioconductor_merfishdata", + "tool_name": "bioconductor-merfishdata", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-merfishdata/app/bioconductor-merfishdata_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-merfishdata/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-merfishdata/app/bioconductor-merfishdata_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-metapod", + "server_name": "biosci_bioconductor_metapod", + "tool_name": "bioconductor-metapod", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-metapod/app/bioconductor-metapod_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-metapod/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-metapod/app/bioconductor-metapod_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-mia", + "server_name": "biosci_bioconductor_mia", + "tool_name": "bioconductor-mia", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-mia/app/bioconductor-mia_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-mia/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-mia/app/bioconductor-mia_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-moleculeexperiment", + "server_name": "biosci_bioconductor_moleculeexperiment", + "tool_name": "bioconductor-moleculeexperiment", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-moleculeexperiment/app/bioconductor-moleculeexperiment_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-moleculeexperiment/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-moleculeexperiment/app/bioconductor-moleculeexperiment_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-mousegastrulationdata", + "server_name": "biosci_bioconductor_mousegastrulationdata", + "tool_name": "bioconductor-mousegastrulationdata", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-mousegastrulationdata/app/bioconductor-mousegastrulationdata_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-mousegastrulationdata/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-mousegastrulationdata/app/bioconductor-mousegastrulationdata_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-mspurity", + "server_name": "biosci_bioconductor_mspurity", + "tool_name": "bioconductor-mspurity", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-mspurity/app/bioconductor-mspurity_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-mspurity/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-mspurity/app/bioconductor-mspurity_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-multiassayexperiment", + "server_name": "biosci_bioconductor_multiassayexperiment", + "tool_name": "bioconductor-multiassayexperiment", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-multiassayexperiment/app/bioconductor-multiassayexperiment_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-multiassayexperiment/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-multiassayexperiment/app/bioconductor-multiassayexperiment_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-multtest", + "server_name": "biosci_bioconductor_multtest", + "tool_name": "bioconductor-multtest", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-multtest/app/bioconductor-multtest_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-multtest/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-multtest/app/bioconductor-multtest_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-mzr", + "server_name": "biosci_bioconductor_mzr", + "tool_name": "bioconductor-mzr", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-mzr/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-nnsvg", + "server_name": "biosci_bioconductor_nnsvg", + "tool_name": "bioconductor-nnsvg", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-nnsvg/app/bioconductor-nnsvg_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-nnsvg/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-nnsvg/app/bioconductor-nnsvg_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-noiseq", + "server_name": "biosci_bioconductor_noiseq", + "tool_name": "bioconductor-noiseq", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-noiseq/app/bioconductor-noiseq_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-noiseq/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-noiseq/app/bioconductor-noiseq_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-orfhunter", + "server_name": "biosci_bioconductor_orfhunter", + "tool_name": "bioconductor-orfhunter", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-orfhunter/app/bioconductor-orfhunter_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-orfhunter/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-orfhunter/app/bioconductor-orfhunter_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-org.ce.eg.db", + "server_name": "biosci_bioconductor_org_ce_eg_db", + "tool_name": "bioconductor-org.ce.eg.db", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-org.ce.eg.db/app/bioconductor-org.ce.eg.db_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-org.ce.eg.db/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-org.ce.eg.db/app/bioconductor-org.ce.eg.db_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-org.hs.eg.db", + "server_name": "biosci_bioconductor_org_hs_eg_db", + "tool_name": "bioconductor-org.hs.eg.db", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-org.hs.eg.db/app/bioconductor-org.hs.eg.db_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-org.hs.eg.db/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-org.hs.eg.db/app/bioconductor-org.hs.eg.db_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-org.mm.eg.db", + "server_name": "biosci_bioconductor_org_mm_eg_db", + "tool_name": "bioconductor-org.mm.eg.db", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-org.mm.eg.db/app/bioconductor-org.mm.eg.db_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-org.mm.eg.db/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-org.mm.eg.db/app/bioconductor-org.mm.eg.db_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-partcnv", + "server_name": "biosci_bioconductor_partcnv", + "tool_name": "bioconductor-partcnv", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-partcnv/app/bioconductor-partcnv_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-partcnv/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-partcnv/app/bioconductor-partcnv_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-phyloseq", + "server_name": "biosci_bioconductor_phyloseq", + "tool_name": "bioconductor-phyloseq", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-phyloseq/app/bioconductor-phyloseq_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-phyloseq/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-phyloseq/app/bioconductor-phyloseq_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-pipecomp", + "server_name": "biosci_bioconductor_pipecomp", + "tool_name": "bioconductor-pipecomp", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-pipecomp/app/bioconductor-pipecomp_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-pipecomp/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-pipecomp/app/bioconductor-pipecomp_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-poem", + "server_name": "biosci_bioconductor_poem", + "tool_name": "bioconductor-poem", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-poem/app/bioconductor-poem_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-poem/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-poem/app/bioconductor-poem_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-preprocesscore", + "server_name": "biosci_bioconductor_preprocesscore", + "tool_name": "bioconductor-preprocesscore", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-preprocesscore/app/bioconductor-preprocesscore_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-preprocesscore/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-preprocesscore/app/bioconductor-preprocesscore_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-protgenerics", + "server_name": "biosci_bioconductor_protgenerics", + "tool_name": "bioconductor-protgenerics", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-protgenerics/app/bioconductor-protgenerics_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-protgenerics/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-protgenerics/app/bioconductor-protgenerics_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-qvalue", + "server_name": "biosci_bioconductor_qvalue", + "tool_name": "bioconductor-qvalue", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-qvalue/app/bioconductor-qvalue_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-qvalue/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-qvalue/app/bioconductor-qvalue_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-rbgl", + "server_name": "biosci_bioconductor_rbgl", + "tool_name": "bioconductor-rbgl", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-rbgl/app/bioconductor-rbgl_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-rbgl/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-rbgl/app/bioconductor-rbgl_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-reactomegsa.data", + "server_name": "biosci_bioconductor_reactomegsa_data", + "tool_name": "bioconductor-reactomegsa.data", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-reactomegsa.data/app/bioconductor-reactomegsa.data_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-reactomegsa.data/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-reactomegsa.data/app/bioconductor-reactomegsa.data_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-regionalst", + "server_name": "biosci_bioconductor_regionalst", + "tool_name": "bioconductor-regionalst", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-regionalst/app/bioconductor-regionalst_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-regionalst/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-regionalst/app/bioconductor-regionalst_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-rgraphviz", + "server_name": "biosci_bioconductor_rgraphviz", + "tool_name": "bioconductor-rgraphviz", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-rgraphviz/app/bioconductor-rgraphviz_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-rgraphviz/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-rgraphviz/app/bioconductor-rgraphviz_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-rhdf5", + "server_name": "biosci_bioconductor_rhdf5", + "tool_name": "bioconductor-rhdf5", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-rhdf5/app/bioconductor-rhdf5_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-rhdf5/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-rhdf5/app/bioconductor-rhdf5_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-rhdf5filters", + "server_name": "biosci_bioconductor_rhdf5filters", + "tool_name": "bioconductor-rhdf5filters", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-rhdf5filters/app/bioconductor-rhdf5filters_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-rhdf5filters/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-rhdf5filters/app/bioconductor-rhdf5filters_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-rhdf5lib", + "server_name": "biosci_bioconductor_rhdf5lib", + "tool_name": "bioconductor-rhdf5lib", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-rhdf5lib/app/bioconductor-rhdf5lib_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-rhdf5lib/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-rhdf5lib/app/bioconductor-rhdf5lib_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-rhtslib", + "server_name": "biosci_bioconductor_rhtslib", + "tool_name": "bioconductor-rhtslib", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-rhtslib/app/bioconductor-rhtslib_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-rhtslib/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-rhtslib/app/bioconductor-rhtslib_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-rsamtools", + "server_name": "biosci_bioconductor_rsamtools", + "tool_name": "bioconductor-rsamtools", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-rsamtools/app/bioconductor-rsamtools_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-rsamtools/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-rsamtools/app/bioconductor-rsamtools_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-rsubread", + "server_name": "biosci_bioconductor_rsubread", + "tool_name": "bioconductor-rsubread", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-rsubread/app/bioconductor-rsubread_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-rsubread/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-rsubread/app/bioconductor-rsubread_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-rtracklayer", + "server_name": "biosci_bioconductor_rtracklayer", + "tool_name": "bioconductor-rtracklayer", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-rtracklayer/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-s4arrays", + "server_name": "biosci_bioconductor_s4arrays", + "tool_name": "bioconductor-s4arrays", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-s4arrays/app/bioconductor-s4arrays_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-s4arrays/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-s4arrays/app/bioconductor-s4arrays_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-s4vectors", + "server_name": "biosci_bioconductor_s4vectors", + "tool_name": "bioconductor-s4vectors", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-s4vectors/app/bioconductor-s4vectors_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-s4vectors/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-s4vectors/app/bioconductor-s4vectors_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scaledmatrix", + "server_name": "biosci_bioconductor_scaledmatrix", + "tool_name": "bioconductor-scaledmatrix", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scaledmatrix/app/bioconductor-scaledmatrix_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scaledmatrix/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scaledmatrix/app/bioconductor-scaledmatrix_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scalign", + "server_name": "biosci_bioconductor_scalign", + "tool_name": "bioconductor-scalign", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scalign/app/bioconductor-scalign_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scalign/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scalign/app/bioconductor-scalign_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scannotatr", + "server_name": "biosci_bioconductor_scannotatr", + "tool_name": "bioconductor-scannotatr", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scannotatr/app/bioconductor-scannotatr_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scannotatr/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scannotatr/app/bioconductor-scannotatr_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scarray.sat", + "server_name": "biosci_bioconductor_scarray_sat", + "tool_name": "bioconductor-scarray.sat", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scarray.sat/app/bioconductor-scarray.sat_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scarray.sat/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scarray.sat/app/bioconductor-scarray.sat_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scater", + "server_name": "biosci_bioconductor_scater", + "tool_name": "bioconductor-scater", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scater/app/bioconductor-scater_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scater/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scater/app/bioconductor-scater_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scbubbletree", + "server_name": "biosci_bioconductor_scbubbletree", + "tool_name": "bioconductor-scbubbletree", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scbubbletree/app/bioconductor-scbubbletree_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scbubbletree/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scbubbletree/app/bioconductor-scbubbletree_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scclassifr", + "server_name": "biosci_bioconductor_scclassifr", + "tool_name": "bioconductor-scclassifr", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scclassifr/app/bioconductor-scclassifr_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scclassifr/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scclassifr/app/bioconductor-scclassifr_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scdotplot", + "server_name": "biosci_bioconductor_scdotplot", + "tool_name": "bioconductor-scdotplot", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scdotplot/app/bioconductor-scdotplot_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scdotplot/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scdotplot/app/bioconductor-scdotplot_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scfeatures", + "server_name": "biosci_bioconductor_scfeatures", + "tool_name": "bioconductor-scfeatures", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scfeatures/app/bioconductor-scfeatures_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scfeatures/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scfeatures/app/bioconductor-scfeatures_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scider", + "server_name": "biosci_bioconductor_scider", + "tool_name": "bioconductor-scider", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scider/app/bioconductor-scider_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scider/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scider/app/bioconductor-scider_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scqtltools", + "server_name": "biosci_bioconductor_scqtltools", + "tool_name": "bioconductor-scqtltools", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scqtltools/app/bioconductor-scqtltools_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scqtltools/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scqtltools/app/bioconductor-scqtltools_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scran", + "server_name": "biosci_bioconductor_scran", + "tool_name": "bioconductor-scran", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scran/app/bioconductor-scran_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scran/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scran/app/bioconductor-scran_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scrnaseqapp", + "server_name": "biosci_bioconductor_scrnaseqapp", + "tool_name": "bioconductor-scrnaseqapp", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scrnaseqapp/app/bioconductor-scrnaseqapp_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scrnaseqapp/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scrnaseqapp/app/bioconductor-scrnaseqapp_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-sctreeviz", + "server_name": "biosci_bioconductor_sctreeviz", + "tool_name": "bioconductor-sctreeviz", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-sctreeviz/app/bioconductor-sctreeviz_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-sctreeviz/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-sctreeviz/app/bioconductor-sctreeviz_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scuttle", + "server_name": "biosci_bioconductor_scuttle", + "tool_name": "bioconductor-scuttle", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scuttle/app/bioconductor-scuttle_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scuttle/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scuttle/app/bioconductor-scuttle_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scvir", + "server_name": "biosci_bioconductor_scvir", + "tool_name": "bioconductor-scvir", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scvir/app/bioconductor-scvir_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scvir/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-scvir/app/bioconductor-scvir_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-seraster", + "server_name": "biosci_bioconductor_seraster", + "tool_name": "bioconductor-seraster", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-seraster/app/bioconductor-seraster_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-seraster/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-seraster/app/bioconductor-seraster_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-shortread", + "server_name": "biosci_bioconductor_shortread", + "tool_name": "bioconductor-shortread", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-shortread/app/bioconductor-shortread_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-shortread/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-shortread/app/bioconductor-shortread_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-signifinder", + "server_name": "biosci_bioconductor_signifinder", + "tool_name": "bioconductor-signifinder", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-signifinder/app/bioconductor-signifinder_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-signifinder/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-signifinder/app/bioconductor-signifinder_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-singlecellexperiment", + "server_name": "biosci_bioconductor_singlecellexperiment", + "tool_name": "bioconductor-singlecellexperiment", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-singlecellexperiment/app/bioconductor-singlecellexperiment_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-singlecellexperiment/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-singlecellexperiment/app/bioconductor-singlecellexperiment_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-singlecelltk", + "server_name": "biosci_bioconductor_singlecelltk", + "tool_name": "bioconductor-singlecelltk", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-singlecelltk/app/bioconductor-singlecelltk_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-singlecelltk/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-singlecelltk/app/bioconductor-singlecelltk_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-smoothclust", + "server_name": "biosci_bioconductor_smoothclust", + "tool_name": "bioconductor-smoothclust", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-smoothclust/app/bioconductor-smoothclust_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-smoothclust/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-smoothclust/app/bioconductor-smoothclust_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-smoppix", + "server_name": "biosci_bioconductor_smoppix", + "tool_name": "bioconductor-smoppix", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-smoppix/app/bioconductor-smoppix_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-smoppix/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-smoppix/app/bioconductor-smoppix_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-sosta", + "server_name": "biosci_bioconductor_sosta", + "tool_name": "bioconductor-sosta", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-sosta/app/bioconductor-sosta_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-sosta/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-sosta/app/bioconductor-sosta_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spacetrooper", + "server_name": "biosci_bioconductor_spacetrooper", + "tool_name": "bioconductor-spacetrooper", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spacetrooper/app/bioconductor-spacetrooper_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spacetrooper/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spacetrooper/app/bioconductor-spacetrooper_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spacexr", + "server_name": "biosci_bioconductor_spacexr", + "tool_name": "bioconductor-spacexr", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spacexr/app/bioconductor-spacexr_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spacexr/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spacexr/app/bioconductor-spacexr_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spanorm", + "server_name": "biosci_bioconductor_spanorm", + "tool_name": "bioconductor-spanorm", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spanorm/app/bioconductor-spanorm_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spanorm/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spanorm/app/bioconductor-spanorm_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spari", + "server_name": "biosci_bioconductor_spari", + "tool_name": "bioconductor-spari", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spari/app/bioconductor-spari_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spari/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spari/app/bioconductor-spari_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-sparsearray", + "server_name": "biosci_bioconductor_sparsearray", + "tool_name": "bioconductor-sparsearray", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-sparsearray/app/bioconductor-sparsearray_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-sparsearray/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-sparsearray/app/bioconductor-sparsearray_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-sparsematrixstats", + "server_name": "biosci_bioconductor_sparsematrixstats", + "tool_name": "bioconductor-sparsematrixstats", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-sparsematrixstats/app/bioconductor-sparsematrixstats_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-sparsematrixstats/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-sparsematrixstats/app/bioconductor-sparsematrixstats_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spasim", + "server_name": "biosci_bioconductor_spasim", + "tool_name": "bioconductor-spasim", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spasim/app/bioconductor-spasim_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spasim/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spasim/app/bioconductor-spasim_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spatialdatasets", + "server_name": "biosci_bioconductor_spatialdatasets", + "tool_name": "bioconductor-spatialdatasets", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spatialdatasets/app/bioconductor-spatialdatasets_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spatialdatasets/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spatialdatasets/app/bioconductor-spatialdatasets_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spatialde", + "server_name": "biosci_bioconductor_spatialde", + "tool_name": "bioconductor-spatialde", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spatialde/app/bioconductor-spatialde_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spatialde/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spatialde/app/bioconductor-spatialde_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spatialdmelxsim", + "server_name": "biosci_bioconductor_spatialdmelxsim", + "tool_name": "bioconductor-spatialdmelxsim", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spatialdmelxsim/app/bioconductor-spatialdmelxsim_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spatialdmelxsim/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spatialdmelxsim/app/bioconductor-spatialdmelxsim_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spatialexperimentio", + "server_name": "biosci_bioconductor_spatialexperimentio", + "tool_name": "bioconductor-spatialexperimentio", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spatialexperimentio/app/bioconductor-spatialexperimentio_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spatialexperimentio/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spatialexperimentio/app/bioconductor-spatialexperimentio_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spatialfda", + "server_name": "biosci_bioconductor_spatialfda", + "tool_name": "bioconductor-spatialfda", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spatialfda/app/bioconductor-spatialfda_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spatialfda/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spatialfda/app/bioconductor-spatialfda_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spatialfeatureexperiment", + "server_name": "biosci_bioconductor_spatialfeatureexperiment", + "tool_name": "bioconductor-spatialfeatureexperiment", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spatialfeatureexperiment/app/bioconductor-spatialfeatureexperiment_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spatialfeatureexperiment/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spatialfeatureexperiment/app/bioconductor-spatialfeatureexperiment_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spatiallibd", + "server_name": "biosci_bioconductor_spatiallibd", + "tool_name": "bioconductor-spatiallibd", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spatiallibd/app/bioconductor-spatiallibd_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spatiallibd/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spatiallibd/app/bioconductor-spatiallibd_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spatialomicsoverlay", + "server_name": "biosci_bioconductor_spatialomicsoverlay", + "tool_name": "bioconductor-spatialomicsoverlay", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spatialomicsoverlay/app/bioconductor-spatialomicsoverlay_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spatialomicsoverlay/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spatialomicsoverlay/app/bioconductor-spatialomicsoverlay_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spatialsimgp", + "server_name": "biosci_bioconductor_spatialsimgp", + "tool_name": "bioconductor-spatialsimgp", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spatialsimgp/app/bioconductor-spatialsimgp_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spatialsimgp/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spatialsimgp/app/bioconductor-spatialsimgp_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-speckle", + "server_name": "biosci_bioconductor_speckle", + "tool_name": "bioconductor-speckle", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-speckle/app/bioconductor-speckle_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-speckle/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-speckle/app/bioconductor-speckle_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spiat", + "server_name": "biosci_bioconductor_spiat", + "tool_name": "bioconductor-spiat", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spiat/app/bioconductor-spiat_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spiat/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spiat/app/bioconductor-spiat_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spicyr", + "server_name": "biosci_bioconductor_spicyr", + "tool_name": "bioconductor-spicyr", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spicyr/app/bioconductor-spicyr_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spicyr/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spicyr/app/bioconductor-spicyr_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spoon", + "server_name": "biosci_bioconductor_spoon", + "tool_name": "bioconductor-spoon", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spoon/app/bioconductor-spoon_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spoon/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spoon/app/bioconductor-spoon_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spotclean", + "server_name": "biosci_bioconductor_spotclean", + "tool_name": "bioconductor-spotclean", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spotclean/app/bioconductor-spotclean_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spotclean/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spotclean/app/bioconductor-spotclean_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spotsweeper", + "server_name": "biosci_bioconductor_spotsweeper", + "tool_name": "bioconductor-spotsweeper", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spotsweeper/app/bioconductor-spotsweeper_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spotsweeper/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-spotsweeper/app/bioconductor-spotsweeper_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-standr", + "server_name": "biosci_bioconductor_standr", + "tool_name": "bioconductor-standr", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-standr/app/bioconductor-standr_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-standr/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-standr/app/bioconductor-standr_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-statial", + "server_name": "biosci_bioconductor_statial", + "tool_name": "bioconductor-statial", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-statial/app/bioconductor-statial_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-statial/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-statial/app/bioconductor-statial_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-stexampledata", + "server_name": "biosci_bioconductor_stexampledata", + "tool_name": "bioconductor-stexampledata", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-stexampledata/app/bioconductor-stexampledata_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-stexampledata/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-stexampledata/app/bioconductor-stexampledata_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-stjoincount", + "server_name": "biosci_bioconductor_stjoincount", + "tool_name": "bioconductor-stjoincount", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-stjoincount/app/bioconductor-stjoincount_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-stjoincount/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-stjoincount/app/bioconductor-stjoincount_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-stpipe", + "server_name": "biosci_bioconductor_stpipe", + "tool_name": "bioconductor-stpipe", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-stpipe/app/bioconductor-stpipe_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-stpipe/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-stpipe/app/bioconductor-stpipe_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-subcellularspatialdata", + "server_name": "biosci_bioconductor_subcellularspatialdata", + "tool_name": "bioconductor-subcellularspatialdata", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-subcellularspatialdata/app/bioconductor-subcellularspatialdata_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-subcellularspatialdata/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-subcellularspatialdata/app/bioconductor-subcellularspatialdata_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-summarizedexperiment", + "server_name": "biosci_bioconductor_summarizedexperiment", + "tool_name": "bioconductor-summarizedexperiment", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-summarizedexperiment/app/bioconductor-summarizedexperiment_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-summarizedexperiment/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-summarizedexperiment/app/bioconductor-summarizedexperiment_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-svp", + "server_name": "biosci_bioconductor_svp", + "tool_name": "bioconductor-svp", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-svp/app/bioconductor-svp_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-svp/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-svp/app/bioconductor-svp_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-synergyfinder", + "server_name": "biosci_bioconductor_synergyfinder", + "tool_name": "bioconductor-synergyfinder", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-synergyfinder/app/bioconductor-synergyfinder_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-synergyfinder/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-synergyfinder/app/bioconductor-synergyfinder_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-tenxvisiumdata", + "server_name": "biosci_bioconductor_tenxvisiumdata", + "tool_name": "bioconductor-tenxvisiumdata", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-tenxvisiumdata/app/bioconductor-tenxvisiumdata_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-tenxvisiumdata/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-tenxvisiumdata/app/bioconductor-tenxvisiumdata_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-tenxxeniumdata", + "server_name": "biosci_bioconductor_tenxxeniumdata", + "tool_name": "bioconductor-tenxxeniumdata", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-tenxxeniumdata/app/bioconductor-tenxxeniumdata_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-tenxxeniumdata/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-tenxxeniumdata/app/bioconductor-tenxxeniumdata_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-tidyomics", + "server_name": "biosci_bioconductor_tidyomics", + "tool_name": "bioconductor-tidyomics", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-tidyomics/app/bioconductor-tidyomics_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-tidyomics/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-tidyomics/app/bioconductor-tidyomics_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-tidyspatialexperiment", + "server_name": "biosci_bioconductor_tidyspatialexperiment", + "tool_name": "bioconductor-tidyspatialexperiment", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-tidyspatialexperiment/app/bioconductor-tidyspatialexperiment_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-tidyspatialexperiment/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-tidyspatialexperiment/app/bioconductor-tidyspatialexperiment_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-tpsvg", + "server_name": "biosci_bioconductor_tpsvg", + "tool_name": "bioconductor-tpsvg", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-tpsvg/app/bioconductor-tpsvg_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-tpsvg/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-tpsvg/app/bioconductor-tpsvg_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-treeio", + "server_name": "biosci_bioconductor_treeio", + "tool_name": "bioconductor-treeio", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-treeio/app/bioconductor-treeio_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-treeio/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-treeio/app/bioconductor-treeio_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-treesummarizedexperiment", + "server_name": "biosci_bioconductor_treesummarizedexperiment", + "tool_name": "bioconductor-treesummarizedexperiment", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-treesummarizedexperiment/app/bioconductor-treesummarizedexperiment_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-treesummarizedexperiment/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-treesummarizedexperiment/app/bioconductor-treesummarizedexperiment_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-tximport", + "server_name": "biosci_bioconductor_tximport", + "tool_name": "bioconductor-tximport", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-tximport/app/bioconductor-tximport_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-tximport/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-tximport/app/bioconductor-tximport_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-variantannotation", + "server_name": "biosci_bioconductor_variantannotation", + "tool_name": "bioconductor-variantannotation", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-variantannotation/app/bioconductor-variantannotation_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-variantannotation/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-variantannotation/app/bioconductor-variantannotation_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-vectrapolarisdata", + "server_name": "biosci_bioconductor_vectrapolarisdata", + "tool_name": "bioconductor-vectrapolarisdata", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-vectrapolarisdata/app/bioconductor-vectrapolarisdata_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-vectrapolarisdata/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-vectrapolarisdata/app/bioconductor-vectrapolarisdata_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-visiumio", + "server_name": "biosci_bioconductor_visiumio", + "tool_name": "bioconductor-visiumio", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-visiumio/app/bioconductor-visiumio_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-visiumio/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-visiumio/app/bioconductor-visiumio_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-visiumstitched", + "server_name": "biosci_bioconductor_visiumstitched", + "tool_name": "bioconductor-visiumstitched", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-visiumstitched/app/bioconductor-visiumstitched_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-visiumstitched/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-visiumstitched/app/bioconductor-visiumstitched_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-voyager", + "server_name": "biosci_bioconductor_voyager", + "tool_name": "bioconductor-voyager", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-voyager/app/bioconductor-voyager_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-voyager/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-voyager/app/bioconductor-voyager_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-weberdivechalcdata", + "server_name": "biosci_bioconductor_weberdivechalcdata", + "tool_name": "bioconductor-weberdivechalcdata", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-weberdivechalcdata/app/bioconductor-weberdivechalcdata_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-weberdivechalcdata/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-weberdivechalcdata/app/bioconductor-weberdivechalcdata_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-xcms", + "server_name": "biosci_bioconductor_xcms", + "tool_name": "bioconductor-xcms", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-xcms/app/bioconductor-xcms_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-xcms/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-xcms/app/bioconductor-xcms_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-xeniumio", + "server_name": "biosci_bioconductor_xeniumio", + "tool_name": "bioconductor-xeniumio", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-xeniumio/app/bioconductor-xeniumio_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-xeniumio/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-xeniumio/app/bioconductor-xeniumio_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-xenlite", + "server_name": "biosci_bioconductor_xenlite", + "tool_name": "bioconductor-xenlite", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-xenlite/app/bioconductor-xenlite_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-xenlite/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-xenlite/app/bioconductor-xenlite_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-xvector", + "server_name": "biosci_bioconductor_xvector", + "tool_name": "bioconductor-xvector", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-xvector/app/bioconductor-xvector_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-xvector/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-xvector/app/bioconductor-xvector_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-zlibbioc", + "server_name": "biosci_bioconductor_zlibbioc", + "tool_name": "bioconductor-zlibbioc", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-zlibbioc/app/bioconductor-zlibbioc_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-zlibbioc/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-zlibbioc/app/bioconductor-zlibbioc_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_biom-format", + "server_name": "biosci_biom_format", + "tool_name": "biom-format", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_biom-format/app/biom-format_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_biom-format/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_biom-format/app/biom-format_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_biopython", + "server_name": "biosci_biopython", + "tool_name": "biopython", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_biopython/app/biopython_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_biopython/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_biopython/app/biopython_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_blast", + "server_name": "biosci_blast", + "tool_name": "blast", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_blast/app/blast_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_blast/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_blast/app/blast_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_blast-legacy", + "server_name": "biosci_blast_legacy", + "tool_name": "blast-legacy", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_blast-legacy/app/blast-legacy_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_blast-legacy/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_blast-legacy/app/blast-legacy_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bowtie", + "server_name": "biosci_bowtie", + "tool_name": "bowtie", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bowtie/app/bowtie_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bowtie/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bowtie/app/bowtie_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bowtie2", + "server_name": "biosci_bowtie2", + "tool_name": "bowtie2", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bowtie2/app/bowtie2_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bowtie2/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bowtie2/app/bowtie2_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bpipe", + "server_name": "biosci_bpipe", + "tool_name": "bpipe", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bpipe/app/bpipe_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bpipe/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bpipe/app/bpipe_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_busco", + "server_name": "biosci_busco", + "tool_name": "busco", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_busco/app/busco_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_busco/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_busco/app/busco_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bwa", + "server_name": "biosci_bwa", + "tool_name": "bwa", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bwa/app/bwa_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bwa/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bwa/app/bwa_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bx-python", + "server_name": "biosci_bx_python", + "tool_name": "bx-python", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bx-python/app/bx-python_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bx-python/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bx-python/app/bx-python_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_c-ares", + "server_name": "biosci_c_ares", + "tool_name": "c-ares", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_c-ares/app/c-ares_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_c-ares/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_c-ares/app/c-ares_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cascade-reg", + "server_name": "biosci_cascade_reg", + "tool_name": "cascade-reg", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cascade-reg/app/cascade-reg_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cascade-reg/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cascade-reg/app/cascade-reg_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cd-hit", + "server_name": "biosci_cd_hit", + "tool_name": "cd-hit", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cd-hit/app/cd-hit_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cd-hit/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cd-hit/app/cd-hit_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cdbtools", + "server_name": "biosci_cdbtools", + "tool_name": "cdbtools", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cdbtools/app/cdbtools_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cdbtools/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cdbtools/app/cdbtools_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cell2cell", + "server_name": "biosci_cell2cell", + "tool_name": "cell2cell", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cell2cell/app/cell2cell_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cell2cell/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cell2cell/app/cell2cell_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cellitac", + "server_name": "biosci_cellitac", + "tool_name": "cellitac", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cellitac/app/cellitac_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cellitac/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cellitac/app/cellitac_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cellqc", + "server_name": "biosci_cellqc", + "tool_name": "cellqc", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cellqc/app/cellqc_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cellqc/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cellqc/app/cellqc_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cellsnake", + "server_name": "biosci_cellsnake", + "tool_name": "cellsnake", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cellsnake/app/cellsnake_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cellsnake/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cellsnake/app/cellsnake_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_celltypist-so", + "server_name": "biosci_celltypist_so", + "tool_name": "celltypist-so", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_celltypist-so/app/celltypist-so_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_celltypist-so/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_celltypist-so/app/celltypist-so_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_checkatlas", + "server_name": "biosci_checkatlas", + "tool_name": "checkatlas", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_checkatlas/app/checkatlas_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_checkatlas/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_checkatlas/app/checkatlas_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_checkm-genome", + "server_name": "biosci_checkm_genome", + "tool_name": "checkm-genome", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_checkm-genome/app/checkm-genome_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_checkm-genome/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_checkm-genome/app/checkm-genome_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_circexplorer2", + "server_name": "biosci_circexplorer2", + "tool_name": "circexplorer2", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_circexplorer2/app/circexplorer2_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_circexplorer2/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_circexplorer2/app/circexplorer2_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_circos", + "server_name": "biosci_circos", + "tool_name": "circos", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_circos/app/circos_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_circos/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_circos/app/circos_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_clustalo", + "server_name": "biosci_clustalo", + "tool_name": "clustalo", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_clustalo/app/clustalo_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_clustalo/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_clustalo/app/clustalo_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_clustalw", + "server_name": "biosci_clustalw", + "tool_name": "clustalw", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_clustalw/app/clustalw_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_clustalw/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_clustalw/app/clustalw_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cmappy", + "server_name": "biosci_cmappy", + "tool_name": "cmappy", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cmappy/app/cmappy_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cmappy/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cmappy/app/cmappy_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cnvkit", + "server_name": "biosci_cnvkit", + "tool_name": "cnvkit", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cnvkit/app/cnvkit_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cnvkit/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cnvkit/app/cnvkit_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_comebin", + "server_name": "biosci_comebin", + "tool_name": "comebin", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_comebin/app/comebin_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_comebin/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_comebin/app/comebin_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_comet-ms", + "server_name": "biosci_comet_ms", + "tool_name": "comet-ms", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_comet-ms/app/comet-ms_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_comet-ms/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_comet-ms/app/comet-ms_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_constellations", + "server_name": "biosci_constellations", + "tool_name": "constellations", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_constellations/app/constellations_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_constellations/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_constellations/app/constellations_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cooler", + "server_name": "biosci_cooler", + "tool_name": "cooler", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cooler/app/cooler_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cooler/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cooler/app/cooler_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cooltools", + "server_name": "biosci_cooltools", + "tool_name": "cooltools", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cooltools/app/cooltools_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cooltools/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cooltools/app/cooltools_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_coreutils", + "server_name": "biosci_coreutils", + "tool_name": "coreutils", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_coreutils/app/coreutils_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_coreutils/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_coreutils/app/coreutils_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cosg", + "server_name": "biosci_cosg", + "tool_name": "cosg", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cosg/app/cosg_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cosg/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cosg/app/cosg_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cospar", + "server_name": "biosci_cospar", + "tool_name": "cospar", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cospar/app/cospar_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cospar/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cospar/app/cospar_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_crispresso2", + "server_name": "biosci_crispresso2", + "tool_name": "crispresso2", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_crispresso2/app/crispresso2_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_crispresso2/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_crispresso2/app/crispresso2_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_crispritz", + "server_name": "biosci_crispritz", + "tool_name": "crispritz", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_crispritz/app/crispritz_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_crispritz/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_crispritz/app/crispritz_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_crisprme", + "server_name": "biosci_crisprme", + "tool_name": "crisprme", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_crisprme/app/crisprme_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_crisprme/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_crisprme/app/crisprme_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cromwell", + "server_name": "biosci_cromwell", + "tool_name": "cromwell", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cromwell/app/cromwell_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cromwell/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cromwell/app/cromwell_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_csvtk", + "server_name": "biosci_csvtk", + "tool_name": "csvtk", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_csvtk/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cutadapt", + "server_name": "biosci_cutadapt", + "tool_name": "cutadapt", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cutadapt/app/cutadapt_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cutadapt/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cutadapt/app/cutadapt_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cwltool", + "server_name": "biosci_cwltool", + "tool_name": "cwltool", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cwltool/app/cwltool_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cwltool/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cwltool/app/cwltool_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cytoscape", + "server_name": "biosci_cytoscape", + "tool_name": "cytoscape", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cytoscape/app/cytoscape_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cytoscape/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cytoscape/app/cytoscape_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cyvcf2", + "server_name": "biosci_cyvcf2", + "tool_name": "cyvcf2", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cyvcf2/app/cyvcf2_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cyvcf2/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_cyvcf2/app/cyvcf2_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_dca", + "server_name": "biosci_dca", + "tool_name": "dca", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_dca/app/dca_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_dca/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_dca/app/dca_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ddocent", + "server_name": "biosci_ddocent", + "tool_name": "ddocent", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ddocent/app/ddocent_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ddocent/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ddocent/app/ddocent_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_deblur", + "server_name": "biosci_deblur", + "tool_name": "deblur", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_deblur/app/deblur_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_deblur/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_deblur/app/deblur_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_deeptools", + "server_name": "biosci_deeptools", + "tool_name": "deeptools", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_deeptools/app/deeptools_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_deeptools/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_deeptools/app/deeptools_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_deeptoolsintervals", + "server_name": "biosci_deeptoolsintervals", + "tool_name": "deeptoolsintervals", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_deeptoolsintervals/app/deeptoolsintervals_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_deeptoolsintervals/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_deeptoolsintervals/app/deeptoolsintervals_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_delly", + "server_name": "biosci_delly", + "tool_name": "delly", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_delly/app/delly_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_delly/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_delly/app/delly_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_dendropy", + "server_name": "biosci_dendropy", + "tool_name": "dendropy", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_dendropy/app/dendropy_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_dendropy/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_dendropy/app/dendropy_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_diamond", + "server_name": "biosci_diamond", + "tool_name": "diamond", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_diamond/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_dnaio", + "server_name": "biosci_dnaio", + "tool_name": "dnaio", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_dnaio/app/dnaio_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_dnaio/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_dnaio/app/dnaio_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_doubletdetection", + "server_name": "biosci_doubletdetection", + "tool_name": "doubletdetection", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_doubletdetection/app/doubletdetection_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_doubletdetection/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_doubletdetection/app/doubletdetection_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_dropkick", + "server_name": "biosci_dropkick", + "tool_name": "dropkick", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_dropkick/app/dropkick_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_dropkick/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_dropkick/app/dropkick_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_dsh-bio", + "server_name": "biosci_dsh_bio", + "tool_name": "dsh-bio", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_dsh-bio/app/dsh-bio_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_dsh-bio/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_dsh-bio/app/dsh-bio_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_dxpy", + "server_name": "biosci_dxpy", + "tool_name": "dxpy", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_dxpy/app/dxpy_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_dxpy/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_dxpy/app/dxpy_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_easy_vitessce", + "server_name": "biosci_easy_vitessce", + "tool_name": "easy_vitessce", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_easy_vitessce/app/easy_vitessce_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_easy_vitessce/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_easy_vitessce/app/easy_vitessce_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_echidna", + "server_name": "biosci_echidna", + "tool_name": "echidna", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_echidna/app/echidna_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_echidna/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_echidna/app/echidna_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_emboss", + "server_name": "biosci_emboss", + "tool_name": "emboss", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_emboss/app/emboss_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_emboss/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_emboss/app/emboss_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ena-webin-cli", + "server_name": "biosci_ena_webin_cli", + "tool_name": "ena-webin-cli", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ena-webin-cli/app/ena-webin-cli_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ena-webin-cli/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ena-webin-cli/app/ena-webin-cli_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ensembl-vep", + "server_name": "biosci_ensembl_vep", + "tool_name": "ensembl-vep", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ensembl-vep/app/ensembl-vep_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ensembl-vep/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ensembl-vep/app/ensembl-vep_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_entrez-direct", + "server_name": "biosci_entrez_direct", + "tool_name": "entrez-direct", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_entrez-direct/app/entrez-direct_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_entrez-direct/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_entrez-direct/app/entrez-direct_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_epic", + "server_name": "biosci_epic", + "tool_name": "epic", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_epic/app/epic_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_epic/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_epic/app/epic_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_episcanpy", + "server_name": "biosci_episcanpy", + "tool_name": "episcanpy", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_episcanpy/app/episcanpy_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_episcanpy/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_episcanpy/app/episcanpy_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_eva-sub-cli", + "server_name": "biosci_eva_sub_cli", + "tool_name": "eva-sub-cli", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_eva-sub-cli/app/eva-sub-cli_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_eva-sub-cli/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_eva-sub-cli/app/eva-sub-cli_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_f5c", + "server_name": "biosci_f5c", + "tool_name": "f5c", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_f5c/app/f5c_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_f5c/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_f5c/app/f5c_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_famsa", + "server_name": "biosci_famsa", + "tool_name": "famsa", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_famsa/app/famsa_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_famsa/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_famsa/app/famsa_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_fast5", + "server_name": "biosci_fast5", + "tool_name": "fast5", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_fast5/app/fast5_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_fast5/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_fast5/app/fast5_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_fastani", + "server_name": "biosci_fastani", + "tool_name": "fastani", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_fastani/app/fastani_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_fastani/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_fastani/app/fastani_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_fastdtw", + "server_name": "biosci_fastdtw", + "tool_name": "fastdtw", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_fastdtw/app/fastdtw_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_fastdtw/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_fastdtw/app/fastdtw_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_fastp", + "server_name": "biosci_fastp", + "tool_name": "fastp", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_fastp/app/fastp_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_fastp/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_fastp/app/fastp_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_fastqc", + "server_name": "biosci_fastqc", + "tool_name": "fastqc", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_fastqc/app/fastqc_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_fastqc/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_fastqc/app/fastqc_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_fasttree", + "server_name": "biosci_fasttree", + "tool_name": "fasttree", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_fasttree/app/fasttree_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_fasttree/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_fasttree/app/fasttree_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_fermi2", + "server_name": "biosci_fermi2", + "tool_name": "fermi2", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_fermi2/app/fermi2_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_fermi2/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_fermi2/app/fermi2_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_fgbio", + "server_name": "biosci_fgbio", + "tool_name": "fgbio", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_fgbio/app/fgbio_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_fgbio/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_fgbio/app/fgbio_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_filechunkio", + "server_name": "biosci_filechunkio", + "tool_name": "filechunkio", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_filechunkio/app/filechunkio_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_filechunkio/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_filechunkio/app/filechunkio_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_flagx", + "server_name": "biosci_flagx", + "tool_name": "flagx", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_flagx/app/flagx_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_flagx/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_flagx/app/flagx_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_flye", + "server_name": "biosci_flye", + "tool_name": "flye", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_flye/app/flye_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_flye/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_flye/app/flye_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_foldseek", + "server_name": "biosci_foldseek", + "tool_name": "foldseek", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_foldseek/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_freebayes", + "server_name": "biosci_freebayes", + "tool_name": "freebayes", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_freebayes/app/freebayes_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_freebayes/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_freebayes/app/freebayes_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ftputil", + "server_name": "biosci_ftputil", + "tool_name": "ftputil", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ftputil/app/ftputil_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ftputil/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ftputil/app/ftputil_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_fwdpy11", + "server_name": "biosci_fwdpy11", + "tool_name": "fwdpy11", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_fwdpy11/app/fwdpy11_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_fwdpy11/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_fwdpy11/app/fwdpy11_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_galaxy-lib", + "server_name": "biosci_galaxy_lib", + "tool_name": "galaxy-lib", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_galaxy-lib/app/galaxy-lib_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_galaxy-lib/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_galaxy-lib/app/galaxy-lib_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gatk", + "server_name": "biosci_gatk", + "tool_name": "gatk", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gatk/app/gatk_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gatk/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gatk/app/gatk_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gatk4", + "server_name": "biosci_gatk4", + "tool_name": "gatk4", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gatk4/app/gatk4_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gatk4/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gatk4/app/gatk4_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gatk4-spark", + "server_name": "biosci_gatk4_spark", + "tool_name": "gatk4-spark", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gatk4-spark/app/gatk4-spark_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gatk4-spark/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gatk4-spark/app/gatk4-spark_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gdk-pixbuf", + "server_name": "biosci_gdk_pixbuf", + "tool_name": "gdk-pixbuf", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gdk-pixbuf/app/gdk-pixbuf_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gdk-pixbuf/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gdk-pixbuf/app/gdk-pixbuf_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gecode", + "server_name": "biosci_gecode", + "tool_name": "gecode", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gecode/app/gecode_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gecode/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gecode/app/gecode_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gemini", + "server_name": "biosci_gemini", + "tool_name": "gemini", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gemini/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gene-trajectory-python", + "server_name": "biosci_gene_trajectory_python", + "tool_name": "gene-trajectory-python", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gene-trajectory-python/app/gene-trajectory-python_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gene-trajectory-python/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gene-trajectory-python/app/gene-trajectory-python_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_genecircuitry", + "server_name": "biosci_genecircuitry", + "tool_name": "genecircuitry", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_genecircuitry/app/genecircuitry_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_genecircuitry/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_genecircuitry/app/genecircuitry_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_geneimpacts", + "server_name": "biosci_geneimpacts", + "tool_name": "geneimpacts", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_geneimpacts/app/geneimpacts_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_geneimpacts/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_geneimpacts/app/geneimpacts_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_genenotebook", + "server_name": "biosci_genenotebook", + "tool_name": "genenotebook", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_genenotebook/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_genoboo", + "server_name": "biosci_genoboo", + "tool_name": "genoboo", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_genoboo/app/genoboo_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_genoboo/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_genoboo/app/genoboo_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_genomad", + "server_name": "biosci_genomad", + "tool_name": "genomad", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_genomad/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_genomepy", + "server_name": "biosci_genomepy", + "tool_name": "genomepy", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_genomepy/app/genomepy_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_genomepy/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_genomepy/app/genomepy_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_genometools-genometools", + "server_name": "biosci_genometools_genometools", + "tool_name": "genometools-genometools", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_genometools-genometools/app/genometools-genometools_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_genometools-genometools/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_genometools-genometools/app/genometools-genometools_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gffread", + "server_name": "biosci_gffread", + "tool_name": "gffread", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gffread/app/gffread_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gffread/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gffread/app/gffread_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gffutils", + "server_name": "biosci_gffutils", + "tool_name": "gffutils", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gffutils/app/gffutils_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gffutils/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gffutils/app/gffutils_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ghostscript", + "server_name": "biosci_ghostscript", + "tool_name": "ghostscript", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ghostscript/app/ghostscript_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ghostscript/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ghostscript/app/ghostscript_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gimmemotifs", + "server_name": "biosci_gimmemotifs", + "tool_name": "gimmemotifs", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gimmemotifs/app/gimmemotifs_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gimmemotifs/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gimmemotifs/app/gimmemotifs_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_glimmerhmm", + "server_name": "biosci_glimmerhmm", + "tool_name": "glimmerhmm", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_glimmerhmm/app/glimmerhmm_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_glimmerhmm/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_glimmerhmm/app/glimmerhmm_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gmap", + "server_name": "biosci_gmap", + "tool_name": "gmap", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gmap/app/gmap_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gmap/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gmap/app/gmap_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gneiss", + "server_name": "biosci_gneiss", + "tool_name": "gneiss", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gneiss/app/gneiss_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gneiss/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gneiss/app/gneiss_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gnuplot", + "server_name": "biosci_gnuplot", + "tool_name": "gnuplot", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gnuplot/app/gnuplot_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gnuplot/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gnuplot/app/gnuplot_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gofasta", + "server_name": "biosci_gofasta", + "tool_name": "gofasta", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gofasta/app/gofasta_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gofasta/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gofasta/app/gofasta_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_goleft", + "server_name": "biosci_goleft", + "tool_name": "goleft", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_goleft/app/goleft_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_goleft/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_goleft/app/goleft_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gridss", + "server_name": "biosci_gridss", + "tool_name": "gridss", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gridss/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gromacs", + "server_name": "biosci_gromacs", + "tool_name": "gromacs", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gromacs/app/gromacs_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gromacs/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gromacs/app/gromacs_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gseapy", + "server_name": "biosci_gseapy", + "tool_name": "gseapy", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gseapy/app/gseapy_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gseapy/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gseapy/app/gseapy_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gtdbtk", + "server_name": "biosci_gtdbtk", + "tool_name": "gtdbtk", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gtdbtk/app/gtdbtk_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gtdbtk/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_gtdbtk/app/gtdbtk_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_harpy", + "server_name": "biosci_harpy", + "tool_name": "harpy", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_harpy/app/harpy_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_harpy/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_harpy/app/harpy_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_hhsuite", + "server_name": "biosci_hhsuite", + "tool_name": "hhsuite", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_hhsuite/app/hhsuite_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_hhsuite/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_hhsuite/app/hhsuite_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_hicexplorer", + "server_name": "biosci_hicexplorer", + "tool_name": "hicexplorer", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_hicexplorer/app/hicexplorer_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_hicexplorer/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_hicexplorer/app/hicexplorer_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_hifiasm", + "server_name": "biosci_hifiasm", + "tool_name": "hifiasm", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_hifiasm/app/hifiasm_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_hifiasm/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_hifiasm/app/hifiasm_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_hisat2", + "server_name": "biosci_hisat2", + "tool_name": "hisat2", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_hisat2/app/hisat2_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_hisat2/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_hisat2/app/hisat2_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_hmmer", + "server_name": "biosci_hmmer", + "tool_name": "hmmer", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_hmmer/app/hmmer_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_hmmer/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_hmmer/app/hmmer_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_htseq", + "server_name": "biosci_htseq", + "tool_name": "htseq", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_htseq/app/htseq_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_htseq/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_htseq/app/htseq_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_htslib", + "server_name": "biosci_htslib", + "tool_name": "htslib", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_htslib/app/htslib_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_htslib/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_htslib/app/htslib_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_humann", + "server_name": "biosci_humann", + "tool_name": "humann", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_humann/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_humann2", + "server_name": "biosci_humann2", + "tool_name": "humann2", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_humann2/app/humann2_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_humann2/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_humann2/app/humann2_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_hyphy", + "server_name": "biosci_hyphy", + "tool_name": "hyphy", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_hyphy/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_igv", + "server_name": "biosci_igv", + "tool_name": "igv", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_igv/app/igv_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_igv/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_igv/app/igv_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_igv-reports", + "server_name": "biosci_igv_reports", + "tool_name": "igv-reports", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_igv-reports/app/igv-reports_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_igv-reports/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_igv-reports/app/igv-reports_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_illumina-interop", + "server_name": "biosci_illumina_interop", + "tool_name": "illumina-interop", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_illumina-interop/app/illumina-interop_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_illumina-interop/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_illumina-interop/app/illumina-interop_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_infernal", + "server_name": "biosci_infernal", + "tool_name": "infernal", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_infernal/app/infernal_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_infernal/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_infernal/app/infernal_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_insilicoseq", + "server_name": "biosci_insilicoseq", + "tool_name": "insilicoseq", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_insilicoseq/app/insilicoseq_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_insilicoseq/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_insilicoseq/app/insilicoseq_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_intarna", + "server_name": "biosci_intarna", + "tool_name": "intarna", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_intarna/app/intarna_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_intarna/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_intarna/app/intarna_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_involucro", + "server_name": "biosci_involucro", + "tool_name": "involucro", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_involucro/app/involucro_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_involucro/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_involucro/app/involucro_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_iow", + "server_name": "biosci_iow", + "tool_name": "iow", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_iow/app/iow_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_iow/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_iow/app/iow_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ipyrad", + "server_name": "biosci_ipyrad", + "tool_name": "ipyrad", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ipyrad/app/ipyrad_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ipyrad/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ipyrad/app/ipyrad_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ipython-cluster-helper", + "server_name": "biosci_ipython_cluster_helper", + "tool_name": "ipython-cluster-helper", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ipython-cluster-helper/app/ipython-cluster-helper_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ipython-cluster-helper/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ipython-cluster-helper/app/ipython-cluster-helper_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_iqtree", + "server_name": "biosci_iqtree", + "tool_name": "iqtree", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_iqtree/app/iqtree_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_iqtree/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_iqtree/app/iqtree_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_itsxpress", + "server_name": "biosci_itsxpress", + "tool_name": "itsxpress", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_itsxpress/app/itsxpress_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_itsxpress/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_itsxpress/app/itsxpress_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ivar", + "server_name": "biosci_ivar", + "tool_name": "ivar", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ivar/app/ivar_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ivar/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ivar/app/ivar_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_jalview", + "server_name": "biosci_jalview", + "tool_name": "jalview", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_jalview/app/jalview_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_jalview/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_jalview/app/jalview_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_java-jdk", + "server_name": "biosci_java_jdk", + "tool_name": "java-jdk", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_java-jdk/app/java-jdk_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_java-jdk/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_java-jdk/app/java-jdk_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_jbrowse2", + "server_name": "biosci_jbrowse2", + "tool_name": "jbrowse2", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_jbrowse2/app/jbrowse2_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_jbrowse2/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_jbrowse2/app/jbrowse2_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_jcvi", + "server_name": "biosci_jcvi", + "tool_name": "jcvi", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_jcvi/app/jcvi_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_jcvi/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_jcvi/app/jcvi_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_jellyfish", + "server_name": "biosci_jellyfish", + "tool_name": "jellyfish", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_jellyfish/app/jellyfish_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_jellyfish/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_jellyfish/app/jellyfish_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_jq", + "server_name": "biosci_jq", + "tool_name": "jq", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_jq/app/jq_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_jq/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_jq/app/jq_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_k8", + "server_name": "biosci_k8", + "tool_name": "k8", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_k8/app/k8_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_k8/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_k8/app/k8_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_kaiju", + "server_name": "biosci_kaiju", + "tool_name": "kaiju", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_kaiju/app/kaiju_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_kaiju/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_kaiju/app/kaiju_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_kalign2", + "server_name": "biosci_kalign2", + "tool_name": "kalign2", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_kalign2/app/kalign2_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_kalign2/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_kalign2/app/kalign2_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_kallisto", + "server_name": "biosci_kallisto", + "tool_name": "kallisto", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_kallisto/app/kallisto_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_kallisto/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_kallisto/app/kallisto_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_kb-python", + "server_name": "biosci_kb_python", + "tool_name": "kb-python", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_kb-python/app/kb-python_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_kb-python/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_kb-python/app/kb-python_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_khipu-metabolomics", + "server_name": "biosci_khipu_metabolomics", + "tool_name": "khipu-metabolomics", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_khipu-metabolomics/app/khipu-metabolomics_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_khipu-metabolomics/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_khipu-metabolomics/app/khipu-metabolomics_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_kma", + "server_name": "biosci_kma", + "tool_name": "kma", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_kma/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_kmc", + "server_name": "biosci_kmc", + "tool_name": "kmc", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_kmc/app/kmc_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_kmc/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_kmc/app/kmc_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_kmer-jellyfish", + "server_name": "biosci_kmer_jellyfish", + "tool_name": "kmer-jellyfish", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_kmer-jellyfish/app/kmer-jellyfish_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_kmer-jellyfish/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_kmer-jellyfish/app/kmer-jellyfish_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_kraken2", + "server_name": "biosci_kraken2", + "tool_name": "kraken2", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_kraken2/app/kraken2_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_kraken2/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_kraken2/app/kraken2_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_krona", + "server_name": "biosci_krona", + "tool_name": "krona", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_krona/app/krona_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_krona/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_krona/app/krona_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_last", + "server_name": "biosci_last", + "tool_name": "last", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_last/app/last_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_last/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_last/app/last_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_lastz", + "server_name": "biosci_lastz", + "tool_name": "lastz", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_lastz/app/lastz_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_lastz/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_lastz/app/lastz_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_liana", + "server_name": "biosci_liana", + "tool_name": "liana", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_liana/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_libcifpp", + "server_name": "biosci_libcifpp", + "tool_name": "libcifpp", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_libcifpp/app/libcifpp_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_libcifpp/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_libcifpp/app/libcifpp_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_libdb", + "server_name": "biosci_libdb", + "tool_name": "libdb", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_libdb/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_libdeflate", + "server_name": "biosci_libdeflate", + "tool_name": "libdeflate", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_libdeflate/app/libdeflate_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_libdeflate/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_libdeflate/app/libdeflate_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_libsequence", + "server_name": "biosci_libsequence", + "tool_name": "libsequence", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_libsequence/app/libsequence_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_libsequence/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_libsequence/app/libsequence_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_locarna", + "server_name": "biosci_locarna", + "tool_name": "locarna", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_locarna/app/locarna_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_locarna/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_locarna/app/locarna_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_macs2", + "server_name": "biosci_macs2", + "tool_name": "macs2", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_macs2/app/macs2_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_macs2/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_macs2/app/macs2_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mafft", + "server_name": "biosci_mafft", + "tool_name": "mafft", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mafft/app/mafft_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mafft/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mafft/app/mafft_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mageck", + "server_name": "biosci_mageck", + "tool_name": "mageck", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mageck/app/mageck_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mageck/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mageck/app/mageck_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mameshiba", + "server_name": "biosci_mameshiba", + "tool_name": "mameshiba", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mameshiba/app/mameshiba_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mameshiba/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mameshiba/app/mameshiba_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mappy", + "server_name": "biosci_mappy", + "tool_name": "mappy", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mappy/app/mappy_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mappy/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mappy/app/mappy_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_markerrepo", + "server_name": "biosci_markerrepo", + "tool_name": "markerrepo", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_markerrepo/app/markerrepo_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_markerrepo/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_markerrepo/app/markerrepo_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mash", + "server_name": "biosci_mash", + "tool_name": "mash", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mash/app/mash_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mash/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mash/app/mash_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_maxquant", + "server_name": "biosci_maxquant", + "tool_name": "maxquant", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_maxquant/app/maxquant_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_maxquant/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_maxquant/app/maxquant_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mcl", + "server_name": "biosci_mcl", + "tool_name": "mcl", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mcl/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_medaka", + "server_name": "biosci_medaka", + "tool_name": "medaka", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_medaka/app/medaka_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_medaka/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_medaka/app/medaka_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_megahit", + "server_name": "biosci_megahit", + "tool_name": "megahit", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_megahit/app/megahit_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_megahit/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_megahit/app/megahit_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_meme", + "server_name": "biosci_meme", + "tool_name": "meme", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_meme/app/meme_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_meme/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_meme/app/meme_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mentalist", + "server_name": "biosci_mentalist", + "tool_name": "mentalist", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mentalist/app/mentalist_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mentalist/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mentalist/app/mentalist_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_metagenome-atlas", + "server_name": "biosci_metagenome_atlas", + "tool_name": "metagenome-atlas", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_metagenome-atlas/app/metagenome-atlas_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_metagenome-atlas/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_metagenome-atlas/app/metagenome-atlas_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_metaphlan", + "server_name": "biosci_metaphlan", + "tool_name": "metaphlan", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_metaphlan/app/metaphlan_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_metaphlan/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_metaphlan/app/metaphlan_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_metaphlan2", + "server_name": "biosci_metaphlan2", + "tool_name": "metaphlan2", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_metaphlan2/app/metaphlan2_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_metaphlan2/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_metaphlan2/app/metaphlan2_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mikado", + "server_name": "biosci_mikado", + "tool_name": "mikado", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mikado/app/mikado_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mikado/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mikado/app/mikado_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_minced", + "server_name": "biosci_minced", + "tool_name": "minced", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_minced/app/minced_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_minced/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_minced/app/minced_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_miniasm", + "server_name": "biosci_miniasm", + "tool_name": "miniasm", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_miniasm/app/miniasm_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_miniasm/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_miniasm/app/miniasm_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_minimap2", + "server_name": "biosci_minimap2", + "tool_name": "minimap2", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_minimap2/app/minimap2_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_minimap2/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_minimap2/app/minimap2_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_minvar", + "server_name": "biosci_minvar", + "tool_name": "minvar", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_minvar/app/minvar_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_minvar/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_minvar/app/minvar_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mitos", + "server_name": "biosci_mitos", + "tool_name": "mitos", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mitos/app/mitos_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mitos/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mitos/app/mitos_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mlst", + "server_name": "biosci_mlst", + "tool_name": "mlst", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mlst/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mmseqs2", + "server_name": "biosci_mmseqs2", + "tool_name": "mmseqs2", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mmseqs2/app/mmseqs2_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mmseqs2/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mmseqs2/app/mmseqs2_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mmtf-python", + "server_name": "biosci_mmtf_python", + "tool_name": "mmtf-python", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mmtf-python/app/mmtf-python_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mmtf-python/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mmtf-python/app/mmtf-python_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mobivision-m", + "server_name": "biosci_mobivision_m", + "tool_name": "mobivision-m", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mobivision-m/app/mobivision-m_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mobivision-m/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mobivision-m/app/mobivision-m_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_moments", + "server_name": "biosci_moments", + "tool_name": "moments", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_moments/app/moments_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_moments/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_moments/app/moments_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mosdepth", + "server_name": "biosci_mosdepth", + "tool_name": "mosdepth", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mosdepth/app/mosdepth_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mosdepth/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mosdepth/app/mosdepth_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mothur", + "server_name": "biosci_mothur", + "tool_name": "mothur", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mothur/app/mothur_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mothur/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mothur/app/mothur_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_msisensor-pro", + "server_name": "biosci_msisensor_pro", + "tool_name": "msisensor-pro", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_msisensor-pro/app/msisensor-pro_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_msisensor-pro/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_msisensor-pro/app/msisensor-pro_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_msproteomicstools", + "server_name": "biosci_msproteomicstools", + "tool_name": "msproteomicstools", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_msproteomicstools/app/msproteomicstools_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_msproteomicstools/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_msproteomicstools/app/msproteomicstools_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_msstitch", + "server_name": "biosci_msstitch", + "tool_name": "msstitch", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_msstitch/app/msstitch_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_msstitch/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_msstitch/app/msstitch_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_multiqc", + "server_name": "biosci_multiqc", + "tool_name": "multiqc", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_multiqc/app/multiqc_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_multiqc/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_multiqc/app/multiqc_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_multiqc-bcbio", + "server_name": "biosci_multiqc_bcbio", + "tool_name": "multiqc-bcbio", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_multiqc-bcbio/app/multiqc-bcbio_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_multiqc-bcbio/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_multiqc-bcbio/app/multiqc-bcbio_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_multiqc-xenium-extra", + "server_name": "biosci_multiqc_xenium_extra", + "tool_name": "multiqc-xenium-extra", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_multiqc-xenium-extra/app/multiqc-xenium-extra_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_multiqc-xenium-extra/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_multiqc-xenium-extra/app/multiqc-xenium-extra_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mummer", + "server_name": "biosci_mummer", + "tool_name": "mummer", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mummer/app/mummer_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mummer/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mummer/app/mummer_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_munkres", + "server_name": "biosci_munkres", + "tool_name": "munkres", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_munkres/app/munkres_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_munkres/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_munkres/app/munkres_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_muscle", + "server_name": "biosci_muscle", + "tool_name": "muscle", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_muscle/app/muscle_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_muscle/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_muscle/app/muscle_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mysql-connector-c", + "server_name": "biosci_mysql_connector_c", + "tool_name": "mysql-connector-c", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mysql-connector-c/app/mysql-connector-c_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mysql-connector-c/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mysql-connector-c/app/mysql-connector-c_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mztosqlite", + "server_name": "biosci_mztosqlite", + "tool_name": "mztosqlite", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mztosqlite/app/mztosqlite_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mztosqlite/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_mztosqlite/app/mztosqlite_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_nanocomp", + "server_name": "biosci_nanocomp", + "tool_name": "nanocomp", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_nanocomp/app/nanocomp_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_nanocomp/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_nanocomp/app/nanocomp_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_nanoget", + "server_name": "biosci_nanoget", + "tool_name": "nanoget", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_nanoget/app/nanoget_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_nanoget/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_nanoget/app/nanoget_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_nanomath", + "server_name": "biosci_nanomath", + "tool_name": "nanomath", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_nanomath/app/nanomath_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_nanomath/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_nanomath/app/nanomath_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_nanoplot", + "server_name": "biosci_nanoplot", + "tool_name": "nanoplot", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_nanoplot/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_nanopolish", + "server_name": "biosci_nanopolish", + "tool_name": "nanopolish", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_nanopolish/app/nanopolish_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_nanopolish/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_nanopolish/app/nanopolish_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ncbi-amrfinderplus", + "server_name": "biosci_ncbi_amrfinderplus", + "tool_name": "ncbi-amrfinderplus", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ncbi-amrfinderplus/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ncbi-datasets-pylib", + "server_name": "biosci_ncbi_datasets_pylib", + "tool_name": "ncbi-datasets-pylib", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ncbi-datasets-pylib/app/ncbi-datasets-pylib_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ncbi-datasets-pylib/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ncbi-datasets-pylib/app/ncbi-datasets-pylib_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ncbi-genome-download", + "server_name": "biosci_ncbi_genome_download", + "tool_name": "ncbi-genome-download", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ncbi-genome-download/app/ncbi-genome-download_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ncbi-genome-download/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ncbi-genome-download/app/ncbi-genome-download_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ncbi-ngs-sdk", + "server_name": "biosci_ncbi_ngs_sdk", + "tool_name": "ncbi-ngs-sdk", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ncbi-ngs-sdk/app/ncbi-ngs-sdk_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ncbi-ngs-sdk/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ncbi-ngs-sdk/app/ncbi-ngs-sdk_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ncbi-vdb", + "server_name": "biosci_ncbi_vdb", + "tool_name": "ncbi-vdb", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ncbi-vdb/app/ncbi-vdb_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ncbi-vdb/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ncbi-vdb/app/ncbi-vdb_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ncls", + "server_name": "biosci_ncls", + "tool_name": "ncls", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ncls/app/ncls_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ncls/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ncls/app/ncls_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_nextalign", + "server_name": "biosci_nextalign", + "tool_name": "nextalign", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_nextalign/app/nextalign_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_nextalign/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_nextalign/app/nextalign_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_nextclade", + "server_name": "biosci_nextclade", + "tool_name": "nextclade", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_nextclade/app/nextclade_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_nextclade/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_nextclade/app/nextclade_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_nextflow", + "server_name": "biosci_nextflow", + "tool_name": "nextflow", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_nextflow/app/nextflow_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_nextflow/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_nextflow/app/nextflow_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_nf-core", + "server_name": "biosci_nf_core", + "tool_name": "nf-core", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_nf-core/app/nf-core_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_nf-core/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_nf-core/app/nf-core_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_nglview", + "server_name": "biosci_nglview", + "tool_name": "nglview", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_nglview/app/nglview_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_nglview/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_nglview/app/nglview_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ngmlr", + "server_name": "biosci_ngmlr", + "tool_name": "ngmlr", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ngmlr/app/ngmlr_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ngmlr/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ngmlr/app/ngmlr_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ngs-smap", + "server_name": "biosci_ngs_smap", + "tool_name": "ngs-smap", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ngs-smap/app/ngs-smap_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ngs-smap/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ngs-smap/app/ngs-smap_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ngs-tools", + "server_name": "biosci_ngs_tools", + "tool_name": "ngs-tools", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ngs-tools/app/ngs-tools_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ngs-tools/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ngs-tools/app/ngs-tools_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_novae", + "server_name": "biosci_novae", + "tool_name": "novae", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_novae/app/novae_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_novae/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_novae/app/novae_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_novoalign", + "server_name": "biosci_novoalign", + "tool_name": "novoalign", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_novoalign/app/novoalign_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_novoalign/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_novoalign/app/novoalign_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ont-fast5-api", + "server_name": "biosci_ont_fast5_api", + "tool_name": "ont-fast5-api", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ont-fast5-api/app/ont-fast5-api_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ont-fast5-api/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ont-fast5-api/app/ont-fast5-api_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_openms-thirdparty", + "server_name": "biosci_openms_thirdparty", + "tool_name": "openms-thirdparty", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_openms-thirdparty/app/openms-thirdparty_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_openms-thirdparty/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_openms-thirdparty/app/openms-thirdparty_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_opticlust", + "server_name": "biosci_opticlust", + "tool_name": "opticlust", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_opticlust/app/opticlust_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_opticlust/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_opticlust/app/opticlust_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_orthofinder", + "server_name": "biosci_orthofinder", + "tool_name": "orthofinder", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_orthofinder/app/orthofinder_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_orthofinder/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_orthofinder/app/orthofinder_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ourotools", + "server_name": "biosci_ourotools", + "tool_name": "ourotools", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ourotools/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pairix", + "server_name": "biosci_pairix", + "tool_name": "pairix", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pairix/app/pairix_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pairix/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pairix/app/pairix_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_palantir", + "server_name": "biosci_palantir", + "tool_name": "palantir", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_palantir/app/palantir_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_palantir/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_palantir/app/palantir_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_paml", + "server_name": "biosci_paml", + "tool_name": "paml", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_paml/app/paml_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_paml/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_paml/app/paml_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pandaseq", + "server_name": "biosci_pandaseq", + "tool_name": "pandaseq", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pandaseq/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pango-designation", + "server_name": "biosci_pango_designation", + "tool_name": "pango-designation", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pango-designation/app/pango-designation_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pango-designation/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pango-designation/app/pango-designation_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pangolearn", + "server_name": "biosci_pangolearn", + "tool_name": "pangolearn", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pangolearn/app/pangolearn_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pangolearn/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pangolearn/app/pangolearn_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pangolin", + "server_name": "biosci_pangolin", + "tool_name": "pangolin", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pangolin/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_parallel", + "server_name": "biosci_parallel", + "tool_name": "parallel", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_parallel/app/parallel_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_parallel/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_parallel/app/parallel_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_parasail-python", + "server_name": "biosci_parasail_python", + "tool_name": "parasail-python", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_parasail-python/app/parasail-python_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_parasail-python/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_parasail-python/app/parasail-python_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pasta", + "server_name": "biosci_pasta", + "tool_name": "pasta", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pasta/app/pasta_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pasta/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pasta/app/pasta_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_paste-bio", + "server_name": "biosci_paste_bio", + "tool_name": "paste-bio", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_paste-bio/app/paste-bio_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_paste-bio/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_paste-bio/app/paste-bio_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pbmm2", + "server_name": "biosci_pbmm2", + "tool_name": "pbmm2", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pbmm2/app/pbmm2_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pbmm2/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pbmm2/app/pbmm2_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pcdl", + "server_name": "biosci_pcdl", + "tool_name": "pcdl", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pcdl/app/pcdl_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pcdl/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pcdl/app/pcdl_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_peakqc", + "server_name": "biosci_peakqc", + "tool_name": "peakqc", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_peakqc/app/peakqc_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_peakqc/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_peakqc/app/peakqc_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_peptides", + "server_name": "biosci_peptides", + "tool_name": "peptides", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_peptides/app/peptides_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_peptides/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_peptides/app/peptides_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-aceperl", + "server_name": "biosci_perl_aceperl", + "tool_name": "perl-aceperl", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-aceperl/app/perl-aceperl_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-aceperl/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-aceperl/app/perl-aceperl_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-algorithm-diff", + "server_name": "biosci_perl_algorithm_diff", + "tool_name": "perl-algorithm-diff", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-algorithm-diff/app/perl-algorithm-diff_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-algorithm-diff/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-algorithm-diff/app/perl-algorithm-diff_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-algorithm-munkres", + "server_name": "biosci_perl_algorithm_munkres", + "tool_name": "perl-algorithm-munkres", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-algorithm-munkres/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-alien-build", + "server_name": "biosci_perl_alien_build", + "tool_name": "perl-alien-build", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-alien-build/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-alien-libxml2", + "server_name": "biosci_perl_alien_libxml2", + "tool_name": "perl-alien-libxml2", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-alien-libxml2/app/perl-alien-libxml2_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-alien-libxml2/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-alien-libxml2/app/perl-alien-libxml2_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-apache-test", + "server_name": "biosci_perl_apache_test", + "tool_name": "perl-apache-test", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-apache-test/app/perl-apache-test_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-apache-test/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-apache-test/app/perl-apache-test_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-app-cpanminus", + "server_name": "biosci_perl_app_cpanminus", + "tool_name": "perl-app-cpanminus", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-app-cpanminus/app/perl-app-cpanminus_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-app-cpanminus/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-app-cpanminus/app/perl-app-cpanminus_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-appconfig", + "server_name": "biosci_perl_appconfig", + "tool_name": "perl-appconfig", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-appconfig/app/perl-appconfig_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-appconfig/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-appconfig/app/perl-appconfig_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-archive-tar", + "server_name": "biosci_perl_archive_tar", + "tool_name": "perl-archive-tar", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-archive-tar/app/perl-archive-tar_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-archive-tar/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-archive-tar/app/perl-archive-tar_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-array-compare", + "server_name": "biosci_perl_array_compare", + "tool_name": "perl-array-compare", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-array-compare/app/perl-array-compare_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-array-compare/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-array-compare/app/perl-array-compare_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-autoloader", + "server_name": "biosci_perl_autoloader", + "tool_name": "perl-autoloader", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-autoloader/app/perl-autoloader_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-autoloader/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-autoloader/app/perl-autoloader_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-base", + "server_name": "biosci_perl_base", + "tool_name": "perl-base", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-base/app/perl-base_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-base/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-base/app/perl-base_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-bio-asn1-entrezgene", + "server_name": "biosci_perl_bio_asn1_entrezgene", + "tool_name": "perl-bio-asn1-entrezgene", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-bio-asn1-entrezgene/app/perl-bio-asn1-entrezgene_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-bio-asn1-entrezgene/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-bio-asn1-entrezgene/app/perl-bio-asn1-entrezgene_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-bio-coordinate", + "server_name": "biosci_perl_bio_coordinate", + "tool_name": "perl-bio-coordinate", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-bio-coordinate/app/perl-bio-coordinate_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-bio-coordinate/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-bio-coordinate/app/perl-bio-coordinate_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-bio-db-hts", + "server_name": "biosci_perl_bio_db_hts", + "tool_name": "perl-bio-db-hts", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-bio-db-hts/app/perl-bio-db-hts_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-bio-db-hts/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-bio-db-hts/app/perl-bio-db-hts_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-bio-featureio", + "server_name": "biosci_perl_bio_featureio", + "tool_name": "perl-bio-featureio", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-bio-featureio/app/perl-bio-featureio_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-bio-featureio/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-bio-featureio/app/perl-bio-featureio_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-bio-phylo", + "server_name": "biosci_perl_bio_phylo", + "tool_name": "perl-bio-phylo", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-bio-phylo/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-bio-samtools", + "server_name": "biosci_perl_bio_samtools", + "tool_name": "perl-bio-samtools", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-bio-samtools/app/perl-bio-samtools_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-bio-samtools/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-bio-samtools/app/perl-bio-samtools_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-bio-searchio-hmmer", + "server_name": "biosci_perl_bio_searchio_hmmer", + "tool_name": "perl-bio-searchio-hmmer", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-bio-searchio-hmmer/app/perl-bio-searchio-hmmer_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-bio-searchio-hmmer/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-bio-searchio-hmmer/app/perl-bio-searchio-hmmer_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-bio-tools-phylo-paml", + "server_name": "biosci_perl_bio_tools_phylo_paml", + "tool_name": "perl-bio-tools-phylo-paml", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-bio-tools-phylo-paml/app/perl-bio-tools-phylo-paml_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-bio-tools-phylo-paml/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-bio-tools-phylo-paml/app/perl-bio-tools-phylo-paml_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-bio-tools-run-alignment-clustalw", + "server_name": "biosci_perl_bio_tools_run_alignment_clustalw", + "tool_name": "perl-bio-tools-run-alignment-clustalw", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-bio-tools-run-alignment-clustalw/app/perl-bio-tools-run-alignment-clustalw_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-bio-tools-run-alignment-clustalw/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-bio-tools-run-alignment-clustalw/app/perl-bio-tools-run-alignment-clustalw_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-bio-tools-run-alignment-tcoffee", + "server_name": "biosci_perl_bio_tools_run_alignment_tcoffee", + "tool_name": "perl-bio-tools-run-alignment-tcoffee", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-bio-tools-run-alignment-tcoffee/app/perl-bio-tools-run-alignment-tcoffee_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-bio-tools-run-alignment-tcoffee/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-bio-tools-run-alignment-tcoffee/app/perl-bio-tools-run-alignment-tcoffee_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-bioperl", + "server_name": "biosci_perl_bioperl", + "tool_name": "perl-bioperl", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-bioperl/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-bioperl-core", + "server_name": "biosci_perl_bioperl_core", + "tool_name": "perl-bioperl-core", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-bioperl-core/app/perl-bioperl-core_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-bioperl-core/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-bioperl-core/app/perl-bioperl-core_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-bioperl-run", + "server_name": "biosci_perl_bioperl_run", + "tool_name": "perl-bioperl-run", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-bioperl-run/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-business-isbn", + "server_name": "biosci_perl_business_isbn", + "tool_name": "perl-business-isbn", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-business-isbn/app/perl-business-isbn_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-business-isbn/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-business-isbn/app/perl-business-isbn_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-business-isbn-data", + "server_name": "biosci_perl_business_isbn_data", + "tool_name": "perl-business-isbn-data", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-business-isbn-data/app/perl-business-isbn-data_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-business-isbn-data/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-business-isbn-data/app/perl-business-isbn-data_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-cache-cache", + "server_name": "biosci_perl_cache_cache", + "tool_name": "perl-cache-cache", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-cache-cache/app/perl-cache-cache_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-cache-cache/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-cache-cache/app/perl-cache-cache_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-capture-tiny", + "server_name": "biosci_perl_capture_tiny", + "tool_name": "perl-capture-tiny", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-capture-tiny/app/perl-capture-tiny_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-capture-tiny/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-capture-tiny/app/perl-capture-tiny_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-carp", + "server_name": "biosci_perl_carp", + "tool_name": "perl-carp", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-carp/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-cgi", + "server_name": "biosci_perl_cgi", + "tool_name": "perl-cgi", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-cgi/app/perl-cgi_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-cgi/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-cgi/app/perl-cgi_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-class-data-inheritable", + "server_name": "biosci_perl_class_data_inheritable", + "tool_name": "perl-class-data-inheritable", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-class-data-inheritable/app/perl-class-data-inheritable_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-class-data-inheritable/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-class-data-inheritable/app/perl-class-data-inheritable_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-class-inspector", + "server_name": "biosci_perl_class_inspector", + "tool_name": "perl-class-inspector", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-class-inspector/app/perl-class-inspector_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-class-inspector/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-class-inspector/app/perl-class-inspector_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-class-load", + "server_name": "biosci_perl_class_load", + "tool_name": "perl-class-load", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-class-load/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-class-load-xs", + "server_name": "biosci_perl_class_load_xs", + "tool_name": "perl-class-load-xs", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-class-load-xs/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-class-method-modifiers", + "server_name": "biosci_perl_class_method_modifiers", + "tool_name": "perl-class-method-modifiers", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-class-method-modifiers/app/perl-class-method-modifiers_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-class-method-modifiers/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-class-method-modifiers/app/perl-class-method-modifiers_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-clone", + "server_name": "biosci_perl_clone", + "tool_name": "perl-clone", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-clone/app/perl-clone_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-clone/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-clone/app/perl-clone_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-common-sense", + "server_name": "biosci_perl_common_sense", + "tool_name": "perl-common-sense", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-common-sense/app/perl-common-sense_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-common-sense/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-common-sense/app/perl-common-sense_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-compress-raw-bzip2", + "server_name": "biosci_perl_compress_raw_bzip2", + "tool_name": "perl-compress-raw-bzip2", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-compress-raw-bzip2/app/perl-compress-raw-bzip2_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-compress-raw-bzip2/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-compress-raw-bzip2/app/perl-compress-raw-bzip2_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-compress-raw-zlib", + "server_name": "biosci_perl_compress_raw_zlib", + "tool_name": "perl-compress-raw-zlib", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-compress-raw-zlib/app/perl-compress-raw-zlib_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-compress-raw-zlib/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-compress-raw-zlib/app/perl-compress-raw-zlib_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-config-general", + "server_name": "biosci_perl_config_general", + "tool_name": "perl-config-general", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-config-general/app/perl-config-general_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-config-general/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-config-general/app/perl-config-general_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-constant", + "server_name": "biosci_perl_constant", + "tool_name": "perl-constant", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-constant/app/perl-constant_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-constant/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-constant/app/perl-constant_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-convert-binary-c", + "server_name": "biosci_perl_convert_binary_c", + "tool_name": "perl-convert-binary-c", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-convert-binary-c/app/perl-convert-binary-c_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-convert-binary-c/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-convert-binary-c/app/perl-convert-binary-c_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-convert-binhex", + "server_name": "biosci_perl_convert_binhex", + "tool_name": "perl-convert-binhex", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-convert-binhex/app/perl-convert-binhex_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-convert-binhex/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-convert-binhex/app/perl-convert-binhex_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-cpan-meta", + "server_name": "biosci_perl_cpan_meta", + "tool_name": "perl-cpan-meta", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-cpan-meta/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-cpan-meta-requirements", + "server_name": "biosci_perl_cpan_meta_requirements", + "tool_name": "perl-cpan-meta-requirements", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-cpan-meta-requirements/app/perl-cpan-meta-requirements_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-cpan-meta-requirements/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-cpan-meta-requirements/app/perl-cpan-meta-requirements_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-crypt-rc4", + "server_name": "biosci_perl_crypt_rc4", + "tool_name": "perl-crypt-rc4", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-crypt-rc4/app/perl-crypt-rc4_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-crypt-rc4/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-crypt-rc4/app/perl-crypt-rc4_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-data-dumper", + "server_name": "biosci_perl_data_dumper", + "tool_name": "perl-data-dumper", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-data-dumper/app/perl-data-dumper_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-data-dumper/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-data-dumper/app/perl-data-dumper_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-data-optlist", + "server_name": "biosci_perl_data_optlist", + "tool_name": "perl-data-optlist", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-data-optlist/app/perl-data-optlist_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-data-optlist/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-data-optlist/app/perl-data-optlist_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-data-stag", + "server_name": "biosci_perl_data_stag", + "tool_name": "perl-data-stag", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-data-stag/app/perl-data-stag_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-data-stag/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-data-stag/app/perl-data-stag_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-date-format", + "server_name": "biosci_perl_date_format", + "tool_name": "perl-date-format", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-date-format/app/perl-date-format_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-date-format/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-date-format/app/perl-date-format_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-db-file", + "server_name": "biosci_perl_db_file", + "tool_name": "perl-db-file", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-db-file/app/perl-db-file_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-db-file/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-db-file/app/perl-db-file_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-dbd-mysql", + "server_name": "biosci_perl_dbd_mysql", + "tool_name": "perl-dbd-mysql", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-dbd-mysql/app/perl-dbd-mysql_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-dbd-mysql/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-dbd-mysql/app/perl-dbd-mysql_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-dbd-sqlite", + "server_name": "biosci_perl_dbd_sqlite", + "tool_name": "perl-dbd-sqlite", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-dbd-sqlite/app/perl-dbd-sqlite_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-dbd-sqlite/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-dbd-sqlite/app/perl-dbd-sqlite_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-dbi", + "server_name": "biosci_perl_dbi", + "tool_name": "perl-dbi", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-dbi/app/perl-dbi_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-dbi/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-dbi/app/perl-dbi_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-devel-globaldestruction", + "server_name": "biosci_perl_devel_globaldestruction", + "tool_name": "perl-devel-globaldestruction", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-devel-globaldestruction/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-devel-overloadinfo", + "server_name": "biosci_perl_devel_overloadinfo", + "tool_name": "perl-devel-overloadinfo", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-devel-overloadinfo/app/perl-devel-overloadinfo_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-devel-overloadinfo/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-devel-overloadinfo/app/perl-devel-overloadinfo_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-devel-stacktrace", + "server_name": "biosci_perl_devel_stacktrace", + "tool_name": "perl-devel-stacktrace", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-devel-stacktrace/app/perl-devel-stacktrace_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-devel-stacktrace/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-devel-stacktrace/app/perl-devel-stacktrace_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-digest-hmac", + "server_name": "biosci_perl_digest_hmac", + "tool_name": "perl-digest-hmac", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-digest-hmac/app/perl-digest-hmac_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-digest-hmac/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-digest-hmac/app/perl-digest-hmac_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-digest-md5", + "server_name": "biosci_perl_digest_md5", + "tool_name": "perl-digest-md5", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-digest-md5/app/perl-digest-md5_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-digest-md5/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-digest-md5/app/perl-digest-md5_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-digest-perl-md5", + "server_name": "biosci_perl_digest_perl_md5", + "tool_name": "perl-digest-perl-md5", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-digest-perl-md5/app/perl-digest-perl-md5_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-digest-perl-md5/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-digest-perl-md5/app/perl-digest-perl-md5_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-digest-sha1", + "server_name": "biosci_perl_digest_sha1", + "tool_name": "perl-digest-sha1", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-digest-sha1/app/perl-digest-sha1_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-digest-sha1/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-digest-sha1/app/perl-digest-sha1_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-dist-checkconflicts", + "server_name": "biosci_perl_dist_checkconflicts", + "tool_name": "perl-dist-checkconflicts", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-dist-checkconflicts/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-dynaloader", + "server_name": "biosci_perl_dynaloader", + "tool_name": "perl-dynaloader", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-dynaloader/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-email-date-format", + "server_name": "biosci_perl_email_date_format", + "tool_name": "perl-email-date-format", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-email-date-format/app/perl-email-date-format_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-email-date-format/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-email-date-format/app/perl-email-date-format_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-encode", + "server_name": "biosci_perl_encode", + "tool_name": "perl-encode", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-encode/app/perl-encode_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-encode/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-encode/app/perl-encode_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-encode-locale", + "server_name": "biosci_perl_encode_locale", + "tool_name": "perl-encode-locale", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-encode-locale/app/perl-encode-locale_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-encode-locale/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-encode-locale/app/perl-encode-locale_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-error", + "server_name": "biosci_perl_error", + "tool_name": "perl-error", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-error/app/perl-error_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-error/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-error/app/perl-error_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-eval-closure", + "server_name": "biosci_perl_eval_closure", + "tool_name": "perl-eval-closure", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-eval-closure/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-exception-class", + "server_name": "biosci_perl_exception_class", + "tool_name": "perl-exception-class", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-exception-class/app/perl-exception-class_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-exception-class/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-exception-class/app/perl-exception-class_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-exporter", + "server_name": "biosci_perl_exporter", + "tool_name": "perl-exporter", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-exporter/app/perl-exporter_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-exporter/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-exporter/app/perl-exporter_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-exporter-tiny", + "server_name": "biosci_perl_exporter_tiny", + "tool_name": "perl-exporter-tiny", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-exporter-tiny/app/perl-exporter-tiny_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-exporter-tiny/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-exporter-tiny/app/perl-exporter-tiny_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-extutils-cbuilder", + "server_name": "biosci_perl_extutils_cbuilder", + "tool_name": "perl-extutils-cbuilder", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-extutils-cbuilder/app/perl-extutils-cbuilder_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-extutils-cbuilder/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-extutils-cbuilder/app/perl-extutils-cbuilder_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-extutils-makemaker", + "server_name": "biosci_perl_extutils_makemaker", + "tool_name": "perl-extutils-makemaker", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-extutils-makemaker/app/perl-extutils-makemaker_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-extutils-makemaker/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-extutils-makemaker/app/perl-extutils-makemaker_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-extutils-manifest", + "server_name": "biosci_perl_extutils_manifest", + "tool_name": "perl-extutils-manifest", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-extutils-manifest/app/perl-extutils-manifest_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-extutils-manifest/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-extutils-manifest/app/perl-extutils-manifest_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-extutils-parsexs", + "server_name": "biosci_perl_extutils_parsexs", + "tool_name": "perl-extutils-parsexs", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-extutils-parsexs/app/perl-extutils-parsexs_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-extutils-parsexs/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-extutils-parsexs/app/perl-extutils-parsexs_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-ffi-checklib", + "server_name": "biosci_perl_ffi_checklib", + "tool_name": "perl-ffi-checklib", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-ffi-checklib/app/perl-ffi-checklib_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-ffi-checklib/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-ffi-checklib/app/perl-ffi-checklib_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-file-listing", + "server_name": "biosci_perl_file_listing", + "tool_name": "perl-file-listing", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-file-listing/app/perl-file-listing_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-file-listing/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-file-listing/app/perl-file-listing_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-file-path", + "server_name": "biosci_perl_file_path", + "tool_name": "perl-file-path", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-file-path/app/perl-file-path_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-file-path/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-file-path/app/perl-file-path_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-file-slurp-tiny", + "server_name": "biosci_perl_file_slurp_tiny", + "tool_name": "perl-file-slurp-tiny", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-file-slurp-tiny/app/perl-file-slurp-tiny_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-file-slurp-tiny/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-file-slurp-tiny/app/perl-file-slurp-tiny_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-file-sort", + "server_name": "biosci_perl_file_sort", + "tool_name": "perl-file-sort", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-file-sort/app/perl-file-sort_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-file-sort/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-file-sort/app/perl-file-sort_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-file-spec", + "server_name": "biosci_perl_file_spec", + "tool_name": "perl-file-spec", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-file-spec/app/perl-file-spec_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-file-spec/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-file-spec/app/perl-file-spec_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-file-temp", + "server_name": "biosci_perl_file_temp", + "tool_name": "perl-file-temp", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-file-temp/app/perl-file-temp_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-file-temp/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-file-temp/app/perl-file-temp_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-file-which", + "server_name": "biosci_perl_file_which", + "tool_name": "perl-file-which", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-file-which/app/perl-file-which_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-file-which/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-file-which/app/perl-file-which_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-font-afm", + "server_name": "biosci_perl_font_afm", + "tool_name": "perl-font-afm", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-font-afm/app/perl-font-afm_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-font-afm/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-font-afm/app/perl-font-afm_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-font-ttf", + "server_name": "biosci_perl_font_ttf", + "tool_name": "perl-font-ttf", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-font-ttf/app/perl-font-ttf_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-font-ttf/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-font-ttf/app/perl-font-ttf_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-gd", + "server_name": "biosci_perl_gd", + "tool_name": "perl-gd", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-gd/app/perl-gd_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-gd/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-gd/app/perl-gd_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-getopt-long", + "server_name": "biosci_perl_getopt_long", + "tool_name": "perl-getopt-long", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-getopt-long/app/perl-getopt-long_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-getopt-long/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-getopt-long/app/perl-getopt-long_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-graph", + "server_name": "biosci_perl_graph", + "tool_name": "perl-graph", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-graph/app/perl-graph_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-graph/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-graph/app/perl-graph_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-graphviz", + "server_name": "biosci_perl_graphviz", + "tool_name": "perl-graphviz", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-graphviz/app/perl-graphviz_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-graphviz/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-graphviz/app/perl-graphviz_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-html-element-extended", + "server_name": "biosci_perl_html_element_extended", + "tool_name": "perl-html-element-extended", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-html-element-extended/app/perl-html-element-extended_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-html-element-extended/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-html-element-extended/app/perl-html-element-extended_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-html-entities-numbered", + "server_name": "biosci_perl_html_entities_numbered", + "tool_name": "perl-html-entities-numbered", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-html-entities-numbered/app/perl-html-entities-numbered_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-html-entities-numbered/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-html-entities-numbered/app/perl-html-entities-numbered_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-html-formatter", + "server_name": "biosci_perl_html_formatter", + "tool_name": "perl-html-formatter", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-html-formatter/app/perl-html-formatter_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-html-formatter/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-html-formatter/app/perl-html-formatter_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-html-parser", + "server_name": "biosci_perl_html_parser", + "tool_name": "perl-html-parser", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-html-parser/app/perl-html-parser_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-html-parser/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-html-parser/app/perl-html-parser_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-html-tableextract", + "server_name": "biosci_perl_html_tableextract", + "tool_name": "perl-html-tableextract", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-html-tableextract/app/perl-html-tableextract_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-html-tableextract/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-html-tableextract/app/perl-html-tableextract_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-html-tagset", + "server_name": "biosci_perl_html_tagset", + "tool_name": "perl-html-tagset", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-html-tagset/app/perl-html-tagset_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-html-tagset/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-html-tagset/app/perl-html-tagset_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-html-tidy", + "server_name": "biosci_perl_html_tidy", + "tool_name": "perl-html-tidy", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-html-tidy/app/perl-html-tidy_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-html-tidy/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-html-tidy/app/perl-html-tidy_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-html-tree", + "server_name": "biosci_perl_html_tree", + "tool_name": "perl-html-tree", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-html-tree/app/perl-html-tree_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-html-tree/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-html-tree/app/perl-html-tree_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-html-treebuilder-xpath", + "server_name": "biosci_perl_html_treebuilder_xpath", + "tool_name": "perl-html-treebuilder-xpath", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-html-treebuilder-xpath/app/perl-html-treebuilder-xpath_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-html-treebuilder-xpath/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-html-treebuilder-xpath/app/perl-html-treebuilder-xpath_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-http-cookies", + "server_name": "biosci_perl_http_cookies", + "tool_name": "perl-http-cookies", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-http-cookies/app/perl-http-cookies_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-http-cookies/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-http-cookies/app/perl-http-cookies_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-http-daemon", + "server_name": "biosci_perl_http_daemon", + "tool_name": "perl-http-daemon", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-http-daemon/app/perl-http-daemon_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-http-daemon/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-http-daemon/app/perl-http-daemon_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-http-date", + "server_name": "biosci_perl_http_date", + "tool_name": "perl-http-date", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-http-date/app/perl-http-date_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-http-date/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-http-date/app/perl-http-date_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-http-message", + "server_name": "biosci_perl_http_message", + "tool_name": "perl-http-message", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-http-message/app/perl-http-message_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-http-message/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-http-message/app/perl-http-message_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-http-negotiate", + "server_name": "biosci_perl_http_negotiate", + "tool_name": "perl-http-negotiate", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-http-negotiate/app/perl-http-negotiate_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-http-negotiate/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-http-negotiate/app/perl-http-negotiate_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-image-info", + "server_name": "biosci_perl_image_info", + "tool_name": "perl-image-info", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-image-info/app/perl-image-info_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-image-info/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-image-info/app/perl-image-info_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-image-size", + "server_name": "biosci_perl_image_size", + "tool_name": "perl-image-size", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-image-size/app/perl-image-size_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-image-size/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-image-size/app/perl-image-size_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-importer", + "server_name": "biosci_perl_importer", + "tool_name": "perl-importer", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-importer/app/perl-importer_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-importer/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-importer/app/perl-importer_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-io-compress", + "server_name": "biosci_perl_io_compress", + "tool_name": "perl-io-compress", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-io-compress/app/perl-io-compress_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-io-compress/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-io-compress/app/perl-io-compress_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-io-html", + "server_name": "biosci_perl_io_html", + "tool_name": "perl-io-html", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-io-html/app/perl-io-html_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-io-html/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-io-html/app/perl-io-html_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-io-sessiondata", + "server_name": "biosci_perl_io_sessiondata", + "tool_name": "perl-io-sessiondata", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-io-sessiondata/app/perl-io-sessiondata_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-io-sessiondata/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-io-sessiondata/app/perl-io-sessiondata_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-io-socket-ssl", + "server_name": "biosci_perl_io_socket_ssl", + "tool_name": "perl-io-socket-ssl", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-io-socket-ssl/app/perl-io-socket-ssl_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-io-socket-ssl/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-io-socket-ssl/app/perl-io-socket-ssl_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-io-string", + "server_name": "biosci_perl_io_string", + "tool_name": "perl-io-string", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-io-string/app/perl-io-string_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-io-string/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-io-string/app/perl-io-string_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-io-stringy", + "server_name": "biosci_perl_io_stringy", + "tool_name": "perl-io-stringy", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-io-stringy/app/perl-io-stringy_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-io-stringy/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-io-stringy/app/perl-io-stringy_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-io-tty", + "server_name": "biosci_perl_io_tty", + "tool_name": "perl-io-tty", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-io-tty/app/perl-io-tty_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-io-tty/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-io-tty/app/perl-io-tty_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-io-zlib", + "server_name": "biosci_perl_io_zlib", + "tool_name": "perl-io-zlib", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-io-zlib/app/perl-io-zlib_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-io-zlib/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-io-zlib/app/perl-io-zlib_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-ipc-cmd", + "server_name": "biosci_perl_ipc_cmd", + "tool_name": "perl-ipc-cmd", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-ipc-cmd/app/perl-ipc-cmd_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-ipc-cmd/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-ipc-cmd/app/perl-ipc-cmd_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-ipc-run", + "server_name": "biosci_perl_ipc_run", + "tool_name": "perl-ipc-run", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-ipc-run/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-ipc-sharelite", + "server_name": "biosci_perl_ipc_sharelite", + "tool_name": "perl-ipc-sharelite", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-ipc-sharelite/app/perl-ipc-sharelite_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-ipc-sharelite/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-ipc-sharelite/app/perl-ipc-sharelite_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-jcode", + "server_name": "biosci_perl_jcode", + "tool_name": "perl-jcode", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-jcode/app/perl-jcode_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-jcode/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-jcode/app/perl-jcode_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-json", + "server_name": "biosci_perl_json", + "tool_name": "perl-json", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-json/app/perl-json_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-json/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-json/app/perl-json_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-json-pp", + "server_name": "biosci_perl_json_pp", + "tool_name": "perl-json-pp", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-json-pp/app/perl-json-pp_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-json-pp/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-json-pp/app/perl-json-pp_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-json-xs", + "server_name": "biosci_perl_json_xs", + "tool_name": "perl-json-xs", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-json-xs/app/perl-json-xs_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-json-xs/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-json-xs/app/perl-json-xs_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-lib", + "server_name": "biosci_perl_lib", + "tool_name": "perl-lib", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-lib/app/perl-lib_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-lib/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-lib/app/perl-lib_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-libwww-perl", + "server_name": "biosci_perl_libwww_perl", + "tool_name": "perl-libwww-perl", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-libwww-perl/app/perl-libwww-perl_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-libwww-perl/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-libwww-perl/app/perl-libwww-perl_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-libxml-perl", + "server_name": "biosci_perl_libxml_perl", + "tool_name": "perl-libxml-perl", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-libxml-perl/app/perl-libxml-perl_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-libxml-perl/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-libxml-perl/app/perl-libxml-perl_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-list-moreutils", + "server_name": "biosci_perl_list_moreutils", + "tool_name": "perl-list-moreutils", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-list-moreutils/app/perl-list-moreutils_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-list-moreutils/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-list-moreutils/app/perl-list-moreutils_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-list-moreutils-xs", + "server_name": "biosci_perl_list_moreutils_xs", + "tool_name": "perl-list-moreutils-xs", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-list-moreutils-xs/app/perl-list-moreutils-xs_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-list-moreutils-xs/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-list-moreutils-xs/app/perl-list-moreutils-xs_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-locale-maketext-simple", + "server_name": "biosci_perl_locale_maketext_simple", + "tool_name": "perl-locale-maketext-simple", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-locale-maketext-simple/app/perl-locale-maketext-simple_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-locale-maketext-simple/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-locale-maketext-simple/app/perl-locale-maketext-simple_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-lwp-mediatypes", + "server_name": "biosci_perl_lwp_mediatypes", + "tool_name": "perl-lwp-mediatypes", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-lwp-mediatypes/app/perl-lwp-mediatypes_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-lwp-mediatypes/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-lwp-mediatypes/app/perl-lwp-mediatypes_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-lwp-protocol-https", + "server_name": "biosci_perl_lwp_protocol_https", + "tool_name": "perl-lwp-protocol-https", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-lwp-protocol-https/app/perl-lwp-protocol-https_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-lwp-protocol-https/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-lwp-protocol-https/app/perl-lwp-protocol-https_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-lwp-simple", + "server_name": "biosci_perl_lwp_simple", + "tool_name": "perl-lwp-simple", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-lwp-simple/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-mailtools", + "server_name": "biosci_perl_mailtools", + "tool_name": "perl-mailtools", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-mailtools/app/perl-mailtools_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-mailtools/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-mailtools/app/perl-mailtools_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-math-bezier", + "server_name": "biosci_perl_math_bezier", + "tool_name": "perl-math-bezier", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-math-bezier/app/perl-math-bezier_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-math-bezier/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-math-bezier/app/perl-math-bezier_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-math-cdf", + "server_name": "biosci_perl_math_cdf", + "tool_name": "perl-math-cdf", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-math-cdf/app/perl-math-cdf_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-math-cdf/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-math-cdf/app/perl-math-cdf_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-math-derivative", + "server_name": "biosci_perl_math_derivative", + "tool_name": "perl-math-derivative", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-math-derivative/app/perl-math-derivative_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-math-derivative/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-math-derivative/app/perl-math-derivative_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-math-random", + "server_name": "biosci_perl_math_random", + "tool_name": "perl-math-random", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-math-random/app/perl-math-random_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-math-random/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-math-random/app/perl-math-random_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-math-round", + "server_name": "biosci_perl_math_round", + "tool_name": "perl-math-round", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-math-round/app/perl-math-round_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-math-round/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-math-round/app/perl-math-round_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-math-spline", + "server_name": "biosci_perl_math_spline", + "tool_name": "perl-math-spline", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-math-spline/app/perl-math-spline_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-math-spline/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-math-spline/app/perl-math-spline_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-math-vecstat", + "server_name": "biosci_perl_math_vecstat", + "tool_name": "perl-math-vecstat", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-math-vecstat/app/perl-math-vecstat_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-math-vecstat/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-math-vecstat/app/perl-math-vecstat_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-mce", + "server_name": "biosci_perl_mce", + "tool_name": "perl-mce", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-mce/app/perl-mce_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-mce/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-mce/app/perl-mce_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-mime-base64", + "server_name": "biosci_perl_mime_base64", + "tool_name": "perl-mime-base64", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-mime-base64/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-mime-lite", + "server_name": "biosci_perl_mime_lite", + "tool_name": "perl-mime-lite", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-mime-lite/app/perl-mime-lite_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-mime-lite/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-mime-lite/app/perl-mime-lite_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-mime-tools", + "server_name": "biosci_perl_mime_tools", + "tool_name": "perl-mime-tools", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-mime-tools/app/perl-mime-tools_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-mime-tools/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-mime-tools/app/perl-mime-tools_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-mime-types", + "server_name": "biosci_perl_mime_types", + "tool_name": "perl-mime-types", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-mime-types/app/perl-mime-types_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-mime-types/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-mime-types/app/perl-mime-types_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-mldbm", + "server_name": "biosci_perl_mldbm", + "tool_name": "perl-mldbm", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-mldbm/app/perl-mldbm_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-mldbm/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-mldbm/app/perl-mldbm_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-module-build", + "server_name": "biosci_perl_module_build", + "tool_name": "perl-module-build", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-module-build/app/perl-module-build_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-module-build/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-module-build/app/perl-module-build_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-module-corelist", + "server_name": "biosci_perl_module_corelist", + "tool_name": "perl-module-corelist", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-module-corelist/app/perl-module-corelist_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-module-corelist/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-module-corelist/app/perl-module-corelist_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-module-implementation", + "server_name": "biosci_perl_module_implementation", + "tool_name": "perl-module-implementation", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-module-implementation/app/perl-module-implementation_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-module-implementation/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-module-implementation/app/perl-module-implementation_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-module-load", + "server_name": "biosci_perl_module_load", + "tool_name": "perl-module-load", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-module-load/app/perl-module-load_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-module-load/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-module-load/app/perl-module-load_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-module-load-conditional", + "server_name": "biosci_perl_module_load_conditional", + "tool_name": "perl-module-load-conditional", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-module-load-conditional/app/perl-module-load-conditional_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-module-load-conditional/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-module-load-conditional/app/perl-module-load-conditional_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-module-metadata", + "server_name": "biosci_perl_module_metadata", + "tool_name": "perl-module-metadata", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-module-metadata/app/perl-module-metadata_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-module-metadata/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-module-metadata/app/perl-module-metadata_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-module-runtime", + "server_name": "biosci_perl_module_runtime", + "tool_name": "perl-module-runtime", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-module-runtime/app/perl-module-runtime_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-module-runtime/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-module-runtime/app/perl-module-runtime_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-module-runtime-conflicts", + "server_name": "biosci_perl_module_runtime_conflicts", + "tool_name": "perl-module-runtime-conflicts", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-module-runtime-conflicts/app/perl-module-runtime-conflicts_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-module-runtime-conflicts/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-module-runtime-conflicts/app/perl-module-runtime-conflicts_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-moo", + "server_name": "biosci_perl_moo", + "tool_name": "perl-moo", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-moo/app/perl-moo_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-moo/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-moo/app/perl-moo_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-moose", + "server_name": "biosci_perl_moose", + "tool_name": "perl-moose", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-moose/app/perl-moose_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-moose/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-moose/app/perl-moose_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-mozilla-ca", + "server_name": "biosci_perl_mozilla_ca", + "tool_name": "perl-mozilla-ca", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-mozilla-ca/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-mro-compat", + "server_name": "biosci_perl_mro_compat", + "tool_name": "perl-mro-compat", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-mro-compat/app/perl-mro-compat_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-mro-compat/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-mro-compat/app/perl-mro-compat_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-net-http", + "server_name": "biosci_perl_net_http", + "tool_name": "perl-net-http", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-net-http/app/perl-net-http_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-net-http/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-net-http/app/perl-net-http_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-net-ssleay", + "server_name": "biosci_perl_net_ssleay", + "tool_name": "perl-net-ssleay", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-net-ssleay/app/perl-net-ssleay_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-net-ssleay/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-net-ssleay/app/perl-net-ssleay_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-ntlm", + "server_name": "biosci_perl_ntlm", + "tool_name": "perl-ntlm", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-ntlm/app/perl-ntlm_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-ntlm/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-ntlm/app/perl-ntlm_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-number-format", + "server_name": "biosci_perl_number_format", + "tool_name": "perl-number-format", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-number-format/app/perl-number-format_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-number-format/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-number-format/app/perl-number-format_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-ole-storage_lite", + "server_name": "biosci_perl_ole_storage_lite", + "tool_name": "perl-ole-storage_lite", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-ole-storage_lite/app/perl-ole-storage_lite_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-ole-storage_lite/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-ole-storage_lite/app/perl-ole-storage_lite_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-package-deprecationmanager", + "server_name": "biosci_perl_package_deprecationmanager", + "tool_name": "perl-package-deprecationmanager", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-package-deprecationmanager/app/perl-package-deprecationmanager_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-package-deprecationmanager/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-package-deprecationmanager/app/perl-package-deprecationmanager_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-package-stash", + "server_name": "biosci_perl_package_stash", + "tool_name": "perl-package-stash", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-package-stash/app/perl-package-stash_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-package-stash/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-package-stash/app/perl-package-stash_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-package-stash-xs", + "server_name": "biosci_perl_package_stash_xs", + "tool_name": "perl-package-stash-xs", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-package-stash-xs/app/perl-package-stash-xs_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-package-stash-xs/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-package-stash-xs/app/perl-package-stash-xs_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-parallel-forkmanager", + "server_name": "biosci_perl_parallel_forkmanager", + "tool_name": "perl-parallel-forkmanager", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-parallel-forkmanager/app/perl-parallel-forkmanager_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-parallel-forkmanager/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-parallel-forkmanager/app/perl-parallel-forkmanager_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-params-check", + "server_name": "biosci_perl_params_check", + "tool_name": "perl-params-check", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-params-check/app/perl-params-check_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-params-check/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-params-check/app/perl-params-check_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-params-util", + "server_name": "biosci_perl_params_util", + "tool_name": "perl-params-util", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-params-util/app/perl-params-util_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-params-util/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-params-util/app/perl-params-util_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-params-validate", + "server_name": "biosci_perl_params_validate", + "tool_name": "perl-params-validate", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-params-validate/app/perl-params-validate_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-params-validate/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-params-validate/app/perl-params-validate_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-parent", + "server_name": "biosci_perl_parent", + "tool_name": "perl-parent", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-parent/app/perl-parent_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-parent/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-parent/app/perl-parent_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-parse-recdescent", + "server_name": "biosci_perl_parse_recdescent", + "tool_name": "perl-parse-recdescent", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-parse-recdescent/app/perl-parse-recdescent_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-parse-recdescent/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-parse-recdescent/app/perl-parse-recdescent_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-path-tiny", + "server_name": "biosci_perl_path_tiny", + "tool_name": "perl-path-tiny", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-path-tiny/app/perl-path-tiny_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-path-tiny/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-path-tiny/app/perl-path-tiny_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-pathtools", + "server_name": "biosci_perl_pathtools", + "tool_name": "perl-pathtools", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-pathtools/app/perl-pathtools_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-pathtools/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-pathtools/app/perl-pathtools_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-pdf-api2", + "server_name": "biosci_perl_pdf_api2", + "tool_name": "perl-pdf-api2", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-pdf-api2/app/perl-pdf-api2_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-pdf-api2/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-pdf-api2/app/perl-pdf-api2_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-perlio-gzip", + "server_name": "biosci_perl_perlio_gzip", + "tool_name": "perl-perlio-gzip", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-perlio-gzip/app/perl-perlio-gzip_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-perlio-gzip/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-perlio-gzip/app/perl-perlio-gzip_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-pod-escapes", + "server_name": "biosci_perl_pod_escapes", + "tool_name": "perl-pod-escapes", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-pod-escapes/app/perl-pod-escapes_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-pod-escapes/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-pod-escapes/app/perl-pod-escapes_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-pod-usage", + "server_name": "biosci_perl_pod_usage", + "tool_name": "perl-pod-usage", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-pod-usage/app/perl-pod-usage_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-pod-usage/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-pod-usage/app/perl-pod-usage_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-postscript", + "server_name": "biosci_perl_postscript", + "tool_name": "perl-postscript", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-postscript/app/perl-postscript_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-postscript/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-postscript/app/perl-postscript_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-readonly", + "server_name": "biosci_perl_readonly", + "tool_name": "perl-readonly", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-readonly/app/perl-readonly_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-readonly/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-readonly/app/perl-readonly_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-regexp-common", + "server_name": "biosci_perl_regexp_common", + "tool_name": "perl-regexp-common", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-regexp-common/app/perl-regexp-common_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-regexp-common/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-regexp-common/app/perl-regexp-common_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-role-tiny", + "server_name": "biosci_perl_role_tiny", + "tool_name": "perl-role-tiny", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-role-tiny/app/perl-role-tiny_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-role-tiny/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-role-tiny/app/perl-role-tiny_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-scalar-list-utils", + "server_name": "biosci_perl_scalar_list_utils", + "tool_name": "perl-scalar-list-utils", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-scalar-list-utils/app/perl-scalar-list-utils_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-scalar-list-utils/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-scalar-list-utils/app/perl-scalar-list-utils_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-sereal", + "server_name": "biosci_perl_sereal", + "tool_name": "perl-sereal", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-sereal/app/perl-sereal_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-sereal/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-sereal/app/perl-sereal_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-sereal-decoder", + "server_name": "biosci_perl_sereal_decoder", + "tool_name": "perl-sereal-decoder", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-sereal-decoder/app/perl-sereal-decoder_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-sereal-decoder/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-sereal-decoder/app/perl-sereal-decoder_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-sereal-encoder", + "server_name": "biosci_perl_sereal_encoder", + "tool_name": "perl-sereal-encoder", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-sereal-encoder/app/perl-sereal-encoder_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-sereal-encoder/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-sereal-encoder/app/perl-sereal-encoder_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-set-intervaltree", + "server_name": "biosci_perl_set_intervaltree", + "tool_name": "perl-set-intervaltree", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-set-intervaltree/app/perl-set-intervaltree_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-set-intervaltree/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-set-intervaltree/app/perl-set-intervaltree_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-set-intspan", + "server_name": "biosci_perl_set_intspan", + "tool_name": "perl-set-intspan", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-set-intspan/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-set-scalar", + "server_name": "biosci_perl_set_scalar", + "tool_name": "perl-set-scalar", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-set-scalar/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-soap-lite", + "server_name": "biosci_perl_soap_lite", + "tool_name": "perl-soap-lite", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-soap-lite/app/perl-soap-lite_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-soap-lite/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-soap-lite/app/perl-soap-lite_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-socket", + "server_name": "biosci_perl_socket", + "tool_name": "perl-socket", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-socket/app/perl-socket_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-socket/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-socket/app/perl-socket_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-sort-naturally", + "server_name": "biosci_perl_sort_naturally", + "tool_name": "perl-sort-naturally", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-sort-naturally/app/perl-sort-naturally_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-sort-naturally/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-sort-naturally/app/perl-sort-naturally_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-spreadsheet-parseexcel", + "server_name": "biosci_perl_spreadsheet_parseexcel", + "tool_name": "perl-spreadsheet-parseexcel", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-spreadsheet-parseexcel/app/perl-spreadsheet-parseexcel_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-spreadsheet-parseexcel/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-spreadsheet-parseexcel/app/perl-spreadsheet-parseexcel_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-spreadsheet-writeexcel", + "server_name": "biosci_perl_spreadsheet_writeexcel", + "tool_name": "perl-spreadsheet-writeexcel", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-spreadsheet-writeexcel/app/perl-spreadsheet-writeexcel_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-spreadsheet-writeexcel/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-spreadsheet-writeexcel/app/perl-spreadsheet-writeexcel_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-statistics-basic", + "server_name": "biosci_perl_statistics_basic", + "tool_name": "perl-statistics-basic", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-statistics-basic/app/perl-statistics-basic_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-statistics-basic/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-statistics-basic/app/perl-statistics-basic_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-statistics-descriptive", + "server_name": "biosci_perl_statistics_descriptive", + "tool_name": "perl-statistics-descriptive", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-statistics-descriptive/app/perl-statistics-descriptive_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-statistics-descriptive/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-statistics-descriptive/app/perl-statistics-descriptive_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-storable", + "server_name": "biosci_perl_storable", + "tool_name": "perl-storable", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-storable/app/perl-storable_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-storable/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-storable/app/perl-storable_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-sub-exporter", + "server_name": "biosci_perl_sub_exporter", + "tool_name": "perl-sub-exporter", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-sub-exporter/app/perl-sub-exporter_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-sub-exporter/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-sub-exporter/app/perl-sub-exporter_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-sub-exporter-progressive", + "server_name": "biosci_perl_sub_exporter_progressive", + "tool_name": "perl-sub-exporter-progressive", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-sub-exporter-progressive/app/perl-sub-exporter-progressive_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-sub-exporter-progressive/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-sub-exporter-progressive/app/perl-sub-exporter-progressive_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-sub-identify", + "server_name": "biosci_perl_sub_identify", + "tool_name": "perl-sub-identify", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-sub-identify/app/perl-sub-identify_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-sub-identify/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-sub-identify/app/perl-sub-identify_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-sub-install", + "server_name": "biosci_perl_sub_install", + "tool_name": "perl-sub-install", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-sub-install/app/perl-sub-install_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-sub-install/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-sub-install/app/perl-sub-install_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-sub-name", + "server_name": "biosci_perl_sub_name", + "tool_name": "perl-sub-name", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-sub-name/app/perl-sub-name_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-sub-name/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-sub-name/app/perl-sub-name_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-sub-quote", + "server_name": "biosci_perl_sub_quote", + "tool_name": "perl-sub-quote", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-sub-quote/app/perl-sub-quote_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-sub-quote/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-sub-quote/app/perl-sub-quote_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-sub-uplevel", + "server_name": "biosci_perl_sub_uplevel", + "tool_name": "perl-sub-uplevel", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-sub-uplevel/app/perl-sub-uplevel_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-sub-uplevel/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-sub-uplevel/app/perl-sub-uplevel_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-svg", + "server_name": "biosci_perl_svg", + "tool_name": "perl-svg", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-svg/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-svg-graph", + "server_name": "biosci_perl_svg_graph", + "tool_name": "perl-svg-graph", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-svg-graph/app/perl-svg-graph_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-svg-graph/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-svg-graph/app/perl-svg-graph_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-task-weaken", + "server_name": "biosci_perl_task_weaken", + "tool_name": "perl-task-weaken", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-task-weaken/app/perl-task-weaken_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-task-weaken/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-task-weaken/app/perl-task-weaken_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-template-toolkit", + "server_name": "biosci_perl_template_toolkit", + "tool_name": "perl-template-toolkit", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-template-toolkit/app/perl-template-toolkit_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-template-toolkit/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-template-toolkit/app/perl-template-toolkit_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-term-table", + "server_name": "biosci_perl_term_table", + "tool_name": "perl-term-table", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-term-table/app/perl-term-table_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-term-table/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-term-table/app/perl-term-table_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-test", + "server_name": "biosci_perl_test", + "tool_name": "perl-test", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-test/app/perl-test_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-test/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-test/app/perl-test_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-test-deep", + "server_name": "biosci_perl_test_deep", + "tool_name": "perl-test-deep", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-test-deep/app/perl-test-deep_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-test-deep/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-test-deep/app/perl-test-deep_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-test-differences", + "server_name": "biosci_perl_test_differences", + "tool_name": "perl-test-differences", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-test-differences/app/perl-test-differences_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-test-differences/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-test-differences/app/perl-test-differences_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-test-exception", + "server_name": "biosci_perl_test_exception", + "tool_name": "perl-test-exception", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-test-exception/app/perl-test-exception_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-test-exception/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-test-exception/app/perl-test-exception_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-test-fatal", + "server_name": "biosci_perl_test_fatal", + "tool_name": "perl-test-fatal", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-test-fatal/app/perl-test-fatal_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-test-fatal/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-test-fatal/app/perl-test-fatal_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-test-harness", + "server_name": "biosci_perl_test_harness", + "tool_name": "perl-test-harness", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-test-harness/app/perl-test-harness_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-test-harness/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-test-harness/app/perl-test-harness_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-test-leaktrace", + "server_name": "biosci_perl_test_leaktrace", + "tool_name": "perl-test-leaktrace", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-test-leaktrace/app/perl-test-leaktrace_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-test-leaktrace/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-test-leaktrace/app/perl-test-leaktrace_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-test-more", + "server_name": "biosci_perl_test_more", + "tool_name": "perl-test-more", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-test-more/app/perl-test-more_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-test-more/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-test-more/app/perl-test-more_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-test-most", + "server_name": "biosci_perl_test_most", + "tool_name": "perl-test-most", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-test-most/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-test-requiresinternet", + "server_name": "biosci_perl_test_requiresinternet", + "tool_name": "perl-test-requiresinternet", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-test-requiresinternet/app/perl-test-requiresinternet_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-test-requiresinternet/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-test-requiresinternet/app/perl-test-requiresinternet_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-test-warn", + "server_name": "biosci_perl_test_warn", + "tool_name": "perl-test-warn", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-test-warn/app/perl-test-warn_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-test-warn/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-test-warn/app/perl-test-warn_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-test2-suite", + "server_name": "biosci_perl_test2_suite", + "tool_name": "perl-test2-suite", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-test2-suite/app/perl-test2-suite_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-test2-suite/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-test2-suite/app/perl-test2-suite_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-text-csv", + "server_name": "biosci_perl_text_csv", + "tool_name": "perl-text-csv", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-text-csv/app/perl-text-csv_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-text-csv/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-text-csv/app/perl-text-csv_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-text-diff", + "server_name": "biosci_perl_text_diff", + "tool_name": "perl-text-diff", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-text-diff/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-text-format", + "server_name": "biosci_perl_text_format", + "tool_name": "perl-text-format", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-text-format/app/perl-text-format_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-text-format/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-text-format/app/perl-text-format_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-text-parsewords", + "server_name": "biosci_perl_text_parsewords", + "tool_name": "perl-text-parsewords", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-text-parsewords/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-threaded", + "server_name": "biosci_perl_threaded", + "tool_name": "perl-threaded", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-threaded/app/perl-threaded_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-threaded/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-threaded/app/perl-threaded_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-tie-ixhash", + "server_name": "biosci_perl_tie_ixhash", + "tool_name": "perl-tie-ixhash", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-tie-ixhash/app/perl-tie-ixhash_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-tie-ixhash/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-tie-ixhash/app/perl-tie-ixhash_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-time-hires", + "server_name": "biosci_perl_time_hires", + "tool_name": "perl-time-hires", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-time-hires/app/perl-time-hires_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-time-hires/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-time-hires/app/perl-time-hires_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-time-local", + "server_name": "biosci_perl_time_local", + "tool_name": "perl-time-local", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-time-local/app/perl-time-local_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-time-local/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-time-local/app/perl-time-local_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-timedate", + "server_name": "biosci_perl_timedate", + "tool_name": "perl-timedate", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-timedate/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-tree-dag_node", + "server_name": "biosci_perl_tree_dag_node", + "tool_name": "perl-tree-dag_node", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-tree-dag_node/app/perl-tree-dag_node_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-tree-dag_node/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-tree-dag_node/app/perl-tree-dag_node_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-try-tiny", + "server_name": "biosci_perl_try_tiny", + "tool_name": "perl-try-tiny", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-try-tiny/app/perl-try-tiny_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-try-tiny/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-try-tiny/app/perl-try-tiny_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-type-tiny", + "server_name": "biosci_perl_type_tiny", + "tool_name": "perl-type-tiny", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-type-tiny/app/perl-type-tiny_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-type-tiny/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-type-tiny/app/perl-type-tiny_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-types-serialiser", + "server_name": "biosci_perl_types_serialiser", + "tool_name": "perl-types-serialiser", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-types-serialiser/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-unicode-map", + "server_name": "biosci_perl_unicode_map", + "tool_name": "perl-unicode-map", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-unicode-map/app/perl-unicode-map_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-unicode-map/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-unicode-map/app/perl-unicode-map_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-uri", + "server_name": "biosci_perl_uri", + "tool_name": "perl-uri", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-uri/app/perl-uri_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-uri/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-uri/app/perl-uri_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-url-encode", + "server_name": "biosci_perl_url_encode", + "tool_name": "perl-url-encode", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-url-encode/app/perl-url-encode_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-url-encode/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-url-encode/app/perl-url-encode_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-version", + "server_name": "biosci_perl_version", + "tool_name": "perl-version", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-version/app/perl-version_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-version/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-version/app/perl-version_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-www-robotrules", + "server_name": "biosci_perl_www_robotrules", + "tool_name": "perl-www-robotrules", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-www-robotrules/app/perl-www-robotrules_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-www-robotrules/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-www-robotrules/app/perl-www-robotrules_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-dom", + "server_name": "biosci_perl_xml_dom", + "tool_name": "perl-xml-dom", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-dom/app/perl-xml-dom_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-dom/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-dom/app/perl-xml-dom_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-dom-xpath", + "server_name": "biosci_perl_xml_dom_xpath", + "tool_name": "perl-xml-dom-xpath", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-dom-xpath/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-filter-buffertext", + "server_name": "biosci_perl_xml_filter_buffertext", + "tool_name": "perl-xml-filter-buffertext", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-filter-buffertext/app/perl-xml-filter-buffertext_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-filter-buffertext/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-filter-buffertext/app/perl-xml-filter-buffertext_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-libxml", + "server_name": "biosci_perl_xml_libxml", + "tool_name": "perl-xml-libxml", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-libxml/app/perl-xml-libxml_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-libxml/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-libxml/app/perl-xml-libxml_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-libxslt", + "server_name": "biosci_perl_xml_libxslt", + "tool_name": "perl-xml-libxslt", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-libxslt/app/perl-xml-libxslt_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-libxslt/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-libxslt/app/perl-xml-libxslt_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-namespacesupport", + "server_name": "biosci_perl_xml_namespacesupport", + "tool_name": "perl-xml-namespacesupport", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-namespacesupport/app/perl-xml-namespacesupport_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-namespacesupport/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-namespacesupport/app/perl-xml-namespacesupport_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-parser", + "server_name": "biosci_perl_xml_parser", + "tool_name": "perl-xml-parser", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-parser/app/perl-xml-parser_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-parser/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-parser/app/perl-xml-parser_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-regexp", + "server_name": "biosci_perl_xml_regexp", + "tool_name": "perl-xml-regexp", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-regexp/app/perl-xml-regexp_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-regexp/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-regexp/app/perl-xml-regexp_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-sax", + "server_name": "biosci_perl_xml_sax", + "tool_name": "perl-xml-sax", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-sax/app/perl-xml-sax_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-sax/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-sax/app/perl-xml-sax_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-sax-base", + "server_name": "biosci_perl_xml_sax_base", + "tool_name": "perl-xml-sax-base", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-sax-base/app/perl-xml-sax-base_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-sax-base/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-sax-base/app/perl-xml-sax-base_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-sax-expat", + "server_name": "biosci_perl_xml_sax_expat", + "tool_name": "perl-xml-sax-expat", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-sax-expat/app/perl-xml-sax-expat_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-sax-expat/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-sax-expat/app/perl-xml-sax-expat_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-sax-writer", + "server_name": "biosci_perl_xml_sax_writer", + "tool_name": "perl-xml-sax-writer", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-sax-writer/app/perl-xml-sax-writer_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-sax-writer/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-sax-writer/app/perl-xml-sax-writer_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-simple", + "server_name": "biosci_perl_xml_simple", + "tool_name": "perl-xml-simple", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-simple/app/perl-xml-simple_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-simple/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-simple/app/perl-xml-simple_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-twig", + "server_name": "biosci_perl_xml_twig", + "tool_name": "perl-xml-twig", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-twig/app/perl-xml-twig_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-twig/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-twig/app/perl-xml-twig_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-writer", + "server_name": "biosci_perl_xml_writer", + "tool_name": "perl-xml-writer", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-writer/app/perl-xml-writer_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-writer/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-writer/app/perl-xml-writer_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-xpath", + "server_name": "biosci_perl_xml_xpath", + "tool_name": "perl-xml-xpath", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-xpath/app/perl-xml-xpath_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-xpath/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-xpath/app/perl-xml-xpath_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-xpathengine", + "server_name": "biosci_perl_xml_xpathengine", + "tool_name": "perl-xml-xpathengine", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-xpathengine/app/perl-xml-xpathengine_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-xpathengine/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xml-xpathengine/app/perl-xml-xpathengine_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xsloader", + "server_name": "biosci_perl_xsloader", + "tool_name": "perl-xsloader", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xsloader/app/perl-xsloader_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xsloader/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-xsloader/app/perl-xsloader_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-yaml", + "server_name": "biosci_perl_yaml", + "tool_name": "perl-yaml", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-yaml/app/perl-yaml_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-yaml/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_perl-yaml/app/perl-yaml_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_phyml", + "server_name": "biosci_phyml", + "tool_name": "phyml", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_phyml/app/phyml_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_phyml/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_phyml/app/phyml_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_piaso", + "server_name": "biosci_piaso", + "tool_name": "piaso", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_piaso/app/piaso_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_piaso/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_piaso/app/piaso_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_picard", + "server_name": "biosci_picard", + "tool_name": "picard", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_picard/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_picard-slim", + "server_name": "biosci_picard_slim", + "tool_name": "picard-slim", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_picard-slim/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pilon", + "server_name": "biosci_pilon", + "tool_name": "pilon", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pilon/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pixelator", + "server_name": "biosci_pixelator", + "tool_name": "pixelator", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pixelator/app/pixelator_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pixelator/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pixelator/app/pixelator_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_planemo", + "server_name": "biosci_planemo", + "tool_name": "planemo", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_planemo/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_plink", + "server_name": "biosci_plink", + "tool_name": "plink", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_plink/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_poa", + "server_name": "biosci_poa", + "tool_name": "poa", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_poa/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_portcullis", + "server_name": "biosci_portcullis", + "tool_name": "portcullis", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_portcullis/app/portcullis_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_portcullis/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_portcullis/app/portcullis_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pplacer", + "server_name": "biosci_pplacer", + "tool_name": "pplacer", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pplacer/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_prank", + "server_name": "biosci_prank", + "tool_name": "prank", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_prank/app/prank_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_prank/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_prank/app/prank_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_primer3", + "server_name": "biosci_primer3", + "tool_name": "primer3", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_primer3/app/primer3_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_primer3/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_primer3/app/primer3_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_primer3-py", + "server_name": "biosci_primer3_py", + "tool_name": "primer3-py", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_primer3-py/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_prodigal", + "server_name": "biosci_prodigal", + "tool_name": "prodigal", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_prodigal/app/prodigal_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_prodigal/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_prodigal/app/prodigal_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_prokka", + "server_name": "biosci_prokka", + "tool_name": "prokka", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_prokka/app/prokka_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_prokka/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_prokka/app/prokka_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_prophyle", + "server_name": "biosci_prophyle", + "tool_name": "prophyle", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_prophyle/app/prophyle_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_prophyle/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_prophyle/app/prophyle_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_proteinortho", + "server_name": "biosci_proteinortho", + "tool_name": "proteinortho", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_proteinortho/app/proteinortho_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_proteinortho/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_proteinortho/app/proteinortho_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_proteomiqon-peptidedb", + "server_name": "biosci_proteomiqon_peptidedb", + "tool_name": "proteomiqon-peptidedb", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_proteomiqon-peptidedb/app/proteomiqon-peptidedb_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_proteomiqon-peptidedb/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_proteomiqon-peptidedb/app/proteomiqon-peptidedb_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_proteomiqon-peptidespectrummatching", + "server_name": "biosci_proteomiqon_peptidespectrummatching", + "tool_name": "proteomiqon-peptidespectrummatching", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_proteomiqon-peptidespectrummatching/app/proteomiqon-peptidespectrummatching_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_proteomiqon-peptidespectrummatching/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_proteomiqon-peptidespectrummatching/app/proteomiqon-peptidespectrummatching_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pubchempy", + "server_name": "biosci_pubchempy", + "tool_name": "pubchempy", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pubchempy/app/pubchempy_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pubchempy/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pubchempy/app/pubchempy_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_py2bit", + "server_name": "biosci_py2bit", + "tool_name": "py2bit", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_py2bit/app/py2bit_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_py2bit/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_py2bit/app/py2bit_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pybedtools", + "server_name": "biosci_pybedtools", + "tool_name": "pybedtools", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pybedtools/app/pybedtools_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pybedtools/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pybedtools/app/pybedtools_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pybigwig", + "server_name": "biosci_pybigwig", + "tool_name": "pybigwig", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pybigwig/app/pybigwig_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pybigwig/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pybigwig/app/pybigwig_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pybiolib", + "server_name": "biosci_pybiolib", + "tool_name": "pybiolib", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pybiolib/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pyfaidx", + "server_name": "biosci_pyfaidx", + "tool_name": "pyfaidx", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pyfaidx/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pyfastx", + "server_name": "biosci_pyfastx", + "tool_name": "pyfastx", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pyfastx/app/pyfastx_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pyfastx/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pyfastx/app/pyfastx_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pyhmmer", + "server_name": "biosci_pyhmmer", + "tool_name": "pyhmmer", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pyhmmer/app/pyhmmer_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pyhmmer/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pyhmmer/app/pyhmmer_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pyranges", + "server_name": "biosci_pyranges", + "tool_name": "pyranges", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pyranges/app/pyranges_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pyranges/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pyranges/app/pyranges_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pyrle", + "server_name": "biosci_pyrle", + "tool_name": "pyrle", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pyrle/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pyrodigal", + "server_name": "biosci_pyrodigal", + "tool_name": "pyrodigal", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pyrodigal/app/pyrodigal_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pyrodigal/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pyrodigal/app/pyrodigal_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pyrovelocity", + "server_name": "biosci_pyrovelocity", + "tool_name": "pyrovelocity", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pyrovelocity/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pysam", + "server_name": "biosci_pysam", + "tool_name": "pysam", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pysam/app/pysam_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pysam/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pysam/app/pysam_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pysftp", + "server_name": "biosci_pysftp", + "tool_name": "pysftp", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pysftp/app/pysftp_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pysftp/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pysftp/app/pysftp_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pyspoa", + "server_name": "biosci_pyspoa", + "tool_name": "pyspoa", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pyspoa/app/pyspoa_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pyspoa/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pyspoa/app/pyspoa_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pytabix", + "server_name": "biosci_pytabix", + "tool_name": "pytabix", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pytabix/app/pytabix_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pytabix/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pytabix/app/pytabix_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pyteomics", + "server_name": "biosci_pyteomics", + "tool_name": "pyteomics", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pyteomics/app/pyteomics_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pyteomics/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pyteomics/app/pyteomics_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_python-edlib", + "server_name": "biosci_python_edlib", + "tool_name": "python-edlib", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_python-edlib/app/python-edlib_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_python-edlib/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_python-edlib/app/python-edlib_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pyvcf", + "server_name": "biosci_pyvcf", + "tool_name": "pyvcf", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pyvcf/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pyvcf3", + "server_name": "biosci_pyvcf3", + "tool_name": "pyvcf3", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pyvcf3/app/pyvcf3_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pyvcf3/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_pyvcf3/app/pyvcf3_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_qcatch", + "server_name": "biosci_qcatch", + "tool_name": "qcatch", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_qcatch/app/qcatch_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_qcatch/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_qcatch/app/qcatch_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_qiime", + "server_name": "biosci_qiime", + "tool_name": "qiime", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_qiime/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_qualimap", + "server_name": "biosci_qualimap", + "tool_name": "qualimap", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_qualimap/app/qualimap_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_qualimap/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_qualimap/app/qualimap_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_quast", + "server_name": "biosci_quast", + "tool_name": "quast", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_quast/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-abdiv", + "server_name": "biosci_r_abdiv", + "tool_name": "r-abdiv", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-abdiv/app/r-abdiv_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-abdiv/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-abdiv/app/r-abdiv_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-acidbase", + "server_name": "biosci_r_acidbase", + "tool_name": "r-acidbase", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-acidbase/app/r-acidbase_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-acidbase/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-acidbase/app/r-acidbase_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-archr", + "server_name": "biosci_r_archr", + "tool_name": "r-archr", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-archr/app/r-archr_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-archr/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-archr/app/r-archr_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-azimuth", + "server_name": "biosci_r_azimuth", + "tool_name": "r-azimuth", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-azimuth/app/r-azimuth_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-azimuth/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-azimuth/app/r-azimuth_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-basejump", + "server_name": "biosci_r_basejump", + "tool_name": "r-basejump", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-basejump/app/r-basejump_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-basejump/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-basejump/app/r-basejump_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-beyondcell", + "server_name": "biosci_r_beyondcell", + "tool_name": "r-beyondcell", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-beyondcell/app/r-beyondcell_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-beyondcell/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-beyondcell/app/r-beyondcell_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-cdseq", + "server_name": "biosci_r_cdseq", + "tool_name": "r-cdseq", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-cdseq/app/r-cdseq_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-cdseq/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-cdseq/app/r-cdseq_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-dwls", + "server_name": "biosci_r_dwls", + "tool_name": "r-dwls", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-dwls/app/r-dwls_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-dwls/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-dwls/app/r-dwls_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-epitrace", + "server_name": "biosci_r_epitrace", + "tool_name": "r-epitrace", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-epitrace/app/r-epitrace_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-epitrace/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-epitrace/app/r-epitrace_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-flanders", + "server_name": "biosci_r_flanders", + "tool_name": "r-flanders", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-flanders/app/r-flanders_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-flanders/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-flanders/app/r-flanders_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-goalie", + "server_name": "biosci_r_goalie", + "tool_name": "r-goalie", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-goalie/app/r-goalie_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-goalie/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-goalie/app/r-goalie_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-mams", + "server_name": "biosci_r_mams", + "tool_name": "r-mams", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-mams/app/r-mams_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-mams/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-mams/app/r-mams_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-redeemr", + "server_name": "biosci_r_redeemr", + "tool_name": "r-redeemr", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-redeemr/app/r-redeemr_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-redeemr/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-redeemr/app/r-redeemr_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-restfulr", + "server_name": "biosci_r_restfulr", + "tool_name": "r-restfulr", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-restfulr/app/r-restfulr_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-restfulr/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-restfulr/app/r-restfulr_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-saige", + "server_name": "biosci_r_saige", + "tool_name": "r-saige", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-saige/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-sceasy", + "server_name": "biosci_r_sceasy", + "tool_name": "r-sceasy", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-sceasy/app/r-sceasy_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-sceasy/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-sceasy/app/r-sceasy_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-scopfunctions", + "server_name": "biosci_r_scopfunctions", + "tool_name": "r-scopfunctions", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-scopfunctions/app/r-scopfunctions_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-scopfunctions/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-scopfunctions/app/r-scopfunctions_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-seurat-data", + "server_name": "biosci_r_seurat_data", + "tool_name": "r-seurat-data", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-seurat-data/app/r-seurat-data_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-seurat-data/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-seurat-data/app/r-seurat-data_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-seurat-disk", + "server_name": "biosci_r_seurat_disk", + "tool_name": "r-seurat-disk", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-seurat-disk/app/r-seurat-disk_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-seurat-disk/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_r-seurat-disk/app/r-seurat-disk_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_racon", + "server_name": "biosci_racon", + "tool_name": "racon", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_racon/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_raxml", + "server_name": "biosci_raxml", + "tool_name": "raxml", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_raxml/app/raxml_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_raxml/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_raxml/app/raxml_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_recognizer", + "server_name": "biosci_recognizer", + "tool_name": "recognizer", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_recognizer/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_repeatmasker", + "server_name": "biosci_repeatmasker", + "tool_name": "repeatmasker", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_repeatmasker/app/repeatmasker_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_repeatmasker/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_repeatmasker/app/repeatmasker_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_rgi", + "server_name": "biosci_rgi", + "tool_name": "rgi", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_rgi/app/rgi_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_rgi/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_rgi/app/rgi_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_rnastructure", + "server_name": "biosci_rnastructure", + "tool_name": "rnastructure", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_rnastructure/app/rnastructure_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_rnastructure/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_rnastructure/app/rnastructure_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_rnftools", + "server_name": "biosci_rnftools", + "tool_name": "rnftools", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_rnftools/app/rnftools_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_rnftools/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_rnftools/app/rnftools_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_rpsbproc", + "server_name": "biosci_rpsbproc", + "tool_name": "rpsbproc", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_rpsbproc/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_rsa", + "server_name": "biosci_rsa", + "tool_name": "rsa", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_rsa/app/rsa_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_rsa/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_rsa/app/rsa_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_rscape", + "server_name": "biosci_rscape", + "tool_name": "rscape", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_rscape/app/rscape_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_rscape/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_rscape/app/rscape_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_rsem", + "server_name": "biosci_rsem", + "tool_name": "rsem", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_rsem/app/rsem_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_rsem/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_rsem/app/rsem_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_rseqc", + "server_name": "biosci_rseqc", + "tool_name": "rseqc", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_rseqc/app/rseqc_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_rseqc/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_rseqc/app/rseqc_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_rtg-tools", + "server_name": "biosci_rtg_tools", + "tool_name": "rtg-tools", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_rtg-tools/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_rust-bio-tools", + "server_name": "biosci_rust_bio_tools", + "tool_name": "rust-bio-tools", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_rust-bio-tools/app/rust-bio-tools_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_rust-bio-tools/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_rust-bio-tools/app/rust-bio-tools_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sage-proteomics", + "server_name": "biosci_sage_proteomics", + "tool_name": "sage-proteomics", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sage-proteomics/app/sage-proteomics_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sage-proteomics/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sage-proteomics/app/sage-proteomics_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_salmon", + "server_name": "biosci_salmon", + "tool_name": "salmon", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_salmon/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_samap", + "server_name": "biosci_samap", + "tool_name": "samap", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_samap/app/samap_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_samap/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_samap/app/samap_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sambamba", + "server_name": "biosci_sambamba", + "tool_name": "sambamba", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sambamba/app/sambamba_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sambamba/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sambamba/app/sambamba_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_samblaster", + "server_name": "biosci_samblaster", + "tool_name": "samblaster", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_samblaster/app/samblaster_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_samblaster/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_samblaster/app/samblaster_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_samsift", + "server_name": "biosci_samsift", + "tool_name": "samsift", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_samsift/app/samsift_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_samsift/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_samsift/app/samsift_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_samtools", + "server_name": "biosci_samtools", + "tool_name": "samtools", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_samtools/app/samtools_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_samtools/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_samtools/app/samtools_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sc-musketeers", + "server_name": "biosci_sc_musketeers", + "tool_name": "sc-musketeers", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sc-musketeers/app/sc-musketeers_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sc-musketeers/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sc-musketeers/app/sc-musketeers_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scaden", + "server_name": "biosci_scaden", + "tool_name": "scaden", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scaden/app/scaden_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scaden/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scaden/app/scaden_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scanpy-cli", + "server_name": "biosci_scanpy_cli", + "tool_name": "scanpy-cli", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scanpy-cli/app/scanpy-cli_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scanpy-cli/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scanpy-cli/app/scanpy-cli_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scanpy-scripts", + "server_name": "biosci_scanpy_scripts", + "tool_name": "scanpy-scripts", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scanpy-scripts/app/scanpy-scripts_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scanpy-scripts/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scanpy-scripts/app/scanpy-scripts_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sccellfie", + "server_name": "biosci_sccellfie", + "tool_name": "sccellfie", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sccellfie/app/sccellfie_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sccellfie/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sccellfie/app/sccellfie_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scepia", + "server_name": "biosci_scepia", + "tool_name": "scepia", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scepia/app/scepia_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scepia/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scepia/app/scepia_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scglue", + "server_name": "biosci_scglue", + "tool_name": "scglue", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scglue/app/scglue_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scglue/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scglue/app/scglue_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scib", + "server_name": "biosci_scib", + "tool_name": "scib", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scib/app/scib_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scib/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scib/app/scib_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scirpy", + "server_name": "biosci_scirpy", + "tool_name": "scirpy", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scirpy/app/scirpy_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scirpy/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scirpy/app/scirpy_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scmidas", + "server_name": "biosci_scmidas", + "tool_name": "scmidas", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scmidas/app/scmidas_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scmidas/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scmidas/app/scmidas_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scrnasim-toolz", + "server_name": "biosci_scrnasim_toolz", + "tool_name": "scrnasim-toolz", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scrnasim-toolz/app/scrnasim-toolz_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scrnasim-toolz/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scrnasim-toolz/app/scrnasim-toolz_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scspectra", + "server_name": "biosci_scspectra", + "tool_name": "scspectra", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scspectra/app/scspectra_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scspectra/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scspectra/app/scspectra_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scstem", + "server_name": "biosci_scstem", + "tool_name": "scstem", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scstem/app/scstem_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scstem/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scstem/app/scstem_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sctriangulate", + "server_name": "biosci_sctriangulate", + "tool_name": "sctriangulate", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sctriangulate/app/sctriangulate_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sctriangulate/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sctriangulate/app/sctriangulate_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scvi", + "server_name": "biosci_scvi", + "tool_name": "scvi", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scvi/app/scvi_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scvi/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scvi/app/scvi_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scvi-tools", + "server_name": "biosci_scvi_tools", + "tool_name": "scvi-tools", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scvi-tools/app/scvi-tools_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scvi-tools/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scvi-tools/app/scvi-tools_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scvis", + "server_name": "biosci_scvis", + "tool_name": "scvis", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scvis/app/scvis_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scvis/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scvis/app/scvis_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scvis_galaxy", + "server_name": "biosci_scvis_galaxy", + "tool_name": "scvis_galaxy", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scvis_galaxy/app/scvis_galaxy_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scvis_galaxy/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scvis_galaxy/app/scvis_galaxy_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scxmatch", + "server_name": "biosci_scxmatch", + "tool_name": "scxmatch", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scxmatch/app/scxmatch_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scxmatch/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_scxmatch/app/scxmatch_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sdeper", + "server_name": "biosci_sdeper", + "tool_name": "sdeper", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sdeper/app/sdeper_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sdeper/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sdeper/app/sdeper_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_seacells", + "server_name": "biosci_seacells", + "tool_name": "seacells", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_seacells/app/seacells_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_seacells/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_seacells/app/seacells_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_searchgui", + "server_name": "biosci_searchgui", + "tool_name": "searchgui", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_searchgui/app/searchgui_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_searchgui/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_searchgui/app/searchgui_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_segemehl", + "server_name": "biosci_segemehl", + "tool_name": "segemehl", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_segemehl/app/segemehl_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_segemehl/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_segemehl/app/segemehl_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sentieon", + "server_name": "biosci_sentieon", + "tool_name": "sentieon", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sentieon/app/sentieon_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sentieon/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sentieon/app/sentieon_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sepp", + "server_name": "biosci_sepp", + "tool_name": "sepp", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sepp/app/sepp_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sepp/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sepp/app/sepp_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_seq2science", + "server_name": "biosci_seq2science", + "tool_name": "seq2science", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_seq2science/app/seq2science_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_seq2science/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_seq2science/app/seq2science_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_seqcluster", + "server_name": "biosci_seqcluster", + "tool_name": "seqcluster", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_seqcluster/app/seqcluster_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_seqcluster/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_seqcluster/app/seqcluster_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_seqfu", + "server_name": "biosci_seqfu", + "tool_name": "seqfu", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_seqfu/app/seqfu_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_seqfu/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_seqfu/app/seqfu_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_seqkit", + "server_name": "biosci_seqkit", + "tool_name": "seqkit", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_seqkit/app/seqkit_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_seqkit/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_seqkit/app/seqkit_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_seqtk", + "server_name": "biosci_seqtk", + "tool_name": "seqtk", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_seqtk/app/seqtk_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_seqtk/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_seqtk/app/seqtk_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sevenbridges-python", + "server_name": "biosci_sevenbridges_python", + "tool_name": "sevenbridges-python", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sevenbridges-python/app/sevenbridges-python_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sevenbridges-python/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sevenbridges-python/app/sevenbridges-python_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_shiba", + "server_name": "biosci_shiba", + "tool_name": "shiba", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_shiba/app/shiba_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_shiba/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_shiba/app/shiba_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_simo-omics", + "server_name": "biosci_simo_omics", + "tool_name": "simo-omics", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_simo-omics/app/simo-omics_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_simo-omics/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_simo-omics/app/simo-omics_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_simplejson", + "server_name": "biosci_simplejson", + "tool_name": "simplejson", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_simplejson/app/simplejson_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_simplejson/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_simplejson/app/simplejson_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sina", + "server_name": "biosci_sina", + "tool_name": "sina", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sina/app/sina_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sina/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sina/app/sina_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sincei", + "server_name": "biosci_sincei", + "tool_name": "sincei", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sincei/app/sincei_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sincei/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sincei/app/sincei_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_slow5tools", + "server_name": "biosci_slow5tools", + "tool_name": "slow5tools", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_slow5tools/app/slow5tools_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_slow5tools/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_slow5tools/app/slow5tools_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_snakemake", + "server_name": "biosci_snakemake", + "tool_name": "snakemake", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_snakemake/app/snakemake_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_snakemake/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_snakemake/app/snakemake_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_snakemake-interface-common", + "server_name": "biosci_snakemake_interface_common", + "tool_name": "snakemake-interface-common", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_snakemake-interface-common/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_snakemake-interface-executor-plugins", + "server_name": "biosci_snakemake_interface_executor_plugins", + "tool_name": "snakemake-interface-executor-plugins", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_snakemake-interface-executor-plugins/app/snakemake-interface-executor-plugins_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_snakemake-interface-executor-plugins/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_snakemake-interface-executor-plugins/app/snakemake-interface-executor-plugins_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_snakemake-interface-logger-plugins", + "server_name": "biosci_snakemake_interface_logger_plugins", + "tool_name": "snakemake-interface-logger-plugins", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_snakemake-interface-logger-plugins/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_snakemake-interface-report-plugins", + "server_name": "biosci_snakemake_interface_report_plugins", + "tool_name": "snakemake-interface-report-plugins", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_snakemake-interface-report-plugins/app/snakemake-interface-report-plugins_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_snakemake-interface-report-plugins/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_snakemake-interface-report-plugins/app/snakemake-interface-report-plugins_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_snakemake-interface-storage-plugins", + "server_name": "biosci_snakemake_interface_storage_plugins", + "tool_name": "snakemake-interface-storage-plugins", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_snakemake-interface-storage-plugins/app/snakemake-interface-storage-plugins_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_snakemake-interface-storage-plugins/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_snakemake-interface-storage-plugins/app/snakemake-interface-storage-plugins_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_snakemake-minimal", + "server_name": "biosci_snakemake_minimal", + "tool_name": "snakemake-minimal", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_snakemake-minimal/app/snakemake-minimal_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_snakemake-minimal/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_snakemake-minimal/app/snakemake-minimal_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_snakemake-wrapper-utils", + "server_name": "biosci_snakemake_wrapper_utils", + "tool_name": "snakemake-wrapper-utils", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_snakemake-wrapper-utils/app/snakemake-wrapper-utils_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_snakemake-wrapper-utils/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_snakemake-wrapper-utils/app/snakemake-wrapper-utils_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_snakesv", + "server_name": "biosci_snakesv", + "tool_name": "snakesv", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_snakesv/app/snakesv_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_snakesv/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_snakesv/app/snakesv_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_snap-aligner", + "server_name": "biosci_snap_aligner", + "tool_name": "snap-aligner", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_snap-aligner/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_snippy", + "server_name": "biosci_snippy", + "tool_name": "snippy", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_snippy/app/snippy_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_snippy/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_snippy/app/snippy_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_snpeff", + "server_name": "biosci_snpeff", + "tool_name": "snpeff", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_snpeff/app/snpeff_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_snpeff/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_snpeff/app/snpeff_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_snpsift", + "server_name": "biosci_snpsift", + "tool_name": "snpsift", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_snpsift/app/snpsift_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_snpsift/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_snpsift/app/snpsift_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sopa", + "server_name": "biosci_sopa", + "tool_name": "sopa", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sopa/app/sopa_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sopa/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sopa/app/sopa_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sorted_nearest", + "server_name": "biosci_sorted_nearest", + "tool_name": "sorted_nearest", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sorted_nearest/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sortmerna", + "server_name": "biosci_sortmerna", + "tool_name": "sortmerna", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sortmerna/app/sortmerna_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sortmerna/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sortmerna/app/sortmerna_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sourmash", + "server_name": "biosci_sourmash", + "tool_name": "sourmash", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sourmash/app/sourmash_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sourmash/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sourmash/app/sourmash_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_spades", + "server_name": "biosci_spades", + "tool_name": "spades", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_spades/app/spades_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_spades/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_spades/app/spades_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_spagrn", + "server_name": "biosci_spagrn", + "tool_name": "spagrn", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_spagrn/app/spagrn_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_spagrn/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_spagrn/app/spagrn_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_spapros", + "server_name": "biosci_spapros", + "tool_name": "spapros", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_spapros/app/spapros_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_spapros/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_spapros/app/spapros_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_spatialleiden", + "server_name": "biosci_spatialleiden", + "tool_name": "spatialleiden", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_spatialleiden/app/spatialleiden_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_spatialleiden/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_spatialleiden/app/spatialleiden_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sra-tools", + "server_name": "biosci_sra_tools", + "tool_name": "sra-tools", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sra-tools/app/sra-tools_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sra-tools/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_sra-tools/app/sra-tools_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_stacks", + "server_name": "biosci_stacks", + "tool_name": "stacks", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_stacks/app/stacks_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_stacks/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_stacks/app/stacks_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_star", + "server_name": "biosci_star", + "tool_name": "star", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_star/app/star_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_star/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_star/app/star_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_star-fusion", + "server_name": "biosci_star_fusion", + "tool_name": "star-fusion", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_star-fusion/app/star-fusion_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_star-fusion/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_star-fusion/app/star-fusion_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_stream", + "server_name": "biosci_stream", + "tool_name": "stream", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_stream/app/stream_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_stream/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_stream/app/stream_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_stringtie", + "server_name": "biosci_stringtie", + "tool_name": "stringtie", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_stringtie/app/stringtie_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_stringtie/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_stringtie/app/stringtie_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_subread", + "server_name": "biosci_subread", + "tool_name": "subread", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_subread/app/subread_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_subread/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_subread/app/subread_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_switchtfi", + "server_name": "biosci_switchtfi", + "tool_name": "switchtfi", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_switchtfi/app/switchtfi_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_switchtfi/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_switchtfi/app/switchtfi_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_t-coffee", + "server_name": "biosci_t_coffee", + "tool_name": "t-coffee", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_t-coffee/app/t-coffee_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_t-coffee/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_t-coffee/app/t-coffee_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_t_coffee", + "server_name": "biosci_t_coffee", + "tool_name": "t_coffee", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_t_coffee/app/t_coffee_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_t_coffee/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_t_coffee/app/t_coffee_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_tabix", + "server_name": "biosci_tabix", + "tool_name": "tabix", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_tabix/app/tabix_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_tabix/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_tabix/app/tabix_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_tabixpp", + "server_name": "biosci_tabixpp", + "tool_name": "tabixpp", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_tabixpp/app/tabixpp_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_tabixpp/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_tabixpp/app/tabixpp_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_talon", + "server_name": "biosci_talon", + "tool_name": "talon", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_talon/app/talon_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_talon/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_talon/app/talon_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_taxonkit", + "server_name": "biosci_taxonkit", + "tool_name": "taxonkit", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_taxonkit/app/taxonkit_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_taxonkit/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_taxonkit/app/taxonkit_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_tb-profiler", + "server_name": "biosci_tb_profiler", + "tool_name": "tb-profiler", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_tb-profiler/app/tb-profiler_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_tb-profiler/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_tb-profiler/app/tb-profiler_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_thapbi-pict", + "server_name": "biosci_thapbi_pict", + "tool_name": "thapbi-pict", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_thapbi-pict/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_tidyp", + "server_name": "biosci_tidyp", + "tool_name": "tidyp", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_tidyp/app/tidyp_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_tidyp/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_tidyp/app/tidyp_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_tirank", + "server_name": "biosci_tirank", + "tool_name": "tirank", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_tirank/app/tirank_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_tirank/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_tirank/app/tirank_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_tmalign", + "server_name": "biosci_tmalign", + "tool_name": "tmalign", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_tmalign/app/tmalign_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_tmalign/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_tmalign/app/tmalign_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_tobias", + "server_name": "biosci_tobias", + "tool_name": "tobias", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_tobias/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_toil", + "server_name": "biosci_toil", + "tool_name": "toil", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_toil/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_transdecoder", + "server_name": "biosci_transdecoder", + "tool_name": "transdecoder", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_transdecoder/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_treetime", + "server_name": "biosci_treetime", + "tool_name": "treetime", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_treetime/app/treetime_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_treetime/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_treetime/app/treetime_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_trf", + "server_name": "biosci_trf", + "tool_name": "trf", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_trf/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_trim-galore", + "server_name": "biosci_trim_galore", + "tool_name": "trim-galore", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_trim-galore/app/trim-galore_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_trim-galore/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_trim-galore/app/trim-galore_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_trimadap", + "server_name": "biosci_trimadap", + "tool_name": "trimadap", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_trimadap/app/trimadap_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_trimadap/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_trimadap/app/trimadap_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_trimal", + "server_name": "biosci_trimal", + "tool_name": "trimal", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_trimal/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_trimmomatic", + "server_name": "biosci_trimmomatic", + "tool_name": "trimmomatic", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_trimmomatic/app/trimmomatic_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_trimmomatic/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_trimmomatic/app/trimmomatic_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_trinity", + "server_name": "biosci_trinity", + "tool_name": "trinity", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_trinity/app/trinity_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_trinity/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_trinity/app/trinity_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_trnascan-se", + "server_name": "biosci_trnascan_se", + "tool_name": "trnascan-se", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_trnascan-se/app/trnascan-se_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_trnascan-se/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_trnascan-se/app/trnascan-se_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ucsc-bedgraphtobigwig", + "server_name": "biosci_ucsc_bedgraphtobigwig", + "tool_name": "ucsc-bedgraphtobigwig", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ucsc-bedgraphtobigwig/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ucsc-bedtobigbed", + "server_name": "biosci_ucsc_bedtobigbed", + "tool_name": "ucsc-bedtobigbed", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ucsc-bedtobigbed/app/ucsc-bedtobigbed_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ucsc-bedtobigbed/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ucsc-bedtobigbed/app/ucsc-bedtobigbed_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ucsc-cell-browser", + "server_name": "biosci_ucsc_cell_browser", + "tool_name": "ucsc-cell-browser", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ucsc-cell-browser/app/ucsc-cell-browser_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ucsc-cell-browser/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ucsc-cell-browser/app/ucsc-cell-browser_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ucsc-fatotwobit", + "server_name": "biosci_ucsc_fatotwobit", + "tool_name": "ucsc-fatotwobit", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ucsc-fatotwobit/app/ucsc-fatotwobit_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ucsc-fatotwobit/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ucsc-fatotwobit/app/ucsc-fatotwobit_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ucsc-gtftogenepred", + "server_name": "biosci_ucsc_gtftogenepred", + "tool_name": "ucsc-gtftogenepred", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ucsc-gtftogenepred/app/ucsc-gtftogenepred_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ucsc-gtftogenepred/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ucsc-gtftogenepred/app/ucsc-gtftogenepred_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ucsc-liftover", + "server_name": "biosci_ucsc_liftover", + "tool_name": "ucsc-liftover", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ucsc-liftover/app/ucsc-liftover_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ucsc-liftover/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ucsc-liftover/app/ucsc-liftover_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ucsc-nibfrag", + "server_name": "biosci_ucsc_nibfrag", + "tool_name": "ucsc-nibfrag", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ucsc-nibfrag/app/ucsc-nibfrag_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ucsc-nibfrag/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ucsc-nibfrag/app/ucsc-nibfrag_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ucsc-twobitinfo", + "server_name": "biosci_ucsc_twobitinfo", + "tool_name": "ucsc-twobitinfo", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ucsc-twobitinfo/app/ucsc-twobitinfo_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ucsc-twobitinfo/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ucsc-twobitinfo/app/ucsc-twobitinfo_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ucsc-twobittofa", + "server_name": "biosci_ucsc_twobittofa", + "tool_name": "ucsc-twobittofa", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ucsc-twobittofa/app/ucsc-twobittofa_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ucsc-twobittofa/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ucsc-twobittofa/app/ucsc-twobittofa_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ucsc-wigtobigwig", + "server_name": "biosci_ucsc_wigtobigwig", + "tool_name": "ucsc-wigtobigwig", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_ucsc-wigtobigwig/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_umi_tools", + "server_name": "biosci_umi_tools", + "tool_name": "umi_tools", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_umi_tools/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_umis", + "server_name": "biosci_umis", + "tool_name": "umis", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_umis/app/umis_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_umis/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_umis/app/umis_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_unicycler", + "server_name": "biosci_unicycler", + "tool_name": "unicycler", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_unicycler/app/unicycler_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_unicycler/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_unicycler/app/unicycler_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_unifrac", + "server_name": "biosci_unifrac", + "tool_name": "unifrac", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_unifrac/app/unifrac_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_unifrac/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_unifrac/app/unifrac_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_unifrac-binaries", + "server_name": "biosci_unifrac_binaries", + "tool_name": "unifrac-binaries", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_unifrac-binaries/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_upimapi", + "server_name": "biosci_upimapi", + "tool_name": "upimapi", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_upimapi/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_urllib3", + "server_name": "biosci_urllib3", + "tool_name": "urllib3", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_urllib3/app/urllib3_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_urllib3/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_urllib3/app/urllib3_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_usher", + "server_name": "biosci_usher", + "tool_name": "usher", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_usher/app/usher_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_usher/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_usher/app/usher_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_vardict", + "server_name": "biosci_vardict", + "tool_name": "vardict", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_vardict/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_vardict-java", + "server_name": "biosci_vardict_java", + "tool_name": "vardict-java", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_vardict-java/app/vardict-java_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_vardict-java/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_vardict-java/app/vardict-java_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_varlociraptor", + "server_name": "biosci_varlociraptor", + "tool_name": "varlociraptor", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_varlociraptor/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_varscan", + "server_name": "biosci_varscan", + "tool_name": "varscan", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_varscan/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_vcflib", + "server_name": "biosci_vcflib", + "tool_name": "vcflib", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_vcflib/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_vcfpy", + "server_name": "biosci_vcfpy", + "tool_name": "vcfpy", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_vcfpy/app/vcfpy_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_vcfpy/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_vcfpy/app/vcfpy_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_vcftools", + "server_name": "biosci_vcftools", + "tool_name": "vcftools", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_vcftools/app/vcftools_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_vcftools/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_vcftools/app/vcftools_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_vcontact2", + "server_name": "biosci_vcontact2", + "tool_name": "vcontact2", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_vcontact2/app/vcontact2_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_vcontact2/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_vcontact2/app/vcontact2_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_viennarna", + "server_name": "biosci_viennarna", + "tool_name": "viennarna", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_viennarna/app/viennarna_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_viennarna/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_viennarna/app/viennarna_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_vitessce-python", + "server_name": "biosci_vitessce_python", + "tool_name": "vitessce-python", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_vitessce-python/app/vitessce-python_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_vitessce-python/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_vitessce-python/app/vitessce-python_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_vpt", + "server_name": "biosci_vpt", + "tool_name": "vpt", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_vpt/app/vpt_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_vpt/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_vpt/app/vpt_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_vsearch", + "server_name": "biosci_vsearch", + "tool_name": "vsearch", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_vsearch/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_vt", + "server_name": "biosci_vt", + "tool_name": "vt", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_vt/app/vt_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_vt/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_vt/app/vt_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_wasp2", + "server_name": "biosci_wasp2", + "tool_name": "wasp2", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_wasp2/app/wasp2_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_wasp2/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_wasp2/app/wasp2_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_whatshap", + "server_name": "biosci_whatshap", + "tool_name": "whatshap", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_whatshap/app/whatshap_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_whatshap/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_whatshap/app/whatshap_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_womtool", + "server_name": "biosci_womtool", + "tool_name": "womtool", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_womtool/app/womtool_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_womtool/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_womtool/app/womtool_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_xclone", + "server_name": "biosci_xclone", + "tool_name": "xclone", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_xclone/app/xclone_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_xclone/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_xclone/app/xclone_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_xopen", + "server_name": "biosci_xopen", + "tool_name": "xopen", + "app_dir_exists": true, + "server_file": "", + "server_file_exists": false, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_xopen/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": false, + "shim_file": "", + "status": "skipped_no_server_file", + "notes": [ + "no *_server.py found in app/" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_yacrd", + "server_name": "biosci_yacrd", + "tool_name": "yacrd", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_yacrd/app/yacrd_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_yacrd/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_yacrd/app/yacrd_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_zdb", + "server_name": "biosci_zdb", + "tool_name": "zdb", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_zdb/app/zdb_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_zdb/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_zdb/app/zdb_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + }, + { + "source_root": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", + "server_dir": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_zol", + "server_name": "biosci_zol", + "tool_name": "zol", + "app_dir_exists": true, + "server_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_zol/app/zol_server.py", + "server_file_exists": true, + "has_fastmcp_bootstrap": false, + "has_main_run": false, + "requirements_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_zol/requirements.txt", + "requirements_created_or_updated": false, + "using_shim": true, + "shim_file": "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_zol/app/zol_shim_server.py", + "status": "registered", + "notes": [ + "generated shim server for MCP stdio compatibility" + ] + } + ] +} \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/merge_help_and_manual_docs.py b/BioScientist/agent_system/toolbase/merge_help_and_manual_docs.py new file mode 100644 index 0000000000000000000000000000000000000000..2ba49f9f585ca27448ee232c42c044f4d179b6cc --- /dev/null +++ b/BioScientist/agent_system/toolbase/merge_help_and_manual_docs.py @@ -0,0 +1,115 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import argparse +import json +import shutil +from pathlib import Path + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser( + description="Merge help_txt and manual_bundle_txt into one folder, preferring help_txt." + ) + parser.add_argument( + "--help-dir", + default="/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/help_txt", + help="Directory with *.help.txt files.", + ) + parser.add_argument( + "--manual-dir", + default="/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/manual_bundle_txt", + help="Directory with *.manual_bundle.txt files.", + ) + parser.add_argument( + "--output-dir", + default="/225040511/project/BioScientist/agent_system/toolbase/output/help_docs/merged_prefer_help_txt", + help="Merged output directory.", + ) + parser.add_argument( + "--clean", + action="store_true", + help="If set, remove old *.txt files in output-dir before writing.", + ) + return parser.parse_args() + + +def collect_help_map(help_dir: Path) -> dict[str, Path]: + result: dict[str, Path] = {} + for p in sorted(help_dir.glob("*.help.txt")): + tool = p.name[: -len(".help.txt")] + result[tool] = p + return result + + +def collect_manual_map(manual_dir: Path) -> dict[str, Path]: + result: dict[str, Path] = {} + for p in sorted(manual_dir.glob("*.manual_bundle.txt")): + tool = p.name[: -len(".manual_bundle.txt")] + result[tool] = p + return result + + +def main() -> int: + args = parse_args() + help_dir = Path(args.help_dir).resolve() + manual_dir = Path(args.manual_dir).resolve() + output_dir = Path(args.output_dir).resolve() + + if not help_dir.exists(): + raise FileNotFoundError(f"help-dir not found: {help_dir}") + if not manual_dir.exists(): + raise FileNotFoundError(f"manual-dir not found: {manual_dir}") + + output_dir.mkdir(parents=True, exist_ok=True) + if args.clean: + for p in output_dir.glob("*.txt"): + p.unlink() + + help_map = collect_help_map(help_dir) + manual_map = collect_manual_map(manual_dir) + all_tools = sorted(set(help_map) | set(manual_map)) + + records: list[dict] = [] + summary = { + "help_preferred": 0, + "manual_fallback": 0, + "total": 0, + } + + for tool in all_tools: + if tool in help_map: + src = help_map[tool] + source = "help_txt" + summary["help_preferred"] += 1 + else: + src = manual_map[tool] + source = "manual_bundle_txt" + summary["manual_fallback"] += 1 + + dst = output_dir / f"{tool}.txt" + shutil.copyfile(src, dst) + records.append( + { + "tool": tool, + "source": source, + "source_file": str(src), + "merged_file": str(dst), + } + ) + + summary["total"] = len(all_tools) + manifest_path = output_dir / "merge_manifest.json" + manifest_path.write_text( + json.dumps({"summary": summary, "items": records}, ensure_ascii=False, indent=2), + encoding="utf-8", + ) + + print(json.dumps(summary, ensure_ascii=False, indent=2)) + print(f"Merged output: {output_dir}") + print(f"Manifest: {manifest_path}") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/BioScientist/agent_system/toolbase/organize_help_docs.py b/BioScientist/agent_system/toolbase/organize_help_docs.py new file mode 100644 index 0000000000000000000000000000000000000000..347c04135dc929fc5c7605aa44379ec6abb49ff8 --- /dev/null +++ b/BioScientist/agent_system/toolbase/organize_help_docs.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import argparse +import shutil +from pathlib import Path + + +def move_group(src_dir: Path, pattern: str, dst_dir: Path) -> int: + dst_dir.mkdir(parents=True, exist_ok=True) + moved = 0 + for p in src_dir.glob(pattern): + if not p.is_file(): + continue + target = dst_dir / p.name + shutil.move(str(p), str(target)) + moved += 1 + return moved + + +def main() -> None: + parser = argparse.ArgumentParser( + description="Organize help_docs by moving *.help.txt and *.manual_bundle.txt into separate folders." + ) + parser.add_argument( + "--help-docs-dir", + type=str, + default="/225040511/project/BioScientist/agent_system/toolbase/output/help_docs", + help="Directory containing help_docs artifacts.", + ) + parser.add_argument( + "--help-subdir", + type=str, + default="help_txt", + help="Subdirectory name for *.help.txt files.", + ) + parser.add_argument( + "--manual-subdir", + type=str, + default="manual_bundle_txt", + help="Subdirectory name for *.manual_bundle.txt files.", + ) + args = parser.parse_args() + + base = Path(args.help_docs_dir) + if not base.exists(): + raise FileNotFoundError(f"help_docs directory not found: {base}") + + moved_help = move_group(base, "*.help.txt", base / args.help_subdir) + moved_manual = move_group(base, "*.manual_bundle.txt", base / args.manual_subdir) + + print(f"moved_help_txt={moved_help}") + print(f"moved_manual_bundle_txt={moved_manual}") + print(f"help_txt_dir={base / args.help_subdir}") + print(f"manual_bundle_txt_dir={base / args.manual_subdir}") + + +if __name__ == "__main__": + main() + diff --git a/BioScientist/agent_system/toolbase/prepare_converter_inputs.py b/BioScientist/agent_system/toolbase/prepare_converter_inputs.py new file mode 100644 index 0000000000000000000000000000000000000000..5113dbc0b15408e974c15692f8949d27c0af2787 --- /dev/null +++ b/BioScientist/agent_system/toolbase/prepare_converter_inputs.py @@ -0,0 +1,1258 @@ +#!/usr/bin/env python3 +""" +Prepare crawler JSON outputs for BioinfoMCP converter and optionally collect help docs. + +Input JSON files: +- bioconda_t0_core_tools.json +- bioconda_t1_domain_tools.json +- bioconda_t2_on_demand_tools.json + +Output files: +- converter_input_t0.json +- converter_input_t1.json +- converter_input_t2.json +- converter_input_all.json +- converter_jobs.json +- help_index.json +""" + +from __future__ import annotations + +import argparse +import json +import re +import subprocess +import shutil +import time +from dataclasses import dataclass +from pathlib import Path +from typing import Dict, List, Tuple +import requests +import time +from pathlib import Path +from typing import Dict, List, Tuple +from datetime import datetime + + +@dataclass +class ToolRow: + source_file: str + tier: str + domain: str + software_name: str + package_name: str + summary: str + description: str + dependencies: List[str] + downloads: int + home_url: str + doc_url: str + dev_url: str + execution_environment: str + execution_environment_reason: str + + +def read_rows(file_path: Path) -> List[dict]: + if not file_path.exists(): + return [] + with file_path.open("r", encoding="utf-8") as f: + data = json.load(f) + if not isinstance(data, list): + raise ValueError(f"JSON root must be list: {file_path}") + return [x for x in data if isinstance(x, dict)] + + +def normalize_rows(file_path: Path, rows: List[dict]) -> List[ToolRow]: + out: List[ToolRow] = [] + for row in rows: + package_name = str(row.get("package_name", "")).strip() + software_name = str(row.get("software_name", "")).strip() or package_name + if not package_name and not software_name: + continue + deps = list(row.get("dependencies", []) or []) + env = str(row.get("execution_environment", "")).strip() + env_reason = str(row.get("execution_environment_reason", "")).strip() + if not env: + env, env_reason = infer_runtime_from_fields(package_name=package_name or software_name, dependencies=deps) + out.append( + ToolRow( + source_file=file_path.name, + tier=str(row.get("tier", "")).strip() or infer_tier(file_path.name), + domain=str(row.get("domain", "")).strip(), + software_name=software_name, + package_name=package_name or software_name, + summary=str(row.get("summary", "")).strip(), + description=str(row.get("description", "")).strip(), + dependencies=deps, + downloads=safe_int(row.get("downloads", -1)), + home_url=str(row.get("home_url", "")).strip(), + doc_url=str(row.get("doc_url", "")).strip(), + dev_url=str(row.get("dev_url", "")).strip(), + execution_environment=env, + execution_environment_reason=env_reason, + ) + ) + return out + + +def infer_tier(filename: str) -> str: + low = filename.lower() + if "t0" in low: + return "T0" + if "t1" in low: + return "T1" + if "t2" in low: + return "T2" + return "" + + +def safe_int(v, default: int = -1) -> int: + try: + return int(v) + except Exception: + return default + + +def parse_bool(v, default: bool = False) -> bool: + if isinstance(v, bool): + return v + if v is None: + return default + return str(v).strip().lower() in ("1", "true", "yes", "y", "on") + + +def infer_runtime_from_fields(package_name: str, dependencies: List[str]) -> Tuple[str, str]: + pkg = package_name.lower() + deps = [str(d).lower() for d in dependencies] + + if pkg.startswith("bioconductor-") or pkg.startswith("r-") or any("r-base" in d or d.startswith("r-") for d in deps): + return "R", "inferred from package/dependencies (R ecosystem)" + if pkg.startswith("perl-") or any(d == "perl" or d.startswith("perl-") for d in deps): + return "Perl", "inferred from package/dependencies (Perl ecosystem)" + if any("openjdk" in d or "default-jre" in d or d == "java" for d in deps): + return "Java", "inferred from Java runtime dependencies" + if any("python" in d for d in deps): + return "Python", "inferred from python dependency" + if any(k in " ".join(deps) for k in ("libgcc", "libstdcxx", "htslib")): + return "Compiled", "inferred from native/compiled dependencies" + return "Other", "fallback runtime classification" + + +def normalize_env_name(name: str) -> str: + x = re.sub(r"[^A-Za-z0-9._-]+", "-", name.strip()) + x = re.sub(r"-{2,}", "-", x).strip("-") + return x[:64] if len(x) > 64 else x + + +def route_env_name(base_env: str, row: ToolRow) -> str: + pkg = row.package_name.lower() + runtime = row.execution_environment.lower() + dep_text = " ".join(str(d).lower() for d in row.dependencies) + domain = (row.domain or "").lower() + + if pkg.startswith("bioconductor-") or pkg.startswith("r-") or runtime == "r": + suffix = "r_bioc" + elif any(k in dep_text for k in ("pytorch", "torch", "jax", "cuda", "scvi")): + suffix = "py_torch" + elif runtime == "python" and any( + k in dep_text or k in pkg + for k in ("scanpy", "anndata", "scvelo", "scarches", "squidpy", "scikit-learn") + ): + suffix = "py_sc" + elif runtime == "perl": + suffix = "perl" + elif runtime == "java": + suffix = "java" + elif "single" in domain and runtime == "python": + suffix = "py_sc" + elif "spatial" in domain and runtime == "python": + suffix = "py_spatial" + else: + suffix = "cli" + return normalize_env_name(f"{base_env}_{suffix}") + + +def dedup_keep_best(rows: List[ToolRow]) -> List[ToolRow]: + best: Dict[str, ToolRow] = {} + for row in rows: + key = row.package_name.lower() + if key not in best: + best[key] = row + continue + old = best[key] + # Prefer higher download count. + if row.downloads > old.downloads: + best[key] = row + return list(best.values()) + + +def to_converter_row(row: ToolRow) -> dict: + # This format is directly consumable by tool2mcp --tools_json, + # because it keeps package_name/software_name/domain. + return { + "package_name": row.package_name, + "software_name": row.software_name, + "domain": row.domain, + "tier": row.tier, + "summary": row.summary, + "description": row.description, + "downloads": row.downloads, + "dependencies": row.dependencies, + "home_url": row.home_url, + "doc_url": row.doc_url, + "dev_url": row.dev_url, + "execution_environment": row.execution_environment, + "execution_environment_reason": row.execution_environment_reason, + "source_file": row.source_file, + } + + +def write_json(path: Path, data) -> None: + path.parent.mkdir(parents=True, exist_ok=True) + with path.open("w", encoding="utf-8") as f: + json.dump(data, f, ensure_ascii=False, indent=2) + + +def read_json_if_exists(path: Path, default): + if not path.exists(): + return default + try: + with path.open("r", encoding="utf-8") as f: + return json.load(f) + except Exception: + return default + + +def _first_nonempty(paths: List[Path]) -> str: + for p in paths: + if p.exists() and p.stat().st_size > 0: + return str(p) + return "" + + +def existing_help_outputs(help_dir: Path, package_name: str) -> Dict[str, str]: + """ + Check whether the tool already has generated help artifacts in output/help_docs. + A tool is considered already processed if manual_bundle/help file exists and is non-empty. + """ + manual_bundle = help_dir / f"{package_name}.manual_bundle.txt" + manual_bundle_sub = help_dir / "manual_bundle_txt" / f"{package_name}.manual_bundle.txt" + help_txt = help_dir / f"{package_name}.help.txt" + help_txt_sub = help_dir / "help_txt" / f"{package_name}.help.txt" + help_log = help_dir / f"{package_name}.help.log" + install_log = help_dir / f"{package_name}.install.log" + + result = { + "manual_bundle_file": _first_nonempty([manual_bundle_sub, manual_bundle]), + "help_file": _first_nonempty([help_txt_sub, help_txt]), + "help_log_file": str(help_log) if help_log.exists() and help_log.stat().st_size > 0 else "", + "install_log_file": str(install_log) if install_log.exists() and install_log.stat().st_size > 0 else "", + } + return result + + +def executable_candidates(row: ToolRow) -> List[str]: + pkg = row.package_name.strip() + sw = row.software_name.strip() + cands = [sw, pkg] + # common name normalizations + cands.append(pkg.replace("bioconductor-", "")) + cands.append(sw.replace("_", "-")) + cands.append(sw.replace("-", "_")) + cands.append(pkg.replace("_", "-")) + cands.append(pkg.replace("-", "_")) + + cleaned = [] + seen = set() + for c in cands: + c = c.strip() + if not c: + continue + if not re.match(r"^[A-Za-z0-9._+-]+$", c): + continue + if c not in seen: + seen.add(c) + cleaned.append(c) + return cleaned + + +def module_candidates(row: ToolRow) -> List[str]: + pkg = row.package_name.strip().replace("-", "_") + sw = row.software_name.strip().replace("-", "_") + cands = [sw, pkg] + cleaned = [] + seen = set() + for c in cands: + c = c.strip().strip(".") + if not c: + continue + if not re.match(r"^[A-Za-z_][A-Za-z0-9_]*$", c): + continue + if c not in seen: + seen.add(c) + cleaned.append(c) + return cleaned + + +def r_package_candidates(row: ToolRow) -> List[str]: + pkg = row.package_name.strip() + sw = row.software_name.strip() + candidates = [] + for raw in [pkg, sw]: + if not raw: + continue + x = raw + if x.startswith("bioconductor-"): + x = x[len("bioconductor-") :] + if x.startswith("r-"): + x = x[len("r-") :] + # R package names often use dot notation + candidates.append(x.replace("-", ".")) + candidates.append(x.replace("-", "")) + # keep order and unique + seen = set() + out = [] + for c in candidates: + if c and c not in seen: + seen.add(c) + out.append(c) + return out + + +def perl_module_candidates(row: ToolRow) -> List[str]: + pkg = row.package_name.strip() + sw = row.software_name.strip() + candidates = [] + for raw in [pkg, sw]: + x = raw + if x.startswith("perl-"): + x = x[len("perl-") :] + x = x.replace("-", "::") + candidates.append(x) + seen = set() + out = [] + for c in candidates: + if c and c not in seen: + seen.add(c) + out.append(c) + return out + + +def run_command(cmd: List[str], timeout: int = 1800) -> Tuple[int, str, str]: + try: + proc = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout) + return proc.returncode, proc.stdout, proc.stderr + except subprocess.TimeoutExpired as exc: + stdout = exc.stdout if isinstance(exc.stdout, str) else (exc.stdout.decode("utf-8", errors="ignore") if exc.stdout else "") + stderr = exc.stderr if isinstance(exc.stderr, str) else (exc.stderr.decode("utf-8", errors="ignore") if exc.stderr else "") + stderr = (stderr or "") + f"\n[TimeoutExpired] command exceeded {timeout}s" + return 124, stdout or "", stderr + + +def resolve_solver(solver: str) -> str: + if shutil.which(solver): + return solver + return "conda" + + +def conda_env_exists(conda_env: str) -> bool: + rc, out, _err = run_command(["conda", "env", "list", "--json"], timeout=120) + if rc != 0: + return False + try: + payload = json.loads(out) + except Exception: + return False + envs = payload.get("envs", []) or [] + marker = f"/envs/{conda_env}" + return any(str(p).endswith(marker) or str(p).endswith(f"\\envs\\{conda_env}") for p in envs) + + +def ensure_conda_env(conda_env: str, python_version: str = "3.10") -> Tuple[bool, str]: + if conda_env_exists(conda_env): + return True, f"Conda env '{conda_env}' already exists." + cmd = ["conda", "create", "-y", "-n", conda_env, f"python={python_version}"] + rc, out, err = run_command(cmd, timeout=1800) + ok = rc == 0 + msg = f"$ {' '.join(cmd)}\n[rc={rc}]\n{(out or '')[:6000]}\n{(err or '')[:6000]}" + return ok, msg + + +def build_install_cmd( + solver: str, + conda_env: str, + package_name: str, + dry_run: bool = False, + strict_channel_priority: bool = False, +) -> List[str]: + cmd = [ + solver, + "install", + "-y", + "-n", + conda_env, + "-c", + "bioconda", + "-c", + "conda-forge", + package_name, + ] + if dry_run: + cmd.append("--dry-run") + if strict_channel_priority: + cmd.append("--strict-channel-priority") + return cmd + + +def install_tool( + conda_env: str, + package_name: str, + timeout: int = 1800, + solver: str = "conda", + strict_channel_priority: bool = False, +) -> Tuple[bool, str]: + cmd = build_install_cmd( + solver=solver, + conda_env=conda_env, + package_name=package_name, + dry_run=False, + strict_channel_priority=strict_channel_priority, + ) + rc, out, err = run_command(cmd, timeout=timeout) + ok = rc == 0 + msg = f"$ {' '.join(cmd)}\n[rc={rc}]\n{(out or '')[:4000]}\n{(err or '')[:4000]}" + return ok, msg + + +def dry_run_install_tool( + conda_env: str, + package_name: str, + timeout: int = 600, + solver: str = "conda", + strict_channel_priority: bool = False, +) -> Tuple[bool, str]: + cmd = build_install_cmd( + solver=solver, + conda_env=conda_env, + package_name=package_name, + dry_run=True, + strict_channel_priority=strict_channel_priority, + ) + rc, out, err = run_command(cmd, timeout=timeout) + ok = rc == 0 + msg = f"$ {' '.join(cmd)}\n[rc={rc}]\n{(out or '')[:5000]}\n{(err or '')[:5000]}" + return ok, msg + + +def try_capture_help(conda_env: str, executable: str, timeout: int = 120) -> Tuple[bool, str]: + cmd = ["conda", "run", "-n", conda_env, executable, "--help"] + rc, out, err = run_command(cmd, timeout=timeout) + text = (out or "") + ("\n" + err if err else "") + lower = text.lower() + # Help sometimes exits non-zero, but still provides usage. + success = ("usage" in lower or "help" in lower) and ("not found" not in lower) + success = success or rc == 0 + log = f"$ {' '.join(cmd)}\n[rc={rc}]\n{text[:12000]}" + return success, log + + +def try_capture_help_module(conda_env: str, module_name: str, timeout: int = 120) -> Tuple[bool, str]: + cmd = ["conda", "run", "-n", conda_env, "python", "-m", module_name, "--help"] + rc, out, err = run_command(cmd, timeout=timeout) + text = (out or "") + ("\n" + err if err else "") + lower = text.lower() + success = ("usage" in lower or "help" in lower) and ("no module named" not in lower) + success = success or rc == 0 + log = f"$ {' '.join(cmd)}\n[rc={rc}]\n{text[:12000]}" + return success, log + + +def try_capture_help_rscript(conda_env: str, timeout: int = 120) -> Tuple[bool, str]: + cmd = ["conda", "run", "-n", conda_env, "Rscript", "--help"] + rc, out, err = run_command(cmd, timeout=timeout) + text = (out or "") + ("\n" + err if err else "") + lower = text.lower() + ok = ("usage" in lower or "help" in lower) and ("not found" not in lower) + ok = ok or rc == 0 + return ok, f"$ {' '.join(cmd)}\n[rc={rc}]\n{text[:12000]}" + + +def try_capture_help_r_package(conda_env: str, pkg_name: str, timeout: int = 180) -> Tuple[bool, str]: + expr = ( + f"if (requireNamespace('{pkg_name}', quietly=TRUE)) " + f"{{library('{pkg_name}', character.only=TRUE); help(package='{pkg_name}')}} " + f"else {{stop('package not installed: {pkg_name}')}}" + ) + cmd = ["conda", "run", "-n", conda_env, "R", "-q", "-e", expr] + rc, out, err = run_command(cmd, timeout=timeout) + text = (out or "") + ("\n" + err if err else "") + lower = text.lower() + ok = ("package:" in lower or "help pages" in lower or "index" in lower) and ("not installed" not in lower) + ok = ok or rc == 0 + return ok, f"$ {' '.join(cmd)}\n[rc={rc}]\n{text[:12000]}" + + +def try_capture_help_perl(conda_env: str, timeout: int = 120) -> Tuple[bool, str]: + cmd = ["conda", "run", "-n", conda_env, "perl", "-h"] + rc, out, err = run_command(cmd, timeout=timeout) + text = (out or "") + ("\n" + err if err else "") + lower = text.lower() + ok = ("usage" in lower or "perl" in lower) and ("not found" not in lower) + ok = ok or rc == 0 + return ok, f"$ {' '.join(cmd)}\n[rc={rc}]\n{text[:12000]}" + + +def try_capture_help_perldoc_module(conda_env: str, module_name: str, timeout: int = 120) -> Tuple[bool, str]: + cmd = ["conda", "run", "-n", conda_env, "perldoc", module_name] + rc, out, err = run_command(cmd, timeout=timeout) + text = (out or "") + ("\n" + err if err else "") + lower = text.lower() + ok = ("name" in lower or "description" in lower or "synopsis" in lower) and ("no documentation found" not in lower) + ok = ok or rc == 0 + return ok, f"$ {' '.join(cmd)}\n[rc={rc}]\n{text[:12000]}" + + +def try_capture_help_java(conda_env: str, timeout: int = 120) -> Tuple[bool, str]: + cmd = ["conda", "run", "-n", conda_env, "java", "-help"] + rc, out, err = run_command(cmd, timeout=timeout) + text = (out or "") + ("\n" + err if err else "") + lower = text.lower() + ok = ("usage" in lower or "java" in lower) and ("not found" not in lower) + ok = ok or rc == 0 + return ok, f"$ {' '.join(cmd)}\n[rc={rc}]\n{text[:12000]}" + + +def capture_help_by_runtime(conda_env: str, row: ToolRow, help_timeout: int = 120) -> Tuple[bool, str, str, List[str]]: + runtime = row.execution_environment.lower() + logs: List[str] = [] + + # Python: CLI -> python -m + if runtime == "python": + for cand in executable_candidates(row): + ok, log = try_capture_help(conda_env=conda_env, executable=cand, timeout=help_timeout) + logs.append(log) + if ok: + return True, f"cli:{cand}", log, logs + for mod in module_candidates(row): + ok, log = try_capture_help_module(conda_env=conda_env, module_name=mod, timeout=help_timeout) + logs.append(log) + if ok: + return True, f"module:{mod}", log, logs + return False, "", "", logs + + # R: Rscript --help -> R package help -> generic CLI + if runtime == "r": + ok, log = try_capture_help_rscript(conda_env=conda_env, timeout=help_timeout) + logs.append(log) + if ok: + return True, "rscript:--help", log, logs + for rpkg in r_package_candidates(row): + ok, log = try_capture_help_r_package(conda_env=conda_env, pkg_name=rpkg, timeout=max(help_timeout, 180)) + logs.append(log) + if ok: + return True, f"r_package:{rpkg}", log, logs + for cand in executable_candidates(row): + ok, log = try_capture_help(conda_env=conda_env, executable=cand, timeout=help_timeout) + logs.append(log) + if ok: + return True, f"cli:{cand}", log, logs + return False, "", "", logs + + # Perl: perldoc module -> perl -h -> generic CLI + if runtime == "perl": + for mod in perl_module_candidates(row): + ok, log = try_capture_help_perldoc_module(conda_env=conda_env, module_name=mod, timeout=help_timeout) + logs.append(log) + if ok: + return True, f"perldoc:{mod}", log, logs + ok, log = try_capture_help_perl(conda_env=conda_env, timeout=help_timeout) + logs.append(log) + if ok: + return True, "perl:-h", log, logs + for cand in executable_candidates(row): + ok, log = try_capture_help(conda_env=conda_env, executable=cand, timeout=help_timeout) + logs.append(log) + if ok: + return True, f"cli:{cand}", log, logs + return False, "", "", logs + + # Java: java -help -> generic CLI + if runtime == "java": + ok, log = try_capture_help_java(conda_env=conda_env, timeout=help_timeout) + logs.append(log) + if ok: + return True, "java:-help", log, logs + for cand in executable_candidates(row): + ok, log = try_capture_help(conda_env=conda_env, executable=cand, timeout=help_timeout) + logs.append(log) + if ok: + return True, f"cli:{cand}", log, logs + return False, "", "", logs + + # Compiled/Other: generic CLI first, then python -m as last fallback. + for cand in executable_candidates(row): + ok, log = try_capture_help(conda_env=conda_env, executable=cand, timeout=help_timeout) + logs.append(log) + if ok: + return True, f"cli:{cand}", log, logs + for mod in module_candidates(row): + ok, log = try_capture_help_module(conda_env=conda_env, module_name=mod, timeout=help_timeout) + logs.append(log) + if ok: + return True, f"module:{mod}", log, logs + return False, "", "", logs + + +def fetch_url_text(url: str, timeout: int = 20) -> Tuple[bool, str]: + if not url: + return False, "" + try: + resp = requests.get(url, timeout=timeout) + if resp.status_code >= 400: + return False, f"[HTTP {resp.status_code}] {url}" + text = resp.text or "" + text = re.sub(r"", " ", text, flags=re.IGNORECASE) + text = re.sub(r"", " ", text, flags=re.IGNORECASE) + text = re.sub(r"<[^>]+>", " ", text) + text = re.sub(r"\s+", " ", text).strip() + return True, text[:20000] + except Exception as exc: + return False, f"[ERROR] {url} -> {exc}" + + +def conda_search_info(package_name: str, timeout: int = 120) -> Tuple[bool, str]: + cmd = ["conda", "search", "-c", "bioconda", "-c", "conda-forge", package_name, "--info"] + rc, out, err = run_command(cmd, timeout=timeout) + text = (out or "") + ("\n" + err if err else "") + ok = rc == 0 and bool(text.strip()) + log = f"$ {' '.join(cmd)}\n[rc={rc}]\n{text[:12000]}" + return ok, log + + +def build_manual_bundle( + row: ToolRow, + cli_help: str, + cli_source: str, + url_docs: List[Tuple[str, str]], + conda_info: str, +) -> str: + parts = [ + f"# Tool: {row.package_name}", + f"software_name: {row.software_name}", + f"tier: {row.tier}", + f"domain: {row.domain}", + f"downloads: {row.downloads}", + f"summary: {row.summary}", + f"description: {row.description}", + f"dependencies: {', '.join(row.dependencies)}", + f"execution_environment: {row.execution_environment}", + f"execution_environment_reason: {row.execution_environment_reason}", + "", + "## URLs", + f"home_url: {row.home_url}", + f"doc_url: {row.doc_url}", + f"dev_url: {row.dev_url}", + "", + ] + if cli_help: + parts += ["## CLI Help Source", cli_source or "unknown", "## CLI Help Content", cli_help, ""] + if url_docs: + parts += ["## URL Docs Extract"] + for url, text in url_docs: + parts += [f"### {url}", text, ""] + if conda_info: + parts += ["## Conda Search Info", conda_info, ""] + return "\n".join(parts).strip() + "\n" + + +def collect_help_for_rows( + rows: List[ToolRow], + output_dir: Path, + conda_env: str, + do_install: bool, + python_version: str = "3.10", + install_timeout: int = 1800, + dry_run_timeout: int = 600, + help_timeout: int = 120, + conda_info_timeout: int = 120, + skip_processed: bool = True, + use_env_routing: bool = True, + enable_dry_run: bool = True, + solver: str = "conda", + strict_channel_priority: bool = False, +) -> Dict[str, dict]: + """ + 为一批工具收集帮助文档,生成 manual bundle。 + + 增强日志功能: + - 分阶段进度输出 + - 每个工具的详细处理日志 + - 成功/失败统计 + - 耗时统计 + """ + start_time = time.time() + help_dir = output_dir / "help_docs" + help_dir.mkdir(parents=True, exist_ok=True) + help_txt_dir = help_dir / "help_txt" + manual_bundle_dir = help_dir / "manual_bundle_txt" + help_txt_dir.mkdir(parents=True, exist_ok=True) + manual_bundle_dir.mkdir(parents=True, exist_ok=True) + + # 日志文件:记录整个批处理的汇总信息 + batch_log_file = help_dir / f"batch_collect_{datetime.now().strftime('%Y%m%d_%H%M%S')}.log" + batch_log_lines = [] + + def log_batch(message: str, also_print: bool = True): + """记录批处理日志""" + timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + log_line = f"[{timestamp}] {message}" + batch_log_lines.append(log_line) + if also_print: + print(log_line) + + def log_to_file(file_path: Path, content: str): + """写入文件并同时记录到批处理日志""" + file_path.write_text(content, encoding="utf-8") + log_batch(f" -> 写入文件: {file_path.name} ({len(content)} bytes)", also_print=False) + + log_batch("=" * 80) + log_batch(f"开始批量收集工具帮助文档") + log_batch(f" - 工具总数: {len(rows)}") + log_batch(f" - Conda 环境: {conda_env}") + log_batch(f" - 是否安装工具: {do_install}") + log_batch(f" - 输出目录: {output_dir}") + log_batch(f" - install_timeout: {install_timeout}s") + log_batch(f" - dry_run_timeout: {dry_run_timeout}s") + log_batch(f" - help_timeout: {help_timeout}s") + log_batch(f" - conda_info_timeout: {conda_info_timeout}s") + log_batch(f" - use_env_routing: {use_env_routing}") + log_batch(f" - enable_dry_run: {enable_dry_run}") + log_batch(f" - solver: {solver}") + log_batch(f" - strict_channel_priority: {strict_channel_priority}") + log_batch("=" * 80) + + index_path = output_dir / "help_index.json" + existing_index = read_json_if_exists(index_path, {}) + if not isinstance(existing_index, dict): + existing_index = {} + index: Dict[str, dict] = dict(existing_index) + stats = { + "total": len(rows), + "installed": 0, + "install_failed": 0, + "help_success": 0, + "help_failed": 0, + "manual_bundle_generated": 0, + "skipped_by_no_install": 0, + "skipped_processed": 0, + "dry_run_failed": 0, + "docs_only_fallback": 0, + } + ensured_envs: Dict[str, bool] = {} + + for idx, row in enumerate(rows, 1): + tool_start_time = time.time() + log_batch(f"\n[{idx}/{len(rows)}] 处理工具: {row.package_name}") + log_batch(f" - Tier: {row.tier}, Domain: {row.domain}") + + key = row.package_name + item = { + "tool": key, + "tier": row.tier, + "domain": row.domain, + "installed": False, + "install_log_file": "", + "help_ok": False, + "help_file": "", + "help_log_file": "", + "executable_used": "", + "manual_bundle_file": "", + "manual_source": "", + "reason": "", + "processing_time_seconds": 0, + } + + if skip_processed: + existing = existing_index.get(key, {}) + existing_fs = existing_help_outputs(help_dir=help_dir, package_name=key) + existing_bundle = existing_fs.get("manual_bundle_file", "") + existing_help = existing_fs.get("help_file", "") + bundle_ok = bool(existing_bundle) + help_ok = bool(existing_help) + if bundle_ok or help_ok: + stats["skipped_processed"] += 1 + reason = "already processed (existing manual/help file found)" + log_batch(f" ⏭️ 跳过: {reason}") + existing["manual_bundle_file"] = existing_bundle or existing.get("manual_bundle_file", "") + existing["help_file"] = existing_help or existing.get("help_file", "") + existing["help_log_file"] = existing_fs.get("help_log_file", "") or existing.get("help_log_file", "") + existing["install_log_file"] = existing_fs.get("install_log_file", "") or existing.get("install_log_file", "") + existing["help_ok"] = True if (existing_bundle or existing_help) else bool(existing.get("help_ok", False)) + existing["reason"] = existing.get("reason") or reason + existing["processing_time_seconds"] = existing.get("processing_time_seconds", 0) + index[key] = existing + continue + + target_env = route_env_name(conda_env, row) if use_env_routing else conda_env + item["target_env"] = target_env + logs: List[str] = [] + success = False + chosen = "" + chosen_source = "" + chosen_help_text = "" + capture_time = 0.0 + docs_only = False + + # ========== 阶段1: 安装工具(带可解性预检) ========== + if do_install: + if target_env not in ensured_envs: + env_ok, env_msg = ensure_conda_env(target_env, python_version=python_version) + ensured_envs[target_env] = env_ok + pre_file = help_dir / f"{target_env}.env_preflight.log" + log_to_file(pre_file, env_msg) + if not ensured_envs.get(target_env, False): + stats["install_failed"] += 1 + item["reason"] = f"conda env preflight failed: {target_env}" + log_batch(f" ❌ 环境不可用: {target_env}") + docs_only = True + stats["docs_only_fallback"] += 1 + else: + if enable_dry_run: + log_batch(f" [阶段1A] dry-run 预检到环境 '{target_env}' ...") + dry_ok, dry_log = dry_run_install_tool( + conda_env=target_env, + package_name=row.package_name, + timeout=dry_run_timeout, + solver=solver, + strict_channel_priority=strict_channel_priority, + ) + dry_file = help_dir / f"{row.package_name}.dryrun.log" + log_to_file(dry_file, dry_log) + if not dry_ok: + stats["dry_run_failed"] += 1 + stats["docs_only_fallback"] += 1 + item["reason"] = "conda dry-run unsatisfiable/timeout -> docs_only fallback" + log_batch(f" ⚠️ dry-run 失败,进入 docs_only 回退") + docs_only = True + + if not docs_only: + log_batch(f" [阶段1B] 安装工具到环境 '{target_env}' ...") + install_start = time.time() + ok, install_log = install_tool( + conda_env=target_env, + package_name=row.package_name, + timeout=install_timeout, + solver=solver, + strict_channel_priority=strict_channel_priority, + ) + install_time = time.time() - install_start + + install_log_file = help_dir / f"{row.package_name}.install.log" + log_to_file(install_log_file, install_log) + item["install_log_file"] = str(install_log_file) + item["installed"] = ok + + if ok: + stats["installed"] += 1 + log_batch(f" ✅ 安装成功 (耗时: {install_time:.2f}s)") + else: + stats["install_failed"] += 1 + stats["docs_only_fallback"] += 1 + item["reason"] = "conda install failed -> docs_only fallback" + log_batch(f" ❌ 安装失败 (耗时: {install_time:.2f}s),进入 docs_only 回退") + docs_only = True + else: + item["reason"] = "install skipped by --skip-install" + stats["skipped_by_no_install"] += 1 + log_batch(f" [阶段1] 跳过安装 (--skip-install)") + docs_only = True + + # ========== 阶段2: 捕获 CLI 帮助 ========== + if docs_only: + logs.append(f"[docs_only] skip cli help capture for {row.package_name}") + chosen_source = "docs_only" + log_batch(" [阶段2] 跳过 CLI 捕获(docs_only 模式)") + else: + log_batch(f" [阶段2] 捕获 CLI 帮助文档 ...") + capture_start = time.time() + + try: + success, chosen_source, chosen_help_text, capture_logs = capture_help_by_runtime( + conda_env=target_env, + row=row, + help_timeout=help_timeout, + ) + logs.extend(capture_logs) + capture_time = time.time() - capture_start + except Exception as e: + capture_time = time.time() - capture_start + log_batch(f" ⚠️ 捕获异常: {str(e)} (耗时: {capture_time:.2f}s)") + success = False + chosen_source = f"exception:{str(e)}" + logs.append(f"Exception during capture: {str(e)}") + + if success: + chosen = chosen_source.split(":", 1)[1] if ":" in chosen_source else chosen_source + help_file = help_txt_dir / f"{row.package_name}.help.txt" + log_to_file(help_file, chosen_help_text) + item["help_file"] = str(help_file) + item["help_ok"] = True + stats["help_success"] += 1 + log_batch(f" ✅ CLI 帮助捕获成功 (耗时: {capture_time:.2f}s)") + log_batch(f" - 可执行文件: {chosen}") + log_batch(f" - 帮助文本长度: {len(chosen_help_text)} 字符") + else: + if not docs_only: + stats["help_failed"] += 1 + log_batch(f" ⚠️ CLI 帮助捕获失败 (耗时: {capture_time:.2f}s)") + log_batch(f" - 来源: {chosen_source}") + + # ========== 阶段3: 收集外部文档 ========== + log_batch(f" [阶段3] 收集外部文档 (URL + conda info) ...") + url_start = time.time() + + url_docs: List[Tuple[str, str]] = [] + url_success_count = 0 + for url in [row.doc_url, row.home_url, row.dev_url]: + if not url: + continue + log_batch(f" - 抓取 URL: {url[:80]}...", also_print=False) + ok, text = fetch_url_text(url) + logs.append(f"[url_fetch] {url}\n{(text or '')[:2000]}") + if ok and text.strip(): + url_docs.append((url, text)) + url_success_count += 1 + log_batch(f" ✅ 成功 (长度: {len(text)} 字符)", also_print=False) + else: + log_batch(f" ❌ 失败", also_print=False) + + conda_ok, conda_info = conda_search_info(row.package_name, timeout=conda_info_timeout) + logs.append(f"[conda_search_info]\n{conda_info}") + conda_info_text = conda_info if conda_ok else "" + log_batch(f" - conda search --info: {'✅ 成功' if conda_ok else '❌ 失败'} (信息长度: {len(conda_info_text)} 字符)", also_print=False) + + url_time = time.time() - url_start + log_batch(f" [阶段3] 完成 (耗时: {url_time:.2f}s, 成功 URL: {url_success_count}/{len([u for u in [row.doc_url, row.home_url, row.dev_url] if u])})") + + # ========== 阶段4: 构建手册包 ========== + log_batch(f" [阶段4] 构建 manual bundle ...") + bundle_start = time.time() + + manual_bundle = build_manual_bundle( + row=row, + cli_help=chosen_help_text, + cli_source=chosen_source, + url_docs=url_docs, + conda_info=conda_info_text, + ) + bundle_file = manual_bundle_dir / f"{row.package_name}.manual_bundle.txt" + log_to_file(bundle_file, manual_bundle) + item["manual_bundle_file"] = str(bundle_file) + stats["manual_bundle_generated"] += 1 + + if chosen_help_text: + item["manual_source"] = chosen_source + manual_source_desc = f"CLI help (via {chosen})" + elif url_docs: + item["manual_source"] = "url_docs" + manual_source_desc = "URL docs" + elif conda_info_text: + item["manual_source"] = "conda_search_info" + manual_source_desc = "conda search --info" + else: + item["manual_source"] = "" + manual_source_desc = "无可用来源" + + bundle_time = time.time() - bundle_start + log_batch(f" [阶段4] 完成 (耗时: {bundle_time:.2f}s, 手册包大小: {len(manual_bundle)} 字符)") + log_batch(f" - 手册来源: {manual_source_desc}") + + # ========== 阶段5: 保存日志 ========== + help_log_file = help_dir / f"{row.package_name}.help.log" + full_log_content = "\n\n" + ("\n" + "=" * 80 + "\n\n").join(logs) + log_to_file(help_log_file, full_log_content) + item["help_log_file"] = str(help_log_file) + + if not success and not item["reason"]: + item["reason"] = "cannot determine runnable executable for --help" + + tool_elapsed = time.time() - tool_start_time + item["processing_time_seconds"] = round(tool_elapsed, 2) + + index[key] = item + + # 工具处理完成汇总 + status_icon = "✅" if item["help_ok"] else "⚠️" + log_batch(f" [完成] {status_icon} 工具 {row.package_name} 处理完成 (总耗时: {tool_elapsed:.2f}s)") + + # ========== 最终汇总 ========== + total_elapsed = time.time() - start_time + log_batch("\n" + "=" * 80) + log_batch("批量收集完成 - 统计报告") + log_batch("=" * 80) + log_batch(f" 📊 总工具数: {stats['total']}") + log_batch(f" 📦 安装成功: {stats['installed']}") + log_batch(f" ❌ 安装失败: {stats['install_failed']}") + log_batch(f" ⏭️ 跳过安装: {stats['skipped_by_no_install']}") + log_batch(f" ⏩ 已处理跳过: {stats['skipped_processed']}") + log_batch(f" 🧪 dry-run 失败: {stats['dry_run_failed']}") + log_batch(f" 📚 docs_only 回退: {stats['docs_only_fallback']}") + log_batch(f" 📖 CLI 帮助成功: {stats['help_success']}") + log_batch(f" ⚠️ CLI 帮助失败: {stats['help_failed']}") + log_batch(f" 📄 手册包生成: {stats['manual_bundle_generated']}") + log_batch(f" ⏱️ 总耗时: {total_elapsed:.2f} 秒") + if stats['total'] > 0: + log_batch(f" 📈 平均每工具耗时: {total_elapsed / stats['total']:.2f} 秒") + log_batch(f" 📁 输出目录: {output_dir}") + log_batch("=" * 80) + + # 写入汇总日志文件 + log_to_file(batch_log_file, "\n".join(batch_log_lines)) + print(f"\n📋 批处理日志已保存至: {batch_log_file}") + + # 如果有失败的工具,列出它们以便排查 + failed_items = [ + (k, v) + for k, v in index.items() + if (not v.get("help_ok", False)) and (not v.get("manual_bundle_file", "")) + ] + if failed_items: + print(f"\n⚠️ 以下 {len(failed_items)} 个工具的帮助文档收集失败:") + for pkg_name, item in failed_items: + reason = item.get("reason", "未知原因") + print(f" - {pkg_name}: {reason}") + + return index + + +def build_converter_jobs(rows: List[ToolRow], help_index: Dict[str, dict]) -> List[dict]: + jobs = [] + for row in rows: + h = help_index.get(row.package_name, {}) + bundle_file = h.get("manual_bundle_file", "") + help_file = h.get("help_file", "") + if bundle_file: + manual = bundle_file + run_help_command = False + elif help_file: + manual = help_file + run_help_command = False + else: + manual = "--help" + run_help_command = True + jobs.append( + { + "name": row.package_name, + "manual": manual, + "run_help_command": run_help_command, + "tier": row.tier, + "domain": row.domain, + } + ) + return jobs + + +def main() -> None: + parser = argparse.ArgumentParser(description="Prepare crawler outputs for BioinfoMCP converter.") + parser.add_argument( + "--input-dir", + default="/225040511/project/BioScientist/agent_system/toolbase/output", + help="Directory containing bioconda_t0/t1/t2 JSON files.", + ) + parser.add_argument( + "--output-dir", + default="/225040511/project/BioScientist/agent_system/toolbase/output", + help="Directory to write converter-ready files.", + ) + parser.add_argument( + "--conda-env", + default="bioinfomcp-env", + help="Base conda environment name. With --use-env-routing, derived envs are auto-created from this prefix.", + ) + parser.add_argument( + "--skip-install", + action="store_true", + help="Do not run conda install; only transform JSON and attempt help on existing env.", + ) + parser.add_argument( + "--max-tools", + type=int, + default=0, + help="Limit number of tools for help collection (0 means all).", + ) + parser.add_argument( + "--python-version", + default="3.10", + help="Python version for auto-created conda env.", + ) + parser.add_argument( + "--install-timeout", + type=int, + default=1800, + help="Timeout (seconds) for each conda install command.", + ) + parser.add_argument( + "--dry-run-timeout", + type=int, + default=600, + help="Timeout (seconds) for conda install --dry-run precheck.", + ) + parser.add_argument( + "--help-timeout", + type=int, + default=120, + help="Timeout (seconds) for each help capture command.", + ) + parser.add_argument( + "--conda-info-timeout", + type=int, + default=120, + help="Timeout (seconds) for conda search --info.", + ) + parser.add_argument( + "--shard-total", + type=int, + default=1, + help="Total shard count for multi-terminal execution.", + ) + parser.add_argument( + "--shard-index", + type=int, + default=0, + help="Current shard index (0-based).", + ) + parser.add_argument( + "--skip-processed", + type=str, + default="True", + help="Skip tools that already have existing manual/help outputs (True/False).", + ) + parser.add_argument( + "--use-env-routing", + type=str, + default="True", + help="Auto route tools to category-specific conda envs (True/False).", + ) + parser.add_argument( + "--enable-dry-run", + type=str, + default="True", + help="Run conda install --dry-run before real install (True/False).", + ) + parser.add_argument( + "--solver", + type=str, + default="conda", + choices=["conda", "mamba"], + help="Package solver executable for install steps.", + ) + parser.add_argument( + "--strict-channel-priority", + type=str, + default="True", + help="Use --strict-channel-priority for install/dry-run (True/False).", + ) + args = parser.parse_args() + use_env_routing = parse_bool(args.use_env_routing, default=True) + enable_dry_run = parse_bool(args.enable_dry_run, default=True) + strict_channel_priority = parse_bool(args.strict_channel_priority, default=True) + skip_processed = parse_bool(args.skip_processed, default=True) + selected_solver = resolve_solver(args.solver) + + input_dir = Path(args.input_dir) + output_dir = Path(args.output_dir) + + files = { + "t0": input_dir / "bioconda_t0_core_tools.json", + "t1": input_dir / "bioconda_t1_domain_tools.json", + "t2": input_dir / "bioconda_t2_on_demand_tools.json", + } + + normalized_by_tier: Dict[str, List[ToolRow]] = {} + all_rows: List[ToolRow] = [] + for tier, file_path in files.items(): + rows = normalize_rows(file_path, read_rows(file_path)) + normalized_by_tier[tier] = rows + all_rows.extend(rows) + + dedup_rows = dedup_keep_best(all_rows) + if args.max_tools > 0: + dedup_rows = dedup_rows[: args.max_tools] + if args.shard_total < 1: + raise ValueError("--shard-total must be >= 1") + if args.shard_index < 0 or args.shard_index >= args.shard_total: + raise ValueError("--shard-index must be in [0, shard_total)") + if args.shard_total > 1: + dedup_rows = [row for idx, row in enumerate(dedup_rows) if idx % args.shard_total == args.shard_index] + print(f"Shard mode enabled: shard {args.shard_index}/{args.shard_total}, tools in this shard: {len(dedup_rows)}") + + # Write converter-friendly JSON per tier and merged. + for tier, rows in normalized_by_tier.items(): + write_json(output_dir / f"converter_input_{tier}.json", [to_converter_row(r) for r in rows]) + write_json(output_dir / "converter_input_all.json", [to_converter_row(r) for r in dedup_rows]) + + # Optional install + help capture + preflight = { + "conda_env": args.conda_env, + "env_ready": True, + "mode": "skip_install", + "solver": selected_solver, + "message": "skip install mode", + } + if not args.skip_install: + if use_env_routing: + preflight = { + "conda_env": args.conda_env, + "env_ready": True, + "mode": "env_routing", + "solver": selected_solver, + "message": "routing mode enabled; per-category envs will be created lazily.", + } + else: + env_ok, env_msg = ensure_conda_env(args.conda_env, python_version=args.python_version) + preflight = { + "conda_env": args.conda_env, + "env_ready": env_ok, + "mode": "single_env", + "solver": selected_solver, + "message": env_msg, + } + write_json(output_dir / "help_preflight.json", preflight) + if not env_ok: + # Environment failed to create; stop before per-tool install. + write_json(output_dir / "help_index.json", {}) + write_json(output_dir / "converter_jobs.json", []) + print("Conda environment preparation failed. See help_preflight.json") + return + write_json(output_dir / "help_preflight.json", preflight) + + help_index = collect_help_for_rows( + rows=dedup_rows, + output_dir=output_dir, + conda_env=args.conda_env, + do_install=not args.skip_install, + python_version=args.python_version, + install_timeout=args.install_timeout, + dry_run_timeout=args.dry_run_timeout, + help_timeout=args.help_timeout, + conda_info_timeout=args.conda_info_timeout, + skip_processed=skip_processed, + use_env_routing=use_env_routing, + enable_dry_run=enable_dry_run, + solver=selected_solver, + strict_channel_priority=strict_channel_priority, + ) + write_json(output_dir / "help_index.json", help_index) + + # Build converter jobs with per-tool manual strategy. + jobs = build_converter_jobs(rows=dedup_rows, help_index=help_index) + write_json(output_dir / "converter_jobs.json", jobs) + + print(f"Prepared {len(dedup_rows)} tools.") + print(f"- converter_input_all.json: {output_dir / 'converter_input_all.json'}") + print(f"- converter_jobs.json: {output_dir / 'converter_jobs.json'}") + print(f"- help_index.json: {output_dir / 'help_index.json'}") + + +if __name__ == "__main__": + main() diff --git a/BioScientist/agent_system/toolbase/register_mcp.py b/BioScientist/agent_system/toolbase/register_mcp.py new file mode 100644 index 0000000000000000000000000000000000000000..791761fe2a3f49b6802307a2afa1b64c8af478cb --- /dev/null +++ b/BioScientist/agent_system/toolbase/register_mcp.py @@ -0,0 +1,5 @@ +from biomni.agent import A1 +agent = A1() +agent.add_mcp(config_path="/225040511/project/Biomni/mcp_config_bioscientist_generated.yaml") +print(len(agent.list_custom_tools())) +print(agent.list_custom_tools()[:20]) \ No newline at end of file diff --git a/BioScientist/agent_system/toolbase/register_mcp_servers_to_biomni.py b/BioScientist/agent_system/toolbase/register_mcp_servers_to_biomni.py new file mode 100644 index 0000000000000000000000000000000000000000..d4cc409cadb30906f96d6e422152d8396b87d76a --- /dev/null +++ b/BioScientist/agent_system/toolbase/register_mcp_servers_to_biomni.py @@ -0,0 +1,433 @@ +#!/usr/bin/env python3 +""" +Batch check/fix MCP server folders and generate a Biomni MCP config. + +Features +- Scan multiple roots containing mcp_* folders +- Validate server script existence +- Ensure requirements.txt contains baseline MCP deps +- Auto-generate FastMCP shim servers when source servers are not directly runnable +- Emit Biomni YAML config consumable by agent.add_mcp(...) +- Emit JSON report for auditing +""" + +from __future__ import annotations + +import argparse +import json +import re +import sys +from dataclasses import asdict, dataclass +from pathlib import Path +from typing import Iterable + + +DEFAULT_SOURCE_DIRS = [ + "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt", + "/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt", +] +DEFAULT_BIOMNI_ROOT = "/225040511/project/Biomni" +DEFAULT_CONFIG_OUT = "/225040511/project/Biomni/mcp_config_bioscientist_generated.yaml" +DEFAULT_REPORT_OUT = "/225040511/project/BioScientist/agent_system/toolbase/mcp_registration_report.json" + + +BASELINE_REQUIREMENTS = ["fastmcp", "mcp"] + + +@dataclass +class ServerRecord: + source_root: str + server_dir: str + server_name: str + tool_name: str + app_dir_exists: bool + server_file: str + server_file_exists: bool + has_fastmcp_bootstrap: bool + has_main_run: bool + requirements_file: str + requirements_created_or_updated: bool + using_shim: bool + shim_file: str + status: str + notes: list[str] + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser( + description="Check/fix MCP server folders and register them into Biomni config." + ) + parser.add_argument( + "--source-dirs", + nargs="+", + default=DEFAULT_SOURCE_DIRS, + help="Roots containing mcp_* directories.", + ) + parser.add_argument( + "--biomni-root", + default=DEFAULT_BIOMNI_ROOT, + help="Biomni repository root.", + ) + parser.add_argument( + "--config-out", + default=DEFAULT_CONFIG_OUT, + help="Output YAML path for Biomni add_mcp config.", + ) + parser.add_argument( + "--report-out", + default=DEFAULT_REPORT_OUT, + help="Output JSON report path.", + ) + parser.add_argument( + "--no-fix-requirements", + action="store_true", + help="Do not modify/create requirements.txt.", + ) + parser.add_argument( + "--no-generate-shims", + action="store_true", + help="Do not generate shim servers; only register directly runnable servers.", + ) + parser.add_argument( + "--python-executable", + default=sys.executable, + help="Python executable used in generated Biomni command entries.", + ) + parser.add_argument( + "--dry-run", + action="store_true", + help="Only analyze and report; do not write files.", + ) + return parser.parse_args() + + +def discover_mcp_dirs(source_roots: Iterable[Path]) -> list[tuple[Path, Path]]: + found: list[tuple[Path, Path]] = [] + for root in source_roots: + if not root.exists(): + continue + for candidate in sorted(root.glob("mcp_*")): + if candidate.is_dir(): + found.append((root, candidate)) + return found + + +def guess_tool_name(server_dir_name: str) -> str: + return server_dir_name[len("mcp_") :] if server_dir_name.startswith("mcp_") else server_dir_name + + +def choose_server_file(server_dir: Path, tool_name: str) -> Path | None: + app_dir = server_dir / "app" + if not app_dir.exists(): + return None + exact = app_dir / f"{tool_name}_server.py" + if exact.exists(): + return exact + any_servers = sorted(app_dir.glob("*_server.py")) + return any_servers[0] if any_servers else None + + +def read_text(path: Path) -> str: + try: + return path.read_text(encoding="utf-8") + except Exception: + return "" + + +def has_fastmcp_bootstrap(code: str) -> bool: + return "from mcp.server.fastmcp import FastMCP" in code and re.search(r"\bmcp\s*=\s*FastMCP\(", code) is not None + + +def has_main_run(code: str) -> bool: + return ('if __name__ == "__main__"' in code or "if __name__ == '__main__'" in code) and "mcp.run(" in code + + +def parse_requirements_text(raw: str) -> list[str]: + lines = [] + for line in raw.splitlines(): + s = line.strip() + if not s or s.startswith("#"): + continue + lines.append(s) + return lines + + +def merge_requirements(existing: list[str], required: list[str]) -> list[str]: + merged = list(existing) + lower_set = {x.lower() for x in merged} + for dep in required: + if dep.lower() not in lower_set: + merged.append(dep) + lower_set.add(dep.lower()) + return merged + + +def pick_requirements_file(server_dir: Path) -> tuple[Path, list[str], str]: + root_req = server_dir / "requirements.txt" + app_req = server_dir / "app" / "requirements.txt" + + root_text = read_text(root_req) if root_req.exists() else "" + app_text = read_text(app_req) if app_req.exists() else "" + + if root_req.exists(): + return root_req, parse_requirements_text(root_text), "root" + if app_req.exists(): + return root_req, parse_requirements_text(app_text), "app_promoted_to_root" + return root_req, [], "new_root" + + +SHIM_TEMPLATE = """#!/usr/bin/env python3 +from __future__ import annotations + +import ast +from pathlib import Path + +from mcp.server.fastmcp import FastMCP + + +SOURCE_SERVER = Path({source_server_path!r}) +LOCAL_SERVER = Path(__file__).with_name(SOURCE_SERVER.name) +SERVER_NAME = {server_name!r} + + +class _ShimMCP: + @staticmethod + def tool(*args, **kwargs): + if args and callable(args[0]) and len(args) == 1 and not kwargs: + return args[0] + def _decorator(fn): + return fn + return _decorator + + +def _resolve_source_server(): + if LOCAL_SERVER.exists() and LOCAL_SERVER.name != Path(__file__).name: + return LOCAL_SERVER + return SOURCE_SERVER + + +def _load_functions(): + source_server = _resolve_source_server() + code = source_server.read_text(encoding="utf-8") + tree = ast.parse(code, filename=str(source_server)) + function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")] + namespace = {{ + "__name__": "__mcp_source__", + "mcp": _ShimMCP(), + }} + exec(compile(code, str(source_server), "exec"), namespace, namespace) + loaded = [] + for name in function_names: + fn = namespace.get(name) + if callable(fn): + loaded.append(fn) + return loaded + + +mcp = FastMCP(SERVER_NAME) +for _fn in _load_functions(): + mcp.tool()(_fn) + + +if __name__ == "__main__": + mcp.run(transport="stdio") +""" + + +def write_shim_if_needed(server_file: Path, server_name: str, dry_run: bool) -> Path: + shim_file = server_file.with_name(server_file.stem.replace("_server", "_shim_server") + ".py") + if dry_run: + return shim_file + shim_code = SHIM_TEMPLATE.format(source_server_path=str(server_file), server_name=server_name) + shim_file.write_text(shim_code, encoding="utf-8") + return shim_file + + +def to_yaml_value(s: str) -> str: + escaped = s.replace("\\", "\\\\").replace('"', '\\"') + return f'"{escaped}"' + + +def write_biomni_yaml(config_path: Path, python_exe: str, entries: list[dict], dry_run: bool) -> None: + lines: list[str] = ["mcp_servers:"] + for e in entries: + lines.append(f" {e['server_name']}:") + lines.append(" enabled: true") + lines.append( + f" command: [{to_yaml_value(python_exe)}, {to_yaml_value(e['server_path'])}]" + ) + lines.append(f" description: {to_yaml_value(e['description'])}") + lines.append("") + if dry_run: + return + config_path.parent.mkdir(parents=True, exist_ok=True) + config_path.write_text("\n".join(lines), encoding="utf-8") + + +def analyze_and_fix_one( + source_root: Path, + server_dir: Path, + fix_requirements: bool, + generate_shims: bool, + dry_run: bool, +) -> tuple[ServerRecord, dict | None]: + tool_name = guess_tool_name(server_dir.name) + server_name = f"biosci_{tool_name}".replace(".", "_").replace("-", "_") + app_dir = server_dir / "app" + server_file = choose_server_file(server_dir, tool_name) + notes: list[str] = [] + + server_exists = server_file is not None and server_file.exists() + code = read_text(server_file) if server_exists and server_file is not None else "" + fastmcp_ok = has_fastmcp_bootstrap(code) + main_run_ok = has_main_run(code) + + req_file, req_existing, req_origin = pick_requirements_file(server_dir) + req_changed = False + if fix_requirements: + req_new = merge_requirements(req_existing, BASELINE_REQUIREMENTS) + if req_new != req_existing or not req_file.exists(): + req_changed = True + if not dry_run: + req_file.write_text("\n".join(req_new) + "\n", encoding="utf-8") + notes.append(f"requirements updated ({req_origin})") + + if not server_exists: + rec = ServerRecord( + source_root=str(source_root), + server_dir=str(server_dir), + server_name=server_name, + tool_name=tool_name, + app_dir_exists=app_dir.exists(), + server_file=str(server_file) if server_file else "", + server_file_exists=False, + has_fastmcp_bootstrap=False, + has_main_run=False, + requirements_file=str(req_file), + requirements_created_or_updated=req_changed, + using_shim=False, + shim_file="", + status="skipped_no_server_file", + notes=notes + ["no *_server.py found in app/"], + ) + return rec, None + + register_path = server_file + using_shim = False + shim_file = "" + if not (fastmcp_ok and main_run_ok): + if generate_shims: + shim_path = write_shim_if_needed(server_file, server_name, dry_run=dry_run) + register_path = shim_path + using_shim = True + shim_file = str(shim_path) + notes.append("generated shim server for MCP stdio compatibility") + else: + rec = ServerRecord( + source_root=str(source_root), + server_dir=str(server_dir), + server_name=server_name, + tool_name=tool_name, + app_dir_exists=app_dir.exists(), + server_file=str(server_file), + server_file_exists=True, + has_fastmcp_bootstrap=fastmcp_ok, + has_main_run=main_run_ok, + requirements_file=str(req_file), + requirements_created_or_updated=req_changed, + using_shim=False, + shim_file="", + status="skipped_non_runnable_without_shim", + notes=notes + ["server lacks FastMCP bootstrap and/or mcp.run main"], + ) + return rec, None + + rec = ServerRecord( + source_root=str(source_root), + server_dir=str(server_dir), + server_name=server_name, + tool_name=tool_name, + app_dir_exists=app_dir.exists(), + server_file=str(server_file), + server_file_exists=True, + has_fastmcp_bootstrap=fastmcp_ok, + has_main_run=main_run_ok, + requirements_file=str(req_file), + requirements_created_or_updated=req_changed, + using_shim=using_shim, + shim_file=shim_file, + status="registered", + notes=notes, + ) + config_entry = { + "server_name": server_name, + "server_path": str(register_path), + "description": f"BioScientist MCP server for {tool_name}", + } + return rec, config_entry + + +def main() -> int: + args = parse_args() + + source_roots = [Path(p).resolve() for p in args.source_dirs] + biomni_root = Path(args.biomni_root).resolve() + config_out = Path(args.config_out).resolve() + report_out = Path(args.report_out).resolve() + + discovered = discover_mcp_dirs(source_roots) + records: list[ServerRecord] = [] + config_entries: list[dict] = [] + + for source_root, server_dir in discovered: + rec, config_entry = analyze_and_fix_one( + source_root=source_root, + server_dir=server_dir, + fix_requirements=not args.no_fix_requirements, + generate_shims=not args.no_generate_shims, + dry_run=args.dry_run, + ) + records.append(rec) + if config_entry: + config_entries.append(config_entry) + + # Stable order in generated YAML. + config_entries = sorted(config_entries, key=lambda x: x["server_name"]) + write_biomni_yaml(config_out, args.python_executable, config_entries, dry_run=args.dry_run) + + report_payload = { + "summary": { + "scanned_dirs": len(discovered), + "registered": sum(1 for r in records if r.status == "registered"), + "skipped_no_server_file": sum(1 for r in records if r.status == "skipped_no_server_file"), + "skipped_non_runnable_without_shim": sum( + 1 for r in records if r.status == "skipped_non_runnable_without_shim" + ), + "using_shim": sum(1 for r in records if r.using_shim), + "requirements_touched": sum(1 for r in records if r.requirements_created_or_updated), + "dry_run": bool(args.dry_run), + }, + "biomni_root": str(biomni_root), + "config_out": str(config_out), + "report_out": str(report_out), + "records": [asdict(r) for r in records], + } + + if not args.dry_run: + report_out.parent.mkdir(parents=True, exist_ok=True) + report_out.write_text(json.dumps(report_payload, ensure_ascii=False, indent=2), encoding="utf-8") + + print(json.dumps(report_payload["summary"], ensure_ascii=False, indent=2)) + print(f"Config path: {config_out}") + print(f"Report path: {report_out}") + print("") + print("Biomni usage:") + print("from biomni.agent import A1") + print("agent = A1()") + print(f'agent.add_mcp(config_path="{config_out}")') + print("print(agent.list_custom_tools())") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/BioScientist/requirements.txt b/BioScientist/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..f863b80c56927e4fb583e1d09a9a0afaea7a2c9b --- /dev/null +++ b/BioScientist/requirements.txt @@ -0,0 +1,13 @@ +# Core runtime +requests>=2.31.0 +beautifulsoup4>=4.12.0 +python-dotenv>=1.0.0 +PyMuPDF>=1.24.0 + +# LLM backends +openai>=1.30.0 +anthropic>=0.34.0 +google-generativeai>=0.8.0 + +# MCP server/runtime helpers used by generated servers +fastmcp>=2.0.0 diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/__pycache__/_virtualenv.cpython-314.pyc b/bioagent-bench/.venv/lib/python3.14/site-packages/__pycache__/_virtualenv.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4515b87ec0851170eb08661c1382f4842809ad24 Binary files /dev/null and b/bioagent-bench/.venv/lib/python3.14/site-packages/__pycache__/_virtualenv.cpython-314.pyc differ diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/aiohappyeyeballs-2.6.1.dist-info/LICENSE b/bioagent-bench/.venv/lib/python3.14/site-packages/aiohappyeyeballs-2.6.1.dist-info/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..f26bcf4d2de6eb136e31006ca3ab447d5e488adf --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/aiohappyeyeballs-2.6.1.dist-info/LICENSE @@ -0,0 +1,279 @@ +A. HISTORY OF THE SOFTWARE +========================== + +Python was created in the early 1990s by Guido van Rossum at Stichting +Mathematisch Centrum (CWI, see https://www.cwi.nl) in the Netherlands +as a successor of a language called ABC. Guido remains Python's +principal author, although it includes many contributions from others. + +In 1995, Guido continued his work on Python at the Corporation for +National Research Initiatives (CNRI, see https://www.cnri.reston.va.us) +in Reston, Virginia where he released several versions of the +software. + +In May 2000, Guido and the Python core development team moved to +BeOpen.com to form the BeOpen PythonLabs team. In October of the same +year, the PythonLabs team moved to Digital Creations, which became +Zope Corporation. In 2001, the Python Software Foundation (PSF, see +https://www.python.org/psf/) was formed, a non-profit organization +created specifically to own Python-related Intellectual Property. +Zope Corporation was a sponsoring member of the PSF. + +All Python releases are Open Source (see https://opensource.org for +the Open Source Definition). Historically, most, but not all, Python +releases have also been GPL-compatible; the table below summarizes +the various releases. + + Release Derived Year Owner GPL- + from compatible? (1) + + 0.9.0 thru 1.2 1991-1995 CWI yes + 1.3 thru 1.5.2 1.2 1995-1999 CNRI yes + 1.6 1.5.2 2000 CNRI no + 2.0 1.6 2000 BeOpen.com no + 1.6.1 1.6 2001 CNRI yes (2) + 2.1 2.0+1.6.1 2001 PSF no + 2.0.1 2.0+1.6.1 2001 PSF yes + 2.1.1 2.1+2.0.1 2001 PSF yes + 2.1.2 2.1.1 2002 PSF yes + 2.1.3 2.1.2 2002 PSF yes + 2.2 and above 2.1.1 2001-now PSF yes + +Footnotes: + +(1) GPL-compatible doesn't mean that we're distributing Python under + the GPL. All Python licenses, unlike the GPL, let you distribute + a modified version without making your changes open source. The + GPL-compatible licenses make it possible to combine Python with + other software that is released under the GPL; the others don't. + +(2) According to Richard Stallman, 1.6.1 is not GPL-compatible, + because its license has a choice of law clause. According to + CNRI, however, Stallman's lawyer has told CNRI's lawyer that 1.6.1 + is "not incompatible" with the GPL. + +Thanks to the many outside volunteers who have worked under Guido's +direction to make these releases possible. + + +B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON +=============================================================== + +Python software and documentation are licensed under the +Python Software Foundation License Version 2. + +Starting with Python 3.8.6, examples, recipes, and other code in +the documentation are dual licensed under the PSF License Version 2 +and the Zero-Clause BSD license. + +Some software incorporated into Python is under different licenses. +The licenses are listed with code falling under that license. + + +PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 +-------------------------------------------- + +1. This LICENSE AGREEMENT is between the Python Software Foundation +("PSF"), and the Individual or Organization ("Licensee") accessing and +otherwise using this software ("Python") in source or binary form and +its associated documentation. + +2. Subject to the terms and conditions of this License Agreement, PSF hereby +grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, +analyze, test, perform and/or display publicly, prepare derivative works, +distribute, and otherwise use Python alone or in any derivative version, +provided, however, that PSF's License Agreement and PSF's notice of copyright, +i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023 Python Software Foundation; +All Rights Reserved" are retained in Python alone or in any derivative version +prepared by Licensee. + +3. In the event Licensee prepares a derivative work that is based on +or incorporates Python or any part thereof, and wants to make +the derivative work available to others as provided herein, then +Licensee hereby agrees to include in any such work a brief summary of +the changes made to Python. + +4. PSF is making Python available to Licensee on an "AS IS" +basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT +INFRINGE ANY THIRD PARTY RIGHTS. + +5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON +FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS +A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, +OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +6. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +7. Nothing in this License Agreement shall be deemed to create any +relationship of agency, partnership, or joint venture between PSF and +Licensee. This License Agreement does not grant permission to use PSF +trademarks or trade name in a trademark sense to endorse or promote +products or services of Licensee, or any third party. + +8. By copying, installing or otherwise using Python, Licensee +agrees to be bound by the terms and conditions of this License +Agreement. + + +BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0 +------------------------------------------- + +BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1 + +1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an +office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the +Individual or Organization ("Licensee") accessing and otherwise using +this software in source or binary form and its associated +documentation ("the Software"). + +2. Subject to the terms and conditions of this BeOpen Python License +Agreement, BeOpen hereby grants Licensee a non-exclusive, +royalty-free, world-wide license to reproduce, analyze, test, perform +and/or display publicly, prepare derivative works, distribute, and +otherwise use the Software alone or in any derivative version, +provided, however, that the BeOpen Python License is retained in the +Software, alone or in any derivative version prepared by Licensee. + +3. BeOpen is making the Software available to Licensee on an "AS IS" +basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT +INFRINGE ANY THIRD PARTY RIGHTS. + +4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE +SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS +AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY +DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +5. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +6. This License Agreement shall be governed by and interpreted in all +respects by the law of the State of California, excluding conflict of +law provisions. Nothing in this License Agreement shall be deemed to +create any relationship of agency, partnership, or joint venture +between BeOpen and Licensee. This License Agreement does not grant +permission to use BeOpen trademarks or trade names in a trademark +sense to endorse or promote products or services of Licensee, or any +third party. As an exception, the "BeOpen Python" logos available at +http://www.pythonlabs.com/logos.html may be used according to the +permissions granted on that web page. + +7. By copying, installing or otherwise using the software, Licensee +agrees to be bound by the terms and conditions of this License +Agreement. + + +CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1 +--------------------------------------- + +1. This LICENSE AGREEMENT is between the Corporation for National +Research Initiatives, having an office at 1895 Preston White Drive, +Reston, VA 20191 ("CNRI"), and the Individual or Organization +("Licensee") accessing and otherwise using Python 1.6.1 software in +source or binary form and its associated documentation. + +2. Subject to the terms and conditions of this License Agreement, CNRI +hereby grants Licensee a nonexclusive, royalty-free, world-wide +license to reproduce, analyze, test, perform and/or display publicly, +prepare derivative works, distribute, and otherwise use Python 1.6.1 +alone or in any derivative version, provided, however, that CNRI's +License Agreement and CNRI's notice of copyright, i.e., "Copyright (c) +1995-2001 Corporation for National Research Initiatives; All Rights +Reserved" are retained in Python 1.6.1 alone or in any derivative +version prepared by Licensee. Alternately, in lieu of CNRI's License +Agreement, Licensee may substitute the following text (omitting the +quotes): "Python 1.6.1 is made available subject to the terms and +conditions in CNRI's License Agreement. This Agreement together with +Python 1.6.1 may be located on the internet using the following +unique, persistent identifier (known as a handle): 1895.22/1013. This +Agreement may also be obtained from a proxy server on the internet +using the following URL: http://hdl.handle.net/1895.22/1013". + +3. In the event Licensee prepares a derivative work that is based on +or incorporates Python 1.6.1 or any part thereof, and wants to make +the derivative work available to others as provided herein, then +Licensee hereby agrees to include in any such work a brief summary of +the changes made to Python 1.6.1. + +4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS" +basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT +INFRINGE ANY THIRD PARTY RIGHTS. + +5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON +1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS +A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1, +OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +6. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +7. This License Agreement shall be governed by the federal +intellectual property law of the United States, including without +limitation the federal copyright law, and, to the extent such +U.S. federal law does not apply, by the law of the Commonwealth of +Virginia, excluding Virginia's conflict of law provisions. +Notwithstanding the foregoing, with regard to derivative works based +on Python 1.6.1 that incorporate non-separable material that was +previously distributed under the GNU General Public License (GPL), the +law of the Commonwealth of Virginia shall govern this License +Agreement only as to issues arising under or with respect to +Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this +License Agreement shall be deemed to create any relationship of +agency, partnership, or joint venture between CNRI and Licensee. This +License Agreement does not grant permission to use CNRI trademarks or +trade name in a trademark sense to endorse or promote products or +services of Licensee, or any third party. + +8. By clicking on the "ACCEPT" button where indicated, or by copying, +installing or otherwise using Python 1.6.1, Licensee agrees to be +bound by the terms and conditions of this License Agreement. + + ACCEPT + + +CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2 +-------------------------------------------------- + +Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam, +The Netherlands. All rights reserved. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Stichting Mathematisch +Centrum or CWI not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO +THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE +FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +ZERO-CLAUSE BSD LICENSE FOR CODE IN THE PYTHON DOCUMENTATION +---------------------------------------------------------------------- + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/aiohappyeyeballs-2.6.1.dist-info/WHEEL b/bioagent-bench/.venv/lib/python3.14/site-packages/aiohappyeyeballs-2.6.1.dist-info/WHEEL new file mode 100644 index 0000000000000000000000000000000000000000..0582547b15f02d3a51659106262832565d5dc5ea --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/aiohappyeyeballs-2.6.1.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: poetry-core 2.1.1 +Root-Is-Purelib: true +Tag: py3-none-any diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/dateutil/parser/isoparser.py b/bioagent-bench/.venv/lib/python3.14/site-packages/dateutil/parser/isoparser.py new file mode 100644 index 0000000000000000000000000000000000000000..7060087df4776a07347cbb60127a70db393e3a65 --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/dateutil/parser/isoparser.py @@ -0,0 +1,416 @@ +# -*- coding: utf-8 -*- +""" +This module offers a parser for ISO-8601 strings + +It is intended to support all valid date, time and datetime formats per the +ISO-8601 specification. + +..versionadded:: 2.7.0 +""" +from datetime import datetime, timedelta, time, date +import calendar +from dateutil import tz + +from functools import wraps + +import re +import six + +__all__ = ["isoparse", "isoparser"] + + +def _takes_ascii(f): + @wraps(f) + def func(self, str_in, *args, **kwargs): + # If it's a stream, read the whole thing + str_in = getattr(str_in, 'read', lambda: str_in)() + + # If it's unicode, turn it into bytes, since ISO-8601 only covers ASCII + if isinstance(str_in, six.text_type): + # ASCII is the same in UTF-8 + try: + str_in = str_in.encode('ascii') + except UnicodeEncodeError as e: + msg = 'ISO-8601 strings should contain only ASCII characters' + six.raise_from(ValueError(msg), e) + + return f(self, str_in, *args, **kwargs) + + return func + + +class isoparser(object): + def __init__(self, sep=None): + """ + :param sep: + A single character that separates date and time portions. If + ``None``, the parser will accept any single character. + For strict ISO-8601 adherence, pass ``'T'``. + """ + if sep is not None: + if (len(sep) != 1 or ord(sep) >= 128 or sep in '0123456789'): + raise ValueError('Separator must be a single, non-numeric ' + + 'ASCII character') + + sep = sep.encode('ascii') + + self._sep = sep + + @_takes_ascii + def isoparse(self, dt_str): + """ + Parse an ISO-8601 datetime string into a :class:`datetime.datetime`. + + An ISO-8601 datetime string consists of a date portion, followed + optionally by a time portion - the date and time portions are separated + by a single character separator, which is ``T`` in the official + standard. Incomplete date formats (such as ``YYYY-MM``) may *not* be + combined with a time portion. + + Supported date formats are: + + Common: + + - ``YYYY`` + - ``YYYY-MM`` + - ``YYYY-MM-DD`` or ``YYYYMMDD`` + + Uncommon: + + - ``YYYY-Www`` or ``YYYYWww`` - ISO week (day defaults to 0) + - ``YYYY-Www-D`` or ``YYYYWwwD`` - ISO week and day + + The ISO week and day numbering follows the same logic as + :func:`datetime.date.isocalendar`. + + Supported time formats are: + + - ``hh`` + - ``hh:mm`` or ``hhmm`` + - ``hh:mm:ss`` or ``hhmmss`` + - ``hh:mm:ss.ssssss`` (Up to 6 sub-second digits) + + Midnight is a special case for `hh`, as the standard supports both + 00:00 and 24:00 as a representation. The decimal separator can be + either a dot or a comma. + + + .. caution:: + + Support for fractional components other than seconds is part of the + ISO-8601 standard, but is not currently implemented in this parser. + + Supported time zone offset formats are: + + - `Z` (UTC) + - `±HH:MM` + - `±HHMM` + - `±HH` + + Offsets will be represented as :class:`dateutil.tz.tzoffset` objects, + with the exception of UTC, which will be represented as + :class:`dateutil.tz.tzutc`. Time zone offsets equivalent to UTC (such + as `+00:00`) will also be represented as :class:`dateutil.tz.tzutc`. + + :param dt_str: + A string or stream containing only an ISO-8601 datetime string + + :return: + Returns a :class:`datetime.datetime` representing the string. + Unspecified components default to their lowest value. + + .. warning:: + + As of version 2.7.0, the strictness of the parser should not be + considered a stable part of the contract. Any valid ISO-8601 string + that parses correctly with the default settings will continue to + parse correctly in future versions, but invalid strings that + currently fail (e.g. ``2017-01-01T00:00+00:00:00``) are not + guaranteed to continue failing in future versions if they encode + a valid date. + + .. versionadded:: 2.7.0 + """ + components, pos = self._parse_isodate(dt_str) + + if len(dt_str) > pos: + if self._sep is None or dt_str[pos:pos + 1] == self._sep: + components += self._parse_isotime(dt_str[pos + 1:]) + else: + raise ValueError('String contains unknown ISO components') + + if len(components) > 3 and components[3] == 24: + components[3] = 0 + return datetime(*components) + timedelta(days=1) + + return datetime(*components) + + @_takes_ascii + def parse_isodate(self, datestr): + """ + Parse the date portion of an ISO string. + + :param datestr: + The string portion of an ISO string, without a separator + + :return: + Returns a :class:`datetime.date` object + """ + components, pos = self._parse_isodate(datestr) + if pos < len(datestr): + raise ValueError('String contains unknown ISO ' + + 'components: {!r}'.format(datestr.decode('ascii'))) + return date(*components) + + @_takes_ascii + def parse_isotime(self, timestr): + """ + Parse the time portion of an ISO string. + + :param timestr: + The time portion of an ISO string, without a separator + + :return: + Returns a :class:`datetime.time` object + """ + components = self._parse_isotime(timestr) + if components[0] == 24: + components[0] = 0 + return time(*components) + + @_takes_ascii + def parse_tzstr(self, tzstr, zero_as_utc=True): + """ + Parse a valid ISO time zone string. + + See :func:`isoparser.isoparse` for details on supported formats. + + :param tzstr: + A string representing an ISO time zone offset + + :param zero_as_utc: + Whether to return :class:`dateutil.tz.tzutc` for zero-offset zones + + :return: + Returns :class:`dateutil.tz.tzoffset` for offsets and + :class:`dateutil.tz.tzutc` for ``Z`` and (if ``zero_as_utc`` is + specified) offsets equivalent to UTC. + """ + return self._parse_tzstr(tzstr, zero_as_utc=zero_as_utc) + + # Constants + _DATE_SEP = b'-' + _TIME_SEP = b':' + _FRACTION_REGEX = re.compile(b'[\\.,]([0-9]+)') + + def _parse_isodate(self, dt_str): + try: + return self._parse_isodate_common(dt_str) + except ValueError: + return self._parse_isodate_uncommon(dt_str) + + def _parse_isodate_common(self, dt_str): + len_str = len(dt_str) + components = [1, 1, 1] + + if len_str < 4: + raise ValueError('ISO string too short') + + # Year + components[0] = int(dt_str[0:4]) + pos = 4 + if pos >= len_str: + return components, pos + + has_sep = dt_str[pos:pos + 1] == self._DATE_SEP + if has_sep: + pos += 1 + + # Month + if len_str - pos < 2: + raise ValueError('Invalid common month') + + components[1] = int(dt_str[pos:pos + 2]) + pos += 2 + + if pos >= len_str: + if has_sep: + return components, pos + else: + raise ValueError('Invalid ISO format') + + if has_sep: + if dt_str[pos:pos + 1] != self._DATE_SEP: + raise ValueError('Invalid separator in ISO string') + pos += 1 + + # Day + if len_str - pos < 2: + raise ValueError('Invalid common day') + components[2] = int(dt_str[pos:pos + 2]) + return components, pos + 2 + + def _parse_isodate_uncommon(self, dt_str): + if len(dt_str) < 4: + raise ValueError('ISO string too short') + + # All ISO formats start with the year + year = int(dt_str[0:4]) + + has_sep = dt_str[4:5] == self._DATE_SEP + + pos = 4 + has_sep # Skip '-' if it's there + if dt_str[pos:pos + 1] == b'W': + # YYYY-?Www-?D? + pos += 1 + weekno = int(dt_str[pos:pos + 2]) + pos += 2 + + dayno = 1 + if len(dt_str) > pos: + if (dt_str[pos:pos + 1] == self._DATE_SEP) != has_sep: + raise ValueError('Inconsistent use of dash separator') + + pos += has_sep + + dayno = int(dt_str[pos:pos + 1]) + pos += 1 + + base_date = self._calculate_weekdate(year, weekno, dayno) + else: + # YYYYDDD or YYYY-DDD + if len(dt_str) - pos < 3: + raise ValueError('Invalid ordinal day') + + ordinal_day = int(dt_str[pos:pos + 3]) + pos += 3 + + if ordinal_day < 1 or ordinal_day > (365 + calendar.isleap(year)): + raise ValueError('Invalid ordinal day' + + ' {} for year {}'.format(ordinal_day, year)) + + base_date = date(year, 1, 1) + timedelta(days=ordinal_day - 1) + + components = [base_date.year, base_date.month, base_date.day] + return components, pos + + def _calculate_weekdate(self, year, week, day): + """ + Calculate the day of corresponding to the ISO year-week-day calendar. + + This function is effectively the inverse of + :func:`datetime.date.isocalendar`. + + :param year: + The year in the ISO calendar + + :param week: + The week in the ISO calendar - range is [1, 53] + + :param day: + The day in the ISO calendar - range is [1 (MON), 7 (SUN)] + + :return: + Returns a :class:`datetime.date` + """ + if not 0 < week < 54: + raise ValueError('Invalid week: {}'.format(week)) + + if not 0 < day < 8: # Range is 1-7 + raise ValueError('Invalid weekday: {}'.format(day)) + + # Get week 1 for the specific year: + jan_4 = date(year, 1, 4) # Week 1 always has January 4th in it + week_1 = jan_4 - timedelta(days=jan_4.isocalendar()[2] - 1) + + # Now add the specific number of weeks and days to get what we want + week_offset = (week - 1) * 7 + (day - 1) + return week_1 + timedelta(days=week_offset) + + def _parse_isotime(self, timestr): + len_str = len(timestr) + components = [0, 0, 0, 0, None] + pos = 0 + comp = -1 + + if len_str < 2: + raise ValueError('ISO time too short') + + has_sep = False + + while pos < len_str and comp < 5: + comp += 1 + + if timestr[pos:pos + 1] in b'-+Zz': + # Detect time zone boundary + components[-1] = self._parse_tzstr(timestr[pos:]) + pos = len_str + break + + if comp == 1 and timestr[pos:pos+1] == self._TIME_SEP: + has_sep = True + pos += 1 + elif comp == 2 and has_sep: + if timestr[pos:pos+1] != self._TIME_SEP: + raise ValueError('Inconsistent use of colon separator') + pos += 1 + + if comp < 3: + # Hour, minute, second + components[comp] = int(timestr[pos:pos + 2]) + pos += 2 + + if comp == 3: + # Fraction of a second + frac = self._FRACTION_REGEX.match(timestr[pos:]) + if not frac: + continue + + us_str = frac.group(1)[:6] # Truncate to microseconds + components[comp] = int(us_str) * 10**(6 - len(us_str)) + pos += len(frac.group()) + + if pos < len_str: + raise ValueError('Unused components in ISO string') + + if components[0] == 24: + # Standard supports 00:00 and 24:00 as representations of midnight + if any(component != 0 for component in components[1:4]): + raise ValueError('Hour may only be 24 at 24:00:00.000') + + return components + + def _parse_tzstr(self, tzstr, zero_as_utc=True): + if tzstr == b'Z' or tzstr == b'z': + return tz.UTC + + if len(tzstr) not in {3, 5, 6}: + raise ValueError('Time zone offset must be 1, 3, 5 or 6 characters') + + if tzstr[0:1] == b'-': + mult = -1 + elif tzstr[0:1] == b'+': + mult = 1 + else: + raise ValueError('Time zone offset requires sign') + + hours = int(tzstr[1:3]) + if len(tzstr) == 3: + minutes = 0 + else: + minutes = int(tzstr[(4 if tzstr[3:4] == self._TIME_SEP else 3):]) + + if zero_as_utc and hours == 0 and minutes == 0: + return tz.UTC + else: + if minutes > 59: + raise ValueError('Invalid minutes in time zone offset') + + if hours > 23: + raise ValueError('Invalid hours in time zone offset') + + return tz.tzoffset(None, mult * (hours * 60 + minutes) * 60) + + +DEFAULT_ISOPARSER = isoparser() +isoparse = DEFAULT_ISOPARSER.isoparse diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/dateutil/tz/_common.py b/bioagent-bench/.venv/lib/python3.14/site-packages/dateutil/tz/_common.py new file mode 100644 index 0000000000000000000000000000000000000000..e6ac11831522b266114d5b68ee1da298e3aeb14a --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/dateutil/tz/_common.py @@ -0,0 +1,419 @@ +from six import PY2 + +from functools import wraps + +from datetime import datetime, timedelta, tzinfo + + +ZERO = timedelta(0) + +__all__ = ['tzname_in_python2', 'enfold'] + + +def tzname_in_python2(namefunc): + """Change unicode output into bytestrings in Python 2 + + tzname() API changed in Python 3. It used to return bytes, but was changed + to unicode strings + """ + if PY2: + @wraps(namefunc) + def adjust_encoding(*args, **kwargs): + name = namefunc(*args, **kwargs) + if name is not None: + name = name.encode() + + return name + + return adjust_encoding + else: + return namefunc + + +# The following is adapted from Alexander Belopolsky's tz library +# https://github.com/abalkin/tz +if hasattr(datetime, 'fold'): + # This is the pre-python 3.6 fold situation + def enfold(dt, fold=1): + """ + Provides a unified interface for assigning the ``fold`` attribute to + datetimes both before and after the implementation of PEP-495. + + :param fold: + The value for the ``fold`` attribute in the returned datetime. This + should be either 0 or 1. + + :return: + Returns an object for which ``getattr(dt, 'fold', 0)`` returns + ``fold`` for all versions of Python. In versions prior to + Python 3.6, this is a ``_DatetimeWithFold`` object, which is a + subclass of :py:class:`datetime.datetime` with the ``fold`` + attribute added, if ``fold`` is 1. + + .. versionadded:: 2.6.0 + """ + return dt.replace(fold=fold) + +else: + class _DatetimeWithFold(datetime): + """ + This is a class designed to provide a PEP 495-compliant interface for + Python versions before 3.6. It is used only for dates in a fold, so + the ``fold`` attribute is fixed at ``1``. + + .. versionadded:: 2.6.0 + """ + __slots__ = () + + def replace(self, *args, **kwargs): + """ + Return a datetime with the same attributes, except for those + attributes given new values by whichever keyword arguments are + specified. Note that tzinfo=None can be specified to create a naive + datetime from an aware datetime with no conversion of date and time + data. + + This is reimplemented in ``_DatetimeWithFold`` because pypy3 will + return a ``datetime.datetime`` even if ``fold`` is unchanged. + """ + argnames = ( + 'year', 'month', 'day', 'hour', 'minute', 'second', + 'microsecond', 'tzinfo' + ) + + for arg, argname in zip(args, argnames): + if argname in kwargs: + raise TypeError('Duplicate argument: {}'.format(argname)) + + kwargs[argname] = arg + + for argname in argnames: + if argname not in kwargs: + kwargs[argname] = getattr(self, argname) + + dt_class = self.__class__ if kwargs.get('fold', 1) else datetime + + return dt_class(**kwargs) + + @property + def fold(self): + return 1 + + def enfold(dt, fold=1): + """ + Provides a unified interface for assigning the ``fold`` attribute to + datetimes both before and after the implementation of PEP-495. + + :param fold: + The value for the ``fold`` attribute in the returned datetime. This + should be either 0 or 1. + + :return: + Returns an object for which ``getattr(dt, 'fold', 0)`` returns + ``fold`` for all versions of Python. In versions prior to + Python 3.6, this is a ``_DatetimeWithFold`` object, which is a + subclass of :py:class:`datetime.datetime` with the ``fold`` + attribute added, if ``fold`` is 1. + + .. versionadded:: 2.6.0 + """ + if getattr(dt, 'fold', 0) == fold: + return dt + + args = dt.timetuple()[:6] + args += (dt.microsecond, dt.tzinfo) + + if fold: + return _DatetimeWithFold(*args) + else: + return datetime(*args) + + +def _validate_fromutc_inputs(f): + """ + The CPython version of ``fromutc`` checks that the input is a ``datetime`` + object and that ``self`` is attached as its ``tzinfo``. + """ + @wraps(f) + def fromutc(self, dt): + if not isinstance(dt, datetime): + raise TypeError("fromutc() requires a datetime argument") + if dt.tzinfo is not self: + raise ValueError("dt.tzinfo is not self") + + return f(self, dt) + + return fromutc + + +class _tzinfo(tzinfo): + """ + Base class for all ``dateutil`` ``tzinfo`` objects. + """ + + def is_ambiguous(self, dt): + """ + Whether or not the "wall time" of a given datetime is ambiguous in this + zone. + + :param dt: + A :py:class:`datetime.datetime`, naive or time zone aware. + + + :return: + Returns ``True`` if ambiguous, ``False`` otherwise. + + .. versionadded:: 2.6.0 + """ + + dt = dt.replace(tzinfo=self) + + wall_0 = enfold(dt, fold=0) + wall_1 = enfold(dt, fold=1) + + same_offset = wall_0.utcoffset() == wall_1.utcoffset() + same_dt = wall_0.replace(tzinfo=None) == wall_1.replace(tzinfo=None) + + return same_dt and not same_offset + + def _fold_status(self, dt_utc, dt_wall): + """ + Determine the fold status of a "wall" datetime, given a representation + of the same datetime as a (naive) UTC datetime. This is calculated based + on the assumption that ``dt.utcoffset() - dt.dst()`` is constant for all + datetimes, and that this offset is the actual number of hours separating + ``dt_utc`` and ``dt_wall``. + + :param dt_utc: + Representation of the datetime as UTC + + :param dt_wall: + Representation of the datetime as "wall time". This parameter must + either have a `fold` attribute or have a fold-naive + :class:`datetime.tzinfo` attached, otherwise the calculation may + fail. + """ + if self.is_ambiguous(dt_wall): + delta_wall = dt_wall - dt_utc + _fold = int(delta_wall == (dt_utc.utcoffset() - dt_utc.dst())) + else: + _fold = 0 + + return _fold + + def _fold(self, dt): + return getattr(dt, 'fold', 0) + + def _fromutc(self, dt): + """ + Given a timezone-aware datetime in a given timezone, calculates a + timezone-aware datetime in a new timezone. + + Since this is the one time that we *know* we have an unambiguous + datetime object, we take this opportunity to determine whether the + datetime is ambiguous and in a "fold" state (e.g. if it's the first + occurrence, chronologically, of the ambiguous datetime). + + :param dt: + A timezone-aware :class:`datetime.datetime` object. + """ + + # Re-implement the algorithm from Python's datetime.py + dtoff = dt.utcoffset() + if dtoff is None: + raise ValueError("fromutc() requires a non-None utcoffset() " + "result") + + # The original datetime.py code assumes that `dst()` defaults to + # zero during ambiguous times. PEP 495 inverts this presumption, so + # for pre-PEP 495 versions of python, we need to tweak the algorithm. + dtdst = dt.dst() + if dtdst is None: + raise ValueError("fromutc() requires a non-None dst() result") + delta = dtoff - dtdst + + dt += delta + # Set fold=1 so we can default to being in the fold for + # ambiguous dates. + dtdst = enfold(dt, fold=1).dst() + if dtdst is None: + raise ValueError("fromutc(): dt.dst gave inconsistent " + "results; cannot convert") + return dt + dtdst + + @_validate_fromutc_inputs + def fromutc(self, dt): + """ + Given a timezone-aware datetime in a given timezone, calculates a + timezone-aware datetime in a new timezone. + + Since this is the one time that we *know* we have an unambiguous + datetime object, we take this opportunity to determine whether the + datetime is ambiguous and in a "fold" state (e.g. if it's the first + occurrence, chronologically, of the ambiguous datetime). + + :param dt: + A timezone-aware :class:`datetime.datetime` object. + """ + dt_wall = self._fromutc(dt) + + # Calculate the fold status given the two datetimes. + _fold = self._fold_status(dt, dt_wall) + + # Set the default fold value for ambiguous dates + return enfold(dt_wall, fold=_fold) + + +class tzrangebase(_tzinfo): + """ + This is an abstract base class for time zones represented by an annual + transition into and out of DST. Child classes should implement the following + methods: + + * ``__init__(self, *args, **kwargs)`` + * ``transitions(self, year)`` - this is expected to return a tuple of + datetimes representing the DST on and off transitions in standard + time. + + A fully initialized ``tzrangebase`` subclass should also provide the + following attributes: + * ``hasdst``: Boolean whether or not the zone uses DST. + * ``_dst_offset`` / ``_std_offset``: :class:`datetime.timedelta` objects + representing the respective UTC offsets. + * ``_dst_abbr`` / ``_std_abbr``: Strings representing the timezone short + abbreviations in DST and STD, respectively. + * ``_hasdst``: Whether or not the zone has DST. + + .. versionadded:: 2.6.0 + """ + def __init__(self): + raise NotImplementedError('tzrangebase is an abstract base class') + + def utcoffset(self, dt): + isdst = self._isdst(dt) + + if isdst is None: + return None + elif isdst: + return self._dst_offset + else: + return self._std_offset + + def dst(self, dt): + isdst = self._isdst(dt) + + if isdst is None: + return None + elif isdst: + return self._dst_base_offset + else: + return ZERO + + @tzname_in_python2 + def tzname(self, dt): + if self._isdst(dt): + return self._dst_abbr + else: + return self._std_abbr + + def fromutc(self, dt): + """ Given a datetime in UTC, return local time """ + if not isinstance(dt, datetime): + raise TypeError("fromutc() requires a datetime argument") + + if dt.tzinfo is not self: + raise ValueError("dt.tzinfo is not self") + + # Get transitions - if there are none, fixed offset + transitions = self.transitions(dt.year) + if transitions is None: + return dt + self.utcoffset(dt) + + # Get the transition times in UTC + dston, dstoff = transitions + + dston -= self._std_offset + dstoff -= self._std_offset + + utc_transitions = (dston, dstoff) + dt_utc = dt.replace(tzinfo=None) + + isdst = self._naive_isdst(dt_utc, utc_transitions) + + if isdst: + dt_wall = dt + self._dst_offset + else: + dt_wall = dt + self._std_offset + + _fold = int(not isdst and self.is_ambiguous(dt_wall)) + + return enfold(dt_wall, fold=_fold) + + def is_ambiguous(self, dt): + """ + Whether or not the "wall time" of a given datetime is ambiguous in this + zone. + + :param dt: + A :py:class:`datetime.datetime`, naive or time zone aware. + + + :return: + Returns ``True`` if ambiguous, ``False`` otherwise. + + .. versionadded:: 2.6.0 + """ + if not self.hasdst: + return False + + start, end = self.transitions(dt.year) + + dt = dt.replace(tzinfo=None) + return (end <= dt < end + self._dst_base_offset) + + def _isdst(self, dt): + if not self.hasdst: + return False + elif dt is None: + return None + + transitions = self.transitions(dt.year) + + if transitions is None: + return False + + dt = dt.replace(tzinfo=None) + + isdst = self._naive_isdst(dt, transitions) + + # Handle ambiguous dates + if not isdst and self.is_ambiguous(dt): + return not self._fold(dt) + else: + return isdst + + def _naive_isdst(self, dt, transitions): + dston, dstoff = transitions + + dt = dt.replace(tzinfo=None) + + if dston < dstoff: + isdst = dston <= dt < dstoff + else: + isdst = not dstoff <= dt < dston + + return isdst + + @property + def _dst_base_offset(self): + return self._dst_offset - self._std_offset + + __hash__ = None + + def __ne__(self, other): + return not (self == other) + + def __repr__(self): + return "%s(...)" % self.__class__.__name__ + + __reduce__ = object.__reduce__ diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/dill/__diff.py b/bioagent-bench/.venv/lib/python3.14/site-packages/dill/__diff.py new file mode 100644 index 0000000000000000000000000000000000000000..6fa8dd51bf87ed14939e2015d861986ad1181b2e --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/dill/__diff.py @@ -0,0 +1,234 @@ +#!/usr/bin/env python +# +# Author: Mike McKerns (mmckerns @caltech and @uqfoundation) +# Copyright (c) 2008-2016 California Institute of Technology. +# Copyright (c) 2016-2026 The Uncertainty Quantification Foundation. +# License: 3-clause BSD. The full license text is available at: +# - https://github.com/uqfoundation/dill/blob/master/LICENSE + +""" +Module to show if an object has changed since it was memorised +""" + +import builtins +import os +import sys +import types +try: + import numpy.ma + HAS_NUMPY = True +except ImportError: + HAS_NUMPY = False + +# pypy doesn't use reference counting +getrefcount = getattr(sys, 'getrefcount', lambda x:0) + +# memo of objects indexed by id to a tuple (attributes, sequence items) +# attributes is a dict indexed by attribute name to attribute id +# sequence items is either a list of ids, of a dictionary of keys to ids +memo = {} +id_to_obj = {} +# types that cannot have changing attributes +builtins_types = set((str, list, dict, set, frozenset, int)) +dont_memo = set(id(i) for i in (memo, sys.modules, sys.path_importer_cache, + os.environ, id_to_obj)) + + +def get_attrs(obj): + """ + Gets all the attributes of an object though its __dict__ or return None + """ + if type(obj) in builtins_types \ + or type(obj) is type and obj in builtins_types: + return + return getattr(obj, '__dict__', None) + + +def get_seq(obj, cache={str: False, frozenset: False, list: True, set: True, + dict: True, tuple: True, type: False, + types.ModuleType: False, types.FunctionType: False, + types.BuiltinFunctionType: False}): + """ + Gets all the items in a sequence or return None + """ + try: + o_type = obj.__class__ + except AttributeError: + o_type = type(obj) + hsattr = hasattr + if o_type in cache: + if cache[o_type]: + if hsattr(obj, "copy"): + return obj.copy() + return obj + elif HAS_NUMPY and o_type in (numpy.ndarray, numpy.ma.core.MaskedConstant): + if obj.shape and obj.size: + return obj + else: + return [] + elif hsattr(obj, "__contains__") and hsattr(obj, "__iter__") \ + and hsattr(obj, "__len__") and hsattr(o_type, "__contains__") \ + and hsattr(o_type, "__iter__") and hsattr(o_type, "__len__"): + cache[o_type] = True + if hsattr(obj, "copy"): + return obj.copy() + return obj + else: + cache[o_type] = False + return None + + +def memorise(obj, force=False): + """ + Adds an object to the memo, and recursively adds all the objects + attributes, and if it is a container, its items. Use force=True to update + an object already in the memo. Updating is not recursively done. + """ + obj_id = id(obj) + if obj_id in memo and not force or obj_id in dont_memo: + return + id_ = id + g = get_attrs(obj) + if g is None: + attrs_id = None + else: + attrs_id = dict((key,id_(value)) for key, value in g.items()) + + s = get_seq(obj) + if s is None: + seq_id = None + elif hasattr(s, "items"): + seq_id = dict((id_(key),id_(value)) for key, value in s.items()) + elif not hasattr(s, "__len__"): #XXX: avoid TypeError from unexpected case + seq_id = None + else: + seq_id = [id_(i) for i in s] + + memo[obj_id] = attrs_id, seq_id + id_to_obj[obj_id] = obj + mem = memorise + if g is not None: + [mem(value) for key, value in g.items()] + + if s is not None: + if hasattr(s, "items"): + [(mem(key), mem(item)) + for key, item in s.items()] + else: + if hasattr(s, '__len__'): + [mem(item) for item in s] + else: mem(s) + + +def release_gone(): + itop, mp, src = id_to_obj.pop, memo.pop, getrefcount + [(itop(id_), mp(id_)) for id_, obj in list(id_to_obj.items()) + if src(obj) < 4] #XXX: correct for pypy? + + +def whats_changed(obj, seen=None, simple=False, first=True): + """ + Check an object against the memo. Returns a list in the form + (attribute changes, container changed). Attribute changes is a dict of + attribute name to attribute value. container changed is a boolean. + If simple is true, just returns a boolean. None for either item means + that it has not been checked yet + """ + # Special cases + if first: + # ignore the _ variable, which only appears in interactive sessions + if "_" in builtins.__dict__: + del builtins._ + if seen is None: + seen = {} + + obj_id = id(obj) + + if obj_id in seen: + if simple: + return any(seen[obj_id]) + return seen[obj_id] + + # Safety checks + if obj_id in dont_memo: + seen[obj_id] = [{}, False] + if simple: + return False + return seen[obj_id] + elif obj_id not in memo: + if simple: + return True + else: + raise RuntimeError("Object not memorised " + str(obj)) + + seen[obj_id] = ({}, False) + + chngd = whats_changed + id_ = id + + # compare attributes + attrs = get_attrs(obj) + if attrs is None: + changed = {} + else: + obj_attrs = memo[obj_id][0] + obj_get = obj_attrs.get + changed = dict((key,None) for key in obj_attrs if key not in attrs) + for key, o in attrs.items(): + if id_(o) != obj_get(key, None) or chngd(o, seen, True, False): + changed[key] = o + + # compare sequence + items = get_seq(obj) + seq_diff = False + if (items is not None) and (hasattr(items, '__len__')): + obj_seq = memo[obj_id][1] + if (len(items) != len(obj_seq)): + seq_diff = True + elif hasattr(obj, "items"): # dict type obj + obj_get = obj_seq.get + for key, item in items.items(): + if id_(item) != obj_get(id_(key)) \ + or chngd(key, seen, True, False) \ + or chngd(item, seen, True, False): + seq_diff = True + break + else: + for i, j in zip(items, obj_seq): # list type obj + if id_(i) != j or chngd(i, seen, True, False): + seq_diff = True + break + seen[obj_id] = changed, seq_diff + if simple: + return changed or seq_diff + return changed, seq_diff + + +def has_changed(*args, **kwds): + kwds['simple'] = True # ignore simple if passed in + return whats_changed(*args, **kwds) + +__import__ = __import__ + + +def _imp(*args, **kwds): + """ + Replaces the default __import__, to allow a module to be memorised + before the user can change it + """ + before = set(sys.modules.keys()) + mod = __import__(*args, **kwds) + after = set(sys.modules.keys()).difference(before) + for m in after: + memorise(sys.modules[m]) + return mod + +builtins.__import__ = _imp +if hasattr(builtins, "_"): + del builtins._ + +# memorise all already imported modules. This implies that this must be +# imported first for any changes to be recorded +for mod in list(sys.modules.values()): + memorise(mod) +release_gone() diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/dill/__info__.py b/bioagent-bench/.venv/lib/python3.14/site-packages/dill/__info__.py new file mode 100644 index 0000000000000000000000000000000000000000..87b181b1f32736cf1dbb3d6e49a729e7dbb2ceb5 --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/dill/__info__.py @@ -0,0 +1,291 @@ +#!/usr/bin/env python +# +# Author: Mike McKerns (mmckerns @caltech and @uqfoundation) +# Copyright (c) 2026 The Uncertainty Quantification Foundation. +# License: 3-clause BSD. The full license text is available at: +# - https://github.com/uqfoundation/dill/blob/master/LICENSE +''' +----------------------------- +dill: serialize all of Python +----------------------------- + +About Dill +========== + +``dill`` extends Python's ``pickle`` module for serializing and de-serializing +Python objects to the majority of the built-in Python types. Serialization +is the process of converting an object to a byte stream, and the inverse +of which is converting a byte stream back to a Python object hierarchy. + +``dill`` provides the user the same interface as the ``pickle`` module, and +also includes some additional features. In addition to pickling Python +objects, ``dill`` provides the ability to save the state of an interpreter +session in a single command. Hence, it would be feasible to save an +interpreter session, close the interpreter, ship the pickled file to +another computer, open a new interpreter, unpickle the session and +thus continue from the 'saved' state of the original interpreter +session. + +``dill`` can be used to store Python objects to a file, but the primary +usage is to send Python objects across the network as a byte stream. +``dill`` is quite flexible, and allows arbitrary user defined classes +and functions to be serialized. Thus ``dill`` is not intended to be +secure against erroneously or maliciously constructed data. It is +left to the user to decide whether the data they unpickle is from +a trustworthy source. + +``dill`` is part of ``pathos``, a Python framework for heterogeneous computing. +``dill`` is in active development, so any user feedback, bug reports, comments, +or suggestions are highly appreciated. A list of issues is located at +https://github.com/uqfoundation/dill/issues, with a legacy list maintained at +https://uqfoundation.github.io/project/pathos/query. + + +Major Features +============== + +``dill`` can pickle the following standard types: + + - none, type, bool, int, float, complex, bytes, str, + - tuple, list, dict, file, buffer, builtin, + - Python classes, namedtuples, dataclasses, metaclasses, + - instances of classes, + - set, frozenset, array, functions, exceptions + +``dill`` can also pickle more 'exotic' standard types: + + - functions with yields, nested functions, lambdas, + - cell, method, unboundmethod, module, code, methodwrapper, + - methoddescriptor, getsetdescriptor, memberdescriptor, wrapperdescriptor, + - dictproxy, slice, notimplemented, ellipsis, quit + +``dill`` cannot yet pickle these standard types: + + - frame, generator, traceback + +``dill`` also provides the capability to: + + - save and load Python interpreter sessions + - save and extract the source code from functions and classes + - interactively diagnose pickling errors + + +Current Release +=============== + +The latest released version of ``dill`` is available from: + + https://pypi.org/project/dill + +``dill`` is distributed under a 3-clause BSD license. + + +Development Version +=================== + +You can get the latest development version with all the shiny new features at: + + https://github.com/uqfoundation + +If you have a new contribution, please submit a pull request. + + +Installation +============ + +``dill`` can be installed with ``pip``:: + + $ pip install dill + +To optionally include the ``objgraph`` diagnostic tool in the install:: + + $ pip install dill[graph] + +To optionally include the ``gprof2dot`` diagnostic tool in the install:: + + $ pip install dill[profile] + +For windows users, to optionally install session history tools:: + + $ pip install dill[readline] + + +Requirements +============ + +``dill`` requires: + + - ``python`` (or ``pypy``), **>=3.9** + - ``setuptools``, **>=42** + +Optional requirements: + + - ``objgraph``, **>=1.7.2** + - ``gprof2dot``, **>=2022.7.29** + - ``pyreadline``, **>=1.7.1** (on windows) + + +Basic Usage +=========== + +``dill`` is a drop-in replacement for ``pickle``. Existing code can be +updated to allow complete pickling using:: + + >>> import dill as pickle + +or:: + + >>> from dill import dumps, loads + +``dumps`` converts the object to a unique byte string, and ``loads`` performs +the inverse operation:: + + >>> squared = lambda x: x**2 + >>> loads(dumps(squared))(3) + 9 + +There are a number of options to control serialization which are provided +as keyword arguments to several ``dill`` functions: + +* with *protocol*, the pickle protocol level can be set. This uses the + same value as the ``pickle`` module, *DEFAULT_PROTOCOL*. +* with *byref=True*, ``dill`` to behave a lot more like pickle with + certain objects (like modules) pickled by reference as opposed to + attempting to pickle the object itself. +* with *recurse=True*, objects referred to in the global dictionary are + recursively traced and pickled, instead of the default behavior of + attempting to store the entire global dictionary. +* with *fmode*, the contents of the file can be pickled along with the file + handle, which is useful if the object is being sent over the wire to a + remote system which does not have the original file on disk. Options are + *HANDLE_FMODE* for just the handle, *CONTENTS_FMODE* for the file content + and *FILE_FMODE* for content and handle. +* with *ignore=False*, objects reconstructed with types defined in the + top-level script environment use the existing type in the environment + rather than a possibly different reconstructed type. + +The default serialization can also be set globally in *dill.settings*. +Thus, we can modify how ``dill`` handles references to the global dictionary +locally or globally:: + + >>> import dill.settings + >>> dumps(absolute) == dumps(absolute, recurse=True) + False + >>> dill.settings['recurse'] = True + >>> dumps(absolute) == dumps(absolute, recurse=True) + True + +``dill`` also includes source code inspection, as an alternate to pickling:: + + >>> import dill.source + >>> print(dill.source.getsource(squared)) + squared = lambda x:x**2 + +To aid in debugging pickling issues, use *dill.detect* which provides +tools like pickle tracing:: + + >>> import dill.detect + >>> with dill.detect.trace(): + >>> dumps(squared) + ┬ F1: at 0x7fe074f8c280> + ├┬ F2: + │└ # F2 [34 B] + ├┬ Co: at 0x7fe07501eb30, file "", line 1> + │├┬ F2: + ││└ # F2 [19 B] + │└ # Co [87 B] + ├┬ D1: + │└ # D1 [22 B] + ├┬ D2: + │└ # D2 [2 B] + ├┬ D2: + │├┬ D2: + ││└ # D2 [2 B] + │└ # D2 [23 B] + └ # F1 [180 B] + +With trace, we see how ``dill`` stored the lambda (``F1``) by first storing +``_create_function``, the underlying code object (``Co``) and ``_create_code`` +(which is used to handle code objects), then we handle the reference to +the global dict (``D2``) plus other dictionaries (``D1`` and ``D2``) that +save the lambda object's state. A ``#`` marks when the object is actually stored. + + +More Information +================ + +Probably the best way to get started is to look at the documentation at +http://dill.rtfd.io. Also see ``dill.tests`` for a set of scripts that +demonstrate how ``dill`` can serialize different Python objects. You can +run the test suite with ``python -m dill.tests``. The contents of any +pickle file can be examined with ``undill``. As ``dill`` conforms to +the ``pickle`` interface, the examples and documentation found at +http://docs.python.org/library/pickle.html also apply to ``dill`` +if one will ``import dill as pickle``. The source code is also generally +well documented, so further questions may be resolved by inspecting the +code itself. Please feel free to submit a ticket on github, or ask a +question on stackoverflow (**@Mike McKerns**). +If you would like to share how you use ``dill`` in your work, please send +an email (to **mmckerns at uqfoundation dot org**). + + +Citation +======== + +If you use ``dill`` to do research that leads to publication, we ask that you +acknowledge use of ``dill`` by citing the following in your publication:: + + M.M. McKerns, L. Strand, T. Sullivan, A. Fang, M.A.G. Aivazis, + "Building a framework for predictive science", Proceedings of + the 10th Python in Science Conference, 2011; + http://arxiv.org/pdf/1202.1056 + + Michael McKerns and Michael Aivazis, + "pathos: a framework for heterogeneous computing", 2010- ; + https://uqfoundation.github.io/project/pathos + +Please see https://uqfoundation.github.io/project/pathos or +http://arxiv.org/pdf/1202.1056 for further information. + +''' + +__version__ = '0.4.1' +__author__ = 'Mike McKerns' + +__license__ = ''' +Copyright (c) 2004-2016 California Institute of Technology. +Copyright (c) 2016-2026 The Uncertainty Quantification Foundation. +All rights reserved. + +This software is available subject to the conditions and terms laid +out below. By downloading and using this software you are agreeing +to the following conditions. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + - Neither the names of the copyright holders nor the names of any of + the contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +''' diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/dill/__init__.py b/bioagent-bench/.venv/lib/python3.14/site-packages/dill/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..8c45188e68a2725216a15ed4679722a9a56a9c0d --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/dill/__init__.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python +# +# Author: Mike McKerns (mmckerns @caltech and @uqfoundation) +# Copyright (c) 2008-2016 California Institute of Technology. +# Copyright (c) 2016-2026 The Uncertainty Quantification Foundation. +# License: 3-clause BSD. The full license text is available at: +# - https://github.com/uqfoundation/dill/blob/master/LICENSE + +# author, version, license, and long description +try: # the package is installed + from .__info__ import __version__, __author__, __doc__, __license__ +except: # pragma: no cover + import os + import sys + parent = os.path.dirname(os.path.abspath(os.path.dirname(__file__))) + sys.path.append(parent) + # get distribution meta info + from version import (__version__, __author__, + get_license_text, get_readme_as_rst) + __license__ = get_license_text(os.path.join(parent, 'LICENSE')) + __license__ = "\n%s" % __license__ + __doc__ = get_readme_as_rst(os.path.join(parent, 'README.md')) + del os, sys, parent, get_license_text, get_readme_as_rst + + +from ._dill import ( + dump, dumps, load, loads, copy, + Pickler, Unpickler, register, pickle, pickles, check, + DEFAULT_PROTOCOL, HIGHEST_PROTOCOL, HANDLE_FMODE, CONTENTS_FMODE, FILE_FMODE, + PickleError, PickleWarning, PicklingError, PicklingWarning, UnpicklingError, + UnpicklingWarning, +) +from .session import ( + dump_module, load_module, load_module_asdict, + dump_session, load_session # backward compatibility +) +from . import detect, logger, session, source, temp + +# get global settings +from .settings import settings + +# make sure "trace" is turned off +logger.trace(False) + +objects = {} +# local import of dill._objects +#from . import _objects +#objects.update(_objects.succeeds) +#del _objects + +# local import of dill.objtypes +from . import objtypes as types + +def load_types(pickleable=True, unpickleable=True): + """load pickleable and/or unpickleable types to ``dill.types`` + + ``dill.types`` is meant to mimic the ``types`` module, providing a + registry of object types. By default, the module is empty (for import + speed purposes). Use the ``load_types`` function to load selected object + types to the ``dill.types`` module. + + Args: + pickleable (bool, default=True): if True, load pickleable types. + unpickleable (bool, default=True): if True, load unpickleable types. + + Returns: + None + """ + from importlib import reload + # local import of dill.objects + from . import _objects + if pickleable: + objects.update(_objects.succeeds) + else: + [objects.pop(obj,None) for obj in _objects.succeeds] + if unpickleable: + objects.update(_objects.failures) + else: + [objects.pop(obj,None) for obj in _objects.failures] + objects.update(_objects.registered) + del _objects + # reset contents of types to 'empty' + [types.__dict__.pop(obj) for obj in list(types.__dict__.keys()) \ + if obj.find('Type') != -1] + # add corresponding types from objects to types + reload(types) + +def extend(use_dill=True): + '''add (or remove) dill types to/from the pickle registry + + by default, ``dill`` populates its types to ``pickle.Pickler.dispatch``. + Thus, all ``dill`` types are available upon calling ``'import pickle'``. + To drop all ``dill`` types from the ``pickle`` dispatch, *use_dill=False*. + + Args: + use_dill (bool, default=True): if True, extend the dispatch table. + + Returns: + None + ''' + from ._dill import _revert_extension, _extend + if use_dill: _extend() + else: _revert_extension() + return + +extend() + + +def license(): + """print license""" + print (__license__) + return + +def citation(): + """print citation""" + print (__doc__[-491:-118]) + return + +# end of file diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/dill/_dill.py b/bioagent-bench/.venv/lib/python3.14/site-packages/dill/_dill.py new file mode 100644 index 0000000000000000000000000000000000000000..27ab56c6f7ce46d4887d0e98bbfaf05aeee56a15 --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/dill/_dill.py @@ -0,0 +1,2265 @@ +# -*- coding: utf-8 -*- +# +# Author: Mike McKerns (mmckerns @caltech and @uqfoundation) +# Copyright (c) 2008-2015 California Institute of Technology. +# Copyright (c) 2016-2026 The Uncertainty Quantification Foundation. +# License: 3-clause BSD. The full license text is available at: +# - https://github.com/uqfoundation/dill/blob/master/LICENSE +""" +dill: a utility for serialization of python objects + +The primary functions in `dill` are :func:`dump` and +:func:`dumps` for serialization ("pickling") to a +file or to a string, respectively, and :func:`load` +and :func:`loads` for deserialization ("unpickling"), +similarly, from a file or from a string. Other notable +functions are :func:`~dill.dump_module` and +:func:`~dill.load_module`, which are used to save and +restore module objects, including an intepreter session. + +Based on code written by Oren Tirosh and Armin Ronacher. +Extended to a (near) full set of the builtin types (in types module), +and coded to the pickle interface, by . +Initial port to python3 by Jonathan Dobson, continued by mmckerns. +Tested against "all" python types (Std. Lib. CH 1-15 @ 2.7) by mmckerns. +Tested against CH16+ Std. Lib. ... TBD. +""" + +from __future__ import annotations + +__all__ = [ + 'dump','dumps','load','loads','copy', + 'Pickler','Unpickler','register','pickle','pickles','check', + 'DEFAULT_PROTOCOL','HIGHEST_PROTOCOL','HANDLE_FMODE','CONTENTS_FMODE','FILE_FMODE', + 'PickleError','PickleWarning','PicklingError','PicklingWarning','UnpicklingError', + 'UnpicklingWarning', +] + +__module__ = 'dill' + +import warnings +from .logger import adapter as logger +from .logger import trace as _trace +log = logger # backward compatibility (see issue #582) + +import os +import sys +diff = None +_use_diff = False +OLD38 = (sys.hexversion < 0x3080000) +OLD39 = (sys.hexversion < 0x3090000) +OLD310 = (sys.hexversion < 0x30a0000) +OLD312a7 = (sys.hexversion < 0x30c00a7) +#XXX: get types from .objtypes ? +import builtins as __builtin__ +from pickle import _Pickler as StockPickler, Unpickler as StockUnpickler +from pickle import GLOBAL, POP +from _contextvars import Context as ContextType +from _thread import LockType +from _thread import RLock as RLockType +try: + from _thread import _ExceptHookArgs as ExceptHookArgsType +except ImportError: + ExceptHookArgsType = None +try: + from _thread import _ThreadHandle as ThreadHandleType +except ImportError: + ThreadHandleType = None +#from io import IOBase +from types import CodeType, FunctionType, MethodType, GeneratorType, \ + TracebackType, FrameType, ModuleType, BuiltinMethodType +BufferType = memoryview #XXX: unregistered +ClassType = type # no 'old-style' classes +EllipsisType = type(Ellipsis) +#FileType = IOBase +NotImplementedType = type(NotImplemented) +SliceType = slice +TypeType = type # 'new-style' classes #XXX: unregistered +XRangeType = range +from types import MappingProxyType as DictProxyType, new_class +from pickle import DEFAULT_PROTOCOL, HIGHEST_PROTOCOL, PickleError, PicklingError, UnpicklingError +import __main__ as _main_module +import marshal +import gc +# import zlib +import abc +import dataclasses +from weakref import ReferenceType, ProxyType, CallableProxyType +from collections import OrderedDict +from enum import Enum, EnumMeta +from functools import partial +from operator import itemgetter, attrgetter +GENERATOR_FAIL = False +import importlib.machinery +EXTENSION_SUFFIXES = tuple(importlib.machinery.EXTENSION_SUFFIXES) +try: + import ctypes + HAS_CTYPES = True + # if using `pypy`, pythonapi is not found + IS_PYPY = not hasattr(ctypes, 'pythonapi') +except ImportError: + HAS_CTYPES = False + IS_PYPY = False +NumpyUfuncType = None +NumpyDType = None +NumpyArrayType = None +try: + if not importlib.machinery.PathFinder().find_spec('numpy'): + raise ImportError("No module named 'numpy'") + NumpyUfuncType = True + NumpyDType = True + NumpyArrayType = True +except ImportError: + pass +def __hook__(): + global NumpyArrayType, NumpyDType, NumpyUfuncType + from numpy import ufunc as NumpyUfuncType + from numpy import ndarray as NumpyArrayType + from numpy import dtype as NumpyDType + return True +if NumpyArrayType: # then has numpy + def ndarraysubclassinstance(obj_type): + if all((c.__module__, c.__name__) != ('numpy', 'ndarray') for c in obj_type.__mro__): + return False + # anything below here is a numpy array (or subclass) instance + __hook__() # import numpy (so the following works!!!) + # verify that __reduce__ has not been overridden + if obj_type.__reduce_ex__ is not NumpyArrayType.__reduce_ex__ \ + or obj_type.__reduce__ is not NumpyArrayType.__reduce__: + return False + return True + def numpyufunc(obj_type): + return any((c.__module__, c.__name__) == ('numpy', 'ufunc') for c in obj_type.__mro__) + def numpydtype(obj_type): + if all((c.__module__, c.__name__) != ('numpy', 'dtype') for c in obj_type.__mro__): + return False + # anything below here is a numpy dtype + __hook__() # import numpy (so the following works!!!) + return obj_type is type(NumpyDType) # handles subclasses +else: + def ndarraysubclassinstance(obj): return False + def numpyufunc(obj): return False + def numpydtype(obj): return False + +from types import GetSetDescriptorType, ClassMethodDescriptorType, \ + WrapperDescriptorType, MethodDescriptorType, MemberDescriptorType, \ + MethodWrapperType #XXX: unused + +# make sure to add these 'hand-built' types to _typemap +CellType = type((lambda x: lambda y: x)(0).__closure__[0]) +PartialType = type(partial(int, base=2)) +SuperType = type(super(Exception, TypeError())) +ItemGetterType = type(itemgetter(0)) +AttrGetterType = type(attrgetter('__repr__')) + +try: + from functools import _lru_cache_wrapper as LRUCacheType +except ImportError: + LRUCacheType = None + +if not isinstance(LRUCacheType, type): + LRUCacheType = None + +def get_file_type(*args, **kwargs): + open = kwargs.pop("open", __builtin__.open) + f = open(os.devnull, *args, **kwargs) + t = type(f) + f.close() + return t + +IS_PYODIDE = sys.platform == 'emscripten' + +FileType = get_file_type('rb', buffering=0) +TextWrapperType = get_file_type('r', buffering=-1) +BufferedRandomType = None if IS_PYODIDE else get_file_type('r+b', buffering=-1) +BufferedReaderType = get_file_type('rb', buffering=-1) +BufferedWriterType = get_file_type('wb', buffering=-1) +try: + from _pyio import open as _open + PyTextWrapperType = get_file_type('r', buffering=-1, open=_open) + PyBufferedRandomType = None if IS_PYODIDE else get_file_type('r+b', buffering=-1, open=_open) + PyBufferedReaderType = get_file_type('rb', buffering=-1, open=_open) + PyBufferedWriterType = get_file_type('wb', buffering=-1, open=_open) +except ImportError: + PyTextWrapperType = PyBufferedRandomType = PyBufferedReaderType = PyBufferedWriterType = None +from io import BytesIO as StringIO +InputType = OutputType = None +from socket import socket as SocketType +#FIXME: additionally calls ForkingPickler.register several times +from multiprocessing.reduction import _reduce_socket as reduce_socket +try: #pragma: no cover + IS_IPYTHON = __IPYTHON__ # is True + ExitType = None # IPython.core.autocall.ExitAutocall + IPYTHON_SINGLETONS = ('exit', 'quit', 'get_ipython') +except NameError: + IS_IPYTHON = False + try: ExitType = type(exit) # apparently 'exit' can be removed + except NameError: ExitType = None + IPYTHON_SINGLETONS = () + +import inspect +import typing + + +### Shims for different versions of Python and dill +class Sentinel(object): + """ + Create a unique sentinel object that is pickled as a constant. + """ + def __init__(self, name, module_name=None): + self.name = name + if module_name is None: + # Use the calling frame's module + self.__module__ = inspect.currentframe().f_back.f_globals['__name__'] + else: + self.__module__ = module_name # pragma: no cover + def __repr__(self): + return self.__module__ + '.' + self.name # pragma: no cover + def __copy__(self): + return self # pragma: no cover + def __deepcopy__(self, memo): + return self # pragma: no cover + def __reduce__(self): + return self.name + def __reduce_ex__(self, protocol): + return self.name + +from . import _shims +from ._shims import Reduce, Getattr + +### File modes +#: Pickles the file handle, preserving mode. The position of the unpickled +#: object is as for a new file handle. +HANDLE_FMODE = 0 +#: Pickles the file contents, creating a new file if on load the file does +#: not exist. The position = min(pickled position, EOF) and mode is chosen +#: as such that "best" preserves behavior of the original file. +CONTENTS_FMODE = 1 +#: Pickles the entire file (handle and contents), preserving mode and position. +FILE_FMODE = 2 + +### Shorthands (modified from python2.5/lib/pickle.py) +def copy(obj, *args, **kwds): + """ + Use pickling to 'copy' an object (i.e. `loads(dumps(obj))`). + + See :func:`dumps` and :func:`loads` for keyword arguments. + """ + ignore = kwds.pop('ignore', Unpickler.settings['ignore']) + return loads(dumps(obj, *args, **kwds), ignore=ignore) + +def dump(obj, file, protocol=None, byref=None, fmode=None, recurse=None, **kwds):#, strictio=None): + """ + Pickle an object to a file. + + See :func:`dumps` for keyword arguments. + """ + from .settings import settings + protocol = settings['protocol'] if protocol is None else int(protocol) + _kwds = kwds.copy() + _kwds.update(dict(byref=byref, fmode=fmode, recurse=recurse)) + Pickler(file, protocol, **_kwds).dump(obj) + return + +def dumps(obj, protocol=None, byref=None, fmode=None, recurse=None, **kwds):#, strictio=None): + """ + Pickle an object to a string. + + *protocol* is the pickler protocol, as defined for Python *pickle*. + + If *byref=True*, then dill behaves a lot more like pickle as certain + objects (like modules) are pickled by reference as opposed to attempting + to pickle the object itself. + + If *recurse=True*, then objects referred to in the global dictionary + are recursively traced and pickled, instead of the default behavior + of attempting to store the entire global dictionary. This is needed for + functions defined via *exec()*. + + *fmode* (:const:`HANDLE_FMODE`, :const:`CONTENTS_FMODE`, + or :const:`FILE_FMODE`) indicates how file handles will be pickled. + For example, when pickling a data file handle for transfer to a remote + compute service, *FILE_FMODE* will include the file contents in the + pickle and cursor position so that a remote method can operate + transparently on an object with an open file handle. + + Default values for keyword arguments can be set in :mod:`dill.settings`. + """ + file = StringIO() + dump(obj, file, protocol, byref, fmode, recurse, **kwds)#, strictio) + return file.getvalue() + +def load(file, ignore=None, **kwds): + """ + Unpickle an object from a file. + + See :func:`loads` for keyword arguments. + """ + return Unpickler(file, ignore=ignore, **kwds).load() + +def loads(str, ignore=None, **kwds): + """ + Unpickle an object from a string. + + If *ignore=False* then objects whose class is defined in the module + *__main__* are updated to reference the existing class in *__main__*, + otherwise they are left to refer to the reconstructed type, which may + be different. + + Default values for keyword arguments can be set in :mod:`dill.settings`. + """ + file = StringIO(str) + return load(file, ignore, **kwds) + +# def dumpzs(obj, protocol=None): +# """pickle an object to a compressed string""" +# return zlib.compress(dumps(obj, protocol)) + +# def loadzs(str): +# """unpickle an object from a compressed string""" +# return loads(zlib.decompress(str)) + +### End: Shorthands ### + +class MetaCatchingDict(dict): + def get(self, key, default=None): + try: + return self[key] + except KeyError: + return default + + def __missing__(self, key): + if issubclass(key, type): + return save_type + else: + raise KeyError() + +class PickleWarning(Warning, PickleError): + pass + +class PicklingWarning(PickleWarning, PicklingError): + pass + +class UnpicklingWarning(PickleWarning, UnpicklingError): + pass + +### Extend the Picklers +class Pickler(StockPickler): + """python's Pickler extended to interpreter sessions""" + dispatch: typing.Dict[type, typing.Callable[[Pickler, typing.Any], None]] \ + = MetaCatchingDict(StockPickler.dispatch.copy()) + """The dispatch table, a dictionary of serializing functions used + by Pickler to save objects of specific types. Use :func:`pickle` + or :func:`register` to associate types to custom functions. + + :meta hide-value: + """ + _session = False + from .settings import settings + + def __init__(self, file, *args, **kwds): + settings = Pickler.settings + _byref = kwds.pop('byref', None) + #_strictio = kwds.pop('strictio', None) + _fmode = kwds.pop('fmode', None) + _recurse = kwds.pop('recurse', None) + StockPickler.__init__(self, file, *args, **kwds) + self._main = _main_module + self._diff_cache = {} + self._byref = settings['byref'] if _byref is None else _byref + self._strictio = False #_strictio + self._fmode = settings['fmode'] if _fmode is None else _fmode + self._recurse = settings['recurse'] if _recurse is None else _recurse + self._postproc = OrderedDict() + self._file = file + + def save(self, obj, save_persistent_id=True): + # numpy hack + obj_type = type(obj) + if NumpyArrayType and not (obj_type is type or obj_type in Pickler.dispatch): + # register if the object is a numpy ufunc + # thanks to Paul Kienzle for pointing out ufuncs didn't pickle + if numpyufunc(obj_type): + @register(obj_type) + def save_numpy_ufunc(pickler, obj): + logger.trace(pickler, "Nu: %s", obj) + name = getattr(obj, '__qualname__', getattr(obj, '__name__', None)) + StockPickler.save_global(pickler, obj, name=name) + logger.trace(pickler, "# Nu") + return + # NOTE: the above 'save' performs like: + # import copy_reg + # def udump(f): return f.__name__ + # def uload(name): return getattr(numpy, name) + # copy_reg.pickle(NumpyUfuncType, udump, uload) + # register if the object is a numpy dtype + if numpydtype(obj_type): + @register(obj_type) + def save_numpy_dtype(pickler, obj): + logger.trace(pickler, "Dt: %s", obj) + pickler.save_reduce(_create_dtypemeta, (obj.type,), obj=obj) + logger.trace(pickler, "# Dt") + return + # NOTE: the above 'save' performs like: + # import copy_reg + # def uload(name): return type(NumpyDType(name)) + # def udump(f): return uload, (f.type,) + # copy_reg.pickle(NumpyDTypeType, udump, uload) + # register if the object is a subclassed numpy array instance + if ndarraysubclassinstance(obj_type): + @register(obj_type) + def save_numpy_array(pickler, obj): + logger.trace(pickler, "Nu: (%s, %s)", obj.shape, obj.dtype) + npdict = getattr(obj, '__dict__', None) + f, args, state = obj.__reduce__() + pickler.save_reduce(_create_array, (f,args,state,npdict), obj=obj) + logger.trace(pickler, "# Nu") + return + # end numpy hack + + if GENERATOR_FAIL and obj_type is GeneratorType: + msg = "Can't pickle %s: attribute lookup builtins.generator failed" % GeneratorType + raise PicklingError(msg) + StockPickler.save(self, obj, save_persistent_id) + + save.__doc__ = StockPickler.save.__doc__ + + def dump(self, obj): #NOTE: if settings change, need to update attributes + logger.trace_setup(self) + StockPickler.dump(self, obj) + dump.__doc__ = StockPickler.dump.__doc__ + +class Unpickler(StockUnpickler): + """python's Unpickler extended to interpreter sessions and more types""" + from .settings import settings + _session = False + + def find_class(self, module, name): + if (module, name) == ('__builtin__', '__main__'): + return self._main.__dict__ #XXX: above set w/save_module_dict + elif (module, name) == ('__builtin__', 'NoneType'): + return type(None) #XXX: special case: NoneType missing + if module == 'dill.dill': module = 'dill._dill' + return StockUnpickler.find_class(self, module, name) + + def __init__(self, *args, **kwds): + settings = Pickler.settings + _ignore = kwds.pop('ignore', None) + StockUnpickler.__init__(self, *args, **kwds) + self._main = _main_module + self._ignore = settings['ignore'] if _ignore is None else _ignore + + def load(self): #NOTE: if settings change, need to update attributes + obj = StockUnpickler.load(self) + if type(obj).__module__ == getattr(_main_module, '__name__', '__main__'): + if not self._ignore: + # point obj class to main + try: obj.__class__ = getattr(self._main, type(obj).__name__) + except (AttributeError,TypeError): pass # defined in a file + #_main_module.__dict__.update(obj.__dict__) #XXX: should update globals ? + return obj + load.__doc__ = StockUnpickler.load.__doc__ + pass + +''' +def dispatch_table(): + """get the dispatch table of registered types""" + return Pickler.dispatch +''' + +pickle_dispatch_copy = StockPickler.dispatch.copy() + +def pickle(t, func): + """expose :attr:`~Pickler.dispatch` table for user-created extensions""" + Pickler.dispatch[t] = func + return + +def register(t): + """decorator to register types to Pickler's :attr:`~Pickler.dispatch` table""" + def proxy(func): + Pickler.dispatch[t] = func + return func + return proxy + +def _revert_extension(): + """drop dill-registered types from pickle's dispatch table""" + for type, func in list(StockPickler.dispatch.items()): + if func.__module__ == __name__: + del StockPickler.dispatch[type] + if type in pickle_dispatch_copy: + StockPickler.dispatch[type] = pickle_dispatch_copy[type] + +def use_diff(on=True): + """ + Reduces size of pickles by only including object which have changed. + + Decreases pickle size but increases CPU time needed. + Also helps avoid some unpickleable objects. + MUST be called at start of script, otherwise changes will not be recorded. + """ + global _use_diff, diff + _use_diff = on + if _use_diff and diff is None: + try: + from . import diff as d + except ImportError: + import diff as d + diff = d + +def _create_typemap(): + import types + d = dict(list(__builtin__.__dict__.items()) + \ + list(types.__dict__.items())).items() + for key, value in d: + if getattr(value, '__module__', None) == 'builtins' \ + and type(value) is type: + yield key, value + return +_reverse_typemap = dict(_create_typemap()) +_reverse_typemap.update({ + 'PartialType': PartialType, + 'SuperType': SuperType, + 'ItemGetterType': ItemGetterType, + 'AttrGetterType': AttrGetterType, +}) +if sys.hexversion < 0x30800a2: + _reverse_typemap.update({ + 'CellType': CellType, + }) + +# "Incidental" implementation specific types. Unpickling these types in another +# implementation of Python (PyPy -> CPython) is not guaranteed to work + +# This dictionary should contain all types that appear in Python implementations +# but are not defined in https://docs.python.org/3/library/types.html#standard-interpreter-types +x=OrderedDict() +_incedental_reverse_typemap = { + 'FileType': FileType, + 'BufferedRandomType': BufferedRandomType, + 'BufferedReaderType': BufferedReaderType, + 'BufferedWriterType': BufferedWriterType, + 'TextWrapperType': TextWrapperType, + 'PyBufferedRandomType': PyBufferedRandomType, + 'PyBufferedReaderType': PyBufferedReaderType, + 'PyBufferedWriterType': PyBufferedWriterType, + 'PyTextWrapperType': PyTextWrapperType, +} + +_incedental_reverse_typemap.update({ + "DictKeysType": type({}.keys()), + "DictValuesType": type({}.values()), + "DictItemsType": type({}.items()), + + "OdictKeysType": type(x.keys()), + "OdictValuesType": type(x.values()), + "OdictItemsType": type(x.items()), +}) + +if ExitType: + _incedental_reverse_typemap['ExitType'] = ExitType +if InputType: + _incedental_reverse_typemap['InputType'] = InputType + _incedental_reverse_typemap['OutputType'] = OutputType + +''' +try: + import symtable + _incedental_reverse_typemap["SymtableEntryType"] = type(symtable.symtable("", "string", "exec")._table) +except: #FIXME: fails to pickle + pass + +if sys.hexversion >= 0x30a00a0: + _incedental_reverse_typemap['LineIteratorType'] = type(compile('3', '', 'eval').co_lines()) +''' + +if sys.hexversion >= 0x30b00b0 and not IS_PYPY: + from types import GenericAlias + _incedental_reverse_typemap["GenericAliasIteratorType"] = type(iter(GenericAlias(list, (int,)))) + ''' + _incedental_reverse_typemap['PositionsIteratorType'] = type(compile('3', '', 'eval').co_positions()) + ''' + +try: + import winreg + _incedental_reverse_typemap["HKEYType"] = winreg.HKEYType +except ImportError: + pass + +_reverse_typemap.update(_incedental_reverse_typemap) +_incedental_types = set(_incedental_reverse_typemap.values()) + +del x + +_typemap = dict((v, k) for k, v in _reverse_typemap.items()) + +def _unmarshal(string): + return marshal.loads(string) + +def _load_type(name): + return _reverse_typemap[name] + +def _create_type(typeobj, *args): + return typeobj(*args) + +def _create_function(fcode, fglobals, fname=None, fdefaults=None, + fclosure=None, fdict=None, fkwdefaults=None): + # same as FunctionType, but enable passing __dict__ to new function, + # __dict__ is the storehouse for attributes added after function creation + func = FunctionType(fcode, fglobals or dict(), fname, fdefaults, fclosure) + if fdict is not None: + func.__dict__.update(fdict) #XXX: better copy? option to copy? + if fkwdefaults is not None: + func.__kwdefaults__ = fkwdefaults + # 'recurse' only stores referenced modules/objects in fglobals, + # thus we need to make sure that we have __builtins__ as well + if "__builtins__" not in func.__globals__: + func.__globals__["__builtins__"] = globals()["__builtins__"] + # assert id(fglobals) == id(func.__globals__) + return func + +class match: + """ + Make avaialable a limited structural pattern matching-like syntax for Python < 3.10 + + Patterns can be only tuples (without types) currently. + Inspired by the package pattern-matching-PEP634. + + Usage: + >>> with match(args) as m: + >>> if m.case(('x', 'y')): + >>> # use m.x and m.y + >>> elif m.case(('x', 'y', 'z')): + >>> # use m.x, m.y and m.z + + Equivalent native code for Python >= 3.10: + >>> match args: + >>> case (x, y): + >>> # use x and y + >>> case (x, y, z): + >>> # use x, y and z + """ + def __init__(self, value): + self.value = value + self._fields = None + def __enter__(self): + return self + def __exit__(self, *exc_info): + return False + def case(self, args): # *args, **kwargs): + """just handles tuple patterns""" + if len(self.value) != len(args): # + len(kwargs): + return False + #if not all(isinstance(arg, pat) for arg, pat in zip(self.value[len(args):], kwargs.values())): + # return False + self.args = args # (*args, *kwargs) + return True + @property + def fields(self): + # Only bind names to values if necessary. + if self._fields is None: + self._fields = dict(zip(self.args, self.value)) + return self._fields + def __getattr__(self, item): + return self.fields[item] + +ALL_CODE_PARAMS = [ + # Version New attribute CodeType parameters + ((3,11,'a'), 'co_endlinetable', 'argcount posonlyargcount kwonlyargcount nlocals stacksize flags code consts names varnames filename name qualname firstlineno linetable endlinetable columntable exceptiontable freevars cellvars'), + ((3,11), 'co_exceptiontable', 'argcount posonlyargcount kwonlyargcount nlocals stacksize flags code consts names varnames filename name qualname firstlineno linetable exceptiontable freevars cellvars'), + ((3,11,'p'), 'co_qualname', 'argcount posonlyargcount kwonlyargcount nlocals stacksize flags code consts names varnames filename name qualname firstlineno linetable freevars cellvars'), + ((3,10), 'co_linetable', 'argcount posonlyargcount kwonlyargcount nlocals stacksize flags code consts names varnames filename name firstlineno linetable freevars cellvars'), + ((3,8), 'co_posonlyargcount', 'argcount posonlyargcount kwonlyargcount nlocals stacksize flags code consts names varnames filename name firstlineno lnotab freevars cellvars'), + ((3,7), 'co_kwonlyargcount', 'argcount kwonlyargcount nlocals stacksize flags code consts names varnames filename name firstlineno lnotab freevars cellvars'), + ] +for version, new_attr, params in ALL_CODE_PARAMS: + if hasattr(CodeType, new_attr): + CODE_VERSION = version + CODE_PARAMS = params.split() + break +ENCODE_PARAMS = set(CODE_PARAMS).intersection( + ['code', 'lnotab', 'linetable', 'endlinetable', 'columntable', 'exceptiontable']) + +def _create_code(*args): + if not isinstance(args[0], int): # co_lnotab stored from >= 3.10 + LNOTAB, *args = args + else: # from < 3.10 (or pre-LNOTAB storage) + LNOTAB = b'' + + with match(args) as m: + # Python 3.11/3.12a (18 members) + if m.case(( + 'argcount', 'posonlyargcount', 'kwonlyargcount', 'nlocals', 'stacksize', 'flags', # args[0:6] + 'code', 'consts', 'names', 'varnames', 'filename', 'name', 'qualname', 'firstlineno', # args[6:14] + 'linetable', 'exceptiontable', 'freevars', 'cellvars' # args[14:] + )): + if CODE_VERSION == (3,11): + return CodeType( + *args[:6], + args[6].encode() if hasattr(args[6], 'encode') else args[6], # code + *args[7:14], + args[14].encode() if hasattr(args[14], 'encode') else args[14], # linetable + args[15].encode() if hasattr(args[15], 'encode') else args[15], # exceptiontable + args[16], + args[17], + ) + fields = m.fields + # PyPy 3.11 7.3.19+ (17 members) + elif m.case(( + 'argcount', 'posonlyargcount', 'kwonlyargcount', 'nlocals', 'stacksize', 'flags', # args[0:6] + 'code', 'consts', 'names', 'varnames', 'filename', 'name', 'qualname', # args[6:13] + 'firstlineno', 'linetable', 'freevars', 'cellvars' # args[13:] + )): + if CODE_VERSION == (3,11,'p'): + return CodeType( + *args[:6], + args[6].encode() if hasattr(args[6], 'encode') else args[6], # code + *args[7:14], + args[14].encode() if hasattr(args[14], 'encode') else args[14], # linetable + args[15], + args[16], + ) + fields = m.fields + # Python 3.10 or 3.8/3.9 (16 members) + elif m.case(( + 'argcount', 'posonlyargcount', 'kwonlyargcount', 'nlocals', 'stacksize', 'flags', # args[0:6] + 'code', 'consts', 'names', 'varnames', 'filename', 'name', 'firstlineno', # args[6:13] + 'LNOTAB_OR_LINETABLE', 'freevars', 'cellvars' # args[13:] + )): + if CODE_VERSION == (3,10) or CODE_VERSION == (3,8): + return CodeType( + *args[:6], + args[6].encode() if hasattr(args[6], 'encode') else args[6], # code + *args[7:13], + args[13].encode() if hasattr(args[13], 'encode') else args[13], # lnotab/linetable + args[14], + args[15], + ) + fields = m.fields + if CODE_VERSION >= (3,10): + fields['linetable'] = m.LNOTAB_OR_LINETABLE + else: + fields['lnotab'] = LNOTAB if LNOTAB else m.LNOTAB_OR_LINETABLE + # Python 3.7 (15 args) + elif m.case(( + 'argcount', 'kwonlyargcount', 'nlocals', 'stacksize', 'flags', # args[0:5] + 'code', 'consts', 'names', 'varnames', 'filename', 'name', 'firstlineno', # args[5:12] + 'lnotab', 'freevars', 'cellvars' # args[12:] + )): + if CODE_VERSION == (3,7): + return CodeType( + *args[:5], + args[5].encode() if hasattr(args[5], 'encode') else args[5], # code + *args[6:12], + args[12].encode() if hasattr(args[12], 'encode') else args[12], # lnotab + args[13], + args[14], + ) + fields = m.fields + # Python 3.11a (20 members) + elif m.case(( + 'argcount', 'posonlyargcount', 'kwonlyargcount', 'nlocals', 'stacksize', 'flags', # args[0:6] + 'code', 'consts', 'names', 'varnames', 'filename', 'name', 'qualname', 'firstlineno', # args[6:14] + 'linetable', 'endlinetable', 'columntable', 'exceptiontable', 'freevars', 'cellvars' # args[14:] + )): + if CODE_VERSION == (3,11,'a'): + return CodeType( + *args[:6], + args[6].encode() if hasattr(args[6], 'encode') else args[6], # code + *args[7:14], + *(a.encode() if hasattr(a, 'encode') else a for a in args[14:18]), # linetable-exceptiontable + args[18], + args[19], + ) + fields = m.fields + else: + raise UnpicklingError("pattern match for code object failed") + + # The args format doesn't match this version. + fields.setdefault('posonlyargcount', 0) # from python <= 3.7 + fields.setdefault('lnotab', LNOTAB) # from python >= 3.10 + fields.setdefault('linetable', b'') # from python <= 3.9 + fields.setdefault('qualname', fields['name']) # from python <= 3.10 + fields.setdefault('exceptiontable', b'') # from python <= 3.10 + fields.setdefault('endlinetable', None) # from python != 3.11a + fields.setdefault('columntable', None) # from python != 3.11a + + args = (fields[k].encode() if k in ENCODE_PARAMS and hasattr(fields[k], 'encode') else fields[k] + for k in CODE_PARAMS) + return CodeType(*args) + +def _create_ftype(ftypeobj, func, args, kwds): + if kwds is None: + kwds = {} + if args is None: + args = () + return ftypeobj(func, *args, **kwds) + +def _create_typing_tuple(argz, *args): #NOTE: workaround python/cpython#94245 + if not argz: + return typing.Tuple[()].copy_with(()) + if argz == ((),): + return typing.Tuple[()] + return typing.Tuple[argz] + +if ThreadHandleType: + def _create_thread_handle(ident, done, *args): #XXX: ignores 'blocking' + from threading import _make_thread_handle + handle = _make_thread_handle(ident) + if done: + handle._set_done() + return handle + +def _create_lock(locked, *args): #XXX: ignores 'blocking' + from threading import Lock + lock = Lock() + if locked: + if not lock.acquire(False): + raise UnpicklingError("Cannot acquire lock") + return lock + +def _create_rlock(count, owner, *args): #XXX: ignores 'blocking' + lock = RLockType() + if owner is not None: + lock._acquire_restore((count, owner)) + if owner and not lock._is_owned(): + raise UnpicklingError("Cannot acquire lock") + return lock + +# thanks to matsjoyce for adding all the different file modes +def _create_filehandle(name, mode, position, closed, open, strictio, fmode, fdata): # buffering=0 + # only pickles the handle, not the file contents... good? or StringIO(data)? + # (for file contents see: http://effbot.org/librarybook/copy-reg.htm) + # NOTE: handle special cases first (are there more special cases?) + names = {'':sys.__stdin__, '':sys.__stdout__, + '':sys.__stderr__} #XXX: better fileno=(0,1,2) ? + if name in list(names.keys()): + f = names[name] #XXX: safer "f=sys.stdin" + elif name == '': + f = os.tmpfile() + elif name == '': + import tempfile + f = tempfile.TemporaryFile(mode) + else: + try: + exists = os.path.exists(name) + except Exception: + exists = False + if not exists: + if strictio: + raise FileNotFoundError("[Errno 2] No such file or directory: '%s'" % name) + elif "r" in mode and fmode != FILE_FMODE: + name = '' # or os.devnull? + current_size = 0 # or maintain position? + else: + current_size = os.path.getsize(name) + + if position > current_size: + if strictio: + raise ValueError("invalid buffer size") + elif fmode == CONTENTS_FMODE: + position = current_size + # try to open the file by name + # NOTE: has different fileno + try: + #FIXME: missing: *buffering*, encoding, softspace + if fmode == FILE_FMODE: + f = open(name, mode if "w" in mode else "w") + f.write(fdata) + if "w" not in mode: + f.close() + f = open(name, mode) + elif name == '': # file did not exist + import tempfile + f = tempfile.TemporaryFile(mode) + # treat x mode as w mode + elif fmode == CONTENTS_FMODE \ + and ("w" in mode or "x" in mode): + # stop truncation when opening + flags = os.O_CREAT + if "+" in mode: + flags |= os.O_RDWR + else: + flags |= os.O_WRONLY + f = os.fdopen(os.open(name, flags), mode) + # set name to the correct value + r = getattr(f, "buffer", f) + r = getattr(r, "raw", r) + r.name = name + assert f.name == name + else: + f = open(name, mode) + except (IOError, FileNotFoundError): + err = sys.exc_info()[1] + raise UnpicklingError(err) + if closed: + f.close() + elif position >= 0 and fmode != HANDLE_FMODE: + f.seek(position) + return f + +def _create_stringi(value, position, closed): + f = StringIO(value) + if closed: f.close() + else: f.seek(position) + return f + +def _create_stringo(value, position, closed): + f = StringIO() + if closed: f.close() + else: + f.write(value) + f.seek(position) + return f + +class _itemgetter_helper(object): + def __init__(self): + self.items = [] + def __getitem__(self, item): + self.items.append(item) + return + +class _attrgetter_helper(object): + def __init__(self, attrs, index=None): + self.attrs = attrs + self.index = index + def __getattribute__(self, attr): + attrs = object.__getattribute__(self, "attrs") + index = object.__getattribute__(self, "index") + if index is None: + index = len(attrs) + attrs.append(attr) + else: + attrs[index] = ".".join([attrs[index], attr]) + return type(self)(attrs, index) + +class _dictproxy_helper(dict): + def __ror__(self, a): + return a + +_dictproxy_helper_instance = _dictproxy_helper() + +__d = {} +try: + # In CPython 3.9 and later, this trick can be used to exploit the + # implementation of the __or__ function of MappingProxyType to get the true + # mapping referenced by the proxy. It may work for other implementations, + # but is not guaranteed. + MAPPING_PROXY_TRICK = __d is (DictProxyType(__d) | _dictproxy_helper_instance) +except Exception: + MAPPING_PROXY_TRICK = False +del __d + +# _CELL_REF and _CELL_EMPTY are used to stay compatible with versions of dill +# whose _create_cell functions do not have a default value. +# _CELL_REF can be safely removed entirely (replaced by empty tuples for calls +# to _create_cell) once breaking changes are allowed. +_CELL_REF = None +_CELL_EMPTY = Sentinel('_CELL_EMPTY') + +def _create_cell(contents=None): + if contents is not _CELL_EMPTY: + value = contents + return (lambda: value).__closure__[0] + +def _create_weakref(obj, *args): + from weakref import ref + if obj is None: # it's dead + from collections import UserDict + return ref(UserDict(), *args) + return ref(obj, *args) + +def _create_weakproxy(obj, callable=False, *args): + from weakref import proxy + if obj is None: # it's dead + if callable: return proxy(lambda x:x, *args) + from collections import UserDict + return proxy(UserDict(), *args) + return proxy(obj, *args) + +def _eval_repr(repr_str): + return eval(repr_str) + +def _create_array(f, args, state, npdict=None): + #array = numpy.core.multiarray._reconstruct(*args) + array = f(*args) + array.__setstate__(state) + if npdict is not None: # we also have saved state in __dict__ + array.__dict__.update(npdict) + return array + +def _create_dtypemeta(scalar_type): + if NumpyDType is True: __hook__() # a bit hacky I think + if scalar_type is None: + return NumpyDType + return type(NumpyDType(scalar_type)) + +def _create_namedtuple(name, fieldnames, modulename, defaults=None): + class_ = _import_module(modulename + '.' + name, safe=True) + if class_ is not None: + return class_ + import collections + t = collections.namedtuple(name, fieldnames, defaults=defaults, module=modulename) + return t + +def _create_capsule(pointer, name, context, destructor): + attr_found = False + try: + # based on https://github.com/python/cpython/blob/f4095e53ab708d95e019c909d5928502775ba68f/Objects/capsule.c#L209-L231 + uname = name.decode('utf8') + for i in range(1, uname.count('.')+1): + names = uname.rsplit('.', i) + try: + module = __import__(names[0]) + except ImportError: + pass + obj = module + for attr in names[1:]: + obj = getattr(obj, attr) + capsule = obj + attr_found = True + break + except Exception: + pass + + if attr_found: + if _PyCapsule_IsValid(capsule, name): + return capsule + raise UnpicklingError("%s object exists at %s but a PyCapsule object was expected." % (type(capsule), name)) + else: + #warnings.warn('Creating a new PyCapsule %s for a C data structure that may not be present in memory. Segmentation faults or other memory errors are possible.' % (name,), UnpicklingWarning) + capsule = _PyCapsule_New(pointer, name, destructor) + _PyCapsule_SetContext(capsule, context) + return capsule + +def _getattr(objclass, name, repr_str): + # hack to grab the reference directly + try: #XXX: works only for __builtin__ ? + attr = repr_str.split("'")[3] + return eval(attr+'.__dict__["'+name+'"]') + except Exception: + try: + attr = objclass.__dict__ + if type(attr) is DictProxyType: + if sys.hexversion > 0x30f00a0 and name in ('__weakref__','__dict__'): + attr = _dictproxy_helper.__dict__[name] + else: + attr = attr[name] + else: + attr = getattr(objclass,name) + except (AttributeError, KeyError): + attr = getattr(objclass,name) + return attr + +def _get_attr(self, name): + # stop recursive pickling + return getattr(self, name, None) or getattr(__builtin__, name) + +def _import_module(import_name, safe=False): + try: + if import_name.startswith('__runtime__.'): + return sys.modules[import_name] + elif '.' in import_name: + items = import_name.split('.') + module = '.'.join(items[:-1]) + obj = items[-1] + submodule = getattr(__import__(module, None, None, [obj]), obj) + if isinstance(submodule, (ModuleType, type)): + return submodule + return __import__(import_name, None, None, [obj]) + else: + return __import__(import_name) + except (ImportError, AttributeError, KeyError): + if safe: + return None + raise + +# https://github.com/python/cpython/blob/a8912a0f8d9eba6d502c37d522221f9933e976db/Lib/pickle.py#L322-L333 +def _getattribute(obj, name): + for subpath in name.split('.'): + if subpath == '': + raise AttributeError("Can't get local attribute {!r} on {!r}" + .format(name, obj)) + try: + parent = obj + obj = getattr(obj, subpath) + except AttributeError: + raise AttributeError("Can't get attribute {!r} on {!r}" + .format(name, obj)) + return obj, parent + +def _locate_function(obj, pickler=None): + module_name = getattr(obj, '__module__', None) + if module_name in ['__main__', None] or \ + pickler and is_dill(pickler, child=False) and pickler._session and module_name == pickler._main.__name__: + return False + if hasattr(obj, '__qualname__'): + module = _import_module(module_name, safe=True) + try: + found, _ = _getattribute(module, obj.__qualname__) + return found is obj + except AttributeError: + return False + else: + found = _import_module(module_name + '.' + obj.__name__, safe=True) + return found is obj + + +def _setitems(dest, source): + for k, v in source.items(): + dest[k] = v + + +def _save_with_postproc(pickler, reduction, is_pickler_dill=None, obj=Getattr.NO_DEFAULT, postproc_list=None): + if obj is Getattr.NO_DEFAULT: + obj = Reduce(reduction) # pragma: no cover + + if is_pickler_dill is None: + is_pickler_dill = is_dill(pickler, child=True) + if is_pickler_dill: + # assert id(obj) not in pickler._postproc, str(obj) + ' already pushed on stack!' + # if not hasattr(pickler, 'x'): pickler.x = 0 + # print(pickler.x*' ', 'push', obj, id(obj), pickler._recurse) + # pickler.x += 1 + if postproc_list is None: + postproc_list = [] + + # Recursive object not supported. Default to a global instead. + if id(obj) in pickler._postproc: + name = '%s.%s ' % (obj.__module__, getattr(obj, '__qualname__', obj.__name__)) if hasattr(obj, '__module__') else '' + warnings.warn('Cannot pickle %r: %shas recursive self-references that trigger a RecursionError.' % (obj, name), PicklingWarning) + pickler.save_global(obj) + return + pickler._postproc[id(obj)] = postproc_list + + # TODO: Use state_setter in Python 3.8 to allow for faster cPickle implementations + pickler.save_reduce(*reduction, obj=obj) + + if is_pickler_dill: + # pickler.x -= 1 + # print(pickler.x*' ', 'pop', obj, id(obj)) + postproc = pickler._postproc.pop(id(obj)) + # assert postproc_list == postproc, 'Stack tampered!' + for reduction in reversed(postproc): + if reduction[0] is _setitems: + # use the internal machinery of pickle.py to speedup when + # updating a dictionary in postproc + dest, source = reduction[1] + if source: + pickler.write(pickler.get(pickler.memo[id(dest)][0])) + if sys.hexversion < 0x30e00a1: + pickler._batch_setitems(iter(source.items())) + else: + pickler._batch_setitems(iter(source.items()), obj=obj) + else: + # Updating with an empty dictionary. Same as doing nothing. + continue + else: + pickler.save_reduce(*reduction) + # pop None created by calling preprocessing step off stack + pickler.write(POP) + +#@register(CodeType) +#def save_code(pickler, obj): +# logger.trace(pickler, "Co: %s", obj) +# pickler.save_reduce(_unmarshal, (marshal.dumps(obj),), obj=obj) +# logger.trace(pickler, "# Co") +# return + +# The following function is based on 'save_codeobject' from 'cloudpickle' +# Copyright (c) 2012, Regents of the University of California. +# Copyright (c) 2009 `PiCloud, Inc. `_. +# License: https://github.com/cloudpipe/cloudpickle/blob/master/LICENSE +@register(CodeType) +def save_code(pickler, obj): + logger.trace(pickler, "Co: %s", obj) + if hasattr(obj, "co_endlinetable"): # python 3.11a (20 args) + args = ( + obj.co_lnotab, # for < python 3.10 [not counted in args] + obj.co_argcount, obj.co_posonlyargcount, + obj.co_kwonlyargcount, obj.co_nlocals, obj.co_stacksize, + obj.co_flags, obj.co_code, obj.co_consts, obj.co_names, + obj.co_varnames, obj.co_filename, obj.co_name, obj.co_qualname, + obj.co_firstlineno, obj.co_linetable, obj.co_endlinetable, + obj.co_columntable, obj.co_exceptiontable, obj.co_freevars, + obj.co_cellvars + ) + elif hasattr(obj, "co_exceptiontable"): # python 3.11 (18 args) + with warnings.catch_warnings(): + if not OLD312a7: # issue 597 + warnings.filterwarnings('ignore', category=DeprecationWarning) + args = ( + obj.co_lnotab, # for < python 3.10 [not counted in args] + obj.co_argcount, obj.co_posonlyargcount, + obj.co_kwonlyargcount, obj.co_nlocals, obj.co_stacksize, + obj.co_flags, obj.co_code, obj.co_consts, obj.co_names, + obj.co_varnames, obj.co_filename, obj.co_name, obj.co_qualname, + obj.co_firstlineno, obj.co_linetable, obj.co_exceptiontable, + obj.co_freevars, obj.co_cellvars + ) + elif hasattr(obj, "co_qualname"): # pypy 3.11 7.3.19+ (17 args) + args = ( + obj.co_lnotab, obj.co_argcount, obj.co_posonlyargcount, + obj.co_kwonlyargcount, obj.co_nlocals, obj.co_stacksize, + obj.co_flags, obj.co_code, obj.co_consts, obj.co_names, + obj.co_varnames, obj.co_filename, obj.co_name, obj.co_qualname, + obj.co_firstlineno, obj.co_linetable, obj.co_freevars, + obj.co_cellvars + ) + elif hasattr(obj, "co_linetable"): # python 3.10 (16 args) + args = ( + obj.co_lnotab, # for < python 3.10 [not counted in args] + obj.co_argcount, obj.co_posonlyargcount, + obj.co_kwonlyargcount, obj.co_nlocals, obj.co_stacksize, + obj.co_flags, obj.co_code, obj.co_consts, obj.co_names, + obj.co_varnames, obj.co_filename, obj.co_name, + obj.co_firstlineno, obj.co_linetable, obj.co_freevars, + obj.co_cellvars + ) + elif hasattr(obj, "co_posonlyargcount"): # python 3.8 (16 args) + args = ( + obj.co_argcount, obj.co_posonlyargcount, + obj.co_kwonlyargcount, obj.co_nlocals, obj.co_stacksize, + obj.co_flags, obj.co_code, obj.co_consts, obj.co_names, + obj.co_varnames, obj.co_filename, obj.co_name, + obj.co_firstlineno, obj.co_lnotab, obj.co_freevars, + obj.co_cellvars + ) + else: # python 3.7 (15 args) + args = ( + obj.co_argcount, obj.co_kwonlyargcount, obj.co_nlocals, + obj.co_stacksize, obj.co_flags, obj.co_code, obj.co_consts, + obj.co_names, obj.co_varnames, obj.co_filename, + obj.co_name, obj.co_firstlineno, obj.co_lnotab, + obj.co_freevars, obj.co_cellvars + ) + + pickler.save_reduce(_create_code, args, obj=obj) + logger.trace(pickler, "# Co") + return + +def _repr_dict(obj): + """Make a short string representation of a dictionary.""" + return "<%s object at %#012x>" % (type(obj).__name__, id(obj)) + +@register(dict) +def save_module_dict(pickler, obj): + if is_dill(pickler, child=False) and obj == pickler._main.__dict__ and \ + not (pickler._session and pickler._first_pass): + logger.trace(pickler, "D1: %s", _repr_dict(obj)) # obj + pickler.write(bytes('c__builtin__\n__main__\n', 'UTF-8')) + logger.trace(pickler, "# D1") + elif (not is_dill(pickler, child=False)) and (obj == _main_module.__dict__): + logger.trace(pickler, "D3: %s", _repr_dict(obj)) # obj + pickler.write(bytes('c__main__\n__dict__\n', 'UTF-8')) #XXX: works in general? + logger.trace(pickler, "# D3") + elif '__name__' in obj and obj != _main_module.__dict__ \ + and type(obj['__name__']) is str \ + and obj is getattr(_import_module(obj['__name__'],True), '__dict__', None): + logger.trace(pickler, "D4: %s", _repr_dict(obj)) # obj + pickler.write(bytes('c%s\n__dict__\n' % obj['__name__'], 'UTF-8')) + logger.trace(pickler, "# D4") + else: + logger.trace(pickler, "D2: %s", _repr_dict(obj)) # obj + if is_dill(pickler, child=False) and pickler._session: + # we only care about session the first pass thru + pickler._first_pass = False + StockPickler.save_dict(pickler, obj) + logger.trace(pickler, "# D2") + return + + +if not OLD310 and MAPPING_PROXY_TRICK: + def save_dict_view(dicttype): + def save_dict_view_for_function(func): + def _save_dict_view(pickler, obj): + logger.trace(pickler, "Dkvi: <%s>", obj) + mapping = obj.mapping | _dictproxy_helper_instance + pickler.save_reduce(func, (mapping,), obj=obj) + logger.trace(pickler, "# Dkvi") + return _save_dict_view + return [ + (funcname, save_dict_view_for_function(getattr(dicttype, funcname))) + for funcname in ('keys', 'values', 'items') + ] +else: + # The following functions are based on 'cloudpickle' + # https://github.com/cloudpipe/cloudpickle/blob/5d89947288a18029672596a4d719093cc6d5a412/cloudpickle/cloudpickle.py#L922-L940 + # Copyright (c) 2012, Regents of the University of California. + # Copyright (c) 2009 `PiCloud, Inc. `_. + # License: https://github.com/cloudpipe/cloudpickle/blob/master/LICENSE + def save_dict_view(dicttype): + def save_dict_keys(pickler, obj): + logger.trace(pickler, "Dk: <%s>", obj) + dict_constructor = _shims.Reduce(dicttype.fromkeys, (list(obj),)) + pickler.save_reduce(dicttype.keys, (dict_constructor,), obj=obj) + logger.trace(pickler, "# Dk") + + def save_dict_values(pickler, obj): + logger.trace(pickler, "Dv: <%s>", obj) + dict_constructor = _shims.Reduce(dicttype, (enumerate(obj),)) + pickler.save_reduce(dicttype.values, (dict_constructor,), obj=obj) + logger.trace(pickler, "# Dv") + + def save_dict_items(pickler, obj): + logger.trace(pickler, "Di: <%s>", obj) + pickler.save_reduce(dicttype.items, (dicttype(obj),), obj=obj) + logger.trace(pickler, "# Di") + + return ( + ('keys', save_dict_keys), + ('values', save_dict_values), + ('items', save_dict_items) + ) + +for __dicttype in ( + dict, + OrderedDict +): + __obj = __dicttype() + for __funcname, __savefunc in save_dict_view(__dicttype): + __tview = type(getattr(__obj, __funcname)()) + if __tview not in Pickler.dispatch: + Pickler.dispatch[__tview] = __savefunc +del __dicttype, __obj, __funcname, __tview, __savefunc + + +@register(ClassType) +def save_classobj(pickler, obj): #FIXME: enable pickler._byref + if not _locate_function(obj, pickler): + logger.trace(pickler, "C1: %s", obj) + pickler.save_reduce(ClassType, (obj.__name__, obj.__bases__, + obj.__dict__), obj=obj) + #XXX: or obj.__dict__.copy()), obj=obj) ? + logger.trace(pickler, "# C1") + else: + logger.trace(pickler, "C2: %s", obj) + name = getattr(obj, '__qualname__', getattr(obj, '__name__', None)) + StockPickler.save_global(pickler, obj, name=name) + logger.trace(pickler, "# C2") + return + +@register(typing._GenericAlias) +def save_generic_alias(pickler, obj): + args = obj.__args__ + if type(obj.__reduce__()) is str: + logger.trace(pickler, "Ga0: %s", obj) + StockPickler.save_global(pickler, obj, name=obj.__reduce__()) + logger.trace(pickler, "# Ga0") + elif obj.__origin__ is tuple and (not args or args == ((),)): + logger.trace(pickler, "Ga1: %s", obj) + pickler.save_reduce(_create_typing_tuple, (args,), obj=obj) + logger.trace(pickler, "# Ga1") + else: + logger.trace(pickler, "Ga2: %s", obj) + StockPickler.save_reduce(pickler, *obj.__reduce__(), obj=obj) + logger.trace(pickler, "# Ga2") + return + +if ThreadHandleType: + @register(ThreadHandleType) + def save_thread_handle(pickler, obj): + logger.trace(pickler, "Th: %s", obj) + pickler.save_reduce(_create_thread_handle, (obj.ident, obj.is_done()), obj=obj) + logger.trace(pickler, "# Th") + return + +@register(LockType) #XXX: copied Thread will have new Event (due to new Lock) +def save_lock(pickler, obj): + logger.trace(pickler, "Lo: %s", obj) + pickler.save_reduce(_create_lock, (obj.locked(),), obj=obj) + logger.trace(pickler, "# Lo") + return + +@register(RLockType) +def save_rlock(pickler, obj): + logger.trace(pickler, "RL: %s", obj) + r = obj.__repr__() # don't use _release_save as it unlocks the lock + count = int(r.split('count=')[1].split()[0].rstrip('>')) + owner = int(r.split('owner=')[1].split()[0]) + pickler.save_reduce(_create_rlock, (count,owner,), obj=obj) + logger.trace(pickler, "# RL") + return + +#@register(SocketType) #FIXME: causes multiprocess test_pickling FAIL +def save_socket(pickler, obj): + logger.trace(pickler, "So: %s", obj) + pickler.save_reduce(*reduce_socket(obj)) + logger.trace(pickler, "# So") + return + +def _save_file(pickler, obj, open_): + if obj.closed: + position = 0 + else: + obj.flush() + if obj in (sys.__stdout__, sys.__stderr__, sys.__stdin__): + position = -1 + else: + position = obj.tell() + if is_dill(pickler, child=True) and pickler._fmode == FILE_FMODE: + f = open_(obj.name, "r") + fdata = f.read() + f.close() + else: + fdata = "" + if is_dill(pickler, child=True): + strictio = pickler._strictio + fmode = pickler._fmode + else: + strictio = False + fmode = 0 # HANDLE_FMODE + pickler.save_reduce(_create_filehandle, (obj.name, obj.mode, position, + obj.closed, open_, strictio, + fmode, fdata), obj=obj) + return + + +@register(FileType) #XXX: in 3.x has buffer=0, needs different _create? +@register(BufferedReaderType) +@register(BufferedWriterType) +@register(TextWrapperType) +def save_file(pickler, obj): + logger.trace(pickler, "Fi: %s", obj) + f = _save_file(pickler, obj, open) + logger.trace(pickler, "# Fi") + return f + +if BufferedRandomType: + @register(BufferedRandomType) + def save_file(pickler, obj): + logger.trace(pickler, "Fi: %s", obj) + f = _save_file(pickler, obj, open) + logger.trace(pickler, "# Fi") + return f + +if PyTextWrapperType: + @register(PyBufferedReaderType) + @register(PyBufferedWriterType) + @register(PyTextWrapperType) + def save_file(pickler, obj): + logger.trace(pickler, "Fi: %s", obj) + f = _save_file(pickler, obj, _open) + logger.trace(pickler, "# Fi") + return f + + if PyBufferedRandomType: + @register(PyBufferedRandomType) + def save_file(pickler, obj): + logger.trace(pickler, "Fi: %s", obj) + f = _save_file(pickler, obj, _open) + logger.trace(pickler, "# Fi") + return f + + +# The following two functions are based on 'saveCStringIoInput' +# and 'saveCStringIoOutput' from spickle +# Copyright (c) 2011 by science+computing ag +# License: http://www.apache.org/licenses/LICENSE-2.0 +if InputType: + @register(InputType) + def save_stringi(pickler, obj): + logger.trace(pickler, "Io: %s", obj) + if obj.closed: + value = ''; position = 0 + else: + value = obj.getvalue(); position = obj.tell() + pickler.save_reduce(_create_stringi, (value, position, \ + obj.closed), obj=obj) + logger.trace(pickler, "# Io") + return + + @register(OutputType) + def save_stringo(pickler, obj): + logger.trace(pickler, "Io: %s", obj) + if obj.closed: + value = ''; position = 0 + else: + value = obj.getvalue(); position = obj.tell() + pickler.save_reduce(_create_stringo, (value, position, \ + obj.closed), obj=obj) + logger.trace(pickler, "# Io") + return + +if LRUCacheType is not None: + from functools import lru_cache + @register(LRUCacheType) + def save_lru_cache(pickler, obj): + logger.trace(pickler, "LRU: %s", obj) + if OLD39: + kwargs = obj.cache_info() + args = (kwargs.maxsize,) + else: + kwargs = obj.cache_parameters() + args = (kwargs['maxsize'], kwargs['typed']) + if args != lru_cache.__defaults__: + wrapper = Reduce(lru_cache, args, is_callable=True) + else: + wrapper = lru_cache + pickler.save_reduce(wrapper, (obj.__wrapped__,), obj=obj) + logger.trace(pickler, "# LRU") + return + +@register(SuperType) +def save_super(pickler, obj): + logger.trace(pickler, "Su: %s", obj) + pickler.save_reduce(super, (obj.__thisclass__, obj.__self__), obj=obj) + logger.trace(pickler, "# Su") + return + +if IS_PYPY: + @register(MethodType) + def save_instancemethod0(pickler, obj): + code = getattr(obj.__func__, '__code__', None) + if code is not None and type(code) is not CodeType \ + and getattr(obj.__self__, obj.__name__) == obj: + # Some PyPy builtin functions have no module name + logger.trace(pickler, "Me2: %s", obj) + # TODO: verify that this works for all PyPy builtin methods + pickler.save_reduce(getattr, (obj.__self__, obj.__name__), obj=obj) + logger.trace(pickler, "# Me2") + return + + logger.trace(pickler, "Me1: %s", obj) + pickler.save_reduce(MethodType, (obj.__func__, obj.__self__), obj=obj) + logger.trace(pickler, "# Me1") + return +else: + @register(MethodType) + def save_instancemethod0(pickler, obj): + logger.trace(pickler, "Me1: %s", obj) + pickler.save_reduce(MethodType, (obj.__func__, obj.__self__), obj=obj) + logger.trace(pickler, "# Me1") + return + +if not IS_PYPY: + @register(MemberDescriptorType) + @register(GetSetDescriptorType) + @register(MethodDescriptorType) + @register(WrapperDescriptorType) + @register(ClassMethodDescriptorType) + def save_wrapper_descriptor(pickler, obj): + logger.trace(pickler, "Wr: %s", obj) + pickler.save_reduce(_getattr, (obj.__objclass__, obj.__name__, + obj.__repr__()), obj=obj) + logger.trace(pickler, "# Wr") + return +else: + @register(MemberDescriptorType) + @register(GetSetDescriptorType) + def save_wrapper_descriptor(pickler, obj): + logger.trace(pickler, "Wr: %s", obj) + pickler.save_reduce(_getattr, (obj.__objclass__, obj.__name__, + obj.__repr__()), obj=obj) + logger.trace(pickler, "# Wr") + return + +@register(CellType) +def save_cell(pickler, obj): + try: + f = obj.cell_contents + except ValueError: # cell is empty + logger.trace(pickler, "Ce3: %s", obj) + # _shims._CELL_EMPTY is defined in _shims.py to support PyPy 2.7. + # It unpickles to a sentinel object _dill._CELL_EMPTY, also created in + # _shims.py. This object is not present in Python 3 because the cell's + # contents can be deleted in newer versions of Python. The reduce object + # will instead unpickle to None if unpickled in Python 3. + + # When breaking changes are made to dill, (_shims._CELL_EMPTY,) can + # be replaced by () OR the delattr function can be removed repending on + # whichever is more convienient. + pickler.save_reduce(_create_cell, (_shims._CELL_EMPTY,), obj=obj) + # Call the function _delattr on the cell's cell_contents attribute + # The result of this function call will be None + pickler.save_reduce(_shims._delattr, (obj, 'cell_contents')) + # pop None created by calling _delattr off stack + pickler.write(POP) + logger.trace(pickler, "# Ce3") + return + if is_dill(pickler, child=True): + if id(f) in pickler._postproc: + # Already seen. Add to its postprocessing. + postproc = pickler._postproc[id(f)] + else: + # Haven't seen it. Add to the highest possible object and set its + # value as late as possible to prevent cycle. + postproc = next(iter(pickler._postproc.values()), None) + if postproc is not None: + logger.trace(pickler, "Ce2: %s", obj) + # _CELL_REF is defined in _shims.py to support older versions of + # dill. When breaking changes are made to dill, (_CELL_REF,) can + # be replaced by () + pickler.save_reduce(_create_cell, (_CELL_REF,), obj=obj) + postproc.append((_shims._setattr, (obj, 'cell_contents', f))) + logger.trace(pickler, "# Ce2") + return + logger.trace(pickler, "Ce1: %s", obj) + pickler.save_reduce(_create_cell, (f,), obj=obj) + logger.trace(pickler, "# Ce1") + return + +if MAPPING_PROXY_TRICK: + @register(DictProxyType) + def save_dictproxy(pickler, obj): + logger.trace(pickler, "Mp: %s", _repr_dict(obj)) # obj + mapping = obj | _dictproxy_helper_instance + pickler.save_reduce(DictProxyType, (mapping,), obj=obj) + logger.trace(pickler, "# Mp") + return +else: + @register(DictProxyType) + def save_dictproxy(pickler, obj): + logger.trace(pickler, "Mp: %s", _repr_dict(obj)) # obj + pickler.save_reduce(DictProxyType, (obj.copy(),), obj=obj) + logger.trace(pickler, "# Mp") + return + +@register(SliceType) +def save_slice(pickler, obj): + logger.trace(pickler, "Sl: %s", obj) + pickler.save_reduce(slice, (obj.start, obj.stop, obj.step), obj=obj) + logger.trace(pickler, "# Sl") + return + +@register(XRangeType) +@register(EllipsisType) +@register(NotImplementedType) +def save_singleton(pickler, obj): + logger.trace(pickler, "Si: %s", obj) + pickler.save_reduce(_eval_repr, (obj.__repr__(),), obj=obj) + logger.trace(pickler, "# Si") + return + +def _proxy_helper(obj): # a dead proxy returns a reference to None + """get memory address of proxy's reference object""" + _repr = repr(obj) + try: _str = str(obj) + except ReferenceError: # it's a dead proxy + return id(None) + if _str == _repr: return id(obj) # it's a repr + try: # either way, it's a proxy from here + address = int(_str.rstrip('>').split(' at ')[-1], base=16) + except ValueError: # special case: proxy of a 'type' + if not IS_PYPY: + address = int(_repr.rstrip('>').split(' at ')[-1], base=16) + else: + objects = iter(gc.get_objects()) + for _obj in objects: + if repr(_obj) == _str: return id(_obj) + # all bad below... nothing found so throw ReferenceError + msg = "Cannot reference object for proxy at '%s'" % id(obj) + raise ReferenceError(msg) + return address + +def _locate_object(address, module=None): + """get object located at the given memory address (inverse of id(obj))""" + special = [None, True, False] #XXX: more...? + for obj in special: + if address == id(obj): return obj + if module: + objects = iter(module.__dict__.values()) + else: objects = iter(gc.get_objects()) + for obj in objects: + if address == id(obj): return obj + # all bad below... nothing found so throw ReferenceError or TypeError + try: address = hex(address) + except TypeError: + raise TypeError("'%s' is not a valid memory address" % str(address)) + raise ReferenceError("Cannot reference object at '%s'" % address) + +@register(ReferenceType) +def save_weakref(pickler, obj): + refobj = obj() + logger.trace(pickler, "R1: %s", obj) + #refobj = ctypes.pythonapi.PyWeakref_GetObject(obj) # dead returns "None" + pickler.save_reduce(_create_weakref, (refobj,), obj=obj) + logger.trace(pickler, "# R1") + return + +@register(ProxyType) +@register(CallableProxyType) +def save_weakproxy(pickler, obj): + # Must do string substitution here and use %r to avoid ReferenceError. + logger.trace(pickler, "R2: %r" % obj) + refobj = _locate_object(_proxy_helper(obj)) + pickler.save_reduce(_create_weakproxy, (refobj, callable(obj)), obj=obj) + logger.trace(pickler, "# R2") + return + +def _is_builtin_module(module): + if not hasattr(module, "__file__"): return True + if module.__file__ is None: return False + # If a module file name starts with prefix, it should be a builtin + # module, so should always be pickled as a reference. + names = ["base_prefix", "base_exec_prefix", "exec_prefix", "prefix", "real_prefix"] + rp = os.path.realpath + # See https://github.com/uqfoundation/dill/issues/566 + return ( + any( + module.__file__.startswith(getattr(sys, name)) + or rp(module.__file__).startswith(rp(getattr(sys, name))) + for name in names + if hasattr(sys, name) + ) + or module.__file__.endswith(EXTENSION_SUFFIXES) + or 'site-packages' in module.__file__ + ) + +def _is_imported_module(module): + return getattr(module, '__loader__', None) is not None or module in sys.modules.values() + +@register(ModuleType) +def save_module(pickler, obj): + if False: #_use_diff: + if obj.__name__.split('.', 1)[0] != "dill": + try: + changed = diff.whats_changed(obj, seen=pickler._diff_cache)[0] + except RuntimeError: # not memorised module, probably part of dill + pass + else: + logger.trace(pickler, "M2: %s with diff", obj) + logger.info("Diff: %s", changed.keys()) + pickler.save_reduce(_import_module, (obj.__name__,), obj=obj, + state=changed) + logger.trace(pickler, "# M2") + return + + logger.trace(pickler, "M1: %s", obj) + pickler.save_reduce(_import_module, (obj.__name__,), obj=obj) + logger.trace(pickler, "# M1") + else: + builtin_mod = _is_builtin_module(obj) + is_session_main = is_dill(pickler, child=True) and obj is pickler._main + if (obj.__name__ not in ("builtins", "dill", "dill._dill") and not builtin_mod + or is_session_main): + logger.trace(pickler, "M1: %s", obj) + # Hack for handling module-type objects in load_module(). + mod_name = obj.__name__ if _is_imported_module(obj) else '__runtime__.%s' % obj.__name__ + # Second references are saved as __builtin__.__main__ in save_module_dict(). + main_dict = obj.__dict__.copy() + for item in ('__builtins__', '__loader__'): + main_dict.pop(item, None) + for item in IPYTHON_SINGLETONS: #pragma: no cover + if getattr(main_dict.get(item), '__module__', '').startswith('IPython'): + del main_dict[item] + pickler.save_reduce(_import_module, (mod_name,), obj=obj, state=main_dict) + logger.trace(pickler, "# M1") + elif obj.__name__ == "dill._dill": + logger.trace(pickler, "M2: %s", obj) + pickler.save_global(obj, name="_dill") + logger.trace(pickler, "# M2") + else: + logger.trace(pickler, "M2: %s", obj) + pickler.save_reduce(_import_module, (obj.__name__,), obj=obj) + logger.trace(pickler, "# M2") + return + +# The following function is based on '_extract_class_dict' from 'cloudpickle' +# Copyright (c) 2012, Regents of the University of California. +# Copyright (c) 2009 `PiCloud, Inc. `_. +# License: https://github.com/cloudpipe/cloudpickle/blob/master/LICENSE +def _get_typedict_type(cls, clsdict, attrs, postproc_list): + """Retrieve a copy of the dict of a class without the inherited methods""" + if len(cls.__bases__) == 1: + inherited_dict = cls.__bases__[0].__dict__ + else: + inherited_dict = {} + for base in reversed(cls.__bases__): + inherited_dict.update(base.__dict__) + to_remove = [] + for name, value in dict.items(clsdict): + try: + base_value = inherited_dict[name] + if value is base_value and hasattr(value, '__qualname__'): + to_remove.append(name) + except KeyError: + pass + for name in to_remove: + dict.pop(clsdict, name) + + if issubclass(type(cls), type): + clsdict.pop('__dict__', None) + clsdict.pop('__weakref__', None) + # clsdict.pop('__prepare__', None) + return clsdict, attrs + +def _get_typedict_abc(obj, _dict, attrs, postproc_list): + if hasattr(abc, '_get_dump'): + (registry, _, _, _) = abc._get_dump(obj) + register = obj.register + postproc_list.extend((register, (reg(),)) for reg in registry) + elif hasattr(obj, '_abc_registry'): + registry = obj._abc_registry + register = obj.register + postproc_list.extend((register, (reg,)) for reg in registry) + else: + raise PicklingError("Cannot find registry of ABC %s", obj) + + if '_abc_registry' in _dict: + _dict.pop('_abc_registry', None) + _dict.pop('_abc_cache', None) + _dict.pop('_abc_negative_cache', None) + # _dict.pop('_abc_negative_cache_version', None) + else: + _dict.pop('_abc_impl', None) + return _dict, attrs + +@register(TypeType) +def save_type(pickler, obj, postproc_list=None): + if obj in _typemap: + logger.trace(pickler, "T1: %s", obj) + # if obj in _incedental_types: + # warnings.warn('Type %r may only exist on this implementation of Python and cannot be unpickled in other implementations.' % (obj,), PicklingWarning) + pickler.save_reduce(_load_type, (_typemap[obj],), obj=obj) + logger.trace(pickler, "# T1") + elif obj.__bases__ == (tuple,) and all([hasattr(obj, attr) for attr in ('_fields','_asdict','_make','_replace')]): + # special case: namedtuples + logger.trace(pickler, "T6: %s", obj) + + obj_name = getattr(obj, '__qualname__', getattr(obj, '__name__', None)) + if obj.__name__ != obj_name: + if postproc_list is None: + postproc_list = [] + postproc_list.append((setattr, (obj, '__qualname__', obj_name))) + + if not obj._field_defaults: + _save_with_postproc(pickler, (_create_namedtuple, (obj.__name__, obj._fields, obj.__module__)), obj=obj, postproc_list=postproc_list) + else: + defaults = [obj._field_defaults[field] for field in obj._fields if field in obj._field_defaults] + _save_with_postproc(pickler, (_create_namedtuple, (obj.__name__, obj._fields, obj.__module__, defaults)), obj=obj, postproc_list=postproc_list) + logger.trace(pickler, "# T6") + return + + # special caes: NoneType, NotImplementedType, EllipsisType, EnumMeta, etc + elif obj is type(None): + logger.trace(pickler, "T7: %s", obj) + #XXX: pickler.save_reduce(type, (None,), obj=obj) + pickler.write(GLOBAL + b'__builtin__\nNoneType\n') + logger.trace(pickler, "# T7") + elif obj is NotImplementedType: + logger.trace(pickler, "T7: %s", obj) + pickler.save_reduce(type, (NotImplemented,), obj=obj) + logger.trace(pickler, "# T7") + elif obj is EllipsisType: + logger.trace(pickler, "T7: %s", obj) + pickler.save_reduce(type, (Ellipsis,), obj=obj) + logger.trace(pickler, "# T7") + elif obj is EnumMeta: + logger.trace(pickler, "T7: %s", obj) + pickler.write(GLOBAL + b'enum\nEnumMeta\n') + logger.trace(pickler, "# T7") + elif obj is ExceptHookArgsType: #NOTE: must be after NoneType for pypy + logger.trace(pickler, "T7: %s", obj) + pickler.write(GLOBAL + b'threading\nExceptHookArgs\n') + logger.trace(pickler, "# T7") + + else: + _byref = getattr(pickler, '_byref', None) + obj_recursive = id(obj) in getattr(pickler, '_postproc', ()) + incorrectly_named = not _locate_function(obj, pickler) + if not _byref and not obj_recursive and incorrectly_named: # not a function, but the name was held over + if postproc_list is None: + postproc_list = [] + + # thanks to Tom Stepleton pointing out pickler._session unneeded + logger.trace(pickler, "T2: %s", obj) + _dict, attrs = _get_typedict_type(obj, obj.__dict__.copy(), None, postproc_list) # copy dict proxy to a dict + + #print (_dict) + #print ("%s\n%s" % (type(obj), obj.__name__)) + #print ("%s\n%s" % (obj.__bases__, obj.__dict__)) + slots = _dict.get('__slots__', ()) + if type(slots) == str: + # __slots__ accepts a single string + slots = (slots,) + + for name in slots: + _dict.pop(name, None) + + if isinstance(obj, abc.ABCMeta): + logger.trace(pickler, "ABC: %s", obj) + _dict, attrs = _get_typedict_abc(obj, _dict, attrs, postproc_list) + logger.trace(pickler, "# ABC") + + qualname = getattr(obj, '__qualname__', None) + if attrs is not None: + for k, v in attrs.items(): + postproc_list.append((setattr, (obj, k, v))) + # TODO: Consider using the state argument to save_reduce? + if qualname is not None: + postproc_list.append((setattr, (obj, '__qualname__', qualname))) + + if not hasattr(obj, '__orig_bases__'): + _save_with_postproc(pickler, (_create_type, ( + type(obj), obj.__name__, obj.__bases__, _dict + )), obj=obj, postproc_list=postproc_list) + else: + # This case will always work, but might be overkill. + _metadict = { + 'metaclass': type(obj) + } + + if _dict: + _dict_update = PartialType(_setitems, source=_dict) + else: + _dict_update = None + + _save_with_postproc(pickler, (new_class, ( + obj.__name__, obj.__orig_bases__, _metadict, _dict_update + )), obj=obj, postproc_list=postproc_list) + logger.trace(pickler, "# T2") + else: + obj_name = getattr(obj, '__qualname__', getattr(obj, '__name__', None)) + logger.trace(pickler, "T4: %s", obj) + if incorrectly_named: + warnings.warn( + "Cannot locate reference to %r." % (obj,), + PicklingWarning, + stacklevel=3, + ) + if obj_recursive: + warnings.warn( + "Cannot pickle %r: %s.%s has recursive self-references that " + "trigger a RecursionError." % (obj, obj.__module__, obj_name), + PicklingWarning, + stacklevel=3, + ) + #print (obj.__dict__) + #print ("%s\n%s" % (type(obj), obj.__name__)) + #print ("%s\n%s" % (obj.__bases__, obj.__dict__)) + StockPickler.save_global(pickler, obj, name=obj_name) + logger.trace(pickler, "# T4") + return + +@register(property) +@register(abc.abstractproperty) +def save_property(pickler, obj): + logger.trace(pickler, "Pr: %s", obj) + pickler.save_reduce(type(obj), (obj.fget, obj.fset, obj.fdel, obj.__doc__), + obj=obj) + logger.trace(pickler, "# Pr") + +@register(staticmethod) +@register(classmethod) +@register(abc.abstractstaticmethod) +@register(abc.abstractclassmethod) +def save_classmethod(pickler, obj): + logger.trace(pickler, "Cm: %s", obj) + orig_func = obj.__func__ + + # if type(obj.__dict__) is dict: + # if obj.__dict__: + # state = obj.__dict__ + # else: + # state = None + # else: + # state = (None, {'__dict__', obj.__dict__}) + + pickler.save_reduce(type(obj), (orig_func,), obj=obj) + logger.trace(pickler, "# Cm") + +@register(FunctionType) +def save_function(pickler, obj): + if not _locate_function(obj, pickler): + if type(obj.__code__) is not CodeType: + # Some PyPy builtin functions have no module name, and thus are not + # able to be located + module_name = getattr(obj, '__module__', None) + if module_name is None: + module_name = __builtin__.__name__ + module = _import_module(module_name, safe=True) + _pypy_builtin = False + try: + found, _ = _getattribute(module, obj.__qualname__) + if getattr(found, '__func__', None) is obj: + _pypy_builtin = True + except AttributeError: + pass + + if _pypy_builtin: + logger.trace(pickler, "F3: %s", obj) + pickler.save_reduce(getattr, (found, '__func__'), obj=obj) + logger.trace(pickler, "# F3") + return + + logger.trace(pickler, "F1: %s", obj) + _recurse = getattr(pickler, '_recurse', None) + _postproc = getattr(pickler, '_postproc', None) + _main_modified = getattr(pickler, '_main_modified', None) + _original_main = getattr(pickler, '_original_main', __builtin__)#'None' + postproc_list = [] + if _recurse: + # recurse to get all globals referred to by obj + from .detect import globalvars + globs_copy = globalvars(obj, recurse=True, builtin=True) + + # Add the name of the module to the globs dictionary to prevent + # the duplication of the dictionary. Pickle the unpopulated + # globals dictionary and set the remaining items after the function + # is created to correctly handle recursion. + globs = {'__name__': obj.__module__} + else: + globs_copy = obj.__globals__ + + # If the globals is the __dict__ from the module being saved as a + # session, substitute it by the dictionary being actually saved. + if _main_modified and globs_copy is _original_main.__dict__: + globs_copy = getattr(pickler, '_main', _original_main).__dict__ + globs = globs_copy + # If the globals is a module __dict__, do not save it in the pickle. + elif globs_copy is not None and obj.__module__ is not None and \ + getattr(_import_module(obj.__module__, True), '__dict__', None) is globs_copy: + globs = globs_copy + else: + globs = {'__name__': obj.__module__} + + if globs_copy is not None and globs is not globs_copy: + # In the case that the globals are copied, we need to ensure that + # the globals dictionary is updated when all objects in the + # dictionary are already created. + glob_ids = {id(g) for g in globs_copy.values()} + for stack_element in _postproc: + if stack_element in glob_ids: + _postproc[stack_element].append((_setitems, (globs, globs_copy))) + break + else: + postproc_list.append((_setitems, (globs, globs_copy))) + + closure = obj.__closure__ + state_dict = {} + for fattrname in ('__doc__', '__kwdefaults__', '__annotations__'): + fattr = getattr(obj, fattrname, None) + if fattr is not None: + state_dict[fattrname] = fattr + if obj.__qualname__ != obj.__name__: + state_dict['__qualname__'] = obj.__qualname__ + if '__name__' not in globs or obj.__module__ != globs['__name__']: + state_dict['__module__'] = obj.__module__ + + state = obj.__dict__ + if type(state) is not dict: + state_dict['__dict__'] = state + state = None + if state_dict: + state = state, state_dict + + _save_with_postproc(pickler, (_create_function, ( + obj.__code__, globs, obj.__name__, obj.__defaults__, + closure + ), state), obj=obj, postproc_list=postproc_list) + + # Lift closure cell update to earliest function (#458) + if _postproc: + topmost_postproc = next(iter(_postproc.values()), None) + if closure and topmost_postproc: + for cell in closure: + possible_postproc = (setattr, (cell, 'cell_contents', obj)) + try: + topmost_postproc.remove(possible_postproc) + except ValueError: + continue + + # Change the value of the cell + pickler.save_reduce(*possible_postproc) + # pop None created by calling preprocessing step off stack + pickler.write(POP) + + logger.trace(pickler, "# F1") + else: + logger.trace(pickler, "F2: %s", obj) + name = getattr(obj, '__qualname__', getattr(obj, '__name__', None)) + StockPickler.save_global(pickler, obj, name=name) + logger.trace(pickler, "# F2") + return + +if HAS_CTYPES and hasattr(ctypes, 'pythonapi'): + _PyCapsule_New = ctypes.pythonapi.PyCapsule_New + _PyCapsule_New.argtypes = (ctypes.c_void_p, ctypes.c_char_p, ctypes.c_void_p) + _PyCapsule_New.restype = ctypes.py_object + _PyCapsule_GetPointer = ctypes.pythonapi.PyCapsule_GetPointer + _PyCapsule_GetPointer.argtypes = (ctypes.py_object, ctypes.c_char_p) + _PyCapsule_GetPointer.restype = ctypes.c_void_p + _PyCapsule_GetDestructor = ctypes.pythonapi.PyCapsule_GetDestructor + _PyCapsule_GetDestructor.argtypes = (ctypes.py_object,) + _PyCapsule_GetDestructor.restype = ctypes.c_void_p + _PyCapsule_GetContext = ctypes.pythonapi.PyCapsule_GetContext + _PyCapsule_GetContext.argtypes = (ctypes.py_object,) + _PyCapsule_GetContext.restype = ctypes.c_void_p + _PyCapsule_GetName = ctypes.pythonapi.PyCapsule_GetName + _PyCapsule_GetName.argtypes = (ctypes.py_object,) + _PyCapsule_GetName.restype = ctypes.c_char_p + _PyCapsule_IsValid = ctypes.pythonapi.PyCapsule_IsValid + _PyCapsule_IsValid.argtypes = (ctypes.py_object, ctypes.c_char_p) + _PyCapsule_IsValid.restype = ctypes.c_bool + _PyCapsule_SetContext = ctypes.pythonapi.PyCapsule_SetContext + _PyCapsule_SetContext.argtypes = (ctypes.py_object, ctypes.c_void_p) + _PyCapsule_SetDestructor = ctypes.pythonapi.PyCapsule_SetDestructor + _PyCapsule_SetDestructor.argtypes = (ctypes.py_object, ctypes.c_void_p) + _PyCapsule_SetName = ctypes.pythonapi.PyCapsule_SetName + _PyCapsule_SetName.argtypes = (ctypes.py_object, ctypes.c_char_p) + _PyCapsule_SetPointer = ctypes.pythonapi.PyCapsule_SetPointer + _PyCapsule_SetPointer.argtypes = (ctypes.py_object, ctypes.c_void_p) + #from _socket import CAPI as _testcapsule + _testcapsule_name = b'dill._dill._testcapsule' + _testcapsule = _PyCapsule_New( + ctypes.cast(_PyCapsule_New, ctypes.c_void_p), + ctypes.c_char_p(_testcapsule_name), + None + ) + PyCapsuleType = type(_testcapsule) + @register(PyCapsuleType) + def save_capsule(pickler, obj): + logger.trace(pickler, "Cap: %s", obj) + name = _PyCapsule_GetName(obj) + #warnings.warn('Pickling a PyCapsule (%s) does not pickle any C data structures and could cause segmentation faults or other memory errors when unpickling.' % (name,), PicklingWarning) + pointer = _PyCapsule_GetPointer(obj, name) + context = _PyCapsule_GetContext(obj) + destructor = _PyCapsule_GetDestructor(obj) + pickler.save_reduce(_create_capsule, (pointer, name, context, destructor), obj=obj) + logger.trace(pickler, "# Cap") + _incedental_reverse_typemap['PyCapsuleType'] = PyCapsuleType + _reverse_typemap['PyCapsuleType'] = PyCapsuleType + _incedental_types.add(PyCapsuleType) +else: + _testcapsule = None + +@register(ContextType) +def save_context(pickler, obj): + logger.trace(pickler, "Cx: %s", obj) + pickler.save_reduce(ContextType, tuple(obj.items()), obj=obj) + logger.trace(pickler, "# Cx") + + +############################# +# A quick fix for issue #500 +# This should be removed when a better solution is found. + +if hasattr(dataclasses, "_HAS_DEFAULT_FACTORY_CLASS"): + @register(dataclasses._HAS_DEFAULT_FACTORY_CLASS) + def save_dataclasses_HAS_DEFAULT_FACTORY_CLASS(pickler, obj): + logger.trace(pickler, "DcHDF: %s", obj) + pickler.write(GLOBAL + b"dataclasses\n_HAS_DEFAULT_FACTORY\n") + logger.trace(pickler, "# DcHDF") + +if hasattr(dataclasses, "MISSING"): + @register(type(dataclasses.MISSING)) + def save_dataclasses_MISSING_TYPE(pickler, obj): + logger.trace(pickler, "DcM: %s", obj) + pickler.write(GLOBAL + b"dataclasses\nMISSING\n") + logger.trace(pickler, "# DcM") + +if hasattr(dataclasses, "KW_ONLY"): + @register(type(dataclasses.KW_ONLY)) + def save_dataclasses_KW_ONLY_TYPE(pickler, obj): + logger.trace(pickler, "DcKWO: %s", obj) + pickler.write(GLOBAL + b"dataclasses\nKW_ONLY\n") + logger.trace(pickler, "# DcKWO") + +if hasattr(dataclasses, "_FIELD_BASE"): + @register(dataclasses._FIELD_BASE) + def save_dataclasses_FIELD_BASE(pickler, obj): + logger.trace(pickler, "DcFB: %s", obj) + pickler.write(GLOBAL + b"dataclasses\n" + obj.name.encode() + b"\n") + logger.trace(pickler, "# DcFB") + +############################# + +# quick sanity checking +def pickles(obj,exact=False,safe=False,**kwds): + """ + Quick check if object pickles with dill. + + If *exact=True* then an equality test is done to check if the reconstructed + object matches the original object. + + If *safe=True* then any exception will raised in copy signal that the + object is not picklable, otherwise only pickling errors will be trapped. + + Additional keyword arguments are as :func:`dumps` and :func:`loads`. + """ + if safe: exceptions = (Exception,) # RuntimeError, ValueError + else: + exceptions = (TypeError, AssertionError, NotImplementedError, PicklingError, UnpicklingError) + try: + pik = copy(obj, **kwds) + #FIXME: should check types match first, then check content if "exact" + try: + #FIXME: should be "(pik == obj).all()" for numpy comparison, though that'll fail if shapes differ + result = bool(pik.all() == obj.all()) + except (AttributeError, TypeError): + warnings.filterwarnings('ignore') #FIXME: be specific + result = pik == obj + if warnings.filters: del warnings.filters[0] + if hasattr(result, 'toarray'): # for unusual types like sparse matrix + result = result.toarray().all() + if result: return True + if not exact: + result = type(pik) == type(obj) + if result: return result + # class instances might have been dumped with byref=False + return repr(type(pik)) == repr(type(obj)) #XXX: InstanceType? + return False + except exceptions: + return False + +def check(obj, *args, **kwds): + """ + Check pickling of an object across another process. + + *python* is the path to the python interpreter (defaults to sys.executable) + + Set *verbose=True* to print the unpickled object in the other process. + + Additional keyword arguments are as :func:`dumps` and :func:`loads`. + """ + # == undocumented == + # python -- the string path or executable name of the selected python + # verbose -- if True, be verbose about printing warning messages + # all other args and kwds are passed to dill.dumps #FIXME: ignore on load + verbose = kwds.pop('verbose', False) + python = kwds.pop('python', None) + if python is None: + import sys + python = sys.executable + # type check + isinstance(python, str) + import subprocess + fail = True + try: + _obj = dumps(obj, *args, **kwds) + fail = False + finally: + if fail and verbose: + print("DUMP FAILED") + #FIXME: fails if python interpreter path contains spaces + # Use the following instead (which also processes the 'ignore' keyword): + # ignore = kwds.pop('ignore', None) + # unpickle = "dill.loads(%s, ignore=%s)"%(repr(_obj), repr(ignore)) + # cmd = [python, "-c", "import dill; print(%s)"%unpickle] + # msg = "SUCCESS" if not subprocess.call(cmd) else "LOAD FAILED" + msg = "%s -c import dill; print(dill.loads(%s))" % (python, repr(_obj)) + msg = "SUCCESS" if not subprocess.call(msg.split(None,2)) else "LOAD FAILED" + if verbose: + print(msg) + return + +# use to protect against missing attributes +def is_dill(pickler, child=None): + "check the dill-ness of your pickler" + if child is False or not hasattr(pickler.__class__, 'mro'): + return 'dill' in pickler.__module__ + return Pickler in pickler.__class__.mro() + +def _extend(): + """extend pickle with all of dill's registered types""" + # need to have pickle not choke on _main_module? use is_dill(pickler) + for t,func in Pickler.dispatch.items(): + try: + StockPickler.dispatch[t] = func + except Exception: #TypeError, PicklingError, UnpicklingError + logger.trace(pickler, "skip: %s", t) + return + +del diff, _use_diff, use_diff + +# EOF diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/dill/_objects.py b/bioagent-bench/.venv/lib/python3.14/site-packages/dill/_objects.py new file mode 100644 index 0000000000000000000000000000000000000000..573fae85bcb1d043e5f07bd57d4d3ae240206424 --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/dill/_objects.py @@ -0,0 +1,545 @@ +#!/usr/bin/env python +# +# Author: Mike McKerns (mmckerns @caltech and @uqfoundation) +# Copyright (c) 2008-2016 California Institute of Technology. +# Copyright (c) 2016-2026 The Uncertainty Quantification Foundation. +# License: 3-clause BSD. The full license text is available at: +# - https://github.com/uqfoundation/dill/blob/master/LICENSE +""" +all Python Standard Library objects (currently: CH 1-15 @ 2.7) +and some other common objects (i.e. numpy.ndarray) +""" + +__all__ = ['registered','failures','succeeds'] + +# helper imports +import warnings; warnings.filterwarnings("ignore", category=DeprecationWarning) +import sys +import queue as Queue +#import dbm as anydbm #XXX: delete foo +from io import BytesIO as StringIO +import re +import array +import collections +import codecs +import struct +import dataclasses +import datetime +import calendar +import weakref +import pprint +import decimal +import numbers +import functools +import itertools +import operator +import tempfile +import shelve +import zlib +import gzip +import zipfile +import tarfile +import csv +import hashlib +import hmac +import os +import logging +import logging.handlers +import optparse +#import __hello__ +import threading +import socket +import contextlib +import contextvars +try: + import bz2 + import sqlite3 + import dbm.ndbm as dbm + HAS_ALL = True +except ImportError: # Ubuntu + HAS_ALL = False +try: + #import curses + #from curses import textpad, panel + HAS_CURSES = True +except ImportError: # Windows + HAS_CURSES = False +try: + import ctypes + HAS_CTYPES = True + # if using `pypy`, pythonapi is not found + IS_PYPY = not hasattr(ctypes, 'pythonapi') +except ImportError: # MacPorts + HAS_CTYPES = False + IS_PYPY = False + +IS_PYODIDE = sys.platform == 'emscripten' + +# helper objects +class _class: + def _method(self): + pass +# @classmethod +# def _clsmethod(cls): #XXX: test me +# pass +# @staticmethod +# def _static(self): #XXX: test me +# pass +class _class2: + def __call__(self): + pass +_instance2 = _class2() +class _newclass(object): + def _method(self): + pass +# @classmethod +# def _clsmethod(cls): #XXX: test me +# pass +# @staticmethod +# def _static(self): #XXX: test me +# pass +class _newclass2(object): + __slots__ = ['descriptor'] +def _function(x): yield x +def _function2(): + try: raise + except Exception: + from sys import exc_info + e, er, tb = exc_info() + return er, tb +if HAS_CTYPES: + class _Struct(ctypes.Structure): + pass + _Struct._fields_ = [("_field", ctypes.c_int),("next", ctypes.POINTER(_Struct))] +_filedescrip, _tempfile = tempfile.mkstemp('r') # deleted in cleanup +if sys.hexversion < 0x30d00a1: + _tmpf = tempfile.TemporaryFile('w') # emits OSError 9 in python 3.13 +else: + _tmpf = tempfile.NamedTemporaryFile('w').file # for > python 3.9 + +# objects used by dill for type declaration +registered = d = {} +# objects dill fails to pickle +failures = x = {} +# all other type objects +succeeds = a = {} + +# types module (part of CH 8) +a['BooleanType'] = bool(1) +a['BuiltinFunctionType'] = len +a['BuiltinMethodType'] = a['BuiltinFunctionType'] +a['BytesType'] = _bytes = codecs.latin_1_encode('\x00')[0] # bytes(1) +a['ClassType'] = _class +a['ComplexType'] = complex(1) +a['DictType'] = _dict = {} +a['DictionaryType'] = a['DictType'] +a['FloatType'] = float(1) +a['FunctionType'] = _function +a['InstanceType'] = _instance = _class() +a['IntType'] = _int = int(1) +a['ListType'] = _list = [] +a['NoneType'] = None +a['ObjectType'] = object() +a['StringType'] = _str = str(1) +a['TupleType'] = _tuple = () +a['TypeType'] = type +a['LongType'] = _int +a['UnicodeType'] = _str +# built-in constants (CH 4) +a['CopyrightType'] = copyright +# built-in types (CH 5) +a['ClassObjectType'] = _newclass # +a['ClassInstanceType'] = _newclass() # +a['SetType'] = _set = set() +a['FrozenSetType'] = frozenset() +# built-in exceptions (CH 6) +a['ExceptionType'] = _exception = _function2()[0] +# string services (CH 7) +a['SREPatternType'] = _srepattern = re.compile('') +# data types (CH 8) +a['ArrayType'] = array.array("f") +a['DequeType'] = collections.deque([0]) +a['DefaultDictType'] = collections.defaultdict(_function, _dict) +a['TZInfoType'] = datetime.tzinfo() +a['DateTimeType'] = datetime.datetime.today() +a['CalendarType'] = calendar.Calendar() +# numeric and mathematical types (CH 9) +a['DecimalType'] = decimal.Decimal(1) +# data compression and archiving (CH 12) +a['TarInfoType'] = tarfile.TarInfo() +# generic operating system services (CH 15) +a['LoggerType'] = _logger = logging.getLogger() +a['FormatterType'] = logging.Formatter() # pickle ok +a['FilterType'] = logging.Filter() # pickle ok +a['LogRecordType'] = logging.makeLogRecord(_dict) # pickle ok +a['OptionParserType'] = _oparser = optparse.OptionParser() # pickle ok +a['OptionGroupType'] = optparse.OptionGroup(_oparser,"foo") # pickle ok +a['OptionType'] = optparse.Option('--foo') # pickle ok +if HAS_CTYPES: + z = x if (IS_PYPY and sys.hexversion < 0x30b0df0) else a + z['CCharType'] = _cchar = ctypes.c_char() + z['CWCharType'] = ctypes.c_wchar() # fail == 2.6 + z['CByteType'] = ctypes.c_byte() + z['CUByteType'] = ctypes.c_ubyte() + z['CShortType'] = ctypes.c_short() + z['CUShortType'] = ctypes.c_ushort() + z['CIntType'] = ctypes.c_int() + z['CUIntType'] = ctypes.c_uint() + z['CLongType'] = ctypes.c_long() + z['CULongType'] = ctypes.c_ulong() + z['CLongLongType'] = ctypes.c_longlong() + z['CULongLongType'] = ctypes.c_ulonglong() + z['CFloatType'] = ctypes.c_float() + z['CDoubleType'] = ctypes.c_double() + z['CSizeTType'] = ctypes.c_size_t() + del z + a['CLibraryLoaderType'] = ctypes.cdll + a['StructureType'] = _Struct + # if not IS_PYPY: + # a['BigEndianStructureType'] = ctypes.BigEndianStructure() +#NOTE: also LittleEndianStructureType and UnionType... abstract classes +#NOTE: remember for ctypesobj.contents creates a new python object +#NOTE: ctypes.c_int._objects is memberdescriptor for object's __dict__ +#NOTE: base class of all ctypes data types is non-public _CData + +import fractions +import io +from io import StringIO as TextIO +# built-in functions (CH 2) +a['ByteArrayType'] = bytearray([1]) +# numeric and mathematical types (CH 9) +a['FractionType'] = fractions.Fraction() +a['NumberType'] = numbers.Number() +# generic operating system services (CH 15) +a['IOBaseType'] = io.IOBase() +a['RawIOBaseType'] = io.RawIOBase() +a['TextIOBaseType'] = io.TextIOBase() +a['BufferedIOBaseType'] = io.BufferedIOBase() +a['UnicodeIOType'] = TextIO() # the new StringIO +a['LoggerAdapterType'] = logging.LoggerAdapter(_logger,_dict) # pickle ok +if HAS_CTYPES: + z = x if (IS_PYPY and sys.hexversion < 0x30b0df0) else a + z['CBoolType'] = ctypes.c_bool(1) + z['CLongDoubleType'] = ctypes.c_longdouble() + del z +import argparse +# data types (CH 8) +a['OrderedDictType'] = collections.OrderedDict(_dict) +a['CounterType'] = collections.Counter(_dict) +if HAS_CTYPES: + z = x if (IS_PYPY and sys.hexversion < 0x30b0df0) else a + z['CSSizeTType'] = ctypes.c_ssize_t() + del z +# generic operating system services (CH 15) +a['NullHandlerType'] = logging.NullHandler() # pickle ok # new 2.7 +a['ArgParseFileType'] = argparse.FileType() # pickle ok + +# -- pickle fails on all below here ----------------------------------------- +# types module (part of CH 8) +a['CodeType'] = compile('','','exec') +a['DictProxyType'] = type.__dict__ +a['DictProxyType2'] = _newclass.__dict__ +a['EllipsisType'] = Ellipsis +a['ClosedFileType'] = open(os.devnull, 'wb', buffering=0).close() +a['GetSetDescriptorType'] = array.array.typecode +a['LambdaType'] = _lambda = lambda x: lambda y: x #XXX: works when not imported! +a['MemberDescriptorType'] = _newclass2.descriptor +if not IS_PYPY: + a['MemberDescriptorType2'] = datetime.timedelta.days +a['MethodType'] = _method = _class()._method #XXX: works when not imported! +a['ModuleType'] = datetime +a['NotImplementedType'] = NotImplemented +a['SliceType'] = slice(1) +a['UnboundMethodType'] = _class._method #XXX: works when not imported! +from dill._dill import get_file_type as openfile +d['TextWrapperType'] = openfile('r', buffering=-1) # same as mode='w','w+','r+' +if not IS_PYODIDE: + d['BufferedRandomType'] = openfile('r+b', buffering=-1) # same as mode='w+b' +d['BufferedReaderType'] = openfile('rb', buffering=-1) # (default: buffering=-1) +d['BufferedWriterType'] = openfile('wb', buffering=-1) +try: # oddities: deprecated + from _pyio import open as _open + d['PyTextWrapperType'] = openfile('r', buffering=-1, open=_open) + if not IS_PYODIDE: + d['PyBufferedRandomType'] = openfile('r+b', buffering=-1, open=_open) + d['PyBufferedReaderType'] = openfile('rb', buffering=-1, open=_open) + d['PyBufferedWriterType'] = openfile('wb', buffering=-1, open=_open) +except ImportError: + pass +del openfile +# other (concrete) object types +z = d if sys.hexversion < 0x30800a2 else a +z['CellType'] = (_lambda)(0).__closure__[0] +del z +a['XRangeType'] = _xrange = range(1) +a['MethodDescriptorType'] = type.__dict__['mro'] +a['WrapperDescriptorType'] = type.__repr__ +#a['WrapperDescriptorType2'] = type.__dict__['__module__']#XXX: GetSetDescriptor +a['ClassMethodDescriptorType'] = type.__dict__['__prepare__'] +# built-in functions (CH 2) +_methodwrap = (1).__lt__ +a['MethodWrapperType'] = _methodwrap +a['StaticMethodType'] = staticmethod(_method) +a['ClassMethodType'] = classmethod(_method) +a['PropertyType'] = property() +d['SuperType'] = super(Exception, _exception) +# string services (CH 7) +_in = _bytes +a['InputType'] = _cstrI = StringIO(_in) +a['OutputType'] = _cstrO = StringIO() +# data types (CH 8) +a['WeakKeyDictionaryType'] = weakref.WeakKeyDictionary() +a['WeakValueDictionaryType'] = weakref.WeakValueDictionary() +a['ReferenceType'] = weakref.ref(_instance) +a['DeadReferenceType'] = weakref.ref(_class()) +a['ProxyType'] = weakref.proxy(_instance) +a['DeadProxyType'] = weakref.proxy(_class()) +a['CallableProxyType'] = weakref.proxy(_instance2) +a['DeadCallableProxyType'] = weakref.proxy(_class2()) +a['QueueType'] = Queue.Queue() +# numeric and mathematical types (CH 9) +d['PartialType'] = functools.partial(int,base=2) +a['IzipType'] = zip('0','1') +d['ItemGetterType'] = operator.itemgetter(0) +d['AttrGetterType'] = operator.attrgetter('__repr__') +# file and directory access (CH 10) +_fileW = _cstrO +# data persistence (CH 11) +if HAS_ALL: + x['ConnectionType'] = _conn = sqlite3.connect(':memory:') + x['CursorType'] = _conn.cursor() +a['ShelveType'] = shelve.Shelf({}) +# data compression and archiving (CH 12) +if HAS_ALL: + x['BZ2FileType'] = bz2.BZ2File(os.devnull) + x['BZ2CompressorType'] = bz2.BZ2Compressor() + x['BZ2DecompressorType'] = bz2.BZ2Decompressor() +#x['ZipFileType'] = _zip = zipfile.ZipFile(os.devnull,'w') +#_zip.write(_tempfile,'x') [causes annoying warning/error printed on import] +#a['ZipInfoType'] = _zip.getinfo('x') +a['TarFileType'] = tarfile.open(fileobj=_fileW,mode='w') +# file formats (CH 13) +x['DialectType'] = csv.get_dialect('excel') +if sys.hexversion < 0x30d00a1: + import xdrlib + a['PackerType'] = xdrlib.Packer() +# optional operating system services (CH 16) +a['LockType'] = threading.Lock() +a['RLockType'] = threading.RLock() +# generic operating system services (CH 15) # also closed/open and r/w/etc... +a['NamedLoggerType'] = _logger = logging.getLogger(__name__) +#a['FrozenModuleType'] = __hello__ #FIXME: prints "Hello world..." +# interprocess communication (CH 17) +x['SocketType'] = _socket = socket.socket() +x['SocketPairType'] = socket.socketpair()[0] +# python runtime services (CH 27) +a['GeneratorContextManagerType'] = contextlib.contextmanager(max)([1]) +#a['ContextType'] = contextvars.Context() #XXX: ContextVar + +try: # ipython + __IPYTHON__ is True # is ipython +except NameError: + # built-in constants (CH 4) + a['QuitterType'] = quit + d['ExitType'] = a['QuitterType'] +try: # numpy #FIXME: slow... 0.05 to 0.1 sec to import numpy + from numpy import ufunc as _numpy_ufunc + from numpy import array as _numpy_array + from numpy import int32 as _numpy_int32 + a['NumpyUfuncType'] = _numpy_ufunc + a['NumpyArrayType'] = _numpy_array + a['NumpyInt32Type'] = _numpy_int32 +except ImportError: + pass +# generic operating system services (CH 15) +a['FileHandlerType'] = logging.FileHandler(os.devnull) +a['RotatingFileHandlerType'] = logging.handlers.RotatingFileHandler(os.devnull) +a['SocketHandlerType'] = logging.handlers.SocketHandler('localhost',514) +a['MemoryHandlerType'] = logging.handlers.MemoryHandler(1) +# data types (CH 8) +a['WeakSetType'] = weakref.WeakSet() # 2.7 +# generic operating system services (CH 15) [errors when dill is imported] +#a['ArgumentParserType'] = _parser = argparse.ArgumentParser('PROG') +#a['NamespaceType'] = _parser.parse_args() # pickle ok +#a['SubParsersActionType'] = _parser.add_subparsers() +#a['MutuallyExclusiveGroupType'] = _parser.add_mutually_exclusive_group() +#a['ArgumentGroupType'] = _parser.add_argument_group() + +# -- dill fails in some versions below here --------------------------------- +# types module (part of CH 8) +d['FileType'] = open(os.devnull, 'rb', buffering=0) # same 'wb','wb+','rb+' +# built-in functions (CH 2) +# Iterators: +a['ListIteratorType'] = iter(_list) # empty vs non-empty +a['SetIteratorType'] = iter(_set) #XXX: empty vs non-empty #FIXME: list_iterator +a['TupleIteratorType']= iter(_tuple) # empty vs non-empty +a['XRangeIteratorType'] = iter(_xrange) # empty vs non-empty +a["BytesIteratorType"] = iter(b'') +a["BytearrayIteratorType"] = iter(bytearray(b'')) +z = x if IS_PYPY else a +z["CallableIteratorType"] = iter(iter, None) +del z +x["MemoryIteratorType"] = iter(memoryview(b'')) +a["ListReverseiteratorType"] = reversed([]) +X = a['OrderedDictType'] +d["OdictKeysType"] = X.keys() +d["OdictValuesType"] = X.values() +d["OdictItemsType"] = X.items() +a["OdictIteratorType"] = iter(X.keys()) #FIXME: list_iterator +del X +#FIXME: list_iterator +a['DictionaryItemIteratorType'] = iter(type.__dict__.items()) +a['DictionaryKeyIteratorType'] = iter(type.__dict__.keys()) +a['DictionaryValueIteratorType'] = iter(type.__dict__.values()) +if sys.hexversion >= 0x30800a0: + a["DictReversekeyiteratorType"] = reversed({}.keys()) + a["DictReversevalueiteratorType"] = reversed({}.values()) + a["DictReverseitemiteratorType"] = reversed({}.items()) + +try: + import symtable + #FIXME: fails to pickle + x["SymtableEntryType"] = symtable.symtable("", "string", "exec")._table +except ImportError: + pass + +if sys.hexversion >= 0x30a00a0 and not IS_PYPY: + x['LineIteratorType'] = compile('3', '', 'eval').co_lines() + +if sys.hexversion >= 0x30b00b0 and not IS_PYPY: + from types import GenericAlias + d["GenericAliasIteratorType"] = iter(GenericAlias(list, (int,))) + x['PositionsIteratorType'] = compile('3', '', 'eval').co_positions() + +# data types (CH 8) +a['PrettyPrinterType'] = pprint.PrettyPrinter() +# file and directory access (CH 10) +a['TemporaryFileType'] = _tmpf +# data compression and archiving (CH 12) +x['GzipFileType'] = gzip.GzipFile(fileobj=_fileW) +# generic operating system services (CH 15) +a['StreamHandlerType'] = logging.StreamHandler() +# numeric and mathematical types (CH 9) +z = a if sys.hexversion < 0x30e00a1 else x +z['CountType'] = itertools.count(0) #FIXME: __reduce__ removed in 3.14.0a1 +z['ChainType'] = itertools.chain('0','1') +z['ProductType'] = itertools.product('0','1') +z['CycleType'] = itertools.cycle('0') +z['PermutationsType'] = itertools.permutations('0') +z['CombinationsType'] = itertools.combinations('0',1) +z['RepeatType'] = itertools.repeat(0) +z['CompressType'] = itertools.compress('0',[1]) +del z +#XXX: ...and etc + +# -- dill fails on all below here ------------------------------------------- +# types module (part of CH 8) +x['GeneratorType'] = _generator = _function(1) #XXX: priority +x['FrameType'] = _generator.gi_frame #XXX: inspect.currentframe() +x['TracebackType'] = _function2()[1] #(see: inspect.getouterframes,getframeinfo) +# other (concrete) object types +# (also: Capsule / CObject ?) +# built-in functions (CH 2) +# built-in types (CH 5) +# string services (CH 7) +x['StructType'] = struct.Struct('c') +x['CallableIteratorType'] = _srepattern.finditer('') +x['SREMatchType'] = _srepattern.match('') +x['SREScannerType'] = _srepattern.scanner('') +x['StreamReader'] = codecs.StreamReader(_cstrI) #XXX: ... and etc +# python object persistence (CH 11) +# x['DbShelveType'] = shelve.open('foo','n')#,protocol=2) #XXX: delete foo +if HAS_ALL: + z = a if IS_PYPY else x + z['DbmType'] = dbm.open(_tempfile,'n') + del z +# x['DbCursorType'] = _dbcursor = anydbm.open('foo','n') #XXX: delete foo +# x['DbType'] = _dbcursor.db +# data compression and archiving (CH 12) +x['ZlibCompressType'] = zlib.compressobj() +x['ZlibDecompressType'] = zlib.decompressobj() +# file formats (CH 13) +x['CSVReaderType'] = csv.reader(_cstrI) +x['CSVWriterType'] = csv.writer(_cstrO) +x['CSVDictReaderType'] = csv.DictReader(_cstrI) +x['CSVDictWriterType'] = csv.DictWriter(_cstrO,{}) +# cryptographic services (CH 14) +x['HashType'] = hashlib.md5() +if (sys.hexversion < 0x30800a1): + x['HMACType'] = hmac.new(_in) +else: + x['HMACType'] = hmac.new(_in, digestmod='md5') +# generic operating system services (CH 15) +if HAS_CURSES: pass + #x['CursesWindowType'] = _curwin = curses.initscr() #FIXME: messes up tty + #x['CursesTextPadType'] = textpad.Textbox(_curwin) + #x['CursesPanelType'] = panel.new_panel(_curwin) +if HAS_CTYPES: + x['CCharPType'] = ctypes.c_char_p() + x['CWCharPType'] = ctypes.c_wchar_p() + x['CVoidPType'] = ctypes.c_void_p() + if sys.platform[:3] == 'win': + x['CDLLType'] = _cdll = ctypes.cdll.msvcrt + else: + x['CDLLType'] = _cdll = ctypes.CDLL(None) + if not IS_PYPY: + x['PyDLLType'] = _pydll = ctypes.pythonapi + x['FuncPtrType'] = _cdll._FuncPtr() + x['CCharArrayType'] = ctypes.create_string_buffer(1) + x['CWCharArrayType'] = ctypes.create_unicode_buffer(1) + x['CParamType'] = ctypes.byref(_cchar) + x['LPCCharType'] = ctypes.pointer(_cchar) + x['LPCCharObjType'] = _lpchar = ctypes.POINTER(ctypes.c_char) + x['NullPtrType'] = _lpchar() + x['NullPyObjectType'] = ctypes.py_object() + x['PyObjectType'] = ctypes.py_object(lambda :None) + z = a if IS_PYPY else x + z['FieldType'] = _field = _Struct._field + z['CFUNCTYPEType'] = _cfunc = ctypes.CFUNCTYPE(ctypes.c_char) + if sys.hexversion < 0x30c00b3: + x['CFunctionType'] = _cfunc(str) + del z +# numeric and mathematical types (CH 9) +a['MethodCallerType'] = operator.methodcaller('mro') # 2.6 +# built-in types (CH 5) +x['MemoryType'] = memoryview(_in) # 2.7 +x['MemoryType2'] = memoryview(bytearray(_in)) # 2.7 +d['DictItemsType'] = _dict.items() # 2.7 +d['DictKeysType'] = _dict.keys() # 2.7 +d['DictValuesType'] = _dict.values() # 2.7 +# generic operating system services (CH 15) +a['RawTextHelpFormatterType'] = argparse.RawTextHelpFormatter('PROG') +a['RawDescriptionHelpFormatterType'] = argparse.RawDescriptionHelpFormatter('PROG') +a['ArgDefaultsHelpFormatterType'] = argparse.ArgumentDefaultsHelpFormatter('PROG') +z = a if IS_PYPY else x +z['CmpKeyType'] = _cmpkey = functools.cmp_to_key(_methodwrap) # 2.7, >=3.2 +z['CmpKeyObjType'] = _cmpkey('0') #2.7, >=3.2 +del z +# oddities: removed, etc +x['BufferType'] = x['MemoryType'] + +from dill._dill import _testcapsule +if _testcapsule is not None: + d['PyCapsuleType'] = _testcapsule +del _testcapsule + +if hasattr(dataclasses, '_HAS_DEFAULT_FACTORY'): + a['DataclassesHasDefaultFactoryType'] = dataclasses._HAS_DEFAULT_FACTORY + +if hasattr(dataclasses, 'MISSING'): + a['DataclassesMissingType'] = dataclasses.MISSING + +if hasattr(dataclasses, 'KW_ONLY'): + a['DataclassesKWOnlyType'] = dataclasses.KW_ONLY + +if hasattr(dataclasses, '_FIELD_BASE'): + a['DataclassesFieldBaseType'] = dataclasses._FIELD + +# -- cleanup ---------------------------------------------------------------- +a.update(d) # registered also succeed +if sys.platform[:3] == 'win': + os.close(_filedescrip) # required on win32 +os.remove(_tempfile) + + +# EOF diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/dill/detect.py b/bioagent-bench/.venv/lib/python3.14/site-packages/dill/detect.py new file mode 100644 index 0000000000000000000000000000000000000000..cdd428765dfbe427e3423e3a8294260a47b2751d --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/dill/detect.py @@ -0,0 +1,287 @@ +#!/usr/bin/env python +# +# Author: Mike McKerns (mmckerns @caltech and @uqfoundation) +# Copyright (c) 2008-2016 California Institute of Technology. +# Copyright (c) 2016-2026 The Uncertainty Quantification Foundation. +# License: 3-clause BSD. The full license text is available at: +# - https://github.com/uqfoundation/dill/blob/master/LICENSE +""" +Methods for detecting objects leading to pickling failures. +""" + +import dis +from inspect import ismethod, isfunction, istraceback, isframe, iscode + +from .pointers import parent, reference, at, parents, children +from .logger import trace + +__all__ = ['baditems','badobjects','badtypes','code','errors','freevars', + 'getmodule','globalvars','nestedcode','nestedglobals','outermost', + 'referredglobals','referrednested','trace','varnames'] + +def getmodule(object, _filename=None, force=False): + """get the module of the object""" + from inspect import getmodule as getmod + module = getmod(object, _filename) + if module or not force: return module + import builtins + from .source import getname + name = getname(object, force=True) + return builtins if name in vars(builtins).keys() else None + +def outermost(func): # is analogous to getsource(func,enclosing=True) + """get outermost enclosing object (i.e. the outer function in a closure) + + NOTE: this is the object-equivalent of getsource(func, enclosing=True) + """ + if ismethod(func): + _globals = func.__func__.__globals__ or {} + elif isfunction(func): + _globals = func.__globals__ or {} + else: + return #XXX: or raise? no matches + _globals = _globals.items() + # get the enclosing source + from .source import getsourcelines + try: lines,lnum = getsourcelines(func, enclosing=True) + except Exception: #TypeError, IOError + lines,lnum = [],None + code = ''.join(lines) + # get all possible names,objects that are named in the enclosing source + _locals = ((name,obj) for (name,obj) in _globals if name in code) + # now only save the objects that generate the enclosing block + for name,obj in _locals: #XXX: don't really need 'name' + try: + if getsourcelines(obj) == (lines,lnum): return obj + except Exception: #TypeError, IOError + pass + return #XXX: or raise? no matches + +def nestedcode(func, recurse=True): #XXX: or return dict of {co_name: co} ? + """get the code objects for any nested functions (e.g. in a closure)""" + func = code(func) + if not iscode(func): return [] #XXX: or raise? no matches + nested = set() + for co in func.co_consts: + if co is None: continue + co = code(co) + if co: + nested.add(co) + if recurse: nested |= set(nestedcode(co, recurse=True)) + return list(nested) + +def code(func): + """get the code object for the given function or method + + NOTE: use dill.source.getsource(CODEOBJ) to get the source code + """ + if ismethod(func): func = func.__func__ + if isfunction(func): func = func.__code__ + if istraceback(func): func = func.tb_frame + if isframe(func): func = func.f_code + if iscode(func): return func + return + +#XXX: ugly: parse dis.dis for name after " len(referrednested(func)), try calling func(). + If possible, python builds code objects, but delays building functions + until func() is called. + """ + import gc + funcs = set() + # get the code objects, and try to track down by referrence + for co in nestedcode(func, recurse): + # look for function objects that refer to the code object + for obj in gc.get_referrers(co): + # get methods + _ = getattr(obj, '__func__', None) # ismethod + if getattr(_, '__code__', None) is co: funcs.add(obj) + # get functions + elif getattr(obj, '__code__', None) is co: funcs.add(obj) + # get frame objects + elif getattr(obj, 'f_code', None) is co: funcs.add(obj) + # get code objects + elif hasattr(obj, 'co_code') and obj is co: funcs.add(obj) +# frameobjs => func.__code__.co_varnames not in func.__code__.co_cellvars +# funcobjs => func.__code__.co_cellvars not in func.__code__.co_varnames +# frameobjs are not found, however funcobjs are... +# (see: test_mixins.quad ... and test_mixins.wtf) +# after execution, code objects get compiled, and then may be found by gc + return list(funcs) + + +def freevars(func): + """get objects defined in enclosing code that are referred to by func + + returns a dict of {name:object}""" + if ismethod(func): func = func.__func__ + if isfunction(func): + closures = func.__closure__ or () + func = func.__code__.co_freevars # get freevars + else: + return {} + + def get_cell_contents(): + for name, c in zip(func, closures): + try: + cell_contents = c.cell_contents + except ValueError: # cell is empty + continue + yield name, c.cell_contents + + return dict(get_cell_contents()) + +# thanks to Davies Liu for recursion of globals +def nestedglobals(func, recurse=True): + """get the names of any globals found within func""" + func = code(func) + if func is None: return list() + import sys + from .temp import capture + CAN_NULL = sys.hexversion >= 0x30b00a7 # NULL may be prepended >= 3.11a7 + names = set() + with capture('stdout') as out: + try: + dis.dis(func) #XXX: dis.dis(None) disassembles last traceback + except IndexError: + pass #FIXME: HACK for IS_PYPY (3.11) + for line in out.getvalue().splitlines(): + if '_GLOBAL' in line: + name = line.split('(')[-1].split(')')[0] + if CAN_NULL: + names.add(name.replace('NULL + ', '').replace(' + NULL', '')) + else: + names.add(name) + for co in getattr(func, 'co_consts', tuple()): + if co and recurse and iscode(co): + names.update(nestedglobals(co, recurse=True)) + return list(names) + +def referredglobals(func, recurse=True, builtin=False): + """get the names of objects in the global scope referred to by func""" + return globalvars(func, recurse, builtin).keys() + +def globalvars(func, recurse=True, builtin=False): + """get objects defined in global scope that are referred to by func + + return a dict of {name:object}""" + if ismethod(func): func = func.__func__ + if isfunction(func): + globs = vars(getmodule(sum)).copy() if builtin else {} + # get references from within closure + orig_func, func = func, set() + for obj in orig_func.__closure__ or {}: + try: + cell_contents = obj.cell_contents + except ValueError: # cell is empty + pass + else: + _vars = globalvars(cell_contents, recurse, builtin) or {} + func.update(_vars) #XXX: (above) be wary of infinte recursion? + globs.update(_vars) + # get globals + globs.update(orig_func.__globals__ or {}) + # get names of references + if not recurse: + func.update(orig_func.__code__.co_names) + else: + func.update(nestedglobals(orig_func.__code__)) + # find globals for all entries of func + for key in func.copy(): #XXX: unnecessary...? + nested_func = globs.get(key) + if nested_func is orig_func: + #func.remove(key) if key in func else None + continue #XXX: globalvars(func, False)? + func.update(globalvars(nested_func, True, builtin)) + elif iscode(func): + globs = vars(getmodule(sum)).copy() if builtin else {} + #globs.update(globals()) + if not recurse: + func = func.co_names # get names + else: + orig_func = func.co_name # to stop infinite recursion + func = set(nestedglobals(func)) + # find globals for all entries of func + for key in func.copy(): #XXX: unnecessary...? + if key is orig_func: + #func.remove(key) if key in func else None + continue #XXX: globalvars(func, False)? + nested_func = globs.get(key) + func.update(globalvars(nested_func, True, builtin)) + else: + return {} + #NOTE: if name not in __globals__, then we skip it... + return dict((name,globs[name]) for name in func if name in globs) + + +def varnames(func): + """get names of variables defined by func + + returns a tuple (local vars, local vars referrenced by nested functions)""" + func = code(func) + if not iscode(func): + return () #XXX: better ((),())? or None? + return func.co_varnames, func.co_cellvars + + +def baditems(obj, exact=False, safe=False): #XXX: obj=globals() ? + """get items in object that fail to pickle""" + if not hasattr(obj,'__iter__'): # is not iterable + return [j for j in (badobjects(obj,0,exact,safe),) if j is not None] + obj = obj.values() if getattr(obj,'values',None) else obj + _obj = [] # can't use a set, as items may be unhashable + [_obj.append(badobjects(i,0,exact,safe)) for i in obj if i not in _obj] + return [j for j in _obj if j is not None] + + +def badobjects(obj, depth=0, exact=False, safe=False): + """get objects that fail to pickle""" + from dill import pickles + if not depth: + if pickles(obj,exact,safe): return None + return obj + return dict(((attr, badobjects(getattr(obj,attr),depth-1,exact,safe)) \ + for attr in dir(obj) if not pickles(getattr(obj,attr),exact,safe))) + +def badtypes(obj, depth=0, exact=False, safe=False): + """get types for objects that fail to pickle""" + from dill import pickles + if not depth: + if pickles(obj,exact,safe): return None + return type(obj) + return dict(((attr, badtypes(getattr(obj,attr),depth-1,exact,safe)) \ + for attr in dir(obj) if not pickles(getattr(obj,attr),exact,safe))) + +def errors(obj, depth=0, exact=False, safe=False): + """get errors for objects that fail to pickle""" + from dill import pickles, copy + if not depth: + try: + pik = copy(obj) + if exact: + assert pik == obj, \ + "Unpickling produces %s instead of %s" % (pik,obj) + assert type(pik) == type(obj), \ + "Unpickling produces %s instead of %s" % (type(pik),type(obj)) + return None + except Exception: + import sys + return sys.exc_info()[1] + _dict = {} + for attr in dir(obj): + try: + _attr = getattr(obj,attr) + except Exception: + import sys + _dict[attr] = sys.exc_info()[1] + continue + if not pickles(_attr,exact,safe): + _dict[attr] = errors(_attr,depth-1,exact,safe) + return _dict + + +# EOF diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/dill/objtypes.py b/bioagent-bench/.venv/lib/python3.14/site-packages/dill/objtypes.py new file mode 100644 index 0000000000000000000000000000000000000000..bf88a47fdd07d3c6cbae71e8599e7f3e2180d442 --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/dill/objtypes.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python +# +# Author: Mike McKerns (mmckerns @caltech and @uqfoundation) +# Copyright (c) 2008-2016 California Institute of Technology. +# Copyright (c) 2016-2026 The Uncertainty Quantification Foundation. +# License: 3-clause BSD. The full license text is available at: +# - https://github.com/uqfoundation/dill/blob/master/LICENSE +""" +all Python Standard Library object types (currently: CH 1-15 @ 2.7) +and some other common object types (i.e. numpy.ndarray) + +to load more objects and types, use dill.load_types() +""" + +# non-local import of dill.objects +from dill import objects +for _type in objects.keys(): + exec("%s = type(objects['%s'])" % (_type,_type)) + +del objects +try: + del _type +except NameError: + pass diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/dill/pointers.py b/bioagent-bench/.venv/lib/python3.14/site-packages/dill/pointers.py new file mode 100644 index 0000000000000000000000000000000000000000..d27745febe7dfa357e295b9f4b8dcaedcb4f3496 --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/dill/pointers.py @@ -0,0 +1,122 @@ +#!/usr/bin/env python +# +# Author: Mike McKerns (mmckerns @caltech and @uqfoundation) +# Copyright (c) 2008-2016 California Institute of Technology. +# Copyright (c) 2016-2026 The Uncertainty Quantification Foundation. +# License: 3-clause BSD. The full license text is available at: +# - https://github.com/uqfoundation/dill/blob/master/LICENSE + +__all__ = ['parent', 'reference', 'at', 'parents', 'children'] + +import gc +import sys + +from ._dill import _proxy_helper as reference +from ._dill import _locate_object as at + +def parent(obj, objtype, ignore=()): + """ +>>> listiter = iter([4,5,6,7]) +>>> obj = parent(listiter, list) +>>> obj == [4,5,6,7] # actually 'is', but don't have handle any longer +True + +NOTE: objtype can be a single type (e.g. int or list) or a tuple of types. + +WARNING: if obj is a sequence (e.g. list), may produce unexpected results. +Parent finds *one* parent (e.g. the last member of the sequence). + """ + depth = 1 #XXX: always looking for the parent (only, right?) + chain = parents(obj, objtype, depth, ignore) + parent = chain.pop() + if parent is obj: + return None + return parent + + +def parents(obj, objtype, depth=1, ignore=()): #XXX: objtype=object ? + """Find the chain of referents for obj. Chain will end with obj. + + objtype: an object type or tuple of types to search for + depth: search depth (e.g. depth=2 is 'grandparents') + ignore: an object or tuple of objects to ignore in the search + """ + edge_func = gc.get_referents # looking for refs, not back_refs + predicate = lambda x: isinstance(x, objtype) # looking for parent type + #if objtype is None: predicate = lambda x: True #XXX: in obj.mro() ? + ignore = (ignore,) if not hasattr(ignore, '__len__') else ignore + ignore = (id(obj) for obj in ignore) + chain = find_chain(obj, predicate, edge_func, depth)[::-1] + #XXX: should pop off obj... ? + return chain + + +def children(obj, objtype, depth=1, ignore=()): #XXX: objtype=object ? + """Find the chain of referrers for obj. Chain will start with obj. + + objtype: an object type or tuple of types to search for + depth: search depth (e.g. depth=2 is 'grandchildren') + ignore: an object or tuple of objects to ignore in the search + + NOTE: a common thing to ignore is all globals, 'ignore=(globals(),)' + + NOTE: repeated calls may yield different results, as python stores + the last value in the special variable '_'; thus, it is often good + to execute something to replace '_' (e.g. >>> 1+1). + """ + edge_func = gc.get_referrers # looking for back_refs, not refs + predicate = lambda x: isinstance(x, objtype) # looking for child type + #if objtype is None: predicate = lambda x: True #XXX: in obj.mro() ? + ignore = (ignore,) if not hasattr(ignore, '__len__') else ignore + ignore = (id(obj) for obj in ignore) + chain = find_chain(obj, predicate, edge_func, depth, ignore) + #XXX: should pop off obj... ? + return chain + + +# more generic helper function (cut-n-paste from objgraph) +# Source at http://mg.pov.lt/objgraph/ +# Copyright (c) 2008-2010 Marius Gedminas +# Copyright (c) 2010 Stefano Rivera +# Released under the MIT licence (see objgraph/objgrah.py) + +def find_chain(obj, predicate, edge_func, max_depth=20, extra_ignore=()): + queue = [obj] + depth = {id(obj): 0} + parent = {id(obj): None} + ignore = set(extra_ignore) + ignore.add(id(extra_ignore)) + ignore.add(id(queue)) + ignore.add(id(depth)) + ignore.add(id(parent)) + ignore.add(id(ignore)) + ignore.add(id(sys._getframe())) # this function + ignore.add(id(sys._getframe(1))) # find_chain/find_backref_chain, likely + gc.collect() + while queue: + target = queue.pop(0) + if predicate(target): + chain = [target] + while parent[id(target)] is not None: + target = parent[id(target)] + chain.append(target) + return chain + tdepth = depth[id(target)] + if tdepth < max_depth: + referrers = edge_func(target) + ignore.add(id(referrers)) + for source in referrers: + if id(source) in ignore: + continue + if id(source) not in depth: + depth[id(source)] = tdepth + 1 + parent[id(source)] = target + queue.append(source) + return [obj] # not found + + +# backward compatibility +refobject = at + + +# EOF diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/dill/session.py b/bioagent-bench/.venv/lib/python3.14/site-packages/dill/session.py new file mode 100644 index 0000000000000000000000000000000000000000..b5dd2ff8d4b3b1af84df9f07fba731be4011712f --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/dill/session.py @@ -0,0 +1,612 @@ +#!/usr/bin/env python +# +# Author: Mike McKerns (mmckerns @caltech and @uqfoundation) +# Author: Leonardo Gama (@leogama) +# Copyright (c) 2008-2015 California Institute of Technology. +# Copyright (c) 2016-2026 The Uncertainty Quantification Foundation. +# License: 3-clause BSD. The full license text is available at: +# - https://github.com/uqfoundation/dill/blob/master/LICENSE +""" +Pickle and restore the intepreter session. +""" + +__all__ = [ + 'dump_module', 'load_module', 'load_module_asdict', + 'dump_session', 'load_session' # backward compatibility +] + +import re +import os +import sys +import warnings +import pathlib +import tempfile + +TEMPDIR = pathlib.PurePath(tempfile.gettempdir()) + +# Type hints. +from typing import Optional, Union + +from dill import _dill, Pickler, Unpickler +from ._dill import ( + BuiltinMethodType, FunctionType, MethodType, ModuleType, TypeType, + _import_module, _is_builtin_module, _is_imported_module, _main_module, + _reverse_typemap, __builtin__, UnpicklingError, +) + +def _module_map(): + """get map of imported modules""" + from collections import defaultdict + from types import SimpleNamespace + modmap = SimpleNamespace( + by_name=defaultdict(list), + by_id=defaultdict(list), + top_level={}, + ) + for modname, module in sys.modules.items(): + if modname in ('__main__', '__mp_main__') or not isinstance(module, ModuleType): + continue + if '.' not in modname: + modmap.top_level[id(module)] = modname + for objname, modobj in module.__dict__.items(): + modmap.by_name[objname].append((modobj, modname)) + modmap.by_id[id(modobj)].append((modobj, objname, modname)) + return modmap + +IMPORTED_AS_TYPES = (ModuleType, TypeType, FunctionType, MethodType, BuiltinMethodType) +if 'PyCapsuleType' in _reverse_typemap: + IMPORTED_AS_TYPES += (_reverse_typemap['PyCapsuleType'],) +IMPORTED_AS_MODULES = ('ctypes', 'typing', 'subprocess', 'threading', + r'concurrent\.futures(\.\w+)?', r'multiprocessing(\.\w+)?') +IMPORTED_AS_MODULES = tuple(re.compile(x) for x in IMPORTED_AS_MODULES) + +def _lookup_module(modmap, name, obj, main_module): + """lookup name or id of obj if module is imported""" + for modobj, modname in modmap.by_name[name]: + if modobj is obj and sys.modules[modname] is not main_module: + return modname, name + __module__ = getattr(obj, '__module__', None) + if isinstance(obj, IMPORTED_AS_TYPES) or (__module__ is not None + and any(regex.fullmatch(__module__) for regex in IMPORTED_AS_MODULES)): + for modobj, objname, modname in modmap.by_id[id(obj)]: + if sys.modules[modname] is not main_module: + return modname, objname + return None, None + +def _stash_modules(main_module): + modmap = _module_map() + newmod = ModuleType(main_module.__name__) + + imported = [] + imported_as = [] + imported_top_level = [] # keep separated for backward compatibility + original = {} + for name, obj in main_module.__dict__.items(): + if obj is main_module: + original[name] = newmod # self-reference + elif obj is main_module.__dict__: + original[name] = newmod.__dict__ + # Avoid incorrectly matching a singleton value in another package (ex.: __doc__). + elif any(obj is singleton for singleton in (None, False, True)) \ + or isinstance(obj, ModuleType) and _is_builtin_module(obj): # always saved by ref + original[name] = obj + else: + source_module, objname = _lookup_module(modmap, name, obj, main_module) + if source_module is not None: + if objname == name: + imported.append((source_module, name)) + else: + imported_as.append((source_module, objname, name)) + else: + try: + imported_top_level.append((modmap.top_level[id(obj)], name)) + except KeyError: + original[name] = obj + + if len(original) < len(main_module.__dict__): + newmod.__dict__.update(original) + newmod.__dill_imported = imported + newmod.__dill_imported_as = imported_as + newmod.__dill_imported_top_level = imported_top_level + if getattr(newmod, '__loader__', None) is None and _is_imported_module(main_module): + # Trick _is_imported_module() to force saving as an imported module. + newmod.__loader__ = True # will be discarded by save_module() + return newmod + else: + return main_module + +def _restore_modules(unpickler, main_module): + try: + for modname, name in main_module.__dict__.pop('__dill_imported'): + main_module.__dict__[name] = unpickler.find_class(modname, name) + for modname, objname, name in main_module.__dict__.pop('__dill_imported_as'): + main_module.__dict__[name] = unpickler.find_class(modname, objname) + for modname, name in main_module.__dict__.pop('__dill_imported_top_level'): + main_module.__dict__[name] = __import__(modname) + except KeyError: + pass + +#NOTE: 06/03/15 renamed main_module to main +def dump_module( + filename: Union[str, os.PathLike] = None, + module: Optional[Union[ModuleType, str]] = None, + refimported: bool = False, + **kwds +) -> None: + """Pickle the current state of :py:mod:`__main__` or another module to a file. + + Save the contents of :py:mod:`__main__` (e.g. from an interactive + interpreter session), an imported module, or a module-type object (e.g. + built with :py:class:`~types.ModuleType`), to a file. The pickled + module can then be restored with the function :py:func:`load_module`. + + Args: + filename: a path-like object or a writable stream. If `None` + (the default), write to a named file in a temporary directory. + module: a module object or the name of an importable module. If `None` + (the default), :py:mod:`__main__` is saved. + refimported: if `True`, all objects identified as having been imported + into the module's namespace are saved by reference. *Note:* this is + similar but independent from ``dill.settings[`byref`]``, as + ``refimported`` refers to virtually all imported objects, while + ``byref`` only affects select objects. + **kwds: extra keyword arguments passed to :py:class:`Pickler()`. + + Raises: + :py:exc:`PicklingError`: if pickling fails. + + Examples: + + - Save current interpreter session state: + + >>> import dill + >>> squared = lambda x: x*x + >>> dill.dump_module() # save state of __main__ to /tmp/session.pkl + + - Save the state of an imported/importable module: + + >>> import dill + >>> import pox + >>> pox.plus_one = lambda x: x+1 + >>> dill.dump_module('pox_session.pkl', module=pox) + + - Save the state of a non-importable, module-type object: + + >>> import dill + >>> from types import ModuleType + >>> foo = ModuleType('foo') + >>> foo.values = [1,2,3] + >>> import math + >>> foo.sin = math.sin + >>> dill.dump_module('foo_session.pkl', module=foo, refimported=True) + + - Restore the state of the saved modules: + + >>> import dill + >>> dill.load_module() + >>> squared(2) + 4 + >>> pox = dill.load_module('pox_session.pkl') + >>> pox.plus_one(1) + 2 + >>> foo = dill.load_module('foo_session.pkl') + >>> [foo.sin(x) for x in foo.values] + [0.8414709848078965, 0.9092974268256817, 0.1411200080598672] + + - Use `refimported` to save imported objects by reference: + + >>> import dill + >>> from html.entities import html5 + >>> type(html5), len(html5) + (dict, 2231) + >>> import io + >>> buf = io.BytesIO() + >>> dill.dump_module(buf) # saves __main__, with html5 saved by value + >>> len(buf.getvalue()) # pickle size in bytes + 71665 + >>> buf = io.BytesIO() + >>> dill.dump_module(buf, refimported=True) # html5 saved by reference + >>> len(buf.getvalue()) + 438 + + *Changed in version 0.3.6:* Function ``dump_session()`` was renamed to + ``dump_module()``. Parameters ``main`` and ``byref`` were renamed to + ``module`` and ``refimported``, respectively. + + Note: + Currently, ``dill.settings['byref']`` and ``dill.settings['recurse']`` + don't apply to this function. + """ + for old_par, par in [('main', 'module'), ('byref', 'refimported')]: + if old_par in kwds: + message = "The argument %r has been renamed %r" % (old_par, par) + if old_par == 'byref': + message += " to distinguish it from dill.settings['byref']" + warnings.warn(message + ".", PendingDeprecationWarning) + if locals()[par]: # the defaults are None and False + raise TypeError("both %r and %r arguments were used" % (par, old_par)) + refimported = kwds.pop('byref', refimported) + module = kwds.pop('main', module) + + from .settings import settings + protocol = settings['protocol'] + main = module + if main is None: + main = _main_module + elif isinstance(main, str): + main = _import_module(main) + if not isinstance(main, ModuleType): + raise TypeError("%r is not a module" % main) + if hasattr(filename, 'write'): + file = filename + else: + if filename is None: + filename = str(TEMPDIR/'session.pkl') + file = open(filename, 'wb') + try: + pickler = Pickler(file, protocol, **kwds) + pickler._original_main = main + if refimported: + main = _stash_modules(main) + pickler._main = main #FIXME: dill.settings are disabled + pickler._byref = False # disable pickling by name reference + pickler._recurse = False # disable pickling recursion for globals + pickler._session = True # is best indicator of when pickling a session + pickler._first_pass = True + pickler._main_modified = main is not pickler._original_main + pickler.dump(main) + finally: + if file is not filename: # if newly opened file + file.close() + return + +# Backward compatibility. +def dump_session(filename=None, main=None, byref=False, **kwds): + warnings.warn("dump_session() has been renamed dump_module()", PendingDeprecationWarning) + dump_module(filename, module=main, refimported=byref, **kwds) +dump_session.__doc__ = dump_module.__doc__ + +class _PeekableReader: + """lightweight stream wrapper that implements peek()""" + def __init__(self, stream): + self.stream = stream + def read(self, n): + return self.stream.read(n) + def readline(self): + return self.stream.readline() + def tell(self): + return self.stream.tell() + def close(self): + return self.stream.close() + def peek(self, n): + stream = self.stream + try: + if hasattr(stream, 'flush'): stream.flush() + position = stream.tell() + stream.seek(position) # assert seek() works before reading + chunk = stream.read(n) + stream.seek(position) + return chunk + except (AttributeError, OSError): + raise NotImplementedError("stream is not peekable: %r", stream) from None + +def _make_peekable(stream): + """return stream as an object with a peek() method""" + import io + if hasattr(stream, 'peek'): + return stream + if not (hasattr(stream, 'tell') and hasattr(stream, 'seek')): + try: + return io.BufferedReader(stream) + except Exception: + pass + return _PeekableReader(stream) + +def _identify_module(file, main=None): + """identify the name of the module stored in the given file-type object""" + from pickletools import genops + UNICODE = {'UNICODE', 'BINUNICODE', 'SHORT_BINUNICODE'} + found_import = False + try: + for opcode, arg, pos in genops(file.peek(256)): + if not found_import: + if opcode.name in ('GLOBAL', 'SHORT_BINUNICODE') and \ + arg.endswith('_import_module'): + found_import = True + else: + if opcode.name in UNICODE: + return arg + else: + raise UnpicklingError("reached STOP without finding main module") + except (NotImplementedError, ValueError) as error: + # ValueError occours when the end of the chunk is reached (without a STOP). + if isinstance(error, NotImplementedError) and main is not None: + # file is not peekable, but we have main. + return None + raise UnpicklingError("unable to identify main module") from error + +def load_module( + filename: Union[str, os.PathLike] = None, + module: Optional[Union[ModuleType, str]] = None, + **kwds +) -> Optional[ModuleType]: + """Update the selected module (default is :py:mod:`__main__`) with + the state saved at ``filename``. + + Restore a module to the state saved with :py:func:`dump_module`. The + saved module can be :py:mod:`__main__` (e.g. an interpreter session), + an imported module, or a module-type object (e.g. created with + :py:class:`~types.ModuleType`). + + When restoring the state of a non-importable module-type object, the + current instance of this module may be passed as the argument ``main``. + Otherwise, a new instance is created with :py:class:`~types.ModuleType` + and returned. + + Args: + filename: a path-like object or a readable stream. If `None` + (the default), read from a named file in a temporary directory. + module: a module object or the name of an importable module; + the module name and kind (i.e. imported or non-imported) must + match the name and kind of the module stored at ``filename``. + **kwds: extra keyword arguments passed to :py:class:`Unpickler()`. + + Raises: + :py:exc:`UnpicklingError`: if unpickling fails. + :py:exc:`ValueError`: if the argument ``main`` and module saved + at ``filename`` are incompatible. + + Returns: + A module object, if the saved module is not :py:mod:`__main__` or + a module instance wasn't provided with the argument ``main``. + + Examples: + + - Save the state of some modules: + + >>> import dill + >>> squared = lambda x: x*x + >>> dill.dump_module() # save state of __main__ to /tmp/session.pkl + >>> + >>> import pox # an imported module + >>> pox.plus_one = lambda x: x+1 + >>> dill.dump_module('pox_session.pkl', module=pox) + >>> + >>> from types import ModuleType + >>> foo = ModuleType('foo') # a module-type object + >>> foo.values = [1,2,3] + >>> import math + >>> foo.sin = math.sin + >>> dill.dump_module('foo_session.pkl', module=foo, refimported=True) + + - Restore the state of the interpreter: + + >>> import dill + >>> dill.load_module() # updates __main__ from /tmp/session.pkl + >>> squared(2) + 4 + + - Load the saved state of an importable module: + + >>> import dill + >>> pox = dill.load_module('pox_session.pkl') + >>> pox.plus_one(1) + 2 + >>> import sys + >>> pox in sys.modules.values() + True + + - Load the saved state of a non-importable module-type object: + + >>> import dill + >>> foo = dill.load_module('foo_session.pkl') + >>> [foo.sin(x) for x in foo.values] + [0.8414709848078965, 0.9092974268256817, 0.1411200080598672] + >>> import math + >>> foo.sin is math.sin # foo.sin was saved by reference + True + >>> import sys + >>> foo in sys.modules.values() + False + + - Update the state of a non-importable module-type object: + + >>> import dill + >>> from types import ModuleType + >>> foo = ModuleType('foo') + >>> foo.values = ['a','b'] + >>> foo.sin = lambda x: x*x + >>> dill.load_module('foo_session.pkl', module=foo) + >>> [foo.sin(x) for x in foo.values] + [0.8414709848078965, 0.9092974268256817, 0.1411200080598672] + + *Changed in version 0.3.6:* Function ``load_session()`` was renamed to + ``load_module()``. Parameter ``main`` was renamed to ``module``. + + See also: + :py:func:`load_module_asdict` to load the contents of module saved + with :py:func:`dump_module` into a dictionary. + """ + if 'main' in kwds: + warnings.warn( + "The argument 'main' has been renamed 'module'.", + PendingDeprecationWarning + ) + if module is not None: + raise TypeError("both 'module' and 'main' arguments were used") + module = kwds.pop('main') + main = module + if hasattr(filename, 'read'): + file = filename + else: + if filename is None: + filename = str(TEMPDIR/'session.pkl') + file = open(filename, 'rb') + try: + file = _make_peekable(file) + #FIXME: dill.settings are disabled + unpickler = Unpickler(file, **kwds) + unpickler._session = True + + # Resolve unpickler._main + pickle_main = _identify_module(file, main) + if main is None and pickle_main is not None: + main = pickle_main + if isinstance(main, str): + if main.startswith('__runtime__.'): + # Create runtime module to load the session into. + main = ModuleType(main.partition('.')[-1]) + else: + main = _import_module(main) + if main is not None: + if not isinstance(main, ModuleType): + raise TypeError("%r is not a module" % main) + unpickler._main = main + else: + main = unpickler._main + + # Check against the pickle's main. + is_main_imported = _is_imported_module(main) + if pickle_main is not None: + is_runtime_mod = pickle_main.startswith('__runtime__.') + if is_runtime_mod: + pickle_main = pickle_main.partition('.')[-1] + error_msg = "can't update{} module{} %r with the saved state of{} module{} %r" + if is_runtime_mod and is_main_imported: + raise ValueError( + error_msg.format(" imported", "", "", "-type object") + % (main.__name__, pickle_main) + ) + if not is_runtime_mod and not is_main_imported: + raise ValueError( + error_msg.format("", "-type object", " imported", "") + % (pickle_main, main.__name__) + ) + if main.__name__ != pickle_main: + raise ValueError(error_msg.format("", "", "", "") % (main.__name__, pickle_main)) + + # This is for find_class() to be able to locate it. + if not is_main_imported: + runtime_main = '__runtime__.%s' % main.__name__ + sys.modules[runtime_main] = main + + loaded = unpickler.load() + finally: + if not hasattr(filename, 'read'): # if newly opened file + file.close() + try: + del sys.modules[runtime_main] + except (KeyError, NameError): + pass + assert loaded is main + _restore_modules(unpickler, main) + if main is _main_module or main is module: + return None + else: + return main + +# Backward compatibility. +def load_session(filename=None, main=None, **kwds): + warnings.warn("load_session() has been renamed load_module().", PendingDeprecationWarning) + load_module(filename, module=main, **kwds) +load_session.__doc__ = load_module.__doc__ + +def load_module_asdict( + filename: Union[str, os.PathLike] = None, + update: bool = False, + **kwds +) -> dict: + """ + Load the contents of a saved module into a dictionary. + + ``load_module_asdict()`` is the near-equivalent of:: + + lambda filename: vars(dill.load_module(filename)).copy() + + however, does not alter the original module. Also, the path of + the loaded module is stored in the ``__session__`` attribute. + + Args: + filename: a path-like object or a readable stream. If `None` + (the default), read from a named file in a temporary directory. + update: if `True`, initialize the dictionary with the current state + of the module prior to loading the state stored at filename. + **kwds: extra keyword arguments passed to :py:class:`Unpickler()` + + Raises: + :py:exc:`UnpicklingError`: if unpickling fails + + Returns: + A copy of the restored module's dictionary. + + Note: + If ``update`` is True, the corresponding module may first be imported + into the current namespace before the saved state is loaded from + filename to the dictionary. Note that any module that is imported into + the current namespace as a side-effect of using ``update`` will not be + modified by loading the saved module in filename to a dictionary. + + Example: + >>> import dill + >>> alist = [1, 2, 3] + >>> anum = 42 + >>> dill.dump_module() + >>> anum = 0 + >>> new_var = 'spam' + >>> main = dill.load_module_asdict() + >>> main['__name__'], main['__session__'] + ('__main__', '/tmp/session.pkl') + >>> main is globals() # loaded objects don't reference globals + False + >>> main['alist'] == alist + True + >>> main['alist'] is alist # was saved by value + False + >>> main['anum'] == anum # changed after the session was saved + False + >>> new_var in main # would be True if the option 'update' was set + False + """ + if 'module' in kwds: + raise TypeError("'module' is an invalid keyword argument for load_module_asdict()") + if hasattr(filename, 'read'): + file = filename + else: + if filename is None: + filename = str(TEMPDIR/'session.pkl') + file = open(filename, 'rb') + try: + file = _make_peekable(file) + main_name = _identify_module(file) + old_main = sys.modules.get(main_name) + main = ModuleType(main_name) + if update: + if old_main is None: + old_main = _import_module(main_name) + main.__dict__.update(old_main.__dict__) + else: + main.__builtins__ = __builtin__ + sys.modules[main_name] = main + load_module(file, **kwds) + finally: + if not hasattr(filename, 'read'): # if newly opened file + file.close() + try: + if old_main is None: + del sys.modules[main_name] + else: + sys.modules[main_name] = old_main + except NameError: # failed before setting old_main + pass + main.__session__ = str(filename) + return main.__dict__ + + +# Internal exports for backward compatibility with dill v0.3.5.1 +# Can't be placed in dill._dill because of circular import problems. +for name in ( + '_lookup_module', '_module_map', '_restore_modules', '_stash_modules', + 'dump_session', 'load_session' # backward compatibility functions +): + setattr(_dill, name, globals()[name]) +del name diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/dill/settings.py b/bioagent-bench/.venv/lib/python3.14/site-packages/dill/settings.py new file mode 100644 index 0000000000000000000000000000000000000000..eb07feffc197c60262c049e6adc3fd4c2aa0e822 --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/dill/settings.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python +# +# Author: Mike McKerns (mmckerns @caltech and @uqfoundation) +# Copyright (c) 2008-2016 California Institute of Technology. +# Copyright (c) 2016-2026 The Uncertainty Quantification Foundation. +# License: 3-clause BSD. The full license text is available at: +# - https://github.com/uqfoundation/dill/blob/master/LICENSE +""" +global settings for Pickler +""" + +from pickle import DEFAULT_PROTOCOL + +settings = { + #'main' : None, + 'protocol' : DEFAULT_PROTOCOL, + 'byref' : False, + #'strictio' : False, + 'fmode' : 0, #HANDLE_FMODE + 'recurse' : False, + 'ignore' : False, +} + +del DEFAULT_PROTOCOL + diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/dill/source.py b/bioagent-bench/.venv/lib/python3.14/site-packages/dill/source.py new file mode 100644 index 0000000000000000000000000000000000000000..b77d9fbd7a0ff92dc5d24721b9cba712f10cf067 --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/dill/source.py @@ -0,0 +1,1025 @@ +#!/usr/bin/env python +# +# Author: Mike McKerns (mmckerns @caltech and @uqfoundation) +# Copyright (c) 2008-2016 California Institute of Technology. +# Copyright (c) 2016-2026 The Uncertainty Quantification Foundation. +# License: 3-clause BSD. The full license text is available at: +# - https://github.com/uqfoundation/dill/blob/master/LICENSE +# +# inspired by inspect.py from Python-2.7.6 +# inspect.py author: 'Ka-Ping Yee ' +# inspect.py merged into original dill.source by Mike McKerns 4/13/14 +""" +Extensions to python's 'inspect' module, which can be used +to retrieve information from live python objects. The methods +defined in this module are augmented to facilitate access to +source code of interactively defined functions and classes, +as well as provide access to source code for objects defined +in a file. +""" + +__all__ = ['findsource', 'getsourcelines', 'getsource', 'indent', 'outdent', \ + '_wrap', 'dumpsource', 'getname', '_namespace', 'getimport', \ + '_importable', 'importable','isdynamic', 'isfrommain'] + +import linecache +import re +from inspect import (getblock, getfile, getmodule, getsourcefile, indentsize, + isbuiltin, isclass, iscode, isframe, isfunction, ismethod, + ismodule, istraceback) +from tokenize import TokenError + +from ._dill import IS_IPYTHON + + +def isfrommain(obj): + "check if object was built in __main__" + module = getmodule(obj) + if module and module.__name__ == '__main__': + return True + return False + + +def isdynamic(obj): + "check if object was built in the interpreter" + try: file = getfile(obj) + except TypeError: file = None + if file == '' and isfrommain(obj): + return True + return False + + +def _matchlambda(func, line): + """check if lambda object 'func' matches raw line of code 'line'""" + from .detect import code as getcode + from .detect import freevars, globalvars, varnames + dummy = lambda : '__this_is_a_big_dummy_function__' + # process the line (removing leading whitespace, etc) + lhs,rhs = line.split('lambda ',1)[-1].split(":", 1) #FIXME: if !1 inputs + try: #FIXME: unsafe + _ = eval("lambda %s : %s" % (lhs,rhs), globals(),locals()) + except Exception: _ = dummy + # get code objects, for comparison + _, code = getcode(_).co_code, getcode(func).co_code + # check if func is in closure + _f = [line.count(i) for i in freevars(func).keys()] + if not _f: # not in closure + # check if code matches + if _ == code: return True + return False + # weak check on freevars + if not all(_f): return False #XXX: VERY WEAK + # weak check on varnames and globalvars + _f = varnames(func) + _f = [line.count(i) for i in _f[0]+_f[1]] + if _f and not all(_f): return False #XXX: VERY WEAK + _f = [line.count(i) for i in globalvars(func).keys()] + if _f and not all(_f): return False #XXX: VERY WEAK + # check if func is a double lambda + if (line.count('lambda ') > 1) and (lhs in freevars(func).keys()): + _lhs,_rhs = rhs.split('lambda ',1)[-1].split(":",1) #FIXME: if !1 inputs + try: #FIXME: unsafe + _f = eval("lambda %s : %s" % (_lhs,_rhs), globals(),locals()) + except Exception: _f = dummy + # get code objects, for comparison + _, code = getcode(_f).co_code, getcode(func).co_code + if len(_) != len(code): return False + #NOTE: should be same code same order, but except for 't' and '\x88' + _ = set((i,j) for (i,j) in zip(_,code) if i != j) + if len(_) != 1: return False #('t','\x88') + return True + # check indentsize + if not indentsize(line): return False #FIXME: is this a good check??? + # check if code 'pattern' matches + #XXX: or pattern match against dis.dis(code)? (or use uncompyle2?) + _ = _.split(_[0]) # 't' #XXX: remove matching values if starts the same? + _f = code.split(code[0]) # '\x88' + #NOTE: should be same code different order, with different first element + _ = dict(re.match(r'([\W\D\S])(.*)', _[i]).groups() for i in range(1,len(_))) + _f = dict(re.match(r'([\W\D\S])(.*)', _f[i]).groups() for i in range(1,len(_f))) + if (_.keys() == _f.keys()) and (sorted(_.values()) == sorted(_f.values())): + return True + return False + + +def findsource(object): + """Return the entire source file and starting line number for an object. + For interactively-defined objects, the 'file' is the interpreter's history. + + The argument may be a module, class, method, function, traceback, frame, + or code object. The source code is returned as a list of all the lines + in the file and the line number indexes a line in that list. An IOError + is raised if the source code cannot be retrieved, while a TypeError is + raised for objects where the source code is unavailable (e.g. builtins).""" + + module = getmodule(object) + try: file = getfile(module) + except TypeError: file = None + is_module_main = (module and module.__name__ == '__main__' and not file) + if IS_IPYTHON and is_module_main: + #FIXME: quick fix for functions and classes in IPython interpreter + try: + file = getfile(object) + sourcefile = getsourcefile(object) + except TypeError: + if isclass(object): + for object_method in filter(isfunction, object.__dict__.values()): + # look for a method of the class + file_candidate = getfile(object_method) + if not file_candidate.startswith('': pat1 = r'(.*(?': + pat1 = r'(.*(?' + if stdin: + lnum = len(lines) - 1 # can't get lnum easily, so leverage pat + if not pat1: pat1 = r'^(\s*def\s)|(.*(? 0: #XXX: won't find decorators in ? + line = lines[lnum] + if pat1.match(line): + if not stdin: break # co_firstlineno does the job + if name == '': # hackery needed to confirm a match + if _matchlambda(obj, line): break + else: # not a lambda, just look for the name + if name in line: # need to check for decorator... + hats = 0 + for _lnum in range(lnum-1,-1,-1): + if pat2.match(lines[_lnum]): hats += 1 + else: break + lnum = lnum - hats + break + lnum = lnum - 1 + return lines, lnum + + try: # turn instances into classes + if not isclass(object) and isclass(type(object)): # __class__ + object = object.__class__ #XXX: sometimes type(class) is better? + #XXX: we don't find how the instance was built + except AttributeError: pass + if isclass(object): + name = object.__name__ + pat = re.compile(r'^(\s*)class\s*' + name + r'\b') + # make some effort to find the best matching class definition: + # use the one with the least indentation, which is the one + # that's most probably not inside a function definition. + candidates = [] + for i in range(len(lines)-1,-1,-1): + match = pat.match(lines[i]) + if match: + # if it's at toplevel, it's already the best one + if lines[i][0] == 'c': + return lines, i + # else add whitespace to candidate list + candidates.append((match.group(1), i)) + if candidates: + # this will sort by whitespace, and by line number, + # less whitespace first #XXX: should sort high lnum before low + candidates.sort() + return lines, candidates[0][1] + else: + raise IOError('could not find class definition') + raise IOError('could not find code object') + + +def getblocks(object, lstrip=False, enclosing=False, locate=False): + """Return a list of source lines and starting line number for an object. + Interactively-defined objects refer to lines in the interpreter's history. + + If enclosing=True, then also return any enclosing code. + If lstrip=True, ensure there is no indentation in the first line of code. + If locate=True, then also return the line number for the block of code. + + DEPRECATED: use 'getsourcelines' instead + """ + lines, lnum = findsource(object) + + if ismodule(object): + if lstrip: lines = _outdent(lines) + return ([lines], [0]) if locate is True else [lines] + + #XXX: 'enclosing' means: closures only? or classes and files? + indent = indentsize(lines[lnum]) + block = getblock(lines[lnum:]) #XXX: catch any TokenError here? + + if not enclosing or not indent: + if lstrip: block = _outdent(block) + return ([block], [lnum]) if locate is True else [block] + + pat1 = r'^(\s*def\s)|(.*(? indent: #XXX: should be >= ? + line += len(code) - skip + elif target in ''.join(code): + blocks.append(code) # save code block as the potential winner + _lnum.append(line - skip) # save the line number for the match + line += len(code) - skip + else: + line += 1 + skip = 0 + # find skip: the number of consecutive decorators + elif pat2.match(lines[line]): + try: code = getblock(lines[line:]) + except TokenError: code = [lines[line]] + skip = 1 + for _line in code[1:]: # skip lines that are decorators + if not pat2.match(_line): break + skip += 1 + line += skip + # no match: reset skip and go to the next line + else: + line +=1 + skip = 0 + + if not blocks: + blocks = [block] + _lnum = [lnum] + if lstrip: blocks = [_outdent(block) for block in blocks] + # return last match + return (blocks, _lnum) if locate is True else blocks + + +def getsourcelines(object, lstrip=False, enclosing=False): + """Return a list of source lines and starting line number for an object. + Interactively-defined objects refer to lines in the interpreter's history. + + The argument may be a module, class, method, function, traceback, frame, + or code object. The source code is returned as a list of the lines + corresponding to the object and the line number indicates where in the + original source file the first line of code was found. An IOError is + raised if the source code cannot be retrieved, while a TypeError is + raised for objects where the source code is unavailable (e.g. builtins). + + If lstrip=True, ensure there is no indentation in the first line of code. + If enclosing=True, then also return any enclosing code.""" + code, n = getblocks(object, lstrip=lstrip, enclosing=enclosing, locate=True) + return code[-1], n[-1] + + +#NOTE: broke backward compatibility 4/16/14 (was lstrip=True, force=True) +def getsource(object, alias='', lstrip=False, enclosing=False, \ + force=False, builtin=False): + """Return the text of the source code for an object. The source code for + interactively-defined objects are extracted from the interpreter's history. + + The argument may be a module, class, method, function, traceback, frame, + or code object. The source code is returned as a single string. An + IOError is raised if the source code cannot be retrieved, while a + TypeError is raised for objects where the source code is unavailable + (e.g. builtins). + + If alias is provided, then add a line of code that renames the object. + If lstrip=True, ensure there is no indentation in the first line of code. + If enclosing=True, then also return any enclosing code. + If force=True, catch (TypeError,IOError) and try to use import hooks. + If builtin=True, force an import for any builtins + """ + # hascode denotes a callable + hascode = _hascode(object) + # is a class instance type (and not in builtins) + instance = _isinstance(object) + + # get source lines; if fail, try to 'force' an import + try: # fails for builtins, and other assorted object types + lines, lnum = getsourcelines(object, enclosing=enclosing) + except (TypeError, IOError): # failed to get source, resort to import hooks + if not force: # don't try to get types that findsource can't get + raise + if not getmodule(object): # get things like 'None' and '1' + if not instance: return getimport(object, alias, builtin=builtin) + # special handling (numpy arrays, ...) + _import = getimport(object, builtin=builtin) + name = getname(object, force=True) + _alias = "%s = " % alias if alias else "" + if alias == name: _alias = "" + return _import+_alias+"%s\n" % name + else: #FIXME: could use a good bit of cleanup, since using getimport... + if not instance: return getimport(object, alias, builtin=builtin) + # now we are dealing with an instance... + name = object.__class__.__name__ + module = object.__module__ + if not name.isidentifier() or not all(i.isidentifier() for i in module.split('.')): #XXX: does exclusing malicious code exclude valid use? + raise SyntaxError('invalid syntax') + if module in ['builtins','__builtin__']: + return getimport(object, alias, builtin=builtin) + else: #FIXME: leverage getimport? use 'from module import name'? + lines, lnum = ["%s = __import__('%s', fromlist=['%s']).%s\n" % (name,module,name,name)], 0 + obj = eval(lines[0].lstrip(name + ' = ')) + lines, lnum = getsourcelines(obj, enclosing=enclosing) + + # strip leading indent (helps ensure can be imported) + if lstrip or alias: + lines = _outdent(lines) + + # instantiate, if there's a nice repr #XXX: BAD IDEA??? + if instance: #and force: #XXX: move into findsource or getsourcelines ? + if '(' in repr(object): lines.append('%r\n' % object) + #else: #XXX: better to somehow to leverage __reduce__ ? + # reconstructor,args = object.__reduce__() + # _ = reconstructor(*args) + else: # fall back to serialization #XXX: bad idea? + #XXX: better not duplicate work? #XXX: better new/enclose=True? + lines = dumpsource(object, alias='', new=force, enclose=False) + lines, lnum = [line+'\n' for line in lines.split('\n')][:-1], 0 + #else: object.__code__ # raise AttributeError + + # add an alias to the source code + if alias: + if hascode: + skip = 0 + for line in lines: # skip lines that are decorators + if not line.startswith('@'): break + skip += 1 + #XXX: use regex from findsource / getsourcelines ? + if lines[skip].lstrip().startswith('def '): # we have a function + if alias != object.__name__: + lines.append('\n%s = %s\n' % (alias, object.__name__)) + elif 'lambda ' in lines[skip]: # we have a lambda + if alias != lines[skip].split('=')[0].strip(): + lines[skip] = '%s = %s' % (alias, lines[skip]) + else: # ...try to use the object's name + if alias != object.__name__: + lines.append('\n%s = %s\n' % (alias, object.__name__)) + else: # class or class instance + if instance: + if alias != lines[-1].split('=')[0].strip(): + lines[-1] = ('%s = ' % alias) + lines[-1] + else: + name = getname(object, force=True) or object.__name__ + if alias != name: + lines.append('\n%s = %s\n' % (alias, name)) + return ''.join(lines) + + +def _hascode(object): + '''True if object has an attribute that stores it's __code__''' + return getattr(object,'__code__',None) or getattr(object,'func_code',None) + +def _isinstance(object): + '''True if object is a class instance type (and is not a builtin)''' + if _hascode(object) or isclass(object) or ismodule(object): + return False + if istraceback(object) or isframe(object) or iscode(object): + return False + # special handling (numpy arrays, ...) + if not getmodule(object) and getmodule(type(object)).__name__ in ['numpy']: + return True +# # check if is instance of a builtin +# if not getmodule(object) and getmodule(type(object)).__name__ in ['__builtin__','builtins']: +# return False + _types = ('") + if not repr(type(object)).startswith(_types): #FIXME: weak hack + return False + if not getmodule(object) or object.__module__ in ['builtins','__builtin__'] or getname(object, force=True) in ['array']: + return False + return True # by process of elimination... it's what we want + + +def _intypes(object): + '''check if object is in the 'types' module''' + import types + # allow user to pass in object or object.__name__ + if type(object) is not type(''): + object = getname(object, force=True) + if object == 'ellipsis': object = 'EllipsisType' + return True if hasattr(types, object) else False + + +def _isstring(object): #XXX: isstringlike better? + '''check if object is a string-like type''' + return isinstance(object, (str, bytes)) + + +def indent(code, spaces=4): + '''indent a block of code with whitespace (default is 4 spaces)''' + indent = indentsize(code) + from numbers import Integral + if isinstance(spaces, Integral): spaces = ' '*spaces + # if '\t' is provided, will indent with a tab + nspaces = indentsize(spaces) + # blank lines (etc) need to be ignored + lines = code.split('\n') +## stq = "'''"; dtq = '"""' +## in_stq = in_dtq = False + for i in range(len(lines)): + #FIXME: works... but shouldn't indent 2nd+ lines of multiline doc + _indent = indentsize(lines[i]) + if indent > _indent: continue + lines[i] = spaces+lines[i] +## #FIXME: may fail when stq and dtq in same line (depends on ordering) +## nstq, ndtq = lines[i].count(stq), lines[i].count(dtq) +## if not in_dtq and not in_stq: +## lines[i] = spaces+lines[i] # we indent +## # entering a comment block +## if nstq%2: in_stq = not in_stq +## if ndtq%2: in_dtq = not in_dtq +## # leaving a comment block +## elif in_dtq and ndtq%2: in_dtq = not in_dtq +## elif in_stq and nstq%2: in_stq = not in_stq +## else: pass + if lines[-1].strip() == '': lines[-1] = '' + return '\n'.join(lines) + + +def _outdent(lines, spaces=None, all=True): + '''outdent lines of code, accounting for docs and line continuations''' + indent = indentsize(lines[0]) + if spaces is None or spaces > indent or spaces < 0: spaces = indent + for i in range(len(lines) if all else 1): + #FIXME: works... but shouldn't outdent 2nd+ lines of multiline doc + _indent = indentsize(lines[i]) + if spaces > _indent: _spaces = _indent + else: _spaces = spaces + lines[i] = lines[i][_spaces:] + return lines + +def outdent(code, spaces=None, all=True): + '''outdent a block of code (default is to strip all leading whitespace)''' + indent = indentsize(code) + if spaces is None or spaces > indent or spaces < 0: spaces = indent + #XXX: will this delete '\n' in some cases? + if not all: return code[spaces:] + return '\n'.join(_outdent(code.split('\n'), spaces=spaces, all=all)) + + +# _wrap provides an wrapper to correctly exec and load into locals +__globals__ = globals() +__locals__ = locals() +def _wrap(f): + """ encapsulate a function and it's __import__ """ + def func(*args, **kwds): + try: + # _ = eval(getsource(f, force=True)) #XXX: safer but less robust + exec(getimportable(f, alias='_'), __globals__, __locals__) + except Exception: + raise ImportError('cannot import name ' + f.__name__) + return _(*args, **kwds) + func.__name__ = f.__name__ + func.__doc__ = f.__doc__ + return func + + +def _enclose(object, alias=''): #FIXME: needs alias to hold returned object + """create a function enclosure around the source of some object""" + #XXX: dummy and stub should append a random string + dummy = '__this_is_a_big_dummy_enclosing_function__' + stub = '__this_is_a_stub_variable__' + code = 'def %s():\n' % dummy + code += indent(getsource(object, alias=stub, lstrip=True, force=True)) + code += indent('return %s\n' % stub) + if alias: code += '%s = ' % alias + code += '%s(); del %s\n' % (dummy, dummy) + #code += "globals().pop('%s',lambda :None)()\n" % dummy + return code + + +def dumpsource(object, alias='', new=False, enclose=True): + """'dump to source', where the code includes a pickled object. + + If new=True and object is a class instance, then create a new + instance using the unpacked class source code. If enclose, then + create the object inside a function enclosure (thus minimizing + any global namespace pollution). + """ + from dill import dumps + pik = repr(dumps(object)) + code = 'import dill\n' + if enclose: + stub = '__this_is_a_stub_variable__' #XXX: *must* be same _enclose.stub + pre = '%s = ' % stub + new = False #FIXME: new=True doesn't work with enclose=True + else: + stub = alias + pre = '%s = ' % stub if alias else alias + + # if a 'new' instance is not needed, then just dump and load + if not new or not _isinstance(object): + code += pre + 'dill.loads(%s)\n' % pik + else: #XXX: other cases where source code is needed??? + code += getsource(object.__class__, alias='', lstrip=True, force=True) + mod = repr(object.__module__) # should have a module (no builtins here) + code += pre + 'dill.loads(%s.replace(b%s,bytes(__name__,"UTF-8")))\n' % (pik,mod) + #code += 'del %s' % object.__class__.__name__ #NOTE: kills any existing! + + if enclose: + # generation of the 'enclosure' + dummy = '__this_is_a_big_dummy_object__' + dummy = _enclose(dummy, alias=alias) + # hack to replace the 'dummy' with the 'real' code + dummy = dummy.split('\n') + code = dummy[0]+'\n' + indent(code) + '\n'.join(dummy[-3:]) + + return code #XXX: better 'dumpsourcelines', returning list of lines? + + +def getname(obj, force=False, fqn=False): #XXX: throw(?) to raise error on fail? + """get the name of the object. for lambdas, get the name of the pointer """ + if fqn: return '.'.join(_namespace(obj)) #NOTE: returns 'type' + module = getmodule(obj) + if not module: # things like "None" and "1" + if not force: return None #NOTE: returns 'instance' NOT 'type' #FIXME? + # handle some special cases + if hasattr(obj, 'dtype') and not obj.shape: + return getname(obj.__class__) + "(" + repr(obj.tolist()) + ")" + return repr(obj) + try: + #XXX: 'wrong' for decorators and curried functions ? + # if obj.func_closure: ...use logic from getimportable, etc ? + name = obj.__name__ + if name == '': + return getsource(obj).split('=',1)[0].strip() + # handle some special cases + if module.__name__ in ['builtins','__builtin__']: + if name == 'ellipsis': name = 'EllipsisType' + return name + except AttributeError: #XXX: better to just throw AttributeError ? + if not force: return None + name = repr(obj) + if name.startswith('<'): # or name.split('('): + return None + return name + + +def _namespace(obj): + """_namespace(obj); return namespace hierarchy (as a list of names) + for the given object. For an instance, find the class hierarchy. + + For example: + + >>> from functools import partial + >>> p = partial(int, base=2) + >>> _namespace(p) + [\'functools\', \'partial\'] + """ + # mostly for functions and modules and such + #FIXME: 'wrong' for decorators and curried functions + try: #XXX: needs some work and testing on different types + module = qual = str(getmodule(obj)).split()[1].strip('>').strip('"').strip("'") + qual = qual.split('.') + if ismodule(obj): + return qual + # get name of a lambda, function, etc + name = getname(obj) or obj.__name__ # failing, raise AttributeError + # check special cases (NoneType, ...) + if module in ['builtins','__builtin__']: # BuiltinFunctionType + if _intypes(name): return ['types'] + [name] + return qual + [name] #XXX: can be wrong for some aliased objects + except Exception: pass + # special case: numpy.inf and numpy.nan (we don't want them as floats) + if str(obj) in ['inf','nan','Inf','NaN']: # is more, but are they needed? + return ['numpy'] + [str(obj)] + # mostly for classes and class instances and such + module = getattr(obj.__class__, '__module__', None) + qual = str(obj.__class__) + try: qual = qual[qual.index("'")+1:-2] + except ValueError: pass # str(obj.__class__) made the 'try' unnecessary + qual = qual.split(".") + if module in ['builtins','__builtin__']: + # check special cases (NoneType, Ellipsis, ...) + if qual[-1] == 'ellipsis': qual[-1] = 'EllipsisType' + if _intypes(qual[-1]): module = 'types' #XXX: BuiltinFunctionType + qual = [module] + qual + return qual + + +#NOTE: 05/25/14 broke backward compatibility: added 'alias' as 3rd argument +def _getimport(head, tail, alias='', verify=True, builtin=False): + """helper to build a likely import string from head and tail of namespace. + ('head','tail') are used in the following context: "from head import tail" + + If verify=True, then test the import string before returning it. + If builtin=True, then force an import for builtins where possible. + If alias is provided, then rename the object on import. + """ + # special handling for a few common types + if tail in ['Ellipsis', 'NotImplemented'] and head in ['types']: + head = len.__module__ + elif tail in ['None'] and head in ['types']: + _alias = '%s = ' % alias if alias else '' + if alias == tail: _alias = '' + return _alias+'%s\n' % tail + # we don't need to import from builtins, so return '' +# elif tail in ['NoneType','int','float','long','complex']: return '' #XXX: ? + if head in ['builtins','__builtin__']: + # special cases (NoneType, Ellipsis, ...) #XXX: BuiltinFunctionType + if tail == 'ellipsis': tail = 'EllipsisType' + if _intypes(tail): head = 'types' + elif not builtin: + _alias = '%s = ' % alias if alias else '' + if alias == tail: _alias = '' + return _alias+'%s\n' % tail + else: pass # handle builtins below + # get likely import string + if not head: _str = "import %s" % tail + else: _str = "from %s import %s" % (head, tail) + _alias = " as %s\n" % alias if alias else "\n" + if alias == tail: _alias = "\n" + _str += _alias + # FIXME: fails on most decorators, currying, and such... + # (could look for magic __wrapped__ or __func__ attr) + # (could fix in 'namespace' to check obj for closure) + if verify and not head.startswith('dill.'):# weird behavior for dill + #print(_str) + try: exec(_str) #XXX: check if == obj? (name collision) + except ImportError: #XXX: better top-down or bottom-up recursion? + _head = head.rsplit(".",1)[0] #(or get all, then compare == obj?) + if not _head: raise + if _head != head: + _str = _getimport(_head, tail, alias, verify) + return _str + + +#XXX: rename builtin to force? vice versa? verify to force? (as in getsource) +#NOTE: 05/25/14 broke backward compatibility: added 'alias' as 2nd argument +def getimport(obj, alias='', verify=True, builtin=False, enclosing=False): + """get the likely import string for the given object + + obj is the object to inspect + If verify=True, then test the import string before returning it. + If builtin=True, then force an import for builtins where possible. + If enclosing=True, get the import for the outermost enclosing callable. + If alias is provided, then rename the object on import. + """ + if enclosing: + from .detect import outermost + _obj = outermost(obj) + obj = _obj if _obj else obj + # get the namespace + qual = _namespace(obj) + head = '.'.join(qual[:-1]) + tail = qual[-1] + # for named things... with a nice repr #XXX: move into _namespace? + try: # look for '<...>' and be mindful it might be in lists, dicts, etc... + name = repr(obj).split('<',1)[1].split('>',1)[1] + name = None # we have a 'object'-style repr + except Exception: # it's probably something 'importable' + if head in ['builtins','__builtin__']: + name = repr(obj) #XXX: catch [1,2], (1,2), set([1,2])... others? + elif _isinstance(obj): + name = getname(obj, force=True).split('(')[0] + else: + name = repr(obj).split('(')[0] + #if not repr(obj).startswith('<'): name = repr(obj).split('(')[0] + #else: name = None + if name: # try using name instead of tail + try: return _getimport(head, name, alias, verify, builtin) + except ImportError: pass + except SyntaxError: + if head in ['builtins','__builtin__']: + _alias = '%s = ' % alias if alias else '' + if alias == name: _alias = '' + return _alias+'%s\n' % name + else: pass + try: + #if type(obj) is type(abs): _builtin = builtin # BuiltinFunctionType + #else: _builtin = False + return _getimport(head, tail, alias, verify, builtin) + except ImportError: + raise # could do some checking against obj + except SyntaxError: + if head in ['builtins','__builtin__']: + _alias = '%s = ' % alias if alias else '' + if alias == tail: _alias = '' + return _alias+'%s\n' % tail + raise # could do some checking against obj + + +def _importable(obj, alias='', source=None, enclosing=False, force=True, \ + builtin=True, lstrip=True): + """get an import string (or the source code) for the given object + + This function will attempt to discover the name of the object, or the repr + of the object, or the source code for the object. To attempt to force + discovery of the source code, use source=True, to attempt to force the + use of an import, use source=False; otherwise an import will be sought + for objects not defined in __main__. The intent is to build a string + that can be imported from a python file. obj is the object to inspect. + If alias is provided, then rename the object with the given alias. + + If source=True, use these options: + If enclosing=True, then also return any enclosing code. + If force=True, catch (TypeError,IOError) and try to use import hooks. + If lstrip=True, ensure there is no indentation in the first line of code. + + If source=False, use these options: + If enclosing=True, get the import for the outermost enclosing callable. + If force=True, then don't test the import string before returning it. + If builtin=True, then force an import for builtins where possible. + """ + if source is None: + source = True if isfrommain(obj) else False + if source: # first try to get the source + try: + return getsource(obj, alias, enclosing=enclosing, \ + force=force, lstrip=lstrip, builtin=builtin) + except Exception: pass + try: + if not _isinstance(obj): + return getimport(obj, alias, enclosing=enclosing, \ + verify=(not force), builtin=builtin) + # first 'get the import', then 'get the instance' + _import = getimport(obj, enclosing=enclosing, \ + verify=(not force), builtin=builtin) + name = getname(obj, force=True) + if not name: + raise AttributeError("object has no atribute '__name__'") + _alias = "%s = " % alias if alias else "" + if alias == name: _alias = "" + return _import+_alias+"%s\n" % name + + except Exception: pass + if not source: # try getsource, only if it hasn't been tried yet + try: + return getsource(obj, alias, enclosing=enclosing, \ + force=force, lstrip=lstrip, builtin=builtin) + except Exception: pass + # get the name (of functions, lambdas, and classes) + # or hope that obj can be built from the __repr__ + #XXX: what to do about class instances and such? + obj = getname(obj, force=force) + # we either have __repr__ or __name__ (or None) + if not obj or obj.startswith('<'): + raise AttributeError("object has no atribute '__name__'") + _alias = '%s = ' % alias if alias else '' + if alias == obj: _alias = '' + return _alias+'%s\n' % obj + #XXX: possible failsafe... (for example, for instances when source=False) + # "import dill; result = dill.loads(); # repr()" + +def _closuredimport(func, alias='', builtin=False): + """get import for closured objects; return a dict of 'name' and 'import'""" + import re + from .detect import freevars, outermost + free_vars = freevars(func) + func_vars = {} + # split into 'funcs' and 'non-funcs' + for name,obj in list(free_vars.items()): + if not isfunction(obj): continue + # get import for 'funcs' + fobj = free_vars.pop(name) + src = getsource(fobj) + if src.lstrip().startswith('@'): # we have a decorator + src = getimport(fobj, alias=alias, builtin=builtin) + else: # we have to "hack" a bit... and maybe be lucky + encl = outermost(func) + # pattern: 'func = enclosing(fobj' + pat = r'.*[\w\s]=\s*'+getname(encl)+r'\('+getname(fobj) + mod = getname(getmodule(encl)) + #HACK: get file containing 'outer' function; is func there? + lines,_ = findsource(encl) + candidate = [line for line in lines if getname(encl) in line and \ + re.match(pat, line)] + if not candidate: + mod = getname(getmodule(fobj)) + #HACK: get file containing 'inner' function; is func there? + lines,_ = findsource(fobj) + candidate = [line for line in lines \ + if getname(fobj) in line and re.match(pat, line)] + if not len(candidate): raise TypeError('import could not be found') + candidate = candidate[-1] + name = candidate.split('=',1)[0].split()[-1].strip() + src = _getimport(mod, name, alias=alias, builtin=builtin) + func_vars[name] = src + if not func_vars: + name = outermost(func) + mod = getname(getmodule(name)) + if not mod or name is func: # then it can be handled by getimport + name = getname(func, force=True) #XXX: better key? + src = getimport(func, alias=alias, builtin=builtin) + else: + lines,_ = findsource(name) + # pattern: 'func = enclosing(' + candidate = [line for line in lines if getname(name) in line and \ + re.match(r'.*[\w\s]=\s*'+getname(name)+r'\(', line)] + if not len(candidate): raise TypeError('import could not be found') + candidate = candidate[-1] + name = candidate.split('=',1)[0].split()[-1].strip() + src = _getimport(mod, name, alias=alias, builtin=builtin) + func_vars[name] = src + return func_vars + +#XXX: should be able to use __qualname__ +def _closuredsource(func, alias=''): + """get source code for closured objects; return a dict of 'name' + and 'code blocks'""" + #FIXME: this entire function is a messy messy HACK + # - pollutes global namespace + # - fails if name of freevars are reused + # - can unnecessarily duplicate function code + from .detect import freevars + free_vars = freevars(func) + func_vars = {} + # split into 'funcs' and 'non-funcs' + for name,obj in list(free_vars.items()): + if not isfunction(obj): + # get source for 'non-funcs' + free_vars[name] = getsource(obj, force=True, alias=name) + continue + # get source for 'funcs' + fobj = free_vars.pop(name) + src = getsource(fobj, alias) # DO NOT include dependencies + # if source doesn't start with '@', use name as the alias + if not src.lstrip().startswith('@'): #FIXME: 'enclose' in dummy; + src = importable(fobj,alias=name)# wrong ref 'name' + org = getsource(func, alias, enclosing=False, lstrip=True) + src = (src, org) # undecorated first, then target + else: #NOTE: reproduces the code! + org = getsource(func, enclosing=True, lstrip=False) + src = importable(fobj, alias, source=True) # include dependencies + src = (org, src) # target first, then decorated + func_vars[name] = src + src = ''.join(free_vars.values()) + if not func_vars: #FIXME: 'enclose' in dummy; wrong ref 'name' + org = getsource(func, alias, force=True, enclosing=False, lstrip=True) + src = (src, org) # variables first, then target + else: + src = (src, None) # just variables (better '' instead of None?) + func_vars[None] = src + # FIXME: remove duplicates (however, order is important...) + return func_vars + +def importable(obj, alias='', source=None, builtin=True): + """get an importable string (i.e. source code or the import string) + for the given object, including any required objects from the enclosing + and global scope + + This function will attempt to discover the name of the object, or the repr + of the object, or the source code for the object. To attempt to force + discovery of the source code, use source=True, to attempt to force the + use of an import, use source=False; otherwise an import will be sought + for objects not defined in __main__. The intent is to build a string + that can be imported from a python file. + + obj is the object to inspect. If alias is provided, then rename the + object with the given alias. If builtin=True, then force an import for + builtins where possible. + """ + #NOTE: we always 'force', and 'lstrip' as necessary + #NOTE: for 'enclosing', use importable(outermost(obj)) + if source is None: + source = True if isfrommain(obj) else False + elif builtin and isbuiltin(obj): + source = False + tried_source = tried_import = False + while True: + if not source: # we want an import + try: + if _isinstance(obj): # for instances, punt to _importable + return _importable(obj, alias, source=False, builtin=builtin) + src = _closuredimport(obj, alias=alias, builtin=builtin) + if len(src) == 0: + raise NotImplementedError('not implemented') + if len(src) > 1: + raise NotImplementedError('not implemented') + return list(src.values())[0] + except Exception: + if tried_source: raise + tried_import = True + # we want the source + try: + src = _closuredsource(obj, alias=alias) + if len(src) == 0: + raise NotImplementedError('not implemented') + # groan... an inline code stitcher + def _code_stitcher(block): + "stitch together the strings in tuple 'block'" + if block[0] and block[-1]: block = '\n'.join(block) + elif block[0]: block = block[0] + elif block[-1]: block = block[-1] + else: block = '' + return block + # get free_vars first + _src = _code_stitcher(src.pop(None)) + _src = [_src] if _src else [] + # get func_vars + for xxx in src.values(): + xxx = _code_stitcher(xxx) + if xxx: _src.append(xxx) + # make a single source string + if not len(_src): + src = '' + elif len(_src) == 1: + src = _src[0] + else: + src = '\n'.join(_src) + # get source code of objects referred to by obj in global scope + from .detect import globalvars + obj = globalvars(obj) #XXX: don't worry about alias? recurse? etc? + obj = list(getsource(_obj,name,force=True) for (name,_obj) in obj.items() if not isbuiltin(_obj)) + obj = '\n'.join(obj) if obj else '' + # combine all referred-to source (global then enclosing) + if not obj: return src + if not src: return obj + return obj + src + except Exception: + if tried_import: raise + tried_source = True + source = not source + # should never get here + return + + +# backward compatibility +def getimportable(obj, alias='', byname=True, explicit=False): + return importable(obj,alias,source=(not byname),builtin=explicit) + #return outdent(_importable(obj,alias,source=(not byname),builtin=explicit)) +def likely_import(obj, passive=False, explicit=False): + return getimport(obj, verify=(not passive), builtin=explicit) +def _likely_import(first, last, passive=False, explicit=True): + return _getimport(first, last, verify=(not passive), builtin=explicit) +_get_name = getname +getblocks_from_history = getblocks + + + +# EOF diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/dill/temp.py b/bioagent-bench/.venv/lib/python3.14/site-packages/dill/temp.py new file mode 100644 index 0000000000000000000000000000000000000000..4b9f4e03b459bfafa3080cc4ac1aa2ecdefd523c --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/dill/temp.py @@ -0,0 +1,252 @@ +#!/usr/bin/env python +# +# Author: Mike McKerns (mmckerns @caltech and @uqfoundation) +# Copyright (c) 2008-2016 California Institute of Technology. +# Copyright (c) 2016-2026 The Uncertainty Quantification Foundation. +# License: 3-clause BSD. The full license text is available at: +# - https://github.com/uqfoundation/dill/blob/master/LICENSE +""" +Methods for serialized objects (or source code) stored in temporary files +and file-like objects. +""" +#XXX: better instead to have functions write to any given file-like object ? +#XXX: currently, all file-like objects are created by the function... + +__all__ = ['dump_source', 'dump', 'dumpIO_source', 'dumpIO',\ + 'load_source', 'load', 'loadIO_source', 'loadIO',\ + 'capture'] + +import contextlib + + +@contextlib.contextmanager +def capture(stream='stdout'): + """builds a context that temporarily replaces the given stream name + + >>> with capture('stdout') as out: + ... print ("foo!") + ... + >>> print (out.getvalue()) + foo! + + """ + import sys + from io import StringIO + orig = getattr(sys, stream) + setattr(sys, stream, StringIO()) + try: + yield getattr(sys, stream) + finally: + setattr(sys, stream, orig) + + +def b(x): # deal with b'foo' versus 'foo' + import codecs + return codecs.latin_1_encode(x)[0] + +def load_source(file, **kwds): + """load an object that was stored with dill.temp.dump_source + + file: filehandle + alias: string name of stored object + mode: mode to open the file, one of: {'r', 'rb'} + + >>> f = lambda x: x**2 + >>> pyfile = dill.temp.dump_source(f, alias='_f') + >>> _f = dill.temp.load_source(pyfile) + >>> _f(4) + 16 + """ + alias = kwds.pop('alias', None) + mode = kwds.pop('mode', 'r') + fname = getattr(file, 'name', file) # fname=file.name or fname=file (if str) + source = open(fname, mode=mode, **kwds).read() + if not alias: + tag = source.strip().splitlines()[-1].split() + if tag[0] != '#NAME:': + stub = source.splitlines()[0] + raise IOError("unknown name for code: %s" % stub) + alias = tag[-1] + local = {} + exec(source, local) + _ = eval("%s" % alias, local) + return _ + +def dump_source(object, **kwds): + """write object source to a NamedTemporaryFile (instead of dill.dump) +Loads with "import" or "dill.temp.load_source". Returns the filehandle. + + >>> f = lambda x: x**2 + >>> pyfile = dill.temp.dump_source(f, alias='_f') + >>> _f = dill.temp.load_source(pyfile) + >>> _f(4) + 16 + + >>> f = lambda x: x**2 + >>> pyfile = dill.temp.dump_source(f, dir='.') + >>> modulename = os.path.basename(pyfile.name).split('.py')[0] + >>> exec('from %s import f as _f' % modulename) + >>> _f(4) + 16 + +Optional kwds: + If 'alias' is specified, the object will be renamed to the given string. + + If 'prefix' is specified, the file name will begin with that prefix, + otherwise a default prefix is used. + + If 'dir' is specified, the file will be created in that directory, + otherwise a default directory is used. + + If 'text' is specified and true, the file is opened in text + mode. Else (the default) the file is opened in binary mode. On + some operating systems, this makes no difference. + +NOTE: Keep the return value for as long as you want your file to exist ! + """ #XXX: write a "load_source"? + from .source import importable, getname + import tempfile + kwds.setdefault('delete', True) + kwds.pop('suffix', '') # this is *always* '.py' + alias = kwds.pop('alias', '') #XXX: include an alias so a name is known + name = str(alias) or getname(object) + name = "\n#NAME: %s\n" % name + #XXX: assumes kwds['dir'] is writable and on $PYTHONPATH + file = tempfile.NamedTemporaryFile(suffix='.py', **kwds) + file.write(b(''.join([importable(object, alias=alias),name]))) + file.flush() + return file + +def load(file, **kwds): + """load an object that was stored with dill.temp.dump + + file: filehandle + mode: mode to open the file, one of: {'r', 'rb'} + + >>> dumpfile = dill.temp.dump([1, 2, 3, 4, 5]) + >>> dill.temp.load(dumpfile) + [1, 2, 3, 4, 5] + """ + import dill as pickle + mode = kwds.pop('mode', 'rb') + name = getattr(file, 'name', file) # name=file.name or name=file (if str) + return pickle.load(open(name, mode=mode, **kwds)) + +def dump(object, **kwds): + """dill.dump of object to a NamedTemporaryFile. +Loads with "dill.temp.load". Returns the filehandle. + + >>> dumpfile = dill.temp.dump([1, 2, 3, 4, 5]) + >>> dill.temp.load(dumpfile) + [1, 2, 3, 4, 5] + +Optional kwds: + If 'suffix' is specified, the file name will end with that suffix, + otherwise there will be no suffix. + + If 'prefix' is specified, the file name will begin with that prefix, + otherwise a default prefix is used. + + If 'dir' is specified, the file will be created in that directory, + otherwise a default directory is used. + + If 'text' is specified and true, the file is opened in text + mode. Else (the default) the file is opened in binary mode. On + some operating systems, this makes no difference. + +NOTE: Keep the return value for as long as you want your file to exist ! + """ + import dill as pickle + import tempfile + kwds.setdefault('delete', True) + file = tempfile.NamedTemporaryFile(**kwds) + pickle.dump(object, file) + file.flush() + return file + +def loadIO(buffer, **kwds): + """load an object that was stored with dill.temp.dumpIO + + buffer: buffer object + + >>> dumpfile = dill.temp.dumpIO([1, 2, 3, 4, 5]) + >>> dill.temp.loadIO(dumpfile) + [1, 2, 3, 4, 5] + """ + import dill as pickle + from io import BytesIO as StringIO + value = getattr(buffer, 'getvalue', buffer) # value or buffer.getvalue + if value != buffer: value = value() # buffer.getvalue() + return pickle.load(StringIO(value)) + +def dumpIO(object, **kwds): + """dill.dump of object to a buffer. +Loads with "dill.temp.loadIO". Returns the buffer object. + + >>> dumpfile = dill.temp.dumpIO([1, 2, 3, 4, 5]) + >>> dill.temp.loadIO(dumpfile) + [1, 2, 3, 4, 5] + """ + import dill as pickle + from io import BytesIO as StringIO + file = StringIO() + pickle.dump(object, file) + file.flush() + return file + +def loadIO_source(buffer, **kwds): + """load an object that was stored with dill.temp.dumpIO_source + + buffer: buffer object + alias: string name of stored object + + >>> f = lambda x:x**2 + >>> pyfile = dill.temp.dumpIO_source(f, alias='_f') + >>> _f = dill.temp.loadIO_source(pyfile) + >>> _f(4) + 16 + """ + alias = kwds.pop('alias', None) + source = getattr(buffer, 'getvalue', buffer) # source or buffer.getvalue + if source != buffer: source = source() # buffer.getvalue() + source = source.decode() # buffer to string + if not alias: + tag = source.strip().splitlines()[-1].split() + if tag[0] != '#NAME:': + stub = source.splitlines()[0] + raise IOError("unknown name for code: %s" % stub) + alias = tag[-1] + local = {} + exec(source, local) + _ = eval("%s" % alias, local) + return _ + +def dumpIO_source(object, **kwds): + """write object source to a buffer (instead of dill.dump) +Loads by with dill.temp.loadIO_source. Returns the buffer object. + + >>> f = lambda x:x**2 + >>> pyfile = dill.temp.dumpIO_source(f, alias='_f') + >>> _f = dill.temp.loadIO_source(pyfile) + >>> _f(4) + 16 + +Optional kwds: + If 'alias' is specified, the object will be renamed to the given string. + """ + from .source import importable, getname + from io import BytesIO as StringIO + alias = kwds.pop('alias', '') #XXX: include an alias so a name is known + name = str(alias) or getname(object) + name = "\n#NAME: %s\n" % name + #XXX: assumes kwds['dir'] is writable and on $PYTHONPATH + file = StringIO() + file.write(b(''.join([importable(object, alias=alias),name]))) + file.flush() + return file + + +del contextlib + + +# EOF diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/dill/tests/test_abc.py b/bioagent-bench/.venv/lib/python3.14/site-packages/dill/tests/test_abc.py new file mode 100644 index 0000000000000000000000000000000000000000..70678fe636cd7c36eb46b0aa2a60e2733594c77c --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/dill/tests/test_abc.py @@ -0,0 +1,169 @@ +#!/usr/bin/env python +# +# Author: Mike McKerns (mmckerns @caltech and @uqfoundation) +# Copyright (c) 2023-2026 The Uncertainty Quantification Foundation. +# License: 3-clause BSD. The full license text is available at: +# - https://github.com/uqfoundation/dill/blob/master/LICENSE +""" +test dill's ability to pickle abstract base class objects +""" +import dill +import abc +from abc import ABC +import warnings + +from types import FunctionType + +dill.settings['recurse'] = True + +class OneTwoThree(ABC): + @abc.abstractmethod + def foo(self): + """A method""" + pass + + @property + @abc.abstractmethod + def bar(self): + """Property getter""" + pass + + @bar.setter + @abc.abstractmethod + def bar(self, value): + """Property setter""" + pass + + @classmethod + @abc.abstractmethod + def cfoo(cls): + """Class method""" + pass + + @staticmethod + @abc.abstractmethod + def sfoo(): + """Static method""" + pass + +class EasyAsAbc(OneTwoThree): + def __init__(self): + self._bar = None + + def foo(self): + return "Instance Method FOO" + + @property + def bar(self): + return self._bar + + @bar.setter + def bar(self, value): + self._bar = value + + @classmethod + def cfoo(cls): + return "Class Method CFOO" + + @staticmethod + def sfoo(): + return "Static Method SFOO" + +def test_abc_non_local(): + assert dill.copy(OneTwoThree) is not OneTwoThree + assert dill.copy(EasyAsAbc) is not EasyAsAbc + + with warnings.catch_warnings(): + warnings.simplefilter("ignore", dill.PicklingWarning) + assert dill.copy(OneTwoThree, byref=True) is OneTwoThree + assert dill.copy(EasyAsAbc, byref=True) is EasyAsAbc + + instance = EasyAsAbc() + # Set a property that StockPickle can't preserve + instance.bar = lambda x: x**2 + depickled = dill.copy(instance) + assert type(depickled) is type(instance) #NOTE: issue #612, test_abc_local + #NOTE: dill.copy of local (or non-local) classes should (not) be the same? + assert type(depickled.bar) is FunctionType + assert depickled.bar(3) == 9 + assert depickled.sfoo() == "Static Method SFOO" + assert depickled.cfoo() == "Class Method CFOO" + assert depickled.foo() == "Instance Method FOO" + +def test_abc_local(): + """ + Test using locally scoped ABC class + """ + class LocalABC(ABC): + @abc.abstractmethod + def foo(self): + pass + + def baz(self): + return repr(self) + + labc = dill.copy(LocalABC) + assert labc is not LocalABC + assert type(labc) is type(LocalABC) + #NOTE: dill.copy of local (or non-local) classes should (not) be the same? + # + # .LocalABC'> + + class Real(labc): + def foo(self): + return "True!" + + def baz(self): + return "My " + super(Real, self).baz() + + real = Real() + assert real.foo() == "True!" + + try: + labc() + except TypeError as e: + # Expected error + pass + else: + print('Failed to raise type error') + assert False + + labc2, pik = dill.copy((labc, Real())) + assert 'Real' == type(pik).__name__ + assert '.Real' in type(pik).__qualname__ + assert type(pik) is not Real + assert labc2 is not LocalABC + assert labc2 is not labc + assert isinstance(pik, labc2) + assert not isinstance(pik, labc) + assert not isinstance(pik, LocalABC) + assert pik.baz() == "My " + repr(pik) + +def test_meta_local_no_cache(): + """ + Test calling metaclass and cache registration + """ + LocalMetaABC = abc.ABCMeta('LocalMetaABC', (), {}) + + class ClassyClass: + pass + + class KlassyClass: + pass + + LocalMetaABC.register(ClassyClass) + + assert not issubclass(KlassyClass, LocalMetaABC) + assert issubclass(ClassyClass, LocalMetaABC) + + res = dill.dumps((LocalMetaABC, ClassyClass, KlassyClass)) + + lmabc, cc, kc = dill.loads(res) + assert type(lmabc) == type(LocalMetaABC) + assert not issubclass(kc, lmabc) + assert issubclass(cc, lmabc) + +if __name__ == '__main__': + test_abc_non_local() + test_abc_local() + test_meta_local_no_cache() diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/dill/tests/test_dataclasses.py b/bioagent-bench/.venv/lib/python3.14/site-packages/dill/tests/test_dataclasses.py new file mode 100644 index 0000000000000000000000000000000000000000..5b2af2d408eae639839c1e613b758f47a2987d9a --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/dill/tests/test_dataclasses.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python +# +# Author: Mike McKerns (mmckerns @caltech and @uqfoundation) +# Author: Anirudh Vegesana (avegesan@cs.stanford.edu) +# Copyright (c) 2022-2026 The Uncertainty Quantification Foundation. +# License: 3-clause BSD. The full license text is available at: +# - https://github.com/uqfoundation/dill/blob/master/LICENSE +""" +test pickling a dataclass +""" + +import dill +import dataclasses + +def test_dataclasses(): + # Issue #500 + @dataclasses.dataclass + class A: + x: int + y: str + + @dataclasses.dataclass + class B: + a: A + + a = A(1, "test") + before = B(a) + save = dill.dumps(before) + after = dill.loads(save) + assert before != after # classes don't match + assert before == B(A(**dataclasses.asdict(after.a))) + assert dataclasses.asdict(before) == dataclasses.asdict(after) + +if __name__ == '__main__': + test_dataclasses() diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/dill/tests/test_module.py b/bioagent-bench/.venv/lib/python3.14/site-packages/dill/tests/test_module.py new file mode 100644 index 0000000000000000000000000000000000000000..bc0e18e3294a103af226c602e8bac2b13b2258af --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/dill/tests/test_module.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python +# +# Author: Mike McKerns (mmckerns @caltech and @uqfoundation) +# Copyright (c) 2008-2016 California Institute of Technology. +# Copyright (c) 2016-2026 The Uncertainty Quantification Foundation. +# License: 3-clause BSD. The full license text is available at: +# - https://github.com/uqfoundation/dill/blob/master/LICENSE + +import sys +import dill +import test_mixins as module +from importlib import reload +dill.settings['recurse'] = True + +cached = (module.__cached__ if hasattr(module, "__cached__") + else module.__file__.split(".", 1)[0] + ".pyc") + +module.a = 1234 + +pik_mod = dill.dumps(module) + +module.a = 0 + +# remove module +del sys.modules[module.__name__] +del module + +module = dill.loads(pik_mod) +def test_attributes(): + #assert hasattr(module, "a") and module.a == 1234 #FIXME: -m dill.tests + assert module.double_add(1, 2, 3) == 2 * module.fx + +# Restart, and test use_diff + +reload(module) + +try: + dill.use_diff() + + module.a = 1234 + + pik_mod = dill.dumps(module) + + module.a = 0 + + # remove module + del sys.modules[module.__name__] + del module + + module = dill.loads(pik_mod) + def test_diff_attributes(): + assert hasattr(module, "a") and module.a == 1234 + assert module.double_add(1, 2, 3) == 2 * module.fx + +except AttributeError: + def test_diff_attributes(): + pass + +# clean up +import os +if os.path.exists(cached): + os.remove(cached) +pycache = os.path.join(os.path.dirname(module.__file__), "__pycache__") +if os.path.exists(pycache) and not os.listdir(pycache): + os.removedirs(pycache) + + +# test when module is None +import math + +def get_lambda(str, **kwarg): + return eval(str, kwarg, None) + +obj = get_lambda('lambda x: math.exp(x)', math=math) + +def test_module_is_none(): + assert obj.__module__ is None + assert dill.copy(obj)(3) == obj(3) + + +if __name__ == '__main__': + test_attributes() + test_diff_attributes() + test_module_is_none() diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/dill/tests/test_moduledict.py b/bioagent-bench/.venv/lib/python3.14/site-packages/dill/tests/test_moduledict.py new file mode 100644 index 0000000000000000000000000000000000000000..7c9392191b9988d006d6e52d804c728fe038a278 --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/dill/tests/test_moduledict.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python +# +# Author: Mike McKerns (mmckerns @caltech and @uqfoundation) +# Copyright (c) 2008-2016 California Institute of Technology. +# Copyright (c) 2016-2026 The Uncertainty Quantification Foundation. +# License: 3-clause BSD. The full license text is available at: +# - https://github.com/uqfoundation/dill/blob/master/LICENSE + +import dill +dill.settings['recurse'] = True + +def f(func): + def w(*args): + return f(*args) + return w + +@f +def f2(): pass + +# check when __main__ and on import +def test_decorated(): + assert dill.pickles(f2) + + +import doctest +import logging +logging.basicConfig(level=logging.DEBUG) + +class SomeUnreferencedUnpicklableClass(object): + def __reduce__(self): + raise Exception + +unpicklable = SomeUnreferencedUnpicklableClass() + +# This works fine outside of Doctest: +def test_normal(): + serialized = dill.dumps(lambda x: x) + +# should not try to pickle unpicklable object in __globals__ +def tests(): + """ + >>> serialized = dill.dumps(lambda x: x) + """ + return + +#print("\n\nRunning Doctest:") +def test_doctest(): + doctest.testmod() + + +if __name__ == '__main__': + test_decorated() + test_normal() + test_doctest() diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/dill/tests/test_registered.py b/bioagent-bench/.venv/lib/python3.14/site-packages/dill/tests/test_registered.py new file mode 100644 index 0000000000000000000000000000000000000000..5c57d8a0d51006fbcfe59c732dc4a1300ff52a6c --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/dill/tests/test_registered.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python +# +# Author: Mike McKerns (mmckerns @caltech and @uqfoundation) +# Copyright (c) 2022-2026 The Uncertainty Quantification Foundation. +# License: 3-clause BSD. The full license text is available at: +# - https://github.com/uqfoundation/dill/blob/master/LICENSE +""" +test pickling registered objects +""" + +import dill +from dill._objects import failures, registered, succeeds +import warnings +warnings.filterwarnings('ignore') + +def check(d, ok=True): + res = [] + for k,v in d.items(): + try: + z = dill.copy(v) + if ok: res.append(k) + except: + if not ok: res.append(k) + return res + +fails = check(failures) +try: + assert not bool(fails) +except AssertionError as e: + print("FAILS: %s" % fails) + raise e from None + +register = check(registered, ok=False) +try: + assert not bool(register) +except AssertionError as e: + print("REGISTER: %s" % register) + raise e from None + +success = check(succeeds, ok=False) +try: + assert not bool(success) +except AssertionError as e: + print("SUCCESS: %s" % success) + raise e from None + +import builtins +import types +q = dill._dill._reverse_typemap +p = {k:v for k,v in q.items() if k not in vars(builtins) and k not in vars(types)} + +diff = set(p.keys()).difference(registered.keys()) +try: + assert not bool(diff) +except AssertionError as e: + print("DIFF: %s" % diff) + raise e from None + +miss = set(registered.keys()).difference(p.keys()) +try: + assert not bool(miss) +except AssertionError as e: + print("MISS: %s" % miss) + raise e from None diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/dill/tests/test_selected.py b/bioagent-bench/.venv/lib/python3.14/site-packages/dill/tests/test_selected.py new file mode 100644 index 0000000000000000000000000000000000000000..b4edb34721b0e661f7d3558aa512097b1c1ade6d --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/dill/tests/test_selected.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python +# +# Author: Mike McKerns (mmckerns @caltech and @uqfoundation) +# Copyright (c) 2008-2016 California Institute of Technology. +# Copyright (c) 2016-2026 The Uncertainty Quantification Foundation. +# License: 3-clause BSD. The full license text is available at: +# - https://github.com/uqfoundation/dill/blob/master/LICENSE +""" +testing some selected object types +""" + +import dill +dill.settings['recurse'] = True + +verbose = False + +def test_dict_contents(): + c = type.__dict__ + for i,j in c.items(): + #try: + ok = dill.pickles(j) + #except Exception: + # print ("FAIL: %s with %s" % (i, dill.detect.errors(j))) + if verbose: print ("%s: %s, %s" % (ok, type(j), j)) + assert ok + if verbose: print ("") + +def _g(x): yield x; + +def _f(): + try: raise + except Exception: + from sys import exc_info + e, er, tb = exc_info() + return er, tb + +class _d(object): + def _method(self): + pass + +from dill import objects +from dill import load_types +load_types(pickleable=True,unpickleable=False) +_newclass = objects['ClassObjectType'] +# some clean-up #FIXME: should happen internal to dill +objects['TemporaryFileType'].close() +objects['FileType'].close() +del objects + +# getset_descriptor for new-style classes (fails on '_method', if not __main__) +def test_class_descriptors(): + d = _d.__dict__ + for i in d.values(): + ok = dill.pickles(i) + if verbose: print ("%s: %s, %s" % (ok, type(i), i)) + assert ok + if verbose: print ("") + od = _newclass.__dict__ + for i in od.values(): + ok = dill.pickles(i) + if verbose: print ("%s: %s, %s" % (ok, type(i), i)) + assert ok + if verbose: print ("") + +# (__main__) class instance for new-style classes +def test_class(): + o = _d() + oo = _newclass() + ok = dill.pickles(o) + if verbose: print ("%s: %s, %s" % (ok, type(o), o)) + assert ok + ok = dill.pickles(oo) + if verbose: print ("%s: %s, %s" % (ok, type(oo), oo)) + assert ok + if verbose: print ("") + +# frames, generators, and tracebacks (all depend on frame) +def test_frame_related(): + g = _g(1) + f = g.gi_frame + e,t = _f() + _is = lambda ok: ok + ok = dill.pickles(f) + if verbose: print ("%s: %s, %s" % (ok, type(f), f)) + assert not ok + ok = dill.pickles(g) + if verbose: print ("%s: %s, %s" % (ok, type(g), g)) + assert _is(not ok) #XXX: dill fails + ok = dill.pickles(t) + if verbose: print ("%s: %s, %s" % (ok, type(t), t)) + assert not ok #XXX: dill fails + ok = dill.pickles(e) + if verbose: print ("%s: %s, %s" % (ok, type(e), e)) + assert ok + if verbose: print ("") + +def test_typing(): + import typing + x = typing.Any + assert x == dill.copy(x) + x = typing.Dict[int, str] + assert x == dill.copy(x) + x = typing.List[int] + assert x == dill.copy(x) + x = typing.Tuple[int, str] + assert x == dill.copy(x) + x = typing.Tuple[int] + assert x == dill.copy(x) + x = typing.Tuple[()] + assert x == dill.copy(x) + x = typing.Tuple[()].copy_with(()) + assert x == dill.copy(x) + return + + +if __name__ == '__main__': + test_frame_related() + test_dict_contents() + test_class() + test_class_descriptors() + test_typing() diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/fsspec-2026.2.0.dist-info/INSTALLER b/bioagent-bench/.venv/lib/python3.14/site-packages/fsspec-2026.2.0.dist-info/INSTALLER new file mode 100644 index 0000000000000000000000000000000000000000..5c69047b2eb8235994febeeae1da4a82365a240a --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/fsspec-2026.2.0.dist-info/INSTALLER @@ -0,0 +1 @@ +uv \ No newline at end of file diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/fsspec-2026.2.0.dist-info/METADATA b/bioagent-bench/.venv/lib/python3.14/site-packages/fsspec-2026.2.0.dist-info/METADATA new file mode 100644 index 0000000000000000000000000000000000000000..bb96eb3cf23a281f3ea8c7e1fe1c8a2a1fcaa2f5 --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/fsspec-2026.2.0.dist-info/METADATA @@ -0,0 +1,257 @@ +Metadata-Version: 2.4 +Name: fsspec +Version: 2026.2.0 +Summary: File-system specification +Project-URL: Changelog, https://filesystem-spec.readthedocs.io/en/latest/changelog.html +Project-URL: Documentation, https://filesystem-spec.readthedocs.io/en/latest/ +Project-URL: Homepage, https://github.com/fsspec/filesystem_spec +Maintainer-email: Martin Durant +License-Expression: BSD-3-Clause +License-File: LICENSE +Keywords: file +Classifier: Development Status :: 4 - Beta +Classifier: Intended Audience :: Developers +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3.12 +Classifier: Programming Language :: Python :: 3.13 +Classifier: Programming Language :: Python :: 3.14 +Requires-Python: >=3.10 +Provides-Extra: abfs +Requires-Dist: adlfs; extra == 'abfs' +Provides-Extra: adl +Requires-Dist: adlfs; extra == 'adl' +Provides-Extra: arrow +Requires-Dist: pyarrow>=1; extra == 'arrow' +Provides-Extra: dask +Requires-Dist: dask; extra == 'dask' +Requires-Dist: distributed; extra == 'dask' +Provides-Extra: dev +Requires-Dist: pre-commit; extra == 'dev' +Requires-Dist: ruff>=0.5; extra == 'dev' +Provides-Extra: doc +Requires-Dist: numpydoc; extra == 'doc' +Requires-Dist: sphinx; extra == 'doc' +Requires-Dist: sphinx-design; extra == 'doc' +Requires-Dist: sphinx-rtd-theme; extra == 'doc' +Requires-Dist: yarl; extra == 'doc' +Provides-Extra: dropbox +Requires-Dist: dropbox; extra == 'dropbox' +Requires-Dist: dropboxdrivefs; extra == 'dropbox' +Requires-Dist: requests; extra == 'dropbox' +Provides-Extra: entrypoints +Provides-Extra: full +Requires-Dist: adlfs; extra == 'full' +Requires-Dist: aiohttp!=4.0.0a0,!=4.0.0a1; extra == 'full' +Requires-Dist: dask; extra == 'full' +Requires-Dist: distributed; extra == 'full' +Requires-Dist: dropbox; extra == 'full' +Requires-Dist: dropboxdrivefs; extra == 'full' +Requires-Dist: fusepy; extra == 'full' +Requires-Dist: gcsfs>2024.2.0; extra == 'full' +Requires-Dist: libarchive-c; extra == 'full' +Requires-Dist: ocifs; extra == 'full' +Requires-Dist: panel; extra == 'full' +Requires-Dist: paramiko; extra == 'full' +Requires-Dist: pyarrow>=1; extra == 'full' +Requires-Dist: pygit2; extra == 'full' +Requires-Dist: requests; extra == 'full' +Requires-Dist: s3fs>2024.2.0; extra == 'full' +Requires-Dist: smbprotocol; extra == 'full' +Requires-Dist: tqdm; extra == 'full' +Provides-Extra: fuse +Requires-Dist: fusepy; extra == 'fuse' +Provides-Extra: gcs +Requires-Dist: gcsfs>2024.2.0; extra == 'gcs' +Provides-Extra: git +Requires-Dist: pygit2; extra == 'git' +Provides-Extra: github +Requires-Dist: requests; extra == 'github' +Provides-Extra: gs +Requires-Dist: gcsfs; extra == 'gs' +Provides-Extra: gui +Requires-Dist: panel; extra == 'gui' +Provides-Extra: hdfs +Requires-Dist: pyarrow>=1; extra == 'hdfs' +Provides-Extra: http +Requires-Dist: aiohttp!=4.0.0a0,!=4.0.0a1; extra == 'http' +Provides-Extra: libarchive +Requires-Dist: libarchive-c; extra == 'libarchive' +Provides-Extra: oci +Requires-Dist: ocifs; extra == 'oci' +Provides-Extra: s3 +Requires-Dist: s3fs>2024.2.0; extra == 's3' +Provides-Extra: sftp +Requires-Dist: paramiko; extra == 'sftp' +Provides-Extra: smb +Requires-Dist: smbprotocol; extra == 'smb' +Provides-Extra: ssh +Requires-Dist: paramiko; extra == 'ssh' +Provides-Extra: test +Requires-Dist: aiohttp!=4.0.0a0,!=4.0.0a1; extra == 'test' +Requires-Dist: numpy; extra == 'test' +Requires-Dist: pytest; extra == 'test' +Requires-Dist: pytest-asyncio!=0.22.0; extra == 'test' +Requires-Dist: pytest-benchmark; extra == 'test' +Requires-Dist: pytest-cov; extra == 'test' +Requires-Dist: pytest-mock; extra == 'test' +Requires-Dist: pytest-recording; extra == 'test' +Requires-Dist: pytest-rerunfailures; extra == 'test' +Requires-Dist: requests; extra == 'test' +Provides-Extra: test-downstream +Requires-Dist: aiobotocore<3.0.0,>=2.5.4; extra == 'test-downstream' +Requires-Dist: dask[dataframe,test]; extra == 'test-downstream' +Requires-Dist: moto[server]<5,>4; extra == 'test-downstream' +Requires-Dist: pytest-timeout; extra == 'test-downstream' +Requires-Dist: xarray; extra == 'test-downstream' +Provides-Extra: test-full +Requires-Dist: adlfs; extra == 'test-full' +Requires-Dist: aiohttp!=4.0.0a0,!=4.0.0a1; extra == 'test-full' +Requires-Dist: backports-zstd; (python_version < '3.14') and extra == 'test-full' +Requires-Dist: cloudpickle; extra == 'test-full' +Requires-Dist: dask; extra == 'test-full' +Requires-Dist: distributed; extra == 'test-full' +Requires-Dist: dropbox; extra == 'test-full' +Requires-Dist: dropboxdrivefs; extra == 'test-full' +Requires-Dist: fastparquet; extra == 'test-full' +Requires-Dist: fusepy; extra == 'test-full' +Requires-Dist: gcsfs; extra == 'test-full' +Requires-Dist: jinja2; extra == 'test-full' +Requires-Dist: kerchunk; extra == 'test-full' +Requires-Dist: libarchive-c; extra == 'test-full' +Requires-Dist: lz4; extra == 'test-full' +Requires-Dist: notebook; extra == 'test-full' +Requires-Dist: numpy; extra == 'test-full' +Requires-Dist: ocifs; extra == 'test-full' +Requires-Dist: pandas<3.0.0; extra == 'test-full' +Requires-Dist: panel; extra == 'test-full' +Requires-Dist: paramiko; extra == 'test-full' +Requires-Dist: pyarrow; extra == 'test-full' +Requires-Dist: pyarrow>=1; extra == 'test-full' +Requires-Dist: pyftpdlib; extra == 'test-full' +Requires-Dist: pygit2; extra == 'test-full' +Requires-Dist: pytest; extra == 'test-full' +Requires-Dist: pytest-asyncio!=0.22.0; extra == 'test-full' +Requires-Dist: pytest-benchmark; extra == 'test-full' +Requires-Dist: pytest-cov; extra == 'test-full' +Requires-Dist: pytest-mock; extra == 'test-full' +Requires-Dist: pytest-recording; extra == 'test-full' +Requires-Dist: pytest-rerunfailures; extra == 'test-full' +Requires-Dist: python-snappy; extra == 'test-full' +Requires-Dist: requests; extra == 'test-full' +Requires-Dist: smbprotocol; extra == 'test-full' +Requires-Dist: tqdm; extra == 'test-full' +Requires-Dist: urllib3; extra == 'test-full' +Requires-Dist: zarr; extra == 'test-full' +Requires-Dist: zstandard; (python_version < '3.14') and extra == 'test-full' +Provides-Extra: tqdm +Requires-Dist: tqdm; extra == 'tqdm' +Description-Content-Type: text/markdown + +# filesystem_spec + +[![PyPI version](https://badge.fury.io/py/fsspec.svg)](https://pypi.python.org/pypi/fsspec/) +[![Anaconda-Server Badge](https://anaconda.org/conda-forge/fsspec/badges/version.svg)](https://anaconda.org/conda-forge/fsspec) +![Build](https://github.com/fsspec/filesystem_spec/workflows/CI/badge.svg) +[![Docs](https://readthedocs.org/projects/filesystem-spec/badge/?version=latest)](https://filesystem-spec.readthedocs.io/en/latest/?badge=latest) + +A specification for pythonic filesystems. + +## Install + +```bash +pip install fsspec +``` + +would install the base fsspec. Various optionally supported features might require specification of custom +extra require, e.g. `pip install fsspec[ssh]` will install dependencies for `ssh` backends support. +Use `pip install fsspec[full]` for installation of all known extra dependencies. + +Up-to-date package also provided through conda-forge distribution: + +```bash +conda install -c conda-forge fsspec +``` + + +## Purpose + +To produce a template or specification for a file-system interface, that specific implementations should follow, +so that applications making use of them can rely on a common behaviour and not have to worry about the specific +internal implementation decisions with any given backend. Many such implementations are included in this package, +or in sister projects such as `s3fs` and `gcsfs`. + +In addition, if this is well-designed, then additional functionality, such as a key-value store or FUSE +mounting of the file-system implementation may be available for all implementations "for free". + +## Documentation + +Please refer to [RTD](https://filesystem-spec.readthedocs.io/en/latest/?badge=latest) + +## Develop + +fsspec uses GitHub Actions for CI. Environment files can be found +in the "ci/" directory. Note that the main environment is called "py38", +but it is expected that the version of python installed be adjustable at +CI runtime. For local use, pick a version suitable for you. + +```bash +# For a new environment (mamba / conda). +mamba create -n fsspec -c conda-forge python=3.10 -y +conda activate fsspec + +# Standard dev install with docs and tests. +pip install -e ".[dev,doc,test]" + +# Full tests except for downstream +pip install s3fs +pip uninstall s3fs +pip install -e .[dev,doc,test_full] +pip install s3fs --no-deps +pytest -v + +# Downstream tests. +sh install_s3fs.sh +# Windows powershell. +install_s3fs.sh +``` + +### Testing + +Tests can be run in the dev environment, if activated, via ``pytest fsspec``. + +The full fsspec suite requires a system-level docker, docker-compose, and fuse +installation. If only making changes to one backend implementation, it is +not generally necessary to run all tests locally. + +It is expected that contributors ensure that any change to fsspec does not +cause issues or regressions for either other fsspec-related packages such +as gcsfs and s3fs, nor for downstream users of fsspec. The "downstream" CI +run and corresponding environment file run a set of tests from the dask +test suite, and very minimal tests against pandas and zarr from the +test_downstream.py module in this repo. + +### Code Formatting + +fsspec uses [Black](https://black.readthedocs.io/en/stable) to ensure +a consistent code format throughout the project. +Run ``black fsspec`` from the root of the filesystem_spec repository to +auto-format your code. Additionally, many editors have plugins that will apply +``black`` as you edit files. ``black`` is included in the ``tox`` environments. + +Optionally, you may wish to setup [pre-commit hooks](https://pre-commit.com) to +automatically run ``black`` when you make a git commit. +Run ``pre-commit install --install-hooks`` from the root of the +filesystem_spec repository to setup pre-commit hooks. ``black`` will now be run +before you commit, reformatting any changed files. You can format without +committing via ``pre-commit run`` or skip these checks with ``git commit +--no-verify``. + +## Support + +Work on this repository is supported in part by: + +"Anaconda, Inc. - Advancing AI through open source." + +anaconda logo diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/fsspec-2026.2.0.dist-info/RECORD b/bioagent-bench/.venv/lib/python3.14/site-packages/fsspec-2026.2.0.dist-info/RECORD new file mode 100644 index 0000000000000000000000000000000000000000..b4e6cc055d592bea4bf7405b7d955bb30c887d00 --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/fsspec-2026.2.0.dist-info/RECORD @@ -0,0 +1,63 @@ +fsspec-2026.2.0.dist-info/INSTALLER,sha256=5hhM4Q4mYTT9z6QB6PGpUAW81PGNFrYrdXMj4oM_6ak,2 +fsspec-2026.2.0.dist-info/METADATA,sha256=Pw6QhbyXeg-elb0hpWPiQRpAeMD_ApJ9vdNFoYCnrPs,10524 +fsspec-2026.2.0.dist-info/RECORD,, +fsspec-2026.2.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +fsspec-2026.2.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87 +fsspec-2026.2.0.dist-info/licenses/LICENSE,sha256=LcNUls5TpzB5FcAIqESq1T53K0mzTN0ARFBnaRQH7JQ,1513 +fsspec/__init__.py,sha256=L7qwNBU1iMNQd8Of87HYSNFT9gWlNMSESaJC8fY0AaQ,2053 +fsspec/_version.py,sha256=AEamMn8IHx_wGXrogRYVBycv6M5u2_UCmFedn7R8hYI,710 +fsspec/archive.py,sha256=vM6t_lgV6lBWbBYwpm3S4ofBQFQxUPr5KkDQrrQcQro,2411 +fsspec/asyn.py,sha256=LP_OicTWXmKHe31wBoYs2MrrNf8rmlhjVeGg5AqvVy8,36630 +fsspec/caching.py,sha256=8IJ4rgcWnvq_b_DqlcMGJ-K59d4Db5O9Gz8PkATAgHo,34023 +fsspec/callbacks.py,sha256=BDIwLzK6rr_0V5ch557fSzsivCElpdqhXr5dZ9Te-EE,9210 +fsspec/compression.py,sha256=3v_Fe39gzRRWfaeXpzNjAGPqgTzmETYRCo3qHVqD3po,5132 +fsspec/config.py,sha256=LF4Zmu1vhJW7Je9Q-cwkRc3xP7Rhyy7Xnwj26Z6sv2g,4279 +fsspec/conftest.py,sha256=uWfm_Qs5alPRxOhRpDfQ0-1jqSJ54pni4y96IxOREXM,3446 +fsspec/core.py,sha256=lc7XSnZU6_C6xljp7Z_xEGN3V7704hbeQLkxvPP0wds,24173 +fsspec/dircache.py,sha256=YzogWJrhEastHU7vWz-cJiJ7sdtLXFXhEpInGKd4EcM,2717 +fsspec/exceptions.py,sha256=pauSLDMxzTJMOjvX1WEUK0cMyFkrFxpWJsyFywav7A8,331 +fsspec/fuse.py,sha256=Q-3NOOyLqBfYa4Db5E19z_ZY36zzYHtIs1mOUasItBQ,10177 +fsspec/generic.py,sha256=9QHQYMNb-8w8-eYuIqShcTjO_LeHXFoQTyt8J5oEq5Q,13482 +fsspec/gui.py,sha256=CQ7QsrTpaDlWSLNOpwNoJc7khOcYXIZxmrAJN9bHWQU,14002 +fsspec/implementations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +fsspec/implementations/arrow.py,sha256=8FhvcvOYLZNMMegCYFFCEHgEqig8AkOU7Ehb8XfcgnA,8890 +fsspec/implementations/asyn_wrapper.py,sha256=3lfJkGs6D_AwRBdxTSYlL-RCVdaXBZ9Itys2P5o5Si0,3738 +fsspec/implementations/cache_mapper.py,sha256=W4wlxyPxZbSp9ItJ0pYRVBMh6bw9eFypgP6kUYuuiI4,2421 +fsspec/implementations/cache_metadata.py,sha256=ipIe4S8nlU_M9oRJkvTqr-b0tcbXVZsxH3GxaelaNOY,8502 +fsspec/implementations/cached.py,sha256=67ipbj-3o8O1zMGR11rZ_IWCi_7h-VRYpEAowFXqrvA,36175 +fsspec/implementations/chained.py,sha256=iGivpNaHUFjB_ea0-HAPhcmm6CL8qnDf270PSj7JwuE,680 +fsspec/implementations/dask.py,sha256=CXZbJzIVOhKV8ILcxuy3bTvcacCueAbyQxmvAkbPkrk,4466 +fsspec/implementations/data.py,sha256=IhOGDkacYp5gkl9jhEu4msQfZPb0gS5Q_ml7Mbr6dgQ,1627 +fsspec/implementations/dbfs.py,sha256=1cvvC6KBWOb8pBVpc01xavVbEPXO1xsgZvPD7H73M9k,16217 +fsspec/implementations/dirfs.py,sha256=VNj6gPMfmmLPK4wxbtxt7mUqW7xkh2XDgMmEmSK_E1c,12166 +fsspec/implementations/ftp.py,sha256=fJhaMIKq2RvzYlLwG3bewy2jq4iRqjVt1aIpwtUIRwI,13235 +fsspec/implementations/gist.py,sha256=Y6jTDrE-wuTwvpPyAQDuuOMBGxlajafKWoB1_yX6jdY,8528 +fsspec/implementations/git.py,sha256=qBDWMz5LNllPqVjr5jf_1FuNha4P5lyQI3IlhYg-wUE,3731 +fsspec/implementations/github.py,sha256=aCsZL8UvXZgdkcB1RUs3DdLeNrjLKcFsFYeQFDWbBFo,11653 +fsspec/implementations/http.py,sha256=-AV5qeNpBWqnsmgnIO9Ily9B6--SR4sQJ7G4cBHarGE,30675 +fsspec/implementations/http_sync.py,sha256=UmBqd938ebwVjYgVtzg-ysG3ZoGhIJw0wFtQAfxV3Aw,30332 +fsspec/implementations/jupyter.py,sha256=q1PlQ66AAswGFyr8MFKWyobaV2YekMWRtqENBDQtD28,4002 +fsspec/implementations/libarchive.py,sha256=SpIA1F-zf7kb2-VYUVuhMrXTBOhBxUXKgEW1RaAdDoA,7098 +fsspec/implementations/local.py,sha256=ERDUdXdRI8AvRX06icXaDKwO-hcQgivc7EorqnayFFM,17028 +fsspec/implementations/memory.py,sha256=TDdLtSPWXxZKrrVGwmc3uS3oK_2mlcVTk2BiqR8IeII,10507 +fsspec/implementations/reference.py,sha256=xSUpB8o_QFAZiVJE2dt78QZMCUMLo5TaJ27e5DwDAfg,48814 +fsspec/implementations/sftp.py,sha256=L9pZOa6eLUWfJNtxkxeG2YI96SQwrM5Hj6ocyUZXUbg,5923 +fsspec/implementations/smb.py,sha256=5fhu8h06nOLBPh2c48aT7WBRqh9cEcbIwtyu06wTjec,15236 +fsspec/implementations/tar.py,sha256=dam78Tp_CozybNqCY2JYgGBS3Uc9FuJUAT9oB0lolOs,4111 +fsspec/implementations/webhdfs.py,sha256=osF2m0nhDil6sbMzYW_4DZzhxF4ygtb59XDiybd9Fyg,17589 +fsspec/implementations/zip.py,sha256=6f3z0s12tDbz1RMx7iDc3JDx730IAaKDdx7tf_XYDp0,6151 +fsspec/json.py,sha256=4EBZ-xOmRiyxmIqPIwxmDImosRQ7io7qBM2xjJPsEE4,3768 +fsspec/mapping.py,sha256=m2ndB_gtRBXYmNJg0Ie1-BVR75TFleHmIQBzC-yWhjU,8343 +fsspec/parquet.py,sha256=xGW3xfd9js7hrre7qN85XpSM0A1FObqkTcAv_H2xSwY,20505 +fsspec/registry.py,sha256=o7EGl8TEaLkcwN53X_103arzuzJeeOoVaNUWnPiXgf0,12148 +fsspec/spec.py,sha256=Ym-Ust6LRjHgbhrmvNqwOBZxoVnaw3g3xHXMZGHx_xg,77692 +fsspec/tests/abstract/__init__.py,sha256=4xUJrv7gDgc85xAOz1p-V_K1hrsdMWTSa0rviALlJk8,10181 +fsspec/tests/abstract/common.py,sha256=1GQwNo5AONzAnzZj0fWgn8NJPLXALehbsuGxS3FzWVU,4973 +fsspec/tests/abstract/copy.py,sha256=gU5-d97U3RSde35Vp4RxPY4rWwL744HiSrJ8IBOp9-8,19967 +fsspec/tests/abstract/get.py,sha256=vNR4HztvTR7Cj56AMo7_tx7TeYz1Jgr_2Wb8Lv-UiBY,20755 +fsspec/tests/abstract/mv.py,sha256=k8eUEBIrRrGMsBY5OOaDXdGnQUKGwDIfQyduB6YD3Ns,1982 +fsspec/tests/abstract/open.py,sha256=Fi2PBPYLbRqysF8cFm0rwnB41kMdQVYjq8cGyDXp3BU,329 +fsspec/tests/abstract/pipe.py,sha256=LFzIrLCB5GLXf9rzFKJmE8AdG7LQ_h4bJo70r8FLPqM,402 +fsspec/tests/abstract/put.py,sha256=7aih17OKB_IZZh1Mkq1eBDIjobhtMQmI8x-Pw-S_aZk,21201 +fsspec/transaction.py,sha256=xliRG6U2Zf3khG4xcw9WiB-yAoqJSHEGK_VjHOdtgo0,2398 +fsspec/utils.py,sha256=E24ji0XLWC6n3bw2sHA28OYxrGU9Wy_al2XydsRgrRk,23623 diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/fsspec-2026.2.0.dist-info/REQUESTED b/bioagent-bench/.venv/lib/python3.14/site-packages/fsspec-2026.2.0.dist-info/REQUESTED new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/fsspec-2026.2.0.dist-info/WHEEL b/bioagent-bench/.venv/lib/python3.14/site-packages/fsspec-2026.2.0.dist-info/WHEEL new file mode 100644 index 0000000000000000000000000000000000000000..ae8ec1bdaa94d726ceb907542d76cbd5d38cafcd --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/fsspec-2026.2.0.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: hatchling 1.28.0 +Root-Is-Purelib: true +Tag: py3-none-any diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/fsspec-2026.2.0.dist-info/licenses/LICENSE b/bioagent-bench/.venv/lib/python3.14/site-packages/fsspec-2026.2.0.dist-info/licenses/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..67590a5e5be5a5a2dde3fe53a7512e404a896c22 --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/fsspec-2026.2.0.dist-info/licenses/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2018, Martin Durant +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/h11/__init__.py b/bioagent-bench/.venv/lib/python3.14/site-packages/h11/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..989e92c3458681a6f0be72ae4105ea742750d328 --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/h11/__init__.py @@ -0,0 +1,62 @@ +# A highish-level implementation of the HTTP/1.1 wire protocol (RFC 7230), +# containing no networking code at all, loosely modelled on hyper-h2's generic +# implementation of HTTP/2 (and in particular the h2.connection.H2Connection +# class). There's still a bunch of subtle details you need to get right if you +# want to make this actually useful, because it doesn't implement all the +# semantics to check that what you're asking to write to the wire is sensible, +# but at least it gets you out of dealing with the wire itself. + +from h11._connection import Connection, NEED_DATA, PAUSED +from h11._events import ( + ConnectionClosed, + Data, + EndOfMessage, + Event, + InformationalResponse, + Request, + Response, +) +from h11._state import ( + CLIENT, + CLOSED, + DONE, + ERROR, + IDLE, + MIGHT_SWITCH_PROTOCOL, + MUST_CLOSE, + SEND_BODY, + SEND_RESPONSE, + SERVER, + SWITCHED_PROTOCOL, +) +from h11._util import LocalProtocolError, ProtocolError, RemoteProtocolError +from h11._version import __version__ + +PRODUCT_ID = "python-h11/" + __version__ + + +__all__ = ( + "Connection", + "NEED_DATA", + "PAUSED", + "ConnectionClosed", + "Data", + "EndOfMessage", + "Event", + "InformationalResponse", + "Request", + "Response", + "CLIENT", + "CLOSED", + "DONE", + "ERROR", + "IDLE", + "MUST_CLOSE", + "SEND_BODY", + "SEND_RESPONSE", + "SERVER", + "SWITCHED_PROTOCOL", + "ProtocolError", + "LocalProtocolError", + "RemoteProtocolError", +) diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/h11/_abnf.py b/bioagent-bench/.venv/lib/python3.14/site-packages/h11/_abnf.py new file mode 100644 index 0000000000000000000000000000000000000000..933587fba22290d7eb7df4c88e12f1e61702b8ce --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/h11/_abnf.py @@ -0,0 +1,132 @@ +# We use native strings for all the re patterns, to take advantage of string +# formatting, and then convert to bytestrings when compiling the final re +# objects. + +# https://svn.tools.ietf.org/svn/wg/httpbis/specs/rfc7230.html#whitespace +# OWS = *( SP / HTAB ) +# ; optional whitespace +OWS = r"[ \t]*" + +# https://svn.tools.ietf.org/svn/wg/httpbis/specs/rfc7230.html#rule.token.separators +# token = 1*tchar +# +# tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" +# / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~" +# / DIGIT / ALPHA +# ; any VCHAR, except delimiters +token = r"[-!#$%&'*+.^_`|~0-9a-zA-Z]+" + +# https://svn.tools.ietf.org/svn/wg/httpbis/specs/rfc7230.html#header.fields +# field-name = token +field_name = token + +# The standard says: +# +# field-value = *( field-content / obs-fold ) +# field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ] +# field-vchar = VCHAR / obs-text +# obs-fold = CRLF 1*( SP / HTAB ) +# ; obsolete line folding +# ; see Section 3.2.4 +# +# https://tools.ietf.org/html/rfc5234#appendix-B.1 +# +# VCHAR = %x21-7E +# ; visible (printing) characters +# +# https://svn.tools.ietf.org/svn/wg/httpbis/specs/rfc7230.html#rule.quoted-string +# obs-text = %x80-FF +# +# However, the standard definition of field-content is WRONG! It disallows +# fields containing a single visible character surrounded by whitespace, +# e.g. "foo a bar". +# +# See: https://www.rfc-editor.org/errata_search.php?rfc=7230&eid=4189 +# +# So our definition of field_content attempts to fix it up... +# +# Also, we allow lots of control characters, because apparently people assume +# that they're legal in practice (e.g., google analytics makes cookies with +# \x01 in them!): +# https://github.com/python-hyper/h11/issues/57 +# We still don't allow NUL or whitespace, because those are often treated as +# meta-characters and letting them through can lead to nasty issues like SSRF. +vchar = r"[\x21-\x7e]" +vchar_or_obs_text = r"[^\x00\s]" +field_vchar = vchar_or_obs_text +field_content = r"{field_vchar}+(?:[ \t]+{field_vchar}+)*".format(**globals()) + +# We handle obs-fold at a different level, and our fixed-up field_content +# already grows to swallow the whole value, so ? instead of * +field_value = r"({field_content})?".format(**globals()) + +# header-field = field-name ":" OWS field-value OWS +header_field = ( + r"(?P{field_name})" + r":" + r"{OWS}" + r"(?P{field_value})" + r"{OWS}".format(**globals()) +) + +# https://svn.tools.ietf.org/svn/wg/httpbis/specs/rfc7230.html#request.line +# +# request-line = method SP request-target SP HTTP-version CRLF +# method = token +# HTTP-version = HTTP-name "/" DIGIT "." DIGIT +# HTTP-name = %x48.54.54.50 ; "HTTP", case-sensitive +# +# request-target is complicated (see RFC 7230 sec 5.3) -- could be path, full +# URL, host+port (for connect), or even "*", but in any case we are guaranteed +# that it contists of the visible printing characters. +method = token +request_target = r"{vchar}+".format(**globals()) +http_version = r"HTTP/(?P[0-9]\.[0-9])" +request_line = ( + r"(?P{method})" + r" " + r"(?P{request_target})" + r" " + r"{http_version}".format(**globals()) +) + +# https://svn.tools.ietf.org/svn/wg/httpbis/specs/rfc7230.html#status.line +# +# status-line = HTTP-version SP status-code SP reason-phrase CRLF +# status-code = 3DIGIT +# reason-phrase = *( HTAB / SP / VCHAR / obs-text ) +status_code = r"[0-9]{3}" +reason_phrase = r"([ \t]|{vchar_or_obs_text})*".format(**globals()) +status_line = ( + r"{http_version}" + r" " + r"(?P{status_code})" + # However, there are apparently a few too many servers out there that just + # leave out the reason phrase: + # https://github.com/scrapy/scrapy/issues/345#issuecomment-281756036 + # https://github.com/seanmonstar/httparse/issues/29 + # so make it optional. ?: is a non-capturing group. + r"(?: (?P{reason_phrase}))?".format(**globals()) +) + +HEXDIG = r"[0-9A-Fa-f]" +# Actually +# +# chunk-size = 1*HEXDIG +# +# but we impose an upper-limit to avoid ridiculosity. len(str(2**64)) == 20 +chunk_size = r"({HEXDIG}){{1,20}}".format(**globals()) +# Actually +# +# chunk-ext = *( ";" chunk-ext-name [ "=" chunk-ext-val ] ) +# +# but we aren't parsing the things so we don't really care. +chunk_ext = r";.*" +chunk_header = ( + r"(?P{chunk_size})" + r"(?P{chunk_ext})?" + r"{OWS}\r\n".format( + **globals() + ) # Even though the specification does not allow for extra whitespaces, + # we are lenient with trailing whitespaces because some servers on the wild use it. +) diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/h11/_events.py b/bioagent-bench/.venv/lib/python3.14/site-packages/h11/_events.py new file mode 100644 index 0000000000000000000000000000000000000000..ca1c3adbde2c4e7710482a18e3471f91f1da610e --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/h11/_events.py @@ -0,0 +1,369 @@ +# High level events that make up HTTP/1.1 conversations. Loosely inspired by +# the corresponding events in hyper-h2: +# +# http://python-hyper.org/h2/en/stable/api.html#events +# +# Don't subclass these. Stuff will break. + +import re +from abc import ABC +from dataclasses import dataclass +from typing import List, Tuple, Union + +from ._abnf import method, request_target +from ._headers import Headers, normalize_and_validate +from ._util import bytesify, LocalProtocolError, validate + +# Everything in __all__ gets re-exported as part of the h11 public API. +__all__ = [ + "Event", + "Request", + "InformationalResponse", + "Response", + "Data", + "EndOfMessage", + "ConnectionClosed", +] + +method_re = re.compile(method.encode("ascii")) +request_target_re = re.compile(request_target.encode("ascii")) + + +class Event(ABC): + """ + Base class for h11 events. + """ + + __slots__ = () + + +@dataclass(init=False, frozen=True) +class Request(Event): + """The beginning of an HTTP request. + + Fields: + + .. attribute:: method + + An HTTP method, e.g. ``b"GET"`` or ``b"POST"``. Always a byte + string. :term:`Bytes-like objects ` and native + strings containing only ascii characters will be automatically + converted to byte strings. + + .. attribute:: target + + The target of an HTTP request, e.g. ``b"/index.html"``, or one of the + more exotic formats described in `RFC 7320, section 5.3 + `_. Always a byte + string. :term:`Bytes-like objects ` and native + strings containing only ascii characters will be automatically + converted to byte strings. + + .. attribute:: headers + + Request headers, represented as a list of (name, value) pairs. See + :ref:`the header normalization rules ` for details. + + .. attribute:: http_version + + The HTTP protocol version, represented as a byte string like + ``b"1.1"``. See :ref:`the HTTP version normalization rules + ` for details. + + """ + + __slots__ = ("method", "headers", "target", "http_version") + + method: bytes + headers: Headers + target: bytes + http_version: bytes + + def __init__( + self, + *, + method: Union[bytes, str], + headers: Union[Headers, List[Tuple[bytes, bytes]], List[Tuple[str, str]]], + target: Union[bytes, str], + http_version: Union[bytes, str] = b"1.1", + _parsed: bool = False, + ) -> None: + super().__init__() + if isinstance(headers, Headers): + object.__setattr__(self, "headers", headers) + else: + object.__setattr__( + self, "headers", normalize_and_validate(headers, _parsed=_parsed) + ) + if not _parsed: + object.__setattr__(self, "method", bytesify(method)) + object.__setattr__(self, "target", bytesify(target)) + object.__setattr__(self, "http_version", bytesify(http_version)) + else: + object.__setattr__(self, "method", method) + object.__setattr__(self, "target", target) + object.__setattr__(self, "http_version", http_version) + + # "A server MUST respond with a 400 (Bad Request) status code to any + # HTTP/1.1 request message that lacks a Host header field and to any + # request message that contains more than one Host header field or a + # Host header field with an invalid field-value." + # -- https://tools.ietf.org/html/rfc7230#section-5.4 + host_count = 0 + for name, value in self.headers: + if name == b"host": + host_count += 1 + if self.http_version == b"1.1" and host_count == 0: + raise LocalProtocolError("Missing mandatory Host: header") + if host_count > 1: + raise LocalProtocolError("Found multiple Host: headers") + + validate(method_re, self.method, "Illegal method characters") + validate(request_target_re, self.target, "Illegal target characters") + + # This is an unhashable type. + __hash__ = None # type: ignore + + +@dataclass(init=False, frozen=True) +class _ResponseBase(Event): + __slots__ = ("headers", "http_version", "reason", "status_code") + + headers: Headers + http_version: bytes + reason: bytes + status_code: int + + def __init__( + self, + *, + headers: Union[Headers, List[Tuple[bytes, bytes]], List[Tuple[str, str]]], + status_code: int, + http_version: Union[bytes, str] = b"1.1", + reason: Union[bytes, str] = b"", + _parsed: bool = False, + ) -> None: + super().__init__() + if isinstance(headers, Headers): + object.__setattr__(self, "headers", headers) + else: + object.__setattr__( + self, "headers", normalize_and_validate(headers, _parsed=_parsed) + ) + if not _parsed: + object.__setattr__(self, "reason", bytesify(reason)) + object.__setattr__(self, "http_version", bytesify(http_version)) + if not isinstance(status_code, int): + raise LocalProtocolError("status code must be integer") + # Because IntEnum objects are instances of int, but aren't + # duck-compatible (sigh), see gh-72. + object.__setattr__(self, "status_code", int(status_code)) + else: + object.__setattr__(self, "reason", reason) + object.__setattr__(self, "http_version", http_version) + object.__setattr__(self, "status_code", status_code) + + self.__post_init__() + + def __post_init__(self) -> None: + pass + + # This is an unhashable type. + __hash__ = None # type: ignore + + +@dataclass(init=False, frozen=True) +class InformationalResponse(_ResponseBase): + """An HTTP informational response. + + Fields: + + .. attribute:: status_code + + The status code of this response, as an integer. For an + :class:`InformationalResponse`, this is always in the range [100, + 200). + + .. attribute:: headers + + Request headers, represented as a list of (name, value) pairs. See + :ref:`the header normalization rules ` for + details. + + .. attribute:: http_version + + The HTTP protocol version, represented as a byte string like + ``b"1.1"``. See :ref:`the HTTP version normalization rules + ` for details. + + .. attribute:: reason + + The reason phrase of this response, as a byte string. For example: + ``b"OK"``, or ``b"Not Found"``. + + """ + + def __post_init__(self) -> None: + if not (100 <= self.status_code < 200): + raise LocalProtocolError( + "InformationalResponse status_code should be in range " + "[100, 200), not {}".format(self.status_code) + ) + + # This is an unhashable type. + __hash__ = None # type: ignore + + +@dataclass(init=False, frozen=True) +class Response(_ResponseBase): + """The beginning of an HTTP response. + + Fields: + + .. attribute:: status_code + + The status code of this response, as an integer. For an + :class:`Response`, this is always in the range [200, + 1000). + + .. attribute:: headers + + Request headers, represented as a list of (name, value) pairs. See + :ref:`the header normalization rules ` for details. + + .. attribute:: http_version + + The HTTP protocol version, represented as a byte string like + ``b"1.1"``. See :ref:`the HTTP version normalization rules + ` for details. + + .. attribute:: reason + + The reason phrase of this response, as a byte string. For example: + ``b"OK"``, or ``b"Not Found"``. + + """ + + def __post_init__(self) -> None: + if not (200 <= self.status_code < 1000): + raise LocalProtocolError( + "Response status_code should be in range [200, 1000), not {}".format( + self.status_code + ) + ) + + # This is an unhashable type. + __hash__ = None # type: ignore + + +@dataclass(init=False, frozen=True) +class Data(Event): + """Part of an HTTP message body. + + Fields: + + .. attribute:: data + + A :term:`bytes-like object` containing part of a message body. Or, if + using the ``combine=False`` argument to :meth:`Connection.send`, then + any object that your socket writing code knows what to do with, and for + which calling :func:`len` returns the number of bytes that will be + written -- see :ref:`sendfile` for details. + + .. attribute:: chunk_start + + A marker that indicates whether this data object is from the start of a + chunked transfer encoding chunk. This field is ignored when when a Data + event is provided to :meth:`Connection.send`: it is only valid on + events emitted from :meth:`Connection.next_event`. You probably + shouldn't use this attribute at all; see + :ref:`chunk-delimiters-are-bad` for details. + + .. attribute:: chunk_end + + A marker that indicates whether this data object is the last for a + given chunked transfer encoding chunk. This field is ignored when when + a Data event is provided to :meth:`Connection.send`: it is only valid + on events emitted from :meth:`Connection.next_event`. You probably + shouldn't use this attribute at all; see + :ref:`chunk-delimiters-are-bad` for details. + + """ + + __slots__ = ("data", "chunk_start", "chunk_end") + + data: bytes + chunk_start: bool + chunk_end: bool + + def __init__( + self, data: bytes, chunk_start: bool = False, chunk_end: bool = False + ) -> None: + object.__setattr__(self, "data", data) + object.__setattr__(self, "chunk_start", chunk_start) + object.__setattr__(self, "chunk_end", chunk_end) + + # This is an unhashable type. + __hash__ = None # type: ignore + + +# XX FIXME: "A recipient MUST ignore (or consider as an error) any fields that +# are forbidden to be sent in a trailer, since processing them as if they were +# present in the header section might bypass external security filters." +# https://svn.tools.ietf.org/svn/wg/httpbis/specs/rfc7230.html#chunked.trailer.part +# Unfortunately, the list of forbidden fields is long and vague :-/ +@dataclass(init=False, frozen=True) +class EndOfMessage(Event): + """The end of an HTTP message. + + Fields: + + .. attribute:: headers + + Default value: ``[]`` + + Any trailing headers attached to this message, represented as a list of + (name, value) pairs. See :ref:`the header normalization rules + ` for details. + + Must be empty unless ``Transfer-Encoding: chunked`` is in use. + + """ + + __slots__ = ("headers",) + + headers: Headers + + def __init__( + self, + *, + headers: Union[ + Headers, List[Tuple[bytes, bytes]], List[Tuple[str, str]], None + ] = None, + _parsed: bool = False, + ) -> None: + super().__init__() + if headers is None: + headers = Headers([]) + elif not isinstance(headers, Headers): + headers = normalize_and_validate(headers, _parsed=_parsed) + + object.__setattr__(self, "headers", headers) + + # This is an unhashable type. + __hash__ = None # type: ignore + + +@dataclass(frozen=True) +class ConnectionClosed(Event): + """This event indicates that the sender has closed their outgoing + connection. + + Note that this does not necessarily mean that they can't *receive* further + data, because TCP connections are composed to two one-way channels which + can be closed independently. See :ref:`closing` for details. + + No fields. + """ + + pass diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/httpx-0.28.1.dist-info/INSTALLER b/bioagent-bench/.venv/lib/python3.14/site-packages/httpx-0.28.1.dist-info/INSTALLER new file mode 100644 index 0000000000000000000000000000000000000000..5c69047b2eb8235994febeeae1da4a82365a240a --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/httpx-0.28.1.dist-info/INSTALLER @@ -0,0 +1 @@ +uv \ No newline at end of file diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/httpx-0.28.1.dist-info/METADATA b/bioagent-bench/.venv/lib/python3.14/site-packages/httpx-0.28.1.dist-info/METADATA new file mode 100644 index 0000000000000000000000000000000000000000..b0d2b196385e98259971519793447c1fd7a9a643 --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/httpx-0.28.1.dist-info/METADATA @@ -0,0 +1,203 @@ +Metadata-Version: 2.3 +Name: httpx +Version: 0.28.1 +Summary: The next generation HTTP client. +Project-URL: Changelog, https://github.com/encode/httpx/blob/master/CHANGELOG.md +Project-URL: Documentation, https://www.python-httpx.org +Project-URL: Homepage, https://github.com/encode/httpx +Project-URL: Source, https://github.com/encode/httpx +Author-email: Tom Christie +License: BSD-3-Clause +Classifier: Development Status :: 4 - Beta +Classifier: Environment :: Web Environment +Classifier: Framework :: AsyncIO +Classifier: Framework :: Trio +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3 :: Only +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3.12 +Classifier: Topic :: Internet :: WWW/HTTP +Requires-Python: >=3.8 +Requires-Dist: anyio +Requires-Dist: certifi +Requires-Dist: httpcore==1.* +Requires-Dist: idna +Provides-Extra: brotli +Requires-Dist: brotli; (platform_python_implementation == 'CPython') and extra == 'brotli' +Requires-Dist: brotlicffi; (platform_python_implementation != 'CPython') and extra == 'brotli' +Provides-Extra: cli +Requires-Dist: click==8.*; extra == 'cli' +Requires-Dist: pygments==2.*; extra == 'cli' +Requires-Dist: rich<14,>=10; extra == 'cli' +Provides-Extra: http2 +Requires-Dist: h2<5,>=3; extra == 'http2' +Provides-Extra: socks +Requires-Dist: socksio==1.*; extra == 'socks' +Provides-Extra: zstd +Requires-Dist: zstandard>=0.18.0; extra == 'zstd' +Description-Content-Type: text/markdown + +

+ HTTPX +

+ +

HTTPX - A next-generation HTTP client for Python.

+ +

+ + Test Suite + + + Package version + +

+ +HTTPX is a fully featured HTTP client library for Python 3. It includes **an integrated command line client**, has support for both **HTTP/1.1 and HTTP/2**, and provides both **sync and async APIs**. + +--- + +Install HTTPX using pip: + +```shell +$ pip install httpx +``` + +Now, let's get started: + +```pycon +>>> import httpx +>>> r = httpx.get('https://www.example.org/') +>>> r + +>>> r.status_code +200 +>>> r.headers['content-type'] +'text/html; charset=UTF-8' +>>> r.text +'\n\n\nExample Domain...' +``` + +Or, using the command-line client. + +```shell +$ pip install 'httpx[cli]' # The command line client is an optional dependency. +``` + +Which now allows us to use HTTPX directly from the command-line... + +

+ httpx --help +

+ +Sending a request... + +

+ httpx http://httpbin.org/json +

+ +## Features + +HTTPX builds on the well-established usability of `requests`, and gives you: + +* A broadly [requests-compatible API](https://www.python-httpx.org/compatibility/). +* An integrated command-line client. +* HTTP/1.1 [and HTTP/2 support](https://www.python-httpx.org/http2/). +* Standard synchronous interface, but with [async support if you need it](https://www.python-httpx.org/async/). +* Ability to make requests directly to [WSGI applications](https://www.python-httpx.org/advanced/transports/#wsgi-transport) or [ASGI applications](https://www.python-httpx.org/advanced/transports/#asgi-transport). +* Strict timeouts everywhere. +* Fully type annotated. +* 100% test coverage. + +Plus all the standard features of `requests`... + +* International Domains and URLs +* Keep-Alive & Connection Pooling +* Sessions with Cookie Persistence +* Browser-style SSL Verification +* Basic/Digest Authentication +* Elegant Key/Value Cookies +* Automatic Decompression +* Automatic Content Decoding +* Unicode Response Bodies +* Multipart File Uploads +* HTTP(S) Proxy Support +* Connection Timeouts +* Streaming Downloads +* .netrc Support +* Chunked Requests + +## Installation + +Install with pip: + +```shell +$ pip install httpx +``` + +Or, to include the optional HTTP/2 support, use: + +```shell +$ pip install httpx[http2] +``` + +HTTPX requires Python 3.8+. + +## Documentation + +Project documentation is available at [https://www.python-httpx.org/](https://www.python-httpx.org/). + +For a run-through of all the basics, head over to the [QuickStart](https://www.python-httpx.org/quickstart/). + +For more advanced topics, see the [Advanced Usage](https://www.python-httpx.org/advanced/) section, the [async support](https://www.python-httpx.org/async/) section, or the [HTTP/2](https://www.python-httpx.org/http2/) section. + +The [Developer Interface](https://www.python-httpx.org/api/) provides a comprehensive API reference. + +To find out about tools that integrate with HTTPX, see [Third Party Packages](https://www.python-httpx.org/third_party_packages/). + +## Contribute + +If you want to contribute with HTTPX check out the [Contributing Guide](https://www.python-httpx.org/contributing/) to learn how to start. + +## Dependencies + +The HTTPX project relies on these excellent libraries: + +* `httpcore` - The underlying transport implementation for `httpx`. + * `h11` - HTTP/1.1 support. +* `certifi` - SSL certificates. +* `idna` - Internationalized domain name support. +* `sniffio` - Async library autodetection. + +As well as these optional installs: + +* `h2` - HTTP/2 support. *(Optional, with `httpx[http2]`)* +* `socksio` - SOCKS proxy support. *(Optional, with `httpx[socks]`)* +* `rich` - Rich terminal support. *(Optional, with `httpx[cli]`)* +* `click` - Command line client support. *(Optional, with `httpx[cli]`)* +* `brotli` or `brotlicffi` - Decoding for "brotli" compressed responses. *(Optional, with `httpx[brotli]`)* +* `zstandard` - Decoding for "zstd" compressed responses. *(Optional, with `httpx[zstd]`)* + +A huge amount of credit is due to `requests` for the API layout that +much of this work follows, as well as to `urllib3` for plenty of design +inspiration around the lower-level networking details. + +--- + +

HTTPX is BSD licensed code.
Designed & crafted with care.

— 🦋 —

+ +## Release Information + +### Fixed + +* Reintroduced supposedly-private `URLTypes` shortcut. (#2673) + + +--- + +[Full changelog](https://github.com/encode/httpx/blob/master/CHANGELOG.md) diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/httpx-0.28.1.dist-info/RECORD b/bioagent-bench/.venv/lib/python3.14/site-packages/httpx-0.28.1.dist-info/RECORD new file mode 100644 index 0000000000000000000000000000000000000000..39e3cf4bdf733ec9d115f76419f49733f65b7607 --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/httpx-0.28.1.dist-info/RECORD @@ -0,0 +1,32 @@ +../../../bin/httpx,sha256=mF-1VwRSpDsCj6_1Ky5B1zk8OH2gnxMLCDmN1Svw5XE,321 +httpx-0.28.1.dist-info/INSTALLER,sha256=5hhM4Q4mYTT9z6QB6PGpUAW81PGNFrYrdXMj4oM_6ak,2 +httpx-0.28.1.dist-info/METADATA,sha256=_rubD48-gNV8gZnDBPNcQzboWB0dGNeYPJJ2a4J5OyU,7052 +httpx-0.28.1.dist-info/RECORD,, +httpx-0.28.1.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +httpx-0.28.1.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87 +httpx-0.28.1.dist-info/entry_points.txt,sha256=2lVkdQmxLA1pNMgSN2eV89o90HCZezhmNwsy6ryKDSA,37 +httpx-0.28.1.dist-info/licenses/LICENSE.md,sha256=TsWdVE8StfU5o6cW_TIaxYzNgDC0ZSIfLIgCAM3yjY0,1508 +httpx/__init__.py,sha256=CsaZe6yZj0rHg6322AWKWHGTMVr9txgEfD5P3_Rrz60,2171 +httpx/__version__.py,sha256=LoUyYeOXTieGzuP_64UL0wxdtxjuu_QbOvE7NOg-IqU,108 +httpx/_api.py,sha256=r_Zgs4jIpcPJLqK5dbbSayqo_iVMKFaxZCd-oOHxLEs,11743 +httpx/_auth.py,sha256=Yr3QwaUSK17rGYx-7j-FdicFIzz4Y9FFV-1F4-7RXX4,11891 +httpx/_client.py,sha256=xD-UG67-WMkeltAAOeGGj-cZ2RRTAm19sWRxlFY7_40,65714 +httpx/_config.py,sha256=pPp2U-wicfcKsF-KYRE1LYdt3e6ERGeIoXZ8Gjo3LWc,8547 +httpx/_content.py,sha256=LGGzrJTR3OvN4Mb1GVVNLXkXJH-6oKlwAttO9p5w_yg,8161 +httpx/_decoders.py,sha256=p0dX8I0NEHexs3UGp4SsZutiMhsXrrWl6-GnqVb0iKM,12041 +httpx/_exceptions.py,sha256=bxW7fxzgVMAdNTbwT0Vnq04gJDW1_gI_GFiQPuMyjL0,8527 +httpx/_main.py,sha256=Cg9GMabiTT_swaDfUgIRitSwxLRMSwUDOm7LdSGqlA4,15626 +httpx/_models.py,sha256=4__Guyv1gLxuZChwim8kfQNiIOcJ9acreFOSurvZfms,44700 +httpx/_multipart.py,sha256=KOHEZZl6oohg9mPaKyyu345qq1rJLg35TUG3YAzXB3Y,9843 +httpx/_status_codes.py,sha256=DYn-2ufBgMeXy5s8x3_TB7wjAuAAMewTakPrm5rXEsc,5639 +httpx/_transports/__init__.py,sha256=GbUoBSAOp7z-l-9j5YhMhR3DMIcn6FVLhj072O3Nnno,275 +httpx/_transports/asgi.py,sha256=HRfiDYMPt4wQH2gFgHZg4c-i3sblo6bL5GTqcET-xz8,5501 +httpx/_transports/base.py,sha256=kZS_VMbViYfF570pogUCJ1bulz-ybfL51Pqs9yktebU,2523 +httpx/_transports/default.py,sha256=AzeaRUyVwCccTyyNJexDf0n1dFfzzydpdIQgvw7PLnk,13983 +httpx/_transports/mock.py,sha256=PTo0d567RITXxGrki6kN7_67wwAxfwiMDcuXJiZCjEo,1232 +httpx/_transports/wsgi.py,sha256=NcPX3Xap_EwCFZWO_OaSyQNuInCYx1QMNbO8GAei6jY,4825 +httpx/_types.py,sha256=Jyh41GQq7AOev8IOWKDAg7zCbvHAfufmW5g_PiTtErY,2965 +httpx/_urlparse.py,sha256=ZAmH47ONfkxrrj-PPYhGeiHjb6AjKCS-ANWIN4OL_KY,18546 +httpx/_urls.py,sha256=dX99VR1DSOHpgo9Aq7PzYO4FKdxqKjwyNp8grf8dHN0,21550 +httpx/_utils.py,sha256=_TVeqAKvxJkKHdz7dFeb4s0LZqQXgeFkXSgfiHBK_1o,8285 +httpx/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/httpx-0.28.1.dist-info/REQUESTED b/bioagent-bench/.venv/lib/python3.14/site-packages/httpx-0.28.1.dist-info/REQUESTED new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/httpx-0.28.1.dist-info/WHEEL b/bioagent-bench/.venv/lib/python3.14/site-packages/httpx-0.28.1.dist-info/WHEEL new file mode 100644 index 0000000000000000000000000000000000000000..21aaa72961a8af71c17d2cb3b76d5f7f567100e4 --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/httpx-0.28.1.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: hatchling 1.26.3 +Root-Is-Purelib: true +Tag: py3-none-any diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/httpx-0.28.1.dist-info/entry_points.txt b/bioagent-bench/.venv/lib/python3.14/site-packages/httpx-0.28.1.dist-info/entry_points.txt new file mode 100644 index 0000000000000000000000000000000000000000..8ae96007f7d725813fd02dc1d06d3834ee1939e4 --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/httpx-0.28.1.dist-info/entry_points.txt @@ -0,0 +1,2 @@ +[console_scripts] +httpx = httpx:main diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/__init__.py b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..443487f6dad78e9fe7044842de7d8003ebbdd7f7 --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/__init__.py @@ -0,0 +1,1741 @@ +# Copyright 2020 The HuggingFace Team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# *********** +# `huggingface_hub` init has 2 modes: +# - Normal usage: +# If imported to use it, all modules and functions are lazy-loaded. This means +# they exist at top level in module but are imported only the first time they are +# used. This way, `from huggingface_hub import something` will import `something` +# quickly without the hassle of importing all the features from `huggingface_hub`. +# - Static check: +# If statically analyzed, all modules and functions are loaded normally. This way +# static typing check works properly as well as autocomplete in text editors and +# IDEs. +# +# The static model imports are done inside the `if TYPE_CHECKING:` statement at +# the bottom of this file. Since module/functions imports are duplicated, it is +# mandatory to make sure to add them twice when adding one. This is checked in the +# `make quality` command. +# +# To update the static imports, please run the following command and commit the changes. +# ``` +# # Use script +# python utils/check_static_imports.py --update-file +# +# # Or run style on codebase +# make style +# ``` +# +# *********** +# Lazy loader vendored from https://github.com/scientific-python/lazy_loader +import importlib +import os +import sys +from typing import TYPE_CHECKING + + +__version__ = "1.14.0" + +# Alphabetical order of definitions is ensured in tests +# WARNING: any comment added in this dictionary definition will be lost when +# re-generating the file ! +_SUBMOD_ATTRS = { + "_buckets": [ + "BucketFile", + "BucketFileMetadata", + "BucketFolder", + "BucketInfo", + "BucketUrl", + "SyncOperation", + "SyncPlan", + ], + "_commit_scheduler": [ + "CommitScheduler", + ], + "_eval_results": [ + "EvalResultEntry", + "eval_result_entries_to_yaml", + "parse_eval_result_entries", + ], + "_inference_endpoints": [ + "InferenceEndpoint", + "InferenceEndpointError", + "InferenceEndpointStatus", + "InferenceEndpointTimeoutError", + "InferenceEndpointType", + ], + "_jobs_api": [ + "JobAccelerator", + "JobHardware", + "JobInfo", + "JobOwner", + "JobStage", + "JobStatus", + ], + "_login": [ + "auth_list", + "auth_switch", + "interpreter_login", + "login", + "logout", + "notebook_login", + ], + "_oauth": [ + "OAuthInfo", + "OAuthOrgInfo", + "OAuthUserInfo", + "attach_huggingface_oauth", + "parse_huggingface_oauth", + ], + "_snapshot_download": [ + "snapshot_download", + ], + "_space_api": [ + "SpaceHardware", + "SpaceRuntime", + "SpaceSecret", + "SpaceStage", + "SpaceStorage", + "SpaceVariable", + "Volume", + ], + "_tensorboard_logger": [ + "HFSummaryWriter", + ], + "_webhooks_payload": [ + "WebhookPayload", + "WebhookPayloadComment", + "WebhookPayloadDiscussion", + "WebhookPayloadDiscussionChanges", + "WebhookPayloadEvent", + "WebhookPayloadMovedTo", + "WebhookPayloadRepo", + "WebhookPayloadUrl", + "WebhookPayloadWebhook", + ], + "_webhooks_server": [ + "WebhooksServer", + "webhook_endpoint", + ], + "cli._cli_utils": [ + "check_cli_update", + "typer_factory", + ], + "community": [ + "Discussion", + "DiscussionComment", + "DiscussionCommit", + "DiscussionEvent", + "DiscussionStatusChange", + "DiscussionTitleChange", + "DiscussionWithDetails", + ], + "constants": [ + "CONFIG_NAME", + "FLAX_WEIGHTS_NAME", + "HUGGINGFACE_CO_URL_HOME", + "HUGGINGFACE_CO_URL_TEMPLATE", + "PYTORCH_WEIGHTS_NAME", + "REPO_TYPE_DATASET", + "REPO_TYPE_MODEL", + "REPO_TYPE_SPACE", + "TF2_WEIGHTS_NAME", + "TF_WEIGHTS_NAME", + "is_offline_mode", + ], + "fastai_utils": [ + "_save_pretrained_fastai", + "from_pretrained_fastai", + "push_to_hub_fastai", + ], + "file_download": [ + "DryRunFileInfo", + "HfFileMetadata", + "_CACHED_NO_EXIST", + "get_hf_file_metadata", + "hf_hub_download", + "hf_hub_url", + "try_to_load_from_cache", + ], + "hf_api": [ + "Collection", + "CollectionItem", + "CommitInfo", + "CommitOperation", + "CommitOperationAdd", + "CommitOperationCopy", + "CommitOperationDelete", + "DatasetInfo", + "DatasetLeaderboardEntry", + "GitCommitInfo", + "GitRefInfo", + "GitRefs", + "HfApi", + "KernelInfo", + "ModelInfo", + "Organization", + "RepoFile", + "RepoFolder", + "RepoUrl", + "SpaceInfo", + "SpaceSearchResult", + "User", + "UserLikes", + "WebhookInfo", + "WebhookWatchedItem", + "accept_access_request", + "add_collection_item", + "add_space_secret", + "add_space_variable", + "auth_check", + "batch_bucket_files", + "bucket_info", + "cancel_access_request", + "cancel_job", + "change_discussion_status", + "comment_discussion", + "copy_files", + "create_branch", + "create_bucket", + "create_collection", + "create_commit", + "create_discussion", + "create_inference_endpoint", + "create_inference_endpoint_from_catalog", + "create_pull_request", + "create_repo", + "create_scheduled_job", + "create_scheduled_uv_job", + "create_tag", + "create_webhook", + "dataset_info", + "delete_branch", + "delete_bucket", + "delete_collection", + "delete_collection_item", + "delete_file", + "delete_folder", + "delete_inference_endpoint", + "delete_repo", + "delete_scheduled_job", + "delete_space_secret", + "delete_space_storage", + "delete_space_variable", + "delete_space_volumes", + "delete_tag", + "delete_webhook", + "disable_space_dev_mode", + "disable_webhook", + "download_bucket_files", + "duplicate_repo", + "duplicate_space", + "edit_discussion_comment", + "enable_space_dev_mode", + "enable_webhook", + "fetch_job_logs", + "fetch_job_metrics", + "fetch_space_logs", + "file_exists", + "get_bucket_file_metadata", + "get_bucket_paths_info", + "get_collection", + "get_dataset_leaderboard", + "get_dataset_tags", + "get_discussion_details", + "get_full_repo_name", + "get_inference_endpoint", + "get_local_safetensors_metadata", + "get_model_tags", + "get_organization_overview", + "get_paths_info", + "get_repo_discussions", + "get_safetensors_metadata", + "get_space_runtime", + "get_space_secrets", + "get_space_variables", + "get_user_overview", + "get_webhook", + "grant_access", + "inspect_job", + "inspect_scheduled_job", + "kernel_info", + "list_accepted_access_requests", + "list_bucket_tree", + "list_buckets", + "list_collections", + "list_daily_papers", + "list_dataset_parquet_files", + "list_datasets", + "list_inference_catalog", + "list_inference_endpoints", + "list_jobs", + "list_jobs_hardware", + "list_lfs_files", + "list_liked_repos", + "list_models", + "list_organization_followers", + "list_organization_members", + "list_papers", + "list_pending_access_requests", + "list_rejected_access_requests", + "list_repo_commits", + "list_repo_files", + "list_repo_likers", + "list_repo_refs", + "list_repo_tree", + "list_spaces", + "list_spaces_hardware", + "list_user_followers", + "list_user_following", + "list_webhooks", + "merge_pull_request", + "model_info", + "move_bucket", + "move_repo", + "paper_info", + "parse_local_safetensors_file_metadata", + "parse_safetensors_file_metadata", + "pause_inference_endpoint", + "pause_space", + "permanently_delete_lfs_files", + "preupload_lfs_files", + "read_paper", + "reject_access_request", + "rename_discussion", + "repo_exists", + "repo_info", + "repo_type_and_id_from_hf_id", + "request_space_hardware", + "request_space_storage", + "restart_space", + "resume_inference_endpoint", + "resume_scheduled_job", + "revision_exists", + "run_as_future", + "run_job", + "run_uv_job", + "scale_to_zero_inference_endpoint", + "search_spaces", + "set_space_sleep_time", + "set_space_volumes", + "space_info", + "super_squash_history", + "suspend_scheduled_job", + "sync_bucket", + "unlike", + "update_collection_item", + "update_collection_metadata", + "update_inference_endpoint", + "update_repo_settings", + "update_webhook", + "upload_file", + "upload_folder", + "upload_large_folder", + "verify_repo_checksums", + "whoami", + ], + "hf_file_system": [ + "HfFileSystem", + "HfFileSystemFile", + "HfFileSystemResolvedPath", + "HfFileSystemStreamFile", + "hffs", + ], + "hub_mixin": [ + "ModelHubMixin", + "PyTorchModelHubMixin", + ], + "inference._client": [ + "InferenceClient", + "InferenceTimeoutError", + ], + "inference._generated._async_client": [ + "AsyncInferenceClient", + ], + "inference._generated.types": [ + "AudioClassificationInput", + "AudioClassificationOutputElement", + "AudioClassificationOutputTransform", + "AudioClassificationParameters", + "AudioToAudioInput", + "AudioToAudioOutputElement", + "AutomaticSpeechRecognitionEarlyStoppingEnum", + "AutomaticSpeechRecognitionGenerationParameters", + "AutomaticSpeechRecognitionInput", + "AutomaticSpeechRecognitionOutput", + "AutomaticSpeechRecognitionOutputChunk", + "AutomaticSpeechRecognitionParameters", + "ChatCompletionInput", + "ChatCompletionInputFunctionDefinition", + "ChatCompletionInputFunctionName", + "ChatCompletionInputGrammarType", + "ChatCompletionInputJSONSchema", + "ChatCompletionInputMessage", + "ChatCompletionInputMessageChunk", + "ChatCompletionInputMessageChunkType", + "ChatCompletionInputResponseFormatJSONObject", + "ChatCompletionInputResponseFormatJSONSchema", + "ChatCompletionInputResponseFormatText", + "ChatCompletionInputStreamOptions", + "ChatCompletionInputTool", + "ChatCompletionInputToolCall", + "ChatCompletionInputToolChoiceClass", + "ChatCompletionInputToolChoiceEnum", + "ChatCompletionInputURL", + "ChatCompletionOutput", + "ChatCompletionOutputComplete", + "ChatCompletionOutputFunctionDefinition", + "ChatCompletionOutputLogprob", + "ChatCompletionOutputLogprobs", + "ChatCompletionOutputMessage", + "ChatCompletionOutputToolCall", + "ChatCompletionOutputTopLogprob", + "ChatCompletionOutputUsage", + "ChatCompletionStreamOutput", + "ChatCompletionStreamOutputChoice", + "ChatCompletionStreamOutputDelta", + "ChatCompletionStreamOutputDeltaToolCall", + "ChatCompletionStreamOutputFunction", + "ChatCompletionStreamOutputLogprob", + "ChatCompletionStreamOutputLogprobs", + "ChatCompletionStreamOutputTopLogprob", + "ChatCompletionStreamOutputUsage", + "DepthEstimationInput", + "DepthEstimationOutput", + "DocumentQuestionAnsweringInput", + "DocumentQuestionAnsweringInputData", + "DocumentQuestionAnsweringOutputElement", + "DocumentQuestionAnsweringParameters", + "FeatureExtractionInput", + "FeatureExtractionInputTruncationDirection", + "FillMaskInput", + "FillMaskOutputElement", + "FillMaskParameters", + "ImageClassificationInput", + "ImageClassificationOutputElement", + "ImageClassificationOutputTransform", + "ImageClassificationParameters", + "ImageSegmentationInput", + "ImageSegmentationOutputElement", + "ImageSegmentationParameters", + "ImageSegmentationSubtask", + "ImageTextToImageInput", + "ImageTextToImageOutput", + "ImageTextToImageParameters", + "ImageTextToImageTargetSize", + "ImageTextToVideoInput", + "ImageTextToVideoOutput", + "ImageTextToVideoParameters", + "ImageTextToVideoTargetSize", + "ImageToImageInput", + "ImageToImageOutput", + "ImageToImageParameters", + "ImageToImageTargetSize", + "ImageToTextEarlyStoppingEnum", + "ImageToTextGenerationParameters", + "ImageToTextInput", + "ImageToTextOutput", + "ImageToTextParameters", + "ImageToVideoInput", + "ImageToVideoOutput", + "ImageToVideoParameters", + "ImageToVideoTargetSize", + "ObjectDetectionBoundingBox", + "ObjectDetectionInput", + "ObjectDetectionOutputElement", + "ObjectDetectionParameters", + "Padding", + "QuestionAnsweringInput", + "QuestionAnsweringInputData", + "QuestionAnsweringOutputElement", + "QuestionAnsweringParameters", + "SentenceSimilarityInput", + "SentenceSimilarityInputData", + "SummarizationInput", + "SummarizationOutput", + "SummarizationParameters", + "SummarizationTruncationStrategy", + "TableQuestionAnsweringInput", + "TableQuestionAnsweringInputData", + "TableQuestionAnsweringOutputElement", + "TableQuestionAnsweringParameters", + "Text2TextGenerationInput", + "Text2TextGenerationOutput", + "Text2TextGenerationParameters", + "Text2TextGenerationTruncationStrategy", + "TextClassificationInput", + "TextClassificationOutputElement", + "TextClassificationOutputTransform", + "TextClassificationParameters", + "TextGenerationInput", + "TextGenerationInputGenerateParameters", + "TextGenerationInputGrammarType", + "TextGenerationOutput", + "TextGenerationOutputBestOfSequence", + "TextGenerationOutputDetails", + "TextGenerationOutputFinishReason", + "TextGenerationOutputPrefillToken", + "TextGenerationOutputToken", + "TextGenerationStreamOutput", + "TextGenerationStreamOutputStreamDetails", + "TextGenerationStreamOutputToken", + "TextToAudioEarlyStoppingEnum", + "TextToAudioGenerationParameters", + "TextToAudioInput", + "TextToAudioOutput", + "TextToAudioParameters", + "TextToImageInput", + "TextToImageOutput", + "TextToImageParameters", + "TextToSpeechEarlyStoppingEnum", + "TextToSpeechGenerationParameters", + "TextToSpeechInput", + "TextToSpeechOutput", + "TextToSpeechParameters", + "TextToVideoInput", + "TextToVideoOutput", + "TextToVideoParameters", + "TokenClassificationAggregationStrategy", + "TokenClassificationInput", + "TokenClassificationOutputElement", + "TokenClassificationParameters", + "TranslationInput", + "TranslationOutput", + "TranslationParameters", + "TranslationTruncationStrategy", + "TypeEnum", + "VideoClassificationInput", + "VideoClassificationOutputElement", + "VideoClassificationOutputTransform", + "VideoClassificationParameters", + "VisualQuestionAnsweringInput", + "VisualQuestionAnsweringInputData", + "VisualQuestionAnsweringOutputElement", + "VisualQuestionAnsweringParameters", + "ZeroShotClassificationInput", + "ZeroShotClassificationOutputElement", + "ZeroShotClassificationParameters", + "ZeroShotImageClassificationInput", + "ZeroShotImageClassificationOutputElement", + "ZeroShotImageClassificationParameters", + "ZeroShotObjectDetectionBoundingBox", + "ZeroShotObjectDetectionInput", + "ZeroShotObjectDetectionOutputElement", + "ZeroShotObjectDetectionParameters", + ], + "inference._mcp.agent": [ + "Agent", + ], + "inference._mcp.mcp_client": [ + "MCPClient", + ], + "repocard": [ + "DatasetCard", + "ModelCard", + "RepoCard", + "SpaceCard", + "metadata_eval_result", + "metadata_load", + "metadata_save", + "metadata_update", + ], + "repocard_data": [ + "CardData", + "DatasetCardData", + "EvalResult", + "ModelCardData", + "SpaceCardData", + ], + "serialization": [ + "StateDictSplit", + "get_torch_storage_id", + "get_torch_storage_size", + "load_state_dict_from_file", + "load_torch_model", + "save_torch_model", + "save_torch_state_dict", + "split_state_dict_into_shards_factory", + "split_torch_state_dict_into_shards", + ], + "serialization._dduf": [ + "DDUFEntry", + "export_entries_as_dduf", + "export_folder_as_dduf", + "read_dduf_file", + ], + "utils": [ + "ASYNC_CLIENT_FACTORY_T", + "CLIENT_FACTORY_T", + "CacheNotFound", + "CachedFileInfo", + "CachedRepoInfo", + "CachedRevisionInfo", + "CorruptedCacheException", + "DeleteCacheStrategy", + "HFCacheInfo", + "HfUri", + "cached_assets_path", + "close_session", + "dump_environment_info", + "get_async_session", + "get_session", + "get_token", + "hf_raise_for_status", + "logging", + "parse_hf_uri", + "scan_cache_dir", + "set_async_client_factory", + "set_client_factory", + ], +} + +# WARNING: __all__ is generated automatically, Any manual edit will be lost when re-generating this file ! +# +# To update the static imports, please run the following command and commit the changes. +# ``` +# # Use script +# python utils/check_all_variable.py --update +# +# # Or run style on codebase +# make style +# ``` + +__all__ = [ + "ASYNC_CLIENT_FACTORY_T", + "Agent", + "AsyncInferenceClient", + "AudioClassificationInput", + "AudioClassificationOutputElement", + "AudioClassificationOutputTransform", + "AudioClassificationParameters", + "AudioToAudioInput", + "AudioToAudioOutputElement", + "AutomaticSpeechRecognitionEarlyStoppingEnum", + "AutomaticSpeechRecognitionGenerationParameters", + "AutomaticSpeechRecognitionInput", + "AutomaticSpeechRecognitionOutput", + "AutomaticSpeechRecognitionOutputChunk", + "AutomaticSpeechRecognitionParameters", + "BucketFile", + "BucketFileMetadata", + "BucketFolder", + "BucketInfo", + "BucketUrl", + "CLIENT_FACTORY_T", + "CONFIG_NAME", + "CacheNotFound", + "CachedFileInfo", + "CachedRepoInfo", + "CachedRevisionInfo", + "CardData", + "ChatCompletionInput", + "ChatCompletionInputFunctionDefinition", + "ChatCompletionInputFunctionName", + "ChatCompletionInputGrammarType", + "ChatCompletionInputJSONSchema", + "ChatCompletionInputMessage", + "ChatCompletionInputMessageChunk", + "ChatCompletionInputMessageChunkType", + "ChatCompletionInputResponseFormatJSONObject", + "ChatCompletionInputResponseFormatJSONSchema", + "ChatCompletionInputResponseFormatText", + "ChatCompletionInputStreamOptions", + "ChatCompletionInputTool", + "ChatCompletionInputToolCall", + "ChatCompletionInputToolChoiceClass", + "ChatCompletionInputToolChoiceEnum", + "ChatCompletionInputURL", + "ChatCompletionOutput", + "ChatCompletionOutputComplete", + "ChatCompletionOutputFunctionDefinition", + "ChatCompletionOutputLogprob", + "ChatCompletionOutputLogprobs", + "ChatCompletionOutputMessage", + "ChatCompletionOutputToolCall", + "ChatCompletionOutputTopLogprob", + "ChatCompletionOutputUsage", + "ChatCompletionStreamOutput", + "ChatCompletionStreamOutputChoice", + "ChatCompletionStreamOutputDelta", + "ChatCompletionStreamOutputDeltaToolCall", + "ChatCompletionStreamOutputFunction", + "ChatCompletionStreamOutputLogprob", + "ChatCompletionStreamOutputLogprobs", + "ChatCompletionStreamOutputTopLogprob", + "ChatCompletionStreamOutputUsage", + "Collection", + "CollectionItem", + "CommitInfo", + "CommitOperation", + "CommitOperationAdd", + "CommitOperationCopy", + "CommitOperationDelete", + "CommitScheduler", + "CorruptedCacheException", + "DDUFEntry", + "DatasetCard", + "DatasetCardData", + "DatasetInfo", + "DatasetLeaderboardEntry", + "DeleteCacheStrategy", + "DepthEstimationInput", + "DepthEstimationOutput", + "Discussion", + "DiscussionComment", + "DiscussionCommit", + "DiscussionEvent", + "DiscussionStatusChange", + "DiscussionTitleChange", + "DiscussionWithDetails", + "DocumentQuestionAnsweringInput", + "DocumentQuestionAnsweringInputData", + "DocumentQuestionAnsweringOutputElement", + "DocumentQuestionAnsweringParameters", + "DryRunFileInfo", + "EvalResult", + "EvalResultEntry", + "FLAX_WEIGHTS_NAME", + "FeatureExtractionInput", + "FeatureExtractionInputTruncationDirection", + "FillMaskInput", + "FillMaskOutputElement", + "FillMaskParameters", + "GitCommitInfo", + "GitRefInfo", + "GitRefs", + "HFCacheInfo", + "HFSummaryWriter", + "HUGGINGFACE_CO_URL_HOME", + "HUGGINGFACE_CO_URL_TEMPLATE", + "HfApi", + "HfFileMetadata", + "HfFileSystem", + "HfFileSystemFile", + "HfFileSystemResolvedPath", + "HfFileSystemStreamFile", + "HfUri", + "ImageClassificationInput", + "ImageClassificationOutputElement", + "ImageClassificationOutputTransform", + "ImageClassificationParameters", + "ImageSegmentationInput", + "ImageSegmentationOutputElement", + "ImageSegmentationParameters", + "ImageSegmentationSubtask", + "ImageTextToImageInput", + "ImageTextToImageOutput", + "ImageTextToImageParameters", + "ImageTextToImageTargetSize", + "ImageTextToVideoInput", + "ImageTextToVideoOutput", + "ImageTextToVideoParameters", + "ImageTextToVideoTargetSize", + "ImageToImageInput", + "ImageToImageOutput", + "ImageToImageParameters", + "ImageToImageTargetSize", + "ImageToTextEarlyStoppingEnum", + "ImageToTextGenerationParameters", + "ImageToTextInput", + "ImageToTextOutput", + "ImageToTextParameters", + "ImageToVideoInput", + "ImageToVideoOutput", + "ImageToVideoParameters", + "ImageToVideoTargetSize", + "InferenceClient", + "InferenceEndpoint", + "InferenceEndpointError", + "InferenceEndpointStatus", + "InferenceEndpointTimeoutError", + "InferenceEndpointType", + "InferenceTimeoutError", + "JobAccelerator", + "JobHardware", + "JobInfo", + "JobOwner", + "JobStage", + "JobStatus", + "KernelInfo", + "MCPClient", + "ModelCard", + "ModelCardData", + "ModelHubMixin", + "ModelInfo", + "OAuthInfo", + "OAuthOrgInfo", + "OAuthUserInfo", + "ObjectDetectionBoundingBox", + "ObjectDetectionInput", + "ObjectDetectionOutputElement", + "ObjectDetectionParameters", + "Organization", + "PYTORCH_WEIGHTS_NAME", + "Padding", + "PyTorchModelHubMixin", + "QuestionAnsweringInput", + "QuestionAnsweringInputData", + "QuestionAnsweringOutputElement", + "QuestionAnsweringParameters", + "REPO_TYPE_DATASET", + "REPO_TYPE_MODEL", + "REPO_TYPE_SPACE", + "RepoCard", + "RepoFile", + "RepoFolder", + "RepoUrl", + "SentenceSimilarityInput", + "SentenceSimilarityInputData", + "SpaceCard", + "SpaceCardData", + "SpaceHardware", + "SpaceInfo", + "SpaceRuntime", + "SpaceSearchResult", + "SpaceSecret", + "SpaceStage", + "SpaceStorage", + "SpaceVariable", + "StateDictSplit", + "SummarizationInput", + "SummarizationOutput", + "SummarizationParameters", + "SummarizationTruncationStrategy", + "SyncOperation", + "SyncPlan", + "TF2_WEIGHTS_NAME", + "TF_WEIGHTS_NAME", + "TableQuestionAnsweringInput", + "TableQuestionAnsweringInputData", + "TableQuestionAnsweringOutputElement", + "TableQuestionAnsweringParameters", + "Text2TextGenerationInput", + "Text2TextGenerationOutput", + "Text2TextGenerationParameters", + "Text2TextGenerationTruncationStrategy", + "TextClassificationInput", + "TextClassificationOutputElement", + "TextClassificationOutputTransform", + "TextClassificationParameters", + "TextGenerationInput", + "TextGenerationInputGenerateParameters", + "TextGenerationInputGrammarType", + "TextGenerationOutput", + "TextGenerationOutputBestOfSequence", + "TextGenerationOutputDetails", + "TextGenerationOutputFinishReason", + "TextGenerationOutputPrefillToken", + "TextGenerationOutputToken", + "TextGenerationStreamOutput", + "TextGenerationStreamOutputStreamDetails", + "TextGenerationStreamOutputToken", + "TextToAudioEarlyStoppingEnum", + "TextToAudioGenerationParameters", + "TextToAudioInput", + "TextToAudioOutput", + "TextToAudioParameters", + "TextToImageInput", + "TextToImageOutput", + "TextToImageParameters", + "TextToSpeechEarlyStoppingEnum", + "TextToSpeechGenerationParameters", + "TextToSpeechInput", + "TextToSpeechOutput", + "TextToSpeechParameters", + "TextToVideoInput", + "TextToVideoOutput", + "TextToVideoParameters", + "TokenClassificationAggregationStrategy", + "TokenClassificationInput", + "TokenClassificationOutputElement", + "TokenClassificationParameters", + "TranslationInput", + "TranslationOutput", + "TranslationParameters", + "TranslationTruncationStrategy", + "TypeEnum", + "User", + "UserLikes", + "VideoClassificationInput", + "VideoClassificationOutputElement", + "VideoClassificationOutputTransform", + "VideoClassificationParameters", + "VisualQuestionAnsweringInput", + "VisualQuestionAnsweringInputData", + "VisualQuestionAnsweringOutputElement", + "VisualQuestionAnsweringParameters", + "Volume", + "WebhookInfo", + "WebhookPayload", + "WebhookPayloadComment", + "WebhookPayloadDiscussion", + "WebhookPayloadDiscussionChanges", + "WebhookPayloadEvent", + "WebhookPayloadMovedTo", + "WebhookPayloadRepo", + "WebhookPayloadUrl", + "WebhookPayloadWebhook", + "WebhookWatchedItem", + "WebhooksServer", + "ZeroShotClassificationInput", + "ZeroShotClassificationOutputElement", + "ZeroShotClassificationParameters", + "ZeroShotImageClassificationInput", + "ZeroShotImageClassificationOutputElement", + "ZeroShotImageClassificationParameters", + "ZeroShotObjectDetectionBoundingBox", + "ZeroShotObjectDetectionInput", + "ZeroShotObjectDetectionOutputElement", + "ZeroShotObjectDetectionParameters", + "_CACHED_NO_EXIST", + "_save_pretrained_fastai", + "accept_access_request", + "add_collection_item", + "add_space_secret", + "add_space_variable", + "attach_huggingface_oauth", + "auth_check", + "auth_list", + "auth_switch", + "batch_bucket_files", + "bucket_info", + "cached_assets_path", + "cancel_access_request", + "cancel_job", + "change_discussion_status", + "check_cli_update", + "close_session", + "comment_discussion", + "copy_files", + "create_branch", + "create_bucket", + "create_collection", + "create_commit", + "create_discussion", + "create_inference_endpoint", + "create_inference_endpoint_from_catalog", + "create_pull_request", + "create_repo", + "create_scheduled_job", + "create_scheduled_uv_job", + "create_tag", + "create_webhook", + "dataset_info", + "delete_branch", + "delete_bucket", + "delete_collection", + "delete_collection_item", + "delete_file", + "delete_folder", + "delete_inference_endpoint", + "delete_repo", + "delete_scheduled_job", + "delete_space_secret", + "delete_space_storage", + "delete_space_variable", + "delete_space_volumes", + "delete_tag", + "delete_webhook", + "disable_space_dev_mode", + "disable_webhook", + "download_bucket_files", + "dump_environment_info", + "duplicate_repo", + "duplicate_space", + "edit_discussion_comment", + "enable_space_dev_mode", + "enable_webhook", + "eval_result_entries_to_yaml", + "export_entries_as_dduf", + "export_folder_as_dduf", + "fetch_job_logs", + "fetch_job_metrics", + "fetch_space_logs", + "file_exists", + "from_pretrained_fastai", + "get_async_session", + "get_bucket_file_metadata", + "get_bucket_paths_info", + "get_collection", + "get_dataset_leaderboard", + "get_dataset_tags", + "get_discussion_details", + "get_full_repo_name", + "get_hf_file_metadata", + "get_inference_endpoint", + "get_local_safetensors_metadata", + "get_model_tags", + "get_organization_overview", + "get_paths_info", + "get_repo_discussions", + "get_safetensors_metadata", + "get_session", + "get_space_runtime", + "get_space_secrets", + "get_space_variables", + "get_token", + "get_torch_storage_id", + "get_torch_storage_size", + "get_user_overview", + "get_webhook", + "grant_access", + "hf_hub_download", + "hf_hub_url", + "hf_raise_for_status", + "hffs", + "inspect_job", + "inspect_scheduled_job", + "interpreter_login", + "is_offline_mode", + "kernel_info", + "list_accepted_access_requests", + "list_bucket_tree", + "list_buckets", + "list_collections", + "list_daily_papers", + "list_dataset_parquet_files", + "list_datasets", + "list_inference_catalog", + "list_inference_endpoints", + "list_jobs", + "list_jobs_hardware", + "list_lfs_files", + "list_liked_repos", + "list_models", + "list_organization_followers", + "list_organization_members", + "list_papers", + "list_pending_access_requests", + "list_rejected_access_requests", + "list_repo_commits", + "list_repo_files", + "list_repo_likers", + "list_repo_refs", + "list_repo_tree", + "list_spaces", + "list_spaces_hardware", + "list_user_followers", + "list_user_following", + "list_webhooks", + "load_state_dict_from_file", + "load_torch_model", + "logging", + "login", + "logout", + "merge_pull_request", + "metadata_eval_result", + "metadata_load", + "metadata_save", + "metadata_update", + "model_info", + "move_bucket", + "move_repo", + "notebook_login", + "paper_info", + "parse_eval_result_entries", + "parse_hf_uri", + "parse_huggingface_oauth", + "parse_local_safetensors_file_metadata", + "parse_safetensors_file_metadata", + "pause_inference_endpoint", + "pause_space", + "permanently_delete_lfs_files", + "preupload_lfs_files", + "push_to_hub_fastai", + "read_dduf_file", + "read_paper", + "reject_access_request", + "rename_discussion", + "repo_exists", + "repo_info", + "repo_type_and_id_from_hf_id", + "request_space_hardware", + "request_space_storage", + "restart_space", + "resume_inference_endpoint", + "resume_scheduled_job", + "revision_exists", + "run_as_future", + "run_job", + "run_uv_job", + "save_torch_model", + "save_torch_state_dict", + "scale_to_zero_inference_endpoint", + "scan_cache_dir", + "search_spaces", + "set_async_client_factory", + "set_client_factory", + "set_space_sleep_time", + "set_space_volumes", + "snapshot_download", + "space_info", + "split_state_dict_into_shards_factory", + "split_torch_state_dict_into_shards", + "super_squash_history", + "suspend_scheduled_job", + "sync_bucket", + "try_to_load_from_cache", + "typer_factory", + "unlike", + "update_collection_item", + "update_collection_metadata", + "update_inference_endpoint", + "update_repo_settings", + "update_webhook", + "upload_file", + "upload_folder", + "upload_large_folder", + "verify_repo_checksums", + "webhook_endpoint", + "whoami", +] + + +def _attach(package_name, submodules=None, submod_attrs=None): + """Attach lazily loaded submodules, functions, or other attributes. + + Typically, modules import submodules and attributes as follows: + + ```py + import mysubmodule + import anothersubmodule + + from .foo import someattr + ``` + + The idea is to replace a package's `__getattr__`, `__dir__`, such that all imports + work exactly the way they would with normal imports, except that the import occurs + upon first use. + + The typical way to call this function, replacing the above imports, is: + + ```python + __getattr__, __dir__ = lazy.attach( + __name__, + ['mysubmodule', 'anothersubmodule'], + {'foo': ['someattr']} + ) + ``` + This functionality requires Python 3.7 or higher. + + Args: + package_name (`str`): + Typically use `__name__`. + submodules (`set`): + List of submodules to attach. + submod_attrs (`dict`): + Dictionary of submodule -> list of attributes / functions. + These attributes are imported as they are used. + + Returns: + __getattr__, __dir__, __all__ + + """ + if submod_attrs is None: + submod_attrs = {} + + if submodules is None: + submodules = set() + else: + submodules = set(submodules) + + attr_to_modules = {attr: mod for mod, attrs in submod_attrs.items() for attr in attrs} + + def __getattr__(name): + if name in submodules: + try: + return importlib.import_module(f"{package_name}.{name}") + except Exception as e: + print(f"Error importing {package_name}.{name}: {e}") + raise + elif name in attr_to_modules: + submod_path = f"{package_name}.{attr_to_modules[name]}" + try: + submod = importlib.import_module(submod_path) + except Exception as e: + print(f"Error importing {submod_path}: {e}") + raise + attr = getattr(submod, name) + + # If the attribute lives in a file (module) with the same + # name as the attribute, ensure that the attribute and *not* + # the module is accessible on the package. + if name == attr_to_modules[name]: + pkg = sys.modules[package_name] + pkg.__dict__[name] = attr + + return attr + else: + raise AttributeError(f"No {package_name} attribute {name}") + + def __dir__(): + return __all__ + + return __getattr__, __dir__ + + +__getattr__, __dir__ = _attach(__name__, submodules=[], submod_attrs=_SUBMOD_ATTRS) + +if os.environ.get("EAGER_IMPORT", ""): + for attr in __all__: + __getattr__(attr) + +# WARNING: any content below this statement is generated automatically. Any manual edit +# will be lost when re-generating this file ! +# +# To update the static imports, please run the following command and commit the changes. +# ``` +# # Use script +# python utils/check_static_imports.py --update +# +# # Or run style on codebase +# make style +# ``` +if TYPE_CHECKING: # pragma: no cover + from ._buckets import ( + BucketFile, # noqa: F401 + BucketFileMetadata, # noqa: F401 + BucketFolder, # noqa: F401 + BucketInfo, # noqa: F401 + BucketUrl, # noqa: F401 + SyncOperation, # noqa: F401 + SyncPlan, # noqa: F401 + ) + from ._commit_scheduler import CommitScheduler # noqa: F401 + from ._eval_results import ( + EvalResultEntry, # noqa: F401 + eval_result_entries_to_yaml, # noqa: F401 + parse_eval_result_entries, # noqa: F401 + ) + from ._inference_endpoints import ( + InferenceEndpoint, # noqa: F401 + InferenceEndpointError, # noqa: F401 + InferenceEndpointStatus, # noqa: F401 + InferenceEndpointTimeoutError, # noqa: F401 + InferenceEndpointType, # noqa: F401 + ) + from ._jobs_api import ( + JobAccelerator, # noqa: F401 + JobHardware, # noqa: F401 + JobInfo, # noqa: F401 + JobOwner, # noqa: F401 + JobStage, # noqa: F401 + JobStatus, # noqa: F401 + ) + from ._login import ( + auth_list, # noqa: F401 + auth_switch, # noqa: F401 + interpreter_login, # noqa: F401 + login, # noqa: F401 + logout, # noqa: F401 + notebook_login, # noqa: F401 + ) + from ._oauth import ( + OAuthInfo, # noqa: F401 + OAuthOrgInfo, # noqa: F401 + OAuthUserInfo, # noqa: F401 + attach_huggingface_oauth, # noqa: F401 + parse_huggingface_oauth, # noqa: F401 + ) + from ._snapshot_download import snapshot_download # noqa: F401 + from ._space_api import ( + SpaceHardware, # noqa: F401 + SpaceRuntime, # noqa: F401 + SpaceSecret, # noqa: F401 + SpaceStage, # noqa: F401 + SpaceStorage, # noqa: F401 + SpaceVariable, # noqa: F401 + Volume, # noqa: F401 + ) + from ._tensorboard_logger import HFSummaryWriter # noqa: F401 + from ._webhooks_payload import ( + WebhookPayload, # noqa: F401 + WebhookPayloadComment, # noqa: F401 + WebhookPayloadDiscussion, # noqa: F401 + WebhookPayloadDiscussionChanges, # noqa: F401 + WebhookPayloadEvent, # noqa: F401 + WebhookPayloadMovedTo, # noqa: F401 + WebhookPayloadRepo, # noqa: F401 + WebhookPayloadUrl, # noqa: F401 + WebhookPayloadWebhook, # noqa: F401 + ) + from ._webhooks_server import ( + WebhooksServer, # noqa: F401 + webhook_endpoint, # noqa: F401 + ) + from .cli._cli_utils import ( + check_cli_update, # noqa: F401 + typer_factory, # noqa: F401 + ) + from .community import ( + Discussion, # noqa: F401 + DiscussionComment, # noqa: F401 + DiscussionCommit, # noqa: F401 + DiscussionEvent, # noqa: F401 + DiscussionStatusChange, # noqa: F401 + DiscussionTitleChange, # noqa: F401 + DiscussionWithDetails, # noqa: F401 + ) + from .constants import ( + CONFIG_NAME, # noqa: F401 + FLAX_WEIGHTS_NAME, # noqa: F401 + HUGGINGFACE_CO_URL_HOME, # noqa: F401 + HUGGINGFACE_CO_URL_TEMPLATE, # noqa: F401 + PYTORCH_WEIGHTS_NAME, # noqa: F401 + REPO_TYPE_DATASET, # noqa: F401 + REPO_TYPE_MODEL, # noqa: F401 + REPO_TYPE_SPACE, # noqa: F401 + TF2_WEIGHTS_NAME, # noqa: F401 + TF_WEIGHTS_NAME, # noqa: F401 + is_offline_mode, # noqa: F401 + ) + from .fastai_utils import ( + _save_pretrained_fastai, # noqa: F401 + from_pretrained_fastai, # noqa: F401 + push_to_hub_fastai, # noqa: F401 + ) + from .file_download import ( + _CACHED_NO_EXIST, # noqa: F401 + DryRunFileInfo, # noqa: F401 + HfFileMetadata, # noqa: F401 + get_hf_file_metadata, # noqa: F401 + hf_hub_download, # noqa: F401 + hf_hub_url, # noqa: F401 + try_to_load_from_cache, # noqa: F401 + ) + from .hf_api import ( + Collection, # noqa: F401 + CollectionItem, # noqa: F401 + CommitInfo, # noqa: F401 + CommitOperation, # noqa: F401 + CommitOperationAdd, # noqa: F401 + CommitOperationCopy, # noqa: F401 + CommitOperationDelete, # noqa: F401 + DatasetInfo, # noqa: F401 + DatasetLeaderboardEntry, # noqa: F401 + GitCommitInfo, # noqa: F401 + GitRefInfo, # noqa: F401 + GitRefs, # noqa: F401 + HfApi, # noqa: F401 + KernelInfo, # noqa: F401 + ModelInfo, # noqa: F401 + Organization, # noqa: F401 + RepoFile, # noqa: F401 + RepoFolder, # noqa: F401 + RepoUrl, # noqa: F401 + SpaceInfo, # noqa: F401 + SpaceSearchResult, # noqa: F401 + User, # noqa: F401 + UserLikes, # noqa: F401 + WebhookInfo, # noqa: F401 + WebhookWatchedItem, # noqa: F401 + accept_access_request, # noqa: F401 + add_collection_item, # noqa: F401 + add_space_secret, # noqa: F401 + add_space_variable, # noqa: F401 + auth_check, # noqa: F401 + batch_bucket_files, # noqa: F401 + bucket_info, # noqa: F401 + cancel_access_request, # noqa: F401 + cancel_job, # noqa: F401 + change_discussion_status, # noqa: F401 + comment_discussion, # noqa: F401 + copy_files, # noqa: F401 + create_branch, # noqa: F401 + create_bucket, # noqa: F401 + create_collection, # noqa: F401 + create_commit, # noqa: F401 + create_discussion, # noqa: F401 + create_inference_endpoint, # noqa: F401 + create_inference_endpoint_from_catalog, # noqa: F401 + create_pull_request, # noqa: F401 + create_repo, # noqa: F401 + create_scheduled_job, # noqa: F401 + create_scheduled_uv_job, # noqa: F401 + create_tag, # noqa: F401 + create_webhook, # noqa: F401 + dataset_info, # noqa: F401 + delete_branch, # noqa: F401 + delete_bucket, # noqa: F401 + delete_collection, # noqa: F401 + delete_collection_item, # noqa: F401 + delete_file, # noqa: F401 + delete_folder, # noqa: F401 + delete_inference_endpoint, # noqa: F401 + delete_repo, # noqa: F401 + delete_scheduled_job, # noqa: F401 + delete_space_secret, # noqa: F401 + delete_space_storage, # noqa: F401 + delete_space_variable, # noqa: F401 + delete_space_volumes, # noqa: F401 + delete_tag, # noqa: F401 + delete_webhook, # noqa: F401 + disable_space_dev_mode, # noqa: F401 + disable_webhook, # noqa: F401 + download_bucket_files, # noqa: F401 + duplicate_repo, # noqa: F401 + duplicate_space, # noqa: F401 + edit_discussion_comment, # noqa: F401 + enable_space_dev_mode, # noqa: F401 + enable_webhook, # noqa: F401 + fetch_job_logs, # noqa: F401 + fetch_job_metrics, # noqa: F401 + fetch_space_logs, # noqa: F401 + file_exists, # noqa: F401 + get_bucket_file_metadata, # noqa: F401 + get_bucket_paths_info, # noqa: F401 + get_collection, # noqa: F401 + get_dataset_leaderboard, # noqa: F401 + get_dataset_tags, # noqa: F401 + get_discussion_details, # noqa: F401 + get_full_repo_name, # noqa: F401 + get_inference_endpoint, # noqa: F401 + get_local_safetensors_metadata, # noqa: F401 + get_model_tags, # noqa: F401 + get_organization_overview, # noqa: F401 + get_paths_info, # noqa: F401 + get_repo_discussions, # noqa: F401 + get_safetensors_metadata, # noqa: F401 + get_space_runtime, # noqa: F401 + get_space_secrets, # noqa: F401 + get_space_variables, # noqa: F401 + get_user_overview, # noqa: F401 + get_webhook, # noqa: F401 + grant_access, # noqa: F401 + inspect_job, # noqa: F401 + inspect_scheduled_job, # noqa: F401 + kernel_info, # noqa: F401 + list_accepted_access_requests, # noqa: F401 + list_bucket_tree, # noqa: F401 + list_buckets, # noqa: F401 + list_collections, # noqa: F401 + list_daily_papers, # noqa: F401 + list_dataset_parquet_files, # noqa: F401 + list_datasets, # noqa: F401 + list_inference_catalog, # noqa: F401 + list_inference_endpoints, # noqa: F401 + list_jobs, # noqa: F401 + list_jobs_hardware, # noqa: F401 + list_lfs_files, # noqa: F401 + list_liked_repos, # noqa: F401 + list_models, # noqa: F401 + list_organization_followers, # noqa: F401 + list_organization_members, # noqa: F401 + list_papers, # noqa: F401 + list_pending_access_requests, # noqa: F401 + list_rejected_access_requests, # noqa: F401 + list_repo_commits, # noqa: F401 + list_repo_files, # noqa: F401 + list_repo_likers, # noqa: F401 + list_repo_refs, # noqa: F401 + list_repo_tree, # noqa: F401 + list_spaces, # noqa: F401 + list_spaces_hardware, # noqa: F401 + list_user_followers, # noqa: F401 + list_user_following, # noqa: F401 + list_webhooks, # noqa: F401 + merge_pull_request, # noqa: F401 + model_info, # noqa: F401 + move_bucket, # noqa: F401 + move_repo, # noqa: F401 + paper_info, # noqa: F401 + parse_local_safetensors_file_metadata, # noqa: F401 + parse_safetensors_file_metadata, # noqa: F401 + pause_inference_endpoint, # noqa: F401 + pause_space, # noqa: F401 + permanently_delete_lfs_files, # noqa: F401 + preupload_lfs_files, # noqa: F401 + read_paper, # noqa: F401 + reject_access_request, # noqa: F401 + rename_discussion, # noqa: F401 + repo_exists, # noqa: F401 + repo_info, # noqa: F401 + repo_type_and_id_from_hf_id, # noqa: F401 + request_space_hardware, # noqa: F401 + request_space_storage, # noqa: F401 + restart_space, # noqa: F401 + resume_inference_endpoint, # noqa: F401 + resume_scheduled_job, # noqa: F401 + revision_exists, # noqa: F401 + run_as_future, # noqa: F401 + run_job, # noqa: F401 + run_uv_job, # noqa: F401 + scale_to_zero_inference_endpoint, # noqa: F401 + search_spaces, # noqa: F401 + set_space_sleep_time, # noqa: F401 + set_space_volumes, # noqa: F401 + space_info, # noqa: F401 + super_squash_history, # noqa: F401 + suspend_scheduled_job, # noqa: F401 + sync_bucket, # noqa: F401 + unlike, # noqa: F401 + update_collection_item, # noqa: F401 + update_collection_metadata, # noqa: F401 + update_inference_endpoint, # noqa: F401 + update_repo_settings, # noqa: F401 + update_webhook, # noqa: F401 + upload_file, # noqa: F401 + upload_folder, # noqa: F401 + upload_large_folder, # noqa: F401 + verify_repo_checksums, # noqa: F401 + whoami, # noqa: F401 + ) + from .hf_file_system import ( + HfFileSystem, # noqa: F401 + HfFileSystemFile, # noqa: F401 + HfFileSystemResolvedPath, # noqa: F401 + HfFileSystemStreamFile, # noqa: F401 + hffs, # noqa: F401 + ) + from .hub_mixin import ( + ModelHubMixin, # noqa: F401 + PyTorchModelHubMixin, # noqa: F401 + ) + from .inference._client import ( + InferenceClient, # noqa: F401 + InferenceTimeoutError, # noqa: F401 + ) + from .inference._generated._async_client import AsyncInferenceClient # noqa: F401 + from .inference._generated.types import ( + AudioClassificationInput, # noqa: F401 + AudioClassificationOutputElement, # noqa: F401 + AudioClassificationOutputTransform, # noqa: F401 + AudioClassificationParameters, # noqa: F401 + AudioToAudioInput, # noqa: F401 + AudioToAudioOutputElement, # noqa: F401 + AutomaticSpeechRecognitionEarlyStoppingEnum, # noqa: F401 + AutomaticSpeechRecognitionGenerationParameters, # noqa: F401 + AutomaticSpeechRecognitionInput, # noqa: F401 + AutomaticSpeechRecognitionOutput, # noqa: F401 + AutomaticSpeechRecognitionOutputChunk, # noqa: F401 + AutomaticSpeechRecognitionParameters, # noqa: F401 + ChatCompletionInput, # noqa: F401 + ChatCompletionInputFunctionDefinition, # noqa: F401 + ChatCompletionInputFunctionName, # noqa: F401 + ChatCompletionInputGrammarType, # noqa: F401 + ChatCompletionInputJSONSchema, # noqa: F401 + ChatCompletionInputMessage, # noqa: F401 + ChatCompletionInputMessageChunk, # noqa: F401 + ChatCompletionInputMessageChunkType, # noqa: F401 + ChatCompletionInputResponseFormatJSONObject, # noqa: F401 + ChatCompletionInputResponseFormatJSONSchema, # noqa: F401 + ChatCompletionInputResponseFormatText, # noqa: F401 + ChatCompletionInputStreamOptions, # noqa: F401 + ChatCompletionInputTool, # noqa: F401 + ChatCompletionInputToolCall, # noqa: F401 + ChatCompletionInputToolChoiceClass, # noqa: F401 + ChatCompletionInputToolChoiceEnum, # noqa: F401 + ChatCompletionInputURL, # noqa: F401 + ChatCompletionOutput, # noqa: F401 + ChatCompletionOutputComplete, # noqa: F401 + ChatCompletionOutputFunctionDefinition, # noqa: F401 + ChatCompletionOutputLogprob, # noqa: F401 + ChatCompletionOutputLogprobs, # noqa: F401 + ChatCompletionOutputMessage, # noqa: F401 + ChatCompletionOutputToolCall, # noqa: F401 + ChatCompletionOutputTopLogprob, # noqa: F401 + ChatCompletionOutputUsage, # noqa: F401 + ChatCompletionStreamOutput, # noqa: F401 + ChatCompletionStreamOutputChoice, # noqa: F401 + ChatCompletionStreamOutputDelta, # noqa: F401 + ChatCompletionStreamOutputDeltaToolCall, # noqa: F401 + ChatCompletionStreamOutputFunction, # noqa: F401 + ChatCompletionStreamOutputLogprob, # noqa: F401 + ChatCompletionStreamOutputLogprobs, # noqa: F401 + ChatCompletionStreamOutputTopLogprob, # noqa: F401 + ChatCompletionStreamOutputUsage, # noqa: F401 + DepthEstimationInput, # noqa: F401 + DepthEstimationOutput, # noqa: F401 + DocumentQuestionAnsweringInput, # noqa: F401 + DocumentQuestionAnsweringInputData, # noqa: F401 + DocumentQuestionAnsweringOutputElement, # noqa: F401 + DocumentQuestionAnsweringParameters, # noqa: F401 + FeatureExtractionInput, # noqa: F401 + FeatureExtractionInputTruncationDirection, # noqa: F401 + FillMaskInput, # noqa: F401 + FillMaskOutputElement, # noqa: F401 + FillMaskParameters, # noqa: F401 + ImageClassificationInput, # noqa: F401 + ImageClassificationOutputElement, # noqa: F401 + ImageClassificationOutputTransform, # noqa: F401 + ImageClassificationParameters, # noqa: F401 + ImageSegmentationInput, # noqa: F401 + ImageSegmentationOutputElement, # noqa: F401 + ImageSegmentationParameters, # noqa: F401 + ImageSegmentationSubtask, # noqa: F401 + ImageTextToImageInput, # noqa: F401 + ImageTextToImageOutput, # noqa: F401 + ImageTextToImageParameters, # noqa: F401 + ImageTextToImageTargetSize, # noqa: F401 + ImageTextToVideoInput, # noqa: F401 + ImageTextToVideoOutput, # noqa: F401 + ImageTextToVideoParameters, # noqa: F401 + ImageTextToVideoTargetSize, # noqa: F401 + ImageToImageInput, # noqa: F401 + ImageToImageOutput, # noqa: F401 + ImageToImageParameters, # noqa: F401 + ImageToImageTargetSize, # noqa: F401 + ImageToTextEarlyStoppingEnum, # noqa: F401 + ImageToTextGenerationParameters, # noqa: F401 + ImageToTextInput, # noqa: F401 + ImageToTextOutput, # noqa: F401 + ImageToTextParameters, # noqa: F401 + ImageToVideoInput, # noqa: F401 + ImageToVideoOutput, # noqa: F401 + ImageToVideoParameters, # noqa: F401 + ImageToVideoTargetSize, # noqa: F401 + ObjectDetectionBoundingBox, # noqa: F401 + ObjectDetectionInput, # noqa: F401 + ObjectDetectionOutputElement, # noqa: F401 + ObjectDetectionParameters, # noqa: F401 + Padding, # noqa: F401 + QuestionAnsweringInput, # noqa: F401 + QuestionAnsweringInputData, # noqa: F401 + QuestionAnsweringOutputElement, # noqa: F401 + QuestionAnsweringParameters, # noqa: F401 + SentenceSimilarityInput, # noqa: F401 + SentenceSimilarityInputData, # noqa: F401 + SummarizationInput, # noqa: F401 + SummarizationOutput, # noqa: F401 + SummarizationParameters, # noqa: F401 + SummarizationTruncationStrategy, # noqa: F401 + TableQuestionAnsweringInput, # noqa: F401 + TableQuestionAnsweringInputData, # noqa: F401 + TableQuestionAnsweringOutputElement, # noqa: F401 + TableQuestionAnsweringParameters, # noqa: F401 + Text2TextGenerationInput, # noqa: F401 + Text2TextGenerationOutput, # noqa: F401 + Text2TextGenerationParameters, # noqa: F401 + Text2TextGenerationTruncationStrategy, # noqa: F401 + TextClassificationInput, # noqa: F401 + TextClassificationOutputElement, # noqa: F401 + TextClassificationOutputTransform, # noqa: F401 + TextClassificationParameters, # noqa: F401 + TextGenerationInput, # noqa: F401 + TextGenerationInputGenerateParameters, # noqa: F401 + TextGenerationInputGrammarType, # noqa: F401 + TextGenerationOutput, # noqa: F401 + TextGenerationOutputBestOfSequence, # noqa: F401 + TextGenerationOutputDetails, # noqa: F401 + TextGenerationOutputFinishReason, # noqa: F401 + TextGenerationOutputPrefillToken, # noqa: F401 + TextGenerationOutputToken, # noqa: F401 + TextGenerationStreamOutput, # noqa: F401 + TextGenerationStreamOutputStreamDetails, # noqa: F401 + TextGenerationStreamOutputToken, # noqa: F401 + TextToAudioEarlyStoppingEnum, # noqa: F401 + TextToAudioGenerationParameters, # noqa: F401 + TextToAudioInput, # noqa: F401 + TextToAudioOutput, # noqa: F401 + TextToAudioParameters, # noqa: F401 + TextToImageInput, # noqa: F401 + TextToImageOutput, # noqa: F401 + TextToImageParameters, # noqa: F401 + TextToSpeechEarlyStoppingEnum, # noqa: F401 + TextToSpeechGenerationParameters, # noqa: F401 + TextToSpeechInput, # noqa: F401 + TextToSpeechOutput, # noqa: F401 + TextToSpeechParameters, # noqa: F401 + TextToVideoInput, # noqa: F401 + TextToVideoOutput, # noqa: F401 + TextToVideoParameters, # noqa: F401 + TokenClassificationAggregationStrategy, # noqa: F401 + TokenClassificationInput, # noqa: F401 + TokenClassificationOutputElement, # noqa: F401 + TokenClassificationParameters, # noqa: F401 + TranslationInput, # noqa: F401 + TranslationOutput, # noqa: F401 + TranslationParameters, # noqa: F401 + TranslationTruncationStrategy, # noqa: F401 + TypeEnum, # noqa: F401 + VideoClassificationInput, # noqa: F401 + VideoClassificationOutputElement, # noqa: F401 + VideoClassificationOutputTransform, # noqa: F401 + VideoClassificationParameters, # noqa: F401 + VisualQuestionAnsweringInput, # noqa: F401 + VisualQuestionAnsweringInputData, # noqa: F401 + VisualQuestionAnsweringOutputElement, # noqa: F401 + VisualQuestionAnsweringParameters, # noqa: F401 + ZeroShotClassificationInput, # noqa: F401 + ZeroShotClassificationOutputElement, # noqa: F401 + ZeroShotClassificationParameters, # noqa: F401 + ZeroShotImageClassificationInput, # noqa: F401 + ZeroShotImageClassificationOutputElement, # noqa: F401 + ZeroShotImageClassificationParameters, # noqa: F401 + ZeroShotObjectDetectionBoundingBox, # noqa: F401 + ZeroShotObjectDetectionInput, # noqa: F401 + ZeroShotObjectDetectionOutputElement, # noqa: F401 + ZeroShotObjectDetectionParameters, # noqa: F401 + ) + from .inference._mcp.agent import Agent # noqa: F401 + from .inference._mcp.mcp_client import MCPClient # noqa: F401 + from .repocard import ( + DatasetCard, # noqa: F401 + ModelCard, # noqa: F401 + RepoCard, # noqa: F401 + SpaceCard, # noqa: F401 + metadata_eval_result, # noqa: F401 + metadata_load, # noqa: F401 + metadata_save, # noqa: F401 + metadata_update, # noqa: F401 + ) + from .repocard_data import ( + CardData, # noqa: F401 + DatasetCardData, # noqa: F401 + EvalResult, # noqa: F401 + ModelCardData, # noqa: F401 + SpaceCardData, # noqa: F401 + ) + from .serialization import ( + StateDictSplit, # noqa: F401 + get_torch_storage_id, # noqa: F401 + get_torch_storage_size, # noqa: F401 + load_state_dict_from_file, # noqa: F401 + load_torch_model, # noqa: F401 + save_torch_model, # noqa: F401 + save_torch_state_dict, # noqa: F401 + split_state_dict_into_shards_factory, # noqa: F401 + split_torch_state_dict_into_shards, # noqa: F401 + ) + from .serialization._dduf import ( + DDUFEntry, # noqa: F401 + export_entries_as_dduf, # noqa: F401 + export_folder_as_dduf, # noqa: F401 + read_dduf_file, # noqa: F401 + ) + from .utils import ( + ASYNC_CLIENT_FACTORY_T, # noqa: F401 + CLIENT_FACTORY_T, # noqa: F401 + CachedFileInfo, # noqa: F401 + CachedRepoInfo, # noqa: F401 + CachedRevisionInfo, # noqa: F401 + CacheNotFound, # noqa: F401 + CorruptedCacheException, # noqa: F401 + DeleteCacheStrategy, # noqa: F401 + HFCacheInfo, # noqa: F401 + HfUri, # noqa: F401 + cached_assets_path, # noqa: F401 + close_session, # noqa: F401 + dump_environment_info, # noqa: F401 + get_async_session, # noqa: F401 + get_session, # noqa: F401 + get_token, # noqa: F401 + hf_raise_for_status, # noqa: F401 + logging, # noqa: F401 + parse_hf_uri, # noqa: F401 + scan_cache_dir, # noqa: F401 + set_async_client_factory, # noqa: F401 + set_client_factory, # noqa: F401 + ) diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_buckets.py b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_buckets.py new file mode 100644 index 0000000000000000000000000000000000000000..179b885032ddd32113b360a7c9d99a3ff7670866 --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_buckets.py @@ -0,0 +1,1225 @@ +# Copyright 2026-present, the HuggingFace Inc. team. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Shared logic for bucket operations. + +This module contains the core buckets logic used by both the CLI and the Python API. +""" + +import fnmatch +import json +import mimetypes +import os +import stat +import sys +import time +from collections.abc import Iterator +from dataclasses import dataclass, field +from datetime import datetime, timezone +from pathlib import Path +from typing import TYPE_CHECKING, Any, Literal + +from . import constants, logging +from .errors import BucketNotFoundError +from .utils import XetFileData, disable_progress_bars, enable_progress_bars, parse_datetime +from .utils._terminal import StatusLine + + +if TYPE_CHECKING: + from .hf_api import HfApi + + +logger = logging.get_logger(__name__) + + +BUCKET_PREFIX = "hf://buckets/" +_SYNC_TIME_WINDOW_MS = 1000 # 1s safety-window for file modification time comparisons + + +# ============================================================================= +# Bucket data structures +# ============================================================================= + + +def _split_bucket_id_and_prefix(path: str) -> tuple[str, str]: + """Split 'namespace/name(/optional/prefix)' into ('namespace/name', 'prefix'). + + Returns (bucket_id, prefix) where prefix may be empty string. + Raises ValueError if path doesn't contain at least namespace/name. + """ + parts = path.split("/", 2) + if len(parts) < 2 or not parts[0] or not parts[1]: + raise ValueError(f"Invalid bucket path: '{path}'. Expected format: namespace/bucket_name") + bucket_id = f"{parts[0]}/{parts[1]}" + prefix = parts[2] if len(parts) > 2 else "" + return bucket_id, prefix + + +@dataclass +class BucketInfo: + """ + Contains information about a bucket on the Hub. This object is returned by [`bucket_info`] and [`list_buckets`]. + + Attributes: + id (`str`): + ID of the bucket. + private (`bool`): + Is the bucket private. + created_at (`datetime`): + Date of creation of the bucket on the Hub. + size (`int`): + Size of the bucket in bytes. + total_files (`int`): + Total number of files in the bucket. + """ + + id: str + private: bool + created_at: datetime + size: int + total_files: int + + def __init__(self, **kwargs): + self.id = kwargs.pop("id") + self.private = kwargs.pop("private") + self.created_at = parse_datetime(kwargs.pop("createdAt")) + self.size = kwargs.pop("size") + self.total_files = kwargs.pop("totalFiles") + self.__dict__.update(**kwargs) + + +@dataclass +class _BucketAddFile: + source: str | Path | bytes + destination: str + + xet_hash: str | None = field(default=None) + size: int | None = field(default=None) + mtime: int = field(init=False) + content_type: str | None = field(init=False) + + def __post_init__(self) -> None: + self.content_type = None + if isinstance(self.source, (str, Path)): # guess content type from source path + self.content_type = mimetypes.guess_type(self.source)[0] + if self.content_type is None: # or default to destination path content type + self.content_type = mimetypes.guess_type(self.destination)[0] + + self.mtime = int( + os.path.getmtime(self.source) * 1000 if not isinstance(self.source, bytes) else time.time() * 1000 + ) + + +@dataclass +class _BucketCopyFile: + destination: str + xet_hash: str + source_repo_type: str # "model", "dataset", "space", "bucket" + source_repo_id: str + size: int | None = field(default=None) + mtime: int = field(init=False) + content_type: str | None = field(init=False) + + def __post_init__(self) -> None: + self.content_type = mimetypes.guess_type(self.destination)[0] + self.mtime = int(time.time() * 1000) + + +@dataclass +class _BucketDeleteFile: + path: str + + +@dataclass(frozen=True) +class BucketFileMetadata: + """Data structure containing information about a file in a bucket. + + Returned by [`get_bucket_file_metadata`]. + + Args: + size (`int`): + Size of the file in bytes. + xet_file_data (`XetFileData`): + Xet information for the file (hash and refresh route). + """ + + size: int + xet_file_data: XetFileData + + +@dataclass +class BucketUrl: + """Describes a bucket URL on the Hub. + + `BucketUrl` is returned by [`create_bucket`]. At initialization, the URL is parsed to populate properties: + - endpoint (`str`) + - namespace (`str`) + - bucket_id (`str`) + - url (`str`) + - handle (`str`) + + Args: + url (`str`): + String value of the bucket url. + endpoint (`str`, *optional*): + Endpoint of the Hub. Defaults to . + """ + + url: str + endpoint: str = "" + namespace: str = field(init=False) + bucket_id: str = field(init=False) + handle: str = field(init=False) + + def __post_init__(self) -> None: + self.endpoint = self.endpoint or constants.ENDPOINT + + # Parse URL: expected format is `{endpoint}/buckets/{namespace}/{bucket_name}` + url_path = self.url.replace(self.endpoint, "").strip("/") + # Remove leading "buckets/" prefix + if url_path.startswith("buckets/"): + url_path = url_path[len("buckets/") :] + bucket_id, prefix = _split_bucket_id_and_prefix(url_path) + if prefix: + raise ValueError(f"Unable to parse bucket URL: {self.url}") + self.namespace = bucket_id.split("/")[0] + self.bucket_id = bucket_id + + self.handle = f"hf://buckets/{self.bucket_id}" + + +@dataclass +class BucketFile: + """ + Contains information about a file in a bucket on the Hub. This object is returned by [`list_bucket_tree`]. + + Similar to [`RepoFile`] but for files in buckets. + """ + + type: Literal["file"] + path: str + size: int + xet_hash: str + mtime: datetime | None + uploaded_at: datetime | None + + def __init__(self, **kwargs): + self.type = kwargs.pop("type") + self.path = kwargs.pop("path") + self.size = kwargs.pop("size") + self.xet_hash = kwargs.pop("xetHash") + mtime = kwargs.pop("mtime", None) + self.mtime = parse_datetime(mtime) if mtime else None + uploaded_at = kwargs.pop("uploadedAt", None) + self.uploaded_at = parse_datetime(uploaded_at) if uploaded_at else None + + +@dataclass +class BucketFolder: + """ + Contains information about a directory in a bucket on the Hub. This object is returned by [`list_bucket_tree`]. + + Similar to [`RepoFolder`] but for directories in buckets. + """ + + type: Literal["directory"] + path: str + uploaded_at: datetime | None + + def __init__(self, **kwargs): + self.type = kwargs.pop("type") + self.path = kwargs.pop("path") + uploaded_at = kwargs.pop("uploadedAt", None) or kwargs.pop("uploaded_at", None) + self.uploaded_at = ( + (uploaded_at if isinstance(uploaded_at, datetime) else parse_datetime(uploaded_at)) + if uploaded_at + else None + ) + + +# ============================================================================= +# Bucket path parsing +# ============================================================================= + + +def _parse_bucket_path(path: str) -> tuple[str, str]: + """Parse a bucket path like hf://buckets/namespace/bucket_name/prefix into (bucket_id, prefix). + + Returns: + tuple: (bucket_id, prefix) where bucket_id is "namespace/bucket_name" and prefix may be empty string. + """ + if not path.startswith(BUCKET_PREFIX): + raise ValueError(f"Invalid bucket path: {path}. Must start with {BUCKET_PREFIX}") + return _split_bucket_id_and_prefix(path.removeprefix(BUCKET_PREFIX)) + + +def _is_bucket_path(path: str) -> bool: + """Check if a path is a bucket path.""" + return path.startswith(BUCKET_PREFIX) + + +# ============================================================================= +# Sync data structures +# ============================================================================= + + +@dataclass +class SyncOperation: + """Represents a sync operation to be performed.""" + + action: Literal["upload", "download", "delete", "skip"] + path: str + size: int | None = None + reason: str = "" + local_mtime: str | None = None + remote_mtime: str | None = None + bucket_file: BucketFile | None = None # BucketFile when available (not serialized to plan file) + + +@dataclass +class SyncPlan: + """Represents a complete sync plan.""" + + source: str + dest: str + timestamp: str + operations: list[SyncOperation] = field(default_factory=list) + + def summary(self) -> dict[str, int | str]: + uploads = sum(1 for op in self.operations if op.action == "upload") + downloads = sum(1 for op in self.operations if op.action == "download") + deletes = sum(1 for op in self.operations if op.action == "delete") + skips = sum(1 for op in self.operations if op.action == "skip") + total_size = sum(op.size or 0 for op in self.operations if op.action in ("upload", "download")) + return { + "uploads": uploads, + "downloads": downloads, + "deletes": deletes, + "skips": skips, + "total_size": total_size, + } + + +# ============================================================================= +# Filter matching +# ============================================================================= + + +class FilterMatcher: + """Matches file paths against include/exclude patterns.""" + + def __init__( + self, + include_patterns: list[str] | None = None, + exclude_patterns: list[str] | None = None, + filter_rules: list[tuple[str, str]] | None = None, + ): + """Initialize the filter matcher. + + Args: + include_patterns: Patterns to include (from --include) + exclude_patterns: Patterns to exclude (from --exclude) + filter_rules: Rules from filter file as list of ("+"/"-", pattern) tuples + """ + self.include_patterns = include_patterns or [] + self.exclude_patterns = exclude_patterns or [] + self.filter_rules = filter_rules or [] + + def matches(self, path: str) -> bool: + """Check if a path should be included based on the filter rules. + + Filtering rules: + - Filters are evaluated in order, first matching rule decides + - If no rules match, include by default (unless include patterns are specified) + """ + # First check filter rules from file (in order) + for sign, pattern in self.filter_rules: + if fnmatch.fnmatch(path, pattern): + return sign == "+" + + # Then check CLI patterns + for pattern in self.exclude_patterns: + if fnmatch.fnmatch(path, pattern): + return False + + for pattern in self.include_patterns: + if fnmatch.fnmatch(path, pattern): + return True + + # If include patterns were specified but none matched, exclude + if self.include_patterns: + return False + + # Default: include + return True + + +def _parse_filter_file(filter_file: str) -> list[tuple[str, str]]: + """Parse a filter file and return a list of (sign, pattern) tuples. + + Filter file format: + - Lines starting with "+" are include patterns + - Lines starting with "-" are exclude patterns + - Empty lines and lines starting with "#" are ignored + """ + rules = [] + with open(filter_file) as f: + for line in f: + line = line.strip() + if not line or line.startswith("#"): + continue + if line.startswith("+"): + rules.append(("+", line[1:].strip())) + elif line.startswith("-"): + rules.append(("-", line[1:].strip())) + else: + # Default to include if no prefix + rules.append(("+", line)) + return rules + + +# ============================================================================= +# File listing +# ============================================================================= + + +def _stat_local(path: str) -> tuple[int, float] | None: + """Stat a local file and return (size, mtime_ms). + + Returns None if the path is missing or is a directory. Uses a single + ``os.stat`` call so callers don't pay for multiple syscalls per file. + """ + try: + st = os.stat(path) + except OSError: + return None + if stat.S_ISDIR(st.st_mode): + return None + return st.st_size, st.st_mtime * 1000 + + +def _list_local_files(local_path: str) -> Iterator[tuple[str, int, float]]: + """List all files in a local directory. + + Yields: + tuple: (relative_path, size, mtime_ms) for each file + """ + local_path = os.path.abspath(local_path) + if not os.path.isdir(local_path): + raise ValueError(f"Local path must be a directory: {local_path}") + + for root, _, files in os.walk(local_path): + for filename in files: + full_path = os.path.join(root, filename) + stat_info = _stat_local(full_path) + if stat_info is None: + continue + rel_path = os.path.relpath(full_path, local_path) + # Normalize to forward slashes for consistency + rel_path = rel_path.replace(os.sep, "/") + yield rel_path, stat_info[0], stat_info[1] + + +def _list_remote_files(api: "HfApi", bucket_id: str, prefix: str) -> Iterator[tuple[str, int, float, Any]]: + """List all files in a bucket with a given prefix. + + Yields: + tuple: (relative_path, size, mtime_ms, bucket_file) for each file. + bucket_file is the BucketFile object from list_bucket_tree. + """ + for item in api.list_bucket_tree(bucket_id, prefix=prefix or None, recursive=True): + if isinstance(item, BucketFolder): + continue + path = item.path + # Remove prefix from path to get relative path + # Only strip prefix if it's followed by "/" (directory boundary) or is exact match + if prefix: + if path.startswith(prefix + "/"): + rel_path = path[len(prefix) + 1 :] + elif path == prefix: + # Exact match: the file IS the prefix (e.g., single file download) + rel_path = path.rsplit("/", 1)[-1] if "/" in path else path + else: + # Path doesn't match prefix pattern (e.g., "submarine.txt" for prefix "sub") + # Skip this file - it was returned by the API but doesn't belong to this prefix + continue + else: + rel_path = path + mtime_ms = item.mtime.timestamp() * 1000 if item.mtime else 0 + yield rel_path, item.size, mtime_ms, item + + +# ============================================================================= +# Sync plan computation +# ============================================================================= + + +def _mtime_to_iso(mtime_ms: float) -> str: + """Convert mtime in milliseconds to ISO format string.""" + return datetime.fromtimestamp(mtime_ms / 1000, tz=timezone.utc).isoformat() + + +def _compare_files_for_sync( + *, + path: str, + action: Literal["upload", "download"], + source_size: int, + source_mtime: float, + dest_size: int, + dest_mtime: float, + source_newer_label: str, + dest_newer_label: str, + ignore_sizes: bool, + ignore_times: bool, + ignore_existing: bool, + bucket_file: Any | None = None, +) -> SyncOperation: + """Compare source and dest files and return the appropriate sync operation. + + This is a unified helper for both upload and download directions. + + Args: + path: Relative file path + action: "upload" or "download" + source_size: Size of the source file (bytes) + source_mtime: Mtime of the source file (milliseconds) + dest_size: Size of the destination file (bytes) + dest_mtime: Mtime of the destination file (milliseconds) + source_newer_label: Label when source is newer (e.g., "local newer" or "remote newer") + dest_newer_label: Label when dest is newer (e.g., "remote newer" or "local newer") + ignore_sizes: Only compare mtime + ignore_times: Only compare size + ignore_existing: Skip files that exist on receiver + bucket_file: BucketFile object (for downloads only) + + Returns: + SyncOperation describing the action to take + """ + local_mtime_iso = _mtime_to_iso(source_mtime if action == "upload" else dest_mtime) + remote_mtime_iso = _mtime_to_iso(dest_mtime if action == "upload" else source_mtime) + + base_kwargs: dict[str, Any] = { + "path": path, + "size": source_size, + "local_mtime": local_mtime_iso, + "remote_mtime": remote_mtime_iso, + } + + if ignore_existing: + return SyncOperation(action="skip", reason="exists on receiver (--ignore-existing)", **base_kwargs) + + size_differs = source_size != dest_size + source_newer = (source_mtime - dest_mtime) > _SYNC_TIME_WINDOW_MS + + if ignore_sizes: + if source_newer: + return SyncOperation(action=action, reason=source_newer_label, bucket_file=bucket_file, **base_kwargs) + else: + dest_newer = (dest_mtime - source_mtime) > _SYNC_TIME_WINDOW_MS + skip_reason = dest_newer_label if dest_newer else "same mtime" + return SyncOperation(action="skip", reason=skip_reason, **base_kwargs) + elif ignore_times: + if size_differs: + return SyncOperation(action=action, reason="size differs", bucket_file=bucket_file, **base_kwargs) + else: + return SyncOperation(action="skip", reason="same size", **base_kwargs) + else: + if size_differs or source_newer: + reason = "size differs" if size_differs else source_newer_label + return SyncOperation(action=action, reason=reason, bucket_file=bucket_file, **base_kwargs) + else: + return SyncOperation(action="skip", reason="identical", **base_kwargs) + + +def _compute_sync_plan( + source: str, + dest: str, + api: "HfApi", + delete: bool = False, + ignore_times: bool = False, + ignore_sizes: bool = False, + existing: bool = False, + ignore_existing: bool = False, + filter_matcher: FilterMatcher | None = None, + status: Any | None = None, +) -> SyncPlan: + """Compute the sync plan by comparing source and destination. + + Returns: + SyncPlan with all operations to be performed + """ + filter_matcher = filter_matcher or FilterMatcher() + is_upload = not _is_bucket_path(source) and _is_bucket_path(dest) + is_download = _is_bucket_path(source) and not _is_bucket_path(dest) + + if not is_upload and not is_download: + raise ValueError("One of source or dest must be a bucket path (hf://buckets/...) and the other must be local.") + + plan = SyncPlan( + source=source, + dest=dest, + timestamp=datetime.now(timezone.utc).isoformat(), + ) + + remote_total: int | None = None + if is_upload: + # Local -> Remote + local_path = os.path.abspath(source) + bucket_id, prefix = _parse_bucket_path(dest) + + if not os.path.isdir(local_path): + raise ValueError(f"Source must be a directory: {local_path}") + + # Get local and remote file lists + local_files = {} + for rel_path, size, mtime_ms in _list_local_files(local_path): + if filter_matcher.matches(rel_path): + local_files[rel_path] = (size, mtime_ms) + if status: + status.update(f"Scanning local directory ({len(local_files)} files)") + if status: + status.done(f"Scanning local directory ({len(local_files)} files)") + + remote_files = {} + if status: + try: + remote_total = api.bucket_info(bucket_id).total_files + except Exception: + pass + try: + for rel_path, size, mtime_ms, _ in _list_remote_files(api, bucket_id, prefix): + if filter_matcher.matches(rel_path): + remote_files[rel_path] = (size, mtime_ms) + if status: + total_str = f"/{remote_total}" if remote_total is not None else "" + status.update(f"Scanning remote bucket ({len(remote_files)}{total_str} files)") + except BucketNotFoundError: + # Bucket doesn't exist yet - this is expected for new uploads + logger.debug(f"Bucket '{bucket_id}' not found, treating as empty.") + if status: + status.done(f"Scanning remote bucket ({len(remote_files)} files)") + + # Compare files + all_paths = set(local_files.keys()) | set(remote_files.keys()) + if status: + status.done(f"Comparing files ({len(all_paths)} paths)") + for path in sorted(all_paths): + local_info = local_files.get(path) + remote_info = remote_files.get(path) + + if local_info and not remote_info: + # New file + if existing: + # --existing: skip new files + plan.operations.append( + SyncOperation( + action="skip", + path=path, + size=local_info[0], + reason="new file (--existing)", + local_mtime=_mtime_to_iso(local_info[1]), + ) + ) + else: + plan.operations.append( + SyncOperation( + action="upload", + path=path, + size=local_info[0], + reason="new file", + local_mtime=_mtime_to_iso(local_info[1]), + ) + ) + elif local_info and remote_info: + # File exists in both - use helper to determine action + local_size, local_mtime = local_info + remote_size, remote_mtime = remote_info + plan.operations.append( + _compare_files_for_sync( + path=path, + action="upload", + source_size=local_size, + source_mtime=local_mtime, + dest_size=remote_size, + dest_mtime=remote_mtime, + source_newer_label="local newer", + dest_newer_label="remote newer", + ignore_sizes=ignore_sizes, + ignore_times=ignore_times, + ignore_existing=ignore_existing, + ) + ) + elif not local_info and remote_info and delete: + # File only in remote and --delete mode + plan.operations.append( + SyncOperation( + action="delete", + path=path, + size=remote_info[0], + reason="not in source (--delete)", + remote_mtime=_mtime_to_iso(remote_info[1]), + ) + ) + + else: + # Remote -> Local (download) + bucket_id, prefix = _parse_bucket_path(source) + local_path = os.path.abspath(dest) + + # Get remote and local file lists + remote_files = {} + bucket_file_map: dict[str, Any] = {} + if status: + try: + remote_total = api.bucket_info(bucket_id).total_files + except Exception: + pass + for rel_path, size, mtime_ms, bucket_file in _list_remote_files(api, bucket_id, prefix): + if filter_matcher.matches(rel_path): + remote_files[rel_path] = (size, mtime_ms) + bucket_file_map[rel_path] = bucket_file + if status: + total_str = f"/{remote_total}" if remote_total is not None else "" + status.update(f"Scanning remote bucket ({len(remote_files)}{total_str} files)") + if status: + status.done(f"Scanning remote bucket ({len(remote_files)} files)") + + local_files = {} + if os.path.isdir(local_path): + if delete: + # Full walk needed to discover local-only files for deletion. + for rel_path, size, mtime_ms in _list_local_files(local_path): + if filter_matcher.matches(rel_path): + local_files[rel_path] = (size, mtime_ms) + if status: + status.update(f"Scanning local directory ({len(local_files)} files)") + else: + # Without --delete, the plan only depends on paths that exist + # remotely. Stat just those instead of walking the whole tree, + # which can take minutes when dest sits in a large directory + # like ~/.cache/huggingface/. + for rel_path in remote_files: + local_file = os.path.join(local_path, rel_path) + stat_info = _stat_local(local_file) + if stat_info is None: + continue + local_files[rel_path] = stat_info + if status: + status.update(f"Scanning local directory ({len(local_files)} files)") + if status: + status.done(f"Scanning local directory ({len(local_files)} files)") + + # Compare files + all_paths = set(remote_files.keys()) | set(local_files.keys()) + if status: + status.done(f"Comparing files ({len(all_paths)} paths)") + for path in sorted(all_paths): + remote_info = remote_files.get(path) + local_info = local_files.get(path) + + if remote_info and not local_info: + # New file + if existing: + # --existing: skip new files + plan.operations.append( + SyncOperation( + action="skip", + path=path, + size=remote_info[0], + reason="new file (--existing)", + remote_mtime=_mtime_to_iso(remote_info[1]), + ) + ) + else: + plan.operations.append( + SyncOperation( + action="download", + path=path, + size=remote_info[0], + reason="new file", + remote_mtime=_mtime_to_iso(remote_info[1]), + bucket_file=bucket_file_map.get(path), + ) + ) + elif remote_info and local_info: + # File exists in both - use helper to determine action + remote_size, remote_mtime = remote_info + local_size, local_mtime = local_info + plan.operations.append( + _compare_files_for_sync( + path=path, + action="download", + source_size=remote_size, + source_mtime=remote_mtime, + dest_size=local_size, + dest_mtime=local_mtime, + source_newer_label="remote newer", + dest_newer_label="local newer", + ignore_sizes=ignore_sizes, + ignore_times=ignore_times, + ignore_existing=ignore_existing, + bucket_file=bucket_file_map.get(path), + ) + ) + elif not remote_info and local_info and delete: + # File only in local and --delete mode + plan.operations.append( + SyncOperation( + action="delete", + path=path, + size=local_info[0], + reason="not in source (--delete)", + local_mtime=_mtime_to_iso(local_info[1]), + ) + ) + + return plan + + +# ============================================================================= +# Plan serialization +# ============================================================================= + + +def _write_plan(plan: SyncPlan, f) -> None: + """Write a sync plan as JSONL to a file-like object.""" + # Write header + header = { + "type": "header", + "source": plan.source, + "dest": plan.dest, + "timestamp": plan.timestamp, + "summary": plan.summary(), + } + f.write(json.dumps(header) + "\n") + + # Write operations + for op in plan.operations: + op_dict: dict[str, Any] = { + "type": "operation", + "action": op.action, + "path": op.path, + "reason": op.reason, + } + if op.size is not None: + op_dict["size"] = op.size + if op.local_mtime is not None: + op_dict["local_mtime"] = op.local_mtime + if op.remote_mtime is not None: + op_dict["remote_mtime"] = op.remote_mtime + f.write(json.dumps(op_dict) + "\n") + + +def _save_plan(plan: SyncPlan, plan_file: str) -> None: + """Save a sync plan to a JSONL file.""" + with open(plan_file, "w") as f: + _write_plan(plan, f) + + +def _load_plan(plan_file: str) -> SyncPlan: + """Load a sync plan from a JSONL file.""" + with open(plan_file) as f: + lines = f.readlines() + + if not lines: + raise ValueError(f"Empty plan file: {plan_file}") + + # Parse header + header = json.loads(lines[0]) + if header.get("type") != "header": + raise ValueError("Invalid plan file: expected header as first line") + + plan = SyncPlan( + source=header["source"], + dest=header["dest"], + timestamp=header["timestamp"], + ) + + # Parse operations + for line in lines[1:]: + op_dict = json.loads(line) + if op_dict.get("type") != "operation": + continue + plan.operations.append( + SyncOperation( + action=op_dict["action"], + path=op_dict["path"], + size=op_dict.get("size"), + reason=op_dict.get("reason", ""), + local_mtime=op_dict.get("local_mtime"), + remote_mtime=op_dict.get("remote_mtime"), + ) + ) + + return plan + + +# ============================================================================= +# Plan execution +# ============================================================================= + + +def _execute_plan(plan: SyncPlan, api: "HfApi", verbose: bool = False, status: Any | None = None) -> None: + """Execute a sync plan.""" + is_upload = not _is_bucket_path(plan.source) and _is_bucket_path(plan.dest) + is_download = _is_bucket_path(plan.source) and not _is_bucket_path(plan.dest) + + if is_upload: + local_path = os.path.abspath(plan.source) + bucket_id, prefix = _parse_bucket_path(plan.dest) + prefix = prefix.rstrip("/") # Avoid double slashes in remote paths + + # Collect operations + add_files: list[tuple[str | Path | bytes, str]] = [] + delete_paths: list[str] = [] + + for op in plan.operations: + match op.action: + case "upload": + local_file = os.path.join(local_path, op.path) + remote_path = f"{prefix}/{op.path}" if prefix else op.path + if verbose: + print(f" Uploading: {op.path} ({op.reason})") + add_files.append((local_file, remote_path)) + case "delete": + remote_path = f"{prefix}/{op.path}" if prefix else op.path + if verbose: + print(f" Deleting: {op.path} ({op.reason})") + delete_paths.append(remote_path) + case "skip" if verbose: + print(f" Skipping: {op.path} ({op.reason})") + + # Execute batch operations + if add_files or delete_paths: + if status: + parts = [] + if add_files: + parts.append(f"uploading {len(add_files)} files") + if delete_paths: + parts.append(f"deleting {len(delete_paths)} files") + status.done(", ".join(parts).capitalize()) + api.batch_bucket_files( + bucket_id, + add=add_files or None, + delete=delete_paths or None, + ) + + elif is_download: + bucket_id, prefix = _parse_bucket_path(plan.source) + prefix = prefix.rstrip("/") # Avoid double slashes in remote paths + local_path = os.path.abspath(plan.dest) + + # Ensure local directory exists + os.makedirs(local_path, exist_ok=True) + + # Collect download operations + download_files: list[tuple[str | BucketFile, str | Path]] = [] + delete_files: list[str] = [] + + for op in plan.operations: + if op.action == "download": + local_file = os.path.join(local_path, op.path) + # Ensure parent directory exists + os.makedirs(os.path.dirname(local_file), exist_ok=True) + if verbose: + print(f" Downloading: {op.path} ({op.reason})") + # Use BucketFile when available (avoids extra metadata fetch per file) + if op.bucket_file is not None: + download_files.append((op.bucket_file, local_file)) + else: + remote_path = f"{prefix}/{op.path}" if prefix else op.path + download_files.append((remote_path, local_file)) + elif op.action == "delete": + local_file = os.path.join(local_path, op.path) + if verbose: + print(f" Deleting: {op.path} ({op.reason})") + delete_files.append(local_file) + elif op.action == "skip" and verbose: + print(f" Skipping: {op.path} ({op.reason})") + + # Execute downloads + if len(download_files) > 0: + if status: + status.done(f"Downloading {len(download_files)} files") + api.download_bucket_files(bucket_id, download_files) + + # Execute deletes + if status and delete_files: + status.done(f"Deleting {len(delete_files)} local files") + for file_path in delete_files: + if os.path.exists(file_path): + os.remove(file_path) + # Remove empty parent directories + parent = os.path.dirname(file_path) + while parent != local_path: + try: + os.rmdir(parent) + parent = os.path.dirname(parent) + except OSError: + break + + +def _print_plan_summary(plan: SyncPlan) -> None: + """Print a summary of the sync plan.""" + summary = plan.summary() + print(f"Sync plan: {plan.source} -> {plan.dest}") + print(f" Uploads: {summary['uploads']}") + print(f" Downloads: {summary['downloads']}") + print(f" Deletes: {summary['deletes']}") + print(f" Skips: {summary['skips']}") + + +# ============================================================================= +# Public sync function (Python API) +# ============================================================================= + + +def sync_bucket_internal( + source: str | None = None, + dest: str | None = None, + *, + api: "HfApi", + delete: bool = False, + ignore_times: bool = False, + ignore_sizes: bool = False, + existing: bool = False, + ignore_existing: bool = False, + include: list[str] | None = None, + exclude: list[str] | None = None, + filter_from: str | None = None, + plan: str | None = None, + apply: str | None = None, + dry_run: bool = False, + verbose: bool = False, + quiet: bool = False, + token: bool | str | None = None, +) -> SyncPlan: + """Sync files between a local directory and a bucket. + + This is equivalent to the ``hf buckets sync`` CLI command. One of ``source`` or ``dest`` must be a bucket path + (``hf://buckets/...``) and the other must be a local directory path. + + Args: + source (`str`, *optional*): + Source path: local directory or ``hf://buckets/namespace/bucket_name(/prefix)``. + Required unless using ``apply``. + dest (`str`, *optional*): + Destination path: local directory or ``hf://buckets/namespace/bucket_name(/prefix)``. + Required unless using ``apply``. + api ([`HfApi`]): + The HfApi instance to use for API calls. + delete (`bool`, *optional*, defaults to `False`): + Delete destination files not present in source. + ignore_times (`bool`, *optional*, defaults to `False`): + Skip files only based on size, ignoring modification times. + ignore_sizes (`bool`, *optional*, defaults to `False`): + Skip files only based on modification times, ignoring sizes. + existing (`bool`, *optional*, defaults to `False`): + Skip creating new files on receiver (only update existing files). + ignore_existing (`bool`, *optional*, defaults to `False`): + Skip updating files that exist on receiver (only create new files). + include (`list[str]`, *optional*): + Include files matching patterns (fnmatch-style). + exclude (`list[str]`, *optional*): + Exclude files matching patterns (fnmatch-style). + filter_from (`str`, *optional*): + Path to a filter file with include/exclude rules. + plan (`str`, *optional*): + Save sync plan to this JSONL file instead of executing. + apply (`str`, *optional*): + Apply a previously saved plan file. When set, ``source`` and ``dest`` are not needed. + dry_run (`bool`, *optional*, defaults to `False`): + Print sync plan to stdout as JSONL without executing. + verbose (`bool`, *optional*, defaults to `False`): + Show detailed per-file operations. + quiet (`bool`, *optional*, defaults to `False`): + Suppress all output and progress bars. + token (Union[bool, str, None], optional): + A valid user access token. If not provided, the locally saved token will be used. + + Returns: + [`SyncPlan`]: The computed (or loaded) sync plan. + + Raises: + `ValueError`: If arguments are invalid (e.g., both paths are remote, conflicting options). + + Example: + ```python + >>> from huggingface_hub import HfApi + >>> api = HfApi() + + # Upload local directory to bucket + >>> api.sync_bucket("./data", "hf://buckets/username/my-bucket") + + # Download bucket to local directory + >>> api.sync_bucket("hf://buckets/username/my-bucket", "./data") + + # Sync with delete and filtering + >>> api.sync_bucket( + ... "./data", + ... "hf://buckets/username/my-bucket", + ... delete=True, + ... include=["*.safetensors"], + ... ) + + # Dry run: preview what would be synced + >>> plan = api.sync_bucket("./data", "hf://buckets/username/my-bucket", dry_run=True) + >>> plan.summary() + {'uploads': 3, 'downloads': 0, 'deletes': 0, 'skips': 1, 'total_size': 4096} + + # Save plan for review, then apply + >>> api.sync_bucket("./data", "hf://buckets/username/my-bucket", plan="sync-plan.jsonl") + >>> api.sync_bucket(apply="sync-plan.jsonl") + ``` + """ + # Build API with token if needed + if token is not None: + from .hf_api import HfApi + + api = HfApi(token=token) + # --- Apply mode --- + if apply: + if source or dest: + raise ValueError("Cannot specify source/dest when using apply.") + if plan is not None: + raise ValueError("Cannot specify both plan and apply.") + if delete: + raise ValueError("Cannot specify delete when using apply.") + if ignore_times: + raise ValueError("Cannot specify ignore_times when using apply.") + if ignore_sizes: + raise ValueError("Cannot specify ignore_sizes when using apply.") + if include: + raise ValueError("Cannot specify include when using apply.") + if exclude: + raise ValueError("Cannot specify exclude when using apply.") + if filter_from: + raise ValueError("Cannot specify filter_from when using apply.") + if existing: + raise ValueError("Cannot specify existing when using apply.") + if ignore_existing: + raise ValueError("Cannot specify ignore_existing when using apply.") + if dry_run: + raise ValueError("Cannot specify dry_run when using apply.") + + sync_plan = _load_plan(apply) + status = StatusLine(enabled=not quiet) + if not quiet: + _print_plan_summary(sync_plan) + print("Executing plan...") + + if quiet: + disable_progress_bars() + try: + _execute_plan(sync_plan, api, verbose=verbose, status=status) + finally: + if quiet: + enable_progress_bars() + + if not quiet: + print("Sync completed.") + + return sync_plan + + # --- Normal mode --- + if not source or not dest: + raise ValueError("Both source and dest are required (unless using apply).") + + source_is_bucket = _is_bucket_path(source) + dest_is_bucket = _is_bucket_path(dest) + + if source_is_bucket and dest_is_bucket: + raise ValueError("Remote to remote sync is not supported. One path must be local.") + + if not source_is_bucket and not dest_is_bucket: + raise ValueError("One of source or dest must be a bucket path (hf://buckets/...).") + + if ignore_times and ignore_sizes: + raise ValueError("Cannot specify both ignore_times and ignore_sizes.") + + if existing and ignore_existing: + raise ValueError("Cannot specify both existing and ignore_existing.") + + if dry_run and plan: + raise ValueError("Cannot specify both dry_run and plan.") + + # Validate local path + if source_is_bucket: + if os.path.exists(dest) and not os.path.isdir(dest): + raise ValueError(f"Destination must be a directory: {dest}") + else: + if not os.path.isdir(source): + raise ValueError(f"Source must be an existing directory: {source}") + + # Build filter matcher + filter_rules = None + if filter_from: + filter_rules = _parse_filter_file(filter_from) + + filter_matcher = FilterMatcher( + include_patterns=include, + exclude_patterns=exclude, + filter_rules=filter_rules, + ) + + # Compute sync plan + status = StatusLine(enabled=not quiet and not dry_run) + sync_plan = _compute_sync_plan( + source=source, + dest=dest, + api=api, + delete=delete, + ignore_times=ignore_times, + ignore_sizes=ignore_sizes, + existing=existing, + ignore_existing=ignore_existing, + filter_matcher=filter_matcher, + status=status, + ) + + if dry_run: + _write_plan(sync_plan, sys.stdout) + return sync_plan + + if plan: + _save_plan(sync_plan, plan) + if not quiet: + _print_plan_summary(sync_plan) + print(f"Plan saved to: {plan}") + return sync_plan + + # Execute plan + if not quiet: + _print_plan_summary(sync_plan) + + summary = sync_plan.summary() + if summary["uploads"] == 0 and summary["downloads"] == 0 and summary["deletes"] == 0: + if not quiet: + print("Nothing to sync.") + return sync_plan + + if not quiet: + print("Syncing...") + + if quiet: + disable_progress_bars() + try: + _execute_plan(sync_plan, api, verbose=verbose, status=status) + finally: + if quiet: + enable_progress_bars() + + if not quiet: + print("Sync completed.") + + return sync_plan diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_commit_api.py b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_commit_api.py new file mode 100644 index 0000000000000000000000000000000000000000..883d22549b268c524c0e59b75a103f0ea87abf73 --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_commit_api.py @@ -0,0 +1,976 @@ +""" +Type definitions and utilities for the `create_commit` API +""" + +import base64 +import io +import os +import warnings +from collections import defaultdict +from collections.abc import Iterable, Iterator +from contextlib import contextmanager +from dataclasses import dataclass, field +from itertools import groupby +from pathlib import Path, PurePosixPath +from typing import TYPE_CHECKING, Any, BinaryIO, Literal, Union + +from tqdm.contrib.concurrent import thread_map + +from . import constants +from .errors import EntryNotFoundError, HfHubHTTPError, XetAuthorizationError, XetRefreshTokenError +from .file_download import hf_hub_url +from .lfs import UploadInfo, lfs_upload, post_lfs_batch_info +from .utils import ( + FORBIDDEN_FOLDERS, + XetTokenType, + are_progress_bars_disabled, + chunk_iterable, + fetch_xet_connection_info_from_repo_info, + get_session, + hf_raise_for_status, + http_backoff, + logging, + sha, + tqdm_stream_file, + validate_hf_hub_args, +) +from .utils import tqdm as hf_tqdm +from .utils._runtime import is_xet_available + + +if TYPE_CHECKING: + from .hf_api import RepoFile + + +logger = logging.get_logger(__name__) + + +UploadMode = Literal["lfs", "regular"] + +# Max is 1,000 per request on the Hub for HfApi.get_paths_info +# Otherwise we get: +# HfHubHTTPError: 413 Client Error: Payload Too Large for url: https://huggingface.co/api/datasets/xxx (Request ID: xxx)\n\ntoo many parameters +# See https://github.com/huggingface/huggingface_hub/issues/1503 +FETCH_LFS_BATCH_SIZE = 500 + +UPLOAD_BATCH_MAX_NUM_FILES = 256 + + +@dataclass +class CommitOperationDelete: + """ + Data structure holding necessary info to delete a file or a folder from a repository + on the Hub. + + Args: + path_in_repo (`str`): + Relative filepath in the repo, for example: `"checkpoints/1fec34a/weights.bin"` + for a file or `"checkpoints/1fec34a/"` for a folder. + is_folder (`bool` or `Literal["auto"]`, *optional*) + Whether the Delete Operation applies to a folder or not. If "auto", the path + type (file or folder) is guessed automatically by looking if path ends with + a "/" (folder) or not (file). To explicitly set the path type, you can set + `is_folder=True` or `is_folder=False`. + """ + + path_in_repo: str + is_folder: bool | Literal["auto"] = "auto" + + def __post_init__(self): + self.path_in_repo = _validate_path_in_repo(self.path_in_repo) + + if self.is_folder == "auto": + self.is_folder = self.path_in_repo.endswith("/") + if not isinstance(self.is_folder, bool): + raise ValueError( + f"Wrong value for `is_folder`. Must be one of [`True`, `False`, `'auto'`]. Got '{self.is_folder}'." + ) + + +@dataclass +class CommitOperationCopy: + """ + Data structure holding necessary info to copy a file in a repository on the Hub. + + Limitations: + - Only LFS files can be copied. To copy a regular file, you need to download it locally and re-upload it + - Cross-repository copies are not supported. + + Note: you can combine a [`CommitOperationCopy`] and a [`CommitOperationDelete`] to rename an LFS file on the Hub. + + Args: + src_path_in_repo (`str`): + Relative filepath in the repo of the file to be copied, e.g. `"checkpoints/1fec34a/weights.bin"`. + path_in_repo (`str`): + Relative filepath in the repo where to copy the file, e.g. `"checkpoints/1fec34a/weights_copy.bin"`. + src_revision (`str`, *optional*): + The git revision of the file to be copied. Can be any valid git revision. + Default to the target commit revision. + """ + + src_path_in_repo: str + path_in_repo: str + src_revision: str | None = None + # set to the OID of the file to be copied if it has already been uploaded + # useful to determine if a commit will be empty or not. + _src_oid: str | None = None + # set to the OID of the file to copy to if it has already been uploaded + # useful to determine if a commit will be empty or not. + _dest_oid: str | None = None + + def __post_init__(self): + self.src_path_in_repo = _validate_path_in_repo(self.src_path_in_repo) + self.path_in_repo = _validate_path_in_repo(self.path_in_repo) + + +@dataclass +class CommitOperationAdd: + """ + Data structure holding necessary info to upload a file to a repository on the Hub. + + Args: + path_in_repo (`str`): + Relative filepath in the repo, for example: `"checkpoints/1fec34a/weights.bin"` + path_or_fileobj (`str`, `Path`, `bytes`, or `BinaryIO`): + Either: + - a path to a local file (as `str` or `pathlib.Path`) to upload + - a buffer of bytes (`bytes`) holding the content of the file to upload + - a "file object" (subclass of `io.BufferedIOBase`), typically obtained + with `open(path, "rb")`. It must support `seek()` and `tell()` methods. + + Raises: + [`ValueError`](https://docs.python.org/3/library/exceptions.html#ValueError) + If `path_or_fileobj` is not one of `str`, `Path`, `bytes` or `io.BufferedIOBase`. + [`ValueError`](https://docs.python.org/3/library/exceptions.html#ValueError) + If `path_or_fileobj` is a `str` or `Path` but not a path to an existing file. + [`ValueError`](https://docs.python.org/3/library/exceptions.html#ValueError) + If `path_or_fileobj` is a `io.BufferedIOBase` but it doesn't support both + `seek()` and `tell()`. + """ + + path_in_repo: str + path_or_fileobj: str | Path | bytes | BinaryIO + upload_info: UploadInfo = field(init=False, repr=False) + + # Internal attributes + + # set to "lfs" or "regular" once known + _upload_mode: UploadMode | None = field(init=False, repr=False, default=None) + + # set to True if .gitignore rules prevent the file from being uploaded as LFS + # (server-side check) + _should_ignore: bool | None = field(init=False, repr=False, default=None) + + # set to the remote OID of the file if it has already been uploaded + # useful to determine if a commit will be empty or not + _remote_oid: str | None = field(init=False, repr=False, default=None) + + # set to True once the file has been uploaded as LFS + _is_uploaded: bool = field(init=False, repr=False, default=False) + + # set to True once the file has been committed + _is_committed: bool = field(init=False, repr=False, default=False) + + def __post_init__(self) -> None: + """Validates `path_or_fileobj` and compute `upload_info`.""" + self.path_in_repo = _validate_path_in_repo(self.path_in_repo) + + # Validate `path_or_fileobj` value + if isinstance(self.path_or_fileobj, Path): + self.path_or_fileobj = str(self.path_or_fileobj) + if isinstance(self.path_or_fileobj, str): + path_or_fileobj = os.path.normpath(os.path.expanduser(self.path_or_fileobj)) + if not os.path.isfile(path_or_fileobj): + raise ValueError(f"Provided path: '{path_or_fileobj}' is not a file on the local file system") + elif not isinstance(self.path_or_fileobj, (io.BufferedIOBase, bytes)): + # ^^ Inspired from: https://stackoverflow.com/questions/44584829/how-to-determine-if-file-is-opened-in-binary-or-text-mode + raise ValueError( + "path_or_fileobj must be either an instance of str, bytes or" + " io.BufferedIOBase. If you passed a file-like object, make sure it is" + " in binary mode." + ) + if isinstance(self.path_or_fileobj, io.BufferedIOBase): + try: + self.path_or_fileobj.tell() + self.path_or_fileobj.seek(0, os.SEEK_CUR) + except (OSError, AttributeError) as exc: + raise ValueError( + "path_or_fileobj is a file-like object but does not implement seek() and tell()" + ) from exc + + # Compute "upload_info" attribute + if isinstance(self.path_or_fileobj, str): + self.upload_info = UploadInfo.from_path(self.path_or_fileobj) + elif isinstance(self.path_or_fileobj, bytes): + self.upload_info = UploadInfo.from_bytes(self.path_or_fileobj) + else: + self.upload_info = UploadInfo.from_fileobj(self.path_or_fileobj) + + @contextmanager + def as_file(self, with_tqdm: bool = False) -> Iterator[BinaryIO]: + """ + A context manager that yields a file-like object allowing to read the underlying + data behind `path_or_fileobj`. + + Args: + with_tqdm (`bool`, *optional*, defaults to `False`): + If True, iterating over the file object will display a progress bar. Only + works if the file-like object is a path to a file. Pure bytes and buffers + are not supported. + + Example: + + ```python + >>> operation = CommitOperationAdd( + ... path_in_repo="remote/dir/weights.h5", + ... path_or_fileobj="./local/weights.h5", + ... ) + CommitOperationAdd(path_in_repo='remote/dir/weights.h5', path_or_fileobj='./local/weights.h5') + + >>> with operation.as_file() as file: + ... content = file.read() + + >>> with operation.as_file(with_tqdm=True) as file: + ... while True: + ... data = file.read(1024) + ... if not data: + ... break + config.json: 100%|█████████████████████████| 8.19k/8.19k [00:02<00:00, 3.72kB/s] + + >>> with operation.as_file(with_tqdm=True) as file: + ... httpx.put(..., data=file) + config.json: 100%|█████████████████████████| 8.19k/8.19k [00:02<00:00, 3.72kB/s] + ``` + """ + if isinstance(self.path_or_fileobj, str) or isinstance(self.path_or_fileobj, Path): + if with_tqdm: + with tqdm_stream_file(self.path_or_fileobj) as file: + yield file + else: + with open(self.path_or_fileobj, "rb") as file: + yield file + elif isinstance(self.path_or_fileobj, bytes): + yield io.BytesIO(self.path_or_fileobj) + elif isinstance(self.path_or_fileobj, io.BufferedIOBase): + prev_pos = self.path_or_fileobj.tell() + yield self.path_or_fileobj + self.path_or_fileobj.seek(prev_pos, io.SEEK_SET) + + def b64content(self) -> bytes: + """ + The base64-encoded content of `path_or_fileobj` + + Returns: `bytes` + """ + with self.as_file() as file: + return base64.b64encode(file.read()) + + @property + def _local_oid(self) -> str | None: + """Return the OID of the local file. + + This OID is then compared to `self._remote_oid` to check if the file has changed compared to the remote one. + If the file did not change, we won't upload it again to prevent empty commits. + + For LFS files, the OID corresponds to the SHA256 of the file content (used a LFS ref). + For regular files, the OID corresponds to the SHA1 of the file content. + Note: this is slightly different to git OID computation since the oid of an LFS file is usually the git-SHA1 of the + pointer file content (not the actual file content). However, using the SHA256 is enough to detect changes + and more convenient client-side. + """ + if self._upload_mode is None: + return None + elif self._upload_mode == "lfs": + return self.upload_info.sha256.hex() + else: + # Regular file => compute sha1 + # => no need to read by chunk since the file is guaranteed to be <=5MB. + with self.as_file() as file: + return sha.git_hash(file.read()) + + +def _validate_path_in_repo(path_in_repo: str) -> str: + # Validate `path_in_repo` value to prevent a server-side issue + if path_in_repo.startswith("/"): + path_in_repo = path_in_repo[1:] + if path_in_repo == "." or path_in_repo == ".." or path_in_repo.startswith("../"): + raise ValueError(f"Invalid `path_in_repo` in CommitOperation: '{path_in_repo}'") + if path_in_repo.startswith("./"): + path_in_repo = path_in_repo[2:] + for forbidden in FORBIDDEN_FOLDERS: + if any(part == forbidden for part in path_in_repo.split("/")): + raise ValueError( + f"Invalid `path_in_repo` in CommitOperation: cannot update files under a '{forbidden}/' folder (path:" + f" '{path_in_repo}')." + ) + return path_in_repo + + +CommitOperation = Union[CommitOperationAdd, CommitOperationCopy, CommitOperationDelete] + + +def _warn_on_overwriting_operations(operations: list[CommitOperation]) -> None: + """ + Warn user when a list of operations is expected to overwrite itself in a single + commit. + + Rules: + - If a filepath is updated by multiple `CommitOperationAdd` operations, a warning + message is triggered. + - If a filepath is updated at least once by a `CommitOperationAdd` and then deleted + by a `CommitOperationDelete`, a warning is triggered. + - If a `CommitOperationDelete` deletes a filepath that is then updated by a + `CommitOperationAdd`, no warning is triggered. This is usually useless (no need to + delete before upload) but can happen if a user deletes an entire folder and then + add new files to it. + """ + nb_additions_per_path: dict[str, int] = defaultdict(int) + for operation in operations: + path_in_repo = operation.path_in_repo + if isinstance(operation, CommitOperationAdd): + if nb_additions_per_path[path_in_repo] > 0: + warnings.warn( + "About to update multiple times the same file in the same commit:" + f" '{path_in_repo}'. This can cause undesired inconsistencies in" + " your repo." + ) + nb_additions_per_path[path_in_repo] += 1 + for parent in PurePosixPath(path_in_repo).parents: + # Also keep track of number of updated files per folder + # => warns if deleting a folder overwrite some contained files + nb_additions_per_path[str(parent)] += 1 + if isinstance(operation, CommitOperationDelete): + if nb_additions_per_path[str(PurePosixPath(path_in_repo))] > 0: + if operation.is_folder: + warnings.warn( + "About to delete a folder containing files that have just been" + f" updated within the same commit: '{path_in_repo}'. This can" + " cause undesired inconsistencies in your repo." + ) + else: + warnings.warn( + "About to delete a file that have just been updated within the" + f" same commit: '{path_in_repo}'. This can cause undesired" + " inconsistencies in your repo." + ) + + +@validate_hf_hub_args +def _upload_files( + *, + additions: list[CommitOperationAdd], + repo_type: str, + repo_id: str, + headers: dict[str, str], + endpoint: str | None = None, + num_threads: int = 5, + revision: str | None = None, + create_pr: bool | None = None, +): + """ + Negotiates per-file transfer (LFS vs Xet) and uploads in batches. + """ + xet_additions: list[CommitOperationAdd] = [] + lfs_actions: list[dict[str, Any]] = [] + lfs_oid2addop: dict[str, CommitOperationAdd] = {} + + for chunk in chunk_iterable(additions, chunk_size=UPLOAD_BATCH_MAX_NUM_FILES): + chunk_list = [op for op in chunk] + + transfers: list[str] = ["basic", "multipart"] + has_buffered_io_data = any(isinstance(op.path_or_fileobj, io.BufferedIOBase) for op in chunk_list) + if is_xet_available(): + if not has_buffered_io_data: + transfers.append("xet") + else: + logger.warning( + "Uploading files as a binary IO buffer is not supported by Xet Storage. " + "Falling back to HTTP upload." + ) + + actions_chunk, errors_chunk, chosen_transfer = post_lfs_batch_info( + upload_infos=[op.upload_info for op in chunk_list], + repo_id=repo_id, + repo_type=repo_type, + revision=revision, + endpoint=endpoint, + headers=headers, + token=None, # already passed in 'headers' + transfers=transfers, + ) + if errors_chunk: + message = "\n".join( + [ + f"Encountered error for file with OID {err.get('oid')}: `{err.get('error', {}).get('message')}" + for err in errors_chunk + ] + ) + raise ValueError(f"LFS batch API returned errors:\n{message}") + + # If server returns a transfer we didn't offer (e.g "xet" while uploading from BytesIO), + # fall back to LFS for this chunk. + if chosen_transfer == "xet" and ("xet" in transfers): + xet_additions.extend(chunk_list) + else: + lfs_actions.extend(actions_chunk) + for op in chunk_list: + lfs_oid2addop[op.upload_info.sha256.hex()] = op + + if len(lfs_actions) > 0: + _upload_lfs_files( + actions=lfs_actions, + oid2addop=lfs_oid2addop, + headers=headers, + endpoint=endpoint, + num_threads=num_threads, + ) + + if len(xet_additions) > 0: + _upload_xet_files( + additions=xet_additions, + repo_type=repo_type, + repo_id=repo_id, + headers=headers, + endpoint=endpoint, + revision=revision, + create_pr=create_pr, + ) + + +@validate_hf_hub_args +def _upload_lfs_files( + *, + actions: list[dict[str, Any]], + oid2addop: dict[str, CommitOperationAdd], + headers: dict[str, str], + endpoint: str | None = None, + num_threads: int = 5, +): + """ + Uploads the content of `additions` to the Hub using the large file storage protocol. + + Relevant external documentation: + - LFS Batch API: https://github.com/git-lfs/git-lfs/blob/main/docs/api/batch.md + + Args: + actions (`list[dict[str, Any]]`): + LFS batch actions returned by the server. + oid2addop (`dict[str, CommitOperationAdd]`): + A dictionary mapping the OID of the file to the corresponding `CommitOperationAdd` object. + headers (`dict[str, str]`): + Headers to use for the request, including authorization headers and user agent. + endpoint (`str`, *optional*): + The endpoint to use for the request. Defaults to `constants.ENDPOINT`. + num_threads (`int`, *optional*): + The number of concurrent threads to use when uploading. Defaults to 5. + + Raises: + [`EnvironmentError`](https://docs.python.org/3/library/exceptions.html#EnvironmentError) + If an upload failed for any reason + [`ValueError`](https://docs.python.org/3/library/exceptions.html#ValueError) + Type of the repo to upload to: `"model"`, `"dataset"` or `"space"`. + repo_id (`str`): + A namespace (user or an organization) and a repo name separated + by a `/`. + headers (`dict[str, str]`): + Headers to use for the request, including authorization headers and user agent. + num_threads (`int`, *optional*): + The number of concurrent threads to use when uploading. Defaults to 5. + revision (`str`, *optional*): + The git revision to upload to. + + Raises: + [`EnvironmentError`](https://docs.python.org/3/library/exceptions.html#EnvironmentError) + If an upload failed for any reason + [`ValueError`](https://docs.python.org/3/library/exceptions.html#ValueError) + If the server returns malformed responses + [`HfHubHTTPError`] + If the LFS batch endpoint returned an HTTP error. + """ + # Filter out files already present upstream + filtered_actions = [] + for action in actions: + if action.get("actions") is None: + logger.debug( + f"Content of file {oid2addop[action['oid']].path_in_repo} is already present upstream - skipping upload." + ) + else: + filtered_actions.append(action) + + # Upload according to server-provided actions + def _wrapped_lfs_upload(batch_action) -> None: + try: + operation = oid2addop[batch_action["oid"]] + lfs_upload(operation=operation, lfs_batch_action=batch_action, headers=headers, endpoint=endpoint) + except Exception as exc: + raise RuntimeError(f"Error while uploading '{operation.path_in_repo}' to the Hub.") from exc + + if len(filtered_actions) == 1: + logger.debug("Uploading 1 LFS file to the Hub") + _wrapped_lfs_upload(filtered_actions[0]) + else: + logger.debug( + f"Uploading {len(filtered_actions)} LFS files to the Hub using up to {num_threads} threads concurrently" + ) + thread_map( + _wrapped_lfs_upload, + filtered_actions, + desc=f"Upload {len(filtered_actions)} LFS files", + max_workers=num_threads, + tqdm_class=hf_tqdm, + ) + + +@validate_hf_hub_args +def _upload_xet_files( + *, + additions: list[CommitOperationAdd], + repo_type: str, + repo_id: str, + headers: dict[str, str], + endpoint: str | None = None, + revision: str | None = None, + create_pr: bool | None = None, +): + """ + Uploads the content of `additions` to the Hub using the xet storage protocol. + This chunks the files and deduplicates the chunks before uploading them to xetcas storage. + + Args: + additions (`` of `CommitOperationAdd`): + The files to be uploaded. + repo_type (`str`): + Type of the repo to upload to: `"model"`, `"dataset"` or `"space"`. + repo_id (`str`): + A namespace (user or an organization) and a repo name separated + by a `/`. + headers (`dict[str, str]`): + Headers to use for the request, including authorization headers and user agent. + endpoint: (`str`, *optional*): + The endpoint to use for the xetcas service. Defaults to `constants.ENDPOINT`. + revision (`str`, *optional*): + The git revision to upload to. + create_pr (`bool`, *optional*): + Whether or not to create a Pull Request with that commit. + + Raises: + [`EnvironmentError`](https://docs.python.org/3/library/exceptions.html#EnvironmentError) + If an upload failed for any reason. + [`ValueError`](https://docs.python.org/3/library/exceptions.html#ValueError) + If the server returns malformed responses or if the user is unauthorized to upload to xet storage. + [`HfHubHTTPError`] + If the LFS batch endpoint returned an HTTP error. + + **How it works:** + The file download system uses Xet storage, which is a content-addressable storage system that breaks files into chunks + for efficient storage and transfer. + + `hf_xet.upload_files` manages uploading files by: + - Taking a list of file paths to upload + - Breaking files into smaller chunks for efficient storage + - Avoiding duplicate storage by recognizing identical chunks across files + - Connecting to a storage server (CAS server) that manages these chunks + + The upload process works like this: + 1. Create a local folder at ~/.cache/huggingface/xet/chunk-cache to store file chunks for reuse. + 2. Process files in parallel (up to 8 files at once): + 2.1. Read the file content. + 2.2. Split the file content into smaller chunks based on content patterns: each chunk gets a unique ID based on what's in it. + 2.3. For each chunk: + - Check if it already exists in storage. + - Skip uploading chunks that already exist. + 2.4. Group chunks into larger blocks for efficient transfer. + 2.5. Upload these blocks to the storage server. + 2.6. Create and upload information about how the file is structured. + 3. Return reference files that contain information about the uploaded files, which can be used later to download them. + """ + if len(additions) == 0: + return + + # at this point, we know that hf_xet is installed + from hf_xet import upload_bytes, upload_files + + from .utils._xet_progress_reporting import XetProgressReporter + + try: + xet_connection_info = fetch_xet_connection_info_from_repo_info( + token_type=XetTokenType.WRITE, + repo_id=repo_id, + repo_type=repo_type, + revision=revision, + headers=headers, + endpoint=endpoint, + params={"create_pr": "1"} if create_pr else None, + ) + except HfHubHTTPError as e: + if e.response.status_code == 401: + raise XetAuthorizationError( + f"You are unauthorized to upload to xet storage for {repo_type}/{repo_id}. " + f"Please check that you have configured your access token with write access to the repo." + ) from e + raise + + xet_endpoint = xet_connection_info.endpoint + access_token_info = (xet_connection_info.access_token, xet_connection_info.expiration_unix_epoch) + + def token_refresher() -> tuple[str, int]: + new_xet_connection = fetch_xet_connection_info_from_repo_info( + token_type=XetTokenType.WRITE, + repo_id=repo_id, + repo_type=repo_type, + revision=revision, + headers=headers, + endpoint=endpoint, + params={"create_pr": "1"} if create_pr else None, + ) + if new_xet_connection is None: + raise XetRefreshTokenError("Failed to refresh xet token") + return new_xet_connection.access_token, new_xet_connection.expiration_unix_epoch + + if not are_progress_bars_disabled(): + progress = XetProgressReporter() + progress_callback = progress.update_progress + else: + progress, progress_callback = None, None + + try: + all_bytes_ops = [op for op in additions if isinstance(op.path_or_fileobj, bytes)] + all_paths_ops = [op for op in additions if isinstance(op.path_or_fileobj, (str, Path))] + + xet_headers = headers.copy() + xet_headers.pop("authorization", None) + + if len(all_paths_ops) > 0: + all_paths = [str(op.path_or_fileobj) for op in all_paths_ops] + all_sha256s = [op.upload_info.sha256.hex() for op in all_paths_ops] + upload_files( + all_paths, + xet_endpoint, + access_token_info, + token_refresher, + progress_callback, + repo_type, + request_headers=xet_headers, + sha256s=all_sha256s, + ) + + if len(all_bytes_ops) > 0: + all_bytes = [op.path_or_fileobj for op in all_bytes_ops] + all_sha256s = [op.upload_info.sha256.hex() for op in all_bytes_ops] + upload_bytes( + all_bytes, + xet_endpoint, + access_token_info, + token_refresher, + progress_callback, + repo_type, + request_headers=xet_headers, + sha256s=all_sha256s, + ) + + finally: + if progress is not None: + progress.close(False) + + return + + +def _validate_preupload_info(preupload_info: dict): + files = preupload_info.get("files") + if not isinstance(files, list): + raise ValueError("preupload_info is improperly formatted") + for file_info in files: + if not ( + isinstance(file_info, dict) + and isinstance(file_info.get("path"), str) + and isinstance(file_info.get("uploadMode"), str) + and (file_info["uploadMode"] in ("lfs", "regular")) + ): + raise ValueError("preupload_info is improperly formatted:") + return preupload_info + + +@validate_hf_hub_args +def _fetch_upload_modes( + additions: Iterable[CommitOperationAdd], + repo_type: str, + repo_id: str, + headers: dict[str, str], + revision: str, + endpoint: str | None = None, + create_pr: bool = False, + gitignore_content: str | None = None, +) -> None: + """ + Requests the Hub "preupload" endpoint to determine whether each input file should be uploaded as a regular git blob, + as a git LFS blob, or as a XET file. Input `additions` are mutated in-place with the upload mode. + + Args: + additions (`Iterable` of :class:`CommitOperationAdd`): + Iterable of :class:`CommitOperationAdd` describing the files to + upload to the Hub. + repo_type (`str`): + Type of the repo to upload to: `"model"`, `"dataset"` or `"space"`. + repo_id (`str`): + A namespace (user or an organization) and a repo name separated + by a `/`. + headers (`dict[str, str]`): + Headers to use for the request, including authorization headers and user agent. + revision (`str`): + The git revision to upload the files to. Can be any valid git revision. + gitignore_content (`str`, *optional*): + The content of the `.gitignore` file to know which files should be ignored. The order of priority + is to first check if `gitignore_content` is passed, then check if the `.gitignore` file is present + in the list of files to commit and finally default to the `.gitignore` file already hosted on the Hub + (if any). + Raises: + [`~utils.HfHubHTTPError`] + If the Hub API returned an error. + [`ValueError`](https://docs.python.org/3/library/exceptions.html#ValueError) + If the Hub API response is improperly formatted. + """ + endpoint = endpoint if endpoint is not None else constants.ENDPOINT + + # Fetch upload mode (LFS or regular) chunk by chunk. + upload_modes: dict[str, UploadMode] = {} + should_ignore_info: dict[str, bool] = {} + oid_info: dict[str, str | None] = {} + + for chunk in chunk_iterable(additions, 256): + payload: dict = { + "files": [ + { + "path": op.path_in_repo, + "sample": base64.b64encode(op.upload_info.sample).decode("ascii"), + "size": op.upload_info.size, + } + for op in chunk + ] + } + if gitignore_content is not None: + payload["gitIgnore"] = gitignore_content + + resp = http_backoff( + "POST", + f"{endpoint}/api/{repo_type}s/{repo_id}/preupload/{revision}", + json=payload, + headers=headers, + params={"create_pr": "1"} if create_pr else None, + ) + hf_raise_for_status(resp) + preupload_info = _validate_preupload_info(resp.json()) + upload_modes.update(**{file["path"]: file["uploadMode"] for file in preupload_info["files"]}) + should_ignore_info.update(**{file["path"]: file["shouldIgnore"] for file in preupload_info["files"]}) + oid_info.update(**{file["path"]: file.get("oid") for file in preupload_info["files"]}) + + # Set upload mode for each addition operation + for addition in additions: + addition._upload_mode = upload_modes[addition.path_in_repo] + addition._should_ignore = should_ignore_info[addition.path_in_repo] + addition._remote_oid = oid_info[addition.path_in_repo] + + # Empty files cannot be uploaded as LFS (S3 would fail with a 501 Not Implemented) + # => empty files are uploaded as "regular" to still allow users to commit them. + for addition in additions: + if addition.upload_info.size == 0: + addition._upload_mode = "regular" + + +@validate_hf_hub_args +def _fetch_files_to_copy( + copies: Iterable[CommitOperationCopy], + repo_type: str, + repo_id: str, + headers: dict[str, str], + revision: str, + endpoint: str | None = None, +) -> dict[tuple[str, str | None], Union["RepoFile", bytes]]: + """ + Fetch information about the files to copy. + + For LFS files, we only need their metadata (file size and sha256) while for regular files + we need to download the raw content from the Hub. + + Args: + copies (`Iterable` of :class:`CommitOperationCopy`): + Iterable of :class:`CommitOperationCopy` describing the files to + copy on the Hub. + repo_type (`str`): + Type of the repo to upload to: `"model"`, `"dataset"` or `"space"`. + repo_id (`str`): + A namespace (user or an organization) and a repo name separated + by a `/`. + headers (`dict[str, str]`): + Headers to use for the request, including authorization headers and user agent. + revision (`str`): + The git revision to upload the files to. Can be any valid git revision. + + Returns: `dict[tuple[str, Optional[str]], Union[RepoFile, bytes]]]` + Key is the file path and revision of the file to copy. + Value is the raw content as bytes (for regular files) or the file information as a RepoFile (for LFS files). + + Raises: + [`~utils.HfHubHTTPError`] + If the Hub API returned an error. + [`ValueError`](https://docs.python.org/3/library/exceptions.html#ValueError) + If the Hub API response is improperly formatted. + """ + from .hf_api import HfApi, RepoFolder + + hf_api = HfApi(endpoint=endpoint, headers=headers) + files_to_copy: dict[tuple[str, str | None], Union["RepoFile", bytes]] = {} + # Store (path, revision) -> oid mapping + oid_info: dict[tuple[str, str | None], str | None] = {} + # 1. Fetch OIDs for destination paths in batches. + dest_paths = [op.path_in_repo for op in copies] + for offset in range(0, len(dest_paths), FETCH_LFS_BATCH_SIZE): + dest_repo_files = hf_api.get_paths_info( + repo_id=repo_id, + paths=dest_paths[offset : offset + FETCH_LFS_BATCH_SIZE], + revision=revision, + repo_type=repo_type, + ) + for file in dest_repo_files: + if not isinstance(file, RepoFolder): + oid_info[(file.path, revision)] = file.blob_id + + # 2. Group by source revision and fetch source file info in batches. + for src_revision, operations in groupby(copies, key=lambda op: op.src_revision): + operations = list(operations) # type: ignore + src_paths = [op.src_path_in_repo for op in operations] + for offset in range(0, len(src_paths), FETCH_LFS_BATCH_SIZE): + src_repo_files = hf_api.get_paths_info( + repo_id=repo_id, + paths=src_paths[offset : offset + FETCH_LFS_BATCH_SIZE], + revision=src_revision or revision, + repo_type=repo_type, + ) + + for src_repo_file in src_repo_files: + if isinstance(src_repo_file, RepoFolder): + raise NotImplementedError("Copying a folder is not implemented.") + oid_info[(src_repo_file.path, src_revision)] = src_repo_file.blob_id + # If it's an LFS file, store the RepoFile object. Otherwise, download raw bytes. + if src_repo_file.lfs: + files_to_copy[(src_repo_file.path, src_revision)] = src_repo_file + else: + # TODO: (optimization) download regular files to copy concurrently + url = hf_hub_url( + endpoint=endpoint, + repo_type=repo_type, + repo_id=repo_id, + revision=src_revision or revision, + filename=src_repo_file.path, + ) + response = get_session().get(url, headers=headers) + hf_raise_for_status(response) + files_to_copy[(src_repo_file.path, src_revision)] = response.content + # 3. Ensure all operations found a corresponding file in the Hub + # and track src/dest OIDs for each operation. + for operation in operations: + if (operation.src_path_in_repo, src_revision) not in files_to_copy: + raise EntryNotFoundError( + f"Cannot copy {operation.src_path_in_repo} at revision " + f"{src_revision or revision}: file is missing on repo." + ) + operation._src_oid = oid_info.get((operation.src_path_in_repo, operation.src_revision)) + operation._dest_oid = oid_info.get((operation.path_in_repo, revision)) + return files_to_copy + + +def _prepare_commit_payload( + operations: Iterable[CommitOperation], + files_to_copy: dict[tuple[str, str | None], Union["RepoFile", bytes]], + commit_message: str, + commit_description: str | None = None, + parent_commit: str | None = None, +) -> Iterable[dict[str, Any]]: + """ + Builds the payload to POST to the `/commit` API of the Hub. + + Payload is returned as an iterator so that it can be streamed as a ndjson in the + POST request. + + For more information, see: + - https://github.com/huggingface/huggingface_hub/issues/1085#issuecomment-1265208073 + - http://ndjson.org/ + """ + commit_description = commit_description if commit_description is not None else "" + + # 1. Send a header item with the commit metadata + header_value = {"summary": commit_message, "description": commit_description} + if parent_commit is not None: + header_value["parentCommit"] = parent_commit + yield {"key": "header", "value": header_value} + + nb_ignored_files = 0 + + # 2. Send operations, one per line + for operation in operations: + # Skip ignored files + if isinstance(operation, CommitOperationAdd) and operation._should_ignore: + logger.debug(f"Skipping file '{operation.path_in_repo}' in commit (ignored by gitignore file).") + nb_ignored_files += 1 + continue + + # 2.a. Case adding a regular file + if isinstance(operation, CommitOperationAdd) and operation._upload_mode == "regular": + yield { + "key": "file", + "value": { + "content": operation.b64content().decode(), + "path": operation.path_in_repo, + "encoding": "base64", + }, + } + # 2.b. Case adding an LFS file + elif isinstance(operation, CommitOperationAdd) and operation._upload_mode == "lfs": + yield { + "key": "lfsFile", + "value": { + "path": operation.path_in_repo, + "algo": "sha256", + "oid": operation.upload_info.sha256.hex(), + "size": operation.upload_info.size, + }, + } + # 2.c. Case deleting a file or folder + elif isinstance(operation, CommitOperationDelete): + yield { + "key": "deletedFolder" if operation.is_folder else "deletedFile", + "value": {"path": operation.path_in_repo}, + } + # 2.d. Case copying a file or folder + elif isinstance(operation, CommitOperationCopy): + file_to_copy = files_to_copy[(operation.src_path_in_repo, operation.src_revision)] + if isinstance(file_to_copy, bytes): + yield { + "key": "file", + "value": { + "content": base64.b64encode(file_to_copy).decode(), + "path": operation.path_in_repo, + "encoding": "base64", + }, + } + elif file_to_copy.lfs: + yield { + "key": "lfsFile", + "value": { + "path": operation.path_in_repo, + "algo": "sha256", + "oid": file_to_copy.lfs.sha256, + }, + } + else: + raise ValueError( + "Malformed files_to_copy (should be raw file content as bytes or RepoFile objects with LFS info." + ) + # 2.e. Never expected to happen + else: + raise ValueError( + f"Unknown operation to commit. Operation: {operation}. Upload mode:" + f" {getattr(operation, '_upload_mode', None)}" + ) + + if nb_ignored_files > 0: + logger.info(f"Skipped {nb_ignored_files} file(s) in commit (ignored by gitignore file).") diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_commit_scheduler.py b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_commit_scheduler.py new file mode 100644 index 0000000000000000000000000000000000000000..4aa4b8bf19400f318251838da0245f1aad2f1dbc --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_commit_scheduler.py @@ -0,0 +1,353 @@ +import atexit +import logging +import os +import time +from concurrent.futures import Future +from dataclasses import dataclass +from io import SEEK_END, SEEK_SET, BytesIO +from pathlib import Path +from threading import Lock, Thread +from typing import Optional + +from .hf_api import DEFAULT_IGNORE_PATTERNS, CommitInfo, CommitOperationAdd, HfApi +from .utils import filter_repo_objects + + +logger = logging.getLogger(__name__) + + +@dataclass(frozen=True) +class _FileToUpload: + """Temporary dataclass to store info about files to upload. Not meant to be used directly.""" + + local_path: Path + path_in_repo: str + size_limit: int + last_modified: float + + +class CommitScheduler: + """ + Scheduler to upload a local folder to the Hub at regular intervals (e.g. push to hub every 5 minutes). + + The recommended way to use the scheduler is to use it as a context manager. This ensures that the scheduler is + properly stopped and the last commit is triggered when the script ends. The scheduler can also be stopped manually + with the `stop` method. Checkout the [upload guide](https://huggingface.co/docs/huggingface_hub/guides/upload#scheduled-uploads) + to learn more about how to use it. + + Args: + repo_id (`str`): + The id of the repo to commit to. + folder_path (`str` or `Path`): + Path to the local folder to upload regularly. + every (`int` or `float`, *optional*): + The number of minutes between each commit. Defaults to 5 minutes. + path_in_repo (`str`, *optional*): + Relative path of the directory in the repo, for example: `"checkpoints/"`. Defaults to the root folder + of the repository. + repo_type (`str`, *optional*): + The type of the repo to commit to. Defaults to `model`. + revision (`str`, *optional*): + The revision of the repo to commit to. Defaults to `main`. + private (`bool`, *optional*): + Whether to make the repo private. If `None` (default), the repo will be public unless the organization's default is private. This value is ignored if the repo already exists. + token (`str`, *optional*): + The token to use to commit to the repo. Defaults to the token saved on the machine. + allow_patterns (`list[str]` or `str`, *optional*): + If provided, only files matching at least one pattern are uploaded. + ignore_patterns (`list[str]` or `str`, *optional*): + If provided, files matching any of the patterns are not uploaded. + squash_history (`bool`, *optional*): + Whether to squash the history of the repo after each commit. Defaults to `False`. Squashing commits is + useful to avoid degraded performances on the repo when it grows too large. + hf_api (`HfApi`, *optional*): + The [`HfApi`] client to use to commit to the Hub. Can be set with custom settings (user agent, token,...). + + Example: + ```py + >>> from pathlib import Path + >>> from huggingface_hub import CommitScheduler + + # Scheduler uploads every 10 minutes + >>> csv_path = Path("watched_folder/data.csv") + >>> CommitScheduler(repo_id="test_scheduler", repo_type="dataset", folder_path=csv_path.parent, every=10) + + >>> with csv_path.open("a") as f: + ... f.write("first line") + + # Some time later (...) + >>> with csv_path.open("a") as f: + ... f.write("second line") + ``` + + Example using a context manager: + ```py + >>> from pathlib import Path + >>> from huggingface_hub import CommitScheduler + + >>> with CommitScheduler(repo_id="test_scheduler", repo_type="dataset", folder_path="watched_folder", every=10) as scheduler: + ... csv_path = Path("watched_folder/data.csv") + ... with csv_path.open("a") as f: + ... f.write("first line") + ... (...) + ... with csv_path.open("a") as f: + ... f.write("second line") + + # Scheduler is now stopped and last commit have been triggered + ``` + """ + + def __init__( + self, + *, + repo_id: str, + folder_path: str | Path, + every: int | float = 5, + path_in_repo: str | None = None, + repo_type: str | None = None, + revision: str | None = None, + private: bool | None = None, + token: str | None = None, + allow_patterns: list[str] | str | None = None, + ignore_patterns: list[str] | str | None = None, + squash_history: bool = False, + hf_api: Optional["HfApi"] = None, + ) -> None: + self.api = hf_api or HfApi(token=token) + + # Folder + self.folder_path = Path(folder_path).expanduser().resolve() + self.path_in_repo = path_in_repo or "" + self.allow_patterns = allow_patterns + + if ignore_patterns is None: + ignore_patterns = [] + elif isinstance(ignore_patterns, str): + ignore_patterns = [ignore_patterns] + self.ignore_patterns = ignore_patterns + DEFAULT_IGNORE_PATTERNS + + if self.folder_path.is_file(): + raise ValueError(f"'folder_path' must be a directory, not a file: '{self.folder_path}'.") + self.folder_path.mkdir(parents=True, exist_ok=True) + + # Repository + repo_url = self.api.create_repo(repo_id=repo_id, private=private, repo_type=repo_type, exist_ok=True) + self.repo_id = repo_url.repo_id + self.repo_type = repo_type + self.revision = revision + self.token = token + + # Keep track of already uploaded files + self.last_uploaded: dict[Path, float] = {} # key is local path, value is timestamp + + # Scheduler + if not every > 0: + raise ValueError(f"'every' must be a positive integer, not '{every}'.") + self.lock = Lock() + self.every = every + self.squash_history = squash_history + + logger.info(f"Scheduled job to push '{self.folder_path}' to '{self.repo_id}' every {self.every} minutes.") + self._scheduler_thread = Thread(target=self._run_scheduler, daemon=True) + self._scheduler_thread.start() + atexit.register(self._push_to_hub) + + self.__stopped = False + + def stop(self) -> None: + """Stop the scheduler. + + A stopped scheduler cannot be restarted. Mostly for tests purposes. + """ + self.__stopped = True + + def __enter__(self) -> "CommitScheduler": + return self + + def __exit__(self, exc_type, exc_value, traceback) -> None: + # Upload last changes before exiting + self.trigger().result() + self.stop() + return + + def _run_scheduler(self) -> None: + """Dumb thread waiting between each scheduled push to Hub.""" + while True: + self.last_future = self.trigger() + time.sleep(self.every * 60) + if self.__stopped: + break + + def trigger(self) -> Future: + """Trigger a `push_to_hub` and return a future. + + This method is automatically called every `every` minutes. You can also call it manually to trigger a commit + immediately, without waiting for the next scheduled commit. + """ + return self.api.run_as_future(self._push_to_hub) + + def _push_to_hub(self) -> CommitInfo | None: + if self.__stopped: # If stopped, already scheduled commits are ignored + return None + + logger.info("(Background) scheduled commit triggered.") + try: + value = self.push_to_hub() + if self.squash_history: + logger.info("(Background) squashing repo history.") + self.api.super_squash_history(repo_id=self.repo_id, repo_type=self.repo_type, branch=self.revision) + return value + except Exception as e: + logger.error(f"Error while pushing to Hub: {e}") # Depending on the setup, error might be silenced + raise + + def push_to_hub(self) -> CommitInfo | None: + """ + Push folder to the Hub and return the commit info. + + > [!WARNING] + > This method is not meant to be called directly. It is run in the background by the scheduler, respecting a + > queue mechanism to avoid concurrent commits. Making a direct call to the method might lead to concurrency + > issues. + + The default behavior of `push_to_hub` is to assume an append-only folder. It lists all files in the folder and + uploads only changed files. If no changes are found, the method returns without committing anything. If you want + to change this behavior, you can inherit from [`CommitScheduler`] and override this method. This can be useful + for example to compress data together in a single file before committing. For more details and examples, check + out our [integration guide](https://huggingface.co/docs/huggingface_hub/main/en/guides/upload#scheduled-uploads). + """ + # Check files to upload (with lock) + with self.lock: + logger.debug("Listing files to upload for scheduled commit.") + + # List files from folder (taken from `_prepare_upload_folder_additions`) + relpath_to_abspath = { + path.relative_to(self.folder_path).as_posix(): path + for path in sorted(self.folder_path.glob("**/*")) # sorted to be deterministic + if path.is_file() + } + prefix = f"{self.path_in_repo.strip('/')}/" if self.path_in_repo else "" + + # Filter with pattern + filter out unchanged files + retrieve current file size + files_to_upload: list[_FileToUpload] = [] + for relpath in filter_repo_objects( + relpath_to_abspath.keys(), allow_patterns=self.allow_patterns, ignore_patterns=self.ignore_patterns + ): + local_path = relpath_to_abspath[relpath] + stat = local_path.stat() + if self.last_uploaded.get(local_path) is None or self.last_uploaded[local_path] != stat.st_mtime: + files_to_upload.append( + _FileToUpload( + local_path=local_path, + path_in_repo=prefix + relpath, + size_limit=stat.st_size, + last_modified=stat.st_mtime, + ) + ) + + # Return if nothing to upload + if len(files_to_upload) == 0: + logger.debug("Dropping schedule commit: no changed file to upload.") + return None + + # Convert `_FileToUpload` as `CommitOperationAdd` (=> compute file shas + limit to file size) + logger.debug("Removing unchanged files since previous scheduled commit.") + add_operations = [ + CommitOperationAdd( + # Cap the file to its current size, even if the user append data to it while a scheduled commit is happening + path_or_fileobj=PartialFileIO(file_to_upload.local_path, size_limit=file_to_upload.size_limit), + path_in_repo=file_to_upload.path_in_repo, + ) + for file_to_upload in files_to_upload + ] + + # Upload files (append mode expected - no need for lock) + logger.debug("Uploading files for scheduled commit.") + commit_info = self.api.create_commit( + repo_id=self.repo_id, + repo_type=self.repo_type, + operations=add_operations, + commit_message="Scheduled Commit", + revision=self.revision, + ) + + # Successful commit: keep track of the latest "last_modified" for each file + for file in files_to_upload: + self.last_uploaded[file.local_path] = file.last_modified + return commit_info + + +class PartialFileIO(BytesIO): + """A file-like object that reads only the first part of a file. + + Useful to upload a file to the Hub when the user might still be appending data to it. Only the first part of the + file is uploaded (i.e. the part that was available when the filesystem was first scanned). + + In practice, only used internally by the CommitScheduler to regularly push a folder to the Hub with minimal + disturbance for the user. The object is passed to `CommitOperationAdd`. + + Only supports `read`, `tell` and `seek` methods. + + Args: + file_path (`str` or `Path`): + Path to the file to read. + size_limit (`int`): + The maximum number of bytes to read from the file. If the file is larger than this, only the first part + will be read (and uploaded). + """ + + def __init__(self, file_path: str | Path, size_limit: int) -> None: + self._file_path = Path(file_path) + self._file = self._file_path.open("rb") + self._size_limit = min(size_limit, os.fstat(self._file.fileno()).st_size) + + def __del__(self) -> None: + self._file.close() + return super().__del__() + + def __repr__(self) -> str: + return f"" + + def __len__(self) -> int: + return self._size_limit + + def __getattribute__(self, name: str): + if name.startswith("_") or name in ("read", "tell", "seek", "fileno"): # only 4 public methods supported + return super().__getattribute__(name) + raise NotImplementedError(f"PartialFileIO does not support '{name}'.") + + def fileno(self): + raise AttributeError("PartialFileIO does not have a fileno.") + + def tell(self) -> int: + """Return the current file position.""" + return self._file.tell() + + def seek(self, __offset: int, __whence: int = SEEK_SET) -> int: + """Change the stream position to the given offset. + + Behavior is the same as a regular file, except that the position is capped to the size limit. + """ + if __whence == SEEK_END: + # SEEK_END => set from the truncated end + __offset = len(self) + __offset + __whence = SEEK_SET + + pos = self._file.seek(__offset, __whence) + if pos > self._size_limit: + return self._file.seek(self._size_limit) + return pos + + def read(self, __size: int | None = -1) -> bytes: + """Read at most `__size` bytes from the file. + + Behavior is the same as a regular file, except that it is capped to the size limit. + """ + current = self._file.tell() + if __size is None or __size < 0: + # Read until file limit + truncated_size = self._size_limit - current + else: + # Read until file limit or __size + truncated_size = min(__size, self._size_limit - current) + return self._file.read(truncated_size) diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_dataset_viewer.py b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_dataset_viewer.py new file mode 100644 index 0000000000000000000000000000000000000000..ada15a7f0c3fd2d8d67d4fe9d803598b32896bb2 --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_dataset_viewer.py @@ -0,0 +1,172 @@ +# Copyright 2026 The HuggingFace Team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import json +import os +import shutil +import subprocess +from dataclasses import dataclass +from typing import TYPE_CHECKING, Any, Union + +from . import constants +from .utils import get_token + + +if TYPE_CHECKING: + import duckdb + + +@dataclass(frozen=True) +class DatasetParquetEntry: + """Represents a single parquet file available for a dataset on the Hub.""" + + config: str + split: str + url: str + size: int + + +def execute_raw_sql_query(sql_query: str, *, token: str | bool | None = None) -> list[dict[str, Any]]: + normalized_query = sql_query.strip().rstrip(";").strip() + _raise_on_forbidden_query(normalized_query) + + connection = None + try: + connection = _get_duckdb_connection(token=token) + relation = connection.sql(normalized_query) + if relation is None: + raise ValueError("SQL query must return rows.") + + if isinstance(relation, _DuckDBCliRelation): + # DuckDB binary => run CLI => parse JSON + return relation.execute() + else: + # DuckDB Python API => fetch columns + rows => convert to dicts + columns = tuple(column[0] for column in relation.description) + rows = tuple(tuple(row) for row in relation.fetchall()) + return [dict(zip(columns, row)) for row in rows] + finally: + if connection is not None: + connection.close() + + +def _raise_on_forbidden_query(query: str) -> None: + if len(query) == 0: + raise ValueError("SQL query cannot be empty.") + + # DuckDB CLI meta-commands are dot-prefixed words (e.g. `.shell`, `.output`). + # Let's forbid them for now but allow SQL expressions like `.5` that can legitimately start a line. + for line in query.splitlines(): + stripped = line.lstrip() + if stripped.startswith(".") and stripped[1:2].isalpha(): + raise ValueError("DuckDB CLI meta-commands are not allowed in SQL queries.") + + +def _get_duckdb_connection( + token: str | bool | None, +) -> Union["duckdb.DuckDBPyConnection", "_DuckDBCliConnection"]: + try: + # If DuckDB is installed as a Python package, use it! + import duckdb + except ImportError as error: + # Otherwise, use the DuckDB CLI binary. + duckdb_binary = shutil.which("duckdb") + if duckdb_binary is None: + raise ImportError( + "DuckDB is required for `hf datasets sql`. Install the Python package with `pip install duckdb` or " + "install the DuckDB CLI binary (for example `brew install duckdb`)." + ) from error + return _DuckDBCliConnection(binary_path=duckdb_binary, token=token) + + # Create a new connection (Python API). + connection = duckdb.connect() + try: + for statement in _build_duckdb_secret_statements(token): + connection.execute(statement) + return connection + except Exception: + connection.close() + raise + + +@dataclass +class _DuckDBCliConnection: + """DuckDB connection. + + Mimics the DuckDB Python API, but runs the queries via the DuckDB CLI binary. + """ + + binary_path: str + token: str | bool | None + + def __post_init__(self) -> None: + self._setup_statements = _build_duckdb_secret_statements(self.token) + + def sql(self, query: str) -> "_DuckDBCliRelation": + return _DuckDBCliRelation(binary_path=self.binary_path, setup_statements=self._setup_statements, query=query) + + def close(self) -> None: + pass + + +@dataclass +class _DuckDBCliRelation: + """DuckDB relation. + + Mimics the DuckDB Python API, but runs the queries via the DuckDB CLI binary. + """ + + binary_path: str + setup_statements: list[str] + query: str + + def execute(self) -> list[dict[str, Any]]: + # Build the DuckDB CLI input. + setup = [] + if self.setup_statements: + setup = [ + f".output {os.devnull}", + *(f"{stmt};" for stmt in self.setup_statements), + ".output", + ] + full_query = "\n".join(setup + [self.query + ";"]) + + # Run DuckDB binary + result = subprocess.run( + [self.binary_path, "-json"], + input=full_query, + capture_output=True, + text=True, + check=False, + ) + if result.returncode != 0: + error_message = result.stderr.strip() or result.stdout.strip() or "DuckDB CLI command failed." + raise RuntimeError(error_message) + + # Parse JSON output and return + return json.loads(result.stdout.strip()) + + +def _build_duckdb_secret_statements(token: str | bool | None) -> list[str]: + if token is None or token is True: + token = get_token() + + if not token: + return [] + + escaped_token = token.replace("'", "''") + escaped_endpoint = constants.ENDPOINT.replace("'", "''") + return [ + f"CREATE OR REPLACE SECRET hf_hub_token (TYPE HTTP, BEARER_TOKEN '{escaped_token}', SCOPE '{escaped_endpoint}')", + f"CREATE OR REPLACE SECRET hf_token (TYPE HUGGINGFACE, TOKEN '{escaped_token}')", + ] diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_eval_results.py b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_eval_results.py new file mode 100644 index 0000000000000000000000000000000000000000..77aee2b595e979a0d4e83a71f7bea81a6f2e4d33 --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_eval_results.py @@ -0,0 +1,211 @@ +"""Evaluation results utilities for the `.eval_results/*.yaml` format. + +See https://huggingface.co/docs/hub/eval-results for more details. +Specifications are available at https://github.com/huggingface/hub-docs/blob/main/eval_results.yaml. +""" + +from dataclasses import dataclass +from typing import Any + + +@dataclass +class EvalResultEntry: + """ + Evaluation result entry for the `.eval_results/*.yaml` format. + + Represents evaluation scores stored in model repos that automatically appear on + the model page and the benchmark dataset's leaderboard. + + For the legacy `model-index` format in `README.md`, use [`EvalResult`] instead. + + See https://huggingface.co/docs/hub/eval-results for more details. + + Args: + dataset_id (`str`): + Benchmark dataset ID from the Hub. Example: "cais/hle", "Idavidrein/gpqa". + task_id (`str`): + Task identifier within the benchmark. Example: "gpqa_diamond". + value (`Any`): + The metric value. Example: 20.90. + dataset_revision (`str`, *optional*): + Git SHA of the benchmark dataset. + verify_token (`str`, *optional*): + A signature that can be used to prove that evaluation is provably auditable and reproducible. + date (`str`, *optional*): + When the evaluation was run (ISO-8601 datetime). Defaults to git commit time. + source_url (`str`, *optional*): + Link to the evaluation source (e.g., https://huggingface.co/spaces/SaylorTwift/smollm3-mmlu-pro). Required if `source_name`, `source_user`, or `source_org` is provided. + source_name (`str`, *optional*): + Display name for the source. Example: "Eval Logs". + source_user (`str`, *optional*): + HF user name for attribution. Example: "celinah". + source_org (`str`, *optional*): + HF org name for attribution. Example: "cais". + notes (`str`, *optional*): + Details about the evaluation setup. Example: "tools", "no-tools", "chain-of-thought". + + Example: + ```python + >>> from huggingface_hub import EvalResultEntry + >>> # Minimal example with required fields only + >>> result = EvalResultEntry( + ... dataset_id="Idavidrein/gpqa", + ... task_id="gpqa_diamond", + ... value=0.412, + ... ) + >>> # Full example with all fields + >>> result = EvalResultEntry( + ... dataset_id="cais/hle", + ... task_id="default", + ... value=20.90, + ... dataset_revision="5503434ddd753f426f4b38109466949a1217c2bb", + ... verify_token="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", + ... date="2025-01-15T10:30:00Z", + ... source_url="https://huggingface.co/datasets/cais/hle", + ... source_name="CAIS HLE", + ... source_org="cais", + ... notes="no-tools", + ... ) + + ``` + """ + + dataset_id: str + task_id: str + value: Any + dataset_revision: str | None = None + verify_token: str | None = None + date: str | None = None + source_url: str | None = None + source_name: str | None = None + source_user: str | None = None + source_org: str | None = None + notes: str | None = None + + def __post_init__(self) -> None: + if ( + self.source_name is not None or self.source_user is not None or self.source_org is not None + ) and self.source_url is None: + raise ValueError( + "If `source_name`, `source_user`, or `source_org` is provided, `source_url` must also be provided." + ) + + +def eval_result_entries_to_yaml(entries: list[EvalResultEntry]) -> list[dict[str, Any]]: + """Convert a list of [`EvalResultEntry`] objects to a YAML-serializable list of dicts. + + This produces the format expected in `.eval_results/*.yaml` files. + + Args: + entries (`list[EvalResultEntry]`): + List of evaluation result entries to serialize. + + Returns: + `list[dict[str, Any]]`: A list of dictionaries ready to be dumped to YAML. + + Example: + ```python + >>> from huggingface_hub import EvalResultEntry, eval_result_entries_to_yaml + >>> entries = [ + ... EvalResultEntry(dataset_id="cais/hle", task_id="default", value=20.90), + ... EvalResultEntry(dataset_id="Idavidrein/gpqa", task_id="gpqa_diamond", value=0.412), + ... ] + >>> yaml_data = eval_result_entries_to_yaml(entries) + >>> yaml_data[0] + {'dataset': {'id': 'cais/hle', 'task_id': 'default'}, 'value': 20.9} + + ``` + + To upload eval results to the Hub: + ```python + >>> import yaml + >>> from huggingface_hub import upload_file, EvalResultEntry, eval_result_entries_to_yaml + >>> entries = [ + ... EvalResultEntry(dataset_id="cais/hle", task_id="default", value=20.90), + ... ] + >>> yaml_content = yaml.dump(eval_result_entries_to_yaml(entries)) + >>> upload_file( + ... path_or_fileobj=yaml_content.encode(), + ... path_in_repo=".eval_results/hle.yaml", + ... repo_id="your-username/your-model", + ... ) + + ``` + """ + result = [] + for entry in entries: + # build the dataset object + dataset: dict[str, Any] = {"id": entry.dataset_id, "task_id": entry.task_id} + if entry.dataset_revision is not None: + dataset["revision"] = entry.dataset_revision + + data: dict[str, Any] = {"dataset": dataset, "value": entry.value} + if entry.verify_token is not None: + data["verifyToken"] = entry.verify_token + if entry.date is not None: + data["date"] = entry.date + # build the source object + if entry.source_url is not None: + source: dict[str, Any] = {"url": entry.source_url} + if entry.source_name is not None: + source["name"] = entry.source_name + if entry.source_user is not None: + source["user"] = entry.source_user + if entry.source_org is not None: + source["org"] = entry.source_org + data["source"] = source + if entry.notes is not None: + data["notes"] = entry.notes + + result.append(data) + return result + + +def parse_eval_result_entries(data: list[dict[str, Any]]) -> list[EvalResultEntry]: + """Parse a list of dicts into [`EvalResultEntry`] objects. + + This parses the `.eval_results/*.yaml` format. For the legacy `model-index` format, + use [`model_index_to_eval_results`] instead. + + Args: + data (`list[dict[str, Any]]`): + A list of dictionaries (e.g., parsed from YAML or API response). + + Returns: + `list[EvalResultEntry]`: A list of evaluation result entry objects. + + Example: + ```python + >>> from huggingface_hub import parse_eval_result_entries + >>> data = [ + ... {"dataset": {"id": "cais/hle", "task_id": "default"}, "value": 20.90}, + ... {"dataset": {"id": "Idavidrein/gpqa", "task_id": "gpqa_diamond"}, "value": 0.412}, + ... ] + >>> entries = parse_eval_result_entries(data) + >>> entries[0].dataset_id + 'cais/hle' + >>> entries[0].value + 20.9 + + ``` + """ + entries = [] + for item in data: + entry_data = item.get("data", item) + dataset = entry_data.get("dataset", {}) + source = entry_data.get("source", {}) + entry = EvalResultEntry( + dataset_id=dataset["id"], + value=entry_data["value"], + task_id=dataset["task_id"], + dataset_revision=dataset.get("revision"), + verify_token=entry_data.get("verifyToken"), + date=entry_data.get("date"), + source_url=source.get("url") if source else None, + source_name=source.get("name") if source else None, + source_user=source.get("user") if source else None, + source_org=source.get("org") if source else None, + notes=entry_data.get("notes"), + ) + entries.append(entry) + return entries diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_hot_reload/__init__.py b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_hot_reload/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..ef08599ad40fcb6d55fac1c397597f68b8b52084 --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_hot_reload/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2026 The HuggingFace Team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_hot_reload/client.py b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_hot_reload/client.py new file mode 100644 index 0000000000000000000000000000000000000000..1c3dc30938ce81e32886d5e585bdab8a33fe5218 --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_hot_reload/client.py @@ -0,0 +1,130 @@ +# Copyright 2026 The HuggingFace Team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import json +import time +from collections import deque +from collections.abc import Iterator +from typing import Literal, TypedDict + +import httpx + +from ..utils._headers import build_hf_headers +from ..utils._http import hf_raise_for_status +from .sse_client import SSEClient +from .types import ApiGetReloadEventSourceData, ApiGetReloadRequest + + +HOT_RELOADING_PORT = 7887 +CLIENT_TIMEOUT = 20 + + +class MultiReplicaStreamWarning(TypedDict): + kind: Literal["warning"] + message: str + + +class MultiReplicaStreamEvent(TypedDict): + kind: Literal["event"] + event: ApiGetReloadEventSourceData + + +class MultiReplicaStreamReplicaHash(TypedDict): + kind: Literal["replicaHash"] + hash: str + + +class MultiReplicaStreamFullMatch(TypedDict): + kind: Literal["fullMatch"] + + +class ReloadClient: + def __init__( + self, + *, + host: str, + subdomain: str, + replica_hash: str, + token: str | None, + ): + base_host = host.replace(subdomain, f"{subdomain}--{HOT_RELOADING_PORT}") + self.replica_hash = replica_hash + self.client = httpx.Client( + base_url=f"{base_host}/--replicas/+{replica_hash}", + headers=build_hf_headers(token=token), + timeout=CLIENT_TIMEOUT, + ) + + def get_reload(self, reload_id: str) -> Iterator[ApiGetReloadEventSourceData] | int: + req = ApiGetReloadRequest(reloadId=reload_id) + with self.client.stream("POST", "/get-reload", json=req) as res: + if res.status_code != 200: + return res.status_code + hf_raise_for_status(res) + for event in SSEClient(res.iter_bytes()).events(): + if event.event == "message": + yield json.loads(event.data) + return None + + +def multi_replica_reload_events( + commit_sha: str, + host: str, + subdomain: str, + replica_hashes: list[str], + token: str | None, + max_retries: int = 10, +) -> Iterator[ + MultiReplicaStreamWarning | MultiReplicaStreamEvent | MultiReplicaStreamReplicaHash | MultiReplicaStreamFullMatch +]: + clients = [ + ReloadClient( + host=host, + subdomain=subdomain, + replica_hash=hash, + token=token, + ) + for hash in replica_hashes + ] + + first_client_events: dict[int, ApiGetReloadEventSourceData] = {} + for client_index, client in enumerate(clients): + if len(clients) > 1: + yield {"kind": "replicaHash", "hash": client.replica_hash} + + retries = 0 + while isinstance((events := client.get_reload(commit_sha)), int): + if (retries := retries + 1) > max_retries: + raise Exception("Too many retries reached") + if (status_code := events) not in (200, 204): + raise Exception(f"Unexpected {status_code=} on `ReloadClient.get_reload`") + subject = "reloadId" if status_code == 204 else "replica" + yield {"kind": "warning", "message": f"Retrying on unexpected {subject} not found"} + time.sleep(2) + + full_match = True + replay: deque[ApiGetReloadEventSourceData] = deque() + for event_index, event in enumerate(events): + if client_index == 0: + first_client_events[event_index] = event + elif full_match := full_match and first_client_events.get(event_index) == event: + replay.append(event) + continue + while replay: + yield {"kind": "event", "event": replay.popleft()} + yield {"kind": "event", "event": event} + + if client_index > 0 and full_match: + yield {"kind": "fullMatch"} diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_hot_reload/sse_client.py b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_hot_reload/sse_client.py new file mode 100644 index 0000000000000000000000000000000000000000..2dab959bbd62045adff1d8d51438acd5bd062265 --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_hot_reload/sse_client.py @@ -0,0 +1,144 @@ +""" +Vendored file: Server Side Events (SSE) client for Python. + +Source: +- Author: Maxime Petazzoni +- Repository: https://github.com/mpetazzoni/sseclient +- File: https://github.com/mpetazzoni/sseclient/blob/main/sseclient/__init__.py + +License: +- Apache-2.0 (from upstream project) + +Provides a generator of SSE received through an existing HTTP response. +""" + +import logging + +__author__ = 'Maxime Petazzoni ' +__email__ = 'maxime.petazzoni@bulix.org' +__all__ = ['SSEClient'] + +_FIELD_SEPARATOR = ':' + + +class SSEClient: + """Implementation of a SSE client. + + See http://www.w3.org/TR/2009/WD-eventsource-20091029/ for the + specification. + """ + + def __init__(self, event_source, char_enc='utf-8'): + """Initialize the SSE client over an existing, ready to consume + event source. + + The event source is expected to be a binary stream and have a close() + method. That would usually be something that implements + io.BinaryIOBase, like an httplib or urllib3 HTTPResponse object. + """ + self._logger = logging.getLogger(self.__class__.__module__) + self._logger.debug('Initialized SSE client from event source %s', + event_source) + self._event_source = event_source + self._char_enc = char_enc + + def _read(self): + """Read the incoming event source stream and yield event chunks. + + Unfortunately it is possible for some servers to decide to break an + event into multiple HTTP chunks in the response. It is thus necessary + to correctly stitch together consecutive response chunks and find the + SSE delimiter (empty new line) to yield full, correct event chunks.""" + data = b'' + for chunk in self._event_source: + for line in chunk.splitlines(True): + data += line + if data.endswith((b'\r\r', b'\n\n', b'\r\n\r\n')): + yield data + data = b'' + if data: + yield data + + def events(self): + for chunk in self._read(): + event = Event() + # Split before decoding so splitlines() only uses \r and \n + for line in chunk.splitlines(): + # Decode the line. + line = line.decode(self._char_enc) + + # Lines starting with a separator are comments and are to be + # ignored. + if not line.strip() or line.startswith(_FIELD_SEPARATOR): + continue + + data = line.split(_FIELD_SEPARATOR, 1) + field = data[0] + + # Ignore unknown fields. + if field not in event.__dict__: + self._logger.debug('Saw invalid field %s while parsing ' + 'Server Side Event', field) + continue + + if len(data) > 1: + # From the spec: + # "If value starts with a single U+0020 SPACE character, + # remove it from value." + if data[1].startswith(' '): + value = data[1][1:] + else: + value = data[1] + else: + # If no value is present after the separator, + # assume an empty value. + value = '' + + # The data field may come over multiple lines and their values + # are concatenated with each other. + if field == 'data': + event.__dict__[field] += value + '\n' + else: + event.__dict__[field] = value + + # Events with no data are not dispatched. + if not event.data: + continue + + # If the data field ends with a newline, remove it. + if event.data.endswith('\n'): + event.data = event.data[0:-1] + + # Empty event names default to 'message' + event.event = event.event or 'message' + + # Dispatch the event + self._logger.debug('Dispatching %s...', event) + yield event + + def close(self): + """Manually close the event source stream.""" + self._event_source.close() + + +class Event: + """Representation of an event from the event stream.""" + + def __init__(self, id=None, event='message', data='', retry=None): + self.id = id + self.event = event + self.data = data + self.retry = retry + + def __str__(self): + s = f'{self.event} event' + if self.id: + s += f' #{self.id}' + if self.data: + s += ', {} byte{}'.format(len(self.data), + 's' if len(self.data) else '') + else: + s += ', no data' + if self.retry: + s += f', retry in {self.retry}ms' + return s diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_hot_reload/types.py b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_hot_reload/types.py new file mode 100644 index 0000000000000000000000000000000000000000..c5f892d6287f5b581edca8fdf64c1827e114621b --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_hot_reload/types.py @@ -0,0 +1,121 @@ +# Copyright 2026 The HuggingFace Team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +from typing import Literal, TypedDict + +from typing_extensions import NotRequired + + +class ReloadRegion(TypedDict): + startLine: int + startCol: int + endLine: int + endCol: int + + +class ReloadOperationObject(TypedDict): + kind: Literal["add", "update", "delete"] + region: ReloadRegion + objectType: str + objectName: str + + +class ReloadOperationRun(TypedDict): + kind: Literal["run"] + region: ReloadRegion + codeLines: str + stdout: NotRequired[str] + stderr: NotRequired[str] + + +class ReloadOperationException(TypedDict): + kind: Literal["exception"] + region: ReloadRegion + traceback: str + + +class ReloadOperationError(TypedDict): + kind: Literal["error"] + traceback: str + + +class ReloadOperationUI(TypedDict): + kind: Literal["ui"] + updated: bool + + +class ReloadOperationFile(TypedDict): + kind: Literal["file"] + created: bool + + +class ApiCreateReloadRequest(TypedDict): + filepath: str + contents: str + reloadId: NotRequired[str] + + +class ApiCreateReloadResponseSuccess(TypedDict): + status: Literal["created"] + reloadId: str + + +class ApiCreateReloadResponseError(TypedDict): + status: Literal["alreadyReloading", "fileNotFound"] + + +class ApiCreateReloadResponse(TypedDict): + res: ApiCreateReloadResponseError | ApiCreateReloadResponseSuccess + + +class ApiGetReloadRequest(TypedDict): + reloadId: str + + +class ApiGetReloadEventSourceData(TypedDict): + data: ( + ReloadOperationError + | ReloadOperationException + | ReloadOperationObject + | ReloadOperationRun + | ReloadOperationUI + | ReloadOperationFile + ) + + +class ApiGetStatusRequest(TypedDict): + revision: str + + +class ApiGetStatusResponse(TypedDict): + reloading: bool + uncommited: list[str] + + +class ApiFetchContentsRequest(TypedDict): + filepath: str + + +class ApiFetchContentsResponseError(TypedDict): + status: Literal["fileNotFound"] + + +class ApiFetchContentsResponseSuccess(TypedDict): + status: Literal["ok"] + contents: str + + +class ApiFetchContentsResponse(TypedDict): + res: ApiFetchContentsResponseError | ApiFetchContentsResponseSuccess diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_inference_endpoints.py b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_inference_endpoints.py new file mode 100644 index 0000000000000000000000000000000000000000..5b8381a8e59459a768685d627ff3301bc9b9940e --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_inference_endpoints.py @@ -0,0 +1,418 @@ +import time +from dataclasses import dataclass, field +from datetime import datetime +from enum import Enum +from typing import TYPE_CHECKING, Optional + +from huggingface_hub.errors import InferenceEndpointError, InferenceEndpointTimeoutError + +from .utils import get_session, logging, parse_datetime + + +if TYPE_CHECKING: + from .hf_api import HfApi + from .inference._client import InferenceClient + from .inference._generated._async_client import AsyncInferenceClient + +logger = logging.get_logger(__name__) + + +class InferenceEndpointStatus(str, Enum): + PENDING = "pending" + INITIALIZING = "initializing" + UPDATING = "updating" + UPDATE_FAILED = "updateFailed" + RUNNING = "running" + PAUSED = "paused" + FAILED = "failed" + SCALED_TO_ZERO = "scaledToZero" + + +class InferenceEndpointType(str, Enum): + PUBlIC = "public" + PROTECTED = "protected" + PRIVATE = "private" + + +class InferenceEndpointScalingMetric(str, Enum): + PENDING_REQUESTS = "pendingRequests" + HARDWARE_USAGE = "hardwareUsage" + + +@dataclass +class InferenceEndpoint: + """ + Contains information about a deployed Inference Endpoint. + + Args: + name (`str`): + The unique name of the Inference Endpoint. + namespace (`str`): + The namespace where the Inference Endpoint is located. + repository (`str`): + The name of the model repository deployed on this Inference Endpoint. + status ([`InferenceEndpointStatus`]): + The current status of the Inference Endpoint. + url (`str`, *optional*): + The URL of the Inference Endpoint, if available. Only a deployed Inference Endpoint will have a URL. + framework (`str`): + The machine learning framework used for the model. + revision (`str`): + The specific model revision deployed on the Inference Endpoint. + task (`str`): + The task associated with the deployed model. + created_at (`datetime.datetime`): + The timestamp when the Inference Endpoint was created. + updated_at (`datetime.datetime`): + The timestamp of the last update of the Inference Endpoint. + type ([`InferenceEndpointType`]): + The type of the Inference Endpoint (public, protected, private). + raw (`dict`): + The raw dictionary data returned from the API. + token (`str` or `bool`, *optional*): + Authentication token for the Inference Endpoint, if set when requesting the API. Will default to the + locally saved token if not provided. Pass `token=False` if you don't want to send your token to the server. + + Example: + ```python + >>> from huggingface_hub import get_inference_endpoint + >>> endpoint = get_inference_endpoint("my-text-to-image") + >>> endpoint + InferenceEndpoint(name='my-text-to-image', ...) + + # Get status + >>> endpoint.status + 'running' + >>> endpoint.url + 'https://my-text-to-image.region.vendor.endpoints.huggingface.cloud' + + # Run inference + >>> endpoint.client.text_to_image(...) + + # Pause endpoint to save $$$ + >>> endpoint.pause() + + # ... + # Resume and wait for deployment + >>> endpoint.resume() + >>> endpoint.wait() + >>> endpoint.client.text_to_image(...) + ``` + """ + + # Field in __repr__ + name: str = field(init=False) + namespace: str + repository: str = field(init=False) + status: InferenceEndpointStatus = field(init=False) + health_route: str = field(init=False) + url: str | None = field(init=False) + + # Other fields + framework: str = field(repr=False, init=False) + revision: str = field(repr=False, init=False) + task: str = field(repr=False, init=False) + created_at: datetime = field(repr=False, init=False) + updated_at: datetime = field(repr=False, init=False) + type: InferenceEndpointType = field(repr=False, init=False) + + # Raw dict from the API + raw: dict = field(repr=False) + + # Internal fields + _token: str | bool | None = field(repr=False, compare=False) + _api: "HfApi" = field(repr=False, compare=False) + + @classmethod + def from_raw( + cls, raw: dict, namespace: str, token: str | bool | None = None, api: Optional["HfApi"] = None + ) -> "InferenceEndpoint": + """Initialize object from raw dictionary.""" + if api is None: + from .hf_api import HfApi + + api = HfApi() + if token is None: + token = api.token + + # All other fields are populated in __post_init__ + return cls(raw=raw, namespace=namespace, _token=token, _api=api) + + def __post_init__(self) -> None: + """Populate fields from raw dictionary.""" + self._populate_from_raw() + + @property + def client(self) -> "InferenceClient": + """Returns a client to make predictions on this Inference Endpoint. + + Returns: + [`InferenceClient`]: an inference client pointing to the deployed endpoint. + + Raises: + [`InferenceEndpointError`]: If the Inference Endpoint is not yet deployed. + """ + if self.url is None: + raise InferenceEndpointError( + "Cannot create a client for this Inference Endpoint as it is not yet deployed. " + "Please wait for the Inference Endpoint to be deployed using `endpoint.wait()` and try again." + ) + from .inference._client import InferenceClient + + return InferenceClient( + model=self.url, + token=self._token, # type: ignore # boolean token shouldn't be possible. In practice it's ok. + ) + + @property + def async_client(self) -> "AsyncInferenceClient": + """Returns a client to make predictions on this Inference Endpoint. + + Returns: + [`AsyncInferenceClient`]: an asyncio-compatible inference client pointing to the deployed endpoint. + + Raises: + [`InferenceEndpointError`]: If the Inference Endpoint is not yet deployed. + """ + if self.url is None: + raise InferenceEndpointError( + "Cannot create a client for this Inference Endpoint as it is not yet deployed. " + "Please wait for the Inference Endpoint to be deployed using `endpoint.wait()` and try again." + ) + from .inference._generated._async_client import AsyncInferenceClient + + return AsyncInferenceClient( + model=self.url, + token=self._token, # type: ignore # boolean token shouldn't be possible. In practice it's ok. + ) + + def wait(self, timeout: int | None = None, refresh_every: int = 5) -> "InferenceEndpoint": + """Wait for the Inference Endpoint to be deployed. + + Information from the server will be fetched every 1s. If the Inference Endpoint is not deployed after `timeout` + seconds, a [`InferenceEndpointTimeoutError`] will be raised. The [`InferenceEndpoint`] will be mutated in place with the latest + data. + + Args: + timeout (`int`, *optional*): + The maximum time to wait for the Inference Endpoint to be deployed, in seconds. If `None`, will wait + indefinitely. + refresh_every (`int`, *optional*): + The time to wait between each fetch of the Inference Endpoint status, in seconds. Defaults to 5s. + + Returns: + [`InferenceEndpoint`]: the same Inference Endpoint, mutated in place with the latest data. + + Raises: + [`InferenceEndpointError`] + If the Inference Endpoint ended up in a failed state. + [`InferenceEndpointTimeoutError`] + If the Inference Endpoint is not deployed after `timeout` seconds. + """ + if timeout is not None and timeout < 0: + raise ValueError("`timeout` cannot be negative.") + if refresh_every <= 0: + raise ValueError("`refresh_every` must be positive.") + + start = time.time() + while True: + if self.status == InferenceEndpointStatus.FAILED: + raise InferenceEndpointError( + f"Inference Endpoint {self.name} failed to deploy. Please check the logs for more information." + ) + if self.status == InferenceEndpointStatus.UPDATE_FAILED: + raise InferenceEndpointError( + f"Inference Endpoint {self.name} failed to update. Please check the logs for more information." + ) + if self.status == InferenceEndpointStatus.RUNNING and self.url is not None: + # Verify the endpoint is actually reachable + _health_url = f"{self.url.rstrip('/')}/{self.health_route.lstrip('/')}" + response = get_session().get(_health_url, headers=self._api._build_hf_headers(token=self._token)) + if response.status_code == 200: + logger.info("Inference Endpoint is ready to be used.") + return self + + if timeout is not None: + if time.time() - start > timeout: + raise InferenceEndpointTimeoutError("Timeout while waiting for Inference Endpoint to be deployed.") + logger.info(f"Inference Endpoint is not deployed yet ({self.status}). Waiting {refresh_every}s...") + time.sleep(refresh_every) + self.fetch() + + def fetch(self) -> "InferenceEndpoint": + """Fetch latest information about the Inference Endpoint. + + Returns: + [`InferenceEndpoint`]: the same Inference Endpoint, mutated in place with the latest data. + """ + obj = self._api.get_inference_endpoint(name=self.name, namespace=self.namespace, token=self._token) # type: ignore [arg-type] + self.raw = obj.raw + self._populate_from_raw() + return self + + def update( + self, + *, + # Compute update + accelerator: str | None = None, + instance_size: str | None = None, + instance_type: str | None = None, + min_replica: int | None = None, + max_replica: int | None = None, + scale_to_zero_timeout: int | None = None, + # Model update + repository: str | None = None, + framework: str | None = None, + revision: str | None = None, + task: str | None = None, + custom_image: dict | None = None, + secrets: dict[str, str] | None = None, + ) -> "InferenceEndpoint": + """Update the Inference Endpoint. + + This method allows the update of either the compute configuration, the deployed model, or both. All arguments are + optional but at least one must be provided. + + This is an alias for [`HfApi.update_inference_endpoint`]. The current object is mutated in place with the + latest data from the server. + + Args: + accelerator (`str`, *optional*): + The hardware accelerator to be used for inference (e.g. `"cpu"`). + instance_size (`str`, *optional*): + The size or type of the instance to be used for hosting the model (e.g. `"x4"`). + instance_type (`str`, *optional*): + The cloud instance type where the Inference Endpoint will be deployed (e.g. `"intel-icl"`). + min_replica (`int`, *optional*): + The minimum number of replicas (instances) to keep running for the Inference Endpoint. + max_replica (`int`, *optional*): + The maximum number of replicas (instances) to scale to for the Inference Endpoint. + scale_to_zero_timeout (`int`, *optional*): + The duration in minutes before an inactive endpoint is scaled to zero. + + repository (`str`, *optional*): + The name of the model repository associated with the Inference Endpoint (e.g. `"gpt2"`). + framework (`str`, *optional*): + The machine learning framework used for the model (e.g. `"custom"`). + revision (`str`, *optional*): + The specific model revision to deploy on the Inference Endpoint (e.g. `"6c0e6080953db56375760c0471a8c5f2929baf11"`). + task (`str`, *optional*): + The task on which to deploy the model (e.g. `"text-classification"`). + custom_image (`dict`, *optional*): + A custom Docker image to use for the Inference Endpoint. This is useful if you want to deploy an + Inference Endpoint running on the `text-generation-inference` (TGI) framework (see examples). + secrets (`dict[str, str]`, *optional*): + Secret values to inject in the container environment. + Returns: + [`InferenceEndpoint`]: the same Inference Endpoint, mutated in place with the latest data. + """ + # Make API call + obj = self._api.update_inference_endpoint( + name=self.name, + namespace=self.namespace, + accelerator=accelerator, + instance_size=instance_size, + instance_type=instance_type, + min_replica=min_replica, + max_replica=max_replica, + scale_to_zero_timeout=scale_to_zero_timeout, + repository=repository, + framework=framework, + revision=revision, + task=task, + custom_image=custom_image, + secrets=secrets, + token=self._token, # type: ignore [arg-type] + ) + + # Mutate current object + self.raw = obj.raw + self._populate_from_raw() + return self + + def pause(self) -> "InferenceEndpoint": + """Pause the Inference Endpoint. + + A paused Inference Endpoint will not be charged. It can be resumed at any time using [`InferenceEndpoint.resume`]. + This is different from scaling the Inference Endpoint to zero with [`InferenceEndpoint.scale_to_zero`], which + would be automatically restarted when a request is made to it. + + This is an alias for [`HfApi.pause_inference_endpoint`]. The current object is mutated in place with the + latest data from the server. + + Returns: + [`InferenceEndpoint`]: the same Inference Endpoint, mutated in place with the latest data. + """ + obj = self._api.pause_inference_endpoint(name=self.name, namespace=self.namespace, token=self._token) # type: ignore [arg-type] + self.raw = obj.raw + self._populate_from_raw() + return self + + def resume(self, running_ok: bool = True) -> "InferenceEndpoint": + """Resume the Inference Endpoint. + + This is an alias for [`HfApi.resume_inference_endpoint`]. The current object is mutated in place with the + latest data from the server. + + Args: + running_ok (`bool`, *optional*): + If `True`, the method will not raise an error if the Inference Endpoint is already running. Defaults to + `True`. + + Returns: + [`InferenceEndpoint`]: the same Inference Endpoint, mutated in place with the latest data. + """ + obj = self._api.resume_inference_endpoint( + name=self.name, namespace=self.namespace, running_ok=running_ok, token=self._token + ) # type: ignore [arg-type] + self.raw = obj.raw + self._populate_from_raw() + return self + + def scale_to_zero(self) -> "InferenceEndpoint": + """Scale Inference Endpoint to zero. + + An Inference Endpoint scaled to zero will not be charged. It will be resumed on the next request to it, with a + cold start delay. This is different from pausing the Inference Endpoint with [`InferenceEndpoint.pause`], which + would require a manual resume with [`InferenceEndpoint.resume`]. + + This is an alias for [`HfApi.scale_to_zero_inference_endpoint`]. The current object is mutated in place with the + latest data from the server. + + Returns: + [`InferenceEndpoint`]: the same Inference Endpoint, mutated in place with the latest data. + """ + obj = self._api.scale_to_zero_inference_endpoint(name=self.name, namespace=self.namespace, token=self._token) # type: ignore [arg-type] + self.raw = obj.raw + self._populate_from_raw() + return self + + def delete(self) -> None: + """Delete the Inference Endpoint. + + This operation is not reversible. If you don't want to be charged for an Inference Endpoint, it is preferable + to pause it with [`InferenceEndpoint.pause`] or scale it to zero with [`InferenceEndpoint.scale_to_zero`]. + + This is an alias for [`HfApi.delete_inference_endpoint`]. + """ + self._api.delete_inference_endpoint(name=self.name, namespace=self.namespace, token=self._token) # type: ignore [arg-type] + + def _populate_from_raw(self) -> None: + """Populate fields from raw dictionary. + + Called in __post_init__ + each time the Inference Endpoint is updated. + """ + # Repr fields + self.name = self.raw["name"] + self.repository = self.raw["model"]["repository"] + self.status = self.raw["status"]["state"] + self.url = self.raw["status"].get("url") + self.health_route = self.raw["healthRoute"] + + # Other fields + self.framework = self.raw["model"]["framework"] + self.revision = self.raw["model"]["revision"] + self.task = self.raw["model"]["task"] + self.created_at = parse_datetime(self.raw["status"]["createdAt"]) + self.updated_at = parse_datetime(self.raw["status"]["updatedAt"]) + self.type = self.raw["type"] diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_jobs_api.py b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_jobs_api.py new file mode 100644 index 0000000000000000000000000000000000000000..108871ce429f67c76782c89a13a845fed88027af --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_jobs_api.py @@ -0,0 +1,410 @@ +# Copyright 2025-present, the HuggingFace Inc. team. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from dataclasses import dataclass +from datetime import datetime +from enum import Enum +from typing import Any + +from huggingface_hub import constants +from huggingface_hub._space_api import SpaceHardware, Volume +from huggingface_hub.utils._datetime import parse_datetime + + +class JobStage(str, Enum): + """ + Enumeration of possible stage of a Job on the Hub. + + Value can be compared to a string: + ```py + assert JobStage.COMPLETED == "COMPLETED" + ``` + Possible values are: `COMPLETED`, `CANCELED`, `ERROR`, `DELETED`, `RUNNING`. + Taken from https://github.com/huggingface/moon-landing/blob/main/server/job_types/JobInfo.ts#L61 (private url). + """ + + # Copied from moon-landing > server > lib > Job.ts + COMPLETED = "COMPLETED" + CANCELED = "CANCELED" + ERROR = "ERROR" + DELETED = "DELETED" + RUNNING = "RUNNING" + + +@dataclass +class JobStatus: + stage: JobStage + message: str | None + + +@dataclass +class JobOwner: + id: str + name: str + type: str + + +@dataclass +class JobInfo: + """ + Contains information about a Job. + + Args: + id (`str`): + Job ID. + created_at (`datetime` or `None`): + When the Job was created. + docker_image (`str` or `None`): + The Docker image from Docker Hub used for the Job. + Can be None if space_id is present instead. + space_id (`str` or `None`): + The Docker image from Hugging Face Spaces used for the Job. + Can be None if docker_image is present instead. + command (`list[str]` or `None`): + Command of the Job, e.g. `["python", "-c", "print('hello world')"]` + arguments (`list[str]` or `None`): + Arguments passed to the command + environment (`dict[str]` or `None`): + Environment variables of the Job as a dictionary. + secrets (`dict[str]` or `None`): + Secret environment variables of the Job (encrypted). + flavor (`str` or `None`): + Flavor for the hardware, as in Hugging Face Spaces. See [`SpaceHardware`] for possible values. + E.g. `"cpu-basic"`. + labels (`dict[str, str]` or `None`): + Labels to attach to the job (key-value pairs). + volumes (`list[Volume]` or `None`): + Volumes mounted in the job container (buckets, models, datasets, spaces). + status: (`JobStatus` or `None`): + Status of the Job, e.g. `JobStatus(stage="RUNNING", message=None)` + See [`JobStage`] for possible stage values. + owner: (`JobOwner` or `None`): + Owner of the Job, e.g. `JobOwner(id="5e9ecfc04957053f60648a3e", name="lhoestq", type="user")` + + Example: + + ```python + >>> from huggingface_hub import run_job + >>> job = run_job( + ... image="python:3.12", + ... command=["python", "-c", "print('Hello from the cloud!')"] + ... ) + >>> job + JobInfo(id='687fb701029421ae5549d998', created_at=datetime.datetime(2025, 7, 22, 16, 6, 25, 79000, tzinfo=datetime.timezone.utc), docker_image='python:3.12', space_id=None, command=['python', '-c', "print('Hello from the cloud!')"], arguments=[], environment={}, secrets={}, flavor='cpu-basic', labels=None, status=JobStatus(stage='RUNNING', message=None), owner=JobOwner(id='5e9ecfc04957053f60648a3e', name='lhoestq', type='user'), endpoint='https://huggingface.co', url='https://huggingface.co/jobs/lhoestq/687fb701029421ae5549d998') + >>> job.id + '687fb701029421ae5549d998' + >>> job.url + 'https://huggingface.co/jobs/lhoestq/687fb701029421ae5549d998' + >>> job.status.stage + 'RUNNING' + ``` + """ + + id: str + created_at: datetime | None + docker_image: str | None + space_id: str | None + command: list[str] | None + arguments: list[str] | None + environment: dict[str, Any] | None + secrets: dict[str, Any] | None + flavor: SpaceHardware | None + labels: dict[str, str] | None + volumes: list[Volume] | None + status: JobStatus + owner: JobOwner + + # Inferred fields + endpoint: str + url: str + + def __init__(self, **kwargs) -> None: + self.id = kwargs["id"] + created_at = kwargs.get("createdAt") or kwargs.get("created_at") + self.created_at = parse_datetime(created_at) if created_at else None + self.docker_image = kwargs.get("dockerImage") or kwargs.get("docker_image") + self.space_id = kwargs.get("spaceId") or kwargs.get("space_id") + owner = kwargs.get("owner", {}) + self.owner = JobOwner(id=owner["id"], name=owner["name"], type=owner["type"]) + self.command = kwargs.get("command") + self.arguments = kwargs.get("arguments") + self.environment = kwargs.get("environment") + self.secrets = kwargs.get("secrets") + self.flavor = kwargs.get("flavor") + self.labels = kwargs.get("labels") + volumes = kwargs.get("volumes") + self.volumes = [Volume(**v) for v in volumes] if volumes else None + status = kwargs.get("status", {}) + self.status = JobStatus(stage=status["stage"], message=status.get("message")) + + # Inferred fields + self.endpoint = kwargs.get("endpoint", constants.ENDPOINT) + self.url = f"{self.endpoint}/jobs/{self.owner.name}/{self.id}" + + +@dataclass +class JobSpec: + docker_image: str | None + space_id: str | None + command: list[str] | None + arguments: list[str] | None + environment: dict[str, Any] | None + secrets: dict[str, Any] | None + flavor: SpaceHardware | None + timeout: int | None + tags: list[str] | None + arch: str | None + labels: dict[str, str] | None + volumes: list[Volume] | None + + def __init__(self, **kwargs) -> None: + self.docker_image = kwargs.get("dockerImage") or kwargs.get("docker_image") + self.space_id = kwargs.get("spaceId") or kwargs.get("space_id") + self.command = kwargs.get("command") + self.arguments = kwargs.get("arguments") + self.environment = kwargs.get("environment") + self.secrets = kwargs.get("secrets") + self.flavor = kwargs.get("flavor") + self.timeout = kwargs.get("timeout") + self.tags = kwargs.get("tags") + self.arch = kwargs.get("arch") + self.labels = kwargs.get("labels") + volumes = kwargs.get("volumes") + self.volumes = [Volume(**v) for v in volumes] if volumes else None + + +@dataclass +class LastJobInfo: + id: str + at: datetime + + def __init__(self, **kwargs) -> None: + self.id = kwargs["id"] + self.at = parse_datetime(kwargs["at"]) + + +@dataclass +class ScheduledJobStatus: + last_job: LastJobInfo | None + next_job_run_at: datetime | None + + def __init__(self, **kwargs) -> None: + last_job = kwargs.get("lastJob") or kwargs.get("last_job") + self.last_job = LastJobInfo(**last_job) if last_job else None + next_job_run_at = kwargs.get("nextJobRunAt") or kwargs.get("next_job_run_at") + self.next_job_run_at = parse_datetime(str(next_job_run_at)) if next_job_run_at else None + + +@dataclass +class ScheduledJobInfo: + """ + Contains information about a Job. + + Args: + id (`str`): + Scheduled Job ID. + created_at (`datetime` or `None`): + When the scheduled Job was created. + tags (`list[str]` or `None`): + The tags of the scheduled Job. + schedule (`str` or `None`): + One of "@annually", "@yearly", "@monthly", "@weekly", "@daily", "@hourly", or a + CRON schedule expression (e.g., '0 9 * * 1' for 9 AM every Monday). + suspend (`bool` or `None`): + Whether the scheduled job is suspended (paused). + concurrency (`bool` or `None`): + Whether multiple instances of this Job can run concurrently. + status (`ScheduledJobStatus` or `None`): + Status of the scheduled Job. + owner: (`JobOwner` or `None`): + Owner of the scheduled Job, e.g. `JobOwner(id="5e9ecfc04957053f60648a3e", name="lhoestq", type="user")` + job_spec: (`JobSpec` or `None`): + Specifications of the Job. + + Example: + + ```python + >>> from huggingface_hub import run_job + >>> scheduled_job = create_scheduled_job( + ... image="python:3.12", + ... command=["python", "-c", "print('Hello from the cloud!')"], + ... schedule="@hourly", + ... ) + >>> scheduled_job.id + '687fb701029421ae5549d999' + >>> scheduled_job.status.next_job_run_at + datetime.datetime(2025, 7, 22, 17, 6, 25, 79000, tzinfo=datetime.timezone.utc) + ``` + """ + + id: str + created_at: datetime | None + job_spec: JobSpec + schedule: str | None + suspend: bool | None + concurrency: bool | None + status: ScheduledJobStatus + owner: JobOwner + + def __init__(self, **kwargs) -> None: + self.id = kwargs["id"] + created_at = kwargs.get("createdAt") or kwargs.get("created_at") + self.created_at = parse_datetime(created_at) if created_at else None + self.job_spec = JobSpec(**(kwargs.get("job_spec") or kwargs.get("jobSpec", {}))) + self.schedule = kwargs.get("schedule") + self.suspend = kwargs.get("suspend") + self.concurrency = kwargs.get("concurrency") + status = kwargs.get("status", {}) + self.status = ScheduledJobStatus( + last_job=status.get("last_job") or status.get("lastJob"), + next_job_run_at=status.get("next_job_run_at") or status.get("nextJobRunAt"), + ) + owner = kwargs.get("owner", {}) + self.owner = JobOwner(id=owner["id"], name=owner["name"], type=owner["type"]) + + +@dataclass +class JobAccelerator: + """ + Contains information about a Job accelerator (GPU). + + Args: + type (`str`): + Type of accelerator, e.g. `"gpu"`. + model (`str`): + Model of accelerator, e.g. `"T4"`, `"A10G"`, `"A100"`, `"L4"`, `"L40S"`. + quantity (`str`): + Number of accelerators, e.g. `"1"`, `"2"`, `"4"`, `"8"`. + vram (`str`): + Total VRAM, e.g. `"16 GB"`, `"24 GB"`. + manufacturer (`str`): + Manufacturer of the accelerator, e.g. `"Nvidia"`. + """ + + type: str + model: str + quantity: str + vram: str + manufacturer: str + + def __init__(self, **kwargs) -> None: + self.type = kwargs["type"] + self.model = kwargs["model"] + self.quantity = kwargs["quantity"] + self.vram = kwargs["vram"] + self.manufacturer = kwargs["manufacturer"] + + +@dataclass +class JobHardware: + """ + Contains information about available Job hardware. + + Args: + name (`str`): + Machine identifier, e.g. `"cpu-basic"`, `"a10g-large"`. + pretty_name (`str`): + Human-readable name, e.g. `"CPU Basic"`, `"Nvidia A10G - large"`. + cpu (`str`): + CPU specification, e.g. `"2 vCPU"`, `"12 vCPU"`. + ram (`str`): + RAM specification, e.g. `"16 GB"`, `"46 GB"`. + accelerator (`JobAccelerator` or `None`): + GPU/accelerator details if available. + unit_cost_micro_usd (`int`): + Cost in micro-dollars per unit, e.g. `167` (= $0.000167). + unit_cost_usd (`float`): + Cost in USD per unit, e.g. `0.000167`. + unit_label (`str`): + Cost unit period, e.g. `"minute"`. + + Example: + + ```python + >>> from huggingface_hub import list_jobs_hardware + >>> hardware_list = list_jobs_hardware() + >>> hardware_list[0] + JobHardware(name='cpu-basic', pretty_name='CPU Basic', cpu='2 vCPU', ram='16 GB', accelerator=None, unit_cost_micro_usd=167, unit_cost_usd=0.000167, unit_label='minute') + >>> hardware_list[0].name + 'cpu-basic' + ``` + """ + + name: str + pretty_name: str + cpu: str + ram: str + accelerator: JobAccelerator | None + unit_cost_micro_usd: int + unit_cost_usd: float + unit_label: str + + def __init__(self, **kwargs) -> None: + self.name = kwargs["name"] + self.pretty_name = kwargs["prettyName"] + self.cpu = kwargs["cpu"] + self.ram = kwargs["ram"] + accelerator = kwargs.get("accelerator") + self.accelerator = JobAccelerator(**accelerator) if accelerator else None + self.unit_cost_micro_usd = kwargs["unitCostMicroUSD"] + self.unit_cost_usd = kwargs["unitCostUSD"] + self.unit_label = kwargs["unitLabel"] + + +def _create_job_spec( + *, + image: str, + command: list[str], + env: dict[str, Any] | None, + secrets: dict[str, Any] | None, + flavor: SpaceHardware | None, + timeout: int | float | str | None, + labels: dict[str, str] | None = None, + volumes: list[Volume] | None = None, +) -> dict[str, Any]: + # prepare job spec to send to HF Jobs API + job_spec: dict[str, Any] = { + "command": command, + "arguments": [], + "environment": env or {}, + "flavor": flavor or SpaceHardware.CPU_BASIC, + } + # secrets are optional + if secrets: + job_spec["secrets"] = secrets + # timeout is optional + if timeout: + time_units_factors = {"s": 1, "m": 60, "h": 3600, "d": 3600 * 24} + if isinstance(timeout, str) and timeout[-1] in time_units_factors: + job_spec["timeoutSeconds"] = int(float(timeout[:-1]) * time_units_factors[timeout[-1]]) + else: + job_spec["timeoutSeconds"] = int(timeout) + # labels are optional + if labels: + job_spec["labels"] = labels + # volumes are optional + if volumes: + job_spec["volumes"] = [vol.to_dict() for vol in volumes] + # input is either from docker hub or from HF spaces + for prefix in ( + "https://huggingface.co/spaces/", + "https://hf.co/spaces/", + "huggingface.co/spaces/", + "hf.co/spaces/", + ): + if image.startswith(prefix): + job_spec["spaceId"] = image[len(prefix) :] + break + else: + job_spec["dockerImage"] = image + return job_spec diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_local_folder.py b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_local_folder.py new file mode 100644 index 0000000000000000000000000000000000000000..2e60361293d0bd45b8a877e55291882144279e42 --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_local_folder.py @@ -0,0 +1,473 @@ +# Copyright 2024-present, the HuggingFace Inc. team. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Contains utilities to handle the `../.cache/huggingface` folder in local directories. + +First discussed in https://github.com/huggingface/huggingface_hub/issues/1738 to store +download metadata when downloading files from the hub to a local directory (without +using the cache). + +./.cache/huggingface folder structure: +[4.0K] data +├── [4.0K] .cache +│ └── [4.0K] huggingface +│ └── [4.0K] download +│ ├── [ 16] file.parquet.metadata +│ ├── [ 16] file.txt.metadata +│ └── [4.0K] folder +│ └── [ 16] file.parquet.metadata +│ +├── [6.5G] file.parquet +├── [1.5K] file.txt +└── [4.0K] folder + └── [ 16] file.parquet + + +Download metadata file structure: +``` +# file.txt.metadata +11c5a3d5811f50298f278a704980280950aedb10 +a16a55fda99d2f2e7b69cce5cf93ff4ad3049930 +1712656091.123 + +# file.parquet.metadata +11c5a3d5811f50298f278a704980280950aedb10 +7c5d3f4b8b76583b422fcb9189ad6c89d5d97a094541ce8932dce3ecabde1421 +1712656091.123 +} +``` +""" + +import base64 +import hashlib +import logging +import os +import time +from dataclasses import dataclass +from pathlib import Path + +from .utils import WeakFileLock + + +logger = logging.getLogger(__name__) + +CACHEDIR_TAG_CONTENT = ( + "Signature: 8a477f597d28d172789f06886806bc55\n" + "# This file is a cache directory tag created by huggingface_hub.\n" + "# For information about cache directory tags, see:\n" + "#\thttps://bford.info/cachedir/\n" +) + + +@dataclass +class LocalDownloadFilePaths: + """ + Paths to the files related to a download process in a local dir. + + Returned by [`get_local_download_paths`]. + + Attributes: + file_path (`Path`): + Path where the file will be saved. + lock_path (`Path`): + Path to the lock file used to ensure atomicity when reading/writing metadata. + metadata_path (`Path`): + Path to the metadata file. + """ + + file_path: Path + lock_path: Path + metadata_path: Path + + def incomplete_path(self, etag: str) -> Path: + """Return the path where a file will be temporarily downloaded before being moved to `file_path`.""" + path = self.metadata_path.parent / f"{_short_hash(self.metadata_path.name)}.{etag}.incomplete" + resolved_path = str(path.resolve()) + # Some Windows versions do not allow for paths longer than 255 characters. + # In this case, we must specify it as an extended path by using the "\\?\" prefix. + if os.name == "nt" and len(resolved_path) > 255 and not resolved_path.startswith("\\\\?\\"): + path = Path("\\\\?\\" + resolved_path) + return path + + +@dataclass(frozen=True) +class LocalUploadFilePaths: + """ + Paths to the files related to an upload process in a local dir. + + Returned by [`get_local_upload_paths`]. + + Attributes: + path_in_repo (`str`): + Path of the file in the repo. + file_path (`Path`): + Path where the file will be saved. + lock_path (`Path`): + Path to the lock file used to ensure atomicity when reading/writing metadata. + metadata_path (`Path`): + Path to the metadata file. + """ + + path_in_repo: str + file_path: Path + lock_path: Path + metadata_path: Path + + +@dataclass +class LocalDownloadFileMetadata: + """ + Metadata about a file in the local directory related to a download process. + + Attributes: + filename (`str`): + Path of the file in the repo. + commit_hash (`str`): + Commit hash of the file in the repo. + etag (`str`): + ETag of the file in the repo. Used to check if the file has changed. + For LFS files, this is the sha256 of the file. For regular files, it corresponds to the git hash. + timestamp (`int`): + Unix timestamp of when the metadata was saved i.e. when the metadata was accurate. + """ + + filename: str + commit_hash: str + etag: str + timestamp: float + + +@dataclass +class LocalUploadFileMetadata: + """ + Metadata about a file in the local directory related to an upload process. + """ + + size: int + + # Default values correspond to "we don't know yet" + timestamp: float | None = None + should_ignore: bool | None = None + sha256: str | None = None + upload_mode: str | None = None + remote_oid: str | None = None + is_uploaded: bool = False + is_committed: bool = False + + def save(self, paths: LocalUploadFilePaths) -> None: + """Save the metadata to disk.""" + with WeakFileLock(paths.lock_path): + with paths.metadata_path.open("w") as f: + new_timestamp = time.time() + f.write(str(new_timestamp) + "\n") + + f.write(str(self.size)) # never None + f.write("\n") + + if self.should_ignore is not None: + f.write(str(int(self.should_ignore))) + f.write("\n") + + if self.sha256 is not None: + f.write(self.sha256) + f.write("\n") + + if self.upload_mode is not None: + f.write(self.upload_mode) + f.write("\n") + + if self.remote_oid is not None: + f.write(self.remote_oid) + f.write("\n") + + f.write(str(int(self.is_uploaded)) + "\n") + f.write(str(int(self.is_committed)) + "\n") + + self.timestamp = new_timestamp + + +def get_local_download_paths(local_dir: Path, filename: str) -> LocalDownloadFilePaths: + """Compute paths to the files related to a download process. + + Folders containing the paths are all guaranteed to exist. + + Args: + local_dir (`Path`): + Path to the local directory in which files are downloaded. + filename (`str`): + Path of the file in the repo. + + Return: + [`LocalDownloadFilePaths`]: the paths to the files (file_path, lock_path, metadata_path, incomplete_path). + """ + # filename is the path in the Hub repository (separated by '/') + # make sure to have a cross-platform transcription + sanitized_filename = os.path.join(*filename.split("/")) + if os.name == "nt": + if sanitized_filename.startswith("..\\") or "\\..\\" in sanitized_filename: + raise ValueError( + f"Invalid filename: cannot handle filename '{sanitized_filename}' on Windows. Please ask the repository" + " owner to rename this file." + ) + file_path = local_dir / sanitized_filename + metadata_path = _huggingface_dir(local_dir) / "download" / f"{sanitized_filename}.metadata" + lock_path = metadata_path.with_suffix(".lock") + + # Some Windows versions do not allow for paths longer than 255 characters. + # In this case, we must specify it as an extended path by using the "\\?\" prefix + if os.name == "nt": + if not str(local_dir).startswith("\\\\?\\") and len(os.path.abspath(lock_path)) > 255: + file_path = Path("\\\\?\\" + os.path.abspath(file_path)) + lock_path = Path("\\\\?\\" + os.path.abspath(lock_path)) + metadata_path = Path("\\\\?\\" + os.path.abspath(metadata_path)) + + file_path.parent.mkdir(parents=True, exist_ok=True) + metadata_path.parent.mkdir(parents=True, exist_ok=True) + return LocalDownloadFilePaths(file_path=file_path, lock_path=lock_path, metadata_path=metadata_path) + + +def get_local_upload_paths(local_dir: Path, filename: str) -> LocalUploadFilePaths: + """Compute paths to the files related to an upload process. + + Folders containing the paths are all guaranteed to exist. + + Args: + local_dir (`Path`): + Path to the local directory that is uploaded. + filename (`str`): + Path of the file in the repo. + + Return: + [`LocalUploadFilePaths`]: the paths to the files (file_path, lock_path, metadata_path). + """ + # filename is the path in the Hub repository (separated by '/') + # make sure to have a cross-platform transcription + sanitized_filename = os.path.join(*filename.split("/")) + if os.name == "nt": + if sanitized_filename.startswith("..\\") or "\\..\\" in sanitized_filename: + raise ValueError( + f"Invalid filename: cannot handle filename '{sanitized_filename}' on Windows. Please ask the repository" + " owner to rename this file." + ) + file_path = local_dir / sanitized_filename + metadata_path = _huggingface_dir(local_dir) / "upload" / f"{sanitized_filename}.metadata" + lock_path = metadata_path.with_suffix(".lock") + + # Some Windows versions do not allow for paths longer than 255 characters. + # In this case, we must specify it as an extended path by using the "\\?\" prefix + if os.name == "nt": + if not str(local_dir).startswith("\\\\?\\") and len(os.path.abspath(lock_path)) > 255: + file_path = Path("\\\\?\\" + os.path.abspath(file_path)) + lock_path = Path("\\\\?\\" + os.path.abspath(lock_path)) + metadata_path = Path("\\\\?\\" + os.path.abspath(metadata_path)) + + file_path.parent.mkdir(parents=True, exist_ok=True) + metadata_path.parent.mkdir(parents=True, exist_ok=True) + return LocalUploadFilePaths( + path_in_repo=filename, file_path=file_path, lock_path=lock_path, metadata_path=metadata_path + ) + + +def read_download_metadata(local_dir: Path, filename: str) -> LocalDownloadFileMetadata | None: + """Read metadata about a file in the local directory related to a download process. + + Args: + local_dir (`Path`): + Path to the local directory in which files are downloaded. + filename (`str`): + Path of the file in the repo. + + Return: + `[LocalDownloadFileMetadata]` or `None`: the metadata if it exists, `None` otherwise. + """ + paths = get_local_download_paths(local_dir, filename) + with WeakFileLock(paths.lock_path): + if paths.metadata_path.exists(): + try: + with paths.metadata_path.open() as f: + commit_hash = f.readline().strip() + etag = f.readline().strip() + timestamp = float(f.readline().strip()) + metadata = LocalDownloadFileMetadata( + filename=filename, + commit_hash=commit_hash, + etag=etag, + timestamp=timestamp, + ) + except Exception as e: + # remove the metadata file if it is corrupted / not the right format + logger.warning( + f"Invalid metadata file {paths.metadata_path}: {e}. Removing it from disk and continue." + ) + try: + paths.metadata_path.unlink() + except Exception as e: + logger.warning(f"Could not remove corrupted metadata file {paths.metadata_path}: {e}") + return None + + try: + # check if the file exists and hasn't been modified since the metadata was saved + stat = paths.file_path.stat() + if ( + stat.st_mtime - 1 <= metadata.timestamp + ): # allow 1s difference as stat.st_mtime might not be precise + return metadata + logger.info(f"Ignored metadata for '{filename}' (outdated). Will re-compute hash.") + except FileNotFoundError: + # file does not exist => metadata is outdated + return None + return None + + +def read_upload_metadata(local_dir: Path, filename: str) -> LocalUploadFileMetadata: + """Read metadata about a file in the local directory related to an upload process. + + TODO: factorize logic with `read_download_metadata`. + + Args: + local_dir (`Path`): + Path to the local directory in which files are downloaded. + filename (`str`): + Path of the file in the repo. + + Return: + `[LocalUploadFileMetadata]` or `None`: the metadata if it exists, `None` otherwise. + """ + paths = get_local_upload_paths(local_dir, filename) + with WeakFileLock(paths.lock_path): + if paths.metadata_path.exists(): + try: + with paths.metadata_path.open() as f: + timestamp = float(f.readline().strip()) + + size = int(f.readline().strip()) # never None + + _should_ignore = f.readline().strip() + should_ignore = None if _should_ignore == "" else bool(int(_should_ignore)) + + _sha256 = f.readline().strip() + sha256 = None if _sha256 == "" else _sha256 + + _upload_mode = f.readline().strip() + upload_mode = None if _upload_mode == "" else _upload_mode + if upload_mode not in (None, "regular", "lfs"): + raise ValueError(f"Invalid upload mode in metadata {paths.path_in_repo}: {upload_mode}") + + _remote_oid = f.readline().strip() + remote_oid = None if _remote_oid == "" else _remote_oid + + is_uploaded = bool(int(f.readline().strip())) + is_committed = bool(int(f.readline().strip())) + + metadata = LocalUploadFileMetadata( + timestamp=timestamp, + size=size, + should_ignore=should_ignore, + sha256=sha256, + upload_mode=upload_mode, + remote_oid=remote_oid, + is_uploaded=is_uploaded, + is_committed=is_committed, + ) + except Exception as e: + # remove the metadata file if it is corrupted / not the right format + logger.warning( + f"Invalid metadata file {paths.metadata_path}: {e}. Removing it from disk and continue." + ) + try: + paths.metadata_path.unlink() + except Exception as e: + logger.warning(f"Could not remove corrupted metadata file {paths.metadata_path}: {e}") + + # corrupted metadata => we don't know anything expect its size + return LocalUploadFileMetadata(size=paths.file_path.stat().st_size) + + # TODO: can we do better? + if ( + metadata.timestamp is not None + and metadata.is_uploaded # file was uploaded + and not metadata.is_committed # but not committed + and time.time() - metadata.timestamp > 20 * 3600 # and it's been more than 20 hours + ): # => we consider it as garbage-collected by S3 + metadata.is_uploaded = False + + # check if the file exists and hasn't been modified since the metadata was saved + try: + if metadata.timestamp is not None and paths.file_path.stat().st_mtime <= metadata.timestamp: + return metadata + logger.info(f"Ignored metadata for '{filename}' (outdated). Will re-compute hash.") + except FileNotFoundError: + # file does not exist => metadata is outdated + pass + + # empty metadata => we don't know anything expect its size + return LocalUploadFileMetadata(size=paths.file_path.stat().st_size) + + +def write_download_metadata(local_dir: Path, filename: str, commit_hash: str, etag: str) -> None: + """Write metadata about a file in the local directory related to a download process. + + Args: + local_dir (`Path`): + Path to the local directory in which files are downloaded. + """ + paths = get_local_download_paths(local_dir, filename) + with WeakFileLock(paths.lock_path): + with paths.metadata_path.open("w") as f: + f.write(f"{commit_hash}\n{etag}\n{time.time()}\n") + + +def _huggingface_dir(local_dir: Path) -> Path: + """Return the path to the `.cache/huggingface` directory in a local directory.""" + # Wrap in lru_cache to avoid overwriting the .gitignore file if called multiple times + path = local_dir / ".cache" / "huggingface" + path.mkdir(exist_ok=True, parents=True) + + # Create a CACHEDIR.TAG so backup tools can skip this directory. + _create_cachedir_tag(path) + + # Create a .gitignore file in the .cache/huggingface directory if it doesn't exist + # Should be thread-safe enough like this. + gitignore = path / ".gitignore" + gitignore_lock = path / ".gitignore.lock" + if not gitignore.exists(): + try: + with WeakFileLock(gitignore_lock, timeout=0.1): + gitignore.write_text("*") + except IndexError: + pass + except OSError: # TimeoutError, FileNotFoundError, PermissionError, etc. + pass + try: + gitignore_lock.unlink() + except OSError: + pass + return path + + +def _create_cachedir_tag(cache_dir: Path) -> None: + """Create a CACHEDIR.TAG file in ``cache_dir`` if one does not already exist. + + The tag follows the `Cache Directory Tagging Standard `_ + so that backup tools can recognize and skip cache directories. + """ + tag_path = cache_dir / "CACHEDIR.TAG" + if not tag_path.exists(): + try: + tag_path.write_text(CACHEDIR_TAG_CONTENT) + except OSError: + pass + + +def _short_hash(filename: str) -> str: + return base64.urlsafe_b64encode(hashlib.sha1(filename.encode()).digest()).decode() diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_login.py b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_login.py new file mode 100644 index 0000000000000000000000000000000000000000..1e358d355c1e9ed92944c553e9c1edd56d2f8a96 --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_login.py @@ -0,0 +1,494 @@ +# Copyright 2020 The HuggingFace Team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Contains methods to log in to the Hub.""" + +import os +import subprocess +from getpass import getpass +from pathlib import Path + +import typer + +from . import constants +from .utils import ( + ANSI, + capture_output, + get_token, + is_google_colab, + is_notebook, + list_credential_helpers, + logging, + run_subprocess, + set_git_credential, + unset_git_credential, +) +from .utils._auth import ( + _get_token_by_name, + _get_token_from_environment, + _get_token_from_file, + _get_token_from_google_colab, + _save_stored_tokens, + _save_token, + get_stored_tokens, +) + + +logger = logging.get_logger(__name__) + +_HF_LOGO_ASCII = """ + _| _| _| _| _|_|_| _|_|_| _|_|_| _| _| _|_|_| _|_|_|_| _|_| _|_|_| _|_|_|_| + _| _| _| _| _| _| _| _|_| _| _| _| _| _| _| _| + _|_|_|_| _| _| _| _|_| _| _|_| _| _| _| _| _| _|_| _|_|_| _|_|_|_| _| _|_|_| + _| _| _| _| _| _| _| _| _| _| _|_| _| _| _| _| _| _| _| + _| _| _|_| _|_|_| _|_|_| _|_|_| _| _| _|_|_| _| _| _| _|_|_| _|_|_|_| +""" + + +def login( + token: str | None = None, + *, + add_to_git_credential: bool = False, + skip_if_logged_in: bool = True, +) -> None: + """Login the machine to access the Hub. + + The `token` is persisted in cache and set as a git credential. Once done, the machine + is logged in and the access token will be available across all `huggingface_hub` + components. If `token` is not provided, it will be prompted to the user either with + a widget (in a notebook) or via the terminal. + + To log in from outside of a script, one can also use `hf auth login` which is + a cli command that wraps [`login`]. + + > [!TIP] + > [`login`] is a drop-in replacement method for [`notebook_login`] as it wraps and + > extends its capabilities. + + > [!TIP] + > When the token is not passed, [`login`] will automatically detect if the script runs + > in a notebook or not. However, this detection might not be accurate due to the + > variety of notebooks that exists nowadays. If that is the case, you can always force + > the UI by using [`notebook_login`] or [`interpreter_login`]. + + Args: + token (`str`, *optional*): + User access token to generate from https://huggingface.co/settings/token. + add_to_git_credential (`bool`, defaults to `False`): + If `True`, token will be set as git credential. If no git credential helper + is configured, a warning will be displayed to the user. If `token` is `None`, + the value of `add_to_git_credential` is ignored and will be prompted again + to the end user. + skip_if_logged_in (`bool`, defaults to `True`): + If `True`, do not prompt for token if user is already logged in. + Set to `False` to force re-login. In CLI, use `--force` instead. + Raises: + [`ValueError`](https://docs.python.org/3/library/exceptions.html#ValueError) + If an organization token is passed. Only personal account tokens are valid + to log in. + [`ValueError`](https://docs.python.org/3/library/exceptions.html#ValueError) + If token is invalid. + [`ImportError`](https://docs.python.org/3/library/exceptions.html#ImportError) + If running in a notebook but `ipywidgets` is not installed. + """ + if token is not None: + if not add_to_git_credential: + logger.info( + "The token has not been saved to the git credentials helper. Pass " + "`add_to_git_credential=True` in this function directly or " + "`--add-to-git-credential` if using via `hf`CLI if " + "you want to set the git credential as well." + ) + _login(token, add_to_git_credential=add_to_git_credential) + elif is_notebook(): + notebook_login(skip_if_logged_in=skip_if_logged_in) + else: + interpreter_login(skip_if_logged_in=skip_if_logged_in) + + +def logout(token_name: str | None = None) -> None: + """Logout the machine from the Hub. + + Token is deleted from the machine and removed from git credential. + + Args: + token_name (`str`, *optional*): + Name of the access token to logout from. If `None`, will log out from all saved access tokens. + Raises: + [`ValueError`](https://docs.python.org/3/library/exceptions.html#ValueError): + If the access token name is not found. + """ + if get_token() is None and not get_stored_tokens(): # No active token and no saved access tokens + logger.warning("Not logged in!") + return + if not token_name: + # Delete all saved access tokens and token + for file_path in (constants.HF_TOKEN_PATH, constants.HF_STORED_TOKENS_PATH): + try: + Path(file_path).unlink() + except FileNotFoundError: + pass + logger.info("Successfully logged out from all access tokens.") + else: + _logout_from_token(token_name) + logger.info(f"Successfully logged out from access token: {token_name}.") + + unset_git_credential() + + # Check if still logged in + if _get_token_from_google_colab() is not None: + raise OSError( + "You are automatically logged in using a Google Colab secret.\n" + "To log out, you must unset the `HF_TOKEN` secret in your Colab settings." + ) + if _get_token_from_environment() is not None: + raise OSError( + "Token has been deleted from your machine but you are still logged in.\n" + "To log out, you must clear out both `HF_TOKEN` and `HUGGING_FACE_HUB_TOKEN` environment variables." + ) + + +def auth_switch(token_name: str, add_to_git_credential: bool = False) -> None: + """Switch to a different access token. + + Args: + token_name (`str`): + Name of the access token to switch to. + add_to_git_credential (`bool`, defaults to `False`): + If `True`, token will be set as git credential. If no git credential helper + is configured, a warning will be displayed to the user. If `token` is `None`, + the value of `add_to_git_credential` is ignored and will be prompted again + to the end user. + + Raises: + [`ValueError`](https://docs.python.org/3/library/exceptions.html#ValueError): + If the access token name is not found. + """ + token = _get_token_by_name(token_name) + if not token: + raise ValueError(f"Access token {token_name} not found in {constants.HF_STORED_TOKENS_PATH}") + # Write token to HF_TOKEN_PATH + _set_active_token(token_name, add_to_git_credential) + logger.info(f"The current active token is: {token_name}") + token_from_environment = _get_token_from_environment() + if token_from_environment is not None and token_from_environment != token: + logger.warning( + "The environment variable `HF_TOKEN` is set and will override the access token you've just switched to." + ) + + +def auth_list() -> None: + """List all stored access tokens.""" + tokens = get_stored_tokens() + + if not tokens: + if _get_token_from_environment(): + logger.info("No stored access tokens found.") + logger.warning("Note: Environment variable `HF_TOKEN` is set and is the current active token.") + else: + logger.info("No access tokens found.") + return + # Find current token + current_token = get_token() + current_token_name = None + for token_name in tokens: + if tokens.get(token_name) == current_token: + current_token_name = token_name + # Print header + max_offset = max(len("token"), max(len(token) for token in tokens)) + 2 + print(f" {{:<{max_offset}}}| {{:<15}}".format("name", "token")) + print("-" * (max_offset + 2) + "|" + "-" * 15) + + # Print saved access tokens + for token_name in tokens: + token = tokens.get(token_name, "") + masked_token = f"{token[:3]}****{token[-4:]}" if token != "" else token + is_current = "*" if token == current_token else " " + + print(f"{is_current} {{:<{max_offset}}}| {{:<15}}".format(token_name, masked_token)) + + if _get_token_from_environment(): + logger.warning( + "\nNote: Environment variable `HF_TOKEN` is set and is the current active token independently from the stored tokens listed above." + ) + elif current_token_name is None: + logger.warning( + "\nNote: No active token is set and no environment variable `HF_TOKEN` is found. Use `hf auth login` to log in." + ) + + +### +# Interpreter-based login (text) +### + + +def interpreter_login(*, skip_if_logged_in: bool = True) -> None: + """ + Displays a prompt to log in to the HF website and store the token. + + This is equivalent to [`login`] without passing a token when not run in a notebook. + [`interpreter_login`] is useful if you want to force the use of the terminal prompt + instead of a notebook widget. + + For more details, see [`login`]. + + Args: + skip_if_logged_in (`bool`, defaults to `True`): + If `True`, do not prompt for token if user is already logged in. + Set to `False` to force re-login. In CLI, use `--force` instead. + """ + if skip_if_logged_in and get_token() is not None: + logger.info("User is already logged in. Use `hf auth login --force` to force re-login.") + return + + print(_HF_LOGO_ASCII) + if get_token() is not None: + logger.info( + " A token is already saved on your machine. Run `hf auth whoami`" + " to get more information or `hf auth logout` if you want" + " to log out." + ) + logger.info(" Setting a new token will erase the existing one.") + + logger.info( + " To log in, `huggingface_hub` requires a token generated from https://huggingface.co/settings/tokens ." + ) + if os.name == "nt": + logger.info("Token can be pasted using 'Right-Click'.") + token = getpass("Enter your token (input will not be visible): ") + add_to_git_credential = typer.confirm("Add token as git credential?") + + _login(token=token, add_to_git_credential=add_to_git_credential) + + +### +# Notebook-based login (widget) +### + +NOTEBOOK_LOGIN_PASSWORD_HTML = """

Immediately click login after typing your password or +it might be stored in plain text in this notebook file.
""" + + +NOTEBOOK_LOGIN_TOKEN_HTML_START = """

Copy a token from your Hugging Face +tokens page and paste it below.
Immediately click login after copying +your token or it might be stored in plain text in this notebook file.
""" + + +NOTEBOOK_LOGIN_TOKEN_HTML_END = """ +Pro Tip: If you don't already have one, you can create a dedicated +'notebooks' token with 'write' access, that you can then easily reuse for all +notebooks. """ + + +def notebook_login(*, skip_if_logged_in: bool = True) -> None: + """ + Displays a widget to log in to the HF website and store the token. + + This is equivalent to [`login`] without passing a token when run in a notebook. + [`notebook_login`] is useful if you want to force the use of the notebook widget + instead of a prompt in the terminal. + + For more details, see [`login`]. + + Args: + skip_if_logged_in (`bool`, defaults to `True`): + If `True`, do not prompt for token if user is already logged in. + Set to `False` to force re-login. In CLI, use `--force` instead. + """ + try: + import ipywidgets.widgets as widgets # type: ignore + from IPython.display import display # type: ignore + except ImportError: + raise ImportError( + "The `notebook_login` function can only be used in a notebook (Jupyter or" + " Colab) and you need the `ipywidgets` module: `pip install ipywidgets`." + ) + if skip_if_logged_in and get_token() is not None: + logger.info("User is already logged in. Use `hf auth login --force` to force re-login.") + return + + box_layout = widgets.Layout(display="flex", flex_flow="column", align_items="center", width="50%") + + token_widget = widgets.Password(description="Token:") + git_checkbox_widget = widgets.Checkbox(value=True, description="Add token as git credential?") + token_finish_button = widgets.Button(description="Login") + + login_token_widget = widgets.VBox( + [ + widgets.HTML(NOTEBOOK_LOGIN_TOKEN_HTML_START), + token_widget, + git_checkbox_widget, + token_finish_button, + widgets.HTML(NOTEBOOK_LOGIN_TOKEN_HTML_END), + ], + layout=box_layout, + ) + display(login_token_widget) + + # On click events + def login_token_event(t): + """Event handler for the login button.""" + token = token_widget.value + add_to_git_credential = git_checkbox_widget.value + # Erase token and clear value to make sure it's not saved in the notebook. + token_widget.value = "" + # Hide inputs + login_token_widget.children = [widgets.Label("Connecting...")] + try: + with capture_output() as captured: + _login(token, add_to_git_credential=add_to_git_credential) + message = captured.getvalue() + except Exception as error: + message = str(error) + # Print result (success message or error) + login_token_widget.children = [widgets.Label(line) for line in message.split("\n") if line.strip()] + + token_finish_button.on_click(login_token_event) + + +### +# Login private helpers +### + + +def _login( + token: str, + add_to_git_credential: bool, +) -> None: + from .hf_api import whoami # avoid circular import + + if token.startswith("api_org"): + raise ValueError("You must use your personal account token, not an organization token.") + + token_info = whoami(token) + permission = token_info["auth"]["accessToken"]["role"] + logger.info(f"Token is valid (permission: {permission}).") + + token_name = token_info["auth"]["accessToken"]["displayName"] + # Store token locally + _save_token(token=token, token_name=token_name) + # Set active token + _set_active_token(token_name=token_name, add_to_git_credential=add_to_git_credential) + logger.info("Login successful.") + if _get_token_from_environment(): + logger.warning( + "Note: Environment variable`HF_TOKEN` is set and is the current active token independently from the token you've just configured." + ) + else: + logger.info(f"The current active token is: `{token_name}`") + + +def _logout_from_token(token_name: str) -> None: + """Logout from a specific access token. + + Args: + token_name (`str`): + The name of the access token to logout from. + Raises: + [`ValueError`](https://docs.python.org/3/library/exceptions.html#ValueError): + If the access token name is not found. + """ + stored_tokens = get_stored_tokens() + # If there is no access tokens saved or the access token name is not found, do nothing + if not stored_tokens or token_name not in stored_tokens: + return + + token = stored_tokens.pop(token_name) + _save_stored_tokens(stored_tokens) + + if token == _get_token_from_file(): + logger.warning(f"Active token '{token_name}' has been deleted.") + Path(constants.HF_TOKEN_PATH).unlink(missing_ok=True) + + +def _set_active_token( + token_name: str, + add_to_git_credential: bool, +) -> None: + """Set the active access token. + + Args: + token_name (`str`): + The name of the token to set as active. + """ + token = _get_token_by_name(token_name) + if not token: + raise ValueError(f"Token {token_name} not found in {constants.HF_STORED_TOKENS_PATH}") + if add_to_git_credential: + if _is_git_credential_helper_configured(): + set_git_credential(token) + logger.info( + "Your token has been saved in your configured git credential helpers" + + f" ({','.join(list_credential_helpers())})." + ) + else: + logger.warning("Token has not been saved to git credential helper.") + # Write token to HF_TOKEN_PATH + path = Path(constants.HF_TOKEN_PATH) + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text(token) + logger.info(f"Your token has been saved to {constants.HF_TOKEN_PATH}") + + +def _is_git_credential_helper_configured() -> bool: + """Check if a git credential helper is configured. + + Warns user if not the case (except for Google Colab where "store" is set by default + by `huggingface_hub`). + """ + helpers = list_credential_helpers() + if len(helpers) > 0: + return True # Do not warn: at least 1 helper is set + + # Only in Google Colab to avoid the warning message + # See https://github.com/huggingface/huggingface_hub/issues/1043#issuecomment-1247010710 + if is_google_colab(): + _set_store_as_git_credential_helper_globally() + return True # Do not warn: "store" is used by default in Google Colab + + # Otherwise, warn user + print( + ANSI.red( + "Cannot authenticate through git-credential as no helper is defined on your" + " machine.\nYou might have to re-authenticate when pushing to the Hugging" + " Face Hub.\nRun the following command in your terminal in case you want to" + " set the 'store' credential helper as default.\n\ngit config --global" + " credential.helper store\n\nRead" + " https://git-scm.com/book/en/v2/Git-Tools-Credential-Storage for more" + " details." + ) + ) + return False + + +def _set_store_as_git_credential_helper_globally() -> None: + """Set globally the credential.helper to `store`. + + To be used only in Google Colab as we assume the user doesn't care about the git + credential config. It is the only particular case where we don't want to display the + warning message in [`notebook_login()`]. + + Related: + - https://github.com/huggingface/huggingface_hub/issues/1043 + - https://github.com/huggingface/huggingface_hub/issues/1051 + - https://git-scm.com/docs/git-credential-store + """ + try: + run_subprocess("git config --global credential.helper store") + except subprocess.CalledProcessError as exc: + raise OSError(exc.stderr) diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_oauth.py b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_oauth.py new file mode 100644 index 0000000000000000000000000000000000000000..cac82ada87262370031740ea6d7c9234aec44de0 --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_oauth.py @@ -0,0 +1,460 @@ +import datetime +import hashlib +import logging +import os +import time +import urllib.parse +import warnings +from dataclasses import dataclass +from typing import TYPE_CHECKING, Literal + +from . import constants +from .hf_api import whoami +from .utils import experimental, get_token + + +logger = logging.getLogger(__name__) + +if TYPE_CHECKING: + import fastapi + + +@dataclass +class OAuthOrgInfo: + """ + Information about an organization linked to a user logged in with OAuth. + + Attributes: + sub (`str`): + Unique identifier for the org. OpenID Connect field. + name (`str`): + The org's full name. OpenID Connect field. + preferred_username (`str`): + The org's username. OpenID Connect field. + picture (`str`): + The org's profile picture URL. OpenID Connect field. + plan (`str`, *optional*): + The org's plan (e.g., "enterprise", "team"). Hugging Face field. + can_pay (`Optional[bool]`, *optional*): + Whether the org has a payment method set up. Hugging Face field. + role_in_org (`Optional[str]`, *optional*): + The user's role in the org. Hugging Face field. + security_restrictions (`Optional[list[Literal["ip", "token-policy", "mfa", "sso"]]]`, *optional*): + Array of security restrictions that the user hasn't completed for this org. Possible values: "ip", "token-policy", "mfa", "sso". Hugging Face field. + """ + + sub: str + name: str + preferred_username: str + picture: str + plan: str | None = None + can_pay: bool | None = None + role_in_org: str | None = None + security_restrictions: list[Literal["ip", "token-policy", "mfa", "sso"]] | None = None + + +@dataclass +class OAuthUserInfo: + """ + Information about a user logged in with OAuth. + + Attributes: + sub (`str`): + Unique identifier for the user, even in case of rename. OpenID Connect field. + name (`str`): + The user's full name. OpenID Connect field. + preferred_username (`str`): + The user's username. OpenID Connect field. + email_verified (`Optional[bool]`, *optional*): + Indicates if the user's email is verified. OpenID Connect field. + email (`Optional[str]`, *optional*): + The user's email address. OpenID Connect field. + picture (`str`): + The user's profile picture URL. OpenID Connect field. + profile (`str`): + The user's profile URL. OpenID Connect field. + website (`Optional[str]`, *optional*): + The user's website URL. OpenID Connect field. + is_pro (`bool`): + Whether the user is a pro user. Hugging Face field. + can_pay (`Optional[bool]`, *optional*): + Whether the user has a payment method set up. Hugging Face field. + orgs (`Optional[list[OrgInfo]]`, *optional*): + List of organizations the user is part of. Hugging Face field. + """ + + sub: str + name: str + preferred_username: str + email_verified: bool | None + email: str | None + picture: str + profile: str + website: str | None + is_pro: bool + can_pay: bool | None + orgs: list[OAuthOrgInfo] | None + + +@dataclass +class OAuthInfo: + """ + Information about the OAuth login. + + Attributes: + access_token (`str`): + The access token. + access_token_expires_at (`datetime.datetime`): + The expiration date of the access token. + user_info ([`OAuthUserInfo`]): + The user information. + state (`str`, *optional*): + State passed to the OAuth provider in the original request to the OAuth provider. + scope (`str`): + Granted scope. + """ + + access_token: str + access_token_expires_at: datetime.datetime + user_info: OAuthUserInfo + state: str | None + scope: str + + +@experimental +def attach_huggingface_oauth(app: "fastapi.FastAPI", route_prefix: str = "/"): + """ + Add OAuth endpoints to a FastAPI app to enable OAuth login with Hugging Face. + + How to use: + - Call this method on your FastAPI app to add the OAuth endpoints. + - Inside your route handlers, call `parse_huggingface_oauth(request)` to retrieve the OAuth info. + - If user is logged in, an [`OAuthInfo`] object is returned with the user's info. If not, `None` is returned. + - In your app, make sure to add links to `/oauth/huggingface/login` and `/oauth/huggingface/logout` for the user to log in and out. + + Example: + ```py + from huggingface_hub import attach_huggingface_oauth, parse_huggingface_oauth + + # Create a FastAPI app + app = FastAPI() + + # Add OAuth endpoints to the FastAPI app + attach_huggingface_oauth(app) + + # Add a route that greets the user if they are logged in + @app.get("/") + def greet_json(request: Request): + # Retrieve the OAuth info from the request + oauth_info = parse_huggingface_oauth(request) # e.g. OAuthInfo dataclass + if oauth_info is None: + return {"msg": "Not logged in!"} + return {"msg": f"Hello, {oauth_info.user_info.preferred_username}!"} + ``` + """ + # TODO: handle generic case (handling OAuth in a non-Space environment with custom dev values) (low priority) + + # Add SessionMiddleware to the FastAPI app to store the OAuth info in the session. + # Session Middleware requires a secret key to sign the cookies. Let's use a hash + # of the OAuth secret key to make it unique to the Space + updated in case OAuth + # config gets updated. When ran locally, we use an empty string as a secret key. + try: + from starlette.middleware.sessions import SessionMiddleware + except ImportError as e: + raise ImportError( + "Cannot initialize OAuth to due a missing library. Please run `pip install huggingface_hub[oauth]` or add " + "`huggingface_hub[oauth]` to your requirements.txt file in order to install the required dependencies." + ) from e + session_secret = (constants.OAUTH_CLIENT_SECRET or "") + "-v1" + app.add_middleware( + SessionMiddleware, # type: ignore + secret_key=hashlib.sha256(session_secret.encode()).hexdigest(), + same_site="none", + https_only=True, + ) # type: ignore + + # Add OAuth endpoints to the FastAPI app: + # - {route_prefix}/oauth/huggingface/login + # - {route_prefix}/oauth/huggingface/callback + # - {route_prefix}/oauth/huggingface/logout + # If the app is running in a Space, OAuth is enabled normally. + # Otherwise, we mock the endpoints to make the user log in with a fake user profile - without any calls to hf.co. + route_prefix = route_prefix.strip("/") + if os.getenv("SPACE_ID") is not None: + logger.info("OAuth is enabled in the Space. Adding OAuth routes.") + _add_oauth_routes(app, route_prefix=route_prefix) + else: + logger.info("App is not running in a Space. Adding mocked OAuth routes.") + _add_mocked_oauth_routes(app, route_prefix=route_prefix) + + +def parse_huggingface_oauth(request: "fastapi.Request") -> OAuthInfo | None: + """ + Returns the information from a logged-in user as a [`OAuthInfo`] object. + + For flexibility and future-proofing, this method is very lax in its parsing and does not raise errors. + Missing fields are set to `None` without a warning. + + Return `None`, if the user is not logged in (no info in session cookie). + + See [`attach_huggingface_oauth`] for an example on how to use this method. + """ + if "oauth_info" not in request.session: + logger.debug("No OAuth info in session.") + return None + + logger.debug("Parsing OAuth info from session.") + oauth_data = request.session["oauth_info"] + user_data = oauth_data.get("userinfo", {}) + orgs_data = user_data.get("orgs", []) + + orgs = ( + [ + OAuthOrgInfo( + sub=org.get("sub"), + name=org.get("name"), + preferred_username=org.get("preferred_username"), + picture=org.get("picture"), + plan=org.get("plan"), + can_pay=org.get("canPay"), + role_in_org=org.get("roleInOrg"), + security_restrictions=org.get("securityRestrictions"), + ) + for org in orgs_data + ] + if orgs_data + else None + ) + + user_info = OAuthUserInfo( + sub=user_data.get("sub"), + name=user_data.get("name"), + preferred_username=user_data.get("preferred_username"), + email_verified=user_data.get("email_verified"), + email=user_data.get("email"), + picture=user_data.get("picture"), + profile=user_data.get("profile"), + website=user_data.get("website"), + is_pro=user_data.get("isPro"), + can_pay=user_data.get("canPay"), + orgs=orgs, + ) + + return OAuthInfo( + access_token=oauth_data.get("access_token"), + access_token_expires_at=datetime.datetime.fromtimestamp(oauth_data.get("expires_at")), + user_info=user_info, + state=oauth_data.get("state"), + scope=oauth_data.get("scope"), + ) + + +def _add_oauth_routes(app: "fastapi.FastAPI", route_prefix: str) -> None: + """Add OAuth routes to the FastAPI app (login, callback handler and logout).""" + try: + import fastapi + from authlib.integrations.base_client.errors import MismatchingStateError + from authlib.integrations.starlette_client import OAuth + from fastapi.responses import RedirectResponse + except ImportError as e: + raise ImportError( + "Cannot initialize OAuth to due a missing library. Please run `pip install huggingface_hub[oauth]` or add " + "`huggingface_hub[oauth]` to your requirements.txt file." + ) from e + + # Check environment variables + msg = ( + "OAuth is required but '{}' environment variable is not set. Make sure you've enabled OAuth in your Space by" + " setting `hf_oauth: true` in the Space metadata." + ) + if constants.OAUTH_CLIENT_ID is None: + raise ValueError(msg.format("OAUTH_CLIENT_ID")) + if constants.OAUTH_CLIENT_SECRET is None: + raise ValueError(msg.format("OAUTH_CLIENT_SECRET")) + if constants.OAUTH_SCOPES is None: + raise ValueError(msg.format("OAUTH_SCOPES")) + if constants.OPENID_PROVIDER_URL is None: + raise ValueError(msg.format("OPENID_PROVIDER_URL")) + + # Register OAuth server + oauth = OAuth() + oauth.register( + name="huggingface", + client_id=constants.OAUTH_CLIENT_ID, + client_secret=constants.OAUTH_CLIENT_SECRET, + client_kwargs={"scope": constants.OAUTH_SCOPES}, + server_metadata_url=constants.OPENID_PROVIDER_URL + "/.well-known/openid-configuration", + ) + + login_uri, callback_uri, logout_uri = _get_oauth_uris(route_prefix) + + # Register OAuth endpoints + @app.get(login_uri) + async def oauth_login(request: fastapi.Request) -> RedirectResponse: + """Endpoint that redirects to HF OAuth page.""" + redirect_uri = _generate_redirect_uri(request) + return await oauth.huggingface.authorize_redirect(request, redirect_uri) # type: ignore + + @app.get(callback_uri) + async def oauth_redirect_callback(request: fastapi.Request) -> RedirectResponse: + """Endpoint that handles the OAuth callback.""" + try: + oauth_info = await oauth.huggingface.authorize_access_token(request) # type: ignore + except MismatchingStateError: + # Parse query params + nb_redirects = int(request.query_params.get("_nb_redirects", 0)) + target_url = request.query_params.get("_target_url") + + # Build redirect URI with the same query params as before and bump nb_redirects count + query_params: dict[str, int | str] = {"_nb_redirects": nb_redirects + 1} + if target_url: + query_params["_target_url"] = target_url + + redirect_uri = f"{login_uri}?{urllib.parse.urlencode(query_params)}" + + # If the user is redirected more than 3 times, it is very likely that the cookie is not working properly. + # (e.g. browser is blocking third-party cookies in iframe). In this case, redirect the user in the + # non-iframe view. + if nb_redirects > constants.OAUTH_MAX_REDIRECTS: + host = os.environ.get("SPACE_HOST") + if host is None: # cannot happen in a Space + raise RuntimeError( + "App is not running in a Space (SPACE_HOST environment variable is not set). Cannot redirect to non-iframe view." + ) from None + host_url = "https://" + host.rstrip("/") + return RedirectResponse(host_url + redirect_uri) + + # Redirect the user to the login page again + return RedirectResponse(redirect_uri) + + # OAuth login worked => store the user info in the session and redirect + logger.debug("Successfully logged in with OAuth. Storing user info in session.") + request.session["oauth_info"] = oauth_info + return RedirectResponse(_get_redirect_target(request)) + + @app.get(logout_uri) + async def oauth_logout(request: fastapi.Request) -> RedirectResponse: + """Endpoint that logs out the user (e.g. delete info from cookie session).""" + logger.debug("Logged out with OAuth. Removing user info from session.") + request.session.pop("oauth_info", None) + return RedirectResponse(_get_redirect_target(request)) + + +def _add_mocked_oauth_routes(app: "fastapi.FastAPI", route_prefix: str = "/") -> None: + """Add fake oauth routes if app is run locally and OAuth is enabled. + + Using OAuth will have the same behavior as in a Space but instead of authenticating with HF, a mocked user profile + is added to the session. + """ + try: + import fastapi + from fastapi.responses import RedirectResponse + from starlette.datastructures import URL + except ImportError as e: + raise ImportError( + "Cannot initialize OAuth to due a missing library. Please run `pip install huggingface_hub[oauth]` or add " + "`huggingface_hub[oauth]` to your requirements.txt file." + ) from e + + warnings.warn( + "OAuth is not supported outside of a Space environment. To help you debug your app locally, the oauth endpoints" + " are mocked to return your profile and token. To make it work, your machine must be logged in to Huggingface." + ) + mocked_oauth_info = _get_mocked_oauth_info() + + login_uri, callback_uri, logout_uri = _get_oauth_uris(route_prefix) + + # Define OAuth routes + @app.get(login_uri) + async def oauth_login(request: fastapi.Request) -> RedirectResponse: + """Fake endpoint that redirects to HF OAuth page.""" + # Define target (where to redirect after login) + redirect_uri = _generate_redirect_uri(request) + return RedirectResponse(callback_uri + "?" + urllib.parse.urlencode({"_target_url": redirect_uri})) + + @app.get(callback_uri) + async def oauth_redirect_callback(request: fastapi.Request) -> RedirectResponse: + """Endpoint that handles the OAuth callback.""" + request.session["oauth_info"] = mocked_oauth_info + return RedirectResponse(_get_redirect_target(request)) + + @app.get(logout_uri) + async def oauth_logout(request: fastapi.Request) -> RedirectResponse: + """Endpoint that logs out the user (e.g. delete cookie session).""" + request.session.pop("oauth_info", None) + logout_url = URL("/").include_query_params(**request.query_params) + return RedirectResponse(url=logout_url, status_code=302) # see https://github.com/gradio-app/gradio/pull/9659 + + +def _generate_redirect_uri(request: "fastapi.Request") -> str: + if "_target_url" in request.query_params: + # if `_target_url` already in query params => respect it + target = request.query_params["_target_url"] + else: + # otherwise => keep query params + target = "/?" + urllib.parse.urlencode(request.query_params) + + redirect_uri = request.url_for("oauth_redirect_callback").include_query_params(_target_url=target) + redirect_uri_as_str = str(redirect_uri) + if redirect_uri.netloc.endswith(".hf.space"): + # In Space, FastAPI redirect as http but we want https + redirect_uri_as_str = redirect_uri_as_str.replace("http://", "https://") + return redirect_uri_as_str + + +def _get_redirect_target(request: "fastapi.Request", default_target: str = "/") -> str: + return request.query_params.get("_target_url", default_target) + + +def _get_mocked_oauth_info() -> dict: + token = get_token() + if token is None: + raise ValueError( + "Your machine must be logged in to HF to debug an OAuth app locally. Please" + " run `hf auth login` or set `HF_TOKEN` as environment variable " + "with one of your access token. You can generate a new token in your " + "settings page (https://huggingface.co/settings/tokens)." + ) + + user = whoami() + if user["type"] != "user": + raise ValueError( + "Your machine is not logged in with a personal account. Please use a " + "personal access token. You can generate a new token in your settings page" + " (https://huggingface.co/settings/tokens)." + ) + + return { + "access_token": token, + "token_type": "bearer", + "expires_in": 8 * 60 * 60, # 8 hours + "id_token": "FOOBAR", + "scope": "openid profile", + "refresh_token": "hf_oauth__refresh_token", + "expires_at": int(time.time()) + 8 * 60 * 60, # 8 hours + "userinfo": { + "sub": "0123456789", + "name": user["fullname"], + "preferred_username": user["name"], + "profile": f"https://huggingface.co/{user['name']}", + "picture": user["avatarUrl"], + "website": "", + "aud": "00000000-0000-0000-0000-000000000000", + "auth_time": 1691672844, + "nonce": "aaaaaaaaaaaaaaaaaaa", + "iat": 1691672844, + "exp": 1691676444, + "iss": "https://huggingface.co", + }, + } + + +def _get_oauth_uris(route_prefix: str = "/") -> tuple[str, str, str]: + route_prefix = route_prefix.strip("/") + if route_prefix: + route_prefix = f"/{route_prefix}" + return ( + f"{route_prefix}/oauth/huggingface/login", + f"{route_prefix}/oauth/huggingface/callback", + f"{route_prefix}/oauth/huggingface/logout", + ) diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_snapshot_download.py b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_snapshot_download.py new file mode 100644 index 0000000000000000000000000000000000000000..bd03124729be17694db9a6d5be610584b584d881 --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_snapshot_download.py @@ -0,0 +1,471 @@ +import os +from collections.abc import Iterable +from pathlib import Path +from typing import Literal, overload + +import httpx +from tqdm.auto import tqdm as base_tqdm +from tqdm.contrib.concurrent import thread_map + +from . import constants +from .errors import ( + DryRunError, + GatedRepoError, + HfHubHTTPError, + LocalEntryNotFoundError, + RepositoryNotFoundError, + RevisionNotFoundError, +) +from .file_download import REGEX_COMMIT_HASH, DryRunFileInfo, hf_hub_download, repo_folder_name +from .hf_api import DatasetInfo, HfApi, KernelInfo, ModelInfo, RepoFile, SpaceInfo +from .utils import OfflineModeIsEnabled, filter_repo_objects, logging, validate_hf_hub_args +from .utils.tqdm import _create_progress_bar +from .utils.tqdm import tqdm as hf_tqdm + + +logger = logging.get_logger(__name__) + +LARGE_REPO_THRESHOLD = 1000 # After this limit, we don't consider `repo_info.siblings` to be reliable enough + + +@overload +def snapshot_download( + repo_id: str, + *, + repo_type: str | None = None, + revision: str | None = None, + cache_dir: str | Path | None = None, + local_dir: str | Path | None = None, + library_name: str | None = None, + library_version: str | None = None, + user_agent: dict | str | None = None, + etag_timeout: float = constants.DEFAULT_ETAG_TIMEOUT, + force_download: bool = False, + token: bool | str | None = None, + local_files_only: bool = False, + allow_patterns: list[str] | str | None = None, + ignore_patterns: list[str] | str | None = None, + max_workers: int = 8, + tqdm_class: type[base_tqdm] | None = None, + headers: dict[str, str] | None = None, + endpoint: str | None = None, + dry_run: Literal[False] = False, +) -> str: ... + + +@overload +def snapshot_download( + repo_id: str, + *, + repo_type: str | None = None, + revision: str | None = None, + cache_dir: str | Path | None = None, + local_dir: str | Path | None = None, + library_name: str | None = None, + library_version: str | None = None, + user_agent: dict | str | None = None, + etag_timeout: float = constants.DEFAULT_ETAG_TIMEOUT, + force_download: bool = False, + token: bool | str | None = None, + local_files_only: bool = False, + allow_patterns: list[str] | str | None = None, + ignore_patterns: list[str] | str | None = None, + max_workers: int = 8, + tqdm_class: type[base_tqdm] | None = None, + headers: dict[str, str] | None = None, + endpoint: str | None = None, + dry_run: Literal[True] = True, +) -> list[DryRunFileInfo]: ... + + +@overload +def snapshot_download( + repo_id: str, + *, + repo_type: str | None = None, + revision: str | None = None, + cache_dir: str | Path | None = None, + local_dir: str | Path | None = None, + library_name: str | None = None, + library_version: str | None = None, + user_agent: dict | str | None = None, + etag_timeout: float = constants.DEFAULT_ETAG_TIMEOUT, + force_download: bool = False, + token: bool | str | None = None, + local_files_only: bool = False, + allow_patterns: list[str] | str | None = None, + ignore_patterns: list[str] | str | None = None, + max_workers: int = 8, + tqdm_class: type[base_tqdm] | None = None, + headers: dict[str, str] | None = None, + endpoint: str | None = None, + dry_run: bool = False, +) -> str | list[DryRunFileInfo]: ... + + +@validate_hf_hub_args +def snapshot_download( + repo_id: str, + *, + repo_type: str | None = None, + revision: str | None = None, + cache_dir: str | Path | None = None, + local_dir: str | Path | None = None, + library_name: str | None = None, + library_version: str | None = None, + user_agent: dict | str | None = None, + etag_timeout: float = constants.DEFAULT_ETAG_TIMEOUT, + force_download: bool = False, + token: bool | str | None = None, + local_files_only: bool = False, + allow_patterns: list[str] | str | None = None, + ignore_patterns: list[str] | str | None = None, + max_workers: int = 8, + tqdm_class: type[base_tqdm] | None = None, + headers: dict[str, str] | None = None, + endpoint: str | None = None, + dry_run: bool = False, +) -> str | list[DryRunFileInfo]: + """Download repo files. + + Download a whole snapshot of a repo's files at the specified revision. This is useful when you want all files from + a repo, because you don't know which ones you will need a priori. All files are nested inside a folder in order + to keep their actual filename relative to that folder. You can also filter which files to download using + `allow_patterns` and `ignore_patterns`. + + If `local_dir` is provided, the file structure from the repo will be replicated in this location. When using this + option, the `cache_dir` will not be used and a `.cache/huggingface/` folder will be created at the root of `local_dir` + to store some metadata related to the downloaded files. While this mechanism is not as robust as the main + cache-system, it's optimized for regularly pulling the latest version of a repository. + + An alternative would be to clone the repo but this requires git and git-lfs to be installed and properly + configured. It is also not possible to filter which files to download when cloning a repository using git. + + Args: + repo_id (`str`): + A user or an organization name and a repo name separated by a `/`. + repo_type (`str`, *optional*): + Set to `"dataset"`, `"space"` or `"kernel"` if downloading from a dataset, space or kernel repo, + `None` or `"model"` if downloading from a model. Default is `None`. + revision (`str`, *optional*): + An optional Git revision id which can be a branch name, a tag, or a + commit hash. + cache_dir (`str`, `Path`, *optional*): + Path to the folder where cached files are stored. + local_dir (`str` or `Path`, *optional*): + If provided, the downloaded files will be placed under this directory. + library_name (`str`, *optional*): + The name of the library to which the object corresponds. + library_version (`str`, *optional*): + The version of the library. + user_agent (`str`, `dict`, *optional*): + The user-agent info in the form of a dictionary or a string. + etag_timeout (`float`, *optional*, defaults to `10`): + When fetching ETag, how many seconds to wait for the server to send + data before giving up which is passed to `httpx.request`. + force_download (`bool`, *optional*, defaults to `False`): + Whether the file should be downloaded even if it already exists in the local cache. + token (`str`, `bool`, *optional*): + A token to be used for the download. + - If `True`, the token is read from the HuggingFace config + folder. + - If a string, it's used as the authentication token. + headers (`dict`, *optional*): + Additional headers to include in the request. Those headers take precedence over the others. + local_files_only (`bool`, *optional*, defaults to `False`): + If `True`, avoid downloading the file and return the path to the + local cached file if it exists. + allow_patterns (`list[str]` or `str`, *optional*): + If provided, only files matching at least one pattern are downloaded. + ignore_patterns (`list[str]` or `str`, *optional*): + If provided, files matching any of the patterns are not downloaded. + max_workers (`int`, *optional*): + Number of concurrent threads to download files (1 thread = 1 file download). + Defaults to 8. + tqdm_class (`tqdm`, *optional*): + If provided, overwrites the default behavior for the progress bar. Passed + argument must inherit from `tqdm.auto.tqdm` or at least mimic its behavior. + Note that the `tqdm_class` is not passed to each individual download. + Defaults to the custom HF progress bar that can be disabled by setting + `HF_HUB_DISABLE_PROGRESS_BARS` environment variable. + dry_run (`bool`, *optional*, defaults to `False`): + If `True`, perform a dry run without actually downloading the files. Returns a list of + [`DryRunFileInfo`] objects containing information about what would be downloaded. + + Returns: + `str` or list of [`DryRunFileInfo`]: + - If `dry_run=False`: Local snapshot path. + - If `dry_run=True`: A list of [`DryRunFileInfo`] objects containing download information. + + Raises: + [`~utils.RepositoryNotFoundError`] + If the repository to download from cannot be found. This may be because it doesn't exist, + or because it is set to `private` and you do not have access. + [`~utils.RevisionNotFoundError`] + If the revision to download from cannot be found. + [`EnvironmentError`](https://docs.python.org/3/library/exceptions.html#EnvironmentError) + If `token=True` and the token cannot be found. + [`OSError`](https://docs.python.org/3/library/exceptions.html#OSError) if + ETag cannot be determined. + [`ValueError`](https://docs.python.org/3/library/exceptions.html#ValueError) + if some parameter value is invalid. + """ + if cache_dir is None: + cache_dir = constants.HF_HUB_CACHE + if revision is None: + revision = constants.DEFAULT_REVISION + if isinstance(cache_dir, Path): + cache_dir = str(cache_dir) + + if repo_type is None: + repo_type = "model" + if repo_type not in constants.REPO_TYPES_WITH_KERNEL: + raise ValueError( + f"Invalid repo type: {repo_type}. Accepted repo types are: {str(constants.REPO_TYPES_WITH_KERNEL)}" + ) + + storage_folder = os.path.join(cache_dir, repo_folder_name(repo_id=repo_id, repo_type=repo_type)) + + api = HfApi( + library_name=library_name, + library_version=library_version, + user_agent=user_agent, + endpoint=endpoint, + headers=headers, + token=token, + ) + + repo_info: ModelInfo | DatasetInfo | SpaceInfo | KernelInfo | None = None + api_call_error: Exception | None = None + if not local_files_only: + # try/except logic to handle different errors => taken from `hf_hub_download` + try: + # if we have internet connection we want to list files to download + repo_info = api.repo_info(repo_id=repo_id, repo_type=repo_type, revision=revision) + except httpx.ProxyError: + # Actually raise on proxy error + raise + except (httpx.ConnectError, httpx.TimeoutException, OfflineModeIsEnabled) as error: + # Internet connection is down + # => will try to use local files only + api_call_error = error + pass + except RevisionNotFoundError: + # The repo was found but the revision doesn't exist on the Hub (never existed or got deleted) + raise + except HfHubHTTPError as error: + # Multiple reasons for an http error: + # - Repository is private and invalid/missing token sent + # - Repository is gated and invalid/missing token sent + # - Hub is down (error 500 or 504) + # => let's switch to 'local_files_only=True' to check if the files are already cached. + # (if it's not the case, the error will be re-raised) + api_call_error = error + pass + + # At this stage, if `repo_info` is None it means either: + # - internet connection is down + # - internet connection is deactivated (local_files_only=True or HF_HUB_OFFLINE=True) + # - repo is private/gated and invalid/missing token sent + # - Hub is down + # => let's look if we can find the appropriate folder in the cache: + # - if the specified revision is a commit hash, look inside "snapshots". + # - f the specified revision is a branch or tag, look inside "refs". + # => if local_dir is not None, we will return the path to the local folder if it exists. + if repo_info is None: + if dry_run: + raise DryRunError( + "Dry run cannot be performed as the repository cannot be accessed. Please check your internet connection or authentication token." + ) from api_call_error + + # Try to get which commit hash corresponds to the specified revision + commit_hash = None + if REGEX_COMMIT_HASH.match(revision): + commit_hash = revision + else: + ref_path = os.path.join(storage_folder, "refs", revision) + if os.path.exists(ref_path): + # retrieve commit_hash from refs file + with open(ref_path) as f: + commit_hash = f.read() + + # Try to locate snapshot folder for this commit hash + if commit_hash is not None and local_dir is None: + snapshot_folder = os.path.join(storage_folder, "snapshots", commit_hash) + if os.path.exists(snapshot_folder): + # Snapshot folder exists => let's return it + # (but we can't check if all the files are actually there) + return snapshot_folder + + # If local_dir is not None, return it if it exists and is not empty + if local_dir is not None: + local_dir = Path(local_dir) + if local_dir.is_dir() and any(local_dir.iterdir()): + logger.warning( + f"Returning existing local_dir `{local_dir}` as remote repo cannot be accessed in `snapshot_download` ({api_call_error})." + ) + return str(local_dir.resolve()) + # If we couldn't find the appropriate folder on disk, raise an error. + if local_files_only: + raise LocalEntryNotFoundError( + "Cannot find an appropriate cached snapshot folder for the specified revision on the local disk and " + "outgoing traffic has been disabled. To enable repo look-ups and downloads online, pass " + "'local_files_only=False' as input." + ) + elif isinstance(api_call_error, OfflineModeIsEnabled): + raise LocalEntryNotFoundError( + "Cannot find an appropriate cached snapshot folder for the specified revision on the local disk and " + "outgoing traffic has been disabled. To enable repo look-ups and downloads online, set " + "'HF_HUB_OFFLINE=0' as environment variable." + ) from api_call_error + elif isinstance(api_call_error, (RepositoryNotFoundError, GatedRepoError)) or ( + isinstance(api_call_error, HfHubHTTPError) and api_call_error.response.status_code == 401 + ): + # Repo not found, gated, or specific authentication error => let's raise the actual error + raise api_call_error + else: + # Otherwise: most likely a connection issue or Hub downtime => let's warn the user + raise LocalEntryNotFoundError( + f"Got: {api_call_error.__class__.__name__}: {api_call_error}" + "\nAn error happened while trying to locate the files on the Hub and we cannot find the appropriate" + " snapshot folder for the specified revision on the local disk. Please check your internet connection" + " and try again." + ) from api_call_error + + # At this stage, internet connection is up and running + # => let's download the files! + assert repo_info.sha is not None, "Repo info returned from server must have a revision sha." + + # Corner case: on very large repos, the siblings list in `repo_info` might not contain all files. + # In that case, we need to use the `list_repo_tree` method to prevent caching issues. + # Note: kernel repos don't expose siblings in their info response, so we always fall back to `list_repo_tree`. + siblings = getattr(repo_info, "siblings", None) + repo_files: Iterable[str] = [f.rfilename for f in siblings] if siblings is not None else [] + unreliable_nb_files = siblings is None or len(siblings) == 0 or len(siblings) > LARGE_REPO_THRESHOLD + if unreliable_nb_files: + logger.info( + "Number of files in the repo is unreliable. Using `list_repo_tree` to ensure all files are listed." + ) + repo_files = ( + f.rfilename + for f in api.list_repo_tree(repo_id=repo_id, recursive=True, revision=revision, repo_type=repo_type) + if isinstance(f, RepoFile) + ) + + filtered_repo_files: Iterable[str] = filter_repo_objects( + items=repo_files, + allow_patterns=allow_patterns, + ignore_patterns=ignore_patterns, + ) + + if not unreliable_nb_files: + filtered_repo_files = list(filtered_repo_files) + tqdm_desc = f"Fetching {len(filtered_repo_files)} files" + else: + tqdm_desc = "Fetching ... files" + if dry_run: + tqdm_desc = "[dry-run] " + tqdm_desc + + commit_hash = repo_info.sha + snapshot_folder = os.path.join(storage_folder, "snapshots", commit_hash) + # if passed revision is not identical to commit_hash + # then revision has to be a branch name or tag name. + # In that case store a ref. + if revision != commit_hash: + ref_path = os.path.join(storage_folder, "refs", revision) + try: + os.makedirs(os.path.dirname(ref_path), exist_ok=True) + with open(ref_path, "w") as f: + f.write(commit_hash) + except OSError as e: + logger.warning(f"Ignored error while writing commit hash to {ref_path}: {e}.") + + results: list[str | DryRunFileInfo] = [] + + # User can use its own tqdm class or the default one from `huggingface_hub.utils` + tqdm_class = tqdm_class or hf_tqdm + + # Create a progress bar for the bytes downloaded + # This progress bar is shared across threads/files and gets updated each time we fetch + # metadata for a file. + bytes_progress = _create_progress_bar( + cls=tqdm_class, + log_level=logger.getEffectiveLevel(), + name="huggingface_hub.snapshot_download", + desc="Downloading (incomplete total...)", + total=0, + initial=0, + unit="B", + unit_scale=True, + ) + + class _AggregatedTqdm: + """Fake tqdm object to aggregate progress into the parent `bytes_progress` bar. + + In practice the `_AggregatedTqdm` object won't be displayed, it's just used to update + the `bytes_progress` bar from each thread/file download. + """ + + def __init__(self, *args, **kwargs): + # Adjust the total of the parent progress bar + total = kwargs.pop("total", None) + if total is not None: + bytes_progress.total += total + bytes_progress.refresh() + + # Adjust initial of the parent progress bar + initial = kwargs.pop("initial", 0) + if initial: + bytes_progress.update(initial) + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_value, traceback): + pass + + def update(self, n: int | float | None = 1) -> None: + bytes_progress.update(n) + + # we pass the commit_hash to hf_hub_download + # so no network call happens if we already + # have the file locally. + def _inner_hf_hub_download(repo_file: str) -> None: + results.append( + hf_hub_download( # type: ignore + repo_id, + filename=repo_file, + repo_type=repo_type, + revision=commit_hash, + endpoint=endpoint, + cache_dir=cache_dir, + local_dir=local_dir, + library_name=library_name, + library_version=library_version, + user_agent=user_agent, + etag_timeout=etag_timeout, + force_download=force_download, + token=token, + headers=headers, + tqdm_class=_AggregatedTqdm, # type: ignore + dry_run=dry_run, + ) + ) + + thread_map( + _inner_hf_hub_download, + filtered_repo_files, + desc=tqdm_desc, + max_workers=max_workers, + tqdm_class=tqdm_class, + ) + + bytes_progress.set_description("Download complete") + + if dry_run: + assert all(isinstance(r, DryRunFileInfo) for r in results) + return results # type: ignore + + if local_dir is not None: + return str(os.path.realpath(local_dir)) + return snapshot_folder diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_space_api.py b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_space_api.py new file mode 100644 index 0000000000000000000000000000000000000000..391ec7e5b996cf6ab42b9b4f4790d0c5322b48a9 --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_space_api.py @@ -0,0 +1,352 @@ +# Copyright 2019-present, the HuggingFace Inc. team. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from dataclasses import dataclass +from datetime import datetime +from enum import Enum +from typing import Literal + +from huggingface_hub.utils import parse_datetime + + +class SpaceStage(str, Enum): + """ + Enumeration of possible stage of a Space on the Hub. + + Value can be compared to a string: + ```py + assert SpaceStage.BUILDING == "BUILDING" + ``` + + Taken from https://github.com/huggingface/moon-landing/blob/main/server/repo_types/SpaceInfo.ts#L61 (private url). + """ + + # Copied from moon-landing > server > repo_types > SpaceInfo.ts (private repo) + NO_APP_FILE = "NO_APP_FILE" + CONFIG_ERROR = "CONFIG_ERROR" + BUILDING = "BUILDING" + BUILD_ERROR = "BUILD_ERROR" + RUNNING = "RUNNING" + RUNNING_BUILDING = "RUNNING_BUILDING" + RUNTIME_ERROR = "RUNTIME_ERROR" + DELETING = "DELETING" + STOPPED = "STOPPED" + PAUSED = "PAUSED" + APP_STARTING = "APP_STARTING" + RUNNING_APP_STARTING = "RUNNING_APP_STARTING" + + +class SpaceHardware(str, Enum): + """ + Enumeration of hardwares available to run your Space on the Hub. + + Value can be compared to a string: + ```py + assert SpaceHardware.CPU_BASIC == "cpu-basic" + ``` + + Taken from https://github.com/huggingface-internal/moon-landing/blob/main/server/repo_types/SpaceHardwareFlavor.ts (private url). + """ + + # CPU + CPU_BASIC = "cpu-basic" + CPU_UPGRADE = "cpu-upgrade" + CPU_PERFORMANCE = "cpu-performance" + CPU_XL = "cpu-xl" + SPRX8 = "sprx8" + + # ZeroGPU + ZERO_A10G = "zero-a10g" + + # GPU + T4_SMALL = "t4-small" + T4_MEDIUM = "t4-medium" + L4X1 = "l4x1" + L4X4 = "l4x4" + L40SX1 = "l40sx1" + L40SX4 = "l40sx4" + L40SX8 = "l40sx8" + A10G_SMALL = "a10g-small" + A10G_LARGE = "a10g-large" + A10G_LARGEX2 = "a10g-largex2" + A10G_LARGEX4 = "a10g-largex4" + A100_LARGE = "a100-large" + A100X4 = "a100x4" + A100X8 = "a100x8" + H200 = "h200" + H200X2 = "h200x2" + H200X4 = "h200x4" + H200X8 = "h200x8" + + # Neuron + INF2X6 = "inf2x6" + + +class SpaceStorage(str, Enum): + """ + Enumeration of persistent storage available for your Space on the Hub. + + Value can be compared to a string: + ```py + assert SpaceStorage.SMALL == "small" + ``` + + Taken from https://github.com/huggingface/moon-landing/blob/main/server/repo_types/SpaceHardwareFlavor.ts#L24 (private url). + """ + + SMALL = "small" + MEDIUM = "medium" + LARGE = "large" + + +@dataclass +class Volume: + """ + Describes a volume to mount in a Space or Job container. + + Args: + type (`str`): + Type of volume: `"bucket"`, `"model"`, `"dataset"`, or `"space"`. + source (`str`): + Source identifier, e.g. `"username/my-bucket"` or `"username/my-model"`. + mount_path (`str`): + Mount path inside the container, e.g. `"/data"`. Must start with `/`. + revision (`str` or `None`): + Git revision (only for repos, defaults to `"main"`). + read_only (`bool` or `None`): + Read-only mount. Forced `True` for repos, defaults to `False` for buckets. + path (`str` or `None`): + Subfolder prefix inside the bucket/repo to mount, e.g. `"path/to/dir"`. + """ + + type: Literal["bucket", "model", "dataset", "space"] + source: str + mount_path: str + revision: str | None = None + read_only: bool | None = None + path: str | None = None + + def __init__(self, **kwargs) -> None: + self.type = kwargs.get("type", "model") + self.source = kwargs["source"] + mount_path = kwargs.get("mountPath") + self.mount_path = mount_path if mount_path is not None else kwargs["mount_path"] + self.revision = kwargs.get("revision") + read_only = kwargs.get("readOnly") + self.read_only = read_only if read_only is not None else kwargs.get("read_only") + self.path = kwargs.get("path") + + def to_dict(self) -> dict: + """Serialize to the JSON payload expected by the Hub API.""" + data: dict = { + "type": self.type, + "source": self.source, + "mountPath": self.mount_path, + } + if self.revision is not None: + data["revision"] = self.revision + if self.read_only is not None: + data["readOnly"] = self.read_only + if self.path is not None: + data["path"] = self.path + return data + + def to_hf_handle(self) -> str: + """Return the volume as an HF handle in the format expected by the CLI.""" + path = f"/{self.path}" if self.path else "" + revision = f"@{self.revision}" if self.revision else "" + ro = {True: ":ro", False: ":rw", None: ""}.get(self.read_only, "") + return f"hf://{self.type}s/{self.source}{revision}{path}:{self.mount_path}{ro}" + + +@dataclass +class SpaceHotReloading: + status: Literal["created", "canceled"] + replica_statuses: list[tuple[str, str | None]] # See _hot_reloading_types.ApiCreateReloadResponse.res.status + raw: dict + + def __init__(self, data: dict) -> None: + self.status = data["status"] + self.replica_statuses = data["replicaStatuses"] + self.raw = data + + +@dataclass +class SpaceRuntime: + """ + Contains information about the current runtime of a Space. + + Args: + stage (`str`): + Current stage of the space. Example: RUNNING. + hardware (`str` or `None`): + Current hardware of the space. Example: "cpu-basic". Can be `None` if Space + is `BUILDING` for the first time. + requested_hardware (`str` or `None`): + Requested hardware. Can be different from `hardware` especially if the request + has just been made. Example: "t4-medium". Can be `None` if no hardware has + been requested yet. + sleep_time (`int` or `None`): + Number of seconds the Space will be kept alive after the last request. By default (if value is `None`), the + Space will never go to sleep if it's running on an upgraded hardware, while it will go to sleep after 48 + hours on a free 'cpu-basic' hardware. For more details, see https://huggingface.co/docs/hub/spaces-gpus#sleep-time. + volumes (`list[Volume]` or `None`): + List of volumes mounted in the Space. Each volume is a [`Volume`] object describing its type, source, + mount path, and optional settings. `None` if no volumes are attached. + raw (`dict`): + Raw response from the server. Contains more information about the Space + runtime like number of replicas, number of cpu, memory size,... + """ + + stage: SpaceStage + hardware: SpaceHardware | None + requested_hardware: SpaceHardware | None + sleep_time: int | None + storage: SpaceStorage | None + hot_reloading: SpaceHotReloading | None + volumes: list[Volume] | None + raw: dict + + def __init__(self, data: dict) -> None: + self.stage = data["stage"] + self.hardware = data.get("hardware", {}).get("current") + self.requested_hardware = data.get("hardware", {}).get("requested") + self.sleep_time = data.get("gcTimeout") + self.storage = data.get("storage") + self.hot_reloading = SpaceHotReloading(raw_hr) if (raw_hr := data.get("hotReloading")) is not None else None + raw_volumes = data.get("volumes") + self.volumes = [Volume(**v) for v in raw_volumes] if raw_volumes is not None else None + self.raw = data + + +@dataclass +class SpaceSecret: + """ + Contains information about a secret of a Space. + + Secret values are write-only and cannot be read back. Only the key, description, + and last update time are returned by the API. + + Args: + key (`str`): + Secret key. Example: `"GITHUB_API_KEY"` + description (`str` or None): + Description of the secret. Example: `"Github API key to access the Github API"`. + updated_at (`datetime` or None): + datetime of the last update of the secret (if the secret has been updated at least once). + """ + + key: str + description: str | None + updated_at: datetime | None + + def __init__(self, key: str, values: dict) -> None: + self.key = key + self.description = values.get("description") + updated_at = values.get("updatedAt") + self.updated_at = parse_datetime(updated_at) if updated_at is not None else None + + +@dataclass +class SpaceVariable: + """ + Contains information about the current variables of a Space. + + Args: + key (`str`): + Variable key. Example: `"MODEL_REPO_ID"` + value (`str`): + Variable value. Example: `"the_model_repo_id"`. + description (`str` or None): + Description of the variable. Example: `"Model Repo ID of the implemented model"`. + updatedAt (`datetime` or None): + datetime of the last update of the variable (if the variable has been updated at least once). + """ + + key: str + value: str + description: str | None + updated_at: datetime | None + + def __init__(self, key: str, values: dict) -> None: + self.key = key + self.value = values["value"] + self.description = values.get("description") + updated_at = values.get("updatedAt") + self.updated_at = parse_datetime(updated_at) if updated_at is not None else None + + +@dataclass +class SpaceSearchResult: + """A single result from the Spaces semantic search API. + + Returned by [`HfApi.search_spaces`]. + + Attributes: + id (`str`): + ID of the Space (e.g. `"username/repo-name"`). + author (`str`): + Author of the Space. + title (`str`): + Display title of the Space. + emoji (`str` or `None`): + Emoji icon of the Space. + sdk (`str` or `None`): + SDK used by the Space (e.g. `"gradio"`, `"docker"`, `"static"`). + likes (`int`): + Number of likes. + private (`bool`): + Whether the Space is private. + tags (`list[str]` or `None`): + List of tags. + runtime ([`SpaceRuntime`] or `None`): + Runtime information (stage, hardware, etc.). + ai_short_description (`str` or `None`): + AI-generated short description. + ai_category (`str` or `None`): + AI-generated category (e.g. `"Image Generation"`). + semantic_relevancy_score (`float` or `None`): + Semantic relevancy score (0-1) relative to the search query. + trending_score (`int` or `None`): + Trending score. + """ + + id: str + author: str + title: str + emoji: str | None + sdk: str | None + likes: int + private: bool + tags: list[str] | None + runtime: SpaceRuntime | None + ai_short_description: str | None + ai_category: str | None + semantic_relevancy_score: float | None + trending_score: int | None + + def __init__(self, data: dict) -> None: + runtime = data.get("runtime") + self.id = data["id"] + self.author = data.get("author", "") + self.title = data.get("title", "") + self.emoji = data.get("emoji") + self.sdk = data.get("sdk") + self.likes = data.get("likes", 0) + self.private = data.get("private", False) + self.tags = data.get("tags") + self.runtime = SpaceRuntime(runtime) if runtime else None + self.ai_short_description = data.get("ai_short_description") + self.ai_category = data.get("ai_category") + self.semantic_relevancy_score = data.get("semanticRelevancyScore") + self.trending_score = data.get("trendingScore") diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_tensorboard_logger.py b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_tensorboard_logger.py new file mode 100644 index 0000000000000000000000000000000000000000..c6a0d222990e25297feaa72c846b94212e0ebcfc --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_tensorboard_logger.py @@ -0,0 +1,189 @@ +# Copyright 2023 The HuggingFace Team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Contains a logger to push training logs to the Hub, using Tensorboard.""" + +from pathlib import Path + +from ._commit_scheduler import CommitScheduler +from .errors import EntryNotFoundError +from .repocard import ModelCard +from .utils import experimental + + +# Depending on user's setup, SummaryWriter can come either from 'tensorboardX' +# or from 'torch.utils.tensorboard'. Both are compatible so let's try to load +# from either of them. +try: + from tensorboardX import SummaryWriter as _RuntimeSummaryWriter + + is_summary_writer_available = True +except ImportError: + try: + from torch.utils.tensorboard import SummaryWriter as _RuntimeSummaryWriter + + is_summary_writer_available = True + except ImportError: + # Dummy class to avoid failing at import. Will raise on instance creation. + class _DummySummaryWriter: + pass + + _RuntimeSummaryWriter = _DummySummaryWriter # type: ignore[assignment] # ty: ignore[conflicting-declarations] + is_summary_writer_available = False + + +class HFSummaryWriter(_RuntimeSummaryWriter): + """ + Wrapper around the tensorboard's `SummaryWriter` to push training logs to the Hub. + + Data is logged locally and then pushed to the Hub asynchronously. Pushing data to the Hub is done in a separate + thread to avoid blocking the training script. In particular, if the upload fails for any reason (e.g. a connection + issue), the main script will not be interrupted. Data is automatically pushed to the Hub every `commit_every` + minutes (default to every 5 minutes). + + > [!WARNING] + > `HFSummaryWriter` is experimental. Its API is subject to change in the future without prior notice. + + Args: + repo_id (`str`): + The id of the repo to which the logs will be pushed. + logdir (`str`, *optional*): + The directory where the logs will be written. If not specified, a local directory will be created by the + underlying `SummaryWriter` object. + commit_every (`int` or `float`, *optional*): + The frequency (in minutes) at which the logs will be pushed to the Hub. Defaults to 5 minutes. + squash_history (`bool`, *optional*): + Whether to squash the history of the repo after each commit. Defaults to `False`. Squashing commits is + useful to avoid degraded performances on the repo when it grows too large. + repo_type (`str`, *optional*): + The type of the repo to which the logs will be pushed. Defaults to "model". + repo_revision (`str`, *optional*): + The revision of the repo to which the logs will be pushed. Defaults to "main". + repo_private (`bool`, *optional*): + Whether to make the repo private. If `None` (default), the repo will be public unless the organization's default is private. This value is ignored if the repo already exists. + path_in_repo (`str`, *optional*): + The path to the folder in the repo where the logs will be pushed. Defaults to "tensorboard/". + repo_allow_patterns (`list[str]` or `str`, *optional*): + A list of patterns to include in the upload. Defaults to `"*.tfevents.*"`. Check out the + [upload guide](https://huggingface.co/docs/huggingface_hub/guides/upload#upload-a-folder) for more details. + repo_ignore_patterns (`list[str]` or `str`, *optional*): + A list of patterns to exclude in the upload. Check out the + [upload guide](https://huggingface.co/docs/huggingface_hub/guides/upload#upload-a-folder) for more details. + token (`str`, *optional*): + Authentication token. Will default to the stored token. See https://huggingface.co/settings/token for more + details + kwargs: + Additional keyword arguments passed to `SummaryWriter`. + + Examples: + ```diff + # Taken from https://pytorch.org/docs/stable/tensorboard.html + - from torch.utils.tensorboard import SummaryWriter + + from huggingface_hub import HFSummaryWriter + + import numpy as np + + - writer = SummaryWriter() + + writer = HFSummaryWriter(repo_id="username/my-trained-model") + + for n_iter in range(100): + writer.add_scalar('Loss/train', np.random.random(), n_iter) + writer.add_scalar('Loss/test', np.random.random(), n_iter) + writer.add_scalar('Accuracy/train', np.random.random(), n_iter) + writer.add_scalar('Accuracy/test', np.random.random(), n_iter) + ``` + + ```py + >>> from huggingface_hub import HFSummaryWriter + + # Logs are automatically pushed every 15 minutes (5 by default) + when exiting the context manager + >>> with HFSummaryWriter(repo_id="test_hf_logger", commit_every=15) as logger: + ... logger.add_scalar("a", 1) + ... logger.add_scalar("b", 2) + ``` + """ + + @experimental + def __new__(cls, *args, **kwargs) -> "HFSummaryWriter": + if not is_summary_writer_available: + raise ImportError( + "You must have `tensorboard` installed to use `HFSummaryWriter`. Please run `pip install --upgrade" + " tensorboardX` first." + ) + return super().__new__(cls) + + def __init__( + self, + repo_id: str, + *, + logdir: str | None = None, + commit_every: int | float = 5, + squash_history: bool = False, + repo_type: str | None = None, + repo_revision: str | None = None, + repo_private: bool | None = None, + path_in_repo: str | None = "tensorboard", + repo_allow_patterns: list[str] | str | None = "*.tfevents.*", + repo_ignore_patterns: list[str] | str | None = None, + token: str | None = None, + **kwargs, + ): + # Initialize SummaryWriter + super().__init__(logdir=logdir, **kwargs) + + # Check logdir has been correctly initialized and fail early otherwise. In practice, SummaryWriter takes care of it. + if not isinstance(self.logdir, str): + raise ValueError(f"`self.logdir` must be a string. Got '{self.logdir}' of type {type(self.logdir)}.") + + # Append logdir name to `path_in_repo` + if path_in_repo is None or path_in_repo == "": + path_in_repo = Path(self.logdir).name + else: + path_in_repo = path_in_repo.strip("/") + "/" + Path(self.logdir).name + + # Initialize scheduler + self.scheduler = CommitScheduler( + folder_path=self.logdir, + path_in_repo=path_in_repo, + repo_id=repo_id, + repo_type=repo_type, + revision=repo_revision, + private=repo_private, + token=token, + allow_patterns=repo_allow_patterns, + ignore_patterns=repo_ignore_patterns, + every=commit_every, + squash_history=squash_history, + ) + + # Exposing some high-level info at root level + self.repo_id = self.scheduler.repo_id + self.repo_type = self.scheduler.repo_type + self.repo_revision = self.scheduler.revision + + # Add `hf-summary-writer` tag to the model card metadata + try: + card = ModelCard.load(repo_id_or_path=self.repo_id, repo_type=self.repo_type) + except EntryNotFoundError: + card = ModelCard("") + tags = card.data.get("tags", []) + if "hf-summary-writer" not in tags: + tags.append("hf-summary-writer") + card.data["tags"] = tags + card.push_to_hub(repo_id=self.repo_id, repo_type=self.repo_type) + + def __exit__(self, exc_type, exc_val, exc_tb): + """Push to hub in a non-blocking way when exiting the logger's context manager.""" + super().__exit__(exc_type, exc_val, exc_tb) + future = self.scheduler.trigger() + future.result() diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_upload_large_folder.py b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_upload_large_folder.py new file mode 100644 index 0000000000000000000000000000000000000000..2fd0045e6776d2170c5ef31548916ba0fd0470a1 --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_upload_large_folder.py @@ -0,0 +1,769 @@ +# Copyright 2024-present, the HuggingFace Inc. team. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import enum +import logging +import os +import queue +import shutil +import sys +import threading +import time +import traceback +from datetime import datetime +from pathlib import Path +from threading import Lock +from typing import TYPE_CHECKING, Any +from urllib.parse import quote + +from ._commit_api import CommitOperationAdd, UploadInfo, _fetch_upload_modes +from ._local_folder import LocalUploadFileMetadata, LocalUploadFilePaths, get_local_upload_paths, read_upload_metadata +from .constants import DEFAULT_REVISION, REPO_TYPES +from .utils import DEFAULT_IGNORE_PATTERNS, _format_size, filter_repo_objects, tqdm +from .utils._runtime import is_xet_available +from .utils.sha import sha_fileobj + + +if TYPE_CHECKING: + from .hf_api import HfApi + +logger = logging.getLogger(__name__) + +WAITING_TIME_IF_NO_TASKS = 10 # seconds +MAX_NB_FILES_FETCH_UPLOAD_MODE = 100 +COMMIT_SIZE_SCALE: list[int] = [20, 50, 75, 100, 125, 200, 250, 400, 600, 1000] + +UPLOAD_BATCH_SIZE_XET = 256 # Max 256 files per upload batch for XET-enabled repos +UPLOAD_BATCH_SIZE_LFS = 1 # Otherwise, batches of 1 for regular LFS upload + +# Repository limits (from https://huggingface.co/docs/hub/repositories-recommendations) +MAX_FILES_PER_REPO = 100_000 # Recommended maximum number of files per repository +MAX_FILES_PER_FOLDER = 10_000 # Recommended maximum number of files per folder +MAX_FILE_SIZE_GB = 200 # Recommended maximum for individual file size (split larger files) +RECOMMENDED_FILE_SIZE_GB = 20 # Recommended maximum for individual file size + + +def _validate_upload_limits(paths_list: list[LocalUploadFilePaths]) -> None: + """ + Validate upload against repository limits and warn about potential issues. + + Args: + paths_list: List of file paths to be uploaded + + Warns about: + - Too many files in the repository (>100k) + - Too many entries (files or subdirectories) in a single folder (>10k) + - Files exceeding size limits (>20GB recommended, >200GB maximum) + """ + logger.info("Running validation checks on files to upload...") + + # Check 1: Total file count + if len(paths_list) > MAX_FILES_PER_REPO: + logger.warning( + f"You are about to upload {len(paths_list):,} files. " + f"This exceeds the recommended limit of {MAX_FILES_PER_REPO:,} files per repository.\n" + f"Consider:\n" + f" - Splitting your data into multiple repositories\n" + f" - Using fewer, larger files (e.g., parquet files)\n" + f" - See: https://huggingface.co/docs/hub/repositories-recommendations" + ) + + # Check 2: Files and subdirectories per folder + # Track immediate children (files and subdirs) for each folder + from collections import defaultdict + + entries_per_folder: dict[str, Any] = defaultdict(lambda: {"files": 0, "subdirs": set()}) + + for paths in paths_list: + path = Path(paths.path_in_repo) + parts = path.parts + + # Count this file in its immediate parent directory + parent = str(path.parent) if str(path.parent) != "." else "." + entries_per_folder[parent]["files"] += 1 + + # Track immediate subdirectories for each parent folder + # Walk through the path components to track parent-child relationships + for i, child in enumerate(parts[:-1]): + parent = "." if i == 0 else "/".join(parts[:i]) + entries_per_folder[parent]["subdirs"].add(child) + + # Check limits for each folder + for folder, data in entries_per_folder.items(): + file_count = data["files"] + subdir_count = len(data["subdirs"]) + total_entries = file_count + subdir_count + + if total_entries > MAX_FILES_PER_FOLDER: + folder_display = "root" if folder == "." else folder + logger.warning( + f"Folder '{folder_display}' contains {total_entries:,} entries " + f"({file_count:,} files and {subdir_count:,} subdirectories). " + f"This exceeds the recommended {MAX_FILES_PER_FOLDER:,} entries per folder.\n" + "Consider reorganising into sub-folders." + ) + + # Check 3: File sizes + large_files = [] + very_large_files = [] + + for paths in paths_list: + size = paths.file_path.stat().st_size + size_gb = size / 1_000_000_000 # Use decimal GB as per Hub limits + + if size_gb > MAX_FILE_SIZE_GB: + very_large_files.append((paths.path_in_repo, size_gb)) + elif size_gb > RECOMMENDED_FILE_SIZE_GB: + large_files.append((paths.path_in_repo, size_gb)) + + # Warn about very large files (>200GB) + if very_large_files: + files_str = "\n - ".join(f"{path}: {size:.1f}GB" for path, size in very_large_files[:5]) + more_str = f"\n ... and {len(very_large_files) - 5} more files" if len(very_large_files) > 5 else "" + logger.warning( + f"Found {len(very_large_files)} files exceeding the {MAX_FILE_SIZE_GB}GB recommended maximum:\n" + f" - {files_str}{more_str}\n" + f"Consider splitting these files into smaller chunks." + ) + + # Warn about large files (>20GB) + if large_files: + files_str = "\n - ".join(f"{path}: {size:.1f}GB" for path, size in large_files[:5]) + more_str = f"\n ... and {len(large_files) - 5} more files" if len(large_files) > 5 else "" + logger.warning( + f"Found {len(large_files)} files larger than {RECOMMENDED_FILE_SIZE_GB}GB (recommended limit):\n" + f" - {files_str}{more_str}\n" + f"Large files may slow down loading and processing." + ) + + logger.info("Validation checks complete.") + + +def upload_large_folder_internal( + api: "HfApi", + repo_id: str, + folder_path: str | Path, + *, + repo_type: str, # Repo type is required! + revision: str | None = None, + private: bool | None = None, + allow_patterns: list[str] | str | None = None, + ignore_patterns: list[str] | str | None = None, + num_workers: int | None = None, + print_report: bool = True, + print_report_every: int = 60, +): + """Upload a large folder to the Hub in the most resilient way possible. + + See [`HfApi.upload_large_folder`] for the full documentation. + """ + # 1. Check args and setup + if repo_type is None: + raise ValueError( + "For large uploads, `repo_type` is explicitly required. Please set it to `model`, `dataset` or `space`." + " If you are using the CLI, pass it as `--repo-type=model`." + ) + if repo_type not in REPO_TYPES: + raise ValueError(f"Invalid repo type, must be one of {REPO_TYPES}") + if revision is None: + revision = DEFAULT_REVISION + + folder_path = Path(folder_path).expanduser().resolve() + if not folder_path.is_dir(): + raise ValueError(f"Provided path: '{folder_path}' is not a directory") + + if ignore_patterns is None: + ignore_patterns = [] + elif isinstance(ignore_patterns, str): + ignore_patterns = [ignore_patterns] + ignore_patterns += DEFAULT_IGNORE_PATTERNS + + if num_workers is None: + nb_cores = os.cpu_count() or 1 + num_workers = max(nb_cores // 2, 1) # Use at most half of cpu cores + + # 2. Create repo if missing + repo_url = api.create_repo(repo_id=repo_id, repo_type=repo_type, private=private, exist_ok=True) + logger.info(f"Repo created: {repo_url}") + repo_id = repo_url.repo_id + + # Warn on too many commits + try: + commits = api.list_repo_commits(repo_id=repo_id, repo_type=repo_type, revision=revision) + commit_count = len(commits) + if commit_count > 500: + logger.warning( + f"\n{'=' * 80}\n" + f"WARNING: This repository has {commit_count} commits.\n" + f"Repositories with a large number of commits can experience performance issues.\n" + f"\n" + f"Consider squashing your commit history using `super_squash_history()`.\n" + "To do so, you need to stop this process, run the snippet below and restart the upload command." + f" from huggingface_hub import super_squash_history\n" + f" super_squash_history(repo_id='{repo_id}', repo_type='{repo_type}')\n" + f"\n" + f"Note: This is a non-revertible operation. See the documentation for more details:\n" + f"https://huggingface.co/docs/huggingface_hub/main/en/package_reference/hf_api#huggingface_hub.HfApi.super_squash_history\n" + f"{'=' * 80}\n" + ) + except Exception as e: + # Don't fail the upload if we can't check commit count + logger.debug(f"Could not check commit count: {e}") + + # 2.1 Check if xet is enabled to set batch file upload size + upload_batch_size = UPLOAD_BATCH_SIZE_XET if is_xet_available() else UPLOAD_BATCH_SIZE_LFS + + # 3. List files to upload + filtered_paths_list = filter_repo_objects( + (path.relative_to(folder_path).as_posix() for path in folder_path.glob("**/*") if path.is_file()), + allow_patterns=allow_patterns, + ignore_patterns=ignore_patterns, + ) + paths_list = [get_local_upload_paths(folder_path, relpath) for relpath in filtered_paths_list] + logger.info(f"Found {len(paths_list)} candidate files to upload") + + # Validate upload against repository limits + _validate_upload_limits(paths_list) + + logger.info("Starting upload...") + + # Read metadata for each file + items = [ + (paths, read_upload_metadata(folder_path, paths.path_in_repo)) + for paths in tqdm(paths_list, desc="Recovering from metadata files") + ] + + # 4. Start workers + status = LargeUploadStatus(items, upload_batch_size) + threads = [ + threading.Thread( + target=_worker_job, + kwargs={ + "status": status, + "api": api, + "repo_id": repo_id, + "repo_type": repo_type, + "revision": revision, + }, + ) + for _ in range(num_workers) + ] + + for thread in threads: + thread.start() + + # 5. Print regular reports + if print_report: + print("\n\n" + status.current_report()) + last_report_ts = time.time() + while True: + time.sleep(1) + if time.time() - last_report_ts >= print_report_every: + if print_report: + _print_overwrite(status.current_report()) + last_report_ts = time.time() + if status.is_done(): + logger.info("Is done: exiting main loop") + break + + for thread in threads: + thread.join() + + logger.info(status.current_report()) + logger.info("Upload is complete!") + + +#################### +# Logic to manage workers and synchronize tasks +#################### + + +class WorkerJob(enum.Enum): + SHA256 = enum.auto() + GET_UPLOAD_MODE = enum.auto() + PREUPLOAD_LFS = enum.auto() + COMMIT = enum.auto() + WAIT = enum.auto() # if no tasks are available but we don't want to exit + + +JOB_ITEM_T = tuple[LocalUploadFilePaths, LocalUploadFileMetadata] + + +class LargeUploadStatus: + """Contains information, queues and tasks for a large upload process.""" + + def __init__(self, items: list[JOB_ITEM_T], upload_batch_size: int = 1): + self.items = items + self.queue_sha256: "queue.Queue[JOB_ITEM_T]" = queue.Queue() + self.queue_get_upload_mode: "queue.Queue[JOB_ITEM_T]" = queue.Queue() + self.queue_preupload_lfs: "queue.Queue[JOB_ITEM_T]" = queue.Queue() + self.queue_commit: "queue.Queue[JOB_ITEM_T]" = queue.Queue() + self.lock = Lock() + + self.nb_workers_sha256: int = 0 + self.nb_workers_get_upload_mode: int = 0 + self.nb_workers_preupload_lfs: int = 0 + self.upload_batch_size: int = upload_batch_size + self.nb_workers_commit: int = 0 + self.nb_workers_waiting: int = 0 + self.last_commit_attempt: float | None = None + + self._started_at = datetime.now() + self._chunk_idx: int = 1 + self._chunk_lock: Lock = Lock() + + # Setup queues + for item in self.items: + paths, metadata = item + if metadata.sha256 is None: + self.queue_sha256.put(item) + elif metadata.upload_mode is None: + self.queue_get_upload_mode.put(item) + elif metadata.upload_mode == "lfs" and not metadata.is_uploaded: + self.queue_preupload_lfs.put(item) + elif not metadata.is_committed: + self.queue_commit.put(item) + else: + logger.debug(f"Skipping file {paths.path_in_repo} (already uploaded and committed)") + + def target_chunk(self) -> int: + with self._chunk_lock: + return COMMIT_SIZE_SCALE[self._chunk_idx] + + def update_chunk(self, success: bool, nb_items: int, duration: float) -> None: + with self._chunk_lock: + if not success: + logger.warning(f"Failed to commit {nb_items} files at once. Will retry with less files in next batch.") + self._chunk_idx -= 1 + elif nb_items >= COMMIT_SIZE_SCALE[self._chunk_idx] and duration < 40: + logger.info(f"Successfully committed {nb_items} at once. Increasing the limit for next batch.") + self._chunk_idx += 1 + + self._chunk_idx = max(0, min(self._chunk_idx, len(COMMIT_SIZE_SCALE) - 1)) + + def current_report(self) -> str: + """Generate a report of the current status of the large upload.""" + nb_hashed = 0 + size_hashed = 0 + nb_preuploaded = 0 + nb_lfs = 0 + nb_lfs_unsure = 0 + size_preuploaded = 0 + nb_committed = 0 + size_committed = 0 + total_size = 0 + ignored_files = 0 + total_files = 0 + + with self.lock: + for _, metadata in self.items: + if metadata.should_ignore: + ignored_files += 1 + continue + total_size += metadata.size + total_files += 1 + if metadata.sha256 is not None: + nb_hashed += 1 + size_hashed += metadata.size + if metadata.upload_mode == "lfs": + nb_lfs += 1 + if metadata.upload_mode is None: + nb_lfs_unsure += 1 + if metadata.is_uploaded: + nb_preuploaded += 1 + size_preuploaded += metadata.size + if metadata.is_committed: + nb_committed += 1 + size_committed += metadata.size + total_size_str = _format_size(total_size) + + now = datetime.now() + now_str = now.strftime("%Y-%m-%d %H:%M:%S") + elapsed = now - self._started_at + elapsed_str = str(elapsed).split(".")[0] # remove milliseconds + + message = "\n" + "-" * 10 + message += f" {now_str} ({elapsed_str}) " + message += "-" * 10 + "\n" + + message += "Files: " + message += f"hashed {nb_hashed}/{total_files} ({_format_size(size_hashed)}/{total_size_str}) | " + message += f"pre-uploaded: {nb_preuploaded}/{nb_lfs} ({_format_size(size_preuploaded)}/{total_size_str})" + if nb_lfs_unsure > 0: + message += f" (+{nb_lfs_unsure} unsure)" + message += f" | committed: {nb_committed}/{total_files} ({_format_size(size_committed)}/{total_size_str})" + message += f" | ignored: {ignored_files}\n" + + message += "Workers: " + message += f"hashing: {self.nb_workers_sha256} | " + message += f"get upload mode: {self.nb_workers_get_upload_mode} | " + message += f"pre-uploading: {self.nb_workers_preupload_lfs} | " + message += f"committing: {self.nb_workers_commit} | " + message += f"waiting: {self.nb_workers_waiting}\n" + message += "-" * 51 + + return message + + def is_done(self) -> bool: + with self.lock: + return all(metadata.is_committed or metadata.should_ignore for _, metadata in self.items) + + +def _worker_job( + status: LargeUploadStatus, + api: "HfApi", + repo_id: str, + repo_type: str, + revision: str, +): + """ + Main process for a worker. The worker will perform tasks based on the priority list until all files are uploaded + and committed. If no tasks are available, the worker will wait for 10 seconds before checking again. + + If a task fails for any reason, the item(s) are put back in the queue for another worker to pick up. + + Read `upload_large_folder` docstring for more information on how tasks are prioritized. + """ + while True: + next_job: tuple[WorkerJob, list[JOB_ITEM_T]] | None = None + + # Determine next task + next_job = _determine_next_job(status) + if next_job is None: + return + job, items = next_job + + # Perform task + match job: + case WorkerJob.SHA256: + item = items[0] # single item + try: + _compute_sha256(item) + status.queue_get_upload_mode.put(item) + except KeyboardInterrupt: + raise + except Exception as e: + logger.error(f"Failed to compute sha256: {e}") + traceback.format_exc() + status.queue_sha256.put(item) + + with status.lock: + status.nb_workers_sha256 -= 1 + + case WorkerJob.GET_UPLOAD_MODE: + try: + _get_upload_mode(items, api=api, repo_id=repo_id, repo_type=repo_type, revision=revision) + except KeyboardInterrupt: + raise + except Exception as e: + logger.error(f"Failed to get upload mode: {e}") + traceback.format_exc() + + # Items are either: + # - dropped (if should_ignore) + # - put in LFS queue (if LFS) + # - put in commit queue (if regular) + # - or put back (if error occurred). + for item in items: + _, metadata = item + if metadata.should_ignore: + continue + match metadata.upload_mode: + case "lfs": + status.queue_preupload_lfs.put(item) + case "regular": + status.queue_commit.put(item) + case _: + status.queue_get_upload_mode.put(item) + + with status.lock: + status.nb_workers_get_upload_mode -= 1 + + case WorkerJob.PREUPLOAD_LFS: + try: + _preupload_lfs(items, api=api, repo_id=repo_id, repo_type=repo_type, revision=revision) + for item in items: + status.queue_commit.put(item) + except KeyboardInterrupt: + raise + except Exception as e: + logger.error(f"Failed to preupload LFS: {e}") + traceback.format_exc() + for item in items: + status.queue_preupload_lfs.put(item) + + with status.lock: + status.nb_workers_preupload_lfs -= 1 + + case WorkerJob.COMMIT: + start_ts = time.time() + success = True + try: + _commit(items, api=api, repo_id=repo_id, repo_type=repo_type, revision=revision) + except KeyboardInterrupt: + raise + except Exception as e: + logger.error(f"Failed to commit: {e}") + traceback.format_exc() + for item in items: + status.queue_commit.put(item) + success = False + duration = time.time() - start_ts + status.update_chunk(success, len(items), duration) + with status.lock: + status.last_commit_attempt = time.time() + status.nb_workers_commit -= 1 + + case WorkerJob.WAIT: + time.sleep(WAITING_TIME_IF_NO_TASKS) + with status.lock: + status.nb_workers_waiting -= 1 + + +def _determine_next_job(status: LargeUploadStatus) -> tuple[WorkerJob, list[JOB_ITEM_T]] | None: + with status.lock: + # 1. Commit if more than 5 minutes since last commit attempt (and at least 1 file) + if ( + status.nb_workers_commit == 0 + and status.queue_commit.qsize() > 0 + and status.last_commit_attempt is not None + and time.time() - status.last_commit_attempt > 5 * 60 + ): + status.nb_workers_commit += 1 + logger.debug("Job: commit (more than 5 minutes since last commit attempt)") + return (WorkerJob.COMMIT, _get_n(status.queue_commit, status.target_chunk())) + + # 2. Commit if at least 100 files are ready to commit + elif status.nb_workers_commit == 0 and status.queue_commit.qsize() >= 150: + status.nb_workers_commit += 1 + logger.debug("Job: commit (>100 files ready)") + return (WorkerJob.COMMIT, _get_n(status.queue_commit, status.target_chunk())) + + # 3. Get upload mode if at least 100 files + elif status.queue_get_upload_mode.qsize() >= MAX_NB_FILES_FETCH_UPLOAD_MODE: + status.nb_workers_get_upload_mode += 1 + logger.debug(f"Job: get upload mode (>{MAX_NB_FILES_FETCH_UPLOAD_MODE} files ready)") + return (WorkerJob.GET_UPLOAD_MODE, _get_n(status.queue_get_upload_mode, MAX_NB_FILES_FETCH_UPLOAD_MODE)) + + # 4. Preupload LFS file if at least `status.upload_batch_size` files and no worker is preuploading LFS + elif status.queue_preupload_lfs.qsize() >= status.upload_batch_size and status.nb_workers_preupload_lfs == 0: + status.nb_workers_preupload_lfs += 1 + logger.debug("Job: preupload LFS (no other worker preuploading LFS)") + return (WorkerJob.PREUPLOAD_LFS, _get_n(status.queue_preupload_lfs, status.upload_batch_size)) + + # 5. Compute sha256 if at least 1 file and no worker is computing sha256 + elif status.queue_sha256.qsize() > 0 and status.nb_workers_sha256 == 0: + status.nb_workers_sha256 += 1 + logger.debug("Job: sha256 (no other worker computing sha256)") + return (WorkerJob.SHA256, _get_one(status.queue_sha256)) + + # 6. Get upload mode if at least 1 file and no worker is getting upload mode + elif status.queue_get_upload_mode.qsize() > 0 and status.nb_workers_get_upload_mode == 0: + status.nb_workers_get_upload_mode += 1 + logger.debug("Job: get upload mode (no other worker getting upload mode)") + return (WorkerJob.GET_UPLOAD_MODE, _get_n(status.queue_get_upload_mode, MAX_NB_FILES_FETCH_UPLOAD_MODE)) + + # 7. Preupload LFS file if at least `status.upload_batch_size` files + elif status.queue_preupload_lfs.qsize() >= status.upload_batch_size: + status.nb_workers_preupload_lfs += 1 + logger.debug("Job: preupload LFS") + return (WorkerJob.PREUPLOAD_LFS, _get_n(status.queue_preupload_lfs, status.upload_batch_size)) + + # 8. Compute sha256 if at least 1 file + elif status.queue_sha256.qsize() > 0: + status.nb_workers_sha256 += 1 + logger.debug("Job: sha256") + return (WorkerJob.SHA256, _get_one(status.queue_sha256)) + + # 9. Get upload mode if at least 1 file + elif status.queue_get_upload_mode.qsize() > 0: + status.nb_workers_get_upload_mode += 1 + logger.debug("Job: get upload mode") + return (WorkerJob.GET_UPLOAD_MODE, _get_n(status.queue_get_upload_mode, MAX_NB_FILES_FETCH_UPLOAD_MODE)) + + # 10. Preupload LFS file if at least 1 file + elif status.queue_preupload_lfs.qsize() > 0: + status.nb_workers_preupload_lfs += 1 + logger.debug("Job: preupload LFS") + return (WorkerJob.PREUPLOAD_LFS, _get_n(status.queue_preupload_lfs, status.upload_batch_size)) + + # 11. Commit if at least 1 file and 1 min since last commit attempt + elif ( + status.nb_workers_commit == 0 + and status.queue_commit.qsize() > 0 + and status.last_commit_attempt is not None + and time.time() - status.last_commit_attempt > 1 * 60 + ): + status.nb_workers_commit += 1 + logger.debug("Job: commit (1 min since last commit attempt)") + return (WorkerJob.COMMIT, _get_n(status.queue_commit, status.target_chunk())) + + # 12. Commit if at least 1 file all other queues are empty and all workers are waiting + # e.g. when it's the last commit + elif ( + status.nb_workers_commit == 0 + and status.queue_commit.qsize() > 0 + and status.queue_sha256.qsize() == 0 + and status.queue_get_upload_mode.qsize() == 0 + and status.queue_preupload_lfs.qsize() == 0 + and status.nb_workers_sha256 == 0 + and status.nb_workers_get_upload_mode == 0 + and status.nb_workers_preupload_lfs == 0 + ): + status.nb_workers_commit += 1 + logger.debug("Job: commit") + return (WorkerJob.COMMIT, _get_n(status.queue_commit, status.target_chunk())) + + # 13. If all queues are empty, exit + elif all(metadata.is_committed or metadata.should_ignore for _, metadata in status.items): + logger.info("All files have been processed! Exiting worker.") + return None + + # 14. If no task is available, wait + else: + status.nb_workers_waiting += 1 + logger.debug(f"No task available, waiting... ({WAITING_TIME_IF_NO_TASKS}s)") + return (WorkerJob.WAIT, []) + + +#################### +# Atomic jobs (sha256, get_upload_mode, preupload_lfs, commit) +#################### + + +def _compute_sha256(item: JOB_ITEM_T) -> None: + """Compute sha256 of a file and save it in metadata.""" + paths, metadata = item + if metadata.sha256 is None: + with paths.file_path.open("rb") as f: + metadata.sha256 = sha_fileobj(f).hex() + metadata.save(paths) + + +def _get_upload_mode(items: list[JOB_ITEM_T], api: "HfApi", repo_id: str, repo_type: str, revision: str) -> None: + """Get upload mode for each file and update metadata. + + Also receive info if the file should be ignored. + """ + additions = [_build_hacky_operation(item) for item in items] + _fetch_upload_modes( + additions=additions, + repo_type=repo_type, + repo_id=repo_id, + headers=api._build_hf_headers(), + revision=quote(revision, safe=""), + endpoint=api.endpoint, + ) + for item, addition in zip(items, additions): + paths, metadata = item + metadata.upload_mode = addition._upload_mode + metadata.should_ignore = addition._should_ignore + metadata.remote_oid = addition._remote_oid + metadata.save(paths) + + +def _preupload_lfs(items: list[JOB_ITEM_T], api: "HfApi", repo_id: str, repo_type: str, revision: str) -> None: + """Preupload LFS files and update metadata.""" + additions = [_build_hacky_operation(item) for item in items] + api.preupload_lfs_files( + repo_id=repo_id, + repo_type=repo_type, + revision=revision, + additions=additions, + ) + + for paths, metadata in items: + metadata.is_uploaded = True + metadata.save(paths) + + +def _commit(items: list[JOB_ITEM_T], api: "HfApi", repo_id: str, repo_type: str, revision: str) -> None: + """Commit files to the repo.""" + additions = [_build_hacky_operation(item) for item in items] + api.create_commit( + repo_id=repo_id, + repo_type=repo_type, + revision=revision, + operations=additions, + commit_message="Add files using upload-large-folder tool", + ) + for paths, metadata in items: + metadata.is_committed = True + metadata.save(paths) + + +#################### +# Hacks with CommitOperationAdd to bypass checks/sha256 calculation +#################### + + +class HackyCommitOperationAdd(CommitOperationAdd): + def __post_init__(self) -> None: + if isinstance(self.path_or_fileobj, Path): + self.path_or_fileobj = str(self.path_or_fileobj) + + +def _build_hacky_operation(item: JOB_ITEM_T) -> HackyCommitOperationAdd: + paths, metadata = item + operation = HackyCommitOperationAdd(path_in_repo=paths.path_in_repo, path_or_fileobj=paths.file_path) + with paths.file_path.open("rb") as file: + sample = file.peek(512)[:512] + if metadata.sha256 is None: + raise ValueError("sha256 must have been computed by now!") + operation.upload_info = UploadInfo(sha256=bytes.fromhex(metadata.sha256), size=metadata.size, sample=sample) + operation._upload_mode = metadata.upload_mode # type: ignore + operation._should_ignore = metadata.should_ignore + operation._remote_oid = metadata.remote_oid + operation._is_uploaded = metadata.is_uploaded + if metadata.is_uploaded and metadata.upload_mode == "lfs": + operation.path_or_fileobj = b"" + return operation + + +#################### +# Misc helpers +#################### + + +def _get_one(queue: "queue.Queue[JOB_ITEM_T]") -> list[JOB_ITEM_T]: + return [queue.get()] + + +def _get_n(queue: "queue.Queue[JOB_ITEM_T]", n: int) -> list[JOB_ITEM_T]: + return [queue.get() for _ in range(min(queue.qsize(), n))] + + +def _print_overwrite(report: str) -> None: + """Print a report, overwriting the previous lines. + + Since tqdm in using `sys.stderr` to (re-)write progress bars, we need to use `sys.stdout` + to print the report. + + Note: works well only if no other process is writing to `sys.stdout`! + """ + report += "\n" + # Get terminal width + terminal_width = shutil.get_terminal_size().columns + + # Count number of lines that should be cleared + nb_lines = sum(len(line) // terminal_width + 1 for line in report.splitlines()) + + # Clear previous lines based on the number of lines in the report + for _ in range(nb_lines): + sys.stdout.write("\r\033[K") # Clear line + sys.stdout.write("\033[F") # Move cursor up one line + + # Print the new report, filling remaining space with whitespace + sys.stdout.write(report) + sys.stdout.write(" " * (terminal_width - len(report.splitlines()[-1]))) + sys.stdout.flush() diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_webhooks_payload.py b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_webhooks_payload.py new file mode 100644 index 0000000000000000000000000000000000000000..976a97a1d30a5105d26f4cb3746be2c9d10d1e4b --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_webhooks_payload.py @@ -0,0 +1,136 @@ +# Copyright 2023-present, the HuggingFace Inc. team. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Contains data structures to parse the webhooks payload.""" + +from typing import Literal + +from .utils import is_pydantic_available + + +if is_pydantic_available(): + from pydantic import BaseModel +else: + # Define a dummy BaseModel to avoid import errors when pydantic is not installed + # Import error will be raised when trying to use the class + + class BaseModel: # type: ignore [no-redef] + def __init__(self, *args, **kwargs) -> None: + raise ImportError( + "You must have `pydantic` installed to use `WebhookPayload`. This is an optional dependency that" + " should be installed separately. Please run `pip install --upgrade pydantic` and retry." + ) + + +# This is an adaptation of the ReportV3 interface implemented in moon-landing. V0, V1 and V2 have been ignored as they +# are not in used anymore. To keep in sync when format is updated in +# https://github.com/huggingface/moon-landing/blob/main/server/lib/HFWebhooks.ts (internal link). + + +WebhookEvent_T = Literal[ + "create", + "delete", + "move", + "update", +] +RepoChangeEvent_T = Literal[ + "add", + "move", + "remove", + "update", +] +RepoType_T = Literal[ + "dataset", + "model", + "space", +] +DiscussionStatus_T = Literal[ + "closed", + "draft", + "open", + "merged", +] +SupportedWebhookVersion = Literal[3] + + +class ObjectId(BaseModel): + id: str + + +class WebhookPayloadUrl(BaseModel): + web: str + api: str | None = None + + +class WebhookPayloadMovedTo(BaseModel): + name: str + owner: ObjectId + + +class WebhookPayloadWebhook(ObjectId): + version: SupportedWebhookVersion + + +class WebhookPayloadEvent(BaseModel): + action: WebhookEvent_T + scope: str + + +class WebhookPayloadDiscussionChanges(BaseModel): + base: str + mergeCommitId: str | None = None + + +class WebhookPayloadComment(ObjectId): + author: ObjectId + hidden: bool + content: str | None = None + url: WebhookPayloadUrl + + +class WebhookPayloadDiscussion(ObjectId): + num: int + author: ObjectId + url: WebhookPayloadUrl + title: str + isPullRequest: bool + status: DiscussionStatus_T + changes: WebhookPayloadDiscussionChanges | None = None + pinned: bool | None = None + + +class WebhookPayloadRepo(ObjectId): + owner: ObjectId + head_sha: str | None = None + name: str + private: bool + subdomain: str | None = None + tags: list[str] | None = None + type: Literal["dataset", "model", "space"] + url: WebhookPayloadUrl + + +class WebhookPayloadUpdatedRef(BaseModel): + ref: str + oldSha: str | None = None + newSha: str | None = None + + +class WebhookPayload(BaseModel): + event: WebhookPayloadEvent + repo: WebhookPayloadRepo + discussion: WebhookPayloadDiscussion | None = None + comment: WebhookPayloadComment | None = None + webhook: WebhookPayloadWebhook + movedTo: WebhookPayloadMovedTo | None = None + updatedRefs: list[WebhookPayloadUpdatedRef] | None = None diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_webhooks_server.py b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_webhooks_server.py new file mode 100644 index 0000000000000000000000000000000000000000..662b16b4b43e9ebbd9fc40d03af888d60fe5e5e4 --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/_webhooks_server.py @@ -0,0 +1,376 @@ +# Copyright 2023-present, the HuggingFace Inc. team. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Contains `WebhooksServer` and `webhook_endpoint` to create a webhook server easily.""" + +import atexit +import inspect +import os +from collections.abc import Callable +from functools import wraps +from typing import TYPE_CHECKING, Any, Optional + +from .utils import experimental, is_fastapi_available, is_gradio_available + + +if TYPE_CHECKING: + import gradio as gr + from fastapi import Request + +if is_fastapi_available(): + from fastapi import FastAPI, Request + from fastapi.responses import JSONResponse +else: + # Will fail at runtime if FastAPI is not available + FastAPI = Request = JSONResponse = None # type: ignore + + +_global_app: Optional["WebhooksServer"] = None +_is_local = os.environ.get("SPACE_ID") is None + + +@experimental +class WebhooksServer: + """ + The [`WebhooksServer`] class lets you create an instance of a Gradio app that can receive Huggingface webhooks. + These webhooks can be registered using the [`~WebhooksServer.add_webhook`] decorator. Webhook endpoints are added to + the app as a POST endpoint to the FastAPI router. Once all the webhooks are registered, the `launch` method has to be + called to start the app. + + It is recommended to accept [`WebhookPayload`] as the first argument of the webhook function. It is a Pydantic + model that contains all the information about the webhook event. The data will be parsed automatically for you. + + Check out the [webhooks guide](../guides/webhooks_server) for a step-by-step tutorial on how to set up your + WebhooksServer and deploy it on a Space. + + > [!WARNING] + > `WebhooksServer` is experimental. Its API is subject to change in the future. + + > [!WARNING] + > You must have `gradio` installed to use `WebhooksServer` (`pip install --upgrade gradio`). + + Args: + ui (`gradio.Blocks`, optional): + A Gradio UI instance to be used as the Space landing page. If `None`, a UI displaying instructions + about the configured webhooks is created. + webhook_secret (`str`, optional): + A secret key to verify incoming webhook requests. You can set this value to any secret you want as long as + you also configure it in your [webhooks settings panel](https://huggingface.co/settings/webhooks). You + can also set this value as the `WEBHOOK_SECRET` environment variable. If no secret is provided, the + webhook endpoints are opened without any security. + + Example: + + ```python + import gradio as gr + from huggingface_hub import WebhooksServer, WebhookPayload + + with gr.Blocks() as ui: + ... + + app = WebhooksServer(ui=ui, webhook_secret="my_secret_key") + + @app.add_webhook("/say_hello") + async def hello(payload: WebhookPayload): + return {"message": "hello"} + + app.launch() + ``` + """ + + def __new__(cls, *args, **kwargs) -> "WebhooksServer": + if not is_gradio_available(): + raise ImportError( + "You must have `gradio` installed to use `WebhooksServer`. Please run `pip install --upgrade gradio`" + " first." + ) + if not is_fastapi_available(): + raise ImportError( + "You must have `fastapi` installed to use `WebhooksServer`. Please run `pip install --upgrade fastapi`" + " first." + ) + return super().__new__(cls) + + def __init__( + self, + ui: Optional["gr.Blocks"] = None, + webhook_secret: str | None = None, + ) -> None: + self._ui = ui + + self.webhook_secret = webhook_secret or os.getenv("WEBHOOK_SECRET") + self.registered_webhooks: dict[str, Callable] = {} + _warn_on_empty_secret(self.webhook_secret) + + def add_webhook(self, path: str | None = None) -> Callable: + """ + Decorator to add a webhook to the [`WebhooksServer`] server. + + Args: + path (`str`, optional): + The URL path to register the webhook function. If not provided, the function name will be used as the + path. In any case, all webhooks are registered under `/webhooks`. + + Raises: + ValueError: If the provided path is already registered as a webhook. + + Example: + ```python + from huggingface_hub import WebhooksServer, WebhookPayload + + app = WebhooksServer() + + @app.add_webhook + async def trigger_training(payload: WebhookPayload): + if payload.repo.type == "dataset" and payload.event.action == "update": + # Trigger a training job if a dataset is updated + ... + + app.launch() + ``` + """ + # Usage: directly as decorator. Example: `@app.add_webhook` + if callable(path): + # If path is a function, it means it was used as a decorator without arguments + return self.add_webhook()(path) + + # Usage: provide a path. Example: `@app.add_webhook(...)` + @wraps(FastAPI.post) + def _inner_post(*args, **kwargs): + func = args[0] + abs_path = f"/webhooks/{(path or func.__name__).strip('/')}" + if abs_path in self.registered_webhooks: + raise ValueError(f"Webhook {abs_path} already exists.") + self.registered_webhooks[abs_path] = func + + return _inner_post + + def launch(self, prevent_thread_lock: bool = False, **launch_kwargs: Any) -> None: + """Launch the Gradio app and register webhooks to the underlying FastAPI server. + + Input parameters are forwarded to Gradio when launching the app. + """ + ui = self._ui or self._get_default_ui() + + # Start Gradio App + # - as non-blocking so that webhooks can be added afterwards + # - as shared if launch locally (to debug webhooks) + launch_kwargs.setdefault("share", _is_local) + self.fastapi_app, _, _ = ui.launch(prevent_thread_lock=True, **launch_kwargs) + + # Register webhooks to FastAPI app + for path, func in self.registered_webhooks.items(): + # Add secret check if required + if self.webhook_secret is not None: + func = _wrap_webhook_to_check_secret(func, webhook_secret=self.webhook_secret) + + # Add route to FastAPI app + self.fastapi_app.post(path)(func) + + # Print instructions and block main thread + space_host = os.environ.get("SPACE_HOST") + url = "https://" + space_host if space_host is not None else (ui.share_url or ui.local_url) + if url is None: + raise ValueError("Cannot find the URL of the app. Please provide a valid `ui` or update `gradio` version.") + url = url.strip("/") + message = "\nWebhooks are correctly setup and ready to use:" + message += "\n" + "\n".join(f" - POST {url}{webhook}" for webhook in self.registered_webhooks) + message += "\nGo to https://huggingface.co/settings/webhooks to setup your webhooks." + print(message) + + if not prevent_thread_lock: + ui.block_thread() + + def _get_default_ui(self) -> "gr.Blocks": + """Default UI if not provided (lists webhooks and provides basic instructions).""" + import gradio as gr + + with gr.Blocks() as ui: + gr.Markdown("# This is an app to process 🤗 Webhooks") + gr.Markdown( + "Webhooks are a foundation for MLOps-related features. They allow you to listen for new changes on" + " specific repos or to all repos belonging to particular set of users/organizations (not just your" + " repos, but any repo). Check out this [guide](https://huggingface.co/docs/hub/webhooks) to get to" + " know more about webhooks on the Huggingface Hub." + ) + gr.Markdown( + f"{len(self.registered_webhooks)} webhook(s) are registered:" + + "\n\n" + + "\n ".join( + f"- [{webhook_path}]({_get_webhook_doc_url(webhook.__name__, webhook_path)})" + for webhook_path, webhook in self.registered_webhooks.items() + ) + ) + gr.Markdown( + "Go to https://huggingface.co/settings/webhooks to setup your webhooks." + + "\nYou app is running locally. Please look at the logs to check the full URL you need to set." + if _is_local + else ( + "\nThis app is running on a Space. You can find the corresponding URL in the options menu" + " (top-right) > 'Embed the Space'. The URL looks like 'https://{username}-{repo_name}.hf.space'." + ) + ) + return ui + + +@experimental +def webhook_endpoint(path: str | None = None) -> Callable: + """Decorator to start a [`WebhooksServer`] and register the decorated function as a webhook endpoint. + + This is a helper to get started quickly. If you need more flexibility (custom landing page or webhook secret), + you can use [`WebhooksServer`] directly. You can register multiple webhook endpoints (to the same server) by using + this decorator multiple times. + + Check out the [webhooks guide](../guides/webhooks_server) for a step-by-step tutorial on how to set up your + server and deploy it on a Space. + + > [!WARNING] + > `webhook_endpoint` is experimental. Its API is subject to change in the future. + + > [!WARNING] + > You must have `gradio` installed to use `webhook_endpoint` (`pip install --upgrade gradio`). + + Args: + path (`str`, optional): + The URL path to register the webhook function. If not provided, the function name will be used as the path. + In any case, all webhooks are registered under `/webhooks`. + + Examples: + The default usage is to register a function as a webhook endpoint. The function name will be used as the path. + The server will be started automatically at exit (i.e. at the end of the script). + + ```python + from huggingface_hub import webhook_endpoint, WebhookPayload + + @webhook_endpoint + async def trigger_training(payload: WebhookPayload): + if payload.repo.type == "dataset" and payload.event.action == "update": + # Trigger a training job if a dataset is updated + ... + + # Server is automatically started at the end of the script. + ``` + + Advanced usage: register a function as a webhook endpoint and start the server manually. This is useful if you + are running it in a notebook. + + ```python + from huggingface_hub import webhook_endpoint, WebhookPayload + + @webhook_endpoint + async def trigger_training(payload: WebhookPayload): + if payload.repo.type == "dataset" and payload.event.action == "update": + # Trigger a training job if a dataset is updated + ... + + # Start the server manually + trigger_training.launch() + ``` + """ + if callable(path): + # If path is a function, it means it was used as a decorator without arguments + return webhook_endpoint()(path) + + @wraps(WebhooksServer.add_webhook) + def _inner(func: Callable) -> Callable: + app = _get_global_app() + app.add_webhook(path)(func) + if len(app.registered_webhooks) == 1: + # Register `app.launch` to run at exit (only once) + atexit.register(app.launch) + + @wraps(app.launch) + def _launch_now(): + # Run the app directly (without waiting atexit) + atexit.unregister(app.launch) + app.launch() + + func.launch = _launch_now # type: ignore + return func + + return _inner + + +def _get_global_app() -> WebhooksServer: + global _global_app + if _global_app is None: + _global_app = WebhooksServer() + return _global_app + + +def _warn_on_empty_secret(webhook_secret: str | None) -> None: + if webhook_secret is None: + print("Webhook secret is not defined. This means your webhook endpoints will be open to everyone.") + print( + "To add a secret, set `WEBHOOK_SECRET` as environment variable or pass it at initialization: " + "\n\t`app = WebhooksServer(webhook_secret='my_secret', ...)`" + ) + print( + "For more details about webhook secrets, please refer to" + " https://huggingface.co/docs/hub/webhooks#webhook-secret." + ) + else: + print("Webhook secret is correctly defined.") + + +def _get_webhook_doc_url(webhook_name: str, webhook_path: str) -> str: + """Returns the anchor to a given webhook in the docs (experimental)""" + return "/docs#/default/" + webhook_name + webhook_path.replace("/", "_") + "_post" + + +def _wrap_webhook_to_check_secret(func: Callable, webhook_secret: str) -> Callable: + """Wraps a webhook function to check the webhook secret before calling the function. + + This is a hacky way to add the `request` parameter to the function signature. Since FastAPI based itself on route + parameters to inject the values to the function, we need to hack the function signature to retrieve the `Request` + object (and hence the headers). A far cleaner solution would be to use a middleware. However, since + `fastapi==0.90.1`, a middleware cannot be added once the app has started. And since the FastAPI app is started by + Gradio internals (and not by us), we cannot add a middleware. + + This method is called only when a secret has been defined by the user. If a request is sent without the + "x-webhook-secret", the function will return a 401 error (unauthorized). If the header is sent but is incorrect, + the function will return a 403 error (forbidden). + + Inspired by https://stackoverflow.com/a/33112180. + """ + initial_sig = inspect.signature(func) + + @wraps(func) + async def _protected_func(request: Request, **kwargs): + request_secret = request.headers.get("x-webhook-secret") + if request_secret is None: + return JSONResponse({"error": "x-webhook-secret header not set."}, status_code=401) + if request_secret != webhook_secret: + return JSONResponse({"error": "Invalid webhook secret."}, status_code=403) + + # Inject `request` in kwargs if required + if "request" in initial_sig.parameters: + kwargs["request"] = request + + # Handle both sync and async routes + if inspect.iscoroutinefunction(func): + return await func(**kwargs) + else: + return func(**kwargs) + + # Update signature to include request + if "request" not in initial_sig.parameters: + _protected_func.__signature__ = initial_sig.replace( # type: ignore + parameters=( + inspect.Parameter(name="request", kind=inspect.Parameter.POSITIONAL_OR_KEYWORD, annotation=Request), + ) + + tuple(initial_sig.parameters.values()) + ) + + # Return protected route + return _protected_func diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/__init__.py b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..8568c82be1c638c0ccd34d460fd8b0f73dcbec4e --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2025 The HuggingFace Team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/_errors.py b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/_errors.py new file mode 100644 index 0000000000000000000000000000000000000000..da08730b6d83d9b573808b0be11e3a5aaf2c3255 --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/_errors.py @@ -0,0 +1,115 @@ +# Copyright 2026 The HuggingFace Team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""CLI error handling utilities.""" + +import traceback +from collections.abc import Callable + +from huggingface_hub.errors import ( + BucketNotFoundError, + CLIError, + CLIExtensionInstallError, + EntryNotFoundError, + GatedRepoError, + HfHubHTTPError, + LocalTokenNotFoundError, + RemoteEntryNotFoundError, + RepositoryNotFoundError, + RevisionNotFoundError, +) + + +def _format_repo_not_found(error: RepositoryNotFoundError) -> str: + label = error.repo_type.capitalize() if error.repo_type else "Repository" + if error.repo_id: + msg = f"{label} '{error.repo_id}' not found." + else: + msg = f"{label} not found." + msg += " If the repo is private, make sure you are authenticated and your token has the required permissions." + return msg + + +def _format_gated_repo(error: GatedRepoError) -> str: + label = error.repo_type if error.repo_type else "repository" + if error.repo_id: + return f"Access denied. {label.capitalize()} '{error.repo_id}' requires approval." + return f"Access denied. This {label} requires approval." + + +def _format_bucket_not_found(error: BucketNotFoundError) -> str: + if error.bucket_id: + return f"Bucket '{error.bucket_id}' not found. If the bucket is private, make sure you are authenticated and your token has the required permissions." + return "Bucket not found. Check the bucket id (namespace/name). If the bucket is private, make sure you are authenticated and your token has the required permissions." + + +def _format_entry_not_found(error: RemoteEntryNotFoundError) -> str: + label = error.repo_type if error.repo_type else "repository" + url = str(error.response.url) if error.response else None + if error.repo_id: + msg = f"File not found in {label} '{error.repo_id}'." + else: + msg = f"File not found in {label}." + if url: + msg += f"\nURL: {url}" + return msg + + +def _format_revision_not_found(error: RevisionNotFoundError) -> str: + label = error.repo_type if error.repo_type else "repository" + if error.repo_id: + return f"Revision not found in {label} '{error.repo_id}'." + return f"Revision not found in {label}. Check the revision parameter." + + +def _format_cli_error(error: CLIError) -> str: + """No traceback, just the error message.""" + return str(error) + + +def _format_cli_extension_install_error(error: CLIExtensionInstallError) -> str: + """Format a CLI extension installation error. + + The error is likely to be a tricky subprocess error to investigate. In this specific case we want to format the + traceback of the root cause while keeping the "nicely formatted" error message of the CLIExtensionInstallError + as a 1-line message. + """ + cause_tb = ( + "".join(traceback.format_exception(type(error.__cause__), error.__cause__, error.__cause__.__traceback__)) + if error.__cause__ is not None + else "" + ) + return f"{cause_tb}\n{error}" + + +CLI_ERROR_MAPPINGS: dict[type[Exception], Callable[..., str]] = { + # GatedRepoError must come before RepositoryNotFoundError (it's a subclass). + GatedRepoError: _format_gated_repo, + BucketNotFoundError: _format_bucket_not_found, + RepositoryNotFoundError: _format_repo_not_found, + RevisionNotFoundError: _format_revision_not_found, + LocalTokenNotFoundError: lambda _: "Not logged in. Run 'hf auth login' first.", + RemoteEntryNotFoundError: _format_entry_not_found, + EntryNotFoundError: lambda error: str(error), + HfHubHTTPError: lambda error: str(error), + ValueError: lambda error: f"Invalid value. {error}", + CLIExtensionInstallError: _format_cli_extension_install_error, + CLIError: _format_cli_error, +} + + +def format_known_exception(error: Exception) -> str | None: + for exc_type, formatter in CLI_ERROR_MAPPINGS.items(): + if isinstance(error, exc_type): + return formatter(error) + return None diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/_file_listing.py b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/_file_listing.py new file mode 100644 index 0000000000000000000000000000000000000000..d8671601e92c2bbab93239453691f223ab400b71 --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/_file_listing.py @@ -0,0 +1,225 @@ +# Copyright 2026-present, the HuggingFace Inc. team. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Shared helpers for listing files in buckets and repos (tree view, flat view, formatting).""" + +import json +from datetime import datetime +from typing import Sequence + +import typer + +from huggingface_hub._buckets import BucketFile, BucketFolder +from huggingface_hub.hf_api import RepoFile, RepoFolder + +from ._cli_utils import api_object_to_dict, get_hf_api +from ._output import OutputFormatWithAuto, out + + +BucketItem = BucketFile | BucketFolder +RepoItem = RepoFile | RepoFolder +ListingItem = BucketItem | RepoItem + + +def get_item_date(item: ListingItem) -> datetime | None: + """Extract date from an item, supporting both repo items (last_commit.date) and bucket items (mtime/uploaded_at).""" + match item: + case BucketFile(mtime=mtime) if mtime is not None: + return mtime + case BucketFile(uploaded_at=uploaded_at) | BucketFolder(uploaded_at=uploaded_at) if uploaded_at is not None: + return uploaded_at + case RepoFile(last_commit=last_commit) | RepoFolder(last_commit=last_commit) if last_commit is not None: + return last_commit.date + case _: + return None + + +def format_size(size: int | float, human_readable: bool = False) -> str: + """Format a size in bytes.""" + if not human_readable: + return str(size) + + for unit in ["B", "KB", "MB", "GB", "TB"]: + if size < 1000: + if unit == "B": + return f"{size} {unit}" + return f"{size:.1f} {unit}" + size /= 1000 + return f"{size:.1f} PB" + + +def format_date(dt: datetime | None, human_readable: bool = False) -> str: + """Format a datetime to a readable date string.""" + if dt is None: + return "" + if human_readable: + return dt.strftime("%b %d %H:%M") + return dt.strftime("%Y-%m-%d %H:%M:%S") + + +def build_tree( + items: Sequence[BucketItem] | Sequence[RepoItem], + human_readable: bool = False, + quiet: bool = False, +) -> list[str]: + """Build a tree representation of files and directories. + + Produces ASCII tree with size and date columns before the tree connector. + When quiet=True, only the tree structure is shown (no size/date). + """ + tree: dict = {} + + for item in items: + parts = item.path.split("/") + current = tree + for part in parts[:-1]: + if part not in current: + current[part] = {"__children__": {}} + current = current[part]["__children__"] + + final_part = parts[-1] + if isinstance(item, BucketFolder | RepoFolder): + if final_part not in current: + current[final_part] = {"__children__": {}} + else: + current[final_part] = {"__item__": item} + + prefix_width = 0 + max_size_width = 0 + max_date_width = 0 + if not quiet: + for item in items: + if isinstance(item, BucketFile | RepoFile): + size_str = format_size(item.size, human_readable) + max_size_width = max(max_size_width, len(size_str)) + date_str = format_date(get_item_date(item), human_readable) + max_date_width = max(max_date_width, len(date_str)) + if max_size_width > 0: + prefix_width = max_size_width + 2 + max_date_width + + lines: list[str] = [] + _render_tree( + tree, + lines, + "", + prefix_width=prefix_width, + max_size_width=max_size_width, + human_readable=human_readable, + ) + return lines + + +def _render_tree( + node: dict, + lines: list[str], + indent: str, + prefix_width: int = 0, + max_size_width: int = 0, + human_readable: bool = False, +) -> None: + """Recursively render a tree structure with size+date prefix.""" + sorted_items = sorted(node.items()) + for i, (name, value) in enumerate(sorted_items): + is_last = i == len(sorted_items) - 1 + connector = "└── " if is_last else "├── " + + is_dir = "__children__" in value + children = value.get("__children__", {}) + + if prefix_width > 0: + if is_dir: + prefix = " " * prefix_width + else: + item = value.get("__item__") + if item is not None: + size_str = format_size(item.size, human_readable) + date_str = format_date(get_item_date(item), human_readable) + prefix = f"{size_str:>{max_size_width}} {date_str}" + else: + prefix = " " * prefix_width + lines.append(f"{prefix} {indent}{connector}{name}{'/' if is_dir else ''}") + else: + lines.append(f"{indent}{connector}{name}{'/' if is_dir else ''}") + + if children: + child_indent = indent + (" " if is_last else "│ ") + _render_tree( + children, + lines, + child_indent, + prefix_width=prefix_width, + max_size_width=max_size_width, + human_readable=human_readable, + ) + + +def list_repo_files_cmd( + repo_id: str, + repo_type: str, + human_readable: bool, + as_tree: bool, + recursive: bool, + revision: str | None, + token: str | None, +) -> None: + """List files in a repo on the Hub. Used by models/datasets/spaces ls commands.""" + if as_tree and out.mode == OutputFormatWithAuto.json: + raise typer.BadParameter("Cannot use --tree with --format json.") + + api = get_hf_api(token=token) + items = list(api.list_repo_tree(repo_id, recursive=recursive, revision=revision, repo_type=repo_type, expand=True)) + print_file_listing(items, human_readable=human_readable, as_tree=as_tree, recursive=recursive) + + +def print_file_listing( + items: Sequence[BucketItem] | Sequence[RepoItem], + *, + human_readable: bool = False, + as_tree: bool = False, + recursive: bool = False, +) -> None: + """Print a file listing in the appropriate format based on the current output mode. + + Supports tree, json, quiet, and flat human-readable views. Works with both + BucketFile/BucketFolder and RepoFile/RepoFolder items. + """ + if not items: + out.text("(empty)") + return + + has_directories = any(isinstance(item, BucketFolder | RepoFolder) for item in items) + + if as_tree: + quiet = out.mode == OutputFormatWithAuto.quiet + for line in build_tree(items, human_readable=human_readable, quiet=quiet): + print(line) + elif out.mode == OutputFormatWithAuto.json: + print(json.dumps([api_object_to_dict(item) for item in items], indent=2)) + elif out.mode == OutputFormatWithAuto.quiet: + for item in items: + if isinstance(item, BucketFolder | RepoFolder): + print(f"{item.path}/") + else: + print(item.path) + else: + for item in items: + if isinstance(item, BucketFolder | RepoFolder): + date_str = format_date(get_item_date(item), human_readable) + print(f"{'':>12} {date_str:>19} {item.path}/") + else: + size_str = format_size(item.size, human_readable) + date_str = format_date(get_item_date(item), human_readable) + print(f"{size_str:>12} {date_str:>19} {item.path}") + + if not recursive and has_directories: + out.hint("Use -R to list files recursively.") diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/_output.py b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/_output.py new file mode 100644 index 0000000000000000000000000000000000000000..e5b60ab9a29bea3365ae27bd17a169138bc84176 --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/_output.py @@ -0,0 +1,272 @@ +# Copyright 2026 The HuggingFace Team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Output framework for the `hf` CLI.""" + +import dataclasses +import datetime +import json +import re +import sys +from collections.abc import Sequence +from enum import Enum +from typing import Any + +import typer + +from huggingface_hub.errors import ConfirmationError +from huggingface_hub.utils import ANSI, StatusLine, disable_progress_bars, is_agent, tabulate + + +# TODO: remove OutputFormat in _cli_utils.py once all commands are migrated to OutputFormatWithAuto. +class OutputFormatWithAuto(str, Enum): + """Output format for CLI commands with auto detection of agent/human mode.""" + + agent = "agent" + auto = "auto" + human = "human" + json = "json" + quiet = "quiet" + + +class Output: + """Output sink for the `hf` CLI. + + Mode is resolved once at init time based on `is_agent()` auto-detection + and can be overridden per-command via `set_mode()`. + """ + + mode: OutputFormatWithAuto + + def __init__(self) -> None: + self.set_mode() + + def set_mode(self, mode: OutputFormatWithAuto = OutputFormatWithAuto.auto) -> None: + """Override the output mode (called once at startup and again per '--format' flag).""" + if mode == OutputFormatWithAuto.auto: + mode = OutputFormatWithAuto.agent if is_agent() else OutputFormatWithAuto.human + self.mode = mode + if mode != OutputFormatWithAuto.human: + disable_progress_bars() + + def is_quiet(self) -> bool: + return self.mode == OutputFormatWithAuto.quiet + + def text(self, msg: str | None = None, *, human: str | None = None, agent: str | None = None) -> None: + """Print a free-form text message to stdout.""" + if msg is not None: + if human is not None or agent is not None: + raise ValueError("Cannot mix 'msg' with 'human'/'agent'.") + human = msg + agent = _strip_ansi(msg) + + match self.mode: + case OutputFormatWithAuto.human: + if human is not None: + print(human) + case OutputFormatWithAuto.agent: + if agent is not None: + print(agent) + # json/quiet: no-op + + def table( + self, + items: Sequence[dict[str, Any]], + *, + headers: list[str] | None = None, + id_key: str | None = None, + alignments: dict[str, str] | None = None, + ) -> None: + """Print tabular data to stdout. + + Args: + items: List of dicts. Headers are auto-detected from keys if not provided. + headers: Explicit column names. If None, derived from dict keys (all-None columns filtered). + id_key: Key to print in quiet mode. If None, uses the first header. + alignments: Optional mapping of header name to "left" or "right". Defaults to "left". + """ + if not items: + match self.mode: + case OutputFormatWithAuto.agent | OutputFormatWithAuto.human: + print("No results found.") + case OutputFormatWithAuto.json: + print("[]") + return + + if headers is None: + all_columns = list(items[0].keys()) + headers = [col for col in all_columns if any(item.get(col) is not None for item in items)] + rows = [[item.get(h) for h in headers] for item in items] + + match self.mode: + case OutputFormatWithAuto.human: # padded table, truncated cells, SCREAMING_SNAKE headers + formatted_rows: list[list[str | int]] = [[_format_table_cell_human(v) for v in row] for row in rows] + screaming_headers = [_to_header(h) for h in headers] + screaming_alignments = {_to_header(k): v for k, v in (alignments or {}).items()} + print(tabulate(formatted_rows, headers=screaming_headers, alignments=screaming_alignments)) + case OutputFormatWithAuto.agent: # TSV, no truncation, full timestamps + print("\t".join(headers)) + for row in rows: + print("\t".join(_format_table_cell_agent(v) for v in row)) + case OutputFormatWithAuto.json: # compact JSON array + print(json.dumps(list(items), default=str)) + case OutputFormatWithAuto.quiet: # id_key column (or first column), one per line + quiet_key = id_key or headers[0] + for item in items: + print(item.get(quiet_key, "")) + + def dict(self, data: Any, *, id_key: str | None = None) -> None: + """Print structured data as JSON in all modes (indented for human, compact otherwise). + + Accepts a dict or a dataclass. + """ + if dataclasses.is_dataclass(data) and not isinstance(data, type): + data = _dataclass_to_dict(data) + if self.mode == OutputFormatWithAuto.quiet and id_key is not None: + print(data.get(id_key, "")) + return + indent = 2 if self.mode == OutputFormatWithAuto.human else None + print(json.dumps(data, indent=indent, default=str)) + + def result(self, message: str, **data: Any) -> None: + """Print a success summary to stdout.""" + match self.mode: + case OutputFormatWithAuto.human: # ✓ message + key: value lines + parts = [ANSI.green(f"✓ {message}")] + for k, v in data.items(): + if v is not None: + parts.append(f" {k}: {v}") + print("\n".join(parts)) + case OutputFormatWithAuto.agent: # key=val pairs, space-separated + parts = [f"{k}={v}" for k, v in data.items() if v is not None] + print(" ".join(parts) if parts else message) + case OutputFormatWithAuto.json: # json.dumps(data), message ignored + print(json.dumps(data, default=str) if data else "") + case OutputFormatWithAuto.quiet: # first value only + values = list(data.values()) + if values: + print(values[0]) + + def confirm(self, message: str, *, default: bool = False, yes: bool = False) -> None: + """ + Ask for confirmation. Raises `ConfirmationError` in non-human modes. + """ + if yes: + return + if self.mode != OutputFormatWithAuto.human: + raise ConfirmationError(f"{message} Use --yes to skip confirmation.") + typer.confirm(message, default=default, abort=True) + + def status(self, message: str | None = None) -> StatusLine: + """Return a status line that emits only in human mode (no-op otherwise).""" + status = StatusLine(enabled=self.mode == OutputFormatWithAuto.human) + if message is not None: + status.update(message) + return status + + def warning(self, message: str) -> None: + """Print a non-fatal warning to stderr (all modes).""" + if self.mode == OutputFormatWithAuto.human: + print(ANSI.yellow(f"Warning: {message}"), file=sys.stderr) + else: + print(f"Warning: {message}", file=sys.stderr) + + def error(self, message: str) -> None: + """Print an error to stderr (all modes).""" + if self.mode == OutputFormatWithAuto.human: + print(ANSI.red(f"Error: {message}"), file=sys.stderr) + else: + print(f"Error: {message}", file=sys.stderr) + + def hint(self, message: str) -> None: + """Print a helpful hint to stderr (human: gray, agent/json: plain text).""" + if self.mode == OutputFormatWithAuto.human: + print(ANSI.gray(f"Hint: {message}"), file=sys.stderr) + else: + print(f"Hint: {message}", file=sys.stderr) + + +# HELPERS + + +def _serialize_value(v: object) -> object: + """Recursively serialize a value to be JSON-compatible.""" + if isinstance(v, datetime.datetime): + return v.isoformat() + elif isinstance(v, dict): + return {key: _serialize_value(val) for key, val in v.items() if val is not None} + elif isinstance(v, list): + return [_serialize_value(item) for item in v] + return v + + +def _dataclass_to_dict(info: Any) -> dict[str, Any]: + """Convert a dataclass to a json-serializable dict.""" + return {k: _serialize_value(v) for k, v in dataclasses.asdict(info).items() if v is not None} + + +_ANSI_RE = re.compile(r"\033\[[0-9;]*m") +_MAX_CELL_LENGTH = 35 + + +def _strip_ansi(text: str) -> str: + return _ANSI_RE.sub("", text) + + +def _single_line(text: str) -> str: + return " ".join(text.split()) + + +def _to_header(name: str) -> str: + """Convert a camelCase or PascalCase string to SCREAMING_SNAKE_CASE.""" + s = re.sub(r"([a-z])([A-Z])", r"\1_\2", name) + return s.upper() + + +def _format_table_value_human(value: Any) -> str: + """Convert a value to string for terminal display.""" + if value is None: + return "" + if isinstance(value, bool): + return "✔" if value else "" + if isinstance(value, datetime.datetime): + return value.strftime("%Y-%m-%d") + if isinstance(value, str) and re.match(r"^\d{4}-\d{2}-\d{2}T", value): + return value[:10] + if isinstance(value, str): + return _single_line(value) + if isinstance(value, list): + return ", ".join(_format_table_value_human(v) for v in value) + elif isinstance(value, dict): + if "name" in value: # Likely to be a user or org => print name + return _single_line(str(value["name"])) + return _single_line(json.dumps(value)) + return _single_line(str(value)) + + +def _format_table_cell_human(value: Any, max_len: int = _MAX_CELL_LENGTH) -> str: + """Format a value + truncate it for table display.""" + cell = _format_table_value_human(value) + if len(cell) > max_len: + cell = cell[: max_len - 3] + "..." + return cell + + +def _format_table_cell_agent(value: Any) -> str: + """Format a cell value for agent TSV output (ISO timestamps, tabs escaped).""" + if isinstance(value, datetime.datetime): + return value.isoformat() + return _single_line(str(value)) + + +out = Output() diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/_skills.py b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/_skills.py new file mode 100644 index 0000000000000000000000000000000000000000..ec5b6255badcb826b50e051bd03ab99fd0e72a19 --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/_skills.py @@ -0,0 +1,252 @@ +"""Internal helpers for Hugging Face marketplace skill installation and upgrades.""" + +import json +import shutil +import tempfile +from dataclasses import dataclass, replace +from pathlib import Path, PurePosixPath +from typing import Any, Literal + +from huggingface_hub._buckets import BucketFile +from huggingface_hub.errors import CLIError + +from ..utils import disable_progress_bars +from ._cli_utils import get_hf_api + + +DEFAULT_SKILLS_BUCKET_ID = "huggingface/skills" +MARKETPLACE_PATH = "marketplace.json" +# Empty marker file dropped into managed skill installs so `hf skills update` knows +# to touch them and leave user-placed skill dirs alone. Filename is historical (used +# to be a JSON manifest with a revision); we keep it for backward compat with installs +# made by previous versions. +MANAGED_MARKER_FILENAME = ".hf-skill-manifest.json" + +SkillUpdateStatus = Literal["up_to_date", "unmanaged", "source_unreachable"] + + +@dataclass(frozen=True) +class MarketplaceSkill: + name: str + repo_path: str + + +@dataclass(frozen=True) +class SkillUpdateInfo: + name: str + skill_dir: Path + status: SkillUpdateStatus + detail: str | None = None + + +def add_skill(skill_name: str, destination_root: Path, force: bool = False) -> Path: + """Resolve a marketplace skill by name and install it.""" + api = get_hf_api() + with disable_progress_bars(): + marketplace_skills = _load_marketplace_skills(api) + skill = _select_marketplace_skill(marketplace_skills, skill_name) + if skill is None: + raise CLIError( + f"Skill '{skill_name}' not found in {DEFAULT_SKILLS_BUCKET_ID}. " + "Try `hf skills add` to install `hf-cli` or use a known skill name." + ) + return _install_marketplace_skill(api, skill, destination_root, force=force) + + +def update_skills(roots: list[Path], selector: str | None = None) -> list[SkillUpdateInfo]: + """Re-sync managed marketplace skill installs from the bucket.""" + skill_dirs = _iter_unique_skill_dirs(roots) + if selector is not None: + selector_lower = selector.strip().lower() + skill_dirs = [d for d in skill_dirs if d.name.lower() == selector_lower] + if not skill_dirs: + raise CLIError(f"No installed skill matches '{selector}'. Install it with `hf skills add {selector}`.") + + api = get_hf_api() + with disable_progress_bars(): + marketplace_skills = {skill.name.lower(): skill for skill in _load_marketplace_skills(api)} + return [_apply_single_update(api, skill_dir, marketplace_skills) for skill_dir in skill_dirs] + + +def _load_marketplace_skills(api) -> list[MarketplaceSkill]: + payload = _load_marketplace_payload(api) + plugins = payload.get("plugins") + if not isinstance(plugins, list): + raise CLIError("Invalid marketplace payload: expected a top-level 'plugins' list.") + + skills: list[MarketplaceSkill] = [] + for plugin in plugins: + if not isinstance(plugin, dict): + continue + name = plugin.get("name") + source = plugin.get("source") + if not isinstance(name, str) or not isinstance(source, str): + continue + skills.append(MarketplaceSkill(name=name, repo_path=_normalize_repo_path(source))) + return skills + + +def _install_marketplace_skill(api, skill: MarketplaceSkill, destination_root: Path, force: bool = False) -> Path: + """Install a marketplace skill into a local skills directory.""" + destination_root = destination_root.expanduser().resolve() + destination_root.mkdir(parents=True, exist_ok=True) + install_dir = destination_root / skill.name + already_exists = install_dir.exists() + + if already_exists and not force: + raise FileExistsError(f"Skill already exists: {install_dir}") + + if already_exists: + # Stage the new content in a sibling tempdir and atomically rename, so the + # existing install stays intact if the download fails halfway through. + with tempfile.TemporaryDirectory(dir=destination_root, prefix=f".{install_dir.name}.install-") as tmp_dir_str: + staged_dir = Path(tmp_dir_str) / install_dir.name + _populate_install_dir(api, skill=skill, install_dir=staged_dir) + _atomic_replace_directory(existing_dir=install_dir, staged_dir=staged_dir) + return install_dir + + try: + _populate_install_dir(api, skill=skill, install_dir=install_dir) + except Exception: + if install_dir.exists(): + shutil.rmtree(install_dir) + raise + return install_dir + + +def _load_marketplace_payload(api) -> dict[str, Any]: + with tempfile.TemporaryDirectory() as tmp_dir: + local_path = Path(tmp_dir) / "marketplace.json" + api.download_bucket_files( + DEFAULT_SKILLS_BUCKET_ID, + [(MARKETPLACE_PATH, local_path)], + raise_on_missing_files=True, + ) + parsed = json.loads(local_path.read_text(encoding="utf-8")) + + if not isinstance(parsed, dict): + raise CLIError("Invalid marketplace payload: expected a JSON object.") + return parsed + + +def _select_marketplace_skill(skills: list[MarketplaceSkill], selector: str) -> MarketplaceSkill | None: + selector_lower = selector.strip().lower() + for skill in skills: + if skill.name.lower() == selector_lower: + return skill + return None + + +def _normalize_repo_path(path: str) -> str: + normalized = path.strip() + while normalized.startswith("./"): + normalized = normalized[2:] + normalized = normalized.strip("/") + if not normalized: + raise CLIError("Invalid marketplace entry: empty source path.") + return normalized + + +def _populate_install_dir(api, skill: MarketplaceSkill, install_dir: Path) -> None: + install_dir.mkdir(parents=True, exist_ok=True) + bucket_files = _list_skill_files(api, skill) + _download_skill_files(api, skill, bucket_files, install_dir) + _validate_installed_skill_dir(install_dir) + (install_dir / MANAGED_MARKER_FILENAME).touch() + + +def _validate_installed_skill_dir(skill_dir: Path) -> None: + skill_file = skill_dir / "SKILL.md" + if not skill_file.is_file(): + raise RuntimeError(f"Installed skill is missing SKILL.md: {skill_file}") + + +def _list_skill_files(api, skill: MarketplaceSkill) -> list[BucketFile]: + """List all files under `skill.repo_path` in the marketplace bucket.""" + prefix = skill.repo_path.rstrip("/") + files: list[BucketFile] = [ + item + for item in api.list_bucket_tree(DEFAULT_SKILLS_BUCKET_ID, prefix=prefix, recursive=True) + if isinstance(item, BucketFile) + ] + if not files: + raise FileNotFoundError(f"Path '{prefix}' not found in bucket '{DEFAULT_SKILLS_BUCKET_ID}'.") + return files + + +def _download_skill_files(api, skill: MarketplaceSkill, files: list[BucketFile], install_dir: Path) -> None: + """Download bucket files into `install_dir`.""" + prefix = skill.repo_path.rstrip("/") + prefix_with_slash = f"{prefix}/" + + # `list_bucket_tree(prefix=...)` matches as a raw string prefix, so e.g. asking for + # "skills/gradio" can also return "skills/gradio-tools/...". Filter on the trailing + # slash to keep only files actually inside the directory, then strip it so files land + # directly under `install_dir` preserving any nested structure. + download_specs: list[tuple[str | BucketFile, str | Path]] = [] + for bucket_file in files: + if not bucket_file.path.startswith(prefix_with_slash): + continue + relative = bucket_file.path[len(prefix_with_slash) :] + local_file = install_dir.joinpath(*PurePosixPath(relative).parts) + local_file.parent.mkdir(parents=True, exist_ok=True) + download_specs.append((bucket_file, local_file)) + + if not download_specs: + raise FileNotFoundError(f"No files found under '{prefix}' in bucket '{DEFAULT_SKILLS_BUCKET_ID}'.") + + api.download_bucket_files(DEFAULT_SKILLS_BUCKET_ID, download_specs) + + +def _atomic_replace_directory(existing_dir: Path, staged_dir: Path) -> None: + backup_dir = staged_dir.parent / f"{existing_dir.name}.backup" + try: + existing_dir.rename(backup_dir) + staged_dir.rename(existing_dir) + shutil.rmtree(backup_dir) + except Exception: + if backup_dir.exists() and not existing_dir.exists(): + backup_dir.rename(existing_dir) + raise + + +def _iter_unique_skill_dirs(roots: list[Path]) -> list[Path]: + seen: set[Path] = set() + discovered: list[Path] = [] + for root in roots: + root = root.expanduser().resolve() + if not root.is_dir(): + continue + for child in sorted(root.iterdir()): + if child.name.startswith("."): + continue + if not child.is_dir() and not child.is_symlink(): + continue + resolved = child.resolve() + if resolved in seen or not resolved.is_dir(): + continue + seen.add(resolved) + discovered.append(resolved) + return discovered + + +def _apply_single_update(api, skill_dir: Path, marketplace_skills: dict[str, MarketplaceSkill]) -> SkillUpdateInfo: + base = SkillUpdateInfo(name=skill_dir.name, skill_dir=skill_dir, status="unmanaged") + + if not (skill_dir / MANAGED_MARKER_FILENAME).exists(): + return base + + skill = marketplace_skills.get(skill_dir.name.lower()) + if skill is None: + return replace( + base, + status="source_unreachable", + detail=f"Skill '{skill_dir.name}' is no longer available in {DEFAULT_SKILLS_BUCKET_ID}.", + ) + + try: + _install_marketplace_skill(api, skill, skill_dir.parent, force=True) + except Exception as exc: + return replace(base, status="source_unreachable", detail=str(exc)) + + return replace(base, status="up_to_date") diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/auth.py b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/auth.py new file mode 100644 index 0000000000000000000000000000000000000000..4ea277e072961584e1e0801533b4c538c1e34511 --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/auth.py @@ -0,0 +1,174 @@ +# Copyright 2020 The HuggingFace Team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Contains commands to authenticate to the Hugging Face Hub and interact with your repositories. + +Usage: + # login and save token locally. + hf auth login --token=hf_*** --add-to-git-credential + + # switch between tokens + hf auth switch + + # list all tokens + hf auth list + + # logout from all tokens + hf auth logout + + # check which account you are logged in as + hf auth whoami +""" + +from typing import Annotated + +import typer + +from huggingface_hub.constants import ENDPOINT +from huggingface_hub.hf_api import whoami + +from .._login import auth_list, auth_switch, login, logout +from ..utils import get_stored_tokens, get_token, logging +from ._cli_utils import TokenOpt, typer_factory +from ._output import out + + +logger = logging.get_logger(__name__) + + +auth_cli = typer_factory(help="Manage authentication (login, logout, etc.).") + + +@auth_cli.command( + "login", + examples=[ + "hf auth login", + "hf auth login --token $HF_TOKEN", + "hf auth login --token $HF_TOKEN --add-to-git-credential", + "hf auth login --force", + ], +) +def auth_login( + token: TokenOpt = None, + add_to_git_credential: Annotated[ + bool, + typer.Option( + help="Save to git credential helper. Useful only if you plan to run git commands directly.", + ), + ] = False, + force: Annotated[ + bool, + typer.Option( + help="Force re-login even if already logged in.", + ), + ] = False, +) -> None: + """Login using a token from huggingface.co/settings/tokens.""" + login(token=token, add_to_git_credential=add_to_git_credential, skip_if_logged_in=not force) + + +@auth_cli.command( + "logout", + examples=["hf auth logout", "hf auth logout --token-name my-token"], +) +def auth_logout( + token_name: Annotated[ + str | None, + typer.Option(help="Name of token to logout"), + ] = None, +) -> None: + """Logout from a specific token.""" + logout(token_name=token_name) + + +def _select_token_name() -> str | None: + token_names = list(get_stored_tokens().keys()) + + if not token_names: + logger.error("No stored tokens found. Please login first.") + return None + + print("Available stored tokens:") + for i, token_name in enumerate(token_names, 1): + print(f"{i}. {token_name}") + while True: + try: + choice = input("Enter the number of the token to switch to (or 'q' to quit): ") + if choice.lower() == "q": + return None + index = int(choice) - 1 + if 0 <= index < len(token_names): + return token_names[index] + else: + print("Invalid selection. Please try again.") + except ValueError: + print("Invalid input. Please enter a number or 'q' to quit.") + + +@auth_cli.command( + "switch", + examples=["hf auth switch", "hf auth switch --token-name my-token"], +) +def auth_switch_cmd( + token_name: Annotated[ + str | None, + typer.Option( + help="Name of the token to switch to", + ), + ] = None, + add_to_git_credential: Annotated[ + bool, + typer.Option( + help="Save to git credential helper. Useful only if you plan to run git commands directly.", + ), + ] = False, +) -> None: + """Switch between access tokens.""" + if token_name is None: + token_name = _select_token_name() + if token_name is None: + print("No token name provided. Aborting.") + raise typer.Exit() + auth_switch(token_name, add_to_git_credential=add_to_git_credential) + + +@auth_cli.command("list | ls", examples=["hf auth list"]) +def auth_list_cmd() -> None: + """List all stored access tokens.""" + auth_list() + + +@auth_cli.command("token", examples=["hf auth token", "hf auth token | xargs curl -H 'Authorization: Bearer {}'"]) +def auth_token() -> None: + """Print the current access token to stdout.""" + token = get_token() + if token is None: + out.error("Not logged in. Run `hf auth login` first.") + raise typer.Exit(code=1) + print(token) + out.hint("Run `hf auth whoami` to see which account this token belongs to.") + + +@auth_cli.command("whoami", examples=["hf auth whoami", "hf auth whoami --format json"]) +def auth_whoami() -> None: + """Find out which huggingface.co account you are logged in as.""" + + token = get_token() + if token is None: + out.error("Not logged in") + raise typer.Exit(code=1) + + info = whoami(token) + orgs = ",".join(org["name"] for org in info["orgs"]) or None + endpoint = ENDPOINT if ENDPOINT != "https://huggingface.co" else None + out.result("Logged in", user=info["name"], orgs=orgs, endpoint=endpoint) diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/buckets.py b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/buckets.py new file mode 100644 index 0000000000000000000000000000000000000000..46b21b82e7e63dfd09f741efb2ffa9f5750f33d2 --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/buckets.py @@ -0,0 +1,821 @@ +# Copyright 2025-present, the HuggingFace Inc. team. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Contains commands to interact with buckets via the CLI.""" + +import os +import sys +from typing import Annotated + +import typer + +from huggingface_hub import logging +from huggingface_hub._buckets import ( + BUCKET_PREFIX, + BucketFile, + FilterMatcher, + _is_bucket_path, + _parse_bucket_path, + _split_bucket_id_and_prefix, +) +from huggingface_hub.utils import ( + SoftTemporaryDirectory, + disable_progress_bars, +) + +from ._cli_utils import ( + SearchOpt, + TokenOpt, + get_hf_api, + typer_factory, +) +from ._file_listing import format_size, print_file_listing +from ._output import OutputFormatWithAuto, out + + +logger = logging.get_logger(__name__) + + +buckets_cli = typer_factory(help="Commands to interact with buckets.") + + +def _is_hf_handle(path: str) -> bool: + return path.startswith("hf://") + + +def _parse_bucket_argument(argument: str) -> tuple[str, str]: + """Parse a bucket argument accepting both 'namespace/name(/prefix)' and 'hf://buckets/namespace/name(/prefix)'. + + Returns: + tuple: (bucket_id, prefix) where bucket_id is "namespace/bucket_name" and prefix may be empty string. + """ + if argument.startswith(BUCKET_PREFIX): + return _parse_bucket_path(argument) + try: + return _split_bucket_id_and_prefix(argument) + except ValueError: + raise ValueError( + f"Invalid bucket argument: {argument}. Must be in format namespace/bucket_name" + f" or {BUCKET_PREFIX}namespace/bucket_name" + ) + + +@buckets_cli.command( + name="create", + examples=[ + "hf buckets create my-bucket", + "hf buckets create user/my-bucket", + "hf buckets create hf://buckets/user/my-bucket", + "hf buckets create user/my-bucket --private", + "hf buckets create user/my-bucket --exist-ok", + ], +) +def create( + bucket_id: Annotated[ + str, + typer.Argument( + help="Bucket ID: bucket_name, namespace/bucket_name, or hf://buckets/namespace/bucket_name", + ), + ], + private: Annotated[ + bool, + typer.Option( + "--private", + help="Create a private bucket.", + ), + ] = False, + exist_ok: Annotated[ + bool, + typer.Option( + "--exist-ok", + help="Do not raise an error if the bucket already exists.", + ), + ] = False, + token: TokenOpt = None, +) -> None: + """Create a new bucket.""" + api = get_hf_api(token=token) + + if bucket_id.startswith(BUCKET_PREFIX): + try: + parsed_id, prefix = _parse_bucket_argument(bucket_id) + except ValueError as e: + raise typer.BadParameter(str(e)) + if prefix: + raise typer.BadParameter( + f"Cannot specify a prefix for bucket creation: {bucket_id}." + f" Use namespace/bucket_name or {BUCKET_PREFIX}namespace/bucket_name." + ) + bucket_id = parsed_id + + bucket_url = api.create_bucket( + bucket_id, + private=private if private else None, + exist_ok=exist_ok, + ) + out.result("Bucket created", handle=bucket_url.handle, url=bucket_url.url) + + +def _is_bucket_id(argument: str) -> bool: + """Check if argument is a bucket ID (namespace/name) vs just a namespace.""" + if argument.startswith(BUCKET_PREFIX): + path = argument[len(BUCKET_PREFIX) :] + else: + path = argument + return "/" in path + + +@buckets_cli.command( + name="list | ls", + examples=[ + "hf buckets list", + "hf buckets list huggingface", + 'hf buckets list --search "my-prefix"', + "hf buckets list user/my-bucket", + "hf buckets list user/my-bucket -R", + "hf buckets list user/my-bucket -h", + "hf buckets list user/my-bucket --tree", + "hf buckets list user/my-bucket --tree -h", + "hf buckets list hf://buckets/user/my-bucket", + "hf buckets list user/my-bucket/sub -R", + ], +) +def list_cmd( + argument: Annotated[ + str | None, + typer.Argument( + help=( + "Namespace (user or org) to list buckets, or bucket ID" + " (namespace/bucket_name(/prefix) or hf://buckets/...) to list files." + ), + ), + ] = None, + human_readable: Annotated[ + bool, + typer.Option( + "--human-readable", + "-h", + help="Show sizes in human readable format.", + ), + ] = False, + as_tree: Annotated[ + bool, + typer.Option( + "--tree", + help="List files in tree format (only for listing files).", + ), + ] = False, + recursive: Annotated[ + bool, + typer.Option( + "--recursive", + "-R", + help="List files recursively (only for listing files).", + ), + ] = False, + search: SearchOpt = None, + token: TokenOpt = None, +) -> None: + """List buckets or files in a bucket. + + When called with no argument or a namespace, lists buckets. + When called with a bucket ID (namespace/bucket_name), lists files in the bucket. + """ + # Determine mode: listing buckets or listing files + is_file_mode = argument is not None and _is_bucket_id(argument) + + if is_file_mode: + if search is not None: + raise typer.BadParameter("Cannot use --search when listing files.") + _list_files( + argument=argument, # type: ignore + human_readable=human_readable, + as_tree=as_tree, + recursive=recursive, + token=token, + ) + else: + _list_buckets( + namespace=argument, + search=search, + human_readable=human_readable, + as_tree=as_tree, + recursive=recursive, + token=token, + ) + + +def _list_buckets( + namespace: str | None, + search: str | None, + human_readable: bool, + as_tree: bool, + recursive: bool, + token: str | None, +) -> None: + """List buckets in a namespace.""" + # Validate incompatible flags + if as_tree: + raise typer.BadParameter("Cannot use --tree when listing buckets.") + if recursive: + raise typer.BadParameter("Cannot use --recursive when listing buckets.") + + # Handle hf://buckets/namespace format + if namespace is not None and namespace.startswith(BUCKET_PREFIX): + namespace = namespace[len(BUCKET_PREFIX) :] + # Strip trailing slash if any + namespace = namespace.rstrip("/") + + api = get_hf_api(token=token) + items = [ + { + "id": bucket.id, + "private": bucket.private, + "size": format_size(bucket.size, human_readable) if human_readable else bucket.size, + "total_files": bucket.total_files, + "created_at": bucket.created_at, + } + for bucket in api.list_buckets(namespace=namespace, search=search) + ] + out.table(items, alignments={"size": "right", "total_files": "right"}) + + +def _list_files( + argument: str, + human_readable: bool, + as_tree: bool, + recursive: bool, + token: str | None, +) -> None: + """List files in a bucket.""" + if as_tree and out.mode == OutputFormatWithAuto.json: + raise typer.BadParameter("Cannot use --tree with --format json.") + + api = get_hf_api(token=token) + + try: + bucket_id, prefix = _parse_bucket_argument(argument) + except ValueError as e: + raise typer.BadParameter(str(e)) + + items = list( + api.list_bucket_tree( + bucket_id, + prefix=prefix or None, + recursive=recursive, + ) + ) + + print_file_listing(items, human_readable=human_readable, as_tree=as_tree, recursive=recursive) + + +@buckets_cli.command( + name="info", + examples=[ + "hf buckets info user/my-bucket", + "hf buckets info hf://buckets/user/my-bucket", + ], +) +def info( + bucket_id: Annotated[ + str, + typer.Argument( + help="Bucket ID: namespace/bucket_name or hf://buckets/namespace/bucket_name", + ), + ], + token: TokenOpt = None, +) -> None: + """Get info about a bucket.""" + api = get_hf_api(token=token) + + try: + parsed_id, _ = _parse_bucket_argument(bucket_id) + except ValueError as e: + raise typer.BadParameter(str(e)) + + bucket = api.bucket_info(parsed_id) + out.dict(bucket, id_key="id") + + +@buckets_cli.command( + name="delete", + examples=[ + "hf buckets delete user/my-bucket", + "hf buckets delete hf://buckets/user/my-bucket", + "hf buckets delete user/my-bucket --yes", + "hf buckets delete user/my-bucket --missing-ok", + ], +) +def delete( + bucket_id: Annotated[ + str, + typer.Argument( + help="Bucket ID: namespace/bucket_name or hf://buckets/namespace/bucket_name", + ), + ], + yes: Annotated[ + bool, + typer.Option( + "--yes", + "-y", + help="Skip confirmation prompt.", + ), + ] = False, + missing_ok: Annotated[ + bool, + typer.Option( + "--missing-ok", + help="Do not raise an error if the bucket does not exist.", + ), + ] = False, + token: TokenOpt = None, +) -> None: + """Delete a bucket. + + This deletes the entire bucket and all its contents. Use `hf buckets rm` to remove individual files. + """ + if bucket_id.startswith(BUCKET_PREFIX): + try: + parsed_id, prefix = _parse_bucket_argument(bucket_id) + except ValueError as e: + raise typer.BadParameter(str(e)) + if prefix: + raise typer.BadParameter( + f"Cannot specify a prefix for bucket deletion: {bucket_id}." + f" Use namespace/bucket_name or {BUCKET_PREFIX}namespace/bucket_name." + ) + bucket_id = parsed_id + elif "/" not in bucket_id: + raise typer.BadParameter( + f"Invalid bucket ID: {bucket_id}." + f" Must be in format namespace/bucket_name or {BUCKET_PREFIX}namespace/bucket_name." + ) + + out.confirm(f"Are you sure you want to delete bucket '{bucket_id}'?", yes=yes) + + api = get_hf_api(token=token) + api.delete_bucket(bucket_id, missing_ok=missing_ok) + out.result("Bucket deleted", bucket_id=bucket_id) + + +@buckets_cli.command( + name="remove | rm", + examples=[ + "hf buckets remove user/my-bucket/file.txt", + "hf buckets rm hf://buckets/user/my-bucket/file.txt", + "hf buckets rm user/my-bucket/logs/ --recursive", + 'hf buckets rm user/my-bucket --recursive --include "*.tmp"', + "hf buckets rm user/my-bucket/data/ --recursive --dry-run", + ], +) +def remove( + argument: Annotated[ + str, + typer.Argument( + help=( + "Bucket path: namespace/bucket_name/path or hf://buckets/namespace/bucket_name/path." + " With --recursive, namespace/bucket_name is also accepted to target all files." + ), + ), + ], + recursive: Annotated[ + bool, + typer.Option( + "--recursive", + "-R", + help="Remove files recursively under the given prefix.", + ), + ] = False, + yes: Annotated[ + bool, + typer.Option( + "--yes", + "-y", + help="Skip confirmation prompt.", + ), + ] = False, + dry_run: Annotated[ + bool, + typer.Option( + "--dry-run", + help="Preview what would be deleted without actually deleting.", + ), + ] = False, + include: Annotated[ + list[str] | None, + typer.Option( + help="Include only files matching pattern (can specify multiple). Requires --recursive.", + ), + ] = None, + exclude: Annotated[ + list[str] | None, + typer.Option( + help="Exclude files matching pattern (can specify multiple). Requires --recursive.", + ), + ] = None, + token: TokenOpt = None, +) -> None: + """Remove files from a bucket. + + To delete an entire bucket, use `hf buckets delete` instead. + """ + try: + bucket_id, prefix = _parse_bucket_argument(argument) + except ValueError as e: + raise typer.BadParameter(str(e)) + + if prefix == "" and not recursive: + raise typer.BadParameter( + f"No file path specified. To remove files, provide a path" + f" (e.g. '{bucket_id}/FILE') or use --recursive to remove all files." + f" To delete the entire bucket, use `hf buckets delete {bucket_id}`." + ) + + if (include or exclude) and not recursive: + raise typer.BadParameter("--include and --exclude require --recursive.") + + api = get_hf_api(token=token) + + if recursive: + status = out.status("Listing files from remote") + + all_files: list[BucketFile] = [] + for item in api.list_bucket_tree( + bucket_id, + prefix=prefix.rstrip("/") or None, + recursive=True, + ): + if isinstance(item, BucketFile): + all_files.append(item) + status.update(f"Listing files from remote ({len(all_files)} files)") + status.done(f"Listing files from remote ({len(all_files)} files)") + + if include or exclude: + matcher = FilterMatcher(include_patterns=include, exclude_patterns=exclude) + matched_files = [f for f in all_files if matcher.matches(f.path)] + else: + matched_files = all_files + + file_paths = [f.path for f in matched_files] + total_size = sum(f.size for f in matched_files) + size_str = format_size(total_size, human_readable=True) + + if not file_paths: + out.text("No files to remove.") + return + + count_label = f"{len(file_paths)} file(s) totaling {size_str}" + + if not yes and not dry_run: + out.text("\n".join(f" {path}" for path in file_paths)) + out.confirm(f"Remove {count_label} from '{bucket_id}'?", yes=False) + + if dry_run: + out.text("\n".join(f"delete: {BUCKET_PREFIX}{bucket_id}/{path}" for path in file_paths)) + out.text(f"(dry run) {count_label} would be removed.") + return + + api.batch_bucket_files(bucket_id, delete=file_paths) + out.result( + f"Removed {count_label} from '{bucket_id}'", + bucket_id=bucket_id, + files_deleted=len(file_paths), + size=size_str, + ) + + else: + file_path = prefix.rstrip("/") + if not file_path: + raise typer.BadParameter("File path cannot be empty.") + + if dry_run: + out.text(f"delete: {BUCKET_PREFIX}{bucket_id}/{file_path}") + out.text("(dry run) 1 file would be removed.") + return + + out.confirm(f"Remove '{file_path}' from '{bucket_id}'?", yes=yes) + + api.batch_bucket_files(bucket_id, delete=[file_path]) + out.result("File removed", path=file_path, bucket_id=bucket_id) + + +@buckets_cli.command( + name="move", + examples=[ + "hf buckets move user/old-bucket user/new-bucket", + "hf buckets move user/my-bucket my-org/my-bucket", + "hf buckets move hf://buckets/user/old-bucket hf://buckets/user/new-bucket", + ], +) +def move( + from_id: Annotated[ + str, + typer.Argument( + help="Source bucket ID: namespace/bucket_name or hf://buckets/namespace/bucket_name", + ), + ], + to_id: Annotated[ + str, + typer.Argument( + help="Destination bucket ID: namespace/bucket_name or hf://buckets/namespace/bucket_name", + ), + ], + token: TokenOpt = None, +) -> None: + """Move (rename) a bucket to a new name or namespace.""" + # Parse from_id + parsed_from_id, from_prefix = _parse_bucket_argument(from_id) + if from_prefix: + raise typer.BadParameter( + f"Cannot specify a prefix for bucket move: {from_id}." + f" Use namespace/bucket_name or {BUCKET_PREFIX}namespace/bucket_name." + ) + + # Parse to_id + parsed_to_id, to_prefix = _parse_bucket_argument(to_id) + if to_prefix: + raise typer.BadParameter( + f"Cannot specify a prefix for bucket move: {to_id}." + f" Use namespace/bucket_name or {BUCKET_PREFIX}namespace/bucket_name." + ) + + api = get_hf_api(token=token) + api.move_bucket(from_id=parsed_from_id, to_id=parsed_to_id) + out.result("Bucket moved", from_id=parsed_from_id, to_id=parsed_to_id) + + +# ============================================================================= +# Sync command +# ============================================================================= + + +@buckets_cli.command( + name="sync", + examples=[ + "hf buckets sync ./data hf://buckets/user/my-bucket", + "hf buckets sync hf://buckets/user/my-bucket ./data", + "hf buckets sync ./data hf://buckets/user/my-bucket --delete", + 'hf buckets sync hf://buckets/user/my-bucket ./data --include "*.safetensors" --exclude "*.tmp"', + "hf buckets sync ./data hf://buckets/user/my-bucket --plan sync-plan.jsonl", + "hf buckets sync --apply sync-plan.jsonl", + "hf buckets sync ./data hf://buckets/user/my-bucket --dry-run", + "hf buckets sync ./data hf://buckets/user/my-bucket --dry-run | jq .", + ], +) +def sync( + source: Annotated[ + str | None, + typer.Argument( + help="Source path: local directory or hf://buckets/namespace/bucket_name(/prefix)", + ), + ] = None, + dest: Annotated[ + str | None, + typer.Argument( + help="Destination path: local directory or hf://buckets/namespace/bucket_name(/prefix)", + ), + ] = None, + delete: Annotated[ + bool, + typer.Option( + help="Delete destination files not present in source.", + ), + ] = False, + ignore_times: Annotated[ + bool, + typer.Option( + "--ignore-times", + help="Skip files only based on size, ignoring modification times.", + ), + ] = False, + ignore_sizes: Annotated[ + bool, + typer.Option( + "--ignore-sizes", + help="Skip files only based on modification times, ignoring sizes.", + ), + ] = False, + plan: Annotated[ + str | None, + typer.Option( + help="Save sync plan to JSONL file for review instead of executing.", + ), + ] = None, + apply: Annotated[ + str | None, + typer.Option( + help="Apply a previously saved plan file.", + ), + ] = None, + dry_run: Annotated[ + bool, + typer.Option( + "--dry-run", + help="Print sync plan to stdout as JSONL without executing.", + ), + ] = False, + include: Annotated[ + list[str] | None, + typer.Option( + help="Include files matching pattern (can specify multiple).", + ), + ] = None, + exclude: Annotated[ + list[str] | None, + typer.Option( + help="Exclude files matching pattern (can specify multiple).", + ), + ] = None, + filter_from: Annotated[ + str | None, + typer.Option( + help="Read include/exclude patterns from file.", + ), + ] = None, + existing: Annotated[ + bool, + typer.Option( + "--existing", + help="Skip creating new files on receiver (only update existing files).", + ), + ] = False, + ignore_existing: Annotated[ + bool, + typer.Option( + "--ignore-existing", + help="Skip updating files that exist on receiver (only create new files).", + ), + ] = False, + verbose: Annotated[ + bool, + typer.Option( + "--verbose", + "-v", + help="Show detailed logging with reasoning.", + ), + ] = False, + token: TokenOpt = None, +) -> None: + """Sync files between local directory and a bucket.""" + api = get_hf_api(token=token) + api.sync_bucket( + source=source, + dest=dest, + delete=delete, + ignore_times=ignore_times, + ignore_sizes=ignore_sizes, + existing=existing, + ignore_existing=ignore_existing, + include=include, + exclude=exclude, + filter_from=filter_from, + plan=plan, + apply=apply, + dry_run=dry_run, + verbose=verbose, + quiet=out.is_quiet(), + ) + if plan and not out.is_quiet(): + out.hint(f"Run `hf buckets sync --apply {plan}` to execute this plan.") + + +# ============================================================================= +# Cp command +# ============================================================================= + + +@buckets_cli.command( + name="cp", + examples=[ + "hf buckets cp hf://buckets/user/my-bucket/config.json", + "hf buckets cp hf://buckets/user/my-bucket/config.json ./data/", + "hf buckets cp hf://buckets/user/my-bucket/config.json my-config.json", + "hf buckets cp hf://buckets/user/my-bucket/config.json -", + "hf buckets cp my-config.json hf://buckets/user/my-bucket", + "hf buckets cp my-config.json hf://buckets/user/my-bucket/logs/", + "hf buckets cp my-config.json hf://buckets/user/my-bucket/remote-config.json", + "hf buckets cp - hf://buckets/user/my-bucket/config.json", + "hf buckets cp hf://buckets/user/my-bucket/logs hf://buckets/user/archive-bucket/ # nests logs/ dir", + "hf buckets cp hf://buckets/user/my-bucket/logs/ hf://buckets/user/archive-bucket/ # copies contents only", + "hf buckets cp hf://datasets/user/my-dataset/processed/ hf://buckets/user/my-bucket/dataset/processed/", + ], +) +def cp( + src: Annotated[ + str, typer.Argument(help="Source: local file, any hf:// handle (model, dataset, bucket), or - for stdin") + ], + dst: Annotated[ + str | None, typer.Argument(help="Destination: local path, bucket hf://... handle, or - for stdout") + ] = None, + token: TokenOpt = None, +) -> None: + """Copy files to or from buckets.""" + api = get_hf_api(token=token) + + src_is_hf = _is_hf_handle(src) + dst_is_hf = dst is not None and _is_hf_handle(dst) + src_is_bucket = _is_bucket_path(src) + dst_is_bucket = dst is not None and _is_bucket_path(dst) + src_is_stdin = src == "-" + dst_is_stdout = dst == "-" + + # Remote to remote copy + if src_is_hf and dst_is_hf: + try: + api.copy_files(src, dst) # type: ignore + except ValueError as e: + raise typer.BadParameter(str(e)) + + out.result("Copied", src=src, dst=dst) + return + + # Local to remote copy + # --- Validation --- + if not src_is_bucket and not dst_is_bucket and not src_is_stdin: + if dst is None: + raise typer.BadParameter("Missing destination. Provide a bucket path as DST.") + raise typer.BadParameter("One of SRC or DST must be a bucket path (hf://buckets/...).") + + if src_is_stdin and not dst_is_bucket: + raise typer.BadParameter("Stdin upload requires a bucket destination.") + + if src_is_stdin and dst_is_bucket: + _, prefix = _parse_bucket_path(dst) # type: ignore + if prefix == "" or prefix.endswith("/"): + raise typer.BadParameter("Stdin upload requires a full destination path including filename.") + + if dst_is_stdout and not src_is_bucket: + raise typer.BadParameter("Cannot pipe to stdout for uploads.") + + if not src_is_bucket and not src_is_stdin and os.path.isdir(src): + raise typer.BadParameter("Source must be a file, not a directory. Use `hf buckets sync` for directories.") + + # --- Determine direction and execute --- + if src_is_bucket: + # Download: remote -> local or stdout + bucket_id, prefix = _parse_bucket_path(src) + if prefix == "" or prefix.endswith("/"): + raise typer.BadParameter("Source path must include a file name, not just a bucket or directory path.") + filename = prefix.rsplit("/", 1)[-1] + + if dst_is_stdout: + # Download to stdout: always suppress progress bars to avoid polluting output + # Only re-enable if they weren't already disabled by the caller + with disable_progress_bars(): + with SoftTemporaryDirectory() as tmp_dir: + tmp_path = os.path.join(tmp_dir, filename) + api.download_bucket_files(bucket_id, [(prefix, tmp_path)]) + with open(tmp_path, "rb") as f: + while chunk := f.read(32_000_000): # 32MB chunks + sys.stdout.buffer.write(chunk) + else: + # Download to file + if dst is None: + local_path = filename + elif os.path.isdir(dst) or dst.endswith(os.sep) or dst.endswith("/"): + local_path = os.path.join(dst, filename) + else: + local_path = dst + + # Ensure parent directory exists + parent_dir = os.path.dirname(local_path) + if parent_dir: + os.makedirs(parent_dir, exist_ok=True) + + api.download_bucket_files(bucket_id, [(prefix, local_path)]) + out.result("Downloaded", src=src, dst=local_path) + + elif src_is_stdin: + # Upload from stdin + bucket_id, remote_path = _parse_bucket_path(dst) # type: ignore + data = sys.stdin.buffer.read() + + api.batch_bucket_files(bucket_id, add=[(data, remote_path)]) + out.result("Uploaded", src="stdin", dst=dst) + + else: + # Upload from file + if not os.path.isfile(src): + raise typer.BadParameter(f"Source file not found: {src}") + + bucket_id, prefix = _parse_bucket_path(dst) # type: ignore + + if prefix == "": + remote_path = os.path.basename(src) + elif prefix.endswith("/"): + remote_path = prefix + os.path.basename(src) + else: + remote_path = prefix + + api.batch_bucket_files(bucket_id, add=[(src, remote_path)]) + out.result("Uploaded", src=src, dst=f"{BUCKET_PREFIX}{bucket_id}/{remote_path}") diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/cache.py b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/cache.py new file mode 100644 index 0000000000000000000000000000000000000000..75b4ec719133d0724452d91a82af66b7eed7d36a --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/cache.py @@ -0,0 +1,752 @@ +# Copyright 2025-present, the HuggingFace Inc. team. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Contains the 'hf cache' command group with cache management subcommands.""" + +import re +import time +from collections import defaultdict +from collections.abc import Callable, Mapping +from dataclasses import dataclass +from enum import Enum +from typing import Annotated, Any + +import typer + +from huggingface_hub.errors import CLIError + +from ..utils import ANSI, CachedRepoInfo, CachedRevisionInfo, CacheNotFound, HFCacheInfo, _format_size, scan_cache_dir +from ..utils._parsing import parse_duration, parse_size +from ._cli_utils import RepoIdArg, RepoTypeOpt, RevisionOpt, TokenOpt, get_hf_api, typer_factory +from ._output import out + + +cache_cli = typer_factory(help="Manage local cache directory.") + + +#### Cache helper utilities + + +@dataclass(frozen=True) +class _DeletionResolution: + revisions: frozenset[str] + selected: dict[CachedRepoInfo, frozenset[CachedRevisionInfo]] + missing: tuple[str, ...] + + +_FILTER_PATTERN = re.compile(r"^(?P[a-zA-Z_]+)\s*(?P==|!=|>=|<=|>|<|=)\s*(?P.+)$") +_ALLOWED_OPERATORS = {"=", "!=", ">", "<", ">=", "<="} +_FILTER_KEYS = {"accessed", "modified", "refs", "size", "type"} +_SORT_KEYS = {"accessed", "modified", "name", "size"} +_SORT_PATTERN = re.compile(r"^(?P[a-zA-Z_]+)(?::(?Pasc|desc))?$") +_SORT_DEFAULT_ORDER = { + # Default ordering: accessed/modified/size are descending (newest/biggest first), name is ascending + "accessed": "desc", + "modified": "desc", + "size": "desc", + "name": "asc", +} + + +# Dynamically generate SortOptions enum from _SORT_KEYS +_sort_options_dict = {} +for key in sorted(_SORT_KEYS): + _sort_options_dict[key] = key + _sort_options_dict[f"{key}_asc"] = f"{key}:asc" + _sort_options_dict[f"{key}_desc"] = f"{key}:desc" + +SortOptions = Enum("SortOptions", _sort_options_dict, type=str, module=__name__) # type: ignore + + +@dataclass(frozen=True) +class CacheDeletionCounts: + """Simple counters summarizing cache deletions for CLI messaging.""" + + repo_count: int + partial_revision_count: int + total_revision_count: int + + +CacheEntry = tuple[CachedRepoInfo, CachedRevisionInfo | None] +RepoRefsMap = dict[CachedRepoInfo, frozenset[str]] + + +def summarize_deletions( + selected_by_repo: Mapping[CachedRepoInfo, frozenset[CachedRevisionInfo]], +) -> CacheDeletionCounts: + """Summarize deletions across repositories.""" + repo_count = 0 + total_revisions = 0 + revisions_in_full_repos = 0 + + for repo, revisions in selected_by_repo.items(): + total_revisions += len(revisions) + if len(revisions) == len(repo.revisions): + repo_count += 1 + revisions_in_full_repos += len(revisions) + + partial_revision_count = total_revisions - revisions_in_full_repos + return CacheDeletionCounts(repo_count, partial_revision_count, total_revisions) + + +def print_cache_selected_revisions(selected_by_repo: Mapping[CachedRepoInfo, frozenset[CachedRevisionInfo]]) -> None: + """Pretty-print selected cache revisions during confirmation prompts.""" + for repo in sorted(selected_by_repo.keys(), key=lambda repo: (repo.repo_type, repo.repo_id.lower())): + repo_key = f"{repo.repo_type}/{repo.repo_id}" + revisions = sorted(selected_by_repo[repo], key=lambda rev: rev.commit_hash) + if len(revisions) == len(repo.revisions): + out.text(f" - {repo_key} (entire repo)") + continue + + out.text(f" - {repo_key}:") + for revision in revisions: + refs = " ".join(sorted(revision.refs)) or "(detached)" + out.text(f" {revision.commit_hash} [{refs}] {revision.size_on_disk_str}") + + +def build_cache_index( + hf_cache_info: HFCacheInfo, +) -> tuple[ + dict[str, CachedRepoInfo], + dict[str, tuple[CachedRepoInfo, CachedRevisionInfo]], +]: + """Create lookup tables so CLI commands can resolve repo ids and revisions quickly.""" + repo_lookup: dict[str, CachedRepoInfo] = {} + revision_lookup: dict[str, tuple[CachedRepoInfo, CachedRevisionInfo]] = {} + for repo in hf_cache_info.repos: + repo_key = repo.cache_id.lower() + repo_lookup[repo_key] = repo + for revision in repo.revisions: + revision_lookup[revision.commit_hash.lower()] = (repo, revision) + return repo_lookup, revision_lookup + + +def collect_cache_entries( + hf_cache_info: HFCacheInfo, *, include_revisions: bool +) -> tuple[list[CacheEntry], RepoRefsMap]: + """Flatten cache metadata into rows consumed by `hf cache ls`.""" + entries: list[CacheEntry] = [] + repo_refs_map: RepoRefsMap = {} + sorted_repos = sorted(hf_cache_info.repos, key=lambda repo: (repo.repo_type, repo.repo_id.lower())) + for repo in sorted_repos: + repo_refs_map[repo] = frozenset({ref for revision in repo.revisions for ref in revision.refs}) + if include_revisions: + for revision in sorted(repo.revisions, key=lambda rev: rev.commit_hash): + entries.append((repo, revision)) + else: + entries.append((repo, None)) + if include_revisions: + entries.sort( + key=lambda entry: ( + entry[0].cache_id, + entry[1].commit_hash if entry[1] is not None else "", + ) + ) + else: + entries.sort(key=lambda entry: entry[0].cache_id) + return entries, repo_refs_map + + +def compile_cache_filter( + expr: str, repo_refs_map: RepoRefsMap +) -> Callable[[CachedRepoInfo, CachedRevisionInfo | None, float], bool]: + """Convert a `hf cache ls` filter expression into the yes/no test we apply to each cache entry before displaying it.""" + match = _FILTER_PATTERN.match(expr.strip()) + if not match: + raise ValueError(f"Invalid filter expression: '{expr}'.") + + key = match.group("key").lower() + op = match.group("op") + value_raw = match.group("value").strip() + + if op not in _ALLOWED_OPERATORS: + raise ValueError(f"Unsupported operator '{op}' in filter '{expr}'. Must be one of {list(_ALLOWED_OPERATORS)}.") + + if key not in _FILTER_KEYS: + raise ValueError(f"Unsupported filter key '{key}' in '{expr}'. Must be one of {list(_FILTER_KEYS)}.") + # at this point we know that key is in `_FILTER_KEYS` + if key == "size": + size_threshold = parse_size(value_raw) + return lambda repo, revision, _: _compare_numeric( + revision.size_on_disk if revision is not None else repo.size_on_disk, + op, + size_threshold, + ) + + if key in {"modified", "accessed"}: + seconds = parse_duration(value_raw.strip()) + + def _time_filter(repo: CachedRepoInfo, revision: CachedRevisionInfo | None, now: float) -> bool: + timestamp = ( + repo.last_accessed + if key == "accessed" + else revision.last_modified + if revision is not None + else repo.last_modified + ) + if timestamp is None: + return False + return _compare_numeric(now - timestamp, op, seconds) + + return _time_filter + + if key == "type": + expected = value_raw.lower() + + if op != "=": + raise ValueError(f"Only '=' is supported for 'type' filters. Got '{op}'.") + + def _type_filter(repo: CachedRepoInfo, revision: CachedRevisionInfo | None, _: float) -> bool: + return repo.repo_type.lower() == expected + + return _type_filter + + else: # key == "refs" + if op != "=": + raise ValueError(f"Only '=' is supported for 'refs' filters. Got {op}.") + + def _refs_filter(repo: CachedRepoInfo, revision: CachedRevisionInfo | None, _: float) -> bool: + refs = revision.refs if revision is not None else repo_refs_map.get(repo, frozenset()) + return value_raw.lower() in [ref.lower() for ref in refs] + + return _refs_filter + + +def _compare_numeric(left: float | None, op: str, right: float) -> bool: + """Evaluate numeric comparisons for filters.""" + if left is None: + return False + + comparisons = { + "=": left == right, + "!=": left != right, + ">": left > right, + "<": left < right, + ">=": left >= right, + "<=": left <= right, + } + + if op not in comparisons: + raise ValueError(f"Unsupported numeric comparison operator: {op}") + + return comparisons[op] + + +def compile_cache_sort(sort_expr: str) -> tuple[Callable[[CacheEntry], tuple[Any, ...]], bool]: + """Convert a `hf cache ls` sort expression into a key function for sorting entries. + + Returns: + A tuple of (key_function, reverse_flag) where reverse_flag indicates whether + to sort in descending order (True) or ascending order (False). + """ + match = _SORT_PATTERN.match(sort_expr.strip().lower()) + if not match: + raise ValueError(f"Invalid sort expression: '{sort_expr}'. Expected format: 'key' or 'key:asc' or 'key:desc'.") + + key = match.group("key").lower() + explicit_order = match.group("order") + + if key not in _SORT_KEYS: + raise ValueError(f"Unsupported sort key '{key}' in '{sort_expr}'. Must be one of {list(_SORT_KEYS)}.") + + # Use explicit order if provided, otherwise use default for the key + order = explicit_order if explicit_order else _SORT_DEFAULT_ORDER[key] + reverse = order == "desc" + + def _sort_key(entry: CacheEntry) -> tuple[Any, ...]: + repo, revision = entry + + if key == "name": + # Sort by cache_id (repo type/id) + value: Any = repo.cache_id.lower() + return (value,) + + if key == "size": + # Use revision size if available, otherwise repo size + value = revision.size_on_disk if revision is not None else repo.size_on_disk + return (value,) + + if key == "accessed": + # For revisions, accessed is not available per-revision, use repo's last_accessed + # For repos, use repo's last_accessed + value = repo.last_accessed if repo.last_accessed is not None else 0.0 + return (value,) + + if key == "modified": + # Use revision's last_modified if available, otherwise repo's last_modified + if revision is not None: + value = revision.last_modified if revision.last_modified is not None else 0.0 + else: + value = repo.last_modified if repo.last_modified is not None else 0.0 + return (value,) + + # Should never reach here due to validation above + raise ValueError(f"Unsupported sort key: {key}") + + return _sort_key, reverse + + +def _resolve_deletion_targets(hf_cache_info: HFCacheInfo, targets: list[str]) -> _DeletionResolution: + """Resolve the deletion targets into a deletion resolution.""" + repo_lookup, revision_lookup = build_cache_index(hf_cache_info) + + selected: dict[CachedRepoInfo, set[CachedRevisionInfo]] = defaultdict(set) + revisions: set[str] = set() + missing: list[str] = [] + + for raw_target in targets: + target = raw_target.strip() + if not target: + continue + lowered = target.lower() + + if re.fullmatch(r"[0-9a-fA-F]{40}", lowered): + match = revision_lookup.get(lowered) + if match is None: + missing.append(raw_target) + continue + repo, revision = match + selected[repo].add(revision) + revisions.add(revision.commit_hash) + continue + + matched_repo = repo_lookup.get(lowered) + if matched_repo is None: + missing.append(raw_target) + continue + + for revision in matched_repo.revisions: + selected[matched_repo].add(revision) + revisions.add(revision.commit_hash) + + frozen_selected = {repo: frozenset(revs) for repo, revs in selected.items()} + return _DeletionResolution( + revisions=frozenset(revisions), + selected=frozen_selected, + missing=tuple(missing), + ) + + +#### Cache CLI commands + + +@cache_cli.command( + "list | ls", + examples=[ + "hf cache ls", + "hf cache ls --revisions", + 'hf cache ls --filter "size>1GB" --limit 20', + "hf cache ls --format json", + ], +) +def ls( + cache_dir: Annotated[ + str | None, + typer.Option( + help="Cache directory to scan (defaults to Hugging Face cache).", + ), + ] = None, + revisions: Annotated[ + bool, + typer.Option( + help="Include revisions in the output instead of aggregated repositories.", + ), + ] = False, + filter: Annotated[ + list[str] | None, + typer.Option( + "-f", + "--filter", + help="Filter entries (e.g. 'size>1GB', 'type=model', 'accessed>7d'). Can be used multiple times.", + ), + ] = None, + sort: Annotated[ + SortOptions | None, + typer.Option( + help="Sort entries by key. Supported keys: 'accessed', 'modified', 'name', 'size'. " + "Append ':asc' or ':desc' to explicitly set the order (e.g., 'modified:asc'). " + "Defaults: 'accessed', 'modified', 'size' default to 'desc' (newest/biggest first); " + "'name' defaults to 'asc' (alphabetical).", + ), + ] = None, + limit: Annotated[ + int | None, + typer.Option( + help="Limit the number of results returned. Returns only the top N entries after sorting.", + ), + ] = None, +) -> None: + """List cached repositories or revisions.""" + try: + hf_cache_info = scan_cache_dir(cache_dir) + except CacheNotFound as exc: + raise CLIError(f"Cache directory not found: {exc.cache_dir}") from exc + + filters = filter or [] + + entries, repo_refs_map = collect_cache_entries(hf_cache_info, include_revisions=revisions) + try: + filter_fns = [compile_cache_filter(expr, repo_refs_map) for expr in filters] + except ValueError as exc: + raise typer.BadParameter(str(exc)) from exc + + now = time.time() + for fn in filter_fns: + entries = [entry for entry in entries if fn(entry[0], entry[1], now)] + + # Apply sorting if requested + if sort: + try: + sort_key_fn, reverse = compile_cache_sort(sort.value) + entries.sort(key=sort_key_fn, reverse=reverse) + except ValueError as exc: + raise typer.BadParameter(str(exc)) from exc + + # Apply limit if requested + if limit is not None: + if limit < 0: + raise typer.BadParameter(f"Limit must be a positive integer, got {limit}.") + entries = entries[:limit] + + if revisions: + items = [ + { + "id": repo.cache_id, + "repo_id": repo.repo_id, + "repo_type": repo.repo_type, + "revision": revision.commit_hash, + "snapshot_path": str(revision.snapshot_path), + "size": revision.size_on_disk_str, + "last_modified": revision.last_modified_str, + "refs": sorted(revision.refs), + } + for repo, revision in entries + if revision is not None + ] + out.table( + items, + headers=["id", "revision", "size", "last_modified", "refs"], + id_key="revision", + alignments={"size": "right"}, + ) + else: + items = [ + { + "id": repo.cache_id, + "repo_id": repo.repo_id, + "repo_type": repo.repo_type, + "size": repo.size_on_disk_str, + "last_accessed": repo.last_accessed_str or "", + "last_modified": repo.last_modified_str, + "refs": sorted(repo_refs_map.get(repo, frozenset())), + } + for repo, _ in entries + ] + out.table( + items, + headers=["id", "size", "last_accessed", "last_modified", "refs"], + id_key="id", + alignments={"size": "right"}, + ) + + if entries: + unique_repos = {repo for repo, _ in entries} + repo_count = len(unique_repos) + if revisions: + revision_count = sum(1 for _, rev in entries if rev is not None) + total_size = sum(rev.size_on_disk for _, rev in entries if rev is not None) + else: + revision_count = sum(len(repo.revisions) for repo in unique_repos) + total_size = sum(repo.size_on_disk for repo in unique_repos) + out.text( + ANSI.bold( + f"\nFound {repo_count} repo(s) for a total of {revision_count} revision(s)" + f" and {_format_size(total_size)} on disk." + ) + ) + + +@cache_cli.command( + examples=[ + "hf cache rm model/gpt2", + "hf cache rm ", + "hf cache rm model/gpt2 --dry-run", + "hf cache rm model/gpt2 --yes", + ], +) +def rm( + targets: Annotated[ + list[str], + typer.Argument( + help="One or more repo IDs (e.g. model/bert-base-uncased) or revision hashes to delete.", + ), + ], + cache_dir: Annotated[ + str | None, + typer.Option( + help="Cache directory to scan (defaults to Hugging Face cache).", + ), + ] = None, + yes: Annotated[ + bool, + typer.Option( + "-y", + "--yes", + help="Skip confirmation prompt.", + ), + ] = False, + dry_run: Annotated[ + bool, + typer.Option( + help="Preview deletions without removing anything.", + ), + ] = False, +) -> None: + """Remove cached repositories or revisions.""" + try: + hf_cache_info = scan_cache_dir(cache_dir) + except CacheNotFound as exc: + raise CLIError(f"Cache directory not found: {exc.cache_dir}") from exc + + resolution = _resolve_deletion_targets(hf_cache_info, targets) + + if resolution.missing: + details = "\n".join(f" - {entry}" for entry in resolution.missing) + out.warning(f"Could not find in cache:\n{details}") + + if len(resolution.revisions) == 0: + out.text("Nothing to delete.") + raise typer.Exit(code=0) + + strategy = hf_cache_info.delete_revisions(*sorted(resolution.revisions)) + counts = summarize_deletions(resolution.selected) + + summary_parts: list[str] = [] + if counts.repo_count: + summary_parts.append(f"{counts.repo_count} repo(s)") + if counts.partial_revision_count: + summary_parts.append(f"{counts.partial_revision_count} revision(s)") + if not summary_parts: + summary_parts.append(f"{counts.total_revision_count} revision(s)") + + summary_text = " and ".join(summary_parts) + out.text(f"About to delete {summary_text} totalling {strategy.expected_freed_size_str}.") + print_cache_selected_revisions(resolution.selected) + + if dry_run: + out.result( + "Dry run: no files were deleted.", + dry_run=True, + repos=counts.repo_count, + revisions=counts.total_revision_count, + size=strategy.expected_freed_size_str, + ) + return + + out.confirm("Proceed with deletion?", yes=yes) + + strategy.execute() + counts = summarize_deletions(resolution.selected) + out.result( + f"Deleted {counts.repo_count} repo(s) and {counts.total_revision_count} revision(s);" + f" freed {strategy.expected_freed_size_str}.", + repos_deleted=counts.repo_count, + revisions_deleted=counts.total_revision_count, + freed=strategy.expected_freed_size_str, + ) + + +@cache_cli.command(examples=["hf cache prune", "hf cache prune --dry-run"]) +def prune( + cache_dir: Annotated[ + str | None, + typer.Option( + help="Cache directory to scan (defaults to Hugging Face cache).", + ), + ] = None, + yes: Annotated[ + bool, + typer.Option( + "-y", + "--yes", + help="Skip confirmation prompt.", + ), + ] = False, + dry_run: Annotated[ + bool, + typer.Option( + help="Preview deletions without removing anything.", + ), + ] = False, +) -> None: + """Remove detached revisions from the cache.""" + try: + hf_cache_info = scan_cache_dir(cache_dir) + except CacheNotFound as exc: + raise CLIError(f"Cache directory not found: {exc.cache_dir}") from exc + + selected: dict[CachedRepoInfo, frozenset[CachedRevisionInfo]] = {} + revisions: set[str] = set() + for repo in hf_cache_info.repos: + detached = frozenset(revision for revision in repo.revisions if len(revision.refs) == 0) + if not detached: + continue + selected[repo] = detached + revisions.update(revision.commit_hash for revision in detached) + + if len(revisions) == 0: + out.text("No unreferenced revisions found. Nothing to prune.") + return + + resolution = _DeletionResolution( + revisions=frozenset(revisions), + selected=selected, + missing=(), + ) + strategy = hf_cache_info.delete_revisions(*sorted(resolution.revisions)) + counts = summarize_deletions(selected) + + out.text( + f"About to delete {counts.total_revision_count} unreferenced revision(s) ({strategy.expected_freed_size_str} total)." + ) + print_cache_selected_revisions(selected) + + if dry_run: + out.result( + "Dry run: no files were deleted.", + dry_run=True, + revisions=counts.total_revision_count, + size=strategy.expected_freed_size_str, + ) + return + + out.confirm("Proceed?", yes=yes) + + strategy.execute() + out.result( + f"Deleted {counts.total_revision_count} unreferenced revision(s); freed {strategy.expected_freed_size_str}.", + revisions_deleted=counts.total_revision_count, + freed=strategy.expected_freed_size_str, + ) + + +@cache_cli.command( + examples=[ + "hf cache verify gpt2", + "hf cache verify gpt2 --revision refs/pr/1", + "hf cache verify my-dataset --repo-type dataset", + ], +) +def verify( + repo_id: RepoIdArg, + repo_type: RepoTypeOpt = RepoTypeOpt.model, + revision: RevisionOpt = None, + cache_dir: Annotated[ + str | None, + typer.Option( + help="Cache directory to use when verifying files from cache (defaults to Hugging Face cache).", + ), + ] = None, + local_dir: Annotated[ + str | None, + typer.Option( + help="If set, verify files under this directory instead of the cache.", + ), + ] = None, + fail_on_missing_files: Annotated[ + bool, + typer.Option( + "--fail-on-missing-files", + help="Fail if some files exist on the remote but are missing locally.", + ), + ] = False, + fail_on_extra_files: Annotated[ + bool, + typer.Option( + "--fail-on-extra-files", + help="Fail if some files exist locally but are not present on the remote revision.", + ), + ] = False, + token: TokenOpt = None, +) -> None: + """Verify checksums for a single repo revision from cache or a local directory. + + Examples: + - Verify main revision in cache: `hf cache verify gpt2` + - Verify specific revision: `hf cache verify gpt2 --revision refs/pr/1` + - Verify dataset: `hf cache verify karpathy/fineweb-edu-100b-shuffle --repo-type dataset` + - Verify local dir: `hf cache verify deepseek-ai/DeepSeek-OCR --local-dir /path/to/repo` + """ + + if local_dir is not None and cache_dir is not None: + out.error("Cannot pass both --local-dir and --cache-dir. Use one or the other.") + raise typer.Exit(code=2) + + api = get_hf_api(token=token) + + result = api.verify_repo_checksums( + repo_id=repo_id, + repo_type=repo_type.value if hasattr(repo_type, "value") else str(repo_type), + revision=revision, + local_dir=local_dir, + cache_dir=cache_dir, + token=token, + ) + + exit_code = 0 + + if result.mismatches: + details = "\n".join( + f" - {m['path']}: expected {m['expected']} ({m['algorithm']}), got {m['actual']}" + for m in result.mismatches + ) + out.text(f"❌ Checksum verification failed for the following file(s):\n{details}") + exit_code = 1 + + if result.missing_paths: + if fail_on_missing_files: + details = "\n".join(f" - {p}" for p in result.missing_paths) + out.text(f"❌ Missing files (present remotely, absent locally):\n{details}") + exit_code = 1 + else: + out.warning( + f"{len(result.missing_paths)} remote file(s) are missing locally. " + "Use --fail-on-missing-files for details." + ) + + if result.extra_paths: + if fail_on_extra_files: + details = "\n".join(f" - {p}" for p in result.extra_paths) + out.text(f"❌ Extra files (present locally, absent remotely):\n{details}") + exit_code = 1 + else: + out.warning( + f"{len(result.extra_paths)} local file(s) do not exist on the remote repo. " + "Use --fail-on-extra-files for details." + ) + + verified_location = result.verified_path + + if exit_code != 0: + out.error( + f"Verification failed for '{repo_id}' ({repo_type.value}) in {verified_location}.\n Revision: {result.revision}" + ) + raise typer.Exit(code=exit_code) + + out.result( + f"Verified {result.checked_count} file(s) for {repo_type.value} '{repo_id}'. All checksums match.", + repo_id=repo_id, + repo_type=repo_type.value, + checked=result.checked_count, + path=str(verified_location), + ) diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/collections.py b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/collections.py new file mode 100644 index 0000000000000000000000000000000000000000..aa0c8a81c07c4986235ea31a793be4dc33494af3 --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/collections.py @@ -0,0 +1,316 @@ +# Copyright 2026 The HuggingFace Team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Contains commands to interact with collections on the Hugging Face Hub. + +Usage: + # list collections on the Hub + hf collections ls + + # list collections for a specific user + hf collections ls --owner username + + # get info about a collection + hf collections info username/collection-slug + + # create a new collection + hf collections create "My Collection" --description "A collection of models" + + # add an item to a collection + hf collections add-item username/collection-slug username/model-name model + + # delete a collection + hf collections delete username/collection-slug +""" + +import enum +from typing import Annotated, get_args + +import typer + +from huggingface_hub.hf_api import CollectionItemType_T, CollectionSort_T + +from ._cli_utils import LimitOpt, TokenOpt, api_object_to_dict, get_hf_api, typer_factory +from ._output import out + + +# Build enums dynamically from Literal types to avoid duplication +_COLLECTION_ITEM_TYPES = get_args(CollectionItemType_T) +CollectionItemType = enum.Enum("CollectionItemType", {t: t for t in _COLLECTION_ITEM_TYPES}, type=str) # type: ignore[misc] + +_COLLECTION_SORT_OPTIONS = get_args(CollectionSort_T) +CollectionSort = enum.Enum("CollectionSort", {s: s for s in _COLLECTION_SORT_OPTIONS}, type=str) # type: ignore[misc] + + +collections_cli = typer_factory(help="Interact with collections on the Hub.") + + +@collections_cli.command( + "list | ls", + examples=[ + "hf collections ls", + "hf collections ls --owner nvidia", + "hf collections ls --item models/teknium/OpenHermes-2.5-Mistral-7B --limit 10", + ], +) +def collections_ls( + owner: Annotated[ + str | None, + typer.Option(help="Filter by owner username or organization."), + ] = None, + item: Annotated[ + str | None, + typer.Option( + help='Filter collections containing a specific item (e.g., "models/gpt2", "datasets/squad", "papers/2311.12983").' + ), + ] = None, + sort: Annotated[ + CollectionSort | None, + typer.Option(help="Sort results by last modified, trending, or upvotes."), + ] = None, + limit: LimitOpt = 10, + token: TokenOpt = None, +) -> None: + """List collections on the Hub.""" + api = get_hf_api(token=token) + sort_key = sort.value if sort else None + results = [ + api_object_to_dict(collection) + for collection in api.list_collections( + owner=owner, + item=item, + sort=sort_key, # type: ignore[arg-type] + limit=limit, + ) + ] + out.table(results) + + +@collections_cli.command( + "info", + examples=[ + "hf collections info username/my-collection-slug", + ], +) +def collections_info( + collection_slug: Annotated[str, typer.Argument(help="The collection slug (e.g., 'username/collection-slug').")], + token: TokenOpt = None, +) -> None: + """Get info about a collection on the Hub.""" + api = get_hf_api(token=token) + collection = api.get_collection(collection_slug) + out.dict(collection) + + +@collections_cli.command( + "create", + examples=[ + 'hf collections create "My Models"', + 'hf collections create "My Models" --description "A collection of my favorite models" --private', + 'hf collections create "Org Collection" --namespace my-org', + ], +) +def collections_create( + title: Annotated[str, typer.Argument(help="The title of the collection.")], + namespace: Annotated[ + str | None, + typer.Option(help="The namespace (username or organization). Defaults to the authenticated user."), + ] = None, + description: Annotated[ + str | None, + typer.Option(help="A description for the collection."), + ] = None, + private: Annotated[ + bool, + typer.Option(help="Create a private collection."), + ] = False, + exists_ok: Annotated[ + bool, + typer.Option(help="Do not raise an error if the collection already exists."), + ] = False, + token: TokenOpt = None, +) -> None: + """Create a new collection on the Hub.""" + api = get_hf_api(token=token) + collection = api.create_collection( + title=title, + namespace=namespace, + description=description, + private=private, + exists_ok=exists_ok, + ) + out.result("Collection created", slug=collection.slug, url=collection.url) + + +@collections_cli.command( + "update", + examples=[ + 'hf collections update username/my-collection --title "New Title"', + 'hf collections update username/my-collection --description "Updated description"', + "hf collections update username/my-collection --private --theme green", + ], +) +def collections_update( + collection_slug: Annotated[str, typer.Argument(help="The collection slug (e.g., 'username/collection-slug').")], + title: Annotated[ + str | None, + typer.Option(help="The new title for the collection."), + ] = None, + description: Annotated[ + str | None, + typer.Option(help="The new description for the collection."), + ] = None, + position: Annotated[ + int | None, + typer.Option(help="The new position of the collection in the owner's list."), + ] = None, + private: Annotated[ + bool | None, + typer.Option(help="Whether the collection should be private."), + ] = None, + theme: Annotated[ + str | None, + typer.Option(help="The theme color for the collection (e.g., 'green', 'blue')."), + ] = None, + token: TokenOpt = None, +) -> None: + """Update a collection's metadata on the Hub.""" + api = get_hf_api(token=token) + collection = api.update_collection_metadata( + collection_slug=collection_slug, + title=title, + description=description, + position=position, + private=private, + theme=theme, + ) + out.result("Collection updated", slug=collection.slug, url=collection.url) + + +@collections_cli.command( + "delete", + examples=[ + "hf collections delete username/my-collection", + "hf collections delete username/my-collection --missing-ok", + ], +) +def collections_delete( + collection_slug: Annotated[str, typer.Argument(help="The collection slug (e.g., 'username/collection-slug').")], + missing_ok: Annotated[ + bool, + typer.Option(help="Do not raise an error if the collection doesn't exist."), + ] = False, + token: TokenOpt = None, +) -> None: + """Delete a collection from the Hub.""" + api = get_hf_api(token=token) + api.delete_collection(collection_slug, missing_ok=missing_ok) + out.result("Collection deleted", slug=collection_slug) + + +@collections_cli.command( + "add-item", + examples=[ + "hf collections add-item username/my-collection moonshotai/kimi-k2 model", + 'hf collections add-item username/my-collection Qwen/DeepPlanning dataset --note "Useful dataset"', + "hf collections add-item username/my-collection Tongyi-MAI/Z-Image space", + ], +) +def collections_add_item( + collection_slug: Annotated[str, typer.Argument(help="The collection slug (e.g., 'username/collection-slug').")], + item_id: Annotated[ + str, typer.Argument(help="The ID of the item to add (repo_id for repos, paper ID for papers).") + ], + item_type: Annotated[ + CollectionItemType, + typer.Argument(help="The type of item (model, dataset, space, paper, collection, or bucket)."), + ], + note: Annotated[ + str | None, + typer.Option(help="A note to attach to the item (max 500 characters)."), + ] = None, + exists_ok: Annotated[ + bool, + typer.Option(help="Do not raise an error if the item is already in the collection."), + ] = False, + token: TokenOpt = None, +) -> None: + """Add an item to a collection.""" + api = get_hf_api(token=token) + collection = api.add_collection_item( + collection_slug=collection_slug, + item_id=item_id, + item_type=item_type.value, # type: ignore[arg-type] + note=note, + exists_ok=exists_ok, + ) + out.result("Item added to collection", slug=collection_slug, url=collection.url) + + +@collections_cli.command( + "update-item", + examples=[ + 'hf collections update-item username/my-collection ITEM_OBJECT_ID --note "Updated note"', + "hf collections update-item username/my-collection ITEM_OBJECT_ID --position 0", + ], +) +def collections_update_item( + collection_slug: Annotated[str, typer.Argument(help="The collection slug (e.g., 'username/collection-slug').")], + item_object_id: Annotated[ + str, + typer.Argument(help="The ID of the item in the collection (from 'item_object_id' field, not the repo_id)."), + ], + note: Annotated[ + str | None, + typer.Option(help="A new note for the item (max 500 characters)."), + ] = None, + position: Annotated[ + int | None, + typer.Option(help="The new position of the item in the collection."), + ] = None, + token: TokenOpt = None, +) -> None: + """Update an item in a collection.""" + api = get_hf_api(token=token) + api.update_collection_item( + collection_slug=collection_slug, + item_object_id=item_object_id, + note=note, + position=position, + ) + out.result("Item updated in collection", slug=collection_slug) + + +@collections_cli.command("delete-item") +def collections_delete_item( + collection_slug: Annotated[str, typer.Argument(help="The collection slug (e.g., 'username/collection-slug').")], + item_object_id: Annotated[ + str, + typer.Argument( + help="The ID of the item in the collection (retrieved from `item_object_id` field returned by 'hf collections info'." + ), + ], + missing_ok: Annotated[ + bool, + typer.Option(help="Do not raise an error if the item doesn't exist."), + ] = False, + token: TokenOpt = None, +) -> None: + """Delete an item from a collection.""" + api = get_hf_api(token=token) + api.delete_collection_item( + collection_slug=collection_slug, + item_object_id=item_object_id, + missing_ok=missing_ok, + ) + out.result("Item deleted from collection", slug=collection_slug) diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/datasets.py b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/datasets.py new file mode 100644 index 0000000000000000000000000000000000000000..14227f0e1e54c47908b38f696f87ad4fc1e9affb --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/datasets.py @@ -0,0 +1,286 @@ +# Copyright 2026 The HuggingFace Team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Contains commands to interact with datasets on the Hugging Face Hub. + +Usage: + # list datasets on the Hub + hf datasets ls + + # list datasets with a search query + hf datasets ls --search "code" + + # get info about a dataset + hf datasets info HuggingFaceFW/fineweb +""" + +import enum +from typing import Annotated, get_args + +import typer + +from huggingface_hub._dataset_viewer import execute_raw_sql_query +from huggingface_hub.errors import CLIError, RepositoryNotFoundError, RevisionNotFoundError +from huggingface_hub.hf_api import DatasetSort_T, ExpandDatasetProperty_T +from huggingface_hub.repocard import DatasetCard + +from ._cli_utils import ( + REPO_LIST_DEFAULT_LIMIT, + AuthorOpt, + FilterOpt, + LimitOpt, + RevisionOpt, + SearchOpt, + TokenOpt, + api_object_to_dict, + get_hf_api, + make_expand_properties_parser, + typer_factory, +) +from ._file_listing import list_repo_files_cmd +from ._output import out + + +_EXPAND_PROPERTIES = sorted(get_args(ExpandDatasetProperty_T)) +_SORT_OPTIONS = get_args(DatasetSort_T) +DatasetSortEnum = enum.Enum("DatasetSortEnum", {s: s for s in _SORT_OPTIONS}, type=str) # type: ignore[misc] + + +ExpandOpt = Annotated[ + str | None, + typer.Option( + help=f"Comma-separated properties to return. When used, only the listed properties (and id) are returned. Example: '--expand=downloads,likes,tags'. Valid: {', '.join(_EXPAND_PROPERTIES)}.", + callback=make_expand_properties_parser(_EXPAND_PROPERTIES), + ), +] + + +datasets_cli = typer_factory(help="Interact with datasets on the Hub.") + + +@datasets_cli.command( + "list | ls", + examples=[ + "hf datasets ls", + "hf datasets ls --sort downloads --limit 10", + 'hf datasets ls --search "code"', + "hf datasets ls --filter benchmark:official", + "hf datasets ls HuggingFaceFW/fineweb", + "hf datasets ls HuggingFaceFW/fineweb -R", + "hf datasets ls HuggingFaceFW/fineweb --tree -h", + ], +) +def datasets_ls( + repo_id: Annotated[ + str | None, + typer.Argument(help="Dataset ID (e.g. `username/repo-name`) to list files from. If omitted, lists datasets."), + ] = None, + search: SearchOpt = None, + author: AuthorOpt = None, + filter: FilterOpt = None, + sort: Annotated[ + DatasetSortEnum | None, + typer.Option(help="Sort results."), + ] = None, + limit: LimitOpt = REPO_LIST_DEFAULT_LIMIT, + expand: ExpandOpt = None, + human_readable: Annotated[ + bool, + typer.Option("--human-readable", "-h", help="Show sizes in human readable format (only for listing files)."), + ] = False, + as_tree: Annotated[ + bool, + typer.Option("--tree", help="List files in tree format (only for listing files)."), + ] = False, + recursive: Annotated[ + bool, + typer.Option("--recursive", "-R", help="List files recursively (only for listing files)."), + ] = False, + revision: RevisionOpt = None, + token: TokenOpt = None, +) -> None: + """List datasets on the Hub, or files in a dataset repo. + + When called with no argument, lists datasets on the Hub. + When called with a dataset ID, lists files in that dataset repo. + """ + if repo_id is not None: + if search is not None: + raise typer.BadParameter("Cannot use --search when listing files.") + if author is not None: + raise typer.BadParameter("Cannot use --author when listing files.") + if filter is not None: + raise typer.BadParameter("Cannot use --filter when listing files.") + if sort is not None: + raise typer.BadParameter("Cannot use --sort when listing files.") + if limit != REPO_LIST_DEFAULT_LIMIT: + raise typer.BadParameter("Cannot use --limit when listing files.") + if expand is not None: + raise typer.BadParameter("Cannot use --expand when listing files.") + return list_repo_files_cmd( + repo_id=repo_id, + repo_type="dataset", + human_readable=human_readable, + as_tree=as_tree, + recursive=recursive, + revision=revision, + token=token, + ) + + if as_tree: + raise typer.BadParameter("Cannot use --tree when listing datasets.") + if recursive: + raise typer.BadParameter("Cannot use --recursive when listing datasets.") + if human_readable: + raise typer.BadParameter("Cannot use --human-readable when listing datasets.") + if revision is not None: + raise typer.BadParameter("Cannot use --revision when listing datasets.") + + api = get_hf_api(token=token) + sort_key = sort.value if sort else None + results = [ + api_object_to_dict(dataset_info) + for dataset_info in api.list_datasets( + filter=filter, + author=author, + search=search, + sort=sort_key, + limit=limit, + expand=expand, # type: ignore + ) + ] + out.table(results) + + +@datasets_cli.command( + "leaderboard", + examples=[ + "hf datasets leaderboard SWE-bench/SWE-bench_Verified", + "hf datasets leaderboard SWE-bench/SWE-bench_Verified --limit 5 --format json", + "hf datasets ls --filter benchmark:official # list available leaderboards", + ], +) +def datasets_leaderboard( + dataset_id: Annotated[str, typer.Argument(help="The benchmark dataset ID (e.g. `SWE-bench/SWE-bench_Verified`).")], + limit: LimitOpt = 20, + token: TokenOpt = None, +) -> None: + """List model scores from a dataset leaderboard. This command helps find the best models for a task or compare models by benchmark scores. Use 'hf datasets ls --filter benchmark:official' to list available leaderboards.""" + api = get_hf_api(token=token) + leaderboard = api.get_dataset_leaderboard(repo_id=dataset_id) + results = [api_object_to_dict(entry) for entry in leaderboard[:limit]] + out.table( + results, + headers=["rank", "model_id", "value", "source"], + id_key="model_id", + alignments={"rank": "right", "value": "right"}, + ) + out.hint("Use 'hf datasets ls --filter benchmark:official' to list available leaderboards.") + if leaderboard: + out.hint(f"Use 'hf models info {leaderboard[0].model_id}' to get details about a model.") + + +@datasets_cli.command( + "info", + examples=[ + "hf datasets info HuggingFaceFW/fineweb", + "hf datasets info my-dataset --expand downloads,likes,tags", + ], +) +def datasets_info( + dataset_id: Annotated[str, typer.Argument(help="The dataset ID (e.g. `username/repo-name`).")], + revision: RevisionOpt = None, + expand: ExpandOpt = None, + token: TokenOpt = None, +) -> None: + """Get info about a dataset on the Hub.""" + api = get_hf_api(token=token) + try: + info = api.dataset_info(repo_id=dataset_id, revision=revision, expand=expand) # type: ignore + except RepositoryNotFoundError as e: + raise CLIError(f"Dataset '{dataset_id}' not found.") from e + except RevisionNotFoundError as e: + raise CLIError(f"Revision '{revision}' not found on '{dataset_id}'.") from e + out.dict(info) + + +@datasets_cli.command( + "parquet", + examples=[ + "hf datasets parquet cfahlgren1/hub-stats", + "hf datasets parquet cfahlgren1/hub-stats --subset models", + "hf datasets parquet cfahlgren1/hub-stats --split train", + "hf datasets parquet cfahlgren1/hub-stats --format json", + ], +) +def datasets_parquet( + dataset_id: Annotated[str, typer.Argument(help="The dataset ID (e.g. `username/repo-name`).")], + subset: Annotated[str | None, typer.Option("--subset", help="Filter parquet entries by subset/config.")] = None, + split: Annotated[str | None, typer.Option(help="Filter parquet entries by split.")] = None, + token: TokenOpt = None, +) -> None: + """List parquet file URLs available for a dataset.""" + api = get_hf_api(token=token) + entries = api.list_dataset_parquet_files(repo_id=dataset_id, config=subset) + filtered = [entry for entry in entries if split is None or entry.split == split] + results = [ + {"subset": entry.config, "split": entry.split, "url": entry.url, "size": entry.size} for entry in filtered + ] + out.table(results, headers=["subset", "split", "url", "size"], id_key="url") + + +@datasets_cli.command( + "sql", + examples=[ + "hf datasets sql \"SELECT COUNT(*) AS rows FROM read_parquet('https://huggingface.co/api/datasets/cfahlgren1/hub-stats/parquet/models/train/0.parquet')\"", + "hf datasets sql \"SELECT * FROM read_parquet('https://huggingface.co/api/datasets/cfahlgren1/hub-stats/parquet/models/train/0.parquet') LIMIT 5\" --format json", + ], +) +def datasets_sql( + sql: Annotated[str, typer.Argument(help="Raw SQL query to execute.")], + token: TokenOpt = None, +) -> None: + """Execute a raw SQL query with DuckDB against dataset parquet URLs.""" + try: + result = execute_raw_sql_query(sql_query=sql, token=token) + except ImportError as e: + raise CLIError(str(e)) from e + out.table(result) + + +@datasets_cli.command( + "card", + examples=[ + "hf datasets card HuggingFaceFW/fineweb", + "hf datasets card HuggingFaceFW/fineweb --metadata", + "hf datasets card HuggingFaceFW/fineweb --metadata --format json", + "hf datasets card HuggingFaceFW/fineweb --text", + ], +) +def datasets_card( + dataset_id: Annotated[str, typer.Argument(help="The dataset ID (e.g. `username/repo-name`).")], + metadata: Annotated[bool, typer.Option("--metadata", help="Output only the metadata from the card.")] = False, + text: Annotated[bool, typer.Option("--text", help="Output only the text body (no metadata).")] = False, + token: TokenOpt = None, +) -> None: + """Get the dataset card (README) for a dataset on the Hub.""" + if metadata and text: + raise CLIError("--metadata and --text are mutually exclusive.") + card = DatasetCard.load(dataset_id, token=token) + if metadata: + out.dict(card.data.to_dict()) + elif text: + out.text(card.text) + else: + out.text(card.content) + out.hint(f"Use `hf datasets card {dataset_id} --metadata` to extract only the card metadata.") diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/deprecated_cli.py b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/deprecated_cli.py new file mode 100644 index 0000000000000000000000000000000000000000..4fbdd8adaba77accf24fbe0d459b4714d503b781 --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/deprecated_cli.py @@ -0,0 +1,35 @@ +"""Deprecated `huggingface-cli` entry point. Warns and exits.""" + +import shutil +import sys + +from ._output import out + + +def main() -> None: + out.warning("`huggingface-cli` is deprecated and no longer works. Use `hf` instead.\n") + + if shutil.which("hf"): + from huggingface_hub.cli._cli_utils import check_cli_update + + check_cli_update("huggingface_hub") + out.hint("`hf` is already installed! Use it directly.\n") + else: + out.hint( + "Install `hf`:\n" + " Standalone (recommended): curl -LsSf https://hf.co/cli/install.sh | bash\n" + " Using Homebrew: brew install hf\n" + " Using pip: pip install huggingface_hub\n", + ) + + out.hint( + "Examples:\n" + " hf auth login\n" + " hf download unsloth/gemma-4-31B-it-GGUF\n" + " hf upload my-cool-model . .\n" + ' hf models ls --search "gemma"\n' + " hf repos ls --format json\n" + " hf jobs run python:3.12 python -c 'print(\"Hello!\")'\n" + " hf --help\n", + ) + sys.exit(1) diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/discussions.py b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/discussions.py new file mode 100644 index 0000000000000000000000000000000000000000..5575064a9d001bc714525c682484a0cf4ea48540 --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/discussions.py @@ -0,0 +1,450 @@ +# Copyright 2026 The HuggingFace Team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Contains commands to interact with discussions and pull requests on the Hugging Face Hub.""" + +import enum +import sys +from pathlib import Path +from typing import Annotated + +import typer + +from huggingface_hub import constants + +from ._cli_utils import ( + AuthorOpt, + LimitOpt, + RepoIdArg, + RepoType, + RepoTypeOpt, + TokenOpt, + api_object_to_dict, + get_hf_api, + typer_factory, +) +from ._output import out + + +class DiscussionStatus(str, enum.Enum): + open = "open" + closed = "closed" + merged = "merged" + draft = "draft" + all = "all" + + +class DiscussionKind(str, enum.Enum): + all = "all" + discussion = "discussion" + pull_request = "pull_request" + + +# "merged" and "draft" are valid Discussion statuses but the Hub API filter +# (DiscussionStatusFilter) only accepts "all", "open", "closed". When the user +# asks for merged/draft we fetch with api_status=None (i.e. all) and filter +# client-side. +_CLIENT_SIDE_STATUSES = {"merged", "draft"} + + +DiscussionNumArg = Annotated[ + int, + typer.Argument( + help="The discussion or pull request number.", + min=1, + ), +] + + +def _read_body(body: str | None, body_file: Path | None) -> str | None: + """Resolve body text from --body or --body-file (supports '-' for stdin).""" + if body is not None and body_file is not None: + raise typer.BadParameter("Cannot use both --body and --body-file.") + if body_file is not None: + if str(body_file) == "-": + return sys.stdin.read() + return body_file.read_text(encoding="utf-8") + return body + + +discussions_cli = typer_factory(help="Manage discussions and pull requests on the Hub.") + + +@discussions_cli.command( + "list | ls", + examples=[ + "hf discussions list username/my-model", + "hf discussions list username/my-model --kind pull_request --status merged", + "hf discussions list username/my-dataset --type dataset --status closed", + "hf discussions list username/my-model --author alice --format json", + ], +) +def discussion_list( + repo_id: RepoIdArg, + status: Annotated[ + DiscussionStatus, + typer.Option( + "-s", + "--status", + help="Filter by status (open, closed, merged, draft, all).", + ), + ] = DiscussionStatus.open, + kind: Annotated[ + DiscussionKind, + typer.Option( + "-k", + "--kind", + help="Filter by kind (discussion, pull_request, all).", + ), + ] = DiscussionKind.all, + author: AuthorOpt = None, + limit: LimitOpt = 30, + repo_type: RepoTypeOpt = RepoType.model, + token: TokenOpt = None, +) -> None: + """List discussions and pull requests on a repo.""" + api = get_hf_api(token=token) + + api_status: constants.DiscussionStatusFilter | None + if status == DiscussionStatus.open: + api_status = "open" + elif status == DiscussionStatus.closed: + api_status = "closed" + else: + api_status = None + + api_discussion_type: constants.DiscussionTypeFilter | None + if kind == DiscussionKind.all: + api_discussion_type = None + else: + api_discussion_type = kind.value # type: ignore[assignment] + + discussions = [] + for d in api.get_repo_discussions( + repo_id=repo_id, + author=author, + discussion_type=api_discussion_type, + discussion_status=api_status, + repo_type=repo_type.value, + ): + if status.value in _CLIENT_SIDE_STATUSES and d.status != status.value: + continue + discussions.append(d) + if len(discussions) >= limit: + break + + items = [api_object_to_dict(d) for d in discussions] + out.table( + items, + headers=["num", "title", "is_pull_request", "status", "author", "created_at"], + id_key="num", + alignments={"num": "right"}, + ) + + +@discussions_cli.command( + "info", + examples=[ + "hf discussions info username/my-model 5", + "hf discussions info username/my-model 5 --format json", + ], +) +def discussion_info( + repo_id: RepoIdArg, + num: DiscussionNumArg, + repo_type: RepoTypeOpt = RepoType.model, + token: TokenOpt = None, +) -> None: + """Get info about a discussion or pull request.""" + api = get_hf_api(token=token) + details = api.get_discussion_details( + repo_id=repo_id, + discussion_num=num, + repo_type=repo_type.value, + ) + out.dict(details) + + +@discussions_cli.command( + "create", + examples=[ + 'hf discussions create username/my-model --title "Bug report"', + 'hf discussions create username/my-model --title "Feature request" --body "Please add X"', + 'hf discussions create username/my-model --title "Fix typo" --pull-request', + 'hf discussions create username/my-dataset --type dataset --title "Data quality issue"', + ], +) +def discussion_create( + repo_id: RepoIdArg, + title: Annotated[ + str, + typer.Option( + "--title", + help="The title of the discussion or pull request.", + ), + ], + body: Annotated[ + str | None, + typer.Option( + "--body", + help="The description (supports Markdown).", + ), + ] = None, + body_file: Annotated[ + Path | None, + typer.Option( + "--body-file", + help="Read the description from a file. Use '-' for stdin.", + ), + ] = None, + pull_request: Annotated[ + bool, + typer.Option( + "--pull-request", + "--pr", + help="Create a pull request instead of a discussion.", + ), + ] = False, + repo_type: RepoTypeOpt = RepoType.model, + token: TokenOpt = None, +) -> None: + """Create a new discussion or pull request on a repo.""" + description = _read_body(body, body_file) + api = get_hf_api(token=token) + discussion = api.create_discussion( + repo_id=repo_id, + title=title, + description=description, + repo_type=repo_type.value, + pull_request=pull_request, + ) + kind = "pull request" if pull_request else "discussion" + ref = f"refs/pr/{discussion.num}" if pull_request else None + out.result(f"Created {kind} #{discussion.num} on {repo_id}", num=discussion.num, url=discussion.url, ref=ref) + + +@discussions_cli.command( + "comment", + examples=[ + 'hf discussions comment username/my-model 5 --body "Thanks for reporting!"', + 'hf discussions comment username/my-model 5 --body "LGTM!"', + ], +) +def discussion_comment( + repo_id: RepoIdArg, + num: DiscussionNumArg, + body: Annotated[ + str | None, + typer.Option( + "--body", + help="The comment text (supports Markdown).", + ), + ] = None, + body_file: Annotated[ + Path | None, + typer.Option( + "--body-file", + help="Read the comment from a file. Use '-' for stdin.", + ), + ] = None, + repo_type: RepoTypeOpt = RepoType.model, + token: TokenOpt = None, +) -> None: + """Comment on a discussion or pull request.""" + comment = _read_body(body, body_file) + if comment is None: + raise typer.BadParameter("Either --body or --body-file is required.") + api = get_hf_api(token=token) + api.comment_discussion( + repo_id=repo_id, + discussion_num=num, + comment=comment, + repo_type=repo_type.value, + ) + out.result(f"Commented on #{num} in {repo_id}", num=num, repo=repo_id) + + +@discussions_cli.command( + "close", + examples=[ + "hf discussions close username/my-model 5", + 'hf discussions close username/my-model 5 --comment "Closing as resolved."', + ], +) +def discussion_close( + repo_id: RepoIdArg, + num: DiscussionNumArg, + comment: Annotated[ + str | None, + typer.Option( + "--comment", + help="An optional comment to post when closing.", + ), + ] = None, + yes: Annotated[ + bool, + typer.Option( + "--yes", + "-y", + help="Skip confirmation prompt.", + ), + ] = False, + repo_type: RepoTypeOpt = RepoType.model, + token: TokenOpt = None, +) -> None: + """Close a discussion or pull request.""" + out.confirm(f"Close #{num} on '{repo_id}'?", yes=yes) + api = get_hf_api(token=token) + api.change_discussion_status( + repo_id=repo_id, + discussion_num=num, + new_status="closed", + comment=comment, + repo_type=repo_type.value, + ) + out.result(f"Closed #{num} in {repo_id}", num=num, repo=repo_id) + + +@discussions_cli.command( + "reopen", + examples=[ + "hf discussions reopen username/my-model 5", + 'hf discussions reopen username/my-model 5 --comment "Reopening for further investigation."', + ], +) +def discussion_reopen( + repo_id: RepoIdArg, + num: DiscussionNumArg, + comment: Annotated[ + str | None, + typer.Option( + "--comment", + help="An optional comment to post when reopening.", + ), + ] = None, + yes: Annotated[ + bool, + typer.Option( + "--yes", + "-y", + help="Skip confirmation prompt.", + ), + ] = False, + repo_type: RepoTypeOpt = RepoType.model, + token: TokenOpt = None, +) -> None: + """Reopen a closed discussion or pull request.""" + out.confirm(f"Reopen #{num} on '{repo_id}'?", yes=yes) + api = get_hf_api(token=token) + api.change_discussion_status( + repo_id=repo_id, + discussion_num=num, + new_status="open", + comment=comment, + repo_type=repo_type.value, + ) + out.result(f"Reopened #{num} in {repo_id}", num=num, repo=repo_id) + + +@discussions_cli.command( + "rename", + examples=[ + 'hf discussions rename username/my-model 5 "Updated title"', + ], +) +def discussion_rename( + repo_id: RepoIdArg, + num: DiscussionNumArg, + new_title: Annotated[ + str, + typer.Argument( + help="The new title.", + ), + ], + repo_type: RepoTypeOpt = RepoType.model, + token: TokenOpt = None, +) -> None: + """Rename a discussion or pull request.""" + api = get_hf_api(token=token) + api.rename_discussion( + repo_id=repo_id, + discussion_num=num, + new_title=new_title, + repo_type=repo_type.value, + ) + out.result(f"Renamed #{num} in {repo_id}", num=num, repo=repo_id, title=new_title) + + +@discussions_cli.command( + "merge", + examples=[ + "hf discussions merge username/my-model 5", + 'hf discussions merge username/my-model 5 --comment "Merging, thanks!"', + ], +) +def discussion_merge( + repo_id: RepoIdArg, + num: DiscussionNumArg, + comment: Annotated[ + str | None, + typer.Option( + "--comment", + help="An optional comment to post when merging.", + ), + ] = None, + yes: Annotated[ + bool, + typer.Option( + "--yes", + "-y", + help="Skip confirmation prompt.", + ), + ] = False, + repo_type: RepoTypeOpt = RepoType.model, + token: TokenOpt = None, +) -> None: + """Merge a pull request.""" + out.confirm(f"Merge #{num} on '{repo_id}'?", yes=yes) + api = get_hf_api(token=token) + api.merge_pull_request( + repo_id=repo_id, + discussion_num=num, + comment=comment, + repo_type=repo_type.value, + ) + out.result(f"Merged #{num} in {repo_id}", num=num, repo=repo_id) + + +@discussions_cli.command( + "diff", + examples=[ + "hf discussions diff username/my-model 5", + ], +) +def discussion_diff( + repo_id: RepoIdArg, + num: DiscussionNumArg, + repo_type: RepoTypeOpt = RepoType.model, + token: TokenOpt = None, +) -> None: + """Show the diff of a pull request.""" + api = get_hf_api(token=token) + details = api.get_discussion_details( + repo_id=repo_id, + discussion_num=num, + repo_type=repo_type.value, + ) + if details.diff: + out.text(details.diff) + else: + out.text("No diff available.") diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/download.py b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/download.py new file mode 100644 index 0000000000000000000000000000000000000000..874c9ad05837cc6b4c35cb592909c8ac24c75766 --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/download.py @@ -0,0 +1,213 @@ +# Copyright 202-present, the HuggingFace Inc. team. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Contains command to download files from the Hub with the CLI. + +Usage: + hf download --help + + # Download file + hf download gpt2 config.json + + # Download entire repo + hf download fffiloni/zeroscope --repo-type=space --revision=refs/pr/78 + + # Download repo with filters + hf download gpt2 --include="*.safetensors" + + # Download with token + hf download Wauplin/private-model --token=hf_*** + + # Download quietly (no progress bar, no warnings, only the returned path) + hf download gpt2 config.json --quiet + + # Download to local dir + hf download gpt2 --local-dir=./models/gpt2 + + # Download a subfolder + hf download HuggingFaceM4/FineVision art/ --repo-type=dataset +""" + +import warnings +from typing import Annotated + +import typer + +from huggingface_hub._snapshot_download import snapshot_download +from huggingface_hub.errors import CLIError +from huggingface_hub.file_download import DryRunFileInfo, hf_hub_download +from huggingface_hub.utils import _format_size + +from ._cli_utils import RepoIdArg, RepoTypeOpt, RevisionOpt, TokenOpt +from ._output import out + + +DOWNLOAD_EXAMPLES = [ + "hf download meta-llama/Llama-3.2-1B-Instruct", + "hf download meta-llama/Llama-3.2-1B-Instruct config.json tokenizer.json", + 'hf download meta-llama/Llama-3.2-1B-Instruct --include "*.safetensors" --exclude "*.bin"', + "hf download meta-llama/Llama-3.2-1B-Instruct --local-dir ./models/llama", + "hf download HuggingFaceM4/FineVision art/ --repo-type dataset", +] + + +def download( + repo_id: RepoIdArg, + filenames: Annotated[ + list[str] | None, + typer.Argument( + help="Files to download (e.g. `config.json`, `data/metadata.jsonl`).", + ), + ] = None, + repo_type: RepoTypeOpt = RepoTypeOpt.model, + revision: RevisionOpt = None, + include: Annotated[ + list[str] | None, + typer.Option( + help="Glob patterns to include from files to download. eg: *.json", + ), + ] = None, + exclude: Annotated[ + list[str] | None, + typer.Option( + help="Glob patterns to exclude from files to download.", + ), + ] = None, + cache_dir: Annotated[ + str | None, + typer.Option( + help="Directory where to save files.", + ), + ] = None, + local_dir: Annotated[ + str | None, + typer.Option( + help="If set, the downloaded file will be placed under this directory. Check out https://huggingface.co/docs/huggingface_hub/guides/download#download-files-to-a-local-folder for more details.", + ), + ] = None, + force_download: Annotated[ + bool, + typer.Option( + help="If True, the files will be downloaded even if they are already cached.", + ), + ] = False, + dry_run: Annotated[ + bool, + typer.Option( + help="If True, perform a dry run without actually downloading the file.", + ), + ] = False, + token: TokenOpt = None, + max_workers: Annotated[ + int, + typer.Option( + help="Maximum number of workers to use for downloading files. Default is 8.", + ), + ] = 8, +) -> None: + """Download files from the Hub.""" + + def run_download() -> str | DryRunFileInfo | list[DryRunFileInfo]: + filenames_list = filenames if filenames is not None else [] + + # Separate subfolder patterns (ending with '/') from regular filenames + # Subfolders like "art/" are converted to include patterns like "art/**" + subfolders = [f for f in filenames_list if f.endswith("/")] + subfolder_patterns = [f"{f.rstrip('/')}/**" for f in subfolders] + regular_filenames = [f for f in filenames_list if not f.endswith("/")] + + # Error if subfolder patterns are combined with --include/--exclude + # Guide user to use --include instead of subfolder argument + if len(subfolder_patterns) > 0: + if include is not None and len(include) > 0: + raise CLIError( + f"Cannot combine subfolder argument ('{subfolders[0]}') with `--include`. " + f'Please use `--include "{subfolders[0]}*"` instead.' + ) + if exclude is not None and len(exclude) > 0: + raise CLIError( + f"Cannot combine subfolder argument ('{subfolders[0]}') with `--exclude`. " + f'Please use `--include "{subfolders[0]}*"` with `--exclude` instead.' + ) + + # Warn user if patterns are ignored (only if regular filenames are provided) + if len(regular_filenames) > 0: + if include is not None and len(include) > 0: + warnings.warn("Ignoring `--include` since filenames have being explicitly set.") + if exclude is not None and len(exclude) > 0: + warnings.warn("Ignoring `--exclude` since filenames have being explicitly set.") + + # Single file to download (not a subfolder): use `hf_hub_download` + if len(regular_filenames) == 1 and len(subfolder_patterns) == 0: + return hf_hub_download( + repo_id=repo_id, + repo_type=repo_type.value, + revision=revision, + filename=regular_filenames[0], + cache_dir=cache_dir, + force_download=force_download, + token=token, + local_dir=local_dir, + library_name="huggingface-cli", + dry_run=dry_run, + ) + + # Otherwise: use `snapshot_download` to ensure all files comes from same revision + if len(regular_filenames) == 0 and len(subfolder_patterns) == 0: + # No filenames provided: use include/exclude patterns + allow_patterns = include + ignore_patterns = exclude + else: + # Combine regular filenames and subfolder patterns as allow_patterns + allow_patterns = regular_filenames + subfolder_patterns + ignore_patterns = None + + return snapshot_download( + repo_id=repo_id, + repo_type=repo_type.value, + revision=revision, + allow_patterns=allow_patterns, + ignore_patterns=ignore_patterns, + force_download=force_download, + cache_dir=cache_dir, + token=token, + local_dir=local_dir, + library_name="huggingface-cli", + max_workers=max_workers, + dry_run=dry_run, + ) + + def _print_result(result: str | DryRunFileInfo | list[DryRunFileInfo]) -> None: + if isinstance(result, str): + out.result("Downloaded", path=result) + return + + # Print dry run info + if isinstance(result, DryRunFileInfo): + result = [result] + will_download = [r for r in result if r.will_download] + out.text( + f"[dry-run] Will download {len(will_download)} files" + f" (out of {len(result)})" + f" totalling {_format_size(sum(r.file_size for r in will_download))}." + ) + items = [ + { + "file": info.filename, + "size": _format_size(info.file_size) if info.will_download else "-", + } + for info in sorted(result, key=lambda x: x.filename) + ] + out.table(items) + + _print_result(run_download()) diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/extensions.py b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/extensions.py new file mode 100644 index 0000000000000000000000000000000000000000..98f9ab303dd1abe1697f68454f116001c61a314b --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/extensions.py @@ -0,0 +1,623 @@ +# Copyright 2026 The HuggingFace Team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Contains helper utilities for hf CLI extensions.""" + +import errno +import json +import os +import re +import shutil +import subprocess +import venv +from dataclasses import asdict, dataclass +from datetime import datetime, timezone +from pathlib import Path +from typing import Annotated, Literal + +import typer + +from huggingface_hub.errors import CLIError, CLIExtensionInstallError, ConfirmationError +from huggingface_hub.utils import get_session, logging + +from ._cli_utils import typer_factory +from ._output import out + + +DEFAULT_EXTENSION_OWNER = "huggingface" +EXTENSIONS_ROOT = Path("~/.local/share/hf/extensions") +MANIFEST_FILENAME = "manifest.json" +EXTENSIONS_HELP = ( + "Manage hf CLI extensions.\n\n" + "Security Warning: extensions are third-party executables or Python packages. " + "Install only from sources you trust." +) +extensions_cli = typer_factory(help=EXTENSIONS_HELP) +_EXTENSIONS_DEFAULT_BRANCH = "main" # Fallback when the GitHub API is unreachable. +_EXTENSIONS_GITHUB_TOPIC = "hf-extension" +_EXTENSIONS_DOWNLOAD_TIMEOUT = 10 +_EXTENSIONS_PIP_INSTALL_TIMEOUT = 300 + +logger = logging.get_logger(__name__) + + +@dataclass +class ExtensionManifest: + owner: str + repo: str + repo_id: str + short_name: str + executable_name: str + executable_path: str + type: Literal["binary", "python"] + installed_at: datetime + source: str + description: str | None = None + + @classmethod + def load(cls, path: Path) -> "ExtensionManifest": + manifest_path = path / MANIFEST_FILENAME + if not manifest_path.is_file(): + raise CLIError(f"Manifest file not found at {manifest_path}. Your extension may be corrupted.") + data = json.loads(manifest_path.read_text()) + data["installed_at"] = datetime.fromisoformat(data["installed_at"]) + return ExtensionManifest(**data) + + def save(self, path: Path) -> None: + manifest_path = path / MANIFEST_FILENAME + manifest_path.parent.mkdir(parents=True, exist_ok=True) + data = asdict(self) + data["installed_at"] = self.installed_at.isoformat() + manifest_path.write_text(json.dumps(data, indent=2, sort_keys=True)) + + +@extensions_cli.command( + "install", + examples=[ + "hf extensions install hf-claude", + "hf extensions install hanouticelina/hf-claude", + "hf extensions install alvarobartt/hf-mem", + ], +) +def extension_install( + ctx: typer.Context, + repo_id: Annotated[ + str, + typer.Argument(help="GitHub extension repository in `[OWNER/]hf-` format."), + ], + force: Annotated[bool, typer.Option("--force", help="Overwrite if already installed.")] = False, +) -> None: + """Install an extension from a public GitHub repository. + + Security warning: this installs a third-party executable or Python package. + Install only from sources you trust. + """ + owner, repo_name, short_name = _normalize_repo_id(repo_id) + root_ctx = ctx.find_root() + reserved_commands = set(getattr(root_ctx.command, "commands", {}).keys()) + if short_name in reserved_commands: + raise CLIError( + f"Cannot install extension '{short_name}' because it conflicts with an existing `hf {short_name}` command." + ) + + extension_dir = _get_extension_dir(short_name) + extension_exists = extension_dir.exists() + if extension_exists and not force: + raise CLIError(f"Extension '{short_name}' is already installed. Use --force to overwrite.") + + branch, description = _resolve_github_repo_info(owner=owner, repo_name=repo_name) + + if extension_exists: + shutil.rmtree(extension_dir) + + manifest = _install_extension_from_github( + owner=owner, + repo_name=repo_name, + short_name=short_name, + extension_dir=extension_dir, + branch=branch, + description=description, + ) + ext_type = manifest.type.capitalize() + print(f"{ext_type} extension installed successfully from {owner}/{repo_name}.") + print(f"Run it with: hf {short_name}") + + +@extensions_cli.command( + "exec", + context_settings={"allow_extra_args": True, "allow_interspersed_args": False, "ignore_unknown_options": True}, + examples=[ + "hf extensions exec claude -- --help", + "hf extensions exec claude --model zai-org/GLM-5", + ], +) +def extension_exec( + ctx: typer.Context, + name: Annotated[ + str, + typer.Argument(help="Extension name (with or without `hf-` prefix)."), + ], +) -> None: + """Execute an installed extension.""" + short_name = _normalize_extension_name(name) + executable_path = _resolve_installed_executable_path(short_name) + + if not executable_path.is_file(): + raise CLIError(f"Extension '{short_name}' is not installed.") + + exit_code = _execute_extension_binary(executable_path=executable_path, args=list(ctx.args)) + raise typer.Exit(code=exit_code) + + +@extensions_cli.command("list | ls", examples=["hf extensions list"]) +def extension_list() -> None: + """List installed extension commands.""" + rows = [ + { + "command": f"hf {manifest.short_name}", + "source": str(manifest.repo_id), + "type": str(manifest.type), + "installed": manifest.installed_at.strftime("%Y-%m-%d"), + "description": manifest.description, + } + for manifest in _list_installed_extensions() + ] + out.table(rows, id_key="command") + + +@extensions_cli.command("search", examples=["hf extensions search"]) +def extension_search() -> None: + """Search extensions available on GitHub (tagged with 'hf-extension' topic).""" + response = get_session().get( + "https://api.github.com/search/repositories", + params={"q": f"topic:{_EXTENSIONS_GITHUB_TOPIC}", "sort": "stars", "order": "desc", "per_page": 100}, + follow_redirects=True, + timeout=_EXTENSIONS_DOWNLOAD_TIMEOUT, + ) + response.raise_for_status() + data = response.json() + + installed = {m.short_name for m in _list_installed_extensions()} + + rows = [] + for repo in data.get("items", []): + repo_name = repo["name"] + short_name = repo_name[3:] if repo_name.startswith("hf-") else repo_name + rows.append( + { + "name": short_name, + "repo": repo["full_name"], + "stars": repo.get("stargazers_count", 0), + "description": repo.get("description") or "", + "installed": "yes" if short_name in installed else "", + } + ) + + out.table(rows, id_key="repo", alignments={"stars": "right"}) + + +@extensions_cli.command("remove | rm", examples=["hf extensions remove claude"]) +def extension_remove( + name: Annotated[ + str, + typer.Argument(help="Extension name to remove (with or without `hf-` prefix)."), + ], +) -> None: + """Remove an installed extension.""" + short_name = _normalize_extension_name(name) + extension_dir = _get_extension_dir(short_name) + + if not extension_dir.is_dir(): + raise CLIError(f"Extension '{short_name}' is not installed.") + + shutil.rmtree(extension_dir) + print(f"Removed extension '{short_name}'.") + + +### HELPER FUNCTIONS + + +def _list_installed_extensions() -> list[ExtensionManifest]: + """Return manifests for all validly-installed extensions, sorted by directory name.""" + root_dir = EXTENSIONS_ROOT.expanduser() + if not root_dir.is_dir(): + return [] + manifests = [] + for extension_dir in sorted(root_dir.iterdir()): + if not extension_dir.is_dir() or not extension_dir.name.startswith("hf-"): + continue + try: + manifests.append(ExtensionManifest.load(extension_dir)) + except Exception as e: + logger.debug(f"Failed to load manifest for extension '{extension_dir.name}': {e}") + continue + return manifests + + +def list_installed_extensions_for_help() -> list[tuple[str, str]]: + entries = [] + for manifest in _list_installed_extensions(): + tag = f"[extension {manifest.repo_id}]" + help_text = f"{manifest.description} {tag}" if manifest.description is not None else tag + entries.append((manifest.short_name, help_text)) + return entries + + +def dispatch_unknown_top_level_extension(args: list[str], known_commands: set[str]) -> int | None: + if not args: + return None + + command_name = args[0] + if command_name.startswith("-"): + return None + all_known = {a.strip() for cmd in known_commands for a in cmd.split("|")} + if command_name in all_known: + return None + + short_name = command_name[3:] if command_name.startswith("hf-") else command_name + if not short_name: + return None + + executable_path: Path | None = None + try: + executable_path = _resolve_installed_executable_path(short_name) + except Exception: + executable_path = _auto_install_official_extension(short_name) + + if executable_path is None or not executable_path.is_file(): + return None + + return _execute_extension_binary(executable_path=executable_path, args=list(args[1:])) + + +def _auto_install_official_extension(short_name: str) -> Path | None: + """Try to auto-install huggingface/hf-. Returns executable path or None.""" + owner, repo_name = DEFAULT_EXTENSION_OWNER, f"hf-{short_name}" + try: + extension_dir = _get_extension_dir(short_name) + except Exception: + return None + if extension_dir.exists(): + return None + try: + response = get_session().get( + f"https://api.github.com/repos/{owner}/{repo_name}", + follow_redirects=True, + timeout=_EXTENSIONS_DOWNLOAD_TIMEOUT, + ) + if response.status_code == 404: + return None + response.raise_for_status() + branch = response.json()["default_branch"] + except Exception: + return None + try: + out.confirm(f"'{short_name}' is an official Hugging Face extension ({owner}/{repo_name}). Install it?") + except ConfirmationError: + return None + try: + manifest = _install_extension_from_github( + owner=owner, repo_name=repo_name, short_name=short_name, extension_dir=extension_dir, branch=branch + ) + return Path(manifest.executable_path).expanduser() + except Exception: + shutil.rmtree(extension_dir, ignore_errors=True) + return None + + +def _install_extension_from_github( + *, + owner: str, + repo_name: str, + short_name: str, + extension_dir: Path, + branch: str, + description: str | None = None, +) -> ExtensionManifest: + """Fetch, install (binary or Python), and save manifest for a GitHub extension.""" + try: + binary = _fetch_remote_binary(owner=owner, repo_name=repo_name, branch=branch, short_name=short_name) + except Exception: + binary = None + if binary is not None: + manifest = _install_binary_extension( + owner=owner, repo_name=repo_name, short_name=short_name, extension_dir=extension_dir, binary=binary + ) + else: + manifest = _install_python_extension( + owner=owner, repo_name=repo_name, short_name=short_name, extension_dir=extension_dir, branch=branch + ) + manifest.description = _try_fetch_remote_description( + owner=owner, repo_name=repo_name, branch=branch, candidate_description=description + ) + manifest.save(extension_dir) + return manifest + + +def _fetch_remote_binary(owner: str, repo_name: str, branch: str, short_name: str) -> bytes: + executable_name = _get_executable_name(short_name) + raw_url = f"https://raw.githubusercontent.com/{owner}/{repo_name}/refs/heads/{branch}/{executable_name}" + response = get_session().get(raw_url, follow_redirects=True, timeout=_EXTENSIONS_DOWNLOAD_TIMEOUT) + response.raise_for_status() + return response.content + + +def _install_binary_extension( + *, owner: str, repo_name: str, short_name: str, extension_dir: Path, binary: bytes +) -> ExtensionManifest: + # Save extension binary + executable_name = _get_executable_name(short_name) + extension_dir.mkdir(parents=True, exist_ok=False) + executable_path = extension_dir / executable_name + executable_path.write_bytes(binary) + + # Make it executable + if os.name != "nt": + os.chmod(executable_path, 0o755) + + # Create manifest + return ExtensionManifest( + owner=owner, + repo=repo_name, + repo_id=f"{owner}/{repo_name}", + short_name=short_name, + executable_name=executable_name, + executable_path=str(executable_path), + type="binary", + installed_at=datetime.now(timezone.utc), + source=f"https://github.com/{owner}/{repo_name}", + ) + + +def _install_python_extension( + *, owner: str, repo_name: str, short_name: str, extension_dir: Path, branch: str +) -> ExtensionManifest: + source_url = f"https://github.com/{owner}/{repo_name}/archive/refs/heads/{branch}.zip" + venv_dir = extension_dir / "venv" + installed = False + + status = out.status() + try: + status.update(f"Creating virtual environment in {venv_dir}") + if extension_dir.exists(): + shutil.rmtree(extension_dir, ignore_errors=True) + extension_dir.mkdir(parents=True, exist_ok=False) + + uv_path = shutil.which("uv") + venv_python = _get_venv_python_path(venv_dir) + if uv_path: + subprocess.run([uv_path, "venv", str(venv_dir)], check=True) + status.done(f"Virtual environment created in {venv_dir}") + + status.update(f"Installing package from {source_url}") + subprocess.run( + [uv_path, "pip", "install", "--python", str(venv_python), source_url], + check=True, + timeout=_EXTENSIONS_PIP_INSTALL_TIMEOUT, + ) + else: + venv.EnvBuilder(with_pip=True).create(str(venv_dir)) + status.done(f"Virtual environment created in {venv_dir}") + + status.update(f"Installing package from {source_url}") + subprocess.run( + [ + str(venv_python), + "-m", + "pip", + "install", + "--disable-pip-version-check", + "--no-input", + source_url, + ], + check=True, + timeout=_EXTENSIONS_PIP_INSTALL_TIMEOUT, + ) + status.done(f"Package installed from {source_url}") + + executable_name = _get_executable_name(short_name) + venv_executable = _get_venv_extension_executable_path(venv_dir, short_name) + if not venv_executable.is_file(): + raise CLIError( + f"Installed package from '{owner}/{repo_name}' does not expose the required console script " + f"'{executable_name}'." + ) + + manifest = ExtensionManifest( + owner=owner, + repo=repo_name, + repo_id=f"{owner}/{repo_name}", + short_name=short_name, + executable_name=executable_name, + executable_path=str(venv_executable.resolve()), + type="python", + installed_at=datetime.now(timezone.utc), + source=f"https://github.com/{owner}/{repo_name}", + ) + installed = True + return manifest + except CLIError: + raise + except subprocess.TimeoutExpired as e: + raise CLIExtensionInstallError( + f"Pip install timed out after {_EXTENSIONS_PIP_INSTALL_TIMEOUT}s for '{owner}/{repo_name}'. " + "See pip output above for details." + ) from e + except subprocess.CalledProcessError as e: + raise CLIExtensionInstallError( + f"Failed to install pip package from '{owner}/{repo_name}' (exit code {e.returncode}). " + "See pip output above for details." + ) from e + except Exception as e: + raise CLIExtensionInstallError(f"Failed to set up pip extension from '{owner}/{repo_name}': {e}") from e + finally: + if not installed: + shutil.rmtree(extension_dir, ignore_errors=True) + + +def _try_fetch_remote_description( + owner: str, repo_name: str, branch: str, candidate_description: str | None +) -> str | None: + """Try to fetch project description either from: + - manifest.json + - pyproject.toml + + Only best effort, no error handling. + """ + # from manifest.json + try: + response = get_session().get( + f"https://raw.githubusercontent.com/{owner}/{repo_name}/refs/heads/{branch}/{MANIFEST_FILENAME}", + follow_redirects=True, + ) + response.raise_for_status() + data = response.json() + description = data.get("description") + if isinstance(description, str): + return description + except Exception: + pass + + # from pyproject.toml + try: + response = get_session().get( + f"https://raw.githubusercontent.com/{owner}/{repo_name}/refs/heads/{branch}/pyproject.toml", + follow_redirects=True, + ) + response.raise_for_status() + + # Weak parser but ok for "best effort" + for line in response.text.splitlines(): + line = line.strip() + if line.startswith("description"): + _, _, value = line.partition("=") + return value.strip().strip("\"'") + except Exception: + pass + + # fallback to value fetched from GH API directly + return candidate_description + + +def _get_extensions_root() -> Path: + root_dir = EXTENSIONS_ROOT.expanduser() + root_dir.mkdir(parents=True, exist_ok=True) + return root_dir + + +def _get_extension_dir(short_name: str) -> Path: + safe_name = _validate_extension_short_name(short_name, original_input=short_name) + root = _get_extensions_root().resolve() + target = (root / f"hf-{safe_name}").resolve() + if root not in target.parents: + raise CLIError(f"Invalid extension name '{short_name}'.") + return target + + +def _resolve_github_repo_info(owner: str, repo_name: str) -> tuple[str, str | None]: + try: + response = get_session().get( + f"https://api.github.com/repos/{owner}/{repo_name}", + follow_redirects=True, + timeout=_EXTENSIONS_DOWNLOAD_TIMEOUT, + ) + response.raise_for_status() + data = response.json() + return data["default_branch"], data.get("description") + except Exception: + return _EXTENSIONS_DEFAULT_BRANCH, None + + +def _get_executable_name(short_name: str) -> str: + name = f"hf-{short_name}" + if os.name == "nt": + name += ".exe" + return name + + +def _resolve_installed_executable_path(short_name: str) -> Path: + extension_dir = _get_extension_dir(short_name) + manifest = ExtensionManifest.load(extension_dir) + return Path(manifest.executable_path).expanduser() + + +def _get_venv_python_path(venv_dir: Path) -> Path: + if os.name == "nt": + return venv_dir / "Scripts" / "python.exe" + return venv_dir / "bin" / "python" + + +def _get_venv_extension_executable_path(venv_dir: Path, short_name: str) -> Path: + executable_name = _get_executable_name(short_name) + if os.name == "nt": + return venv_dir / "Scripts" / executable_name + return venv_dir / "bin" / executable_name + + +_ALLOWED_EXTENSION_NAME = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._-]*$") + + +def _validate_extension_short_name(short_name: str, *, original_input: str) -> str: + name = short_name.strip() + if not name: + raise CLIError("Extension name cannot be empty.") + if any(sep in name for sep in ("/", "\\")): + raise CLIError(f"Invalid extension name '{original_input}'.") + if ".." in name or ":" in name: + raise CLIError(f"Invalid extension name '{original_input}'.") + if not _ALLOWED_EXTENSION_NAME.fullmatch(name): + raise CLIError( + f"Invalid extension name '{original_input}'. Allowed characters: letters, digits, '.', '_' and '-'." + ) + return name + + +def _normalize_repo_id(repo_id: str) -> tuple[str, str, str]: + if "://" in repo_id: + raise CLIError("Only GitHub repositories in `[OWNER/]hf-` format are supported.") + + parts = repo_id.split("/") + if len(parts) == 1: + owner = DEFAULT_EXTENSION_OWNER + repo_name = parts[0] + elif len(parts) == 2 and all(parts): + owner, repo_name = parts + else: + raise CLIError(f"Expected `[OWNER/]REPO` format, got '{repo_id}'.") + + if not repo_name.startswith("hf-"): + raise CLIError(f"Extension repository name must start with 'hf-', got '{repo_name}'.") + + short_name = repo_name[3:] + if not short_name: + raise CLIError("Invalid extension repository name 'hf-'.") + _validate_extension_short_name(short_name, original_input=repo_id) + + return owner, repo_name, short_name + + +def _normalize_extension_name(name: str) -> str: + candidate = name.strip() + if not candidate: + raise CLIError("Extension name cannot be empty.") + normalized = candidate[3:] if candidate.startswith("hf-") else candidate + return _validate_extension_short_name(normalized, original_input=name) + + +def _execute_extension_binary(executable_path: Path, args: list[str]) -> int: + try: + return subprocess.call([str(executable_path)] + args) + except OSError as e: + if os.name == "nt" or e.errno != errno.ENOEXEC: + raise + return subprocess.call(["sh", str(executable_path)] + args) diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/hf.py b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/hf.py new file mode 100644 index 0000000000000000000000000000000000000000..026a2d9d3e2fcec398e77270708cd3a70b7934a4 --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/hf.py @@ -0,0 +1,128 @@ +# Copyright 2020 The HuggingFace Team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import sys +import traceback +from typing import Annotated + +import typer + +from huggingface_hub import __version__, constants +from huggingface_hub.cli._cli_utils import check_cli_update, fallback_typer_group_factory, typer_factory +from huggingface_hub.cli._errors import format_known_exception +from huggingface_hub.cli.auth import auth_cli +from huggingface_hub.cli.buckets import buckets_cli, sync +from huggingface_hub.cli.cache import cache_cli +from huggingface_hub.cli.collections import collections_cli +from huggingface_hub.cli.datasets import datasets_cli +from huggingface_hub.cli.discussions import discussions_cli +from huggingface_hub.cli.download import DOWNLOAD_EXAMPLES, download +from huggingface_hub.cli.extensions import ( + dispatch_unknown_top_level_extension, + extensions_cli, + list_installed_extensions_for_help, +) +from huggingface_hub.cli.inference_endpoints import ie_cli +from huggingface_hub.cli.jobs import jobs_cli +from huggingface_hub.cli.lfs import lfs_enable_largefiles, lfs_multipart_upload +from huggingface_hub.cli.models import models_cli +from huggingface_hub.cli.papers import papers_cli +from huggingface_hub.cli.repo_files import repo_files_cli +from huggingface_hub.cli.repos import repos_cli +from huggingface_hub.cli.skills import skills_cli +from huggingface_hub.cli.spaces import spaces_cli +from huggingface_hub.cli.system import env, update, version +from huggingface_hub.cli.upload import UPLOAD_EXAMPLES, upload +from huggingface_hub.cli.upload_large_folder import UPLOAD_LARGE_FOLDER_EXAMPLES, upload_large_folder +from huggingface_hub.cli.webhooks import webhooks_cli +from huggingface_hub.utils import ANSI, logging + + +app = typer_factory( + help="Hugging Face Hub CLI", + cls=fallback_typer_group_factory( + dispatch_unknown_top_level_extension, + extra_commands_provider=list_installed_extensions_for_help, + ), +) + + +def _version_callback(value: bool) -> None: + if value: + print(__version__) + raise typer.Exit() + + +@app.callback(invoke_without_command=True) +def app_callback( + version: Annotated[ + bool | None, typer.Option("-v", "--version", callback=_version_callback, is_eager=True, hidden=True) + ] = None, +) -> None: + pass + + +# top level single commands (defined in their respective files) +app.command()(sync) +app.command(examples=DOWNLOAD_EXAMPLES)(download) +app.command(examples=UPLOAD_EXAMPLES)(upload) +app.command(examples=UPLOAD_LARGE_FOLDER_EXAMPLES)(upload_large_folder) + +app.command(topic="help")(env) +app.command(topic="help")(update) +app.command(topic="help")(version) + +app.command(hidden=True)(lfs_enable_largefiles) +app.command(hidden=True)(lfs_multipart_upload) + +# command groups +app.add_typer(auth_cli, name="auth") +app.add_typer(buckets_cli, name="buckets") +app.add_typer(cache_cli, name="cache") +app.add_typer(collections_cli, name="collections") +app.add_typer(datasets_cli, name="datasets") +app.add_typer(discussions_cli, name="discussions") +app.add_typer(jobs_cli, name="jobs") +app.add_typer(models_cli, name="models") +app.add_typer(papers_cli, name="papers") +app.add_typer(repos_cli, name="repos | repo") +app.add_typer(repo_files_cli, name="repo-files", hidden=True) +app.add_typer(skills_cli, name="skills") +app.add_typer(spaces_cli, name="spaces") +app.add_typer(webhooks_cli, name="webhooks") +app.add_typer(ie_cli, name="endpoints") +app.add_typer(extensions_cli, name="extensions | ext") + + +def main(): + if not constants.HF_DEBUG: + logging.set_verbosity_info() + check_cli_update("huggingface_hub") + + try: + app() + except Exception as e: + message = format_known_exception(e) + if message: + print(f"Error: {message}", file=sys.stderr) + if constants.HF_DEBUG: + traceback.print_exc() + else: + print(ANSI.gray("Set HF_DEBUG=1 as environment variable for full traceback.")) + sys.exit(1) + raise + + +if __name__ == "__main__": + main() diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/inference_endpoints.py b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/inference_endpoints.py new file mode 100644 index 0000000000000000000000000000000000000000..ee30745d9a8340db77e152b7cd8f970488ffe034 --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/inference_endpoints.py @@ -0,0 +1,438 @@ +"""CLI commands for Hugging Face Inference Endpoints.""" + +from typing import Annotated + +import typer + +from huggingface_hub._inference_endpoints import InferenceEndpointScalingMetric +from huggingface_hub.errors import HfHubHTTPError + +from ._cli_utils import TokenOpt, get_hf_api, typer_factory +from ._output import out + + +ie_cli = typer_factory(help="Manage Hugging Face Inference Endpoints.") + +catalog_app = typer_factory(help="Interact with the Inference Endpoints catalog.") + + +NameArg = Annotated[ + str, + typer.Argument(help="Endpoint name."), +] +NameOpt = Annotated[ + str | None, + typer.Option(help="Endpoint name."), +] + +NamespaceOpt = Annotated[ + str | None, + typer.Option( + help="The namespace associated with the Inference Endpoint. Defaults to the current user's namespace.", + ), +] + + +@ie_cli.command("list | ls", examples=["hf endpoints ls", "hf endpoints ls --namespace my-org"]) +def ls( + namespace: NamespaceOpt = None, + token: TokenOpt = None, +) -> None: + """Lists all Inference Endpoints for the given namespace.""" + api = get_hf_api(token=token) + try: + endpoints = api.list_inference_endpoints(namespace=namespace, token=token) + except HfHubHTTPError as error: + out.error(f"Listing failed: {error}") + raise typer.Exit(code=error.response.status_code) from error + + results = [] + for endpoint in endpoints: + raw = endpoint.raw + status = raw.get("status", {}) + model = raw.get("model", {}) + compute = raw.get("compute", {}) + provider = raw.get("provider", {}) + results.append( + { + "name": raw.get("name", ""), + "model": model.get("repository", "") if isinstance(model, dict) else "", + "status": status.get("state", "") if isinstance(status, dict) else "", + "task": model.get("task", "") if isinstance(model, dict) else "", + "framework": model.get("framework", "") if isinstance(model, dict) else "", + "instance": compute.get("instanceType", "") if isinstance(compute, dict) else "", + "vendor": provider.get("vendor", "") if isinstance(provider, dict) else "", + "region": provider.get("region", "") if isinstance(provider, dict) else "", + } + ) + out.table(results, id_key="name") + + +@ie_cli.command(name="deploy", examples=["hf endpoints deploy my-endpoint --repo gpt2 --framework pytorch ..."]) +def deploy( + name: NameArg, + repo: Annotated[ + str, + typer.Option( + help="The name of the model repository associated with the Inference Endpoint (e.g. 'openai/gpt-oss-120b').", + ), + ], + framework: Annotated[ + str, + typer.Option( + help="The machine learning framework used for the model (e.g. 'vllm').", + ), + ], + accelerator: Annotated[ + str, + typer.Option( + help="The hardware accelerator to be used for inference (e.g. 'cpu').", + ), + ], + instance_size: Annotated[ + str, + typer.Option( + help="The size or type of the instance to be used for hosting the model (e.g. 'x4').", + ), + ], + instance_type: Annotated[ + str, + typer.Option( + help="The cloud instance type where the Inference Endpoint will be deployed (e.g. 'intel-icl').", + ), + ], + region: Annotated[ + str, + typer.Option( + help="The cloud region in which the Inference Endpoint will be created (e.g. 'us-east-1').", + ), + ], + vendor: Annotated[ + str, + typer.Option( + help="The cloud provider or vendor where the Inference Endpoint will be hosted (e.g. 'aws').", + ), + ], + *, + namespace: NamespaceOpt = None, + task: Annotated[ + str | None, + typer.Option( + help="The task on which to deploy the model (e.g. 'text-classification').", + ), + ] = None, + token: TokenOpt = None, + min_replica: Annotated[ + int, + typer.Option( + help="The minimum number of replicas (instances) to keep running for the Inference Endpoint.", + ), + ] = 1, + max_replica: Annotated[ + int, + typer.Option( + help="The maximum number of replicas (instances) to scale to for the Inference Endpoint.", + ), + ] = 1, + scale_to_zero_timeout: Annotated[ + int | None, + typer.Option( + help="The duration in minutes before an inactive endpoint is scaled to zero.", + ), + ] = None, + scaling_metric: Annotated[ + InferenceEndpointScalingMetric | None, + typer.Option( + help="The metric reference for scaling.", + ), + ] = None, + scaling_threshold: Annotated[ + float | None, + typer.Option( + help="The scaling metric threshold used to trigger a scale up. Ignored when scaling metric is not provided.", + ), + ] = None, +) -> None: + """Deploy an Inference Endpoint from a Hub repository.""" + api = get_hf_api(token=token) + endpoint = api.create_inference_endpoint( + name=name, + repository=repo, + framework=framework, + accelerator=accelerator, + instance_size=instance_size, + instance_type=instance_type, + region=region, + vendor=vendor, + namespace=namespace, + task=task, + token=token, + min_replica=min_replica, + max_replica=max_replica, + scaling_metric=scaling_metric, + scaling_threshold=scaling_threshold, + scale_to_zero_timeout=scale_to_zero_timeout, + ) + out.dict(endpoint.raw) + + +@catalog_app.command(name="deploy", examples=["hf endpoints catalog deploy --repo meta-llama/Llama-3.2-1B-Instruct"]) +def deploy_from_catalog( + repo: Annotated[ + str, + typer.Option( + help="The name of the model repository associated with the Inference Endpoint (e.g. 'openai/gpt-oss-120b').", + ), + ], + name: NameOpt = None, + accelerator: Annotated[ + str | None, + typer.Option( + help="The hardware accelerator to be used for inference (e.g. 'cpu', 'gpu', 'neuron').", + ), + ] = None, + namespace: NamespaceOpt = None, + token: TokenOpt = None, +) -> None: + """Deploy an Inference Endpoint from the Model Catalog.""" + api = get_hf_api(token=token) + try: + endpoint = api.create_inference_endpoint_from_catalog( + repo_id=repo, + name=name, + accelerator=accelerator, + namespace=namespace, + token=token, + ) + except HfHubHTTPError as error: + out.error(f"Deployment failed: {error}") + raise typer.Exit(code=error.response.status_code) from error + + out.dict(endpoint.raw) + + +def list_catalog( + token: TokenOpt = None, +) -> None: + """List available Catalog models.""" + api = get_hf_api(token=token) + try: + models = api.list_inference_catalog(token=token) + except HfHubHTTPError as error: + out.error(f"Catalog fetch failed: {error}") + raise typer.Exit(code=error.response.status_code) from error + + out.dict({"models": models}) + + +catalog_app.command(name="list | ls", examples=["hf endpoints catalog ls"])(list_catalog) +ie_cli.command(name="list-catalog", hidden=True)(list_catalog) + + +ie_cli.add_typer(catalog_app, name="catalog") + + +@ie_cli.command(examples=["hf endpoints describe my-endpoint"]) +def describe( + name: NameArg, + namespace: NamespaceOpt = None, + token: TokenOpt = None, +) -> None: + """Get information about an existing endpoint.""" + api = get_hf_api(token=token) + try: + endpoint = api.get_inference_endpoint(name=name, namespace=namespace, token=token) + except HfHubHTTPError as error: + out.error(f"Fetch failed: {error}") + raise typer.Exit(code=error.response.status_code) from error + + out.dict(endpoint.raw) + + +@ie_cli.command(examples=["hf endpoints update my-endpoint --min-replica 2"]) +def update( + name: NameArg, + namespace: NamespaceOpt = None, + repo: Annotated[ + str | None, + typer.Option( + help="The name of the model repository associated with the Inference Endpoint (e.g. 'openai/gpt-oss-120b').", + ), + ] = None, + accelerator: Annotated[ + str | None, + typer.Option( + help="The hardware accelerator to be used for inference (e.g. 'cpu').", + ), + ] = None, + instance_size: Annotated[ + str | None, + typer.Option( + help="The size or type of the instance to be used for hosting the model (e.g. 'x4').", + ), + ] = None, + instance_type: Annotated[ + str | None, + typer.Option( + help="The cloud instance type where the Inference Endpoint will be deployed (e.g. 'intel-icl').", + ), + ] = None, + framework: Annotated[ + str | None, + typer.Option( + help="The machine learning framework used for the model (e.g. 'custom').", + ), + ] = None, + revision: Annotated[ + str | None, + typer.Option( + help="The specific model revision to deploy on the Inference Endpoint (e.g. '6c0e6080953db56375760c0471a8c5f2929baf11').", + ), + ] = None, + task: Annotated[ + str | None, + typer.Option( + help="The task on which to deploy the model (e.g. 'text-classification').", + ), + ] = None, + min_replica: Annotated[ + int | None, + typer.Option( + help="The minimum number of replicas (instances) to keep running for the Inference Endpoint.", + ), + ] = None, + max_replica: Annotated[ + int | None, + typer.Option( + help="The maximum number of replicas (instances) to scale to for the Inference Endpoint.", + ), + ] = None, + scale_to_zero_timeout: Annotated[ + int | None, + typer.Option( + help="The duration in minutes before an inactive endpoint is scaled to zero.", + ), + ] = None, + scaling_metric: Annotated[ + InferenceEndpointScalingMetric | None, + typer.Option( + help="The metric reference for scaling.", + ), + ] = None, + scaling_threshold: Annotated[ + float | None, + typer.Option( + help="The scaling metric threshold used to trigger a scale up. Ignored when scaling metric is not provided.", + ), + ] = None, + token: TokenOpt = None, +) -> None: + """Update an existing endpoint.""" + api = get_hf_api(token=token) + try: + endpoint = api.update_inference_endpoint( + name=name, + namespace=namespace, + repository=repo, + framework=framework, + revision=revision, + task=task, + accelerator=accelerator, + instance_size=instance_size, + instance_type=instance_type, + min_replica=min_replica, + max_replica=max_replica, + scale_to_zero_timeout=scale_to_zero_timeout, + scaling_metric=scaling_metric, + scaling_threshold=scaling_threshold, + token=token, + ) + except HfHubHTTPError as error: + out.error(f"Update failed: {error}") + raise typer.Exit(code=error.response.status_code) from error + out.dict(endpoint.raw) + + +@ie_cli.command(examples=["hf endpoints delete my-endpoint"]) +def delete( + name: NameArg, + namespace: NamespaceOpt = None, + yes: Annotated[ + bool, + typer.Option("--yes", help="Skip confirmation prompts."), + ] = False, + token: TokenOpt = None, +) -> None: + """Delete an Inference Endpoint permanently.""" + out.confirm(f"Delete endpoint '{name}'?", yes=yes) + + api = get_hf_api(token=token) + try: + api.delete_inference_endpoint(name=name, namespace=namespace, token=token) + except HfHubHTTPError as error: + out.error(f"Delete failed: {error}") + raise typer.Exit(code=error.response.status_code) from error + + out.result(f"Deleted '{name}'.", name=name) + + +@ie_cli.command(examples=["hf endpoints pause my-endpoint"]) +def pause( + name: NameArg, + namespace: NamespaceOpt = None, + token: TokenOpt = None, +) -> None: + """Pause an Inference Endpoint.""" + api = get_hf_api(token=token) + try: + endpoint = api.pause_inference_endpoint(name=name, namespace=namespace, token=token) + except HfHubHTTPError as error: + out.error(f"Pause failed: {error}") + raise typer.Exit(code=error.response.status_code) from error + + out.dict(endpoint.raw) + + +@ie_cli.command(examples=["hf endpoints resume my-endpoint"]) +def resume( + name: NameArg, + namespace: NamespaceOpt = None, + fail_if_already_running: Annotated[ + bool, + typer.Option( + "--fail-if-already-running", + help="If `True`, the method will raise an error if the Inference Endpoint is already running.", + ), + ] = False, + token: TokenOpt = None, +) -> None: + """Resume an Inference Endpoint.""" + api = get_hf_api(token=token) + try: + endpoint = api.resume_inference_endpoint( + name=name, + namespace=namespace, + token=token, + running_ok=not fail_if_already_running, + ) + except HfHubHTTPError as error: + out.error(f"Resume failed: {error}") + raise typer.Exit(code=error.response.status_code) from error + out.dict(endpoint.raw) + + +@ie_cli.command(examples=["hf endpoints scale-to-zero my-endpoint"]) +def scale_to_zero( + name: NameArg, + namespace: NamespaceOpt = None, + token: TokenOpt = None, +) -> None: + """Scale an Inference Endpoint to zero.""" + api = get_hf_api(token=token) + try: + endpoint = api.scale_to_zero_inference_endpoint(name=name, namespace=namespace, token=token) + except HfHubHTTPError as error: + out.error(f"Scale To Zero failed: {error}") + raise typer.Exit(code=error.response.status_code) from error + + out.dict(endpoint.raw) diff --git a/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/jobs.py b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/jobs.py new file mode 100644 index 0000000000000000000000000000000000000000..f2830b16dfcf6fe9fccbc7dca19e0199e5b39db2 --- /dev/null +++ b/bioagent-bench/.venv/lib/python3.14/site-packages/huggingface_hub/cli/jobs.py @@ -0,0 +1,1150 @@ +# Copyright 2025 The HuggingFace Team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Contains commands to interact with jobs on the Hugging Face Hub. + +Usage: + # run a job + hf jobs run + + # List running or completed jobs + hf jobs ps [-a] [-f key=value] [--format table|json|TEMPLATE] [-q] + + # Print logs from a job (non-blocking) + hf jobs logs + + # Stream logs from a job (blocking, like `docker logs -f`) + hf jobs logs -f + + # Stream resources usage stats and metrics from a job + hf jobs stats + + # Inspect detailed information about a job + hf jobs inspect + + # Cancel a running job + hf jobs cancel + + # List available hardware options + hf jobs hardware + + # Run a UV script + hf jobs uv run