czty commited on
Commit
d9bc96c
·
verified ·
1 Parent(s): dfa977b

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_abnumber/Dockerfile +40 -0
  2. Biomni/mcp_generated/mcp_abnumber/docker-compose.yml +22 -0
  3. Biomni/mcp_generated/mcp_abyss/app/abyss_server.py +211 -0
  4. Biomni/mcp_generated/mcp_abyss/requirements.txt +2 -0
  5. Biomni/mcp_generated/mcp_arvados-cwl-runner/Dockerfile +40 -0
  6. Biomni/mcp_generated/mcp_arvados-cwl-runner/app/arvados-cwl-runner_server.py +278 -0
  7. Biomni/mcp_generated/mcp_arvados-cwl-runner/app/arvados-cwl-runner_shim_server.py +55 -0
  8. Biomni/mcp_generated/mcp_arvados-cwl-runner/app/requirements.txt +1 -0
  9. Biomni/mcp_generated/mcp_arvados-cwl-runner/docker-compose.yml +22 -0
  10. Biomni/mcp_generated/mcp_arvados-cwl-runner/environment.yaml +10 -0
  11. Biomni/mcp_generated/mcp_arvados-cwl-runner/requirements.txt +2 -0
  12. Biomni/mcp_generated/mcp_auspice/Dockerfile +40 -0
  13. Biomni/mcp_generated/mcp_auspice/app/auspice_server.py +406 -0
  14. Biomni/mcp_generated/mcp_auspice/app/auspice_shim_server.py +55 -0
  15. Biomni/mcp_generated/mcp_auspice/app/requirements.txt +1 -0
  16. Biomni/mcp_generated/mcp_auspice/docker-compose.yml +22 -0
  17. Biomni/mcp_generated/mcp_auspice/environment.yaml +10 -0
  18. Biomni/mcp_generated/mcp_auspice/requirements.txt +2 -0
  19. Biomni/mcp_generated/mcp_barrnap/Dockerfile +40 -0
  20. Biomni/mcp_generated/mcp_barrnap/app/barrnap_server.py +246 -0
  21. Biomni/mcp_generated/mcp_barrnap/app/barrnap_shim_server.py +55 -0
  22. Biomni/mcp_generated/mcp_barrnap/app/requirements.txt +1 -0
  23. Biomni/mcp_generated/mcp_barrnap/docker-compose.yml +22 -0
  24. Biomni/mcp_generated/mcp_barrnap/environment.yaml +10 -0
  25. Biomni/mcp_generated/mcp_barrnap/requirements.txt +2 -0
  26. Biomni/mcp_generated/mcp_bedtools/Dockerfile +40 -0
  27. Biomni/mcp_generated/mcp_bedtools/app/__pycache__/bedtools_server.cpython-311.pyc +0 -0
  28. Biomni/mcp_generated/mcp_bedtools/app/__pycache__/bedtools_shim_server.cpython-311.pyc +0 -0
  29. Biomni/mcp_generated/mcp_bedtools/app/bedtools_server.py +708 -0
  30. Biomni/mcp_generated/mcp_bedtools/app/bedtools_shim_server.py +55 -0
  31. Biomni/mcp_generated/mcp_bedtools/docker-compose.yml +22 -0
  32. Biomni/mcp_generated/mcp_bedtools/environment.yaml +10 -0
  33. Biomni/mcp_generated/mcp_bedtools/requirements.txt +2 -0
  34. Biomni/mcp_generated/mcp_bin2cell/Dockerfile +40 -0
  35. Biomni/mcp_generated/mcp_bin2cell/app/bin2cell_server.py +286 -0
  36. Biomni/mcp_generated/mcp_bin2cell/app/bin2cell_shim_server.py +55 -0
  37. Biomni/mcp_generated/mcp_bin2cell/app/requirements.txt +1 -0
  38. Biomni/mcp_generated/mcp_bin2cell/docker-compose.yml +22 -0
  39. Biomni/mcp_generated/mcp_bin2cell/environment.yaml +10 -0
  40. Biomni/mcp_generated/mcp_bin2cell/requirements.txt +2 -0
  41. Biomni/mcp_generated/mcp_bioconductor-alabaster/Dockerfile +40 -0
  42. Biomni/mcp_generated/mcp_bioconductor-alabaster/app/bioconductor-alabaster_server.py +66 -0
  43. Biomni/mcp_generated/mcp_bioconductor-alabaster/app/bioconductor-alabaster_shim_server.py +55 -0
  44. Biomni/mcp_generated/mcp_bioconductor-alabaster/docker-compose.yml +22 -0
  45. Biomni/mcp_generated/mcp_bioconductor-alabaster/environment.yaml +10 -0
  46. Biomni/mcp_generated/mcp_bioconductor-alabaster/requirements.txt +2 -0
  47. Biomni/mcp_generated/mcp_bioconductor-apeglm/Dockerfile +40 -0
  48. Biomni/mcp_generated/mcp_bioconductor-apeglm/app/bioconductor-apeglm_server.py +133 -0
  49. Biomni/mcp_generated/mcp_bioconductor-apeglm/app/bioconductor-apeglm_shim_server.py +55 -0
  50. Biomni/mcp_generated/mcp_bioconductor-apeglm/docker-compose.yml +22 -0
