Skip to content

Commit 7917fc6

Browse files
committed
merge with main
2 parents 80a29e5 + dc2ad94 commit 7917fc6

4 files changed

Lines changed: 108 additions & 57 deletions

File tree

README.md

Lines changed: 92 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<h1 align="center">Toolomics</h1>
22

33
<p align="center">
4-
<em>A suite of MCP-based Tools from the HolobiomicsLab. Used by AI-Agents such as <i>Mimosa-AI</i></em>
4+
<em>Companion platform for MCP server management and workspace-isolated scientific tool execution for Mimosa and other MCP-compatible agents.</em>
55
</p>
66

77
<p align="center">
@@ -21,14 +21,15 @@
2121

2222
---
2323

24-
> ***Toolomics*** — deploys containerized tools, manages isolated instances, and enables file sharing across AI agents for bioinformatics, metabolomics, molecular docking, and beyond.
24+
> ***Toolomics*** exposes computational tools as discoverable MCP services, manages isolated multi-instance workspaces, and lets agents share files across scientific workflows.
2525
26-
**Use cases:**
27-
- Deploy MCP servers for browser automation, PDF processing, and data extraction
28-
- Run isolated, multi-instance agent workspaces with automatic resource management
29-
- Orchestrate containerized bioinformatics pipelines (XCMS, RStudio, Redis) with zero config
26+
In this repository, Toolomics:
27+
- discovering MCP services from `server.py` and `docker-compose.yml` definitions under `mcp_host/`
28+
- assigning ports and recording them in instance-specific `config_<instance_id>.json` files
29+
- isolating workspaces, Docker projects, volumes, and auxiliary services per deployment instance
30+
- making files created by one MCP server immediately available to other MCP servers through a shared workspace
3031

31-
## Install & deploy tools
32+
## Quick Start
3233

3334
### Deploy all automatically with default setup for Mimosa-AI
3435

@@ -48,37 +49,57 @@ This would create a workspace `workspace/` and start all Toolomics MCPs servers
4849
./start.sh <min port> <max port> <workspace name>
4950
```
5051

51-
### Deploy using python script
52+
Example:
5253

53-
***Not recommanded, start.sh will handle python, requirements and workpsace installation automatically.***
54+
```bash
55+
./start.sh 5000 5099 workspace_mimosa
56+
```
57+
58+
On first run, Toolomics will:
59+
1. check Python and `pip`
60+
2. optionally install `requirements.txt`
61+
3. create or reuse the requested workspace
62+
4. derive an instance ID from the workspace path
63+
5. create or update `config_<instance_id>.json` with discovered services and assigned ports
5464

55-
First, install the required dependencies, you can use either pip or the faster UV package manager:
65+
Newly discovered services are added with `"enabled": false` by default. Enable the MCP servers you want in the generated config file, then rerun `./start.sh`.
5666

57-
**1. Install dependencies:**
67+
### Manual Deployment
68+
69+
If you prefer to run the deployment script directly:
70+
71+
**1. Install dependencies**
5872
```bash
5973
python3.10 -m pip install -r requirements.txt
60-
# or using UV
74+
# or
6175
uv pip install -r requirements.txt
6276
```
6377

64-
**2. Run script:**
78+
**2. Run the deployment manager**
6579
```bash
66-
python3.10 deploy.py --config config.json --workspace <workspace name> --host_port_min <min port> --host_port_max <max port>
80+
python3.10 deploy.py --config config.json --mcp-dir mcp_host --workspace <workspace name> --host_port_min <min port> --host_port_max <max port>
6781
```
6882

69-
## Centralized File Management
83+
Passing `--config config.json` is supported, but `deploy.py` will automatically expand it to an instance-specific file such as `config_86517947.json` based on the workspace path.
84+
85+
## Centralized Workspace
7086

71-
All MCP servers execute in a centralized **workspace directory** (default: `workspace/`). This means:
87+
All MCP servers execute against a centralized workspace directory (default: `workspace/`). This means:
7288

73-
- **Browser MCP** downloads files → `workspace/downloaded_file.pdf`
74-
- **PDF MCP** processes files → `workspace/extracted_text.txt`
75-
- **Any MCP** creates files → `workspace/output_file.json`
89+
- Browser MCP downloads files to the workspace
90+
- PDF MCP processes files already present in the workspace
91+
- Other MCP servers can consume the same files without copying them between tool-specific directories
92+
93+
Example paths:
94+
- `workspace/downloaded_file.pdf`
95+
- `workspace/extracted_text.txt`
96+
- `workspace/output_file.json`
7697

7798
This centralized approach ensures that AI agents can easily find and work with files across different MCP tools without needing to track file locations.
7899

79100
## Multi-Instance Deployment
80101

81-
Toolomics supports running **multiple independent instances simultaneously**, each with its own workspace and Docker service isolation.
102+
Toolomics supports running multiple independent instances simultaneously, each with its own workspace and Docker service isolation.
82103

83104
### How It Works
84105

@@ -88,14 +109,14 @@ Each instance is automatically assigned a unique **instance ID** (8-character ha
88109

89110
This means each instance has its own configuration and doesn't interfere with others.
90111

91-
**Example: Deploy two instances concurrently**
112+
**Example: deploy two instances concurrently**
92113

93114
```bash
94115
# Terminal 1: Instance for user Martin
95-
start.sh 5000 5100 workspace_martin
116+
./start.sh 5000 5099 workspace_martin
96117

