czty commited on
Commit
1f7bea0
·
verified ·
1 Parent(s): b6fb194

Add files using upload-large-folder tool

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. Biomni/mcp_generated/mcp_adapterremoval/Dockerfile +40 -0
  2. Biomni/mcp_generated/mcp_adapterremoval/app/adapterremoval_shim_server.py +55 -0
  3. Biomni/mcp_generated/mcp_adapterremoval/app/requirements.txt +1 -0
  4. Biomni/mcp_generated/mcp_adapterremoval/docker-compose.yml +22 -0
  5. Biomni/mcp_generated/mcp_adapterremoval/environment.yaml +10 -0
  6. Biomni/mcp_generated/mcp_adapterremoval/requirements.txt +2 -0
  7. Biomni/mcp_generated/mcp_alfred/Dockerfile +40 -0
  8. Biomni/mcp_generated/mcp_alfred/app/alfred_server.py +638 -0
  9. Biomni/mcp_generated/mcp_alfred/app/alfred_shim_server.py +55 -0
  10. Biomni/mcp_generated/mcp_alfred/app/requirements.txt +1 -0
  11. Biomni/mcp_generated/mcp_alfred/docker-compose.yml +22 -0
  12. Biomni/mcp_generated/mcp_alfred/environment.yaml +10 -0
  13. Biomni/mcp_generated/mcp_alfred/requirements.txt +2 -0
  14. Biomni/mcp_generated/mcp_aria2/Dockerfile +40 -0
  15. Biomni/mcp_generated/mcp_aria2/app/aria2_shim_server.py +55 -0
  16. Biomni/mcp_generated/mcp_aria2/docker-compose.yml +22 -0
  17. Biomni/mcp_generated/mcp_aria2/requirements.txt +2 -0
  18. Biomni/mcp_generated/mcp_augur/requirements.txt +2 -0
  19. Biomni/mcp_generated/mcp_bioconductor-biocfilecache/Dockerfile +40 -0
  20. Biomni/mcp_generated/mcp_bioconductor-biocfilecache/app/bioconductor-biocfilecache_server.py +314 -0
  21. Biomni/mcp_generated/mcp_bioconductor-biocfilecache/app/bioconductor-biocfilecache_shim_server.py +55 -0
  22. Biomni/mcp_generated/mcp_bioconductor-biocfilecache/app/requirements.txt +1 -0
  23. Biomni/mcp_generated/mcp_bioconductor-biocfilecache/docker-compose.yml +22 -0
  24. Biomni/mcp_generated/mcp_bioconductor-biocfilecache/environment.yaml +10 -0
  25. Biomni/mcp_generated/mcp_bioconductor-biocfilecache/requirements.txt +2 -0
  26. Biomni/mcp_generated/mcp_bioconductor-biocgenerics/Dockerfile +40 -0
  27. Biomni/mcp_generated/mcp_bioconductor-biocgenerics/app/bioconductor-biocgenerics_shim_server.py +55 -0
  28. Biomni/mcp_generated/mcp_bioconductor-biocgenerics/docker-compose.yml +22 -0
  29. Biomni/mcp_generated/mcp_bioconductor-biocgenerics/environment.yaml +10 -0
  30. Biomni/mcp_generated/mcp_bioconductor-delayedarray/requirements.txt +2 -0
  31. Biomni/mcp_generated/mcp_bioconductor-nebulosa/Dockerfile +40 -0
  32. Biomni/mcp_generated/mcp_bioconductor-nebulosa/app/bioconductor-nebulosa_server.py +185 -0
  33. Biomni/mcp_generated/mcp_bioconductor-nebulosa/app/bioconductor-nebulosa_shim_server.py +55 -0
  34. Biomni/mcp_generated/mcp_bioconductor-nebulosa/docker-compose.yml +22 -0
  35. Biomni/mcp_generated/mcp_bioconductor-nebulosa/environment.yaml +10 -0
  36. Biomni/mcp_generated/mcp_bioconductor-nebulosa/requirements.txt +2 -0
  37. Biomni/mcp_generated/mcp_brooklyn_plot/Dockerfile +40 -0
  38. Biomni/mcp_generated/mcp_brooklyn_plot/app/brooklyn_plot_server.py +170 -0
  39. Biomni/mcp_generated/mcp_brooklyn_plot/app/brooklyn_plot_shim_server.py +55 -0
  40. Biomni/mcp_generated/mcp_brooklyn_plot/docker-compose.yml +22 -0
  41. Biomni/mcp_generated/mcp_brooklyn_plot/environment.yaml +10 -0
  42. Biomni/mcp_generated/mcp_brooklyn_plot/requirements.txt +2 -0
  43. Biomni/mcp_generated/mcp_bx-python/Dockerfile +40 -0
  44. Biomni/mcp_generated/mcp_bx-python/app/bx-python_server.py +361 -0
  45. Biomni/mcp_generated/mcp_bx-python/app/bx-python_shim_server.py +55 -0
  46. Biomni/mcp_generated/mcp_bx-python/app/requirements.txt +1 -0
  47. Biomni/mcp_generated/mcp_bx-python/docker-compose.yml +22 -0
  48. Biomni/mcp_generated/mcp_bx-python/environment.yaml +10 -0
  49. Biomni/mcp_generated/mcp_bx-python/requirements.txt +2 -0
  50. Biomni/mcp_generated/mcp_cd-hit/Dockerfile +40 -0