Biomni/mcp_generated/mcp_abnumber/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 abnumber via conda (e.g., from bioconda)
14
+ RUN conda install -c bioconda abnumber -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/abnumber_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/abnumber_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/abnumber_server.py"]
40
+
Biomni/mcp_generated/mcp_abnumber/docker-compose.yml ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: '3.8'
2
+
3
+ services:
4
+ mcp-abnumber:
5
+ build: .
6
+ image: mcp-abnumber:latest
7
+ container_name: mcp-abnumber
8
+ ports:
9
+ - "8000:8000"
10
+ environment:
11
+ - MCP_SERVER_NAME=abnumber
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_abyss/app/abyss_server.py ADDED
@@ -0,0 +1,211 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import subprocess
2
+ from pathlib import Path
3
+ from typing import List, Optional, Dict, Any
4
+
5
+ # from mcp import tool as mcp_tool
6
+ # Note: The 'mcp' import is commented out as per the instructions.
7
+ # In a real MCP environment, you would uncomment the line above.
8
+
9
+ def mcp_tool(func):
10
+ """A placeholder decorator to mimic @mcp.tool()."""
11
+ return func
12
+
13
+ @mcp_tool
14
+ def run_perl(
15
+ programfile: Optional[Path] = None,
16
+ program_string: Optional[str] = None,
17
+ arguments: Optional[List[str]] = None,
18
+ include_dirs: Optional[List[Path]] = None,
19
+ use_modules: Optional[List[str]] = None,
20
+ no_modules: Optional[List[str]] = None,
21
+ warnings: str = "normal",
22
+ check_syntax_only: bool = False,
23
+ enable_all_features: bool = False,
24
+ ) -> Dict[str, Any]:
25
+ """
26
+ Executes a Perl script or a one-liner command with specified options.
27
+
28
+ This tool serves as a wrapper around the Perl interpreter, allowing for the execution
29
+ of scripts from files or direct command-line strings. It provides options for
30
+ managing modules, include paths, and warning levels.
31
+
32
+ Args:
33
+ programfile: Path to the Perl program file to execute.
34
+ program_string: A string containing a one-liner Perl program to execute.
35
+ arguments: A list of arguments to pass to the program file or one-liner.
36
+ include_dirs: A list of directories to add to Perl's @INC path for finding modules.
37
+ use_modules: A list of modules to 'use' before executing the program.
38
+ no_modules: A list of modules to 'no' (disable) before executing the program.
39
+ warnings: Set the warning level. Can be 'normal' (-w), 'all' (-W), or 'none' (-X).
40
+ check_syntax_only: If True, checks the syntax of the program without executing it (-c).
41
+ enable_all_features: If True and using program_string, enables all optional features (-E).
42
+ """
43
+ # 1. Input Validation
44
+ if not (programfile or program_string):
45
+ raise ValueError("Either 'programfile' or 'program_string' must be provided.")
46
+ if programfile and program_string:
47
+ raise ValueError("Cannot provide both 'programfile' and 'program_string'.")
48
+
49
+ if programfile and not programfile.is_file():
50
+ raise FileNotFoundError(f"Program file not found: {programfile}")
51
+
52
+ if include_dirs:
53
+ for d in include_dirs:
54
+ if not d.is_dir():
55
+ raise NotADirectoryError(f"Include directory not found: {d}")
56
+
57
+ allowed_warnings = ["normal", "all", "none"]
58
+ if warnings not in allowed_warnings:
59
+ raise ValueError(f"Invalid 'warnings' value '{warnings}'. Must be one of {allowed_warnings}.")
60
+
61
+ # 2. Command Construction
62
+ cmd = ["perl"]
63
+
64
+ # Handle warnings
65
+ if warnings == "normal":
66
+ cmd.append("-w")
67
+ elif warnings == "all":
68
+ cmd.append("-W")
69
+ elif warnings == "none":
70
+ cmd.append("-X")
71
+
72
+ # Handle syntax check
73
+ if check_syntax_only:
74
+ cmd.append("-c")
75
+
76
+ # Handle include directories
77
+ if include_dirs:
78
+ for d in include_dirs:
79
+ cmd.extend(["-I", str(d)])
80
+
81
+ # Handle modules
82
+ if use_modules:
83
+ for module in use_modules:
84
+ cmd.extend(["-M", module])
85
+ if no_modules:
86
+ for module in no_modules:
87
+ cmd.extend(["-m", module])
88
+
89
+ # Handle program source (file or string)
90
+ if program_string:
91
+ if enable_all_features:
92
+ cmd.append("-E")
93
+ else:
94
+ cmd.append("-e")
95
+ cmd.append(program_string)
96
+ elif programfile:
97
+ cmd.append(str(programfile))
98
+
99
+ # Handle arguments to the script
100
+ if arguments:
101
+ cmd.extend(arguments)
102
+
103
+ command_executed = " ".join(map(str, cmd))
104
+
105
+ # 3. Subprocess Execution
106
+ try:
107
+ result = subprocess.run(
108
+ cmd,
109
+ capture_output=True,
110
+ text=True,
111
+ check=False, # Check manually to provide better error context
112
+ )
113
+ if result.returncode != 0:
114
+ raise subprocess.CalledProcessError(
115
+ result.returncode, cmd, output=result.stdout, stderr=result.stderr
116
+ )
117
+ except FileNotFoundError:
118
+ raise RuntimeError("Perl executable not found. Please ensure it is in your system's PATH.")
119
+ except subprocess.CalledProcessError as e:
120
+ return {
121
+ "error": "Perl execution failed.",
122
+ "return_code": e.returncode,
123
+ "stdout": e.stdout,
124
+ "stderr": e.stderr,
125
+ "command_executed": command_executed,
126
+ }
127
+
128
+ # 4. Structured Result Return
129
+ return {
130
+ "command_executed": command_executed,
131
+ "stdout": result.stdout,
132
+ "stderr": result.stderr,
133
+ "output_files": [] # The wrapper itself doesn't create files
134
+ }
135
+
136
+ @mcp_tool
137
+ def perl_version() -> Dict[str, Any]:
138
+ """
139
+ Retrieves the version, patchlevel, and license of the Perl interpreter.
140
+
141
+ This corresponds to the `perl -v` command.
142
+ """
143
+ cmd = ["perl", "-v"]
144
+ command_executed = " ".join(cmd)
145
+
146
+ try:
147
+ result = subprocess.run(
148
+ cmd,
149
+ capture_output=True,
150
+ text=True,
151
+ check=True,
152
+ )
153
+ except FileNotFoundError:
154
+ raise RuntimeError("Perl executable not found. Please ensure it is in your system's PATH.")
155
+ except subprocess.CalledProcessError as e:
156
+ return {
157
+ "error": "Failed to get Perl version.",
158
+ "return_code": e.returncode,
159
+ "stdout": e.stdout,
160
+ "stderr": e.stderr,
161
+ "command_executed": command_executed,
162
+ }
163
+
164
+ return {
165
+ "command_executed": command_executed,
166
+ "stdout": result.stdout,
167
+ "stderr": result.stderr,
168
+ }
169
+
170
+ @mcp_tool
171
+ def perl_config(variable: Optional[str] = None) -> Dict[str, Any]:
172
+ """
173
+ Prints the configuration summary for the Perl installation.
174
+
175
+ This corresponds to the `perl -V` command. If a variable name is provided,
176
+ it prints the value of that specific configuration variable.
177
+
178
+ Args:
179
+ variable: A specific Config.pm variable to query.
180
+ """
181
+ cmd = ["perl"]
182
+ if variable:
183
+ cmd.append(f"-V:{variable}")
184
+ else:
185
+ cmd.append("-V")
186
+
187
+ command_executed = " ".join(cmd)
188
+
189
+ try:
190
+ result = subprocess.run(
191
+ cmd,
192
+ capture_output=True,
193
+ text=True,
194
+ check=True,
195
+ )
196
+ except FileNotFoundError:
197
+ raise RuntimeError("Perl executable not found. Please ensure it is in your system's PATH.")
198
+ except subprocess.CalledProcessError as e:
199
+ return {
200
+ "error": "Failed to get Perl configuration.",
201
+ "return_code": e.returncode,
202
+ "stdout": e.stdout,
203
+ "stderr": e.stderr,
204
+ "command_executed": command_executed,
205
+ }
206
+
207
+ return {
208
+ "command_executed": command_executed,
209
+ "stdout": result.stdout,
210
+ "stderr": result.stderr,
211
+ }
Biomni/mcp_generated/mcp_abyss/requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ fastmcp
2
+ mcp
Biomni/mcp_generated/mcp_arvados-cwl-runner/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 arvados-cwl-runner via conda (e.g., from bioconda)
14
+ RUN conda install -c bioconda arvados-cwl-runner -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/arvados-cwl-runner_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/arvados-cwl-runner_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/arvados-cwl-runner_server.py"]
40
+
Biomni/mcp_generated/mcp_arvados-cwl-runner/app/arvados-cwl-runner_server.py ADDED
@@ -0,0 +1,278 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import subprocess
2
+ import os
3
+ from pathlib import Path
4
+ from typing import Optional, List, Union
5
+
6
+ from mcp.server.fastmcp import FastMCP
7
+
8
+ SERVER_NAME = 'local_arvados_cwl_runner'
9
+ mcp = FastMCP(SERVER_NAME)
10
+
11
+ @mcp.tool()
12
+ def arvados_cwl_runner(
13
+ workflow: str,
14
+ job_order: Optional[str] = None,
15
+ project_uuid: Optional[str] = None,
16
+ name: Optional[str] = None,
17
+ output_name: Optional[str] = None,
18
+ local: bool = False,
19
+ api: str = "containers",
20
+ eval_timeout: float = 20.0,
21
+ log_level: str = "INFO",
22
+ enable_reuse: bool = True,
23
+ submit: bool = True,
24
+ wait: bool = True,
25
+ priority: int = 1,
26
+ cluster_id: Optional[str] = None,
27
+ storage_classes: str = "default",
28
+ tmpdir_prefix: Optional[str] = None,
29
+ debug: bool = False,
30
+ ):
31
+ """
32
+ Run a CWL workflow on Arvados or locally.
33
+
34
+ Args:
35
+ workflow: Path to the CWL workflow file (.cwl).
36
+ job_order: Path to the input parameters file (YAML or JSON).
37
+ project_uuid: Arvados project UUID where the workflow should run.
38
+ name: Name for the pipeline instance or container request.
39
+ output_name: Name for the output collection.
40
+ local: Run the workflow locally instead of on the Arvados cluster.
41
+ api: Arvados API to use (containers or jobs). Default is containers.
42
+ eval_timeout: Time to wait for CWL expression evaluation (seconds).
43
+ log_level: Logging level (DEBUG, INFO, WARNING, ERROR).
44
+ enable_reuse: Enable job/container reuse.
45
+ submit: Submit the workflow to Arvados (True) or run it in the foreground (False).
46
+ wait: Wait for the workflow to complete before exiting.
47
+ priority: Workflow priority (1-1000).
48
+ cluster_id: Specific Arvados cluster ID to submit to.
49
+ storage_classes: Comma-separated list of storage classes for outputs.
50
+ tmpdir_prefix: Path prefix for temporary directories.
51
+ debug: Enable debug logging and keep temporary files.
52
+ """
53
+
54
+ # Input validation
55
+ workflow_path = Path(workflow)
56
+ if not workflow_path.exists():
57
+ return {"error": f"Workflow file not found: {workflow}"}
58
+
59
+ cmd = ["arvados-cwl-runner"]
60
+
61
+ # Boolean flags
62
+ if local:
63
+ cmd.append("--local")
64
+ if not enable_reuse:
65
+ cmd.append("--disable-reuse")
66
+ if not submit:
67
+ cmd.append("--no-submit")
68
+ if not wait:
69
+ cmd.append("--no-wait")
70
+ if debug:
71
+ cmd.append("--debug")
72
+
73
+ # String/Value parameters
74
+ cmd.extend(["--api", api])
75
+ cmd.extend(["--eval-timeout", str(eval_timeout)])
76
+ cmd.extend(["--log-level", log_level])
77
+ cmd.extend(["--priority", str(priority)])
78
+ cmd.extend(["--collection-storage-classes", storage_classes])
79
+
80
+ if project_uuid:
81
+ cmd.extend(["--project-uuid", project_uuid])
82
+ if name:
83
+ cmd.extend(["--name", name])
84
+ if output_name:
85
+ cmd.extend(["--output-name", output_name])
86
+ if cluster_id:
87
+ cmd.extend(["--cluster-id", cluster_id])
88
+ if tmpdir_prefix:
89
+ cmd.extend(["--tmpdir-prefix", tmpdir_prefix])
90
+
91
+ # Positional arguments
92
+ cmd.append(str(workflow_path))
93
+
94
+ if job_order:
95
+ job_order_path = Path(job_order)
96
+ if not job_order_path.exists():
97
+ return {"error": f"Job order file not found: {job_order}"}
98
+ cmd.append(str(job_order_path))
99
+
100
+ try:
101
+ result = subprocess.run(cmd, capture_output=True, text=True, check=True)
102
+ return {
103
+ "command_executed": " ".join(cmd),
104
+ "stdout": result.stdout,
105
+ "stderr": result.stderr,
106
+ "status": "success"
107
+ }
108
+ except subprocess.CalledProcessError as e:
109
+ return {
110
+ "command_executed": " ".join(cmd),
111
+ "stdout": e.stdout,
112
+ "stderr": e.stderr,
113
+ "error": str(e),
114
+ "status": "failed"
115
+ }
116
+
117
+ @mcp.tool()
118
+ def arvados_cwl_validate(
119
+ workflow: str,
120
+ ):
121
+ """
122
+ Validate a CWL workflow file for syntax and Arvados compatibility.
123
+
124
+ Args:
125
+ workflow: Path to the CWL workflow file.
126
+ """
127
+ workflow_path = Path(workflow)
128
+ if not workflow_path.exists():
129
+ return {"error": f"Workflow file not found: {workflow}"}
130
+
131
+ cmd = ["arvados-cwl-runner", "--validate", str(workflow_path)]
132
+
133
+ try:
134
+ result = subprocess.run(cmd, capture_output=True, text=True, check=True)
135
+ return {
136
+ "command_executed": " ".join(cmd),
137
+ "stdout": result.stdout,
138
+ "stderr": result.stderr,
139
+ "status": "valid"
140
+ }
141
+ except subprocess.CalledProcessError as e:
142
+ return {
143
+ "command_executed": " ".join(cmd),
144
+ "stdout": e.stdout,
145
+ "stderr": e.stderr,
146
+ "error": "Validation failed",
147
+ "status": "invalid"
148
+ }
149
+
150
+ @mcp.tool()
151
+ def arvados_cwl_create_workflow(
152
+ workflow: str,
153
+ project_uuid: Optional[str] = None,
154
+ name: Optional[str] = None,
155
+ description: Optional[str] = None,
156
+ ):
157
+ """
158
+ Register a CWL workflow in Arvados as a reusable Workflow object.
159
+
160
+ Args:
161
+ workflow: Path to the CWL workflow file.
162
+ project_uuid: Arvados project UUID where the workflow should be stored.
163
+ name: Name for the workflow object in Arvados.
164
+ description: Description for the workflow.
165
+ """
166
+ workflow_path = Path(workflow)
167
+ if not workflow_path.exists():
168
+ return {"error": f"Workflow file not found: {workflow}"}
169
+
170
+ cmd = ["arvados-cwl-runner", "--create-workflow"]
171
+
172
+ if project_uuid:
173
+ cmd.extend(["--project-uuid", project_uuid])
174
+ if name:
175
+ cmd.extend(["--name", name])
176
+ if description:
177
+ cmd.extend(["--description", description])
178
+
179
+ cmd.append(str(workflow_path))
180
+
181
+ try:
182
+ result = subprocess.run(cmd, capture_output=True, text=True, check=True)
183
+ return {
184
+ "command_executed": " ".join(cmd),
185
+ "stdout": result.stdout,
186
+ "stderr": result.stderr,
187
+ "status": "success"
188
+ }
189
+ except subprocess.CalledProcessError as e:
190
+ return {
191
+ "command_executed": " ".join(cmd),
192
+ "stdout": e.stdout,
193
+ "stderr": e.stderr,
194
+ "error": str(e),
195
+ "status": "failed"
196
+ }
197
+
198
+ @mcp.tool()
199
+ def arvados_cwl_update_workflow(
200
+ workflow_uuid: str,
201
+ workflow: str,
202
+ name: Optional[str] = None,
203
+ description: Optional[str] = None,
204
+ ):
205
+ """
206
+ Update an existing Arvados Workflow object with a new CWL definition.
207
+
208
+ Args:
209
+ workflow_uuid: The UUID of the Arvados Workflow object to update.
210
+ workflow: Path to the new CWL workflow file.
211
+ name: New name for the workflow object.
212
+ description: New description for the workflow.
213
+ """
214
+ workflow_path = Path(workflow)
215
+ if not workflow_path.exists():
216
+ return {"error": f"Workflow file not found: {workflow}"}
217
+
218
+ cmd = ["arvados-cwl-runner", "--update-workflow", workflow_uuid]
219
+
220
+ if name:
221
+ cmd.extend(["--name", name])
222
+ if description:
223
+ cmd.extend(["--description", description])
224
+
225
+ cmd.append(str(workflow_path))
226
+
227
+ try:
228
+ result = subprocess.run(cmd, capture_output=True, text=True, check=True)
229
+ return {
230
+ "command_executed": " ".join(cmd),
231
+ "stdout": result.stdout,
232
+ "stderr": result.stderr,
233
+ "status": "success"
234
+ }
235
+ except subprocess.CalledProcessError as e:
236
+ return {
237
+ "command_executed": " ".join(cmd),
238
+ "stdout": e.stdout,
239
+ "stderr": e.stderr,
240
+ "error": str(e),
241
+ "status": "failed"
242
+ }
243
+
244
+ @mcp.tool()
245
+ def arvados_cwl_create_template(
246
+ workflow: str,
247
+ ):
248
+ """
249
+ Create an Arvados Pipeline Template from a CWL workflow (legacy API).
250
+
251
+ Args:
252
+ workflow: Path to the CWL workflow file.
253
+ """
254
+ workflow_path = Path(workflow)
255
+ if not workflow_path.exists():
256
+ return {"error": f"Workflow file not found: {workflow}"}
257
+
258
+ cmd = ["arvados-cwl-runner", "--create-template", str(workflow_path)]
259
+
260
+ try:
261
+ result = subprocess.run(cmd, capture_output=True, text=True, check=True)
262
+ return {
263
+ "command_executed": " ".join(cmd),
264
+ "stdout": result.stdout,
265
+ "stderr": result.stderr,
266
+ "status": "success"
267
+ }
268
+ except subprocess.CalledProcessError as e:
269
+ return {
270
+ "command_executed": " ".join(cmd),
271
+ "stdout": e.stdout,
272
+ "stderr": e.stderr,
273
+ "error": str(e),
274
+ "status": "failed"
275
+ }
276
+
277
+ if __name__ == "__main__":
278
+ mcp.run(transport="stdio")
Biomni/mcp_generated/mcp_arvados-cwl-runner/app/arvados-cwl-runner_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_arvados-cwl-runner/app/arvados-cwl-runner_server.py')
11
+ LOCAL_SERVER = Path(__file__).with_name(SOURCE_SERVER.name)
12
+ SERVER_NAME = 'biosci_arvados_cwl_runner'
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_arvados-cwl-runner/app/requirements.txt ADDED
@@ -0,0 +1 @@
 
 
1
+
Biomni/mcp_generated/mcp_arvados-cwl-runner/docker-compose.yml ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: '3.8'
2
+
3
+ services:
4
+ mcp-arvados-cwl-runner:
5
+ build: .
6
+ image: mcp-arvados-cwl-runner:latest
7
+ container_name: mcp-arvados-cwl-runner
8
+ ports:
9
+ - "8000:8000"
10
+ environment:
11
+ - MCP_SERVER_NAME=arvados-cwl-runner
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_arvados-cwl-runner/environment.yaml ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ name: mcp-tool
3
+ channels:
4
+ - bioconda
5
+ - conda-forge
6
+ - defaults
7
+ dependencies:
8
+ - arvados-cwl-runner
9
+ - python=3.10
10
+
Biomni/mcp_generated/mcp_arvados-cwl-runner/requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ fastmcp
2
+ mcp
Biomni/mcp_generated/mcp_auspice/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 auspice via conda (e.g., from bioconda)
14
+ RUN conda install -c bioconda auspice -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/auspice_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/auspice_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/auspice_server.py"]
40
+
Biomni/mcp_generated/mcp_auspice/app/auspice_server.py ADDED
@@ -0,0 +1,406 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import subprocess
2
+ from pathlib import Path
3
+ from typing import Dict, List, Optional, Any
4
+
5
+ # This is a placeholder for the MCP decorator.
6
+ # In a real MCP environment, this would be provided by the MCP framework.
7
+ def tool():
8
+ def decorator(f):
9
+ return f
10
+ return decorator
11
+
12
+ mcp = type("mcp", (), {"tool": tool})()
13
+
14
+
15
+ from mcp.server.fastmcp import FastMCP
16
+
17
+ SERVER_NAME = 'local_auspice'
18
+ mcp = FastMCP(SERVER_NAME)
19
+
20
+ @mcp.tool()
21
+ def view(
22
+ dataset_dir: Optional[List[Path]] = None,
23
+ host: str = "localhost",
24
+ port: int = 4000,
25
+ verbose: bool = False,
26
+ allow_remote_access: bool = False,
27
+ handlers: Optional[Path] = None,
28
+ config: Optional[Path] = None,
29
+ extend: Optional[Path] = None,
30
+ ) -> Dict[str, str]:
31
+ """
32
+ Starts the Auspice server to view and explore phylogenomic data.
33
+ Note: This command starts a long-running server process and may not be suitable
34
+ for automated workflows that expect a command to terminate.
35
+
36
+ Args:
37
+ dataset_dir: Directory of datasets to serve. Can be specified multiple times.
38
+ host: Host IP address to listen on.
39
+ port: Port to listen on.
40
+ verbose: Print more information to the console.
41
+ allow_remote_access: Allow remote connections to the server.
42
+ handlers: Path to a Javascript file with custom API handlers.
43
+ config: Path to a custom config JSON file.
44
+ extend: Path to a directory containing custom client code.
45
+
46
+ Returns:
47
+ A dictionary containing the command executed, stdout, and stderr.
48
+ """
49
+ cmd = ["auspice", "view"]
50
+
51
+ if dataset_dir:
52
+ for d in dataset_dir:
53
+ if not d.is_dir():
54
+ raise ValueError(f"Dataset directory not found: {d}")
55
+ cmd.extend(["--datasetDir", str(d)])
56
+
57
+ cmd.extend(["--host", host])
58
+ cmd.extend(["--port", str(port)])
59
+
60
+ if verbose:
61
+ cmd.append("--verbose")
62
+ if allow_remote_access:
63
+ cmd.append("--allow-remote-access")
64
+
65
+ if handlers:
66
+ if not handlers.is_file():
67
+ raise FileNotFoundError(f"Handlers file not found: {handlers}")
68
+ cmd.extend(["--handlers", str(handlers)])
69
+
70
+ if config:
71
+ if not config.is_file():
72
+ raise FileNotFoundError(f"Config file not found: {config}")
73
+ cmd.extend(["--config", str(config)])
74
+
75
+ if extend:
76
+ if not extend.is_dir():
77
+ raise ValueError(f"Extend directory not found: {extend}")
78
+ cmd.extend(["--extend", str(extend)])
79
+
80
+ try:
81
+ # This will block until the server is manually stopped.
82
+ result = subprocess.run(
83
+ cmd, capture_output=True, text=True, check=True
84
+ )
85
+ return {
86
+ "command_executed": " ".join(cmd),
87
+ "stdout": result.stdout,
88
+ "stderr": result.stderr,
89
+ }
90
+ except FileNotFoundError:
91
+ return {
92
+ "command_executed": " ".join(cmd),
93
+ "stdout": "",
94
+ "stderr": "Error: 'auspice' command not found. Please ensure it is installed and in your PATH.",
95
+ }
96
+ except subprocess.CalledProcessError as e:
97
+ return {
98
+ "command_executed": " ".join(cmd),
99
+ "stdout": e.stdout,
100
+ "stderr": e.stderr,
101
+ }
102
+
103
+
104
+ @mcp.tool()
105
+ def build(
106
+ verbose: bool = False,
107
+ extend: Optional[Path] = None,
108
+ deploy_path: Optional[str] = None,
109
+ ) -> Dict[str, Any]:
110
+ """
111
+ Creates a production bundle of the Auspice client-side app.
112
+ The output is typically created in a './dist' directory.
113
+
114
+ Args:
115
+ verbose: Print more information to the console.
116
+ extend: Path to a directory containing custom client code.
117
+ deploy_path: Path to deploy the app to (e.g., for GitHub pages).
118
+
119
+ Returns:
120
+ A dictionary containing the command executed, stdout, stderr, and output files.
121
+ """
122
+ cmd = ["auspice", "build"]
123
+
124
+ if verbose:
125
+ cmd.append("--verbose")
126
+
127
+ if extend:
128
+ if not extend.is_dir():
129
+ raise ValueError(f"Extend directory not found: {extend}")
130
+ cmd.extend(["--extend", str(extend)])
131
+
132
+ if deploy_path:
133
+ cmd.extend(["--deploy-path", deploy_path])
134
+
135
+ try:
136
+ result = subprocess.run(
137
+ cmd, capture_output=True, text=True, check=True
138
+ )
139
+ output_dir = Path("./dist")
140
+ return {
141
+ "command_executed": " ".join(cmd),
142
+ "stdout": result.stdout,
143
+ "stderr": result.stderr,
144
+ "output_files": {
145
+ "build_directory": str(output_dir) if output_dir.exists() else "Not created"
146
+ }
147
+ }
148
+ except FileNotFoundError:
149
+ return {
150
+ "command_executed": " ".join(cmd),
151
+ "stdout": "",
152
+ "stderr": "Error: 'auspice' command not found. Please ensure it is installed and in your PATH.",
153
+ "output_files": {}
154
+ }
155
+ except subprocess.CalledProcessError as e:
156
+ return {
157
+ "command_executed": " ".join(cmd),
158
+ "stdout": e.stdout,
159
+ "stderr": e.stderr,
160
+ "output_files": {}
161
+ }
162
+
163
+
164
+ @mcp.tool()
165
+ def export_v1(
166
+ dataset_dir: Path,
167
+ output_dir: Path,
168
+ verbose: bool = False,
169
+ ) -> Dict[str, Any]:
170
+ """
171
+ Exports auspice v1 JSONs to create a static site.
172
+ This is a deprecated command and will be removed in a future version.
173
+
174
+ Args:
175
+ dataset_dir: Directory of datasets to export.
176
+ output_dir: Directory to export the auspice client and datasets to.
177
+ verbose: Print more information to the console.
178
+
179
+ Returns:
180
+ A dictionary containing the command executed, stdout, stderr, and output directory.
181
+ """
182
+ cmd = ["auspice", "export", "v1"]
183
+
184
+ if not dataset_dir.is_dir():
185
+ raise ValueError(f"Dataset directory not found: {dataset_dir}")
186
+ cmd.extend(["--dataset-dir", str(dataset_dir)])
187
+
188
+ output_dir.mkdir(parents=True, exist_ok=True)
189
+ cmd.extend(["--output-dir", str(output_dir)])
190
+
191
+ if verbose:
192
+ cmd.append("--verbose")
193
+
194
+ try:
195
+ result = subprocess.run(
196
+ cmd, capture_output=True, text=True, check=True
197
+ )
198
+ return {
199
+ "command_executed": " ".join(cmd),
200
+ "stdout": result.stdout,
201
+ "stderr": result.stderr,
202
+ "output_files": {
203
+ "export_directory": str(output_dir)
204
+ }
205
+ }
206
+ except FileNotFoundError:
207
+ return {
208
+ "command_executed": " ".join(cmd),
209
+ "stdout": "",
210
+ "stderr": "Error: 'auspice' command not found. Please ensure it is installed and in your PATH.",
211
+ "output_files": {}
212
+ }
213
+ except subprocess.CalledProcessError as e:
214
+ return {
215
+ "command_executed": " ".join(cmd),
216
+ "stdout": e.stdout,
217
+ "stderr": e.stderr,
218
+ "output_files": {}
219
+ }
220
+
221
+
222
+ @mcp.tool()
223
+ def export_v2(
224
+ dataset_dir: Path,
225
+ output_dir: Path,
226
+ verbose: bool = False,
227
+ config: Optional[Path] = None,
228
+ extend: Optional[Path] = None,
229
+ deploy_path: Optional[str] = None,
230
+ ) -> Dict[str, Any]:
231
+ """
232
+ Exports auspice v2 JSONs to create a static site.
233
+
234
+ Args:
235
+ dataset_dir: Directory of datasets to export.
236
+ output_dir: Directory to export the auspice client and datasets to.
237
+ verbose: Print more information to the console.
238
+ config: Path to a custom config JSON file.
239
+ extend: Path to a directory containing custom client code.
240
+ deploy_path: Path to deploy the app to (e.g., for GitHub pages).
241
+
242
+ Returns:
243
+ A dictionary containing the command executed, stdout, stderr, and output directory.
244
+ """
245
+ cmd = ["auspice", "export", "v2"]
246
+
247
+ if not dataset_dir.is_dir():
248
+ raise ValueError(f"Dataset directory not found: {dataset_dir}")
249
+ cmd.extend(["--dataset-dir", str(dataset_dir)])
250
+
251
+ output_dir.mkdir(parents=True, exist_ok=True)
252
+ cmd.extend(["--output-dir", str(output_dir)])
253
+
254
+ if verbose:
255
+ cmd.append("--verbose")
256
+
257
+ if config:
258
+ if not config.is_file():
259
+ raise FileNotFoundError(f"Config file not found: {config}")
260
+ cmd.extend(["--config", str(config)])
261
+
262
+ if extend:
263
+ if not extend.is_dir():
264
+ raise ValueError(f"Extend directory not found: {extend}")
265
+ cmd.extend(["--extend", str(extend)])
266
+
267
+ if deploy_path:
268
+ cmd.extend(["--deploy-path", deploy_path])
269
+
270
+ try:
271
+ result = subprocess.run(
272
+ cmd, capture_output=True, text=True, check=True
273
+ )
274
+ return {
275
+ "command_executed": " ".join(cmd),
276
+ "stdout": result.stdout,
277
+ "stderr": result.stderr,
278
+ "output_files": {
279
+ "export_directory": str(output_dir)
280
+ }
281
+ }
282
+ except FileNotFoundError:
283
+ return {
284
+ "command_executed": " ".join(cmd),
285
+ "stdout": "",
286
+ "stderr": "Error: 'auspice' command not found. Please ensure it is installed and in your PATH.",
287
+ "output_files": {}
288
+ }
289
+ except subprocess.CalledProcessError as e:
290
+ return {
291
+ "command_executed": " ".join(cmd),
292
+ "stdout": e.stdout,
293
+ "stderr": e.stderr,
294
+ "output_files": {}
295
+ }
296
+
297
+
298
+ @mcp.tool()
299
+ def develop(
300
+ verbose: bool = False,
301
+ extend: Optional[Path] = None,
302
+ config: Optional[Path] = None,
303
+ dataset_dir: Optional[List[Path]] = None,
304
+ port: int = 4000,
305
+ host: str = "localhost",
306
+ ) -> Dict[str, str]:
307
+ """
308
+ Starts the Auspice development server with hot-reloading.
309
+ Note: This command starts a long-running server process and may not be suitable
310
+ for automated workflows that expect a command to terminate.
311
+
312
+ Args:
313
+ verbose: Print more information to the console.
314
+ extend: Path to a directory containing custom client code.
315
+ config: Path to a custom config JSON file.
316
+ dataset_dir: Directory of datasets to serve. Can be specified multiple times.
317
+ port: Port to listen on.
318
+ host: Host IP address to listen on.
319
+
320
+ Returns:
321
+ A dictionary containing the command executed, stdout, and stderr.
322
+ """
323
+ cmd = ["auspice", "develop"]
324
+
325
+ if verbose:
326
+ cmd.append("--verbose")
327
+
328
+ if extend:
329
+ if not extend.is_dir():
330
+ raise ValueError(f"Extend directory not found: {extend}")
331
+ cmd.extend(["--extend", str(extend)])
332
+
333
+ if config:
334
+ if not config.is_file():
335
+ raise FileNotFoundError(f"Config file not found: {config}")
336
+ cmd.extend(["--config", str(config)])
337
+
338
+ if dataset_dir:
339
+ for d in dataset_dir:
340
+ if not d.is_dir():
341
+ raise ValueError(f"Dataset directory not found: {d}")
342
+ cmd.extend(["--datasetDir", str(d)])
343
+
344
+ cmd.extend(["--port", str(port)])
345
+ cmd.extend(["--host", host])
346
+
347
+ try:
348
+ # This will block until the server is manually stopped.
349
+ result = subprocess.run(
350
+ cmd, capture_output=True, text=True, check=True
351
+ )
352
+ return {
353
+ "command_executed": " ".join(cmd),
354
+ "stdout": result.stdout,
355
+ "stderr": result.stderr,
356
+ }
357
+ except FileNotFoundError:
358
+ return {
359
+ "command_executed": " ".join(cmd),
360
+ "stdout": "",
361
+ "stderr": "Error: 'auspice' command not found. Please ensure it is installed and in your PATH.",
362
+ }
363
+ except subprocess.CalledProcessError as e:
364
+ return {
365
+ "command_executed": " ".join(cmd),
366
+ "stdout": e.stdout,
367
+ "stderr": e.stderr,
368
+ }
369
+
370
+
371
+ @mcp.tool()
372
+ def version() -> Dict[str, str]:
373
+ """
374
+ Prints the version number of auspice and exits.
375
+
376
+ Returns:
377
+ A dictionary containing the command executed, stdout, stderr, and parsed version.
378
+ """
379
+ cmd = ["auspice", "version"]
380
+ try:
381
+ result = subprocess.run(
382
+ cmd, capture_output=True, text=True, check=True
383
+ )
384
+ return {
385
+ "command_executed": " ".join(cmd),
386
+ "stdout": result.stdout,
387
+ "stderr": result.stderr,
388
+ "version": result.stdout.strip(),
389
+ }
390
+ except FileNotFoundError:
391
+ return {
392
+ "command_executed": " ".join(cmd),
393
+ "stdout": "",
394
+ "stderr": "Error: 'auspice' command not found. Please ensure it is installed and in your PATH.",
395
+ "version": "",
396
+ }
397
+ except subprocess.CalledProcessError as e:
398
+ return {
399
+ "command_executed": " ".join(cmd),
400
+ "stdout": e.stdout,
401
+ "stderr": e.stderr,
402
+ "version": "",
403
+ }
404
+
405
+ if __name__ == "__main__":
406
+ mcp.run(transport="stdio")
Biomni/mcp_generated/mcp_auspice/app/auspice_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_auspice/app/auspice_server.py')
11
+ LOCAL_SERVER = Path(__file__).with_name(SOURCE_SERVER.name)
12
+ SERVER_NAME = 'biosci_auspice'
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_auspice/app/requirements.txt ADDED
@@ -0,0 +1 @@
 
 
1
+
Biomni/mcp_generated/mcp_auspice/docker-compose.yml ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: '3.8'
2
+
3
+ services:
4
+ mcp-auspice:
5
+ build: .
6
+ image: mcp-auspice:latest
7
+ container_name: mcp-auspice
8
+ ports:
9
+ - "8000:8000"
10
+ environment:
11
+ - MCP_SERVER_NAME=auspice
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_auspice/environment.yaml ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ name: mcp-tool
3
+ channels:
4
+ - bioconda
5
+ - conda-forge
6
+ - defaults
7
+ dependencies:
8
+ - auspice
9
+ - python=3.10
10
+
Biomni/mcp_generated/mcp_auspice/requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ fastmcp
2
+ mcp
Biomni/mcp_generated/mcp_barrnap/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 barrnap via conda (e.g., from bioconda)
14
+ RUN conda install -c bioconda barrnap -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/barrnap_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/barrnap_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/barrnap_server.py"]
40
+
Biomni/mcp_generated/mcp_barrnap/app/barrnap_server.py ADDED
@@ -0,0 +1,246 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import subprocess
2
+ import tempfile
3
+ from pathlib import Path
4
+ from typing import List, Optional, Union
5
+
6
+ # Assume mcp is imported and available in the actual runtime environment
7
+ # from mcp import tool
8
+
9
+ from mcp.server.fastmcp import FastMCP
10
+
11
+ SERVER_NAME = 'local_barrnap'
12
+ mcp = FastMCP(SERVER_NAME)
13
+
14
+ @mcp.tool()
15
+ def perl(
16
+ program_file: Optional[Path] = None,
17
+ program_arguments: Optional[List[str]] = None,
18
+ zero_record_separator: Optional[str] = None,
19
+ autosplit_mode: bool = False,
20
+ unicode_features: Optional[str] = None,
21
+ check_syntax_only: bool = False,
22
+ debugger: Optional[str] = None,
23
+ debug_flags: Optional[str] = None,
24
+ execute_program_line: Optional[List[str]] = None,
25
+ execute_program_line_extended: Optional[List[str]] = None,
26
+ no_sitecustomize: bool = False,
27
+ split_pattern: Optional[str] = None,
28
+ in_place_edit_extension: Optional[str] = None,
29
+ include_directories: Optional[List[Path]] = None,
30
+ line_ending_processing: Optional[str] = None,
31
+ use_modules: Optional[List[str]] = None,
32
+ no_modules: Optional[List[str]] = None,
33
+ loop_around_program: bool = False,
34
+ loop_and_print: bool = False,
35
+ rudimentary_switches: bool = False,
36
+ search_path_for_program: bool = False,
37
+ tainting_warnings: bool = False,
38
+ tainting_checks: bool = False,
39
+ dump_core_after_parsing: bool = False,
40
+ allow_unsafe_operations: bool = False,
41
+ print_version: bool = False,
42
+ print_config_summary: Optional[str] = None,
43
+ enable_warnings: bool = False,
44
+ enable_all_warnings: bool = False,
45
+ ignore_text_before_shebang: Optional[Path] = None,
46
+ disable_all_warnings: bool = False,
47
+ ) -> dict:
48
+ """
49
+ Executes Perl programs with various command-line switches.
50
+
51
+ This tool provides an interface to the Perl interpreter, allowing users to
52
+ run Perl scripts, execute one-liners, and control various aspects of Perl's
53
+ behavior, including debugging, warnings, Unicode features, and module loading.
54
+
55
+ Args:
56
+ program_file: Path to the Perl program file to execute.
57
+ If -e or -E is used, this should typically be omitted.
58
+ program_arguments: List of arguments to pass to the Perl program.
59
+ zero_record_separator: Specify record separator. If an empty string, uses '\0'.
60
+ Otherwise, specifies an octal value. (e.g., "0" for -0, "0777" for -0777)
61
+ autosplit_mode: Enable autosplit mode with -n or -p (splits $_ into @F).
62
+ unicode_features: Enables the listed Unicode features (e.g., "all", "io").
63
+ check_syntax_only: Check syntax only (runs BEGIN and CHECK blocks).
64
+ debugger: Run program under debugger. If an empty string, uses default debugger (-d).
65
+ Otherwise, specifies a debugger (e.g., ":MyDebugger").
66
+ debug_flags: Set debugging flags (argument is a bit mask or alphabets).
67
+ execute_program_line: One line of program to execute. Can be specified multiple times.
68
+ If used, program_file should typically be omitted.
69
+ execute_program_line_extended: Like -e, but enables all optional features.
70
+ Can be specified multiple times.
71
+ If used, program_file should typically be omitted.
72
+ no_sitecustomize: Don't do $sitelib/sitecustomize.pl at startup.
73
+ split_pattern: split() pattern for -a switch (e.g., "/\t/").
74
+ in_place_edit_extension: Edit <> files in place. If an empty string, no backup is made (-i).
75
+ If an extension is supplied (e.g., ".bak"), a backup is made.
76
+ include_directories: Specify @INC/#include directory. Can be specified multiple times.
77
+ line_ending_processing: Enable line ending processing. If an empty string, enables default (-l).
78
+ Otherwise, specifies line terminator (e.g., "012").
79
+ use_modules: Execute "use module..." before executing program. Can be specified multiple times.
80
+ Corresponds to -m or -M.
81
+ no_modules: Execute "no module..." before executing program. Can be specified multiple times.
82
+ Corresponds to -m- or -M-.
83
+ loop_around_program: Assume "while (<>) { ... }" loop around program (-n).
84
+ loop_and_print: Assume loop like -n but print line also, like sed (-p).
85
+ rudimentary_switches: Enable rudimentary parsing for switches after programfile (-s).
86
+ search_path_for_program: Look for programfile using PATH environment variable (-S).
87
+ tainting_warnings: Enable tainting warnings (-t).
88
+ tainting_checks: Enable tainting checks (-T).
89
+ dump_core_after_parsing: Dump core after parsing program (-u).
90
+ allow_unsafe_operations: Allow unsafe operations (-U).
91
+ print_version: Print version, patchlevel and license (-v).
92
+ print_config_summary: Print configuration summary. If an empty string, prints full summary (-V).
93
+ Otherwise, prints a single Config.pm variable (e.g., ":archname").
94
+ enable_warnings: Enable many useful warnings (-w).
95
+ enable_all_warnings: Enable all warnings (-W).
96
+ ignore_text_before_shebang: Ignore text before #!perl line. If None, just ignores (-x).
97
+ Optionally change to directory (e.g., Path("/tmp")).
98
+ disable_all_warnings: Disable all warnings (-X).
99
+
100
+ Returns:
101
+ A dictionary containing the command executed, stdout, stderr, and any output files.
102
+ """
103
+ cmd = ["perl"]
104
+ output_files = []
105
+
106
+ # Input validation
107
+ if program_file and not program_file.is_file():
108
+ return {
109
+ "command_executed": " ".join(cmd),
110
+ "stdout": "",
111
+ "stderr": f"Error: Program file '{program_file}' not found.",
112
+ "output_files": [],
113
+ }
114
+
115
+ if (execute_program_line or execute_program_line_extended) and program_file:
116
+ return {
117
+ "command_executed": " ".join(cmd),
118
+ "stdout": "",
119
+ "stderr": "Error: Cannot use -e/-E with a program file. Please omit program_file.",
120
+ "output_files": [],
121
+ }
122
+
123
+ # Add switches
124
+ if zero_record_separator is not None:
125
+ cmd.append(f"-0{zero_record_separator}")
126
+ if autosplit_mode:
127
+ cmd.append("-a")
128
+ if unicode_features:
129
+ cmd.append(f"-C{unicode_features}")
130
+ if check_syntax_only:
131
+ cmd.append("-c")
132
+ if debugger is not None:
133
+ cmd.append(f"-d{':' if debugger else ''}{debugger}")
134
+ if debug_flags:
135
+ cmd.append(f"-D{debug_flags}")
136
+ if execute_program_line:
137
+ for line in execute_program_line:
138
+ cmd.append("-e")
139
+ cmd.append(line)
140
+ if execute_program_line_extended:
141
+ for line in execute_program_line_extended:
142
+ cmd.append("-E")
143
+ cmd.append(line)
144
+ if no_sitecustomize:
145
+ cmd.append("-f")
146
+ if split_pattern:
147
+ cmd.append(f"-F{split_pattern}")
148
+ if in_place_edit_extension is not None:
149
+ cmd.append(f"-i{in_place_edit_extension}")
150
+ if include_directories:
151
+ for directory in include_directories:
152
+ if not directory.is_dir():
153
+ return {
154
+ "command_executed": " ".join(cmd),
155
+ "stdout": "",
156
+ "stderr": f"Error: Include directory '{directory}' not found.",
157
+ "output_files": [],
158
+ }
159
+ cmd.append("-I")
160
+ cmd.append(str(directory))
161
+ if line_ending_processing is not None:
162
+ cmd.append(f"-l{line_ending_processing}")
163
+ if use_modules:
164
+ for module in use_modules:
165
+ # The help document shows -[mM][-]module.
166
+ # Assuming -M for 'use' and -m- for 'no'.
167
+ # For simplicity, we'll use -M for 'use' as it's more common for explicit module loading.
168
+ cmd.append(f"-M{module}")
169
+ if no_modules:
170
+ for module in no_modules:
171
+ cmd.append(f"-M-{module}") # Using -M- for 'no module'
172
+ if loop_around_program:
173
+ cmd.append("-n")
174
+ if loop_and_print:
175
+ cmd.append("-p")
176
+ if rudimentary_switches:
177
+ cmd.append("-s")
178
+ if search_path_for_program:
179
+ cmd.append("-S")
180
+ if tainting_warnings:
181
+ cmd.append("-t")
182
+ if tainting_checks:
183
+ cmd.append("-T")
184
+ if dump_core_after_parsing:
185
+ cmd.append("-u")
186
+ if allow_unsafe_operations:
187
+ cmd.append("-U")
188
+ if print_version:
189
+ cmd.append("-v")
190
+ if print_config_summary is not None:
191
+ cmd.append(f"-V{':' if print_config_summary else ''}{print_config_summary}")
192
+ if enable_warnings:
193
+ cmd.append("-w")
194
+ if enable_all_warnings:
195
+ cmd.append("-W")
196
+ if ignore_text_before_shebang is not None:
197
+ if ignore_text_before_shebang and not ignore_text_before_shebang.is_dir():
198
+ return {
199
+ "command_executed": " ".join(cmd),
200
+ "stdout": "",
201
+ "stderr": f"Error: Directory for -x '{ignore_text_before_shebang}' not found.",
202
+ "output_files": [],
203
+ }
204
+ cmd.append(f"-x{str(ignore_text_before_shebang) if ignore_text_before_shebang else ''}")
205
+ if disable_all_warnings:
206
+ cmd.append("-X")
207
+
208
+ # Add program file and its arguments
209
+ if program_file:
210
+ cmd.append(str(program_file))
211
+ if program_arguments:
212
+ cmd.extend(program_arguments)
213
+
214
+ try:
215
+ process = subprocess.run(
216
+ cmd,
217
+ capture_output=True,
218
+ text=True,
219
+ check=True,
220
+ )
221
+ stdout = process.stdout
222
+ stderr = process.stderr
223
+ except subprocess.CalledProcessError as e:
224
+ return {
225
+ "command_executed": " ".join(e.cmd),
226
+ "stdout": e.stdout,
227
+ "stderr": e.stderr,
228
+ "output_files": [],
229
+ }
230
+ except FileNotFoundError:
231
+ return {
232
+ "command_executed": " ".join(cmd),
233
+ "stdout": "",
234
+ "stderr": "Error: 'perl' command not found. Ensure Perl is installed and in your PATH.",
235
+ "output_files": [],
236
+ }
237
+
238
+ return {
239
+ "command_executed": " ".join(cmd),
240
+ "stdout": stdout,
241
+ "stderr": stderr,
242
+ "output_files": output_files,
243
+ }
244
+
245
+ if __name__ == "__main__":
246
+ mcp.run(transport="stdio")
Biomni/mcp_generated/mcp_barrnap/app/barrnap_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_barrnap/app/barrnap_server.py')
11
+ LOCAL_SERVER = Path(__file__).with_name(SOURCE_SERVER.name)
12
+ SERVER_NAME = 'biosci_barrnap'
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_barrnap/app/requirements.txt ADDED
@@ -0,0 +1 @@
 
 
1
+
Biomni/mcp_generated/mcp_barrnap/docker-compose.yml ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: '3.8'
2
+
3
+ services:
4
+ mcp-barrnap:
5
+ build: .
6
+ image: mcp-barrnap:latest
7
+ container_name: mcp-barrnap
8
+ ports:
9
+ - "8000:8000"
10
+ environment:
11
+ - MCP_SERVER_NAME=barrnap
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_barrnap/environment.yaml ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ name: mcp-tool
3
+ channels:
4
+ - bioconda
5
+ - conda-forge
6
+ - defaults
7
+ dependencies:
8
+ - barrnap
9
+ - python=3.10
10
+
Biomni/mcp_generated/mcp_barrnap/requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ fastmcp
2
+ mcp
Biomni/mcp_generated/mcp_bedtools/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 bedtools via conda (e.g., from bioconda)
14
+ RUN conda install -c bioconda bedtools -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 bedtools_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/bedtools_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/bedtools_server.py"]
40
+
Biomni/mcp_generated/mcp_bedtools/app/__pycache__/bedtools_server.cpython-311.pyc ADDED
Binary file (31.2 kB). View file
 