97118
# Terminal 2: Instance for user John (simultaneous)
98-
start.sh 5100 5200 workspace_john
119+
./start.sh 5100 5199 workspace_john
99120
```
100121

101122
### Automatic Resource Isolation
@@ -107,31 +128,49 @@ Each instance automatically gets isolated resources:
107128
| **Workspace** | Separate directory (`workspace_martin/`, `workspace_john/`) |
108129
| **Docker Containers** | Suffixed with instance ID (`xcmsrocker_a3f2b1c9`, `xcmsrocker_f7e2d4a1`) |
109130
| **Data Volumes** | Instance-specific names (`rstudio_data_a3f2b1c9`, `redis-data_f7e2d4a1`) |
110-
| **MCP Server Ports** | Different port ranges (5000-5100 vs 5100-5200) |
131+
| **MCP Server Ports** | Different port ranges (5000-5099 vs 5100-5199) |
111132
| **Auxiliary Ports** | Dynamic allocation (8787→9537, 8080→9037, etc.) |
112133

113-
## Using MCP with Your Client
134+
This multi-tenant, workspace-isolated design is the same property referenced in the manuscript when Toolomics is described as the companion discovery and execution layer for Mimosa.
135+
136+
## Discovering And Using MCP Services
114137

115-
To interact with the tools using a client (e.g., for your AI agent), you can use the `fastmcp` library.
138+
To interact with the tools using a client such as Mimosa or another MCP-compatible agent, you can use the generated config file directly or scan a predefined local port range.
116139

117140
### Finding the MCP Port
118141

119-
Each MCP server is assigned a port, which is recorded in the `config.json` file. For example:
142+
Each MCP server is assigned a port, which is recorded in the instance-specific config file. For example:
120143

121144
```json
122145
[
123-
{
124-
"mcp_host/browser/server.py": 5002
125-
},
126-
{
127-
"mcp_host/Rscript/server.py": 5001
128-
},
129-
{
130-
"mcp_host/files/csv/server.py": 5101
131-
}
146+
{
147+
"path": "mcp_host/pdf/server.py",
148+
"port": 5002,
149+
"enabled": true
150+
},
151+
{
152+
"path": "mcp_host/image_analysis/server.py",
153+
"port": 5006,
154+
"enabled": true
155+
},
156+
{
157+
"path": "mcp_host/shell/docker-compose.yml",
158+
"port": 5012,
159+
"enabled": true
160+
}
132161
]
133162
```
134163

164+
### Scanning A Predefined Port Range
165+
166+
Toolomics includes a helper script that scans `localhost:5000-5200` and enumerates active MCP tools:
167+
168+
```bash
169+
python3 discover_mcp.py
170+
```
171+
172+
This mirrors the local port-range discovery pattern described in the manuscript for Mimosa's tool discovery layer.
173+
135174
### Example Client Code
136175

137176
Here is an example of how to use a client to interact with an MCP server running on port `5002`:
@@ -158,17 +197,16 @@ async def main():
158197
# Other MCP tools can access it from the same location
159198
```
160199

161-
## Adding a New MCP
200+
## Adding A New MCP
162201

163202
You can easily add a new tool as an MCP server.
164203

165204
### Steps to Add a New MCP
166205

167-
1. Create a `server.py` file with your MCP implementation, it should take the port number as first argument (eg: `server.py 5003`).
168-
2. Place the file in a subfolder of the `mcp_host` directory. For example, to add a metabolomics-related tool, create a subfolder like `mcp_host/your_tool_name`.
169-
170-
The `deploy.py` script will look for new `server.py` file, attribute a port for your script and add it to `config.json` (unless you manually did by modifying the config.json), finally it will run your script with the assigned port as first argument.
171-
206+
1. Create a `server.py` file with your MCP implementation. It should accept the assigned port as either an environment variable or the first command-line argument.
207+
2. Place the file in a subfolder of `mcp_host/`, for example `mcp_host/your_tool_name/server.py`.
208+
3. Run `./start.sh` or `deploy.py` to let Toolomics discover the service and assign it a port.
209+
4. Set `"enabled": true` for the new service in the generated `config_<instance_id>.json`, then rerun deployment.
172210

173211
### Example MCP Implementation
174212

