# Medsci Agent

> Biomedical research agent with 28 MCP tools powered by MedGemma, TxGemma and OpenCode

- **Type:** MCP server
- **Install:** `agentstack add mcp-omar-a-hassan-medsci-agent`
- **Verified:** Pending review
- **Seller:** [omar-A-hassan](https://agentstack.voostack.com/s/omar-a-hassan)
- **Installs:** 0
- **Category:** [AI & ML](https://agentstack.voostack.com/c/ai-and-ml)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [omar-A-hassan](https://github.com/omar-A-hassan)
- **Source:** https://github.com/omar-A-hassan/medsci-agent

## Install

```sh
agentstack add mcp-omar-a-hassan-medsci-agent
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

The open source biomedical research agent.

  
  
  
  
  
  
  

[](https://www.kaggle.com/competitions/med-gemma-impact-challenge)

MedSci Agent gives any LLM access to 28 biomedical and execution tools — drug ADMET prediction, protein structure search, single-cell RNA-seq analysis, medical image interpretation, literature search, policy-controlled document acquisition, and isolated sandbox execution — all powered by [MedGemma](https://huggingface.co/google/medgemma-4b-it), [TxGemma](https://huggingface.co/google/txgemma-2b-predict) running locally via Ollama, and [OpenCode](https://opencode.ai). No data leaves your machine.

Built for the [MedGemma Impact Challenge](https://www.kaggle.com/competitions/med-gemma-impact-challenge).

---

## Quick Start

Once [setup](#setup) is complete and Ollama is running, open the project in [OpenCode](https://opencode.ai) and try:

**Drug discovery:**
> Analyze the drug-likeness of ibuprofen (CC(C)Cc1ccc(cc1)C(C)C(=O)O) and predict its ADMET properties.

**Single-cell omics:**
> Read my H5AD file, preprocess it, cluster with Leiden at resolution 0.5, and run differential expression.

**Literature search:**
> Search PubMed for recent papers on CRISPR-Cas9 gene therapy for sickle cell disease.

The Agent automatically selects the right tools, calls MedGemma for interpretation, and returns a synthesized answer.

---

## Architecture

You bring your own LLM. Configure any model in OpenCode (via `/model`) and it becomes the orchestrator — it reads your query, selects the right tools, calls them through MCP, and synthesizes the results. The MCP servers handle the domain logic underneath.

```
Cloud LLM (user's choice via OpenCode)
    |
    | tool calls via MCP
    v
+--- MCP Servers (Bun / TypeScript) ---+
|                                       |
|  server-drug        5 tools           |
|  server-protein     5 tools           |
|  server-literature  4 tools           |
|  server-acquisition 2 tools           |
|  server-imaging     1 tool            |
|  server-omics       5 tools           |
|  server-paperqa     1 tool            |
|  server-sandbox     5 tools           |
|                                       |
+-------+-------------------+-----------+
        |                   |
        v                   v
   Ollama (local)     Python Sidecar
   - MedGemma 4B      - RDKit
   - TxGemma 2B       - BioPython
                       - Scanpy
```

**MedGemma** interprets tool outputs — it reads raw data from APIs and computational tools, then provides clinically relevant summaries. Every tool that calls MedGemma returns a `model_used` flag and degrades gracefully if the model is unavailable.

**TxGemma** predicts ADMET properties (absorption, distribution, metabolism, excretion, toxicity). It runs exact prompt templates from the [Therapeutics Data Commons](https://tdcommons.ai) and outputs binary classifications for six safety endpoints.

The **Python sidecar** is a long-running process that pre-imports scientific libraries and handles requests over stdin/stdout via JSON-RPC. This avoids the 2–5 second startup cost of importing RDKit or Scanpy on every call.

**`synthesize` parameter:** Every drug, protein, and omics tool accepts an optional `"synthesize": false` input field. When `false`, the tool skips the MedGemma interpretation step and returns raw data immediately. This is useful when you want fast data-only results, or when Ollama is unavailable. Default is `true` (synthesis enabled).

---

## Tools

### Drug Discovery (server-drug)

| Tool | Description | Backend |
|------|-------------|---------|
| `analyze_molecule` | Physicochemical properties from SMILES (MW, LogP, TPSA, HBD/HBA, rings, formula) | RDKit + MedGemma |
| `lipinski_filter` | Lipinski Rule of Five drug-likeness check | RDKit |
| `molecular_similarity` | Tanimoto similarity between two molecules using Morgan fingerprints | RDKit |
| `predict_admet` | BBB penetration, intestinal absorption, hERG blocking, CYP3A4 inhibition, Ames mutagenicity, DILI risk | TxGemma + RDKit + MedGemma |
| `search_chembl` | Search ChEMBL for bioactive molecules and targets | ChEMBL API + MedGemma |

### Protein Analysis (server-protein)

| Tool | Description | Backend |
|------|-------------|---------|
| `parse_fasta` | Parse FASTA files, return sequence metadata | BioPython |
| `analyze_sequence` | Sequence length, composition, molecular weight | BioPython + MedGemma |
| `search_uniprot` | Search UniProt by gene, protein name, or accession | UniProt API + MedGemma |
| `search_pdb` | Search PDB for 3D structures by protein or PDB ID | RCSB PDB API + MedGemma |
| `predict_structure` | Retrieve AlphaFold predicted structure and confidence scores | AlphaFold DB API + MedGemma |

### Literature, Acquisition & Synthesis (server-literature, server-acquisition & server-paperqa)

| Tool | Description | Backend |
|------|-------------|---------|
| `search_pubmed` | Search PubMed with Boolean and MeSH queries | NCBI E-utilities + MedGemma |
| `fetch_abstract` | Fetch full abstract and metadata by PMID | NCBI E-utilities + MedGemma |
| `search_openalex` | Search OpenAlex for scholarly works, citations, open access status | OpenAlex API + MedGemma |
| `search_clinical_trials` | Search ClinicalTrials.gov by condition, drug, or intervention | ClinicalTrials.gov API + MedGemma |
| `resolve_identifier_to_sources` | Resolve DOI/PMID/PMCID into candidate source URLs with provenance and confidence | NCBI ID Converter + deterministic transforms |
| `acquire_documents` | Policy-controlled document retrieval from DOI/PMID/PMCID/URL with content-level labeling and explicit extraction backend metadata (`pmid/pmcid`: BioC-first with Scrapling fallback, `doi/url`: Scrapling-primary) | NCBI BioC + Scrapling sidecar + safety policy engine |
| `search_and_analyze` | Deep semantic synthesis of up to 10 identifiers/documents (internal NCBI acquisition or pre-acquired documents) using contextual LLM re-ranking | PaperQA2 + Tantivy |

### Medical Imaging (server-imaging)

| Tool | Description | Backend |
|------|-------------|---------|
| `analyze_medical_image` | Analyze X-ray, CT, pathology, or dermatology images (PNG/JPEG, max 50 MB) | MedGemma (multimodal) |

### Omics (server-omics)

| Tool | Description | Backend |
|------|-------------|---------|
| `read_h5ad` | Load H5AD file, return observation and variable metadata | Scanpy |
| `preprocess_omics` | Filter, normalize, log-transform, find highly variable genes | Scanpy |
| `cluster_cells` | Leiden or Louvain clustering with UMAP coordinates | Scanpy |
| `differential_expression` | Differential expression between groups (Wilcoxon, t-test, logreg) | Scanpy + MedGemma |
| `gene_set_enrichment` | Pathway enrichment against MSigDB, GO, KEGG via Enrichr | Enrichr API + MedGemma |

### Sandbox Execution (server-sandbox)

| Tool | Description | Backend |
|------|-------------|---------|
| `sandbox_prepare` | Create/reuse a Docker sandbox with default `network_policy=deny` | Docker Sandbox CLI |
| `sandbox_run_job` | Execute command in sandbox with deterministic timeout + logs | Docker Sandbox CLI |
| `sandbox_status` | Check sandbox state (`running`/`stopped`/`unknown`) with retry/backoff | Docker Sandbox CLI |
| `sandbox_fetch_artifact` | Read artifact/log content with size/path safety constraints | Host file access + safety checks |
| `sandbox_teardown` | Stop or remove sandbox | Docker Sandbox CLI |

---

## Setup

### Fresh install — complete sequence

```bash
# 1. Install Bun and uv (if not already installed)
curl -fsSL https://bun.sh/install | bash
curl -LsSf https://astral.sh/uv/install.sh | sh

# 2. Clone and install JS/TS dependencies
git clone https://github.com/omar-A-hassan/medsci-agent.git
cd medsci-agent
bun install

# 3. Create Python environments
bun run setup:py:core     # RDKit + BioPython + Scanpy → .venv/
bun run setup:py:paperqa  # PaperQA + Scrapling + ACE → packages/server-paperqa/.venv-paperqa/

# 4. Pull Ollama models (Ollama must be installed first: https://ollama.com)
ollama pull medgemma:latest
ollama pull mxbai-embed-large
ollama pull hf.co/matrixportalx/txgemma-2b-predict-GGUF:Q4_K_M

# 5. (Optional) Export API keys for cloud features — do this BEFORE starting OpenCode
export OPENROUTER_API_KEY="sk-or-..."   # needed for ACE MCP and cloud PaperQA
export ANTHROPIC_API_KEY="sk-ant-..."  # only if using Anthropic directly

# 6. Verify setup
bun run typecheck
bun test

# 7. Open in OpenCode
opencode  # MCP servers start automatically via opencode.json
```

The `opencode.json` is pre-configured for local-only use (Ollama + local Python). No additional configuration is needed for the core tools. See the sections below for cloud model setup and optional features.

---

### Prerequisites

- [Bun](https://bun.sh) >= 1.1
- [uv](https://docs.astral.sh/uv/) (Python package and environment manager)
- [Ollama](https://ollama.com)
- [OpenCode](https://opencode.ai)
- **Docker Desktop 4.40+** with the **Docker AI Sandbox** feature enabled (required for sandbox tools only)
  - The `sandbox_*` tools use `docker sandbox` subcommands — a first-party feature in Docker Desktop 4.40+. Enable it under _Settings → Features in Development → Docker AI Sandbox_.
  - All other tools work without Docker.

> **Sandbox not available?** If you don't have Docker Desktop 4.40+ you can still use all 23 non-sandbox tools. Leave the `medsci-sandbox` MCP server enabled — calls to sandbox tools will return clear errors rather than crashing.

### 1. Clone and install

```bash
git clone https://github.com/omar-A-hassan/medsci-agent.git
cd medsci-agent
bun install
```

### 2. Python environments

The system uses two strictly decoupled Python virtual environments, both managed with `uv`.

**Core Environment (Required):**
```bash
bun run setup:py:core
```

**PaperQA + Acquisition Environment (Required for strict full-text retrieval and deep synthesis):**
```bash
bun run setup:py:paperqa
```

Or run both in one command:

```bash
bun run setup:py:all
```

> **Important:** Set `MEDSCI_PYTHON` to `.venv/bin/python3` for core tools. Both `medsci-paperqa` and `medsci-acquisition` should run with `packages/server-paperqa/.venv-paperqa/bin/python3` to keep Scrapling and PaperQA dependencies in one environment.
>
> Dependency ownership:
> - `.venv` (uv groups: `scientific`, `test`): core science sidecars (RDKit/BioPython/Scanpy and related tool stacks).
> - `packages/server-paperqa/.venv-paperqa` (uv groups: `paperqa`, `ace`, `test`): PaperQA + acquisition parsing + ACE stack.

### 3. Pull Ollama models

```bash
ollama pull medgemma:latest                                      # Biomedical interpretation
ollama pull mxbai-embed-large                                    # Document embeddings for PaperQA
ollama pull hf.co/matrixportalx/txgemma-2b-predict-GGUF:Q4_K_M  # ADMET prediction
```

If `medgemma:latest` is not available directly, pull the GGUF from HuggingFace and alias it:

```bash
ollama pull hf.co/unsloth/medgemma-4b-it-GGUF:Q4_K_M
cp ~/.ollama/models/manifests/hf.co/unsloth/medgemma-4b-it-GGUF/Q4_K_M \
   ~/.ollama/models/manifests/registry.ollama.ai/library/medgemma/latest
```

> **Note:** The `cp` command creates an alias so the code can reference the model as `medgemma:latest` regardless of how it was downloaded.

### 4. Configure OpenCode

The included `opencode.json` is pre-configured. Set the `model` field to your preferred cloud LLM:

```json
{
  "model": "openai/gpt-4o"
}
```

Update the `MEDSCI_PYTHON` path in each server's environment block if your virtual environment is in a different location.

### 4.1 Optional: Enable ACE MCP (self-improvement layer)

MedSci now supports optional ACE MCP integration for adaptive strategy learning.

Install ACE MCP in the PaperQA/acquisition virtual environment (recommended):

```bash
bun run setup:py:paperqa
```

Configured MCP server name: `ace-mcp` (in `opencode.json`)

ACE model default: `openrouter/arcee-ai/trinity-large-preview:free` (set via `ACE_MCP_DEFAULT_MODEL` in `opencode.json`). This is a free OpenRouter model that requires `OPENROUTER_API_KEY`. To change:

```bash
export ACE_MCP_DEFAULT_MODEL="your/provider-model"
```

Credential model for ACE:
- ACE runs as a separate MCP process and needs provider credentials available in that process environment.
- If you use OpenAI for ACE, export `OPENAI_API_KEY` before starting OpenCode.
- If you use Anthropic/Gemini/Mistral/etc for ACE, set the corresponding provider key env var.
- ACE can use the same cloud provider/model family you use in OpenCode, but it does not automatically inherit the currently selected chat model unless you configure `ACE_MCP_DEFAULT_MODEL` accordingly.
- ACE in this setup is intentionally decoupled from local MedSci models (`medgemma`, `txgemma`, PaperQA embedding model) and should not use them unless you explicitly reconfigure it.

Default behavior in MedSci:
- in-run reflection is read-only (`ace.ask` / `ace.skillbook.get`)
- automatic post-run learning is triggered by plugin guardrails (gated by evidence quality)
- manual fallback remains available via `/ace-learn`

Skillbooks are persisted under `.opencode/ace/skillbooks/`.

Why ACE is installed in `packages/server-paperqa/.venv-paperqa` (not the core `.venv`):
- ACE learning is orchestration/synthesis logic, closest to the PaperQA + acquisition stack.
- Keeping ACE out of the core scientific sidecar avoids dependency drift for RDKit/Scanpy/BioPython workflows.
- This preserves strict environment separation and reduces breakage risk in domain toolchains.

Example override:

```bash
export ACE_MCP_DEFAULT_MODEL="anthropic/claude-3-5-sonnet-latest"
export ANTHROPIC_API_KEY="..."
```

> **Key export timing:** API keys must be exported in the shell _before_ starting OpenCode. MCP server processes are spawned at startup and inherit env from that moment — changing env vars afterwards has no effect until OpenCode is restarted.

### 5. Run tests

```bash
bun run test:all
```

This runs:
- all Bun tests across MCP servers (including sidecar-in-loop tests when `packages/server-paperqa/.venv-paperqa` exists),
- and PaperQA Python tests using the PaperQA venv interpreter.

### 6. Start

Make sure Ollama is running, then open the project directory in OpenCode. The MCP servers start automatically.

---

## OpenCode Agent Usage

### Agent roles

- `medsci` is the primary orchestrator for cross-domain workflows.
- `drug`, `protein`, `omics`, and `imaging` are focused subagents for domain-deep tasks.
- All agents follow a planning-first contract (brief plan before first tool call, then strict sequential execution).

### Built-in project commands

This repo ships OpenCode slash commands under `.opencode/commands`:

- `/triage` — classify request and propose minimal sequential MCP plan
- `/lit-deep` — literature discovery + PaperQA deep synthesis workflow
- `/sandbox-job` — sandbox lifecycle run (`prepare → run_job → status(advisory) → fetch → teardown`)
- `/qc-check` — maker-checker quality gate on scientific outputs
- `/handoff-report` — compact handoff for next agent/human
- `/ace-learn` — manual ACE learning fallback/override for a completed task
- `/ace-strategies` — inspect ACE strategy state for a domain/session

### Sandbox command default

For inline script execution, prefer:

```bash
python3 -c "print('sandbox smoke ok')"
```

instead of `python -c ...` to avoid environment-path variability across sandbox templates.

### Determinism and status policy

- Treat `sandbox_run_job` success/failure as source-of-truth for execution outcome.
- Treat `sandbox_status` as advisory state signal.
- Backend applies status retry/backoff before returning `unknown`.

---

## Configuration

Environment variables (set in `opencode.json` under each server's `environment`):

| Variable | Default | Description |
|----------|---------|-------------|
| `MEDSCI_PROFILE` | `standard` | Hardware profile: `lite`, `standard`, or `full` |
| `MEDSCI_PYTHON` | `p

…

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [omar-A-hassan](https://github.com/omar-A-hassan)
- **Source:** [omar-A-hassan/medsci-agent](https://github.com/omar-A-hassan/medsci-agent)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** yes
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: flagged — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-omar-a-hassan-medsci-agent
- Seller: https://agentstack.voostack.com/s/omar-a-hassan
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