Biomni/mcp_generated/mcp_adapterremoval/Dockerfile ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ FROM python:3.10-slim
3
+
4
+ # Install system dependencies
5
+ RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/*
6
+
7
+ # Install Miniconda
8
+ 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
9
+
10
+ # Add conda to PATH
11
+ ENV PATH="/opt/conda/bin:$PATH"
12
+
13
+ # Install adapterremoval via conda (e.g., from bioconda)
14
+ RUN conda install -c bioconda adapterremoval -y && conda clean -a
15
+
16
+ # Install Python dependencies
17
+ RUN pip install uv
18
+ RUN uv pip install --system fastmcp
19
+
20
+ # Create app directory
21
+ WORKDIR /app
22
+
23
+ # Copy your MCP server
24
+ COPY app/adapterremoval_server.py /app/
25
+
26
+ # Create workspace and output directories
27
+ RUN mkdir -p /app/workspace /app/output
28
+
29
+ # Make sure the server script is executable
30
+ RUN chmod +x /app/adapterremoval_server.py
31
+
32
+ # Expose port for MCP over HTTP (optional)
33
+ EXPOSE 8000
34
+
35
+ # Health check
36
+ HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)"
37
+
38
+ # Default command runs the MCP server via stdio
39
+ CMD ["python", "/app/adapterremoval_server.py"]
40
+
Biomni/mcp_generated/mcp_adapterremoval/app/adapterremoval_shim_server.py ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ from __future__ import annotations
3
+
4
+ import ast
5
+ from pathlib import Path
6
+
7
+ from mcp.server.fastmcp import FastMCP
8
+
9
+
10
+ SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_adapterremoval/app/adapterremoval_server.py')
11
+ LOCAL_SERVER = Path(__file__).with_name(SOURCE_SERVER.name)
12
+ SERVER_NAME = 'biosci_adapterremoval'
13
+
14
+
15
+ class _ShimMCP:
16
+ @staticmethod
17
+ def tool(*args, **kwargs):
18
+ if args and callable(args[0]) and len(args) == 1 and not kwargs:
19
+ return args[0]
20
+ def _decorator(fn):
21
+ return fn
22
+ return _decorator
23
+
24
+
25
+ def _resolve_source_server():
26
+ if LOCAL_SERVER.exists() and LOCAL_SERVER.name != Path(__file__).name:
27
+ return LOCAL_SERVER
28
+ return SOURCE_SERVER
29
+
30
+
31
+ def _load_functions():
32
+ source_server = _resolve_source_server()
33
+ code = source_server.read_text(encoding="utf-8")
34
+ tree = ast.parse(code, filename=str(source_server))
35
+ function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")]
36
+ namespace = {
37
+ "__name__": "__mcp_source__",
38
+ "mcp": _ShimMCP(),
39
+ }
40
+ exec(compile(code, str(source_server), "exec"), namespace, namespace)
41
+ loaded = []
42
+ for name in function_names:
43
+ fn = namespace.get(name)
44
+ if callable(fn):
45
+ loaded.append(fn)
46
+ return loaded
47
+
48
+
49
+ mcp = FastMCP(SERVER_NAME)
50
+ for _fn in _load_functions():
51
+ mcp.tool()(_fn)
52
+
53
+
54
+ if __name__ == "__main__":
55
+ mcp.run(transport="stdio")
Biomni/mcp_generated/mcp_adapterremoval/app/requirements.txt ADDED
@@ -0,0 +1 @@
 
 
1
+
Biomni/mcp_generated/mcp_adapterremoval/docker-compose.yml ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: '3.8'
2
+
3
+ services:
4
+ mcp-adapterremoval:
5
+ build: .
6
+ image: mcp-adapterremoval:latest
7
+ container_name: mcp-adapterremoval
8
+ ports:
9
+ - "8000:8000"
10
+ environment:
11
+ - MCP_SERVER_NAME=adapterremoval
12
+ volumes:
13
+ - ./workspace:/app/workspace
14
+ - ./output:/app/output
15
+ restart: unless-stopped
16
+ healthcheck:
17
+ test: ["CMD", "python", "-c", "import sys; sys.exit(0)"]
18
+ interval: 30s
19
+ timeout: 10s
20
+ retries: 3
21
+ start_period: 5s
22
+
Biomni/mcp_generated/mcp_adapterremoval/environment.yaml ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ name: mcp-tool
3
+ channels:
4
+ - bioconda
5
+ - conda-forge
6
+ - defaults
7
+ dependencies:
8
+ - adapterremoval
9
+ - python=3.10
10
+
Biomni/mcp_generated/mcp_adapterremoval/requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ fastmcp
2
+ mcp
Biomni/mcp_generated/mcp_alfred/Dockerfile ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ FROM python:3.10-slim
3
+
4
+ # Install system dependencies
5
+ RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/*
6
+
7
+ # Install Miniconda
8
+ 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
9
+
10
+ # Add conda to PATH
11
+ ENV PATH="/opt/conda/bin:$PATH"
12
+
13
+ # Install alfred via conda (e.g., from bioconda)
14
+ RUN conda install -c bioconda alfred -y && conda clean -a
15
+
16
+ # Install Python dependencies
17
+ RUN pip install uv
18
+ RUN uv pip install --system fastmcp
19
+
20
+ # Create app directory
21
+ WORKDIR /app
22
+
23
+ # Copy your MCP server
24
+ COPY app/alfred_server.py /app/
25
+
26
+ # Create workspace and output directories
27
+ RUN mkdir -p /app/workspace /app/output
28
+
29
+ # Make sure the server script is executable
30
+ RUN chmod +x /app/alfred_server.py
31
+
32
+ # Expose port for MCP over HTTP (optional)
33
+ EXPOSE 8000
34
+
35
+ # Health check
36
+ HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)"
37
+
38
+ # Default command runs the MCP server via stdio
39
+ CMD ["python", "/app/alfred_server.py"]
40
+
Biomni/mcp_generated/mcp_alfred/app/alfred_server.py ADDED
@@ -0,0 +1,638 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import subprocess
2
+ import tempfile
3
+ from pathlib import Path
4
+ from typing import List, Literal, Optional
5
+
6
+ # MCP-related decorators are assumed to be available in the environment.
7
+ #
8
+ # For local testing, you can create a dummy decorator:
9
+ #
10
+ # def mcp_tool_dummy(*args, **kwargs):
11
+ # def decorator(func):
12
+ # return func
13
+ # return decorator
14
+ #
15
+ # mcp = type("mcp", (), {"tool": mcp_tool_dummy})
16
+
17
+
18
+ from mcp.server.fastmcp import FastMCP
19
+
20
+ SERVER_NAME = 'local_alfred'
21
+ mcp = FastMCP(SERVER_NAME)
22
+
23
+ @mcp.tool()
24
+ def alfred_stats(
25
+ in_bam: Path,
26
+ ref: Path,
27
+ outfile: Optional[Path] = None,
28
+ bed: Optional[Path] = None,
29
+ threads: int = 1,
30
+ minmapq: int = 0,
31
+ flag: int = 0,
32
+ fflag: int = 1540,
33
+ coverage: Optional[Path] = None,
34
+ dist: Optional[Path] = None,
35
+ sampleid: Optional[str] = None,
36
+ libid: Optional[str] = None,
37
+ readgroup: Optional[str] = None,
38
+ uncompressed: bool = False,
39
+ ):
40
+ """
41
+ Compute alignment summary statistics for a BAM file.
42
+
43
+ Args:
44
+ in_bam: Input BAM file.
45
+ ref: Reference FASTA file.
46
+ outfile: Output file for alignment metrics (e.g., metrics.tsv.gz). Defaults to stdout.
47
+ bed: BED file with regions of interest.
48
+ threads: Number of threads to use.
49
+ minmapq: Minimum mapping quality for reads to be considered.
50
+ flag: Required SAM flag.
51
+ fflag: Filtering SAM flag (reads with these flags will be ignored).
52
+ coverage: Output file for coverage statistics (e.g., cov.txt.gz).
53
+ dist: Output file for insert size distribution (e.g., dist.txt.gz).
54
+ sampleid: Sample ID to be used in the output.
55
+ libid: Library ID to be used in the output.
56
+ readgroup: Read-group ID to be used in the output.
57
+ uncompressed: Write uncompressed output files.
58
+ """
59
+ if not in_bam.exists():
60
+ raise FileNotFoundError(f"Input BAM file not found: {in_bam}")
61
+ if not ref.exists():
62
+ raise FileNotFoundError(f"Reference FASTA file not found: {ref}")
63
+ if bed and not bed.exists():
64
+ raise FileNotFoundError(f"BED file not found: {bed}")
65
+ if threads < 1:
66
+ raise ValueError("Number of threads must be at least 1.")
67
+
68
+ cmd = ["alfred", "stats", "-r", str(ref)]
69
+ output_files = []
70
+
71
+ if outfile:
72
+ cmd.extend(["-o", str(outfile)])
73
+ output_files.append(str(outfile))
74
+ if bed:
75
+ cmd.extend(["-b", str(bed)])
76
+ if threads > 1:
77
+ cmd.extend(["-p", str(threads)])
78
+ if minmapq != 0:
79
+ cmd.extend(["-m", str(minmapq)])
80
+ if flag != 0:
81
+ cmd.extend(["-f", str(flag)])
82
+ if fflag != 1540:
83
+ cmd.extend(["-F", str(fflag)])
84
+ if coverage:
85
+ cmd.extend(["-c", str(coverage)])
86
+ output_files.append(str(coverage))
87
+ if dist:
88
+ cmd.extend(["-d", str(dist)])
89
+ output_files.append(str(dist))
90
+ if sampleid:
91
+ cmd.extend(["-s", sampleid])
92
+ if libid:
93
+ cmd.extend(["-l", libid])
94
+ if readgroup:
95
+ cmd.extend(["-g", readgroup])
96
+ if uncompressed:
97
+ cmd.append("-u")
98
+
99
+ cmd.append(str(in_bam))
100
+
101
+ try:
102
+ result = subprocess.run(
103
+ cmd, check=True, capture_output=True, text=True, encoding="utf-8"
104
+ )
105
+ return {
106
+ "command_executed": " ".join(cmd),
107
+ "stdout": result.stdout,
108
+ "stderr": result.stderr,
109
+ "output_files": output_files,
110
+ }
111
+ except subprocess.CalledProcessError as e:
112
+ return {
113
+ "command_executed": " ".join(cmd),
114
+ "stdout": e.stdout,
115
+ "stderr": e.stderr,
116
+ "error": "Alfred stats failed",
117
+ "return_code": e.returncode,
118
+ }
119
+
120
+
121
+ @mcp.tool()
122
+ def alfred_count(
123
+ in_bam: Path,
124
+ ref: Path,
125
+ bed: Optional[Path] = None,
126
+ gtf: Optional[Path] = None,
127
+ outfile: Optional[Path] = None,
128
+ threads: int = 1,
129
+ minmapq: int = 0,
130
+ flag: int = 0,
131
+ fflag: int = 1540,
132
+ sampleid: Optional[str] = None,
133
+ libid: Optional[str] = None,
134
+ readgroup: Optional[str] = None,
135
+ uncompressed: bool = False,
136
+ feature: str = "exon",
137
+ id_attribute: str = "gene_id",
138
+ stranded: Literal[0, 1, 2] = 0,
139
+ antisense: bool = False,
140
+ ):
141
+ """
142
+ Count reads in genomic features from a BAM file.
143
+
144
+ Args:
145
+ in_bam: Input BAM file.
146
+ ref: Reference FASTA file.
147
+ bed: BED file with features. Provide either 'bed' or 'gtf'.
148
+ gtf: GTF file with features. Provide either 'bed' or 'gtf'.
149
+ outfile: Output file for feature counts (e.g., counts.tsv.gz). Defaults to stdout.
150
+ threads: Number of threads to use.
151
+ minmapq: Minimum mapping quality.
152
+ flag: Required SAM flag.
153
+ fflag: Filtering SAM flag.
154
+ sampleid: Sample ID.
155
+ libid: Library ID.
156
+ readgroup: Read-group ID.
157
+ uncompressed: Write uncompressed output.
158
+ feature: GTF feature to count (e.g., 'exon').
159
+ id_attribute: GTF identifier to aggregate by (e.g., 'gene_id').
160
+ stranded: Strandedness (0: unstranded, 1: forward, 2: reverse).
161
+ antisense: Count antisense reads.
162
+ """
163
+ if not in_bam.exists():
164
+ raise FileNotFoundError(f"Input BAM file not found: {in_bam}")
165
+ if not ref.exists():
166
+ raise FileNotFoundError(f"Reference FASTA file not found: {ref}")
167
+ if bed and gtf:
168
+ raise ValueError("Parameters 'bed' and 'gtf' are mutually exclusive.")
169
+ if not bed and not gtf:
170
+ raise ValueError("Either 'bed' or 'gtf' must be provided.")
171
+ if bed and not bed.exists():
172
+ raise FileNotFoundError(f"BED file not found: {bed}")
173
+ if gtf and not gtf.exists():
174
+ raise FileNotFoundError(f"GTF file not found: {gtf}")
175
+ if threads < 1:
176
+ raise ValueError("Number of threads must be at least 1.")
177
+
178
+ cmd = ["alfred", "count", "-r", str(ref)]
179
+ output_files = []
180
+
181
+ if bed:
182
+ cmd.extend(["-b", str(bed)])
183
+ if gtf:
184
+ cmd.extend(["-j", str(gtf)])
185
+ if outfile:
186
+ cmd.extend(["-o", str(outfile)])
187
+ output_files.append(str(outfile))
188
+ if threads > 1:
189
+ cmd.extend(["-p", str(threads)])
190
+ if minmapq != 0:
191
+ cmd.extend(["-m", str(minmapq)])
192
+ if flag != 0:
193
+ cmd.extend(["-f", str(flag)])
194
+ if fflag != 1540:
195
+ cmd.extend(["-F", str(fflag)])
196
+ if sampleid:
197
+ cmd.extend(["-s", sampleid])
198
+ if libid:
199
+ cmd.extend(["-l", libid])
200
+ if readgroup:
201
+ cmd.extend(["-g", readgroup])
202
+ if uncompressed:
203
+ cmd.append("-u")
204
+ if feature != "exon":
205
+ cmd.extend(["-e", feature])
206
+ if id_attribute != "gene_id":
207
+ cmd.extend(["-i", id_attribute])
208
+ if stranded != 0:
209
+ cmd.extend(["-a", str(stranded)])
210
+ if antisense:
211
+ cmd.append("-z")
212
+
213
+ cmd.append(str(in_bam))
214
+
215
+ try:
216
+ result = subprocess.run(
217
+ cmd, check=True, capture_output=True, text=True, encoding="utf-8"
218
+ )
219
+ return {
220
+ "command_executed": " ".join(cmd),
221
+ "stdout": result.stdout,
222
+ "stderr": result.stderr,
223
+ "output_files": output_files,
224
+ }
225
+ except subprocess.CalledProcessError as e:
226
+ return {
227
+ "command_executed": " ".join(cmd),
228
+ "stdout": e.stdout,
229
+ "stderr": e.stderr,
230
+ "error": "Alfred count failed",
231
+ "return_code": e.returncode,
232
+ }
233
+
234
+
235
+ @mcp.tool()
236
+ def alfred_annotate(
237
+ in_vcf: Path,
238
+ in_bam: Path,
239
+ outfile: Path,
240
+ ref: Path,
241
+ bed: Optional[Path] = None,
242
+ gtf: Optional[Path] = None,
243
+ threads: int = 1,
244
+ minmapq: int = 0,
245
+ flag: int = 0,
246
+ fflag: int = 1540,
247
+ feature: str = "exon",
248
+ id_attribute: str = "gene_id",
249
+ annotation_type: Literal["INFO", "FORMAT"] = "FORMAT",
250
+ field: str = "FE",
251
+ ):
252
+ """
253
+ Annotate variants in a VCF/BCF file with feature overlaps from a BAM file.
254
+
255
+ Args:
256
+ in_vcf: Input VCF/BCF file.
257
+ in_bam: Input BAM file.
258
+ outfile: Output VCF/BCF file.
259
+ ref: Reference FASTA file.
260
+ bed: BED file with features. Provide either 'bed' or 'gtf'.
261
+ gtf: GTF file with features. Provide either 'bed' or 'gtf'.
262
+ threads: Number of threads to use.
263
+ minmapq: Minimum mapping quality.
264
+ flag: Required SAM flag.
265
+ fflag: Filtering SAM flag.
266
+ feature: GTF feature to count (e.g., 'exon').
267
+ id_attribute: GTF identifier to aggregate by (e.g., 'gene_id').
268
+ annotation_type: Annotation type ('INFO' or 'FORMAT').
269
+ field: Annotation field name.
270
+ """
271
+ if not in_vcf.exists():
272
+ raise FileNotFoundError(f"Input VCF/BCF file not found: {in_vcf}")
273
+ if not in_bam.exists():
274
+ raise FileNotFoundError(f"Input BAM file not found: {in_bam}")
275
+ if not ref.exists():
276
+ raise FileNotFoundError(f"Reference FASTA file not found: {ref}")
277
+ if bed and gtf:
278
+ raise ValueError("Parameters 'bed' and 'gtf' are mutually exclusive.")
279
+ if not bed and not gtf:
280
+ raise ValueError("Either 'bed' or 'gtf' must be provided.")
281
+ if bed and not bed.exists():
282
+ raise FileNotFoundError(f"BED file not found: {bed}")
283
+ if gtf and not gtf.exists():
284
+ raise FileNotFoundError(f"GTF file not found: {gtf}")
285
+ if threads < 1:
286
+ raise ValueError("Number of threads must be at least 1.")
287
+
288
+ cmd = ["alfred", "annotate", "-o", str(outfile), "-r", str(ref)]
289
+ output_files = [str(outfile)]
290
+
291
+ if bed:
292
+ cmd.extend(["-b", str(bed)])
293
+ if gtf:
294
+ cmd.extend(["-j", str(gtf)])
295
+ if threads > 1:
296
+ cmd.extend(["-p", str(threads)])
297
+ if minmapq != 0:
298
+ cmd.extend(["-m", str(minmapq)])
299
+ if flag != 0:
300
+ cmd.extend(["-f", str(flag)])
301
+ if fflag != 1540:
302
+ cmd.extend(["-F", str(fflag)])
303
+ if feature != "exon":
304
+ cmd.extend(["-e", feature])
305
+ if id_attribute != "gene_id":
306
+ cmd.extend(["-i", id_attribute])
307
+ if annotation_type != "FORMAT":
308
+ cmd.extend(["-t", annotation_type])
309
+ if field != "FE":
310
+ cmd.extend(["-a", field])
311
+
312
+ cmd.extend([str(in_vcf), str(in_bam)])
313
+
314
+ try:
315
+ result = subprocess.run(
316
+ cmd, check=True, capture_output=True, text=True, encoding="utf-8"
317
+ )
318
+ return {
319
+ "command_executed": " ".join(cmd),
320
+ "stdout": result.stdout,
321
+ "stderr": result.stderr,
322
+ "output_files": output_files,
323
+ }
324
+ except subprocess.CalledProcessError as e:
325
+ return {
326
+ "command_executed": " ".join(cmd),
327
+ "stdout": e.stdout,
328
+ "stderr": e.stderr,
329
+ "error": "Alfred annotate failed",
330
+ "return_code": e.returncode,
331
+ }
332
+
333
+
334
+ @mcp.tool()
335
+ def alfred_qc(
336
+ input_bams: List[Path],
337
+ outfile: Path,
338
+ ref: Path,
339
+ bed: Optional[Path] = None,
340
+ gtf: Optional[Path] = None,
341
+ threads: int = 1,
342
+ minmapq: int = 0,
343
+ flag: int = 0,
344
+ fflag: int = 1540,
345
+ contigs: Optional[str] = None,
346
+ feature: str = "exon",
347
+ id_attribute: str = "gene_id",
348
+ stranded: Literal[0, 1, 2] = 0,
349
+ antisense: bool = False,
350
+ uncompressed: bool = False,
351
+ sites: Optional[Path] = None,
352
+ genome: Optional[Path] = None,
353
+ ):
354
+ """
355
+ Generate a multi-sample QC report from one or more BAM files.
356
+
357
+ Args:
358
+ input_bams: List of input BAM files.
359
+ outfile: Output file for QC metrics (e.g., out.qc.json.gz).
360
+ ref: Reference FASTA file.
361
+ bed: BED file with regions of interest.
362
+ gtf: GTF file with features.
363
+ threads: Number of threads to use.
364
+ minmapq: Minimum mapping quality.
365
+ flag: Required SAM flag.
366
+ fflag: Filtering SAM flag.
367
+ contigs: Comma-separated list of contigs to include.
368
+ feature: GTF feature to count (e.g., 'exon').
369
+ id_attribute: GTF identifier to aggregate by (e.g., 'gene_id').
370
+ stranded: Strandedness (0: unstranded, 1: forward, 2: reverse).
371
+ antisense: Count antisense reads.
372
+ uncompressed: Write uncompressed output.
373
+ sites: VCF/BCF file with sites of interest.
374
+ genome: Genome accessibility file.
375
+ """
376
+ if not input_bams:
377
+ raise ValueError("At least one input BAM file is required.")
378
+ for bam in input_bams:
379
+ if not bam.exists():
380
+ raise FileNotFoundError(f"Input BAM file not found: {bam}")
381
+ if not ref.exists():
382
+ raise FileNotFoundError(f"Reference FASTA file not found: {ref}")
383
+ if bed and not bed.exists():
384
+ raise FileNotFoundError(f"BED file not found: {bed}")
385
+ if gtf and not gtf.exists():
386
+ raise FileNotFoundError(f"GTF file not found: {gtf}")
387
+ if sites and not sites.exists():
388
+ raise FileNotFoundError(f"Sites VCF/BCF file not found: {sites}")
389
+ if genome and not genome.exists():
390
+ raise FileNotFoundError(f"Genome accessibility file not found: {genome}")
391
+ if threads < 1:
392
+ raise ValueError("Number of threads must be at least 1.")
393
+
394
+ cmd = ["alfred", "qc", "-o", str(outfile), "-r", str(ref)]
395
+ output_files = [str(outfile)]
396
+
397
+ if bed:
398
+ cmd.extend(["-b", str(bed)])
399
+ if gtf:
400
+ cmd.extend(["-j", str(gtf)])
401
+ if threads > 1:
402
+ cmd.extend(["-p", str(threads)])
403
+ if minmapq != 0:
404
+ cmd.extend(["-m", str(minmapq)])
405
+ if flag != 0:
406
+ cmd.extend(["-f", str(flag)])
407
+ if fflag != 1540:
408
+ cmd.extend(["-F", str(fflag)])
409
+ if contigs:
410
+ cmd.extend(["-c", contigs])
411
+ if feature != "exon":
412
+ cmd.extend(["-e", feature])
413
+ if id_attribute != "gene_id":
414
+ cmd.extend(["-i", id_attribute])
415
+ if stranded != 0:
416
+ cmd.extend(["-a", str(stranded)])
417
+ if antisense:
418
+ cmd.append("-z")
419
+ if uncompressed:
420
+ cmd.append("-u")
421
+ if sites:
422
+ cmd.extend(["-s", str(sites)])
423
+ if genome:
424
+ cmd.extend(["-g", str(genome)])
425
+
426
+ cmd.extend([str(bam) for bam in input_bams])
427
+
428
+ try:
429
+ result = subprocess.run(
430
+ cmd, check=True, capture_output=True, text=True, encoding="utf-8"
431
+ )
432
+ return {
433
+ "command_executed": " ".join(cmd),
434
+ "stdout": result.stdout,
435
+ "stderr": result.stderr,
436
+ "output_files": output_files,
437
+ }
438
+ except subprocess.CalledProcessError as e:
439
+ return {
440
+ "command_executed": " ".join(cmd),
441
+ "stdout": e.stdout,
442
+ "stderr": e.stderr,
443
+ "error": "Alfred qc failed",
444
+ "return_code": e.returncode,
445
+ }
446
+
447
+
448
+ @mcp.tool()
449
+ def alfred_merge(
450
+ input_qc_files: List[Path], outfile: Path, uncompressed: bool = False
451
+ ):
452
+ """
453
+ Merge multiple alfred QC files.
454
+
455
+ Args:
456
+ input_qc_files: List of input QC JSON files (e.g., *.qc.json.gz).
457
+ outfile: Output file for merged QC metrics (e.g., out.qc.json.gz).
458
+ uncompressed: Write uncompressed output.
459
+ """
460
+ if not input_qc_files:
461
+ raise ValueError("At least one input QC file is required.")
462
+ for qc_file in input_qc_files:
463
+ if not qc_file.exists():
464
+ raise FileNotFoundError(f"Input QC file not found: {qc_file}")
465
+
466
+ cmd = ["alfred", "merge", "-o", str(outfile)]
467
+ output_files = [str(outfile)]
468
+
469
+ if uncompressed:
470
+ cmd.append("-u")
471
+
472
+ cmd.extend([str(f) for f in input_qc_files])
473
+
474
+ try:
475
+ result = subprocess.run(
476
+ cmd, check=True, capture_output=True, text=True, encoding="utf-8"
477
+ )
478
+ return {
479
+ "command_executed": " ".join(cmd),
480
+ "stdout": result.stdout,
481
+ "stderr": result.stderr,
482
+ "output_files": output_files,
483
+ }
484
+ except subprocess.CalledProcessError as e:
485
+ return {
486
+ "command_executed": " ".join(cmd),
487
+ "stdout": e.stdout,
488
+ "stderr": e.stderr,
489
+ "error": "Alfred merge failed",
490
+ "return_code": e.returncode,
491
+ }
492
+
493
+
494
+ @mcp.tool()
495
+ def alfred_track(
496
+ in_bam: Path,
497
+ ref: Path,
498
+ outfile: Optional[Path] = None,
499
+ bed: Optional[Path] = None,
500
+ threads: int = 1,
501
+ minmapq: int = 0,
502
+ flag: int = 0,
503
+ fflag: int = 1540,
504
+ step: int = 1000,
505
+ window: int = 1000,
506
+ uncompressed: bool = False,
507
+ ):
508
+ """
509
+ Create a bedGraph track from a BAM file.
510
+
511
+ Args:
512
+ in_bam: Input BAM file.
513
+ ref: Reference FASTA file.
514
+ outfile: Output bedGraph file (e.g., track.bedGraph.gz). Defaults to stdout.
515
+ bed: BED file with regions of interest.
516
+ threads: Number of threads to use.
517
+ minmapq: Minimum mapping quality.
518
+ flag: Required SAM flag.
519
+ fflag: Filtering SAM flag.
520
+ step: Step size for coverage computation.
521
+ window: Window size for coverage computation.
522
+ uncompressed: Write uncompressed output.
523
+ """
524
+ if not in_bam.exists():
525
+ raise FileNotFoundError(f"Input BAM file not found: {in_bam}")
526
+ if not ref.exists():
527
+ raise FileNotFoundError(f"Reference FASTA file not found: {ref}")
528
+ if bed and not bed.exists():
529
+ raise FileNotFoundError(f"BED file not found: {bed}")
530
+ if threads < 1:
531
+ raise ValueError("Number of threads must be at least 1.")
532
+ if step <= 0 or window <= 0:
533
+ raise ValueError("Step and window sizes must be positive.")
534
+
535
+ cmd = ["alfred", "track", "-r", str(ref)]
536
+ output_files = []
537
+
538
+ if outfile:
539
+ cmd.extend(["-o", str(outfile)])
540
+ output_files.append(str(outfile))
541
+ if bed:
542
+ cmd.extend(["-b", str(bed)])
543
+ if threads > 1:
544
+ cmd.extend(["-p", str(threads)])
545
+ if minmapq != 0:
546
+ cmd.extend(["-m", str(minmapq)])
547
+ if flag != 0:
548
+ cmd.extend(["-f", str(flag)])
549
+ if fflag != 1540:
550
+ cmd.extend(["-F", str(fflag)])
551
+ if step != 1000:
552
+ cmd.extend(["-s", str(step)])
553
+ if window != 1000:
554
+ cmd.extend(["-w", str(window)])
555
+ if uncompressed:
556
+ cmd.append("-u")
557
+
558
+ cmd.append(str(in_bam))
559
+
560
+ try:
561
+ result = subprocess.run(
562
+ cmd, check=True, capture_output=True, text=True, encoding="utf-8"
563
+ )
564
+ return {
565
+ "command_executed": " ".join(cmd),
566
+ "stdout": result.stdout,
567
+ "stderr": result.stderr,
568
+ "output_files": output_files,
569
+ }
570
+ except subprocess.CalledProcessError as e:
571
+ return {
572
+ "command_executed": " ".join(cmd),
573
+ "stdout": e.stdout,
574
+ "stderr": e.stderr,
575
+ "error": "Alfred track failed",
576
+ "return_code": e.returncode,
577
+ }
578
+
579
+
580
+ @mcp.tool()
581
+ def alfred_motif(
582
+ ref_fa: Path,
583
+ motif: str,
584
+ outfile: Optional[Path] = None,
585
+ mincount: int = 1,
586
+ uncompressed: bool = False,
587
+ ):
588
+ """
589
+ Search for motifs in a FASTA file.
590
+
591
+ Args:
592
+ ref_fa: Reference FASTA file.
593
+ motif: Motif to search for.
594
+ outfile: Output BED file (e.g., motif.bed.gz). Defaults to stdout.
595
+ mincount: Minimum number of motif repeats.
596
+ uncompressed: Write uncompressed output.
597
+ """
598
+ if not ref_fa.exists():
599
+ raise FileNotFoundError(f"Reference FASTA file not found: {ref_fa}")
600
+ if not motif:
601
+ raise ValueError("Motif string cannot be empty.")
602
+ if mincount < 1:
603
+ raise ValueError("Minimum count must be at least 1.")
604
+
605
+ cmd = ["alfred", "motif", "-m", motif]
606
+ output_files = []
607
+
608
+ if outfile:
609
+ cmd.extend(["-o", str(outfile)])
610
+ output_files.append(str(outfile))
611
+ if mincount != 1:
612
+ cmd.extend(["-c", str(mincount)])
613
+ if uncompressed:
614
+ cmd.append("-u")
615
+
616
+ cmd.append(str(ref_fa))
617
+
618
+ try:
619
+ result = subprocess.run(
620
+ cmd, check=True, capture_output=True, text=True, encoding="utf-8"
621
+ )
622
+ return {
623
+ "command_executed": " ".join(cmd),
624
+ "stdout": result.stdout,
625
+ "stderr": result.stderr,
626
+ "output_files": output_files,
627
+ }
628
+ except subprocess.CalledProcessError as e:
629
+ return {
630
+ "command_executed": " ".join(cmd),
631
+ "stdout": e.stdout,
632
+ "stderr": e.stderr,
633
+ "error": "Alfred motif failed",
634
+ "return_code": e.returncode,
635
+ }
636
+
637
+ if __name__ == "__main__":
638
+ mcp.run(transport="stdio")
Biomni/mcp_generated/mcp_alfred/app/alfred_shim_server.py ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ from __future__ import annotations
3
+
4
+ import ast
5
+ from pathlib import Path
6
+
7
+ from mcp.server.fastmcp import FastMCP
8
+
9
+
10
+ SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_alfred/app/alfred_server.py')
11
+ LOCAL_SERVER = Path(__file__).with_name(SOURCE_SERVER.name)
12
+ SERVER_NAME = 'biosci_alfred'
13
+
14
+
15
+ class _ShimMCP:
16
+ @staticmethod
17
+ def tool(*args, **kwargs):
18
+ if args and callable(args[0]) and len(args) == 1 and not kwargs:
19
+ return args[0]
20
+ def _decorator(fn):
21
+ return fn
22
+ return _decorator
23
+
24
+
25
+ def _resolve_source_server():
26
+ if LOCAL_SERVER.exists() and LOCAL_SERVER.name != Path(__file__).name:
27
+ return LOCAL_SERVER
28
+ return SOURCE_SERVER
29
+
30
+
31
+ def _load_functions():
32
+ source_server = _resolve_source_server()
33
+ code = source_server.read_text(encoding="utf-8")
34
+ tree = ast.parse(code, filename=str(source_server))
35
+ function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")]
36
+ namespace = {
37
+ "__name__": "__mcp_source__",
38
+ "mcp": _ShimMCP(),
39
+ }
40
+ exec(compile(code, str(source_server), "exec"), namespace, namespace)
41
+ loaded = []
42
+ for name in function_names:
43
+ fn = namespace.get(name)
44
+ if callable(fn):
45
+ loaded.append(fn)
46
+ return loaded
47
+
48
+
49
+ mcp = FastMCP(SERVER_NAME)
50
+ for _fn in _load_functions():
51
+ mcp.tool()(_fn)
52
+
53
+
54
+ if __name__ == "__main__":
55
+ mcp.run(transport="stdio")
Biomni/mcp_generated/mcp_alfred/app/requirements.txt ADDED
@@ -0,0 +1 @@
 
 
1
+
Biomni/mcp_generated/mcp_alfred/docker-compose.yml ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: '3.8'
2
+
3
+ services:
4
+ mcp-alfred:
5
+ build: .
6
+ image: mcp-alfred:latest
7
+ container_name: mcp-alfred
8
+ ports:
9
+ - "8000:8000"
10
+ environment:
11
+ - MCP_SERVER_NAME=alfred
12
+ volumes:
13
+ - ./workspace:/app/workspace
14
+ - ./output:/app/output
15
+ restart: unless-stopped
16
+ healthcheck:
17
+ test: ["CMD", "python", "-c", "import sys; sys.exit(0)"]
18
+ interval: 30s
19
+ timeout: 10s
20
+ retries: 3
21
+ start_period: 5s
22
+
Biomni/mcp_generated/mcp_alfred/environment.yaml ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ name: mcp-tool
3
+ channels:
4
+ - bioconda
5
+ - conda-forge
6
+ - defaults
7
+ dependencies:
8
+ - alfred
9
+ - python=3.10
10
+
Biomni/mcp_generated/mcp_alfred/requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ fastmcp
2
+ mcp
Biomni/mcp_generated/mcp_aria2/Dockerfile ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ FROM python:3.10-slim
3
+
4
+ # Install system dependencies
5
+ RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/*
6
+
7
+ # Install Miniconda
8
+ 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
9
+
10
+ # Add conda to PATH
11
+ ENV PATH="/opt/conda/bin:$PATH"
12
+
13
+ # Install aria2 via conda (e.g., from bioconda)
14
+ RUN conda install -c bioconda aria2 -y && conda clean -a
15
+
16
+ # Install Python dependencies
17
+ RUN pip install uv
18
+ RUN uv pip install --system fastmcp
19
+
20
+ # Create app directory
21
+ WORKDIR /app
22
+
23
+ # Copy your MCP server
24
+ COPY aria2_server.py /app/
25
+
26
+ # Create workspace and output directories
27
+ RUN mkdir -p /app/workspace /app/output
28
+
29
+ # Make sure the server script is executable
30
+ RUN chmod +x /app/aria2_server.py
31
+
32
+ # Expose port for MCP over HTTP (optional)
33
+ EXPOSE 8000
34
+
35
+ # Health check
36
+ HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)"
37
+
38
+ # Default command runs the MCP server via stdio
39
+ CMD ["python", "/app/aria2_server.py"]
40
+
Biomni/mcp_generated/mcp_aria2/app/aria2_shim_server.py ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ from __future__ import annotations
3
+
4
+ import ast
5
+ from pathlib import Path
6
+
7
+ from mcp.server.fastmcp import FastMCP
8
+
9
+
10
+ SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_aria2/app/aria2_server.py')
11
+ LOCAL_SERVER = Path(__file__).with_name(SOURCE_SERVER.name)
12
+ SERVER_NAME = 'biosci_aria2'
13
+
14
+
15
+ class _ShimMCP:
16
+ @staticmethod
17
+ def tool(*args, **kwargs):
18
+ if args and callable(args[0]) and len(args) == 1 and not kwargs:
19
+ return args[0]
20
+ def _decorator(fn):
21
+ return fn
22
+ return _decorator
23
+
24
+
25
+ def _resolve_source_server():
26
+ if LOCAL_SERVER.exists() and LOCAL_SERVER.name != Path(__file__).name:
27
+ return LOCAL_SERVER
28
+ return SOURCE_SERVER
29
+
30
+
31
+ def _load_functions():
32
+ source_server = _resolve_source_server()
33
+ code = source_server.read_text(encoding="utf-8")
34
+ tree = ast.parse(code, filename=str(source_server))
35
+ function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")]
36
+ namespace = {
37
+ "__name__": "__mcp_source__",
38
+ "mcp": _ShimMCP(),
39
+ }
40
+ exec(compile(code, str(source_server), "exec"), namespace, namespace)
41
+ loaded = []
42
+ for name in function_names:
43
+ fn = namespace.get(name)
44
+ if callable(fn):
45
+ loaded.append(fn)
46
+ return loaded
47
+
48
+
49
+ mcp = FastMCP(SERVER_NAME)
50
+ for _fn in _load_functions():
51
+ mcp.tool()(_fn)
52
+
53
+
54
+ if __name__ == "__main__":
55
+ mcp.run(transport="stdio")
Biomni/mcp_generated/mcp_aria2/docker-compose.yml ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: '3.8'
2
+
3
+ services:
4
+ mcp-aria2:
5
+ build: .
6
+ image: mcp-aria2:latest
7
+ container_name: mcp-aria2
8
+ ports:
9
+ - "8000:8000"
10
+ environment:
11
+ - MCP_SERVER_NAME=aria2
12
+ volumes:
13
+ - ./workspace:/app/workspace
14
+ - ./output:/app/output
15
+ restart: unless-stopped
16
+ healthcheck:
17
+ test: ["CMD", "python", "-c", "import sys; sys.exit(0)"]
18
+ interval: 30s
19
+ timeout: 10s
20
+ retries: 3
21
+ start_period: 5s
22
+
Biomni/mcp_generated/mcp_aria2/requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ fastmcp
2
+ mcp
Biomni/mcp_generated/mcp_augur/requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ fastmcp
2
+ mcp
Biomni/mcp_generated/mcp_bioconductor-biocfilecache/Dockerfile ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ FROM python:3.10-slim
3
+
4
+ # Install system dependencies
5
+ RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/*
6
+
7
+ # Install Miniconda
8
+ 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
9
+
10
+ # Add conda to PATH
11
+ ENV PATH="/opt/conda/bin:$PATH"
12
+
13
+ # Install bioconductor-biocfilecache via conda (e.g., from bioconda)
14
+ RUN conda install -c bioconda bioconductor-biocfilecache -y && conda clean -a
15
+
16
+ # Install Python dependencies
17
+ RUN pip install uv
18
+ RUN uv pip install --system fastmcp
19
+
20
+ # Create app directory
21
+ WORKDIR /app
22
+
23
+ # Copy your MCP server
24
+ COPY app/bioconductor-biocfilecache_server.py /app/
25
+
26
+ # Create workspace and output directories
27
+ RUN mkdir -p /app/workspace /app/output
28
+
29
+ # Make sure the server script is executable
30
+ RUN chmod +x /app/bioconductor-biocfilecache_server.py
31
+
32
+ # Expose port for MCP over HTTP (optional)
33
+ EXPOSE 8000
34
+
35
+ # Health check
36
+ HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)"
37
+
38
+ # Default command runs the MCP server via stdio
39
+ CMD ["python", "/app/bioconductor-biocfilecache_server.py"]
40
+
Biomni/mcp_generated/mcp_bioconductor-biocfilecache/app/bioconductor-biocfilecache_server.py ADDED
@@ -0,0 +1,314 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import subprocess
2
+ import logging
3
+ from pathlib import Path
4
+ from typing import List, Literal, Optional, Dict
5
+
6
+ # This is a placeholder for the actual MCP decorator.
7
+ # In a real MCP environment, this would be provided by the MCP framework.
8
+ class mcp:
9
+ @staticmethod
10
+ def tool():
11
+ def decorator(func):
12
+ return func
13
+ return decorator
14
+
15
+ def _validate_cache_path(cache_path: Path, check_exists: bool = True) -> None:
16
+ """Helper function to validate the cache path."""
17
+ if check_exists and not cache_path.is_dir():
18
+ raise FileNotFoundError(f"BiocFileCache directory not found at '{cache_path}'")
19
+
20
+ def _r_string_vector(items: List[str]) -> str:
21
+ """Converts a Python list of strings to an R character vector string."""
22
+ if not items:
23
+ return "c()"
24
+ # Escape single quotes for R: ' -> \'
25
+ escaped_items = [item.replace("'", "\\'") for item in items]
26
+ quoted_items = [f"'{item}'" for item in escaped_items]
27
+ return f"c({', '.join(quoted_items)})"
28
+
29
+ def _run_r_command(r_command: str) -> Dict:
30
+ """Executes an R command and returns a structured response."""
31
+ command = ["Rscript", "-e", r_command]
32
+ command_str = " ".join(command)
33
+ try:
34
+ result = subprocess.run(
35
+ command,
36
+ check=True,
37
+ capture_output=True,
38
+ text=True,
39
+ encoding='utf-8'
40
+ )
41
+ return {
42
+ "command_executed": command_str,
43
+ "stdout": result.stdout.strip(),
44
+ "stderr": result.stderr.strip(),
45
+ }
46
+ except FileNotFoundError:
47
+ logging.error("Rscript not found. R must be installed and in the system's PATH.")
48
+ raise RuntimeError("Rscript not found. R must be installed and in the system's PATH.")
49
+ except subprocess.CalledProcessError as e:
50
+ logging.error(f"R script execution failed.\nStderr: {e.stderr}\nStdout: {e.stdout}")
51
+ return {
52
+ "command_executed": command_str,
53
+ "stdout": e.stdout.strip(),
54
+ "stderr": e.stderr.strip(),
55
+ "error": "R script execution failed."
56
+ }
57
+
58
+ from mcp.server.fastmcp import FastMCP
59
+
60
+ SERVER_NAME = 'local_bioconductor_biocfilecache'
61
+ mcp = FastMCP(SERVER_NAME)
62
+
63
+ @mcp.tool()
64
+ def biocfilecache_new(cache_path: Path) -> Dict:
65
+ """
66
+ Creates a new, empty BiocFileCache at the specified location.
67
+
68
+ Args:
69
+ cache_path: The directory path where the cache will be created.
70
+ The parent directory must exist, and the target path must not.
71
+
72
+ Returns:
73
+ A dictionary containing the command executed, stdout (the cache path),
74
+ stderr, and the path to the created cache directory.
75
+ """
76
+ if cache_path.exists():
77
+ raise ValueError(f"Cache path '{cache_path}' already exists. Cannot create a new cache here.")
78
+ if not cache_path.parent.is_dir():
79
+ raise FileNotFoundError(f"Parent directory '{cache_path.parent}' does not exist.")
80
+
81
+ # Use forward slashes for R path compatibility
82
+ safe_cache_path = str(cache_path).replace('\\', '/')
83
+ r_command = (
84
+ f"library(BiocFileCache); "
85
+ f"bfc <- bfcnew('{safe_cache_path}', ask=FALSE); "
86
+ f"cat(bfcpath(bfc))"
87
+ )
88
+
89
+ response = _run_r_command(r_command)
90
+ if "error" not in response:
91
+ response["output_files"] = {"cache_directory": str(cache_path)}
92
+ return response
93
+
94
+ @mcp.tool()
95
+ def biocfilecache_add(
96
+ cache_path: Path,
97
+ rname: str,
98
+ fpath: str,
99
+ action: Literal["copy", "move", "asis"] = "copy",
100
+ rtype: Literal["web", "local"] = "web"
101
+ ) -> Dict:
102
+ """
103
+ Adds a resource to the BiocFileCache.
104
+
105
+ Args:
106
+ cache_path: Path to the BiocFileCache directory.
107
+ rname: A user-friendly name for the resource.
108
+ fpath: The path to the resource, either a URL or a local file path.
109
+ action: How to handle the file. 'copy' (default), 'move', or 'asis' (for remote files).
110
+ rtype: The type of resource, 'web' (default) or 'local'.
111
+
112
+ Returns:
113
+ A dictionary containing the command executed, stdout (the new resource ID), and stderr.
114
+ """
115
+ _validate_cache_path(cache_path)
116
+ if rtype == "local" and not Path(fpath).exists():
117
+ raise FileNotFoundError(f"Local file '{fpath}' not found for adding to cache.")
118
+
119
+ safe_cache_path = str(cache_path).replace('\\', '/')
120
+ # Escape single quotes and normalize path for R
121
+ safe_rname = rname.replace("'", "\\'")
122
+ safe_fpath = fpath.replace('\\', '/').replace("'", "\\'")
123
+
124
+ r_command = (
125
+ f"library(BiocFileCache); "
126
+ f"bfc <- BiocFileCache('{safe_cache_path}', ask=FALSE); "
127
+ f"rid <- bfcadd(bfc, rname='{safe_rname}', fpath='{safe_fpath}', action='{action}', rtype='{rtype}'); "
128
+ f"cat(rid)"
129
+ )
130
+ return _run_r_command(r_command)
131
+
132
+ @mcp.tool()
133
+ def biocfilecache_rpath(cache_path: Path, rids: List[str]) -> Dict:
134
+ """
135
+ Retrieves the local file paths of resources from the cache using their resource IDs (rids).
136
+
137
+ Args:
138
+ cache_path: Path to the BiocFileCache directory.
139
+ rids: A list of resource IDs (e.g., ['BFC1', 'BFC2']) to look up.
140
+
141
+ Returns:
142
+ A dictionary containing the command executed, stdout (newline-separated file paths), and stderr.
143
+ """
144
+ _validate_cache_path(cache_path)
145
+ if not rids:
146
+ raise ValueError("The 'rids' list cannot be empty.")
147
+
148
+ safe_cache_path = str(cache_path).replace('\\', '/')
149
+ rids_vector = _r_string_vector(rids)
150
+ r_command = (
151
+ f"library(BiocFileCache); "
152
+ f"bfc <- BiocFileCache('{safe_cache_path}', ask=FALSE); "
153
+ f"paths <- bfcrpath(bfc, rids={rids_vector}); "
154
+ f"cat(paths, sep='\\n')"
155
+ )
156
+ return _run_r_command(r_command)
157
+
158
+ @mcp.tool()
159
+ def biocfilecache_query(cache_path: Path, query: str, field: Optional[str] = None) -> Dict:
160
+ """
161
+ Queries the cache metadata using an SQL-like expression.
162
+
163
+ Args:
164
+ cache_path: Path to the BiocFileCache directory.
165
+ query: The SQL 'WHERE' clause for filtering resources (e.g., "rname == 'my_file'").
166
+ field: Optional. The specific column/field to return from the query results.
167
+
168
+ Returns:
169
+ A dictionary containing the command executed, stdout (query results as a table), and stderr.
170
+ """
171
+ _validate_cache_path(cache_path)
172
+ safe_cache_path = str(cache_path).replace('\\', '/')
173
+ safe_query = query.replace("'", "\\'")
174
+
175
+ field_arg = ""
176
+ if field:
177
+ safe_field = field.replace("'", "\\'")
178
+ field_arg = f", field='{safe_field}'"
179
+
180
+ r_command = (
181
+ f"library(BiocFileCache); "
182
+ f"bfc <- BiocFileCache('{safe_cache_path}', ask=FALSE); "
183
+ f"res <- bfcquery(bfc, query='{safe_query}'{field_arg}); "
184
+ f"print(res)"
185
+ )
186
+ return _run_r_command(r_command)
187
+
188
+ @mcp.tool()
189
+ def biocfilecache_remove(cache_path: Path, rids: List[str]) -> Dict:
190
+ """
191
+ Removes resources and their associated files from the cache.
192
+
193
+ Args:
194
+ cache_path: Path to the BiocFileCache directory.
195
+ rids: A list of resource IDs to remove.
196
+
197
+ Returns:
198
+ A dictionary containing the command executed, stdout, and stderr.
199
+ """
200
+ _validate_cache_path(cache_path)
201
+ if not rids:
202
+ raise ValueError("The 'rids' list cannot be empty.")
203
+
204
+ safe_cache_path = str(cache_path).replace('\\', '/')
205
+ rids_vector = _r_string_vector(rids)
206
+ r_command = (
207
+ f"library(BiocFileCache); "
208
+ f"bfc <- BiocFileCache('{safe_cache_path}', ask=FALSE); "
209
+ f"bfcremove(bfc, rids={rids_vector}); "
210
+ f"cat('Specified resources removed.')"
211
+ )
212
+ return _run_r_command(r_command)
213
+
214
+ @mcp.tool()
215
+ def biocfilecache_ls(cache_path: Path, pattern: Optional[str] = None) -> Dict:
216
+ """
217
+ Lists resources in the cache, optionally filtering by a regular expression.
218
+
219
+ Args:
220
+ cache_path: Path to the BiocFileCache directory.
221
+ pattern: An optional regular expression to filter resource names (rname).
222
+
223
+ Returns:
224
+ A dictionary containing the command executed, stdout (a table of resources), and stderr.
225
+ """
226
+ _validate_cache_path(cache_path)
227
+ safe_cache_path = str(cache_path).replace('\\', '/')
228
+
229
+ pattern_arg = ""
230
+ if pattern:
231
+ safe_pattern = pattern.replace("'", "\\'")
232
+ pattern_arg = f", pattern='{safe_pattern}'"
233
+
234
+ r_command = (
235
+ f"library(BiocFileCache); "
236
+ f"bfc <- BiocFileCache('{safe_cache_path}', ask=FALSE); "
237
+ f"res <- bfcls(bfc{pattern_arg}); "
238
+ f"print(res)"
239
+ )
240
+ return _run_r_command(r_command)
241
+
242
+ @mcp.tool()
243
+ def biocfilecache_update(cache_path: Path, rids: List[str]) -> Dict:
244
+ """
245
+ Updates resources in the cache by re-downloading them.
246
+
247
+ Args:
248
+ cache_path: Path to the BiocFileCache directory.
249
+ rids: A list of resource IDs to update.
250
+
251
+ Returns:
252
+ A dictionary containing the command executed, stdout (updated resource info), and stderr.
253
+ """
254
+ _validate_cache_path(cache_path)
255
+ if not rids:
256
+ raise ValueError("The 'rids' list cannot be empty.")
257
+
258
+ safe_cache_path = str(cache_path).replace('\\', '/')
259
+ rids_vector = _r_string_vector(rids)
260
+ r_command = (
261
+ f"library(BiocFileCache); "
262
+ f"bfc <- BiocFileCache('{safe_cache_path}', ask=FALSE); "
263
+ f"res <- bfcupdate(bfc, rids={rids_vector}); "
264
+ f"print(res)"
265
+ )
266
+ return _run_r_command(r_command)
267
+
268
+ @mcp.tool()
269
+ def biocfilecache_clean(cache_path: Path) -> Dict:
270
+ """
271
+ Cleans the cache by removing files that are no longer tracked in the database.
272
+
273
+ Args:
274
+ cache_path: Path to the BiocFileCache directory.
275
+
276
+ Returns:
277
+ A dictionary containing the command executed, stdout, and stderr.
278
+ """
279
+ _validate_cache_path(cache_path)
280
+ safe_cache_path = str(cache_path).replace('\\', '/')
281
+ r_command = (
282
+ f"library(BiocFileCache); "
283
+ f"bfc <- BiocFileCache('{safe_cache_path}', ask=FALSE); "
284
+ f"bfcclean(bfc, ask=FALSE); "
285
+ f"cat('Cache cleaned.')"
286
+ )
287
+ return _run_r_command(r_command)
288
+
289
+ @mcp.tool()
290
+ def biocfilecache_info(cache_path: Path, rids: Optional[List[str]] = None) -> Dict:
291
+ """
292
+ Retrieves detailed metadata for all or specified resources in the cache.
293
+
294
+ Args:
295
+ cache_path: Path to the BiocFileCache directory.
296
+ rids: Optional list of resource IDs to get information for. If None, info for all resources is returned.
297
+
298
+ Returns:
299
+ A dictionary containing the command executed, stdout (a table of resource info), and stderr.
300
+ """
301
+ _validate_cache_path(cache_path)
302
+ safe_cache_path = str(cache_path).replace('\\', '/')
303
+ rids_arg = f", rids={_r_string_vector(rids)}" if rids else ""
304
+
305
+ r_command = (
306
+ f"library(BiocFileCache); "
307
+ f"bfc <- BiocFileCache('{safe_cache_path}', ask=FALSE); "
308
+ f"res <- bfcinfo(bfc{rids_arg}); "
309
+ f"print(res)"
310
+ )
311
+ return _run_r_command(r_command)
312
+
313
+ if __name__ == "__main__":
314
+ mcp.run(transport="stdio")
Biomni/mcp_generated/mcp_bioconductor-biocfilecache/app/bioconductor-biocfilecache_shim_server.py ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ from __future__ import annotations
3
+
4
+ import ast
5
+ from pathlib import Path
6
+
7
+ from mcp.server.fastmcp import FastMCP
8
+
9
+
10
+ SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bioconductor-biocfilecache/app/bioconductor-biocfilecache_server.py')
11
+ LOCAL_SERVER = Path(__file__).with_name(SOURCE_SERVER.name)
12
+ SERVER_NAME = 'biosci_bioconductor_biocfilecache'
13
+
14
+
15
+ class _ShimMCP:
16
+ @staticmethod
17
+ def tool(*args, **kwargs):
18
+ if args and callable(args[0]) and len(args) == 1 and not kwargs:
19
+ return args[0]
20
+ def _decorator(fn):
21
+ return fn
22
+ return _decorator
23
+
24
+
25
+ def _resolve_source_server():
26
+ if LOCAL_SERVER.exists() and LOCAL_SERVER.name != Path(__file__).name:
27
+ return LOCAL_SERVER
28
+ return SOURCE_SERVER
29
+
30
+
31
+ def _load_functions():
32
+ source_server = _resolve_source_server()
33
+ code = source_server.read_text(encoding="utf-8")
34
+ tree = ast.parse(code, filename=str(source_server))
35
+ function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")]
36
+ namespace = {
37
+ "__name__": "__mcp_source__",
38
+ "mcp": _ShimMCP(),
39
+ }
40
+ exec(compile(code, str(source_server), "exec"), namespace, namespace)
41
+ loaded = []
42
+ for name in function_names:
43
+ fn = namespace.get(name)
44
+ if callable(fn):
45
+ loaded.append(fn)
46
+ return loaded
47
+
48
+
49
+ mcp = FastMCP(SERVER_NAME)
50
+ for _fn in _load_functions():
51
+ mcp.tool()(_fn)
52
+
53
+
54
+ if __name__ == "__main__":
55
+ mcp.run(transport="stdio")
Biomni/mcp_generated/mcp_bioconductor-biocfilecache/app/requirements.txt ADDED
@@ -0,0 +1 @@
 
 
1
+
Biomni/mcp_generated/mcp_bioconductor-biocfilecache/docker-compose.yml ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: '3.8'
2
+
3
+ services:
4
+ mcp-bioconductor-biocfilecache:
5
+ build: .
6
+ image: mcp-bioconductor-biocfilecache:latest
7
+ container_name: mcp-bioconductor-biocfilecache
8
+ ports:
9
+ - "8000:8000"
10
+ environment:
11
+ - MCP_SERVER_NAME=bioconductor-biocfilecache
12
+ volumes:
13
+ - ./workspace:/app/workspace
14
+ - ./output:/app/output
15
+ restart: unless-stopped
16
+ healthcheck:
17
+ test: ["CMD", "python", "-c", "import sys; sys.exit(0)"]
18
+ interval: 30s
19
+ timeout: 10s
20
+ retries: 3
21
+ start_period: 5s
22
+
Biomni/mcp_generated/mcp_bioconductor-biocfilecache/environment.yaml ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ name: mcp-tool
3
+ channels:
4
+ - bioconda
5
+ - conda-forge
6
+ - defaults
7
+ dependencies:
8
+ - bioconductor-biocfilecache
9
+ - python=3.10
10
+
Biomni/mcp_generated/mcp_bioconductor-biocfilecache/requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ fastmcp
2
+ mcp
Biomni/mcp_generated/mcp_bioconductor-biocgenerics/Dockerfile ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ FROM python:3.10-slim
3
+
4
+ # Install system dependencies
5
+ RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/*
6
+
7
+ # Install Miniconda
8
+ 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
9
+
10
+ # Add conda to PATH
11
+ ENV PATH="/opt/conda/bin:$PATH"
12
+
13
+ # Install bioconductor-biocgenerics via conda (e.g., from bioconda)
14
+ RUN conda install -c bioconda bioconductor-biocgenerics -y && conda clean -a
15
+
16
+ # Install Python dependencies
17
+ RUN pip install uv
18
+ RUN uv pip install --system fastmcp
19
+
20
+ # Create app directory
21
+ WORKDIR /app
22
+
23
+ # Copy your MCP server
24
+ COPY bioconductor-biocgenerics_server.py /app/
25
+
26
+ # Create workspace and output directories
27
+ RUN mkdir -p /app/workspace /app/output
28
+
29
+ # Make sure the server script is executable
30
+ RUN chmod +x /app/bioconductor-biocgenerics_server.py
31
+
32
+ # Expose port for MCP over HTTP (optional)
33
+ EXPOSE 8000
34
+
35
+ # Health check
36
+ HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)"
37
+
38
+ # Default command runs the MCP server via stdio
39
+ CMD ["python", "/app/bioconductor-biocgenerics_server.py"]
40
+
Biomni/mcp_generated/mcp_bioconductor-biocgenerics/app/bioconductor-biocgenerics_shim_server.py ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ from __future__ import annotations
3
+
4
+ import ast
5
+ from pathlib import Path
6
+
7
+ from mcp.server.fastmcp import FastMCP
8
+
9
+
10
+ SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-biocgenerics/app/bioconductor-biocgenerics_server.py')
11
+ LOCAL_SERVER = Path(__file__).with_name(SOURCE_SERVER.name)
12
+ SERVER_NAME = 'biosci_bioconductor_biocgenerics'
13
+
14
+
15
+ class _ShimMCP:
16
+ @staticmethod
17
+ def tool(*args, **kwargs):
18
+ if args and callable(args[0]) and len(args) == 1 and not kwargs:
19
+ return args[0]
20
+ def _decorator(fn):
21
+ return fn
22
+ return _decorator
23
+
24
+
25
+ def _resolve_source_server():
26
+ if LOCAL_SERVER.exists() and LOCAL_SERVER.name != Path(__file__).name:
27
+ return LOCAL_SERVER
28
+ return SOURCE_SERVER
29
+
30
+
31
+ def _load_functions():
32
+ source_server = _resolve_source_server()
33
+ code = source_server.read_text(encoding="utf-8")
34
+ tree = ast.parse(code, filename=str(source_server))
35
+ function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")]
36
+ namespace = {
37
+ "__name__": "__mcp_source__",
38
+ "mcp": _ShimMCP(),
39
+ }
40
+ exec(compile(code, str(source_server), "exec"), namespace, namespace)
41
+ loaded = []
42
+ for name in function_names:
43
+ fn = namespace.get(name)
44
+ if callable(fn):
45
+ loaded.append(fn)
46
+ return loaded
47
+
48
+
49
+ mcp = FastMCP(SERVER_NAME)
50
+ for _fn in _load_functions():
51
+ mcp.tool()(_fn)
52
+
53
+
54
+ if __name__ == "__main__":
55
+ mcp.run(transport="stdio")
Biomni/mcp_generated/mcp_bioconductor-biocgenerics/docker-compose.yml ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: '3.8'
2
+
3
+ services:
4
+ mcp-bioconductor-biocgenerics:
5
+ build: .
6
+ image: mcp-bioconductor-biocgenerics:latest
7
+ container_name: mcp-bioconductor-biocgenerics
8
+ ports:
9
+ - "8000:8000"
10
+ environment:
11
+ - MCP_SERVER_NAME=bioconductor-biocgenerics
12
+ volumes:
13
+ - ./workspace:/app/workspace
14
+ - ./output:/app/output
15
+ restart: unless-stopped
16
+ healthcheck:
17
+ test: ["CMD", "python", "-c", "import sys; sys.exit(0)"]
18
+ interval: 30s
19
+ timeout: 10s
20
+ retries: 3
21
+ start_period: 5s
22
+
Biomni/mcp_generated/mcp_bioconductor-biocgenerics/environment.yaml ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ name: mcp-tool
3
+ channels:
4
+ - bioconda
5
+ - conda-forge
6
+ - defaults
7
+ dependencies:
8
+ - bioconductor-biocgenerics
9
+ - python=3.10
10
+
Biomni/mcp_generated/mcp_bioconductor-delayedarray/requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ fastmcp
2
+ mcp
Biomni/mcp_generated/mcp_bioconductor-nebulosa/Dockerfile ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ FROM python:3.10-slim
3
+
4
+ # Install system dependencies
5
+ RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/*
6
+
7
+ # Install Miniconda
8
+ 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
9
+
10
+ # Add conda to PATH
11
+ ENV PATH="/opt/conda/bin:$PATH"
12
+
13
+ # Install bioconductor-nebulosa via conda (e.g., from bioconda)
14
+ RUN conda install -c bioconda bioconductor-nebulosa -y && conda clean -a
15
+
16
+ # Install Python dependencies
17
+ RUN pip install uv
18
+ RUN uv pip install --system fastmcp
19
+
20
+ # Create app directory
21
+ WORKDIR /app
22
+
23
+ # Copy your MCP server
24
+ COPY bioconductor-nebulosa_server.py /app/
25
+
26
+ # Create workspace and output directories
27
+ RUN mkdir -p /app/workspace /app/output
28
+
29
+ # Make sure the server script is executable
30
+ RUN chmod +x /app/bioconductor-nebulosa_server.py
31
+
32
+ # Expose port for MCP over HTTP (optional)
33
+ EXPOSE 8000
34
+
35
+ # Health check
36
+ HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)"
37
+
38
+ # Default command runs the MCP server via stdio
39
+ CMD ["python", "/app/bioconductor-nebulosa_server.py"]
40
+
Biomni/mcp_generated/mcp_bioconductor-nebulosa/app/bioconductor-nebulosa_server.py ADDED
@@ -0,0 +1,185 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import subprocess
2
+ import tempfile
3
+ from pathlib import Path
4
+ from typing import List, Optional, Tuple
5
+
6
+ # This is a placeholder for the MCP decorator.
7
+ # In a real MCP environment, this would be imported.
8
+ def tool(*args, **kwargs):
9
+ def decorator(func):
10
+ return func
11
+ return decorator
12
+
13
+ mcp = type("mcp", (), {"tool": tool})
14
+
15
+
16
+ from mcp.server.fastmcp import FastMCP
17
+
18
+ SERVER_NAME = 'local_bioconductor_nebulosa'
19
+ mcp = FastMCP(SERVER_NAME)
20
+
21
+ @mcp.tool()
22
+ def nebulosa_plot_density(
23
+ object_file: Path,
24
+ features: List[str],
25
+ output_file: Path,
26
+ reduction: Optional[str] = None,
27
+ dims: Tuple[int, int] = (1, 2),
28
+ pal: str = "viridis",
29
+ joint: bool = False,
30
+ combine: bool = True,
31
+ pt_size: float = 0.1,
32
+ pt_shape: int = 16,
33
+ pt_alpha: float = 1.0,
34
+ dens_alpha: float = 0.5,
35
+ plot_width: float = 8.0,
36
+ plot_height: float = 6.0,
37
+ ) -> dict:
38
+ """
39
+ Generates density plots for single-cell features using the Nebulosa R package.
40
+
41
+ This tool wraps the `plot_density` function from `bioconductor-nebulosa`. It takes a
42
+ single-cell object (e.g., from Seurat, saved as an .rds file), a list of features
43
+ (e.g., genes), and generates a plot showing the expression density of these
44
+ features on a dimensionality reduction embedding (like UMAP or t-SNE).
45
+
46
+ Args:
47
+ object_file: Path to the input single-cell object file in .rds format.
48
+ features: A list of features (e.g., genes) to plot.
49
+ output_file: Path to save the output plot. Supported formats include PDF, PNG, JPEG.
50
+ reduction: The dimensionality reduction to use (e.g., 'umap', 'tsne').
51
+ If None, the default from the object is used.
52
+ dims: A tuple of two integers specifying the dimensions to plot (e.g., (1, 2)).
53
+ pal: The color palette to use for the density plot (e.g., 'viridis', 'magma').
54
+ joint: If True, plots all features jointly on a single plot.
55
+ combine: If True and `joint` is False, combines multiple feature plots into a single grid.
56
+ pt_size: The size of the points in the plot.
57
+ pt_shape: The shape of the points (integer code).
58
+ pt_alpha: The transparency of the points (0.0 to 1.0).
59
+ dens_alpha: The transparency of the density layer (0.0 to 1.0).
60
+ plot_width: The width of the output plot in inches.
61
+ plot_height: The height of the output plot in inches.
62
+
63
+ Returns:
64
+ A dictionary containing the execution command, stdout, stderr, and a
65
+ mapping to the generated output plot file.
66
+ """
67
+ # --- Input Validation ---
68
+ if not object_file.is_file():
69
+ raise FileNotFoundError(f"Input object file not found: {object_file}")
70
+
71
+ if not features:
72
+ raise ValueError("The 'features' list cannot be empty.")
73
+
74
+ if not output_file.parent.exists():
75
+ raise FileNotFoundError(f"Output directory does not exist: {output_file.parent}")
76
+
77
+ if len(dims) != 2:
78
+ raise ValueError(f"'dims' must be a tuple of two integers, but got {dims}")
79
+
80
+ if not (0.0 <= pt_alpha <= 1.0):
81
+ raise ValueError(f"'pt_alpha' must be between 0.0 and 1.0, but got {pt_alpha}")
82
+
83
+ if not (0.0 <= dens_alpha <= 1.0):
84
+ raise ValueError(f"'dens_alpha' must be between 0.0 and 1.0, but got {dens_alpha}")
85
+
86
+ # --- R Script Generation ---
87
+ # Convert Python types to R syntax strings
88
+ features_r_str = ', '.join(f'"{f}"' for f in features)
89
+ reduction_r_str = f'"{reduction}"' if reduction else "NULL"
90
+ joint_r_str = str(joint).upper()
91
+ combine_r_str = str(combine).upper()
92
+
93
+ r_script_content = f"""
94
+ # Suppress package startup messages for cleaner output
95
+ suppressPackageStartupMessages(library(Nebulosa))
96
+ suppressPackageStartupMessages(library(Seurat)) # Assumes a Seurat object for loading
97
+ suppressPackageStartupMessages(library(ggplot2))
98
+
99
+ # --- Parameters from Python ---
100
+ object_path <- "{object_file.resolve()}"
101
+ output_path <- "{output_file.resolve()}"
102
+ features_vec <- c({features_r_str})
103
+ reduction_val <- {reduction_r_str}
104
+ dims_vec <- c({dims[0]}, {dims[1]})
105
+ pal_str <- "{pal}"
106
+ joint_bool <- {joint_r_str}
107
+ combine_bool <- {combine_r_str}
108
+ pt_size_num <- {pt_size}
109
+ pt_shape_num <- {pt_shape}
110
+ pt_alpha_num <- {pt_alpha}
111
+ dens_alpha_num <- {dens_alpha}
112
+ plot_width_num <- {plot_width}
113
+ plot_height_num <- {plot_height}
114
+
115
+ # --- Main Logic ---
116
+ cat("Loading single-cell object from:", object_path, "\\n")
117
+ sobj <- readRDS(object_path)
118
+
119
+ cat("Generating density plot for features:", paste(features_vec, collapse=", "), "\\n")
120
+ p <- plot_density(
121
+ object = sobj,
122
+ features = features_vec,
123
+ reduction = reduction_val,
124
+ dims = dims_vec,
125
+ pal = pal_str,
126
+ joint = joint_bool,
127
+ combine = combine_bool,
128
+ pt.size = pt_size_num,
129
+ pt.shape = pt_shape_num,
130
+ pt.alpha = pt_alpha_num,
131
+ dens.alpha = dens_alpha_num
132
+ )
133
+
134
+ cat("Saving plot to:", output_path, "\\n")
135
+ ggsave(
136
+ filename = output_path,
137
+ plot = p,
138
+ width = plot_width_num,
139
+ height = plot_height_num,
140
+ units = "in"
141
+ )
142
+
143
+ cat("Plot generation complete.\\n")
144
+ """
145
+
146
+ # --- Subprocess Execution ---
147
+ stdout_str, stderr_str = "", ""
148
+ command_to_run = []
149
+
150
+ try:
151
+ with tempfile.NamedTemporaryFile(
152
+ mode="w", suffix=".R", delete=False
153
+ ) as tmp_script:
154
+ tmp_script_path = Path(tmp_script.name)
155
+ tmp_script.write(r_script_content)
156
+
157
+ command_to_run = ["Rscript", str(tmp_script_path)]
158
+ process = subprocess.run(
159
+ command_to_run,
160
+ capture_output=True,
161
+ text=True,
162
+ check=True,
163
+ )
164
+ stdout_str = process.stdout
165
+ stderr_str = process.stderr
166
+
167
+ except FileNotFoundError:
168
+ raise RuntimeError("Rscript not found. Please ensure R is installed and in your PATH.")
169
+ except subprocess.CalledProcessError as e:
170
+ stderr_str = e.stderr + f"\n--- R Script Content ---\n{r_script_content}"
171
+ raise RuntimeError(f"R script execution failed with exit code {e.returncode}:\n{stderr_str}")
172
+ finally:
173
+ if 'tmp_script_path' in locals() and tmp_script_path.exists():
174
+ tmp_script_path.unlink()
175
+
176
+ # --- Structured Result Return ---
177
+ return {
178
+ "command_executed": " ".join(command_to_run),
179
+ "stdout": stdout_str,
180
+ "stderr": stderr_str,
181
+ "output_files": {"density_plot": str(output_file)},
182
+ }
183
+
184
+ if __name__ == "__main__":
185
+ mcp.run(transport="stdio")
Biomni/mcp_generated/mcp_bioconductor-nebulosa/app/bioconductor-nebulosa_shim_server.py ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ from __future__ import annotations
3
+
4
+ import ast
5
+ from pathlib import Path
6
+
7
+ from mcp.server.fastmcp import FastMCP
8
+
9
+
10
+ SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_bioconductor-nebulosa/app/bioconductor-nebulosa_server.py')
11
+ LOCAL_SERVER = Path(__file__).with_name(SOURCE_SERVER.name)
12
+ SERVER_NAME = 'biosci_bioconductor_nebulosa'
13
+
14
+
15
+ class _ShimMCP:
16
+ @staticmethod
17
+ def tool(*args, **kwargs):
18
+ if args and callable(args[0]) and len(args) == 1 and not kwargs:
19
+ return args[0]
20
+ def _decorator(fn):
21
+ return fn
22
+ return _decorator
23
+
24
+
25
+ def _resolve_source_server():
26
+ if LOCAL_SERVER.exists() and LOCAL_SERVER.name != Path(__file__).name:
27
+ return LOCAL_SERVER
28
+ return SOURCE_SERVER
29
+
30
+
31
+ def _load_functions():
32
+ source_server = _resolve_source_server()
33
+ code = source_server.read_text(encoding="utf-8")
34
+ tree = ast.parse(code, filename=str(source_server))
35
+ function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")]
36
+ namespace = {
37
+ "__name__": "__mcp_source__",
38
+ "mcp": _ShimMCP(),
39
+ }
40
+ exec(compile(code, str(source_server), "exec"), namespace, namespace)
41
+ loaded = []
42
+ for name in function_names:
43
+ fn = namespace.get(name)
44
+ if callable(fn):
45
+ loaded.append(fn)
46
+ return loaded
47
+
48
+
49
+ mcp = FastMCP(SERVER_NAME)
50
+ for _fn in _load_functions():
51
+ mcp.tool()(_fn)
52
+
53
+
54
+ if __name__ == "__main__":
55
+ mcp.run(transport="stdio")
Biomni/mcp_generated/mcp_bioconductor-nebulosa/docker-compose.yml ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: '3.8'
2
+
3
+ services:
4
+ mcp-bioconductor-nebulosa:
5
+ build: .
6
+ image: mcp-bioconductor-nebulosa:latest
7
+ container_name: mcp-bioconductor-nebulosa
8
+ ports:
9
+ - "8000:8000"
10
+ environment:
11
+ - MCP_SERVER_NAME=bioconductor-nebulosa
12
+ volumes:
13
+ - ./workspace:/app/workspace
14
+ - ./output:/app/output
15
+ restart: unless-stopped
16
+ healthcheck:
17
+ test: ["CMD", "python", "-c", "import sys; sys.exit(0)"]
18
+ interval: 30s
19
+ timeout: 10s
20
+ retries: 3
21
+ start_period: 5s
22
+
Biomni/mcp_generated/mcp_bioconductor-nebulosa/environment.yaml ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ name: mcp-tool
3
+ channels:
4
+ - bioconda
5
+ - conda-forge
6
+ - defaults
7
+ dependencies:
8
+ - bioconductor-nebulosa
9
+ - python=3.10
10
+
Biomni/mcp_generated/mcp_bioconductor-nebulosa/requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ fastmcp
2
+ mcp
Biomni/mcp_generated/mcp_brooklyn_plot/Dockerfile ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ FROM python:3.10-slim
3
+
4
+ # Install system dependencies
5
+ RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/*
6
+
7
+ # Install Miniconda
8
+ 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
9
+
10
+ # Add conda to PATH
11
+ ENV PATH="/opt/conda/bin:$PATH"
12
+
13
+ # Install brooklyn_plot via conda (e.g., from bioconda)
14
+ RUN conda install -c bioconda brooklyn_plot -y && conda clean -a
15
+
16
+ # Install Python dependencies
17
+ RUN pip install uv
18
+ RUN uv pip install --system fastmcp
19
+
20
+ # Create app directory
21
+ WORKDIR /app
22
+
23
+ # Copy your MCP server
24
+ COPY brooklyn_plot_server.py /app/
25
+
26
+ # Create workspace and output directories
27
+ RUN mkdir -p /app/workspace /app/output
28
+
29
+ # Make sure the server script is executable
30
+ RUN chmod +x /app/brooklyn_plot_server.py
31
+
32
+ # Expose port for MCP over HTTP (optional)
33
+ EXPOSE 8000
34
+
35
+ # Health check
36
+ HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)"
37
+
38
+ # Default command runs the MCP server via stdio
39
+ CMD ["python", "/app/brooklyn_plot_server.py"]
40
+
Biomni/mcp_generated/mcp_brooklyn_plot/app/brooklyn_plot_server.py ADDED
@@ -0,0 +1,170 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import subprocess
2
+ import logging
3
+ from pathlib import Path
4
+ from typing import List, Optional, Literal, Dict, Any
5
+
6
+ # Set up a logger for internal use
7
+ logger = logging.getLogger(__name__)
8
+
9
+ # @mcp.tool() decorator is assumed to be imported from the MCP framework.
10
+ # No need to define it here.
11
+
12
+ from mcp.server.fastmcp import FastMCP
13
+
14
+ SERVER_NAME = 'local_brooklyn_plot'
15
+ mcp = FastMCP(SERVER_NAME)
16
+
17
+ @mcp.tool()
18
+ def run_brooklyn_plot(
19
+ input_file: Path,
20
+ output_file: str,
21
+ input_type: Literal["vcf", "txt"],
22
+ title: str = "Brooklyn Plot",
23
+ width: int = 12,
24
+ height: int = 8,
25
+ dpi: int = 300,
26
+ output_format: Literal["png", "pdf", "svg", "jpg"] = "png",
27
+ style: str = "seaborn-whitegrid",
28
+ palette: str = "colorblind",
29
+ font_scale: float = 1.2,
30
+ hide_legend: bool = False,
31
+ show_genes: bool = False,
32
+ gene_fontsize: int = 8,
33
+ min_vaf: float = 0.0,
34
+ max_vaf: float = 1.0,
35
+ min_depth: int = 0,
36
+ genes_to_label: Optional[List[str]] = None,
37
+ ) -> Dict[str, Any]:
38
+ """
39
+ Generates a Brooklyn plot from variant data.
40
+
41
+ A Brooklyn plot is a type of visualization used in genomics to display variant allele frequencies (VAFs)
42
+ of mutations across different samples or time points, often used in cancer genomics to track clonal evolution.
43
+ This tool takes a VCF or a tab-delimited file as input and produces a customizable plot.
44
+
45
+ Args:
46
+ input_file: Path to the input file containing variant data (VCF or tab-delimited text).
47
+ output_file: Name for the output plot file. The extension should match the chosen format.
48
+ input_type: Type of the input file.
49
+ title: Title of the plot.
50
+ width: Width of the plot in inches.
51
+ height: Height of the plot in inches.
52
+ dpi: Resolution of the plot in dots per inch.
53
+ output_format: Format of the output plot.
54
+ style: Style of the plot. Any valid matplotlib style is accepted.
55
+ palette: Color palette for the plot. Any valid seaborn palette is accepted.
56
+ font_scale: Font scale for the plot.
57
+ hide_legend: If True, hides the legend from the plot.
58
+ show_genes: If True, shows gene names on the plot.
59
+ gene_fontsize: Font size for gene names.
60
+ min_vaf: Minimum variant allele frequency (VAF) to include in the plot.
61
+ max_vaf: Maximum variant allele frequency (VAF) to include in the plot.
62
+ min_depth: Minimum read depth to include in the plot.
63
+ genes_to_label: A list of specific gene names to label on the plot.
64
+
65
+ Returns:
66
+ A dictionary containing the command executed, stdout, stderr, and a list of output files.
67
+ """
68
+ # --- Input Validation ---
69
+ if not input_file.is_file():
70
+ raise FileNotFoundError(f"Input file not found: {input_file}")
71
+
72
+ if width <= 0 or height <= 0 or dpi <= 0:
73
+ raise ValueError("Plot dimensions (width, height, dpi) must be positive.")
74
+ if font_scale <= 0 or gene_fontsize <= 0:
75
+ raise ValueError("Font scaling parameters (font_scale, gene_fontsize) must be positive.")
76
+ if min_depth < 0:
77
+ raise ValueError("min_depth cannot be negative.")
78
+
79
+ if not (0.0 <= min_vaf <= 1.0):
80
+ raise ValueError(f"min_vaf must be between 0.0 and 1.0, but got {min_vaf}")
81
+ if not (0.0 <= max_vaf <= 1.0):
82
+ raise ValueError(f"max_vaf must be between 0.0 and 1.0, but got {max_vaf}")
83
+ if min_vaf > max_vaf:
84
+ raise ValueError(f"min_vaf ({min_vaf}) cannot be greater than max_vaf ({max_vaf})")
85
+
86
+ # --- Command Construction ---
87
+ cmd = [
88
+ "brooklyn_plot",
89
+ "-i", str(input_file),
90
+ "-o", output_file,
91
+ "-t", input_type,
92
+ ]
93
+
94
+ # Add optional arguments if they differ from the default
95
+ if title != "Brooklyn Plot":
96
+ cmd.extend(["--title", title])
97
+ if width != 12:
98
+ cmd.extend(["--width", str(width)])
99
+ if height != 8:
100
+ cmd.extend(["--height", str(height)])
101
+ if dpi != 300:
102
+ cmd.extend(["--dpi", str(dpi)])
103
+ if output_format != "png":
104
+ cmd.extend(["--format", output_format])
105
+ if style != "seaborn-whitegrid":
106
+ cmd.extend(["--style", style])
107
+ if palette != "colorblind":
108
+ cmd.extend(["--palette", palette])
109
+ if font_scale != 1.2:
110
+ cmd.extend(["--font_scale", str(font_scale)])
111
+ if gene_fontsize != 8:
112
+ cmd.extend(["--gene_fontsize", str(gene_fontsize)])
113
+ if min_vaf != 0.0:
114
+ cmd.extend(["--min_vaf", str(min_vaf)])
115
+ if max_vaf != 1.0:
116
+ cmd.extend(["--max_vaf", str(max_vaf)])
117
+ if min_depth != 0:
118
+ cmd.extend(["--min_depth", str(min_depth)])
119
+
120
+ # Add boolean flags if True
121
+ if hide_legend:
122
+ cmd.append("--hide_legend")
123
+ if show_genes:
124
+ cmd.append("--show_genes")
125
+
126
+ # Add list-based argument
127
+ if genes_to_label:
128
+ cmd.append("--genes_to_label")
129
+ cmd.extend(genes_to_label)
130
+
131
+ command_executed = " ".join(cmd)
132
+ logger.info(f"Executing command: {command_executed}")
133
+
134
+ # --- Subprocess Execution ---
135
+ try:
136
+ result = subprocess.run(
137
+ cmd,
138
+ check=True,
139
+ capture_output=True,
140
+ text=True,
141
+ )
142
+
143
+ output_path = Path(output_file)
144
+ output_files = [str(output_path)] if output_path.exists() else []
145
+ if not output_files:
146
+ logger.warning(f"Output file '{output_file}' was not created by the tool.")
147
+
148
+ return {
149
+ "command_executed": command_executed,
150
+ "stdout": result.stdout,
151
+ "stderr": result.stderr,
152
+ "output_files": output_files,
153
+ }
154
+ except FileNotFoundError:
155
+ error_message = "Error: 'brooklyn_plot' command not found. Please ensure the tool is installed and in the system's PATH."
156
+ logger.error(error_message)
157
+ # Re-raising as a more specific error for the MCP framework
158
+ raise RuntimeError(error_message) from None
159
+ except subprocess.CalledProcessError as e:
160
+ logger.error(f"brooklyn_plot failed with exit code {e.returncode}")
161
+ # Return structured error information as per MCP guidelines
162
+ return {
163
+ "command_executed": command_executed,
164
+ "stdout": e.stdout,
165
+ "stderr": e.stderr,
166
+ "output_files": [],
167
+ }
168
+
169
+ if __name__ == "__main__":
170
+ mcp.run(transport="stdio")
Biomni/mcp_generated/mcp_brooklyn_plot/app/brooklyn_plot_shim_server.py ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ from __future__ import annotations
3
+
4
+ import ast
5
+ from pathlib import Path
6
+
7
+ from mcp.server.fastmcp import FastMCP
8
+
9
+
10
+ SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_help_txt/mcp_brooklyn_plot/app/brooklyn_plot_server.py')
11
+ LOCAL_SERVER = Path(__file__).with_name(SOURCE_SERVER.name)
12
+ SERVER_NAME = 'biosci_brooklyn_plot'
13
+
14
+
15
+ class _ShimMCP:
16
+ @staticmethod
17
+ def tool(*args, **kwargs):
18
+ if args and callable(args[0]) and len(args) == 1 and not kwargs:
19
+ return args[0]
20
+ def _decorator(fn):
21
+ return fn
22
+ return _decorator
23
+
24
+
25
+ def _resolve_source_server():
26
+ if LOCAL_SERVER.exists() and LOCAL_SERVER.name != Path(__file__).name:
27
+ return LOCAL_SERVER
28
+ return SOURCE_SERVER
29
+
30
+
31
+ def _load_functions():
32
+ source_server = _resolve_source_server()
33
+ code = source_server.read_text(encoding="utf-8")
34
+ tree = ast.parse(code, filename=str(source_server))
35
+ function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")]
36
+ namespace = {
37
+ "__name__": "__mcp_source__",
38
+ "mcp": _ShimMCP(),
39
+ }
40
+ exec(compile(code, str(source_server), "exec"), namespace, namespace)
41
+ loaded = []
42
+ for name in function_names:
43
+ fn = namespace.get(name)
44
+ if callable(fn):
45
+ loaded.append(fn)
46
+ return loaded
47
+
48
+
49
+ mcp = FastMCP(SERVER_NAME)
50
+ for _fn in _load_functions():
51
+ mcp.tool()(_fn)
52
+
53
+
54
+ if __name__ == "__main__":
55
+ mcp.run(transport="stdio")
Biomni/mcp_generated/mcp_brooklyn_plot/docker-compose.yml ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: '3.8'
2
+
3
+ services:
4
+ mcp-brooklyn_plot:
5
+ build: .
6
+ image: mcp-brooklyn_plot:latest
7
+ container_name: mcp-brooklyn_plot
8
+ ports:
9
+ - "8000:8000"
10
+ environment:
11
+ - MCP_SERVER_NAME=brooklyn_plot
12
+ volumes:
13
+ - ./workspace:/app/workspace
14
+ - ./output:/app/output
15
+ restart: unless-stopped
16
+ healthcheck:
17
+ test: ["CMD", "python", "-c", "import sys; sys.exit(0)"]
18
+ interval: 30s
19
+ timeout: 10s
20
+ retries: 3
21
+ start_period: 5s
22
+
Biomni/mcp_generated/mcp_brooklyn_plot/environment.yaml ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ name: mcp-tool
3
+ channels:
4
+ - bioconda
5
+ - conda-forge
6
+ - defaults
7
+ dependencies:
8
+ - brooklyn_plot
9
+ - python=3.10
10
+
Biomni/mcp_generated/mcp_brooklyn_plot/requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ fastmcp
2
+ mcp
Biomni/mcp_generated/mcp_bx-python/Dockerfile ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ FROM python:3.10-slim
3
+
4
+ # Install system dependencies
5
+ RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/*
6
+
7
+ # Install Miniconda
8
+ 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
9
+
10
+ # Add conda to PATH
11
+ ENV PATH="/opt/conda/bin:$PATH"
12
+
13
+ # Install bx-python via conda (e.g., from bioconda)
14
+ RUN conda install -c bioconda bx-python -y && conda clean -a
15
+
16
+ # Install Python dependencies
17
+ RUN pip install uv
18
+ RUN uv pip install --system fastmcp
19
+
20
+ # Create app directory
21
+ WORKDIR /app
22
+
23
+ # Copy your MCP server
24
+ COPY app/bx-python_server.py /app/
25
+
26
+ # Create workspace and output directories
27
+ RUN mkdir -p /app/workspace /app/output
28
+
29
+ # Make sure the server script is executable
30
+ RUN chmod +x /app/bx-python_server.py
31
+
32
+ # Expose port for MCP over HTTP (optional)
33
+ EXPOSE 8000
34
+
35
+ # Health check
36
+ HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)"
37
+
38
+ # Default command runs the MCP server via stdio
39
+ CMD ["python", "/app/bx-python_server.py"]
40
+
Biomni/mcp_generated/mcp_bx-python/app/bx-python_server.py ADDED
@@ -0,0 +1,361 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import subprocess
2
+ import tempfile
3
+ from pathlib import Path
4
+ from typing import List, Optional
5
+
6
+ # Note: The bx-python package is a suite of individual command-line scripts.
7
+ # Each script is wrapped as a separate MCP tool function. The following is a
8
+ # representative selection of these tools.
9
+
10
+ from mcp.server.fastmcp import FastMCP
11
+
12
+ SERVER_NAME = 'local_bx_python'
13
+ mcp = FastMCP(SERVER_NAME)
14
+
15
+ @mcp.tool()
16
+ def bed_intersect(
17
+ bed1: Path,
18
+ bed2: Path,
19
+ output_file: Optional[Path] = None,
20
+ find_intersections: bool = False,
21
+ find_non_intersections: bool = False,
22
+ count_intersections: bool = False,
23
+ min_overlap_cols: int = 1,
24
+ preserve_intervals: bool = True,
25
+ ) -> dict:
26
+ """
27
+ Finds intersecting regions between two BED files.
28
+
29
+ This tool corresponds to the `bed_intersect.py` script.
30
+ It can report the intersections, non-intersections, or just the count.
31
+ """
32
+ # Input validation
33
+ if not bed1.is_file():
34
+ raise FileNotFoundError(f"Input BED file not found: {bed1}")
35
+ if not bed2.is_file():
36
+ raise FileNotFoundError(f"Second input BED file not found: {bed2}")
37
+ if find_intersections and find_non_intersections:
38
+ raise ValueError("Cannot specify both --find-intersections (-i) and --find-non-intersections (-I).")
39
+ if min_overlap_cols < 1:
40
+ raise ValueError("--min-overlap-cols must be a positive integer.")
41
+
42
+ cmd = ["bed_intersect", str(bed1), str(bed2)]
43
+
44
+ if find_intersections:
45
+ cmd.append("-i")
46
+ if find_non_intersections:
47
+ cmd.append("-I")
48
+ if count_intersections:
49
+ cmd.append("-c")
50
+ if min_overlap_cols != 1:
51
+ cmd.extend(["-m", str(min_overlap_cols)])
52
+ if not preserve_intervals:
53
+ cmd.append("-p") # The script's -p flag means "don't chop up intervals", which is counter-intuitive. We reverse it for clarity.
54
+
55
+ command_executed = " ".join(cmd)
56
+ output_files = []
57
+ stdout_capture = ""
58
+ stderr_capture = ""
59
+
60
+ try:
61
+ if output_file:
62
+ output_files.append(str(output_file))
63
+ with open(output_file, "w") as f_out:
64
+ result = subprocess.run(
65
+ cmd,
66
+ check=True,
67
+ text=True,
68
+ stdout=f_out,
69
+ stderr=subprocess.PIPE
70
+ )
71
+ stderr_capture = result.stderr
72
+ else:
73
+ result = subprocess.run(
74
+ cmd,
75
+ check=True,
76
+ text=True,
77
+ capture_output=True
78
+ )
79
+ stdout_capture = result.stdout
80
+ stderr_capture = result.stderr
81
+
82
+ except FileNotFoundError:
83
+ raise RuntimeError("bed_intersect command not found. Is bx-python installed and in the system's PATH?")
84
+ except subprocess.CalledProcessError as e:
85
+ return {
86
+ "command_executed": command_executed,
87
+ "stdout": e.stdout,
88
+ "stderr": e.stderr,
89
+ "return_code": e.returncode,
90
+ "output_files": []
91
+ }
92
+
93
+ return {
94
+ "command_executed": command_executed,
95
+ "stdout": stdout_capture,
96
+ "stderr": stderr_capture,
97
+ "output_files": output_files
98
+ }
99
+
100
+ @mcp.tool()
101
+ def maf_filter(
102
+ maf_file: Path,
103
+ expression: str,
104
+ output_file: Optional[Path] = None,
105
+ species: Optional[str] = None,
106
+ min_score: Optional[float] = None,
107
+ actions: Optional[str] = None,
108
+ score_column: Optional[str] = None,
109
+ score_op: Optional[str] = None,
110
+ ) -> dict:
111
+ """
112
+ Filters a MAF file based on a given expression.
113
+
114
+ This tool corresponds to the `maf_filter.py` script. It allows for complex
115
+ filtering of Multiple Alignment Format (MAF) files.
116
+ """
117
+ if not maf_file.is_file():
118
+ raise FileNotFoundError(f"Input MAF file not found: {maf_file}")
119
+ if score_op and score_op not in ["avg", "min", "max", "sum"]:
120
+ raise ValueError(f"Invalid score_op: {score_op}. Must be one of 'avg', 'min', 'max', 'sum'.")
121
+
122
+ cmd = ["maf_filter"]
123
+ cmd.extend(["-e", expression])
124
+
125
+ if species:
126
+ cmd.extend(["-s", species])
127
+ if min_score is not None:
128
+ cmd.extend(["-m", str(min_score)])
129
+ if actions:
130
+ cmd.extend(["-a", actions])
131
+ if score_column:
132
+ cmd.extend(["-S", score_column])
133
+ if score_op:
134
+ cmd.extend(["-O", score_op])
135
+
136
+ cmd.append(str(maf_file))
137
+ command_executed = " ".join(cmd)
138
+ output_files = []
139
+ stdout_capture = ""
140
+ stderr_capture = ""
141
+
142
+ try:
143
+ if output_file:
144
+ output_files.append(str(output_file))
145
+ with open(output_file, "w") as f_out:
146
+ result = subprocess.run(
147
+ cmd,
148
+ check=True,
149
+ text=True,
150
+ stdout=f_out,
151
+ stderr=subprocess.PIPE
152
+ )
153
+ stderr_capture = result.stderr
154
+ else:
155
+ result = subprocess.run(
156
+ cmd,
157
+ check=True,
158
+ text=True,
159
+ capture_output=True
160
+ )
161
+ stdout_capture = result.stdout
162
+ stderr_capture = result.stderr
163
+
164
+ except FileNotFoundError:
165
+ raise RuntimeError("maf_filter command not found. Is bx-python installed and in the system's PATH?")
166
+ except subprocess.CalledProcessError as e:
167
+ return {
168
+ "command_executed": command_executed,
169
+ "stdout": e.stdout,
170
+ "stderr": e.stderr,
171
+ "return_code": e.returncode,
172
+ "output_files": []
173
+ }
174
+
175
+ return {
176
+ "command_executed": command_executed,
177
+ "stdout": stdout_capture,
178
+ "stderr": stderr_capture,
179
+ "output_files": output_files
180
+ }
181
+
182
+ @mcp.tool()
183
+ def fasta_formatter(
184
+ fasta_file: Path,
185
+ output_file: Optional[Path] = None,
186
+ line_length: int = 80,
187
+ ) -> dict:
188
+ """
189
+ Reformats a FASTA file to a specified line length.
190
+
191
+ This tool corresponds to the `fasta_formatter.py` script.
192
+ """
193
+ if not fasta_file.is_file():
194
+ raise FileNotFoundError(f"Input FASTA file not found: {fasta_file}")
195
+ if line_length <= 0:
196
+ raise ValueError("line_length must be a positive integer.")
197
+
198
+ cmd = ["fasta_formatter", str(fasta_file)]
199
+ if line_length != 80: # Assuming 80 is the default, though the script might not have one.
200
+ cmd.extend(["-c", str(line_length)])
201
+
202
+ command_executed = " ".join(cmd)
203
+ output_files = []
204
+ stdout_capture = ""
205
+ stderr_capture = ""
206
+
207
+ try:
208
+ if output_file:
209
+ output_files.append(str(output_file))
210
+ with open(output_file, "w") as f_out:
211
+ result = subprocess.run(
212
+ cmd,
213
+ check=True,
214
+ text=True,
215
+ stdout=f_out,
216
+ stderr=subprocess.PIPE
217
+ )
218
+ stderr_capture = result.stderr
219
+ else:
220
+ result = subprocess.run(
221
+ cmd,
222
+ check=True,
223
+ text=True,
224
+ capture_output=True
225
+ )
226
+ stdout_capture = result.stdout
227
+ stderr_capture = result.stderr
228
+
229
+ except FileNotFoundError:
230
+ raise RuntimeError("fasta_formatter command not found. Is bx-python installed and in the system's PATH?")
231
+ except subprocess.CalledProcessError as e:
232
+ return {
233
+ "command_executed": command_executed,
234
+ "stdout": e.stdout,
235
+ "stderr": e.stderr,
236
+ "return_code": e.returncode,
237
+ "output_files": []
238
+ }
239
+
240
+ return {
241
+ "command_executed": command_executed,
242
+ "stdout": stdout_capture,
243
+ "stderr": stderr_capture,
244
+ "output_files": output_files
245
+ }
246
+
247
+ @mcp.tool()
248
+ def wig_to_bigwig(
249
+ wig_file: Path,
250
+ chrom_sizes: Path,
251
+ bigwig_output: Path,
252
+ clip_val: Optional[int] = None,
253
+ chunk_size: int = 1024,
254
+ ) -> dict:
255
+ """
256
+ Converts a Wiggle (WIG) format file to a BigWig file.
257
+
258
+ This tool corresponds to the `wig_to_bigwig.py` script.
259
+ """
260
+ if not wig_file.is_file():
261
+ raise FileNotFoundError(f"Input Wiggle file not found: {wig_file}")
262
+ if not chrom_sizes.is_file():
263
+ raise FileNotFoundError(f"Chromosome sizes file not found: {chrom_sizes}")
264
+ if chunk_size <= 0:
265
+ raise ValueError("chunk_size must be a positive integer.")
266
+
267
+ cmd = ["wig_to_bigwig", str(wig_file), str(chrom_sizes), str(bigwig_output)]
268
+
269
+ if clip_val is not None:
270
+ cmd.extend(["-clip", str(clip_val)])
271
+ if chunk_size != 1024:
272
+ cmd.extend(["-chunk", str(chunk_size)])
273
+
274
+ command_executed = " ".join(cmd)
275
+
276
+ try:
277
+ result = subprocess.run(
278
+ cmd,
279
+ check=True,
280
+ text=True,
281
+ capture_output=True
282
+ )
283
+ except FileNotFoundError:
284
+ raise RuntimeError("wig_to_bigwig command not found. Is bx-python installed and in the system's PATH?")
285
+ except subprocess.CalledProcessError as e:
286
+ return {
287
+ "command_executed": command_executed,
288
+ "stdout": e.stdout,
289
+ "stderr": e.stderr,
290
+ "return_code": e.returncode,
291
+ "output_files": []
292
+ }
293
+
294
+ return {
295
+ "command_executed": command_executed,
296
+ "stdout": result.stdout,
297
+ "stderr": result.stderr,
298
+ "output_files": [str(bigwig_output)]
299
+ }
300
+
301
+ @mcp.tool()
302
+ def get_flanking_sequences(
303
+ bed_file: Path,
304
+ genome_file: Path,
305
+ output_fasta: Path,
306
+ length: int,
307
+ location: str = "g",
308
+ ) -> dict:
309
+ """
310
+ Extracts flanking sequences for regions in a BED file from a genome FASTA file.
311
+
312
+ This tool corresponds to the `get_flanking_sequences.py` script.
313
+ """
314
+ if not bed_file.is_file():
315
+ raise FileNotFoundError(f"Input BED file not found: {bed_file}")
316
+ if not genome_file.is_file():
317
+ raise FileNotFoundError(f"Genome FASTA file not found: {genome_file}")
318
+ if length <= 0:
319
+ raise ValueError("length must be a positive integer.")
320
+ valid_locations = ["b", "e", "g", "G"]
321
+ if location not in valid_locations:
322
+ raise ValueError(f"Invalid location '{location}'. Must be one of {valid_locations}.")
323
+
324
+ cmd = [
325
+ "get_flanking_sequences",
326
+ str(bed_file),
327
+ "-g", str(genome_file),
328
+ "-o", str(output_fasta),
329
+ "-l", str(length),
330
+ "-L", location
331
+ ]
332
+
333
+ command_executed = " ".join(cmd)
334
+
335
+ try:
336
+ result = subprocess.run(
337
+ cmd,
338
+ check=True,
339
+ text=True,
340
+ capture_output=True
341
+ )
342
+ except FileNotFoundError:
343
+ raise RuntimeError("get_flanking_sequences command not found. Is bx-python installed and in the system's PATH?")
344
+ except subprocess.CalledProcessError as e:
345
+ return {
346
+ "command_executed": command_executed,
347
+ "stdout": e.stdout,
348
+ "stderr": e.stderr,
349
+ "return_code": e.returncode,
350
+ "output_files": []
351
+ }
352
+
353
+ return {
354
+ "command_executed": command_executed,
355
+ "stdout": result.stdout,
356
+ "stderr": result.stderr,
357
+ "output_files": [str(output_fasta)]
358
+ }
359
+
360
+ if __name__ == "__main__":
361
+ mcp.run(transport="stdio")
Biomni/mcp_generated/mcp_bx-python/app/bx-python_shim_server.py ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ from __future__ import annotations
3
+
4
+ import ast
5
+ from pathlib import Path
6
+
7
+ from mcp.server.fastmcp import FastMCP
8
+
9
+
10
+ SOURCE_SERVER = Path('/225040511/project/BioScientist/agent_system/toolbase/mcp_batch_from_manual_txt/mcp_bx-python/app/bx-python_server.py')
11
+ LOCAL_SERVER = Path(__file__).with_name(SOURCE_SERVER.name)
12
+ SERVER_NAME = 'biosci_bx_python'
13
+
14
+
15
+ class _ShimMCP:
16
+ @staticmethod
17
+ def tool(*args, **kwargs):
18
+ if args and callable(args[0]) and len(args) == 1 and not kwargs:
19
+ return args[0]
20
+ def _decorator(fn):
21
+ return fn
22
+ return _decorator
23
+
24
+
25
+ def _resolve_source_server():
26
+ if LOCAL_SERVER.exists() and LOCAL_SERVER.name != Path(__file__).name:
27
+ return LOCAL_SERVER
28
+ return SOURCE_SERVER
29
+
30
+
31
+ def _load_functions():
32
+ source_server = _resolve_source_server()
33
+ code = source_server.read_text(encoding="utf-8")
34
+ tree = ast.parse(code, filename=str(source_server))
35
+ function_names = [n.name for n in tree.body if isinstance(n, ast.FunctionDef) and not n.name.startswith("_")]
36
+ namespace = {
37
+ "__name__": "__mcp_source__",
38
+ "mcp": _ShimMCP(),
39
+ }
40
+ exec(compile(code, str(source_server), "exec"), namespace, namespace)
41
+ loaded = []
42
+ for name in function_names:
43
+ fn = namespace.get(name)
44
+ if callable(fn):
45
+ loaded.append(fn)
46
+ return loaded
47
+
48
+
49
+ mcp = FastMCP(SERVER_NAME)
50
+ for _fn in _load_functions():
51
+ mcp.tool()(_fn)
52
+
53
+
54
+ if __name__ == "__main__":
55
+ mcp.run(transport="stdio")
Biomni/mcp_generated/mcp_bx-python/app/requirements.txt ADDED
@@ -0,0 +1 @@
 
 
1
+
Biomni/mcp_generated/mcp_bx-python/docker-compose.yml ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: '3.8'
2
+
3
+ services:
4
+ mcp-bx-python:
5
+ build: .
6
+ image: mcp-bx-python:latest
7
+ container_name: mcp-bx-python
8
+ ports:
9
+ - "8000:8000"
10
+ environment:
11
+ - MCP_SERVER_NAME=bx-python
12
+ volumes:
13
+ - ./workspace:/app/workspace
14
+ - ./output:/app/output
15
+ restart: unless-stopped
16
+ healthcheck:
17
+ test: ["CMD", "python", "-c", "import sys; sys.exit(0)"]
18
+ interval: 30s
19
+ timeout: 10s
20
+ retries: 3
21
+ start_period: 5s
22
+
Biomni/mcp_generated/mcp_bx-python/environment.yaml ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ name: mcp-tool
3
+ channels:
4
+ - bioconda
5
+ - conda-forge
6
+ - defaults
7
+ dependencies:
8
+ - bx-python
9
+ - python=3.10
10
+
Biomni/mcp_generated/mcp_bx-python/requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ fastmcp
2
+ mcp
Biomni/mcp_generated/mcp_cd-hit/Dockerfile ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ FROM python:3.10-slim
3
+
4
+ # Install system dependencies
5
+ RUN apt-get update && apt-get install -y default-jre wget curl && apt-get clean && rm -rf /var/lib/apt/lists/*
6
+
7
+ # Install Miniconda
8
+ 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
9
+
10
+ # Add conda to PATH
11
+ ENV PATH="/opt/conda/bin:$PATH"
12
+
13
+ # Install cd-hit via conda (e.g., from bioconda)
14
+ RUN conda install -c bioconda cd-hit -y && conda clean -a
15
+
16
+ # Install Python dependencies
17
+ RUN pip install uv
18
+ RUN uv pip install --system fastmcp
19
+
20
+ # Create app directory
21
+ WORKDIR /app
22
+
23
+ # Copy your MCP server
24
+ COPY app/cd-hit_server.py /app/
25
+
26
+ # Create workspace and output directories
27
+ RUN mkdir -p /app/workspace /app/output
28
+
29
+ # Make sure the server script is executable
30
+ RUN chmod +x /app/cd-hit_server.py
31
+
32
+ # Expose port for MCP over HTTP (optional)
33
+ EXPOSE 8000
34
+
35
+ # Health check
36
+ HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD python -c "import sys; sys.exit(0)"
37
+
38
+ # Default command runs the MCP server via stdio
39
+ CMD ["python", "/app/cd-hit_server.py"]
40
+