Biomni/mcp_generated/mcp_bedtools/app/__pycache__/bedtools_shim_server.cpython-311.pyc ADDED
Binary file (3.55 kB). View file
 
Biomni/mcp_generated/mcp_bedtools/app/bedtools_server.py ADDED
@@ -0,0 +1,708 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import subprocess
2
+ import tempfile
3
+ from pathlib import Path
4
+ from typing import List, Optional
5
+
6
+ # This is a placeholder for the MCP decorator.
7
+ # In a real MCP environment, this would be provided by the MCP framework.
8
+ def tool(func):
9
+ """A dummy decorator to stand in for @mcp.tool()."""
10
+ return func
11
+
12
+ mcp = type("mcp", (), {"tool": tool})
13
+
14
+
15
+ from mcp.server.fastmcp import FastMCP
16
+
17
+ SERVER_NAME = 'local_bedtools'
18
+ mcp = FastMCP(SERVER_NAME)
19
+
20
+ @mcp.tool()
21
+ def intersect(
22
+ a: Path,
23
+ b: List[Path],
24
+ output: Optional[Path] = None,
25
+ wa: bool = False,
26
+ wb: bool = False,
27
+ loj: bool = False,
28
+ wo: bool = False,
29
+ wao: bool = False,
30
+ u: bool = False,
31
+ c: bool = False,
32
+ v: bool = False,
33
+ ubam: bool = False,
34
+ s: bool = False,
35
+ S: bool = False,
36
+ f: float = 1e-9,
37
+ F: float = 1e-9,
38
+ r: bool = False,
39
+ e: bool = False,
40
+ split: bool = False,
41
+ g: Optional[Path] = None,
42
+ header: bool = False,
43
+ bed: bool = False,
44
+ sorted: bool = False,
45
+ names: Optional[str] = None,
46
+ filenames: bool = False,
47
+ nonamecheck: bool = False,
48
+ ):
49
+ """
50
+ Find overlapping intervals in two or more BED/GFF/VCF/BAM files.
51
+
52
+ This tool allows one to screen for overlaps between two sets of genomic features.
53
+ """
54
+ # Input validation
55
+ if not a.exists():
56
+ raise FileNotFoundError(f"Input file -a does not exist: {a}")
57
+ for b_file in b:
58
+ if not b_file.exists():
59
+ raise FileNotFoundError(f"Input file in -b list does not exist: {b_file}")
60
+ if g and not g.exists():
61
+ raise FileNotFoundError(f"Genome file -g does not exist: {g}")
62
+
63
+ exclusive_flags = [u, c, v, wo, wao]
64
+ if sum(exclusive_flags) > 1:
65
+ raise ValueError("Options -u, -c, -v, -wo, -wao are mutually exclusive.")
66
+ if s and S:
67
+ raise ValueError("Options -s and -S are mutually exclusive.")
68
+ if f < 0.0 or f > 1.0:
69
+ raise ValueError("-f (fraction) must be between 0.0 and 1.0.")
70
+ if F < 0.0 or F > 1.0:
71
+ raise ValueError("-F (fraction) must be between 0.0 and 1.0.")
72
+ if sorted and not g:
73
+ raise ValueError("The -sorted option requires a genome file (-g).")
74
+
75
+ # Command construction
76
+ cmd = ["bedtools", "intersect", "-a", str(a), "-b"]
77
+ cmd.extend([str(p) for p in b])
78
+
79
+ if wa: cmd.append("-wa")
80
+ if wb: cmd.append("-wb")
81
+ if loj: cmd.append("-loj")
82
+ if wo: cmd.append("-wo")
83
+ if wao: cmd.append("-wao")
84
+ if u: cmd.append("-u")
85
+ if c: cmd.append("-c")
86
+ if v: cmd.append("-v")
87
+ if ubam: cmd.append("-ubam")
88
+ if s: cmd.append("-s")
89
+ if S: cmd.append("-S")
90
+ if f != 1e-9: cmd.extend(["-f", str(f)])
91
+ if F != 1e-9: cmd.extend(["-F", str(F)])
92
+ if r: cmd.append("-r")
93
+ if e: cmd.append("-e")
94
+ if split: cmd.append("-split")
95
+ if g: cmd.extend(["-g", str(g)])
96
+ if header: cmd.append("-header")
97
+ if bed: cmd.append("-bed")
98
+ if sorted: cmd.append("-sorted")
99
+ if names: cmd.extend(["-names", names])
100
+ if filenames: cmd.append("-filenames")
101
+ if nonamecheck: cmd.append("-nonamecheck")
102
+
103
+ # Subprocess execution
104
+ command_executed = " ".join(cmd)
105
+ output_files = []
106
+ stdout_capture, stderr_capture = "", ""
107
+
108
+ try:
109
+ if output:
110
+ output_files.append(str(output))
111
+ with open(output, "w") as f_out:
112
+ result = subprocess.run(
113
+ cmd, check=True, text=True, stdout=f_out, stderr=subprocess.PIPE
114
+ )
115
+ stderr_capture = result.stderr
116
+ else:
117
+ result = subprocess.run(
118
+ cmd, check=True, text=True, capture_output=True
119
+ )
120
+ stdout_capture = result.stdout
121
+ stderr_capture = result.stderr
122
+ except subprocess.CalledProcessError as e:
123
+ return {
124
+ "command_executed": command_executed,
125
+ "stdout": e.stdout or "",
126
+ "stderr": e.stderr or "CalledProcessError with no stderr.",
127
+ "output_files": [],
128
+ "return_code": e.returncode,
129
+ }
130
+
131
+ return {
132
+ "command_executed": command_executed,
133
+ "stdout": stdout_capture,
134
+ "stderr": stderr_capture,
135
+ "output_files": output_files,
136
+ }
137
+
138
+
139
+ @mcp.tool()
140
+ def merge(
141
+ i: Path,
142
+ output: Optional[Path] = None,
143
+ s: bool = False,
144
+ S: Optional[str] = None,
145
+ d: int = 0,
146
+ c: Optional[str] = None,
147
+ o: Optional[str] = None,
148
+ header: bool = False,
149
+ delim: str = ";",
150
+ n: bool = False,
151
+ nms: bool = False,
152
+ scores: Optional[str] = None,
153
+ bed: bool = False,
154
+ prec: int = 5,
155
+ ):
156
+ """
157
+ Merge overlapping features in a BED/GFF/VCF file.
158
+
159
+ This tool combines overlapping or "book-ended" features into a single feature.
160
+ """
161
+ # Input validation
162
+ if not i.exists():
163
+ raise FileNotFoundError(f"Input file -i does not exist: {i}")
164
+ if S and S not in ["+", "-"]:
165
+ raise ValueError("Option -S must be either '+' or '-'.")
166
+ if s and S:
167
+ raise ValueError("Options -s and -S are mutually exclusive.")
168
+ if d < 0:
169
+ raise ValueError("Option -d (distance) must be a non-negative integer.")
170
+ if (c and not o) or (o and not c):
171
+ raise ValueError("Options -c and -o must be used together.")
172
+ if c and o:
173
+ if len(c.split(',')) != len(o.split(',')):
174
+ raise ValueError("The number of columns in -c must match the number of operations in -o.")
175
+
176
+ # Command construction
177
+ cmd = ["bedtools", "merge", "-i", str(i)]
178
+
179
+ if s: cmd.append("-s")
180
+ if S: cmd.extend(["-S", S])
181
+ if d > 0: cmd.extend(["-d", str(d)])
182
+ if c: cmd.extend(["-c", c])
183
+ if o: cmd.extend(["-o", o])
184
+ if header: cmd.append("-header")
185
+ if delim != ";": cmd.extend(["-delim", delim])
186
+ if n: cmd.append("-n")
187
+ if nms: cmd.append("-nms")
188
+ if scores: cmd.extend(["-scores", scores])
189
+ if bed: cmd.append("-bed")
190
+ if prec != 5: cmd.extend(["-prec", str(prec)])
191
+
192
+ # Subprocess execution
193
+ command_executed = " ".join(cmd)
194
+ output_files = []
195
+ stdout_capture, stderr_capture = "", ""
196
+
197
+ try:
198
+ if output:
199
+ output_files.append(str(output))
200
+ with open(output, "w") as f_out:
201
+ result = subprocess.run(
202
+ cmd, check=True, text=True, stdout=f_out, stderr=subprocess.PIPE
203
+ )
204
+ stderr_capture = result.stderr
205
+ else:
206
+ result = subprocess.run(
207
+ cmd, check=True, text=True, capture_output=True
208
+ )
209
+ stdout_capture = result.stdout
210
+ stderr_capture = result.stderr
211
+ except subprocess.CalledProcessError as e:
212
+ return {
213
+ "command_executed": command_executed,
214
+ "stdout": e.stdout or "",
215
+ "stderr": e.stderr or "CalledProcessError with no stderr.",
216
+ "output_files": [],
217
+ "return_code": e.returncode,
218
+ }
219
+
220
+ return {
221
+ "command_executed": command_executed,
222
+ "stdout": stdout_capture,
223
+ "stderr": stderr_capture,
224
+ "output_files": output_files,
225
+ }
226
+
227
+
228
+ @mcp.tool()
229
+ def subtract(
230
+ a: Path,
231
+ b: List[Path],
232
+ output: Optional[Path] = None,
233
+ f: float = 1e-9,
234
+ F: float = 1e-9,
235
+ r: bool = False,
236
+ e: bool = False,
237
+ s: bool = False,
238
+ S: bool = False,
239
+ A: bool = False,
240
+ B: bool = False,
241
+ N: bool = False,
242
+ header: bool = False,
243
+ g: Optional[Path] = None,
244
+ ):
245
+ """
246
+ Remove overlapping intervals from a BED/GFF/VCF file.
247
+
248
+ This tool removes portions of features in file A that are overlapped by features in file(s) B.
249
+ """
250
+ # Input validation
251
+ if not a.exists():
252
+ raise FileNotFoundError(f"Input file -a does not exist: {a}")
253
+ for b_file in b:
254
+ if not b_file.exists():
255
+ raise FileNotFoundError(f"Input file in -b list does not exist: {b_file}")
256
+ if g and not g.exists():
257
+ raise FileNotFoundError(f"Genome file -g does not exist: {g}")
258
+ if A and B:
259
+ raise ValueError("Options -A and -B are mutually exclusive.")
260
+ if s and S:
261
+ raise ValueError("Options -s and -S are mutually exclusive.")
262
+
263
+ # Command construction
264
+ cmd = ["bedtools", "subtract", "-a", str(a), "-b"]
265
+ cmd.extend([str(p) for p in b])
266
+
267
+ if f != 1e-9: cmd.extend(["-f", str(f)])
268
+ if F != 1e-9: cmd.extend(["-F", str(F)])
269
+ if r: cmd.append("-r")
270
+ if e: cmd.append("-e")
271
+ if s: cmd.append("-s")
272
+ if S: cmd.append("-S")
273
+ if A: cmd.append("-A")
274
+ if B: cmd.append("-B")
275
+ if N: cmd.append("-N")
276
+ if header: cmd.append("-header")
277
+ if g: cmd.extend(["-g", str(g)])
278
+
279
+ # Subprocess execution
280
+ command_executed = " ".join(cmd)
281
+ output_files = []
282
+ stdout_capture, stderr_capture = "", ""
283
+
284
+ try:
285
+ if output:
286
+ output_files.append(str(output))
287
+ with open(output, "w") as f_out:
288
+ result = subprocess.run(
289
+ cmd, check=True, text=True, stdout=f_out, stderr=subprocess.PIPE
290
+ )
291
+ stderr_capture = result.stderr
292
+ else:
293
+ result = subprocess.run(
294
+ cmd, check=True, text=True, capture_output=True
295
+ )
296
+ stdout_capture = result.stdout
297
+ stderr_capture = result.stderr
298
+ except subprocess.CalledProcessError as e:
299
+ return {
300
+ "command_executed": command_executed,
301
+ "stdout": e.stdout or "",
302
+ "stderr": e.stderr or "CalledProcessError with no stderr.",
303
+ "output_files": [],
304
+ "return_code": e.returncode,
305
+ }
306
+
307
+ return {
308
+ "command_executed": command_executed,
309
+ "stdout": stdout_capture,
310
+ "stderr": stderr_capture,
311
+ "output_files": output_files,
312
+ }
313
+
314
+
315
+ @mcp.tool()
316
+ def slop(
317
+ i: Path,
318
+ g: Path,
319
+ output: Optional[Path] = None,
320
+ b: int = 0,
321
+ l: int = 0,
322
+ r: int = 0,
323
+ s: bool = False,
324
+ pct: bool = False,
325
+ header: bool = False,
326
+ ):
327
+ """
328
+ Increase the size of features in a BED/GFF/VCF file.
329
+
330
+ This tool will increase the size of each feature in a feature file by a user-defined number of bases.
331
+ """
332
+ # Input validation
333
+ if not i.exists():
334
+ raise FileNotFoundError(f"Input file -i does not exist: {i}")
335
+ if not g.exists():
336
+ raise FileNotFoundError(f"Genome file -g does not exist: {g}")
337
+ if b != 0 and (l != 0 or r != 0):
338
+ raise ValueError("Option -b cannot be used with -l or -r.")
339
+
340
+ # Command construction
341
+ cmd = ["bedtools", "slop", "-i", str(i), "-g", str(g)]
342
+
343
+ if b != 0: cmd.extend(["-b", str(b)])
344
+ if l != 0: cmd.extend(["-l", str(l)])
345
+ if r != 0: cmd.extend(["-r", str(r)])
346
+ if s: cmd.append("-s")
347
+ if pct: cmd.append("-pct")
348
+ if header: cmd.append("-header")
349
+
350
+ # Subprocess execution
351
+ command_executed = " ".join(cmd)
352
+ output_files = []
353
+ stdout_capture, stderr_capture = "", ""
354
+
355
+ try:
356
+ if output:
357
+ output_files.append(str(output))
358
+ with open(output, "w") as f_out:
359
+ result = subprocess.run(
360
+ cmd, check=True, text=True, stdout=f_out, stderr=subprocess.PIPE
361
+ )
362
+ stderr_capture = result.stderr
363
+ else:
364
+ result = subprocess.run(
365
+ cmd, check=True, text=True, capture_output=True
366
+ )
367
+ stdout_capture = result.stdout
368
+ stderr_capture = result.stderr
369
+ except subprocess.CalledProcessError as e:
370
+ return {
371
+ "command_executed": command_executed,
372
+ "stdout": e.stdout or "",
373
+ "stderr": e.stderr or "CalledProcessError with no stderr.",
374
+ "output_files": [],
375
+ "return_code": e.returncode,
376
+ }
377
+
378
+ return {
379
+ "command_executed": command_executed,
380
+ "stdout": stdout_capture,
381
+ "stderr": stderr_capture,
382
+ "output_files": output_files,
383
+ }
384
+
385
+
386
+ @mcp.tool()
387
+ def getfasta(
388
+ fi: Path,
389
+ bed: Path,
390
+ fo: Optional[Path] = None,
391
+ s: bool = False,
392
+ split: bool = False,
393
+ name: bool = False,
394
+ name_plus: bool = False,
395
+ tab: bool = False,
396
+ full_header: bool = False,
397
+ ):
398
+ """
399
+ Extract DNA sequences from a FASTA file based on BED/GFF/VCF coordinates.
400
+ """
401
+ # Input validation
402
+ if not fi.exists():
403
+ raise FileNotFoundError(f"FASTA input file -fi does not exist: {fi}")
404
+ if not bed.exists():
405
+ raise FileNotFoundError(f"BED/GFF/VCF file -bed does not exist: {bed}")
406
+ if name and name_plus:
407
+ raise ValueError("Options -name and -name+ are mutually exclusive.")
408
+
409
+ # Command construction
410
+ cmd = ["bedtools", "getfasta", "-fi", str(fi), "-bed", str(bed)]
411
+
412
+ if s: cmd.append("-s")
413
+ if split: cmd.append("-split")
414
+ if name: cmd.append("-name")
415
+ if name_plus: cmd.append("-name+")
416
+ if tab: cmd.append("-tab")
417
+ if full_header: cmd.append("-fullHeader")
418
+ if fo: cmd.extend(["-fo", str(fo)])
419
+
420
+ # Subprocess execution
421
+ command_executed = " ".join(cmd)
422
+ output_files = []
423
+ stdout_capture, stderr_capture = "", ""
424
+
425
+ try:
426
+ # getfasta is unique in that it has a dedicated -fo parameter
427
+ # and doesn't typically write to stdout if -fo is used.
428
+ result = subprocess.run(
429
+ cmd, check=True, text=True, capture_output=True
430
+ )
431
+ stdout_capture = result.stdout
432
+ stderr_capture = result.stderr
433
+ if fo:
434
+ output_files.append(str(fo))
435
+
436
+ except subprocess.CalledProcessError as e:
437
+ return {
438
+ "command_executed": command_executed,
439
+ "stdout": e.stdout or "",
440
+ "stderr": e.stderr or "CalledProcessError with no stderr.",
441
+ "output_files": [],
442
+ "return_code": e.returncode,
443
+ }
444
+
445
+ return {
446
+ "command_executed": command_executed,
447
+ "stdout": stdout_capture,
448
+ "stderr": stderr_capture,
449
+ "output_files": output_files,
450
+ }
451
+
452
+
453
+ @mcp.tool()
454
+ def sort(
455
+ i: Path,
456
+ output: Optional[Path] = None,
457
+ header: bool = False,
458
+ g: Optional[Path] = None,
459
+ faidx: Optional[Path] = None,
460
+ sizeA: bool = False,
461
+ sizeD: bool = False,
462
+ chrThenSizeA: bool = False,
463
+ chrThenSizeD: bool = False,
464
+ chrThenScoreA: bool = False,
465
+ chrThenScoreD: bool = False,
466
+ ):
467
+ """
468
+ Sort a BED/GFF/VCF file by chromosome and then by start position.
469
+ """
470
+ # Input validation
471
+ if not i.exists():
472
+ raise FileNotFoundError(f"Input file -i does not exist: {i}")
473
+ if g and not g.exists():
474
+ raise FileNotFoundError(f"Genome file -g does not exist: {g}")
475
+ if faidx and not faidx.exists():
476
+ raise FileNotFoundError(f"FASTA index file -faidx does not exist: {faidx}")
477
+
478
+ sort_flags = [sizeA, sizeD, chrThenSizeA, chrThenSizeD, chrThenScoreA, chrThenScoreD]
479
+ if sum(sort_flags) > 1:
480
+ raise ValueError("Multiple sorting order flags were provided, but only one is allowed.")
481
+
482
+ # Command construction
483
+ cmd = ["bedtools", "sort", "-i", str(i)]
484
+
485
+ if header: cmd.append("-header")
486
+ if g: cmd.extend(["-g", str(g)])
487
+ if faidx: cmd.extend(["-faidx", str(faidx)])
488
+ if sizeA: cmd.append("-sizeA")
489
+ if sizeD: cmd.append("-sizeD")
490
+ if chrThenSizeA: cmd.append("-chrThenSizeA")
491
+ if chrThenSizeD: cmd.append("-chrThenSizeD")
492
+ if chrThenScoreA: cmd.append("-chrThenScoreA")
493
+ if chrThenScoreD: cmd.append("-chrThenScoreD")
494
+
495
+ # Subprocess execution
496
+ command_executed = " ".join(cmd)
497
+ output_files = []
498
+ stdout_capture, stderr_capture = "", ""
499
+
500
+ try:
501
+ if output:
502
+ output_files.append(str(output))
503
+ with open(output, "w") as f_out:
504
+ result = subprocess.run(
505
+ cmd, check=True, text=True, stdout=f_out, stderr=subprocess.PIPE
506
+ )
507
+ stderr_capture = result.stderr
508
+ else:
509
+ result = subprocess.run(
510
+ cmd, check=True, text=True, capture_output=True
511
+ )
512
+ stdout_capture = result.stdout
513
+ stderr_capture = result.stderr
514
+ except subprocess.CalledProcessError as e:
515
+ return {
516
+ "command_executed": command_executed,
517
+ "stdout": e.stdout or "",
518
+ "stderr": e.stderr or "CalledProcessError with no stderr.",
519
+ "output_files": [],
520
+ "return_code": e.returncode,
521
+ }
522
+
523
+ return {
524
+ "command_executed": command_executed,
525
+ "stdout": stdout_capture,
526
+ "stderr": stderr_capture,
527
+ "output_files": output_files,
528
+ }
529
+
530
+
531
+ @mcp.tool()
532
+ def coverage(
533
+ a: Path,
534
+ b: List[Path],
535
+ output: Optional[Path] = None,
536
+ s: bool = False,
537
+ S: bool = False,
538
+ f: float = 1e-9,
539
+ F: float = 1e-9,
540
+ r: bool = False,
541
+ e: bool = False,
542
+ split: bool = False,
543
+ d: bool = False,
544
+ counts: bool = False,
545
+ hist: bool = False,
546
+ mean: bool = False,
547
+ g: Optional[Path] = None,
548
+ header: bool = False,
549
+ sorted: bool = False,
550
+ ):
551
+ """
552
+ Compute the coverage of features in file A on features in file(s) B.
553
+ """
554
+ # Input validation
555
+ if not a.exists():
556
+ raise FileNotFoundError(f"Input file -a does not exist: {a}")
557
+ for b_file in b:
558
+ if not b_file.exists():
559
+ raise FileNotFoundError(f"Input file in -b list does not exist: {b_file}")
560
+ if g and not g.exists():
561
+ raise FileNotFoundError(f"Genome file -g does not exist: {g}")
562
+ if s and S:
563
+ raise ValueError("Options -s and -S are mutually exclusive.")
564
+ if sorted and not g:
565
+ raise ValueError("The -sorted option requires a genome file (-g).")
566
+
567
+ # Command construction
568
+ cmd = ["bedtools", "coverage", "-a", str(a), "-b"]
569
+ cmd.extend([str(p) for p in b])
570
+
571
+ if s: cmd.append("-s")
572
+ if S: cmd.append("-S")
573
+ if f != 1e-9: cmd.extend(["-f", str(f)])
574
+ if F != 1e-9: cmd.extend(["-F", str(F)])
575
+ if r: cmd.append("-r")
576
+ if e: cmd.append("-e")
577
+ if split: cmd.append("-split")
578
+ if d: cmd.append("-d")
579
+ if counts: cmd.append("-counts")
580
+ if hist: cmd.append("-hist")
581
+ if mean: cmd.append("-mean")
582
+ if g: cmd.extend(["-g", str(g)])
583
+ if header: cmd.append("-header")
584
+ if sorted: cmd.append("-sorted")
585
+
586
+ # Subprocess execution
587
+ command_executed = " ".join(cmd)
588
+ output_files = []
589
+ stdout_capture, stderr_capture = "", ""
590
+
591
+ try:
592
+ if output:
593
+ output_files.append(str(output))
594
+ with open(output, "w") as f_out:
595
+ result = subprocess.run(
596
+ cmd, check=True, text=True, stdout=f_out, stderr=subprocess.PIPE
597
+ )
598
+ stderr_capture = result.stderr
599
+ else:
600
+ result = subprocess.run(
601
+ cmd, check=True, text=True, capture_output=True
602
+ )
603
+ stdout_capture = result.stdout
604
+ stderr_capture = result.stderr
605
+ except subprocess.CalledProcessError as e:
606
+ return {
607
+ "command_executed": command_executed,
608
+ "stdout": e.stdout or "",
609
+ "stderr": e.stderr or "CalledProcessError with no stderr.",
610
+ "output_files": [],
611
+ "return_code": e.returncode,
612
+ }
613
+
614
+ return {
615
+ "command_executed": command_executed,
616
+ "stdout": stdout_capture,
617
+ "stderr": stderr_capture,
618
+ "output_files": output_files,
619
+ }
620
+
621
+
622
+ @mcp.tool()
623
+ def genomecov(
624
+ i: Path,
625
+ g: Path,
626
+ output: Optional[Path] = None,
627
+ d: bool = False,
628
+ dz: bool = False,
629
+ bga: bool = False,
630
+ bg: bool = False,
631
+ scale: float = 1.0,
632
+ pc: bool = False,
633
+ fs: bool = False,
634
+ split: bool = False,
635
+ strand: Optional[str] = None,
636
+ max: int = 0,
637
+ trackline: bool = False,
638
+ trackopts: Optional[str] = None,
639
+ ):
640
+ """
641
+ Compute genome-wide coverage of a feature file.
642
+ """
643
+ # Input validation
644
+ if not i.exists():
645
+ raise FileNotFoundError(f"Input file -i does not exist: {i}")
646
+ if not g.exists():
647
+ raise FileNotFoundError(f"Genome file -g does not exist: {g}")
648
+ if strand and strand not in ["+", "-"]:
649
+ raise ValueError("Option -strand must be either '+' or '-'.")
650
+ if max < 0:
651
+ raise ValueError("Option -max must be a non-negative integer.")
652
+ output_modes = [d, dz, bga, bg]
653
+ if sum(output_modes) > 1:
654
+ raise ValueError("Output format flags (-d, -dz, -bga, -bg) are mutually exclusive.")
655
+
656
+ # Command construction
657
+ cmd = ["bedtools", "genomecov", "-i", str(i), "-g", str(g)]
658
+
659
+ if d: cmd.append("-d")
660
+ if dz: cmd.append("-dz")
661
+ if bga: cmd.append("-bga")
662
+ if bg: cmd.append("-bg")
663
+ if scale != 1.0: cmd.extend(["-scale", str(scale)])
664
+ if pc: cmd.append("-pc")
665
+ if fs: cmd.append("-fs")
666
+ if split: cmd.append("-split")
667
+ if strand: cmd.extend(["-strand", strand])
668
+ if max > 0: cmd.extend(["-max", str(max)])
669
+ if trackline: cmd.append("-trackline")
670
+ if trackopts: cmd.extend(["-trackopts", trackopts])
671
+
672
+ # Subprocess execution
673
+ command_executed = " ".join(cmd)
674
+ output_files = []
675
+ stdout_capture, stderr_capture = "", ""
676
+
677
+ try:
678
+ if output:
679
+ output_files.append(str(output))
680
+ with open(output, "w") as f_out:
681
+ result = subprocess.run(
682
+ cmd, check=True, text=True, stdout=f_out, stderr=subprocess.PIPE
683
+ )
684
+ stderr_capture = result.stderr
685
+ else:
686
+ result = subprocess.run(
687
+ cmd, check=True, text=True, capture_output=True
688
+ )
689
+ stdout_capture = result.stdout
690
+ stderr_capture = result.stderr
691
+ except subprocess.CalledProcessError as e:
692
+ return {
693
+ "command_executed": command_executed,
694
+ "stdout": e.stdout or "",
695
+ "stderr": e.stderr or "CalledProcessError with no stderr.",
696
+ "output_files": [],
697
+ "return_code": e.returncode,
698
+ }
699
+
700
+ return {
701
+ "command_executed": command_executed,
702
+ "stdout": stdout_capture,
703
+ "stderr": stderr_capture,
704
+ "output_files": output_files,
705
+ }
706
+
707
+ if __name__ == "__main__":
708
+ mcp.run(transport="stdio")
Biomni/mcp_generated/mcp_bedtools/app/bedtools_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_bedtools/app/bedtools_server.py')
11
+ LOCAL_SERVER = Path(__file__).with_name(SOURCE_SERVER.name)
12
+ SERVER_NAME = 'biosci_bedtools'
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_bedtools/docker-compose.yml ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: '3.8'
2
+
3
+ services:
4
+ mcp-bedtools:
5
+ build: .
6
+ image: mcp-bedtools:latest
7
+ container_name: mcp-bedtools
8
+ ports:
9
+ - "8000:8000"
10
+ environment:
11
+ - MCP_SERVER_NAME=bedtools
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_bedtools/environment.yaml ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ name: mcp-tool
3
+ channels:
4
+ - bioconda
5
+ - conda-forge
6
+ - defaults
7
+ dependencies:
8
+ - bedtools
9
+ - python=3.10
10
+
Biomni/mcp_generated/mcp_bedtools/requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ fastmcp
2
+ mcp
Biomni/mcp_generated/mcp_bin2cell/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 bin2cell via conda (e.g., from bioconda)
14
+ RUN conda install -c bioconda bin2cell -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/bin2cell_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/bin2cell_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/bin2cell_server.py"]
40
+
Biomni/mcp_generated/mcp_bin2cell/app/bin2cell_server.py ADDED
@@ -0,0 +1,286 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import subprocess
2
+ from pathlib import Path
3
+ from typing import Optional, List
4
+
5
+ from mcp.server.fastmcp import FastMCP
6
+
7
+ SERVER_NAME = 'local_bin2cell'
8
+ mcp = FastMCP(SERVER_NAME)
9
+
10
+ @mcp.tool()
11
+ def bin2cell_prepare_bins(
12
+ input_dir: str,
13
+ output_h5ad: str,
14
+ bin_size: int = 2,
15
+ destripe: bool = True,
16
+ ):
17
+ """
18
+ Reads Visium HD data from a SpaceRanger output directory and optionally performs destriping
19
+ to correct for technical effects in 2um bin data.
20
+
21
+ Args:
22
+ input_dir: Path to the SpaceRanger output directory (containing 'outs' folder).
23
+ output_h5ad: Path where the processed bin-level AnnData object will be saved.
24
+ bin_size: Resolution of bins to load (default is 2um).
25
+ destripe: Whether to apply the destriping correction for variable bin dimensions.
26
+ """
27
+ # Input validation
28
+ input_path = Path(input_dir)
29
+ if not input_path.exists():
30
+ return {"error": f"Input directory {input_dir} does not exist."}
31
+
32
+ output_path = Path(output_h5ad)
33
+ if not output_path.parent.exists():
34
+ output_path.parent.mkdir(parents=True, exist_ok=True)
35
+
36
+ if bin_size <= 0:
37
+ return {"error": "bin_size must be a positive integer."}
38
+
39
+ # Construct Python command
40
+ # We use a python script string to execute the library functions
41
+ destripe_cmd = "b2c.pp.destripe(adata)" if destripe else "pass"
42
+ python_script = f"""
43
+ import bin2cell as b2c
44
+ import scanpy as sc
45
+ import os
46
+
47
+ try:
48
+ # Load Visium HD data
49
+ adata = b2c.pp.read_visium_hd_folder('{input_dir}', bin_size={bin_size})
50
+
51
+ # Perform destriping if requested
52
+ if {destripe}:
53
+ b2c.pp.destripe(adata)
54
+
55
+ # Save the result
56
+ adata.write('{output_h5ad}')
57
+ print("Successfully prepared bin data.")
58
+ except Exception as e:
59
+ print(f"Error: {{str(e)}}")
60
+ exit(1)
61
+ """
62
+
63
+ try:
64
+ result = subprocess.run(
65
+ ["python", "-c", python_script],
66
+ capture_output=True,
67
+ text=True,
68
+ check=True
69
+ )
70
+ return {
71
+ "command_executed": f"bin2cell.pp.read_visium_hd_folder and destripe={destripe}",
72
+ "stdout": result.stdout,
73
+ "stderr": result.stderr,
74
+ "output_files": [output_h5ad]
75
+ }
76
+ except subprocess.CalledProcessError as e:
77
+ return {
78
+ "error": "Failed to prepare bin data",
79
+ "stdout": e.stdout,
80
+ "stderr": e.stderr,
81
+ "command_executed": e.cmd
82
+ }
83
+
84
+ @mcp.tool()
85
+ def bin2cell_run_stardist(
86
+ image_path: str,
87
+ output_mask_path: str,
88
+ model_name: str = "2D_versatile_he",
89
+ prob_thresh: float = 0.5,
90
+ nms_thresh: float = 0.3,
91
+ ):
92
+ """
93
+ Performs cell segmentation on a morphology image using StarDist.
94
+
95
+ Args:
96
+ image_path: Path to the high-resolution morphology image (e.g., tissue_hires_image.png).
97
+ output_mask_path: Path where the resulting segmentation mask (.tif) will be saved.
98
+ model_name: StarDist model to use (default: '2D_versatile_he').
99
+ prob_thresh: Probability threshold for StarDist detection.
100
+ nms_thresh: Non-maximum suppression threshold for StarDist.
101
+ """
102
+ # Input validation
103
+ img_path = Path(image_path)
104
+ if not img_path.exists():
105
+ return {"error": f"Image file {image_path} does not exist."}
106
+
107
+ out_mask = Path(output_mask_path)
108
+ if not out_mask.parent.exists():
109
+ out_mask.parent.mkdir(parents=True, exist_ok=True)
110
+
111
+ python_script = f"""
112
+ import bin2cell as b2c
113
+ import cv2
114
+ import numpy as np
115
+
116
+ try:
117
+ # Run StarDist segmentation via bin2cell wrapper
118
+ # Note: bin2cell.tl.stardist handles the model loading and prediction
119
+ b2c.tl.stardist(
120
+ '{image_path}',
121
+ '{output_mask_path}',
122
+ model='{model_name}',
123
+ prob_thresh={prob_thresh},
124
+ nms_thresh={nms_thresh}
125
+ )
126
+ print("Successfully generated segmentation mask.")
127
+ except Exception as e:
128
+ print(f"Error: {{str(e)}}")
129
+ exit(1)
130
+ """
131
+
132
+ try:
133
+ result = subprocess.run(
134
+ ["python", "-c", python_script],
135
+ capture_output=True,
136
+ text=True,
137
+ check=True
138
+ )
139
+ return {
140
+ "command_executed": f"bin2cell.tl.stardist on {image_path}",
141
+ "stdout": result.stdout,
142
+ "stderr": result.stderr,
143
+ "output_files": [output_mask_path]
144
+ }
145
+ except subprocess.CalledProcessError as e:
146
+ return {
147
+ "error": "StarDist segmentation failed",
148
+ "stdout": e.stdout,
149
+ "stderr": e.stderr,
150
+ "command_executed": e.cmd
151
+ }
152
+
153
+ @mcp.tool()
154
+ def bin2cell_extract_cells(
155
+ bin_h5ad_path: str,
156
+ mask_path: str,
157
+ output_cell_h5ad_path: str,
158
+ qc_metrics: bool = True,
159
+ ):
160
+ """
161
+ Groups subcellular bins into cells based on a segmentation mask and generates a cell-level AnnData object.
162
+
163
+ Args:
164
+ bin_h5ad_path: Path to the bin-level AnnData object (output from bin2cell_prepare_bins).
165
+ mask_path: Path to the segmentation mask file (output from bin2cell_run_stardist).
166
+ output_cell_h5ad_path: Path where the final cell-level AnnData object will be saved.
167
+ qc_metrics: Whether to calculate standard scanpy QC metrics for the new cell object.
168
+ """
169
+ # Input validation
170
+ bin_path = Path(bin_h5ad_path)
171
+ if not bin_path.exists():
172
+ return {"error": f"Bin h5ad file {bin_h5ad_path} does not exist."}
173
+
174
+ m_path = Path(mask_path)
175
+ if not m_path.exists():
176
+ return {"error": f"Mask file {mask_path} does not exist."}
177
+
178
+ out_cell_path = Path(output_cell_h5ad_path)
179
+ if not out_cell_path.parent.exists():
180
+ out_cell_path.parent.mkdir(parents=True, exist_ok=True)
181
+
182
+ python_script = f"""
183
+ import bin2cell as b2c
184
+ import scanpy as sc
185
+
186
+ try:
187
+ # Load the bin-level data
188
+ adata_bins = sc.read_h5ad('{bin_h5ad_path}')
189
+
190
+ # Extract cells based on the mask
191
+ adata_cells = b2c.tl.extract_cells(adata_bins, '{mask_path}')
192
+
193
+ # Calculate QC metrics if requested
194
+ if {qc_metrics}:
195
+ sc.pp.calculate_qc_metrics(adata_cells, inplace=True)
196
+
197
+ # Save the cell-level object
198
+ adata_cells.write('{output_cell_h5ad_path}')
199
+ print("Successfully extracted cells from bins.")
200
+ except Exception as e:
201
+ print(f"Error: {{str(e)}}")
202
+ exit(1)
203
+ """
204
+
205
+ try:
206
+ result = subprocess.run(
207
+ ["python", "-c", python_script],
208
+ capture_output=True,
209
+ text=True,
210
+ check=True
211
+ )
212
+ return {
213
+ "command_executed": f"bin2cell.tl.extract_cells using mask {mask_path}",
214
+ "stdout": result.stdout,
215
+ "stderr": result.stderr,
216
+ "output_files": [output_cell_h5ad_path]
217
+ }
218
+ except subprocess.CalledProcessError as e:
219
+ return {
220
+ "error": "Cell extraction failed",
221
+ "stdout": e.stdout,
222
+ "stderr": e.stderr,
223
+ "command_executed": e.cmd
224
+ }
225
+
226
+ @mcp.tool()
227
+ def bin2cell_visualize_segmentation(
228
+ bin_h5ad_path: str,
229
+ output_image_path: str,
230
+ basis: str = "spatial",
231
+ ):
232
+ """
233
+ Generates a visualization of the bin-to-cell assignments.
234
+
235
+ Args:
236
+ bin_h5ad_path: Path to the bin-level AnnData object containing cell assignments.
237
+ output_image_path: Path to save the visualization plot (e.g., .png or .pdf).
238
+ basis: The coordinate system to use for plotting (default: 'spatial').
239
+ """
240
+ bin_path = Path(bin_h5ad_path)
241
+ if not bin_path.exists():
242
+ return {"error": f"Bin h5ad file {bin_h5ad_path} does not exist."}
243
+
244
+ python_script = f"""
245
+ import scanpy as sc
246
+ import matplotlib.pyplot as plt
247
+ import bin2cell as b2c
248
+
249
+ try:
250
+ adata = sc.read_h5ad('{bin_h5ad_path}')
251
+ if 'cell_id' not in adata.obs.columns:
252
+ print("Error: cell_id not found in adata.obs. Run extract_cells first.")
253
+ exit(1)
254
+
255
+ # Plotting logic
256
+ sc.pl.embedding(adata, basis='{basis}', color='cell_id', show=False)
257
+ plt.savefig('{output_image_path}')
258
+ print("Successfully saved visualization.")
259
+ except Exception as e:
260
+ print(f"Error: {{str(e)}}")
261
+ exit(1)
262
+ """
263
+
264
+ try:
265
+ result = subprocess.run(
266
+ ["python", "-c", python_script],
267
+ capture_output=True,
268
+ text=True,
269
+ check=True
270
+ )
271
+ return {
272
+ "command_executed": f"Visualization of cell_id on {basis}",
273
+ "stdout": result.stdout,
274
+ "stderr": result.stderr,
275
+ "output_files": [output_image_path]
276
+ }
277
+ except subprocess.CalledProcessError as e:
278
+ return {
279
+ "error": "Visualization failed",
280
+ "stdout": e.stdout,
281
+ "stderr": e.stderr,
282
+ "command_executed": e.cmd
283
+ }
284
+
285
+ if __name__ == "__main__":
286
+ mcp.run(transport="stdio")
Biomni/mcp_generated/mcp_bin2cell/app/bin2cell_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_bin2cell/app/bin2cell_server.py')
11
+ LOCAL_SERVER = Path(__file__).with_name(SOURCE_SERVER.name)
12
+ SERVER_NAME = 'biosci_bin2cell'
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_bin2cell/app/requirements.txt ADDED
@@ -0,0 +1 @@
 
 
1
+
Biomni/mcp_generated/mcp_bin2cell/docker-compose.yml ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: '3.8'
2
+
3
+ services:
4
+ mcp-bin2cell:
5
+ build: .
6
+ image: mcp-bin2cell:latest
7
+ container_name: mcp-bin2cell
8
+ ports:
9
+ - "8000:8000"
10
+ environment:
11
+ - MCP_SERVER_NAME=bin2cell
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_bin2cell/environment.yaml ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ name: mcp-tool
3
+ channels:
4
+ - bioconda
5
+ - conda-forge
6
+ - defaults
7
+ dependencies:
8
+ - bin2cell
9
+ - python=3.10
10
+
Biomni/mcp_generated/mcp_bin2cell/requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ fastmcp
2
+ mcp
Biomni/mcp_generated/mcp_bioconductor-alabaster/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-alabaster via conda (e.g., from bioconda)
14
+ RUN conda install -c bioconda bioconductor-alabaster -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-alabaster_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-alabaster_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-alabaster_server.py"]
40
+
Biomni/mcp_generated/mcp_bioconductor-alabaster/app/bioconductor-alabaster_server.py ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import subprocess
2
+ import sys
3
+ from pathlib import Path
4
+ from typing import Optional, List
5
+ import tempfile
6
+ import logging
7
+
8
+ # Configure logging
9
+ logging.basicConfig(level=logging.INFO)
10
+
11
+ # Mock mcp.tool decorator for standalone execution
12
+ class mcp:
13
+ def tool(func):
14
+ def wrapper(*args, **kwargs):
15
+ return func(*args, **kwargs)
16
+ return wrapper
17
+
18
+ @mcp.tool
19
+ def alabaster_check():
20
+ """
21
+ Verifies the installation of the bioconductor-alabaster umbrella package.
22
+
23
+ This tool does not perform any data analysis. Instead, it attempts to load
24
+ the 'alabaster' library within an R session to confirm that the Alabaster
25
+ framework and all its components are correctly installed and accessible.
26
+ A successful execution indicates the environment is ready for tools that
27
+ depend on the Alabaster suite.
28
+ """
29
+ command = ["Rscript", "-e", "library(alabaster)"]
30
+ command_str = " ".join(command)
31
+ logging.info(f"Executing command: {command_str}")
32
+
33
+ try:
34
+ process = subprocess.run(
35
+ command,
36
+ check=True,
37
+ capture_output=True,
38
+ text=True,
39
+ )
40
+ stdout = process.stdout
41
+ stderr = process.stderr
42
+ logging.info("bioconductor-alabaster package loaded successfully.")
43
+
44
+ except FileNotFoundError:
45
+ logging.error("Rscript not found. Please ensure R is installed and in your PATH.")
46
+ # Re-raise with a more informative message for the MCP context
47
+ raise RuntimeError("Rscript executable not found. R installation is required.") from None
48
+
49
+ except subprocess.CalledProcessError as e:
50
+ logging.error(f"Error loading bioconductor-alabaster package.")
51
+ logging.error(f"Stderr: {e.stderr}")
52
+ logging.error(f"Stdout: {e.stdout}")
53
+ return {
54
+ "command_executed": command_str,
55
+ "stdout": e.stdout,
56
+ "stderr": e.stderr,
57
+ "error": "Failed to load the 'alabaster' R library. It may not be installed correctly.",
58
+ "return_code": e.returncode,
59
+ }
60
+
61
+ return {
62
+ "command_executed": command_str,
63
+ "stdout": stdout,
64
+ "stderr": stderr,
65
+ "status": "success"
66
+ }
Biomni/mcp_generated/mcp_bioconductor-alabaster/app/bioconductor-alabaster_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-alabaster/app/bioconductor-alabaster_server.py')
11
+ LOCAL_SERVER = Path(__file__).with_name(SOURCE_SERVER.name)
12
+ SERVER_NAME = 'biosci_bioconductor_alabaster'
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-alabaster/docker-compose.yml ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: '3.8'
2
+
3
+ services:
4
+ mcp-bioconductor-alabaster:
5
+ build: .
6
+ image: mcp-bioconductor-alabaster:latest
7
+ container_name: mcp-bioconductor-alabaster
8
+ ports:
9
+ - "8000:8000"
10
+ environment:
11
+ - MCP_SERVER_NAME=bioconductor-alabaster
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-alabaster/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-alabaster
9
+ - python=3.10
10
+
Biomni/mcp_generated/mcp_bioconductor-alabaster/requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ fastmcp
2
+ mcp
Biomni/mcp_generated/mcp_bioconductor-apeglm/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-apeglm via conda (e.g., from bioconda)
14
+ RUN conda install -c bioconda bioconductor-apeglm -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-apeglm_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-apeglm_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-apeglm_server.py"]
40
+
Biomni/mcp_generated/mcp_bioconductor-apeglm/app/bioconductor-apeglm_server.py ADDED
@@ -0,0 +1,133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import subprocess
2
+ from pathlib import Path
3
+ from typing import List, Optional, Dict, Any
4
+
5
+ from mcp.server.fastmcp import FastMCP
6
+
7
+ SERVER_NAME = 'local_bioconductor_apeglm'
8
+ mcp = FastMCP(SERVER_NAME)
9
+
10
+ @mcp.tool()
11
+ def run_r_script(
12
+ r_script_file: Optional[Path] = None,
13
+ r_expressions: Optional[List[str]] = None,
14
+ script_args: Optional[List[str]] = None,
15
+ verbose: bool = False,
16
+ default_packages: Optional[str] = None,
17
+ save_workspace: bool = False,
18
+ no_environ: bool = False,
19
+ no_site_file: bool = False,
20
+ no_init_file: bool = False,
21
+ restore_workspace: bool = False,
22
+ vanilla: bool = False,
23
+ ) -> Dict[str, Any]:
24
+ """
25
+ Executes an R script file or R expressions using the Rscript command.
26
+
27
+ This tool provides a wrapper for the Rscript command, allowing users to run
28
+ R code with various configuration options. It supports executing a specified
29
+ R script file or a list of R expressions directly. It also allows passing
30
+ arguments to the R script itself and configuring R's startup behavior.
31
+
32
+ Args:
33
+ r_script_file: Path to an R script file to execute. Mutually exclusive with `r_expressions`.
34
+ r_expressions: A list of R expressions (strings) to execute. Mutually exclusive with `r_script_file`.
35
+ script_args: A list of arguments to be passed to the R script or expressions.
36
+ verbose: If True, print information on progress (corresponds to Rscript's --verbose).
37
+ default_packages: A comma-separated list of package names, or 'NULL',
38
+ to set the default packages loaded (corresponds to --default-packages).
39
+ save_workspace: If True, save the workspace at the end of the session (corresponds to R's --save).
40
+ Ignored if `vanilla` is True.
41
+ no_environ: If True, don't read the site and user environment files (corresponds to R's --no-environ).
42
+ Ignored if `vanilla` is True.
43
+ no_site_file: If True, don't read the site-wide Rprofile (corresponds to R's --no-site-file).
44
+ Ignored if `vanilla` is True.
45
+ no_init_file: If True, don't read the user R profile (corresponds to R's --no-init-file).
46
+ Ignored if `vanilla` is True.
47
+ restore_workspace: If True, restore previously saved objects at startup (corresponds to R's --restore).
48
+ Ignored if `vanilla` is True.
49
+ vanilla: If True, combine --no-save, --no-restore, --no-site-file, --no-init-file, and --no-environ.
50
+ This option overrides individual settings for these flags.
51
+
52
+ Returns:
53
+ A dictionary containing the command executed, stdout, stderr, and any output files.
54
+ In case of an error, it includes error details and the return code.
55
+
56
+ Raises:
57
+ ValueError: If neither `r_script_file` nor `r_expressions` is provided, or if both are provided.
58
+ FileNotFoundError: If `r_script_file` is provided but does not exist.
59
+ """
60
+ command: List[str] = ["Rscript"]
61
+ output_files: List[Path] = []
62
+
63
+ # Input validation for script source
64
+ if r_script_file is None and r_expressions is None:
65
+ raise ValueError("Either 'r_script_file' or 'r_expressions' must be provided.")
66
+ if r_script_file is not None and r_expressions is not None:
67
+ raise ValueError("Cannot provide both 'r_script_file' and 'r_expressions'. Choose one.")
68
+
69
+ if r_script_file:
70
+ if not r_script_file.is_file():
71
+ raise FileNotFoundError(f"R script file not found: {r_script_file}")
72
+
73
+ # Add Rscript specific options
74
+ if verbose:
75
+ command.append("--verbose")
76
+ if default_packages is not None:
77
+ command.append(f"--default-packages={default_packages}")
78
+
79
+ # Add R options (passed to R, in addition to --no-echo --no-restore by Rscript)
80
+ if vanilla:
81
+ command.append("--vanilla")
82
+ else:
83
+ # Only add these if --vanilla is not set, as --vanilla implies them
84
+ if save_workspace:
85
+ command.append("--save")
86
+ if no_environ:
87
+ command.append("--no-environ")
88
+ if no_site_file:
89
+ command.append("--no-site-file")
90
+ if no_init_file:
91
+ command.append("--no-init-file")
92
+ if restore_workspace:
93
+ command.append("--restore")
94
+
95
+ # Add the script source (file or expressions)
96
+ if r_script_file:
97
+ command.append(str(r_script_file))
98
+ elif r_expressions:
99
+ for expr in r_expressions:
100
+ command.extend(["-e", expr])
101
+
102
+ # Add arguments to the R script
103
+ if script_args:
104
+ command.extend(script_args)
105
+
106
+ try:
107
+ process = subprocess.run(
108
+ command,
109
+ capture_output=True,
110
+ text=True,
111
+ check=True
112
+ )
113
+ stdout = process.stdout
114
+ stderr = process.stderr
115
+ except subprocess.CalledProcessError as e:
116
+ return {
117
+ "command_executed": " ".join(command),
118
+ "stdout": e.stdout,
119
+ "stderr": e.stderr,
120
+ "error": str(e),
121
+ "returncode": e.returncode,
122
+ "output_files": output_files,
123
+ }
124
+
125
+ return {
126
+ "command_executed": " ".join(command),
127
+ "stdout": stdout,
128
+ "stderr": stderr,
129
+ "output_files": output_files,
130
+ }
131
+
132
+ if __name__ == "__main__":
133
+ mcp.run(transport="stdio")
Biomni/mcp_generated/mcp_bioconductor-apeglm/app/bioconductor-apeglm_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-apeglm/app/bioconductor-apeglm_server.py')
11
+ LOCAL_SERVER = Path(__file__).with_name(SOURCE_SERVER.name)
12
+ SERVER_NAME = 'biosci_bioconductor_apeglm'
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-apeglm/docker-compose.yml ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: '3.8'
2
+
3
+ services:
4
+ mcp-bioconductor-apeglm:
5
+ build: .
6
+ image: mcp-bioconductor-apeglm:latest
7
+ container_name: mcp-bioconductor-apeglm
8
+ ports:
9
+ - "8000:8000"
10
+ environment:
11
+ - MCP_SERVER_NAME=bioconductor-apeglm
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
+