@@ -177,16 +215,17 @@ The `fastmcp` library simplifies the creation of MCP servers. Here's a basic exa
177215
```python
178216
#!/usr/bin/env python3
179217

180-
from fastmcp import FastMCP
218+
import os
219+
import sys
181220
from pathlib import Path
221+
from fastmcp import FastMCP
222+
182223
project_root = Path(__file__).resolve().parent.parent.parent
183-
sys.path.append(str(project_root)) # Add 'a/' to Python's search path
224+
sys.path.append(str(project_root))
184225

185226
from shared import CommandResult, run_bash_subprocess, return_as_dict
186227

187-
description = """
188-
a calculator that ...
189-
"""
228+
description = "A calculator MCP."
190229

191230
mcp = FastMCP(
192231
name="calculator",
@@ -212,20 +251,17 @@ if __name__ == "__main__":
212251
mcp.run(transport="streamable-http", port=port, host="0.0.0.0")
213252
```
214253

215-
### Automatic Port Assignment
216-
217-
When you run the `start.sh` or `deploy.py` script for the first time, it will automatically assign a port to your new MCP server and save the mapping in the `config.json` file.
218-
219254
## Dockerizing an MCP Server
220255

221-
For MCP servers that require isolated dependencies or need to run in a containerized environment (e.g., for ML models, system tools, or heavy dependencies), you can deploy them using Docker.
256+
For MCP servers that require isolated dependencies or need to run in a containerized environment, you can deploy them with Docker. This is one of the main ways Toolomics keeps tool dependencies isolated across concurrent scientific workflows.
222257

223258
### How It Works
224259

225260
If a `docker-compose.yml` file exists in the same directory as your `server.py`, the deployment script will:
226261
- **Automatically deploy the server in Docker** instead of running it directly on the host
227262
- **Skip the standalone Python execution** to avoid duplicate deployments
228263
- **Pass the assigned port** to the Docker container via the `MCP_PORT` environment variable
264+
- **Pass instance isolation metadata** such as `INSTANCE_ID` and `WORKSPACE_PATH` to the container
229265

230266
### Steps to Dockerize an MCP
231267

@@ -288,8 +324,9 @@ services:
288324
- "${MCP_PORT}:${MCP_PORT}"
289325
environment:
290326
- MCP_PORT=${MCP_PORT}
327+
- INSTANCE_ID=${INSTANCE_ID}
291328
volumes:
292-
- ../../workspace:/workspace
329+
- ../../${WORKSPACE_PATH}:/app/workspace:rw
293330
```
294331
295332
**Important**: The build context must be set to the project root (`../..`) to allow the Dockerfile to access `shared.py` and other project files.
@@ -298,8 +335,9 @@ services:
298335

299336
The deployment script will automatically:
300337
- Detect the `docker-compose.yml`
301-
- Assign a port (5000-5099 range for mcp_host)
338+
- Assign a port in the selected host range
302339
- Set the `MCP_PORT` environment variable
340+
- Set `INSTANCE_ID` and `WORKSPACE_PATH`
303341
- Build and start the Docker container
304342
- Skip running `server.py` directly on the host
305343

discover_mcp.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from fastmcp import Client
88

99
async def discover_mcp_servers():
10-
"""Discover MCP servers on ports 5000-5050 and list their tools."""
10+
"""Discover MCP servers on ports 5000-5200 and list their tools."""
1111
print("🔍 Discovering MCP servers on ports 5000-5200...")
1212

1313
for port in range(5000, 5201):
@@ -27,4 +27,4 @@ async def discover_mcp_servers():
2727

2828
if __name__ == "__main__":
2929
print("🧪 Starting MCP Server Discovery")
30-
asyncio.run(discover_mcp_servers())
30+
asyncio.run(discover_mcp_servers())

docs/licensing-notes.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,6 @@ This wording is intended for repository governance documentation and remains sub
2525

2626
## Co-authorship context (informational)
2727

28-
Current named research co-authors: Martin Legrand, Tao Jiang, Matthieu Feraud, Benjamin Navet, and Louis-Felix Nothias.
28+
Current named manuscript co-authors: Martin Legrand, Tao Jiang, Matthieu Feraud, Benjamin Navet, Yousouf Taghzouti, Fabien Gandon, Elise Dumont, and Louis-Felix Nothias.
2929

3030
This co-authorship note is informational and does not itself determine legal ownership or licensing authority.

start.sh

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,19 @@ else
238238
fi
239239
HOST_PID=$!
240240
wait $HOST_PID
241+
DEPLOY_EXIT_CODE=$?
242+
243+
echo ""
244+
if [ $DEPLOY_EXIT_CODE -ne 0 ]; then
245+
echo "=== DEPLOYMENT FAILED ==="
246+
echo "deploy.py exited with status $DEPLOY_EXIT_CODE"
247+
echo ""
248+
echo "Instance-specific config file: $INSTANCE_CONFIG"
249+
echo "If this was a first run, enable the MCP services you want in that file"
250+
echo "and rerun this command."
251+
echo ""
252+
exit $DEPLOY_EXIT_CODE
253+
fi
241254

242255
# After deployment, show the config file location
243256
echo ""

0 commit comments

Comments
 (